Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Dec 2014 16:38:57 +0000 (08:38 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 10 Dec 2014 16:38:57 +0000 (08:38 -0800)
Pull irq core updates from Thomas Gleixner:
 "This is the first (boring) part of irq updates:

   - support for big endian I/O accessors in the generic irq chip

   - cleanup of brcmstb/bcm7120 drivers so they can be reused for non
     ARM SoCs

   - the usual pile of fixes and updates for the various ARM irq chips"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits)
  irqchip: dw-apb-ictl: Add PM support
  irqchip: dw-apb-ictl: Enable IRQ_GC_MASK_CACHE_PER_TYPE
  irqchip: dw-apb-ictl: Always use use {readl|writel}_relaxed
  ARM: orion: convert the irq_reg_{readl,writel} calls to the new API
  irqchip: atmel-aic: Add missing entry for rm9200 irq fixups
  irqchip: atmel-aic: Rename at91sam9_aic_irq_fixup for naming consistency
  irqchip: atmel-aic: Add specific irq fixup function for sam9g45 and sam9rl
  irqchip: atmel-aic: Add irq fixups for at91sam926x SoCs
  irqchip: atmel-aic: Add irq fixup for RTT block
  irqchip: brcmstb-l2: Convert driver to use irq_reg_{readl,writel}
  irqchip: bcm7120-l2: Convert driver to use irq_reg_{readl,writel}
  irqchip: bcm7120-l2: Decouple driver from brcmstb-l2
  irqchip: bcm7120-l2: Extend driver to support 64+ bit controllers
  irqchip: bcm7120-l2: Use gc->mask_cache to simplify suspend/resume functions
  irqchip: bcm7120-l2: Fix missing nibble in gc->unused mask
  irqchip: bcm7120-l2: Make sure all register accesses use base+offset
  irqchip: bcm7120-l2, brcmstb-l2: Remove ARM Kconfig dependency
  irqchip: bcm7120-l2: Eliminate bad IRQ check
  irqchip: brcmstb-l2: Eliminate dependency on ARM code
  genirq: Generic chip: Add big endian I/O accessors
  ...

3341 files changed:
Documentation/ABI/stable/sysfs-driver-ib_srp
Documentation/ABI/testing/sysfs-ibft
Documentation/DocBook/media/Makefile
Documentation/DocBook/media/v4l/compat.xml
Documentation/HOWTO
Documentation/RCU/rcu.txt
Documentation/RCU/stallwarn.txt
Documentation/RCU/trace.txt
Documentation/RCU/whatisRCU.txt
Documentation/SubmittingPatches
Documentation/arm/firmware.txt
Documentation/arm/sunxi/README
Documentation/arm64/legacy_instructions.txt [new file with mode: 0644]
Documentation/arm64/memory.txt
Documentation/atomic_ops.txt
Documentation/block/biodoc.txt
Documentation/development-process/2.Process
Documentation/development-process/8.Conclusion
Documentation/device-mapper/cache-policies.txt
Documentation/devicetree/bindings/arm/amlogic.txt
Documentation/devicetree/bindings/arm/arch_timer.txt
Documentation/devicetree/bindings/arm/arm-boards
Documentation/devicetree/bindings/arm/bcm/cygnus.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/arm/fsl.txt
Documentation/devicetree/bindings/arm/gic.txt
Documentation/devicetree/bindings/arm/marvell,berlin.txt
Documentation/devicetree/bindings/arm/mediatek.txt
Documentation/devicetree/bindings/arm/omap/omap.txt
Documentation/devicetree/bindings/arm/rockchip.txt
Documentation/devicetree/bindings/arm/samsung-boards.txt
Documentation/devicetree/bindings/arm/ste-nomadik.txt
Documentation/devicetree/bindings/arm/sunxi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/ux500/power_domain.txt [new file with mode: 0644]
Documentation/devicetree/bindings/ata/sata_rcar.txt
Documentation/devicetree/bindings/bus/brcm,gisb-arb.txt
Documentation/devicetree/bindings/bus/mvebu-mbus.txt
Documentation/devicetree/bindings/clock/bcm-cygnus-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/vf610-clock.txt
Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
Documentation/devicetree/bindings/hwmon/ltc2978.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
Documentation/devicetree/bindings/i2c/trivial-devices.txt
Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Documentation/devicetree/bindings/mailbox/mailbox.txt [new file with mode: 0644]
Documentation/devicetree/bindings/memory-controllers/mvebu-sdram-controller.txt [new file with mode: 0644]
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/max77686.txt
Documentation/devicetree/bindings/mfd/max77693.txt
Documentation/devicetree/bindings/mfd/s2mps11.txt
Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
Documentation/devicetree/bindings/mmc/img-dw-mshc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/sdhci-pxa.txt
Documentation/devicetree/bindings/net/smsc-lan91c111.txt
Documentation/devicetree/bindings/nios2/nios2.txt [new file with mode: 0644]
Documentation/devicetree/bindings/nios2/timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/pci.txt
Documentation/devicetree/bindings/pinctrl/img,tz1090-pdc-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/img,tz1090-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/lantiq,falcon-pinumx.txt
Documentation/devicetree/bindings/pinctrl/lantiq,xway-pinumx.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-sirf.txt
Documentation/devicetree/bindings/pinctrl/pinctrl_spear.txt
Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/qcom,ipq8064-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt
Documentation/devicetree/bindings/power/power-controller.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
Documentation/devicetree/bindings/regulator/act8865-regulator.txt
Documentation/devicetree/bindings/regulator/max77802.txt
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/devicetree/bindings/regulator/sky81452-regulator.txt
Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/atmel,at91sam9-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/sgtl5000.txt
Documentation/devicetree/bindings/submitting-patches.txt
Documentation/devicetree/bindings/thermal/imx-thermal.txt
Documentation/devicetree/bindings/thermal/rcar-thermal.txt
Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
Documentation/devicetree/bindings/timer/renesas,mtu2.txt
Documentation/devicetree/bindings/timer/renesas,tmu.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/w1/omap-hdq.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/cadence-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
Documentation/devicetree/bindings/watchdog/marvel.txt
Documentation/devicetree/bindings/watchdog/meson6-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/qcom-wdt.txt [new file with mode: 0644]
Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
Documentation/filesystems/Locking
Documentation/filesystems/overlayfs.txt [new file with mode: 0644]
Documentation/filesystems/vfs.txt
Documentation/hwmon/lm75
Documentation/hwmon/lm95234
Documentation/hwmon/lm95245
Documentation/hwmon/nct6775
Documentation/hwmon/nct7802 [new file with mode: 0644]
Documentation/hwmon/tmp401
Documentation/input/elantech.txt
Documentation/kernel-parameters.txt
Documentation/kmemleak.txt
Documentation/locking/lglock.txt [new file with mode: 0644]
Documentation/mailbox.txt [new file with mode: 0644]
Documentation/memory-barriers.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/timestamping.txt
Documentation/nios2/README [new file with mode: 0644]
Documentation/power/pm_qos_interface.txt
Documentation/prctl/Makefile
Documentation/ptp/testptp.mk [new file with mode: 0644]
Documentation/scsi/libsas.txt
Documentation/scsi/osd.txt
Documentation/scsi/scsi_mid_low_api.txt
Documentation/scsi/st.txt
Documentation/scsi/wd719x.txt [new file with mode: 0644]
Documentation/target/tcmu-design.txt [new file with mode: 0644]
Documentation/vDSO/Makefile
Documentation/vDSO/vdso_standalone_test_x86.c
Documentation/video4linux/vivid.txt
Documentation/vm/hugetlbpage.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/angel4.dts
arch/arc/boot/dts/nsimosci.dts
arch/arc/configs/fpga_defconfig
arch/arc/configs/fpga_noramfs_defconfig
arch/arc/configs/nsimosci_defconfig
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/atomic.h
arch/arc/include/asm/bitops.h
arch/arc/include/asm/bug.h
arch/arc/include/asm/cache.h
arch/arc/include/asm/current.h
arch/arc/include/asm/io.h
arch/arc/include/asm/irqflags.h
arch/arc/include/asm/kgdb.h
arch/arc/include/asm/processor.h
arch/arc/include/asm/setup.h
arch/arc/include/asm/smp.h
arch/arc/include/asm/string.h
arch/arc/include/asm/syscalls.h
arch/arc/include/asm/thread_info.h
arch/arc/include/asm/unaligned.h
arch/arc/kernel/Makefile
arch/arc/kernel/disasm.c
arch/arc/kernel/head.S
arch/arc/kernel/kgdb.c
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/smp.c
arch/arc/mm/cache_arc700.c
arch/arc/mm/tlb.c
arch/arc/plat-arcfpga/Kconfig
arch/arc/plat-arcfpga/include/plat/irq.h [deleted file]
arch/arc/plat-arcfpga/include/plat/memmap.h [deleted file]
arch/arc/plat-arcfpga/platform.c
arch/arc/plat-arcfpga/smp.c
arch/arc/plat-tb10x/Kconfig
arch/arc/plat-tb10x/tb10x.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am335x-igep0033.dtsi
arch/arm/boot/dts/am335x-lxm.dts [new file with mode: 0644]
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am437x-sk-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/am57xx-beagle-x15.dts [new file with mode: 0644]
arch/arm/boot/dts/arm-realview-pb1176.dts [new file with mode: 0644]
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 [new file with mode: 0644]
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-370.dtsi
arch/arm/boot/dts/armada-375.dtsi
arch/arm/boot/dts/armada-385-db.dts
arch/arm/boot/dts/armada-38x.dtsi
arch/arm/boot/dts/armada-xp-axpwifiap.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-mv78230.dtsi
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 [new file with mode: 0644]
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9x25.dtsi
arch/arm/boot/dts/at91sam9x35.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/at91sam9x5_can.dtsi
arch/arm/boot/dts/at91sam9x5_usart3.dtsi
arch/arm/boot/dts/atlas6.dtsi
arch/arm/boot/dts/bcm-cygnus-clock.dtsi [new file with mode: 0644]
arch/arm/boot/dts/bcm-cygnus.dtsi [new file with mode: 0644]
arch/arm/boot/dts/bcm2835-rpi-b-plus.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm2835-rpi-b.dts
arch/arm/boot/dts/bcm2835-rpi.dtsi [new file with mode: 0644]
arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm4708-netgear-r6250.dts
arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm47081.dtsi [new file with mode: 0644]
arch/arm/boot/dts/bcm5301x.dtsi
arch/arm/boot/dts/bcm911360_entphn.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm911360k.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm958300k.dts [new file with mode: 0644]
arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts
arch/arm/boot/dts/berlin2.dtsi
arch/arm/boot/dts/berlin2cd-google-chromecast.dts
arch/arm/boot/dts/berlin2cd.dtsi
arch/arm/boot/dts/berlin2q-marvell-dmp.dts
arch/arm/boot/dts/berlin2q.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/dra74x.dtsi
arch/arm/boot/dts/emev2-kzm9d.dts
arch/arm/boot/dts/emev2.dtsi
arch/arm/boot/dts/exynos3250-monk.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos3250-pinctrl.dtsi
arch/arm/boot/dts/exynos3250-rinato.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/exynos4210-universal_c210.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4212.dtsi
arch/arm/boot/dts/exynos4412-odroid-common.dtsi
arch/arm/boot/dts/exynos4412-trats2.dts
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/boot/dts/exynos4415-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos4415.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
arch/arm/boot/dts/exynos4x12.dtsi
arch/arm/boot/dts/exynos5250-arndale.dts
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250-snow.dts
arch/arm/boot/dts/exynos5250-spring.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5420-peach-pit.dts
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5800-peach-pi.dts
arch/arm/boot/dts/hisi-x5hd2-dkb.dts
arch/arm/boot/dts/hisi-x5hd2.dtsi
arch/arm/boot/dts/imx28-evk.dts
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6dl.dtsi
arch/arm/boot/dts/imx6q-tbs2910.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi
arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
arch/arm/boot/dts/imx6qdl-rex.dtsi
arch/arm/boot/dts/imx6qdl-sabresd.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6sl-evk.dts
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/boot/dts/imx6sx-sdb.dts
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/integrator.dtsi
arch/arm/boot/dts/k2e-evm.dts
arch/arm/boot/dts/k2e.dtsi
arch/arm/boot/dts/k2l-evm.dts
arch/arm/boot/dts/keystone.dtsi
arch/arm/boot/dts/kirkwood-dir665.dts [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-synology.dtsi
arch/arm/boot/dts/ls1021a-qds.dts [new file with mode: 0644]
arch/arm/boot/dts/ls1021a-twr.dts [new file with mode: 0644]
arch/arm/boot/dts/ls1021a.dtsi [new file with mode: 0644]
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/meson6-atv1200.dts
arch/arm/boot/dts/meson6.dtsi
arch/arm/boot/dts/meson8.dtsi [new file with mode: 0644]
arch/arm/boot/dts/mt6592-evb.dts [new file with mode: 0644]
arch/arm/boot/dts/mt6592.dtsi [new file with mode: 0644]
arch/arm/boot/dts/mt8127-moose.dts [new file with mode: 0644]
arch/arm/boot/dts/mt8127.dtsi [new file with mode: 0644]
arch/arm/boot/dts/mt8135-evbp1.dts [new file with mode: 0644]
arch/arm/boot/dts/mt8135.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
arch/arm/boot/dts/omap-zoom-common.dtsi
arch/arm/boot/dts/omap2420-n8x0-common.dtsi
arch/arm/boot/dts/omap2420.dtsi
arch/arm/boot/dts/omap2430-sdp.dts
arch/arm/boot/dts/omap2430.dtsi
arch/arm/boot/dts/omap3-cm-t3517.dts
arch/arm/boot/dts/omap3-cm-t3530.dts
arch/arm/boot/dts/omap3-cm-t3730.dts
arch/arm/boot/dts/omap3-cm-t3x.dtsi
arch/arm/boot/dts/omap3-cm-t3x30.dtsi
arch/arm/boot/dts/omap3-devkit8000.dts
arch/arm/boot/dts/omap3-evm-37xx.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-common.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap3-igep0020-rev-f.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-igep0020.dts
arch/arm/boot/dts/omap3-igep0030-common.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap3-igep0030-rev-g.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-igep0030.dts
arch/arm/boot/dts/omap3-ldp.dts
arch/arm/boot/dts/omap3-lilly-a83x.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap3-sb-t35.dtsi
arch/arm/boot/dts/omap3-sbc-t3517.dts
arch/arm/boot/dts/omap3-sbc-t3530.dts
arch/arm/boot/dts/omap3-sbc-t3730.dts
arch/arm/boot/dts/omap3-tao3530.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap3430-sdp.dts
arch/arm/boot/dts/omap4-duovero-parlor.dts
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap44xx-clocks.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/prima2.dtsi
arch/arm/boot/dts/r7s72100-genmai.dts
arch/arm/boot/dts/r7s72100.dtsi
arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
arch/arm/boot/dts/r8a73a4.dtsi
arch/arm/boot/dts/r8a7740-armadillo800eva.dts
arch/arm/boot/dts/r8a7740.dtsi
arch/arm/boot/dts/r8a7778-bockw-reference.dts
arch/arm/boot/dts/r8a7778.dtsi
arch/arm/boot/dts/r8a7779-marzen.dts
arch/arm/boot/dts/r8a7779.dtsi
arch/arm/boot/dts/r8a7790-lager.dts
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/r8a7791-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/r8a77xx-aa104xd12-panel.dtsi [new file with mode: 0644]
arch/arm/boot/dts/rk3066a-bqcurie2.dts
arch/arm/boot/dts/rk3066a-marsboard.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3066a.dtsi
arch/arm/boot/dts/rk3188-radxarock.dts
arch/arm/boot/dts/rk3188.dtsi
arch/arm/boot/dts/rk3288-evb-rk808.dts
arch/arm/boot/dts/rk3288-evb.dtsi
arch/arm/boot/dts/rk3288-thermal.dtsi [new file with mode: 0644]
arch/arm/boot/dts/rk3288.dtsi
arch/arm/boot/dts/rk3xxx.dtsi
arch/arm/boot/dts/s3c6410-mini6410.dts
arch/arm/boot/dts/s3c64xx.dtsi
arch/arm/boot/dts/sama5d31.dtsi
arch/arm/boot/dts/sama5d33.dtsi
arch/arm/boot/dts/sama5d34.dtsi
arch/arm/boot/dts/sama5d35.dtsi
arch/arm/boot/dts/sama5d36.dtsi
arch/arm/boot/dts/sama5d3xcm.dtsi
arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
arch/arm/boot/dts/sh73a0.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/socfpga_arria10.dtsi [new file with mode: 0644]
arch/arm/boot/dts/socfpga_arria10_socdk.dts [new file with mode: 0755]
arch/arm/boot/dts/socfpga_arria5.dtsi
arch/arm/boot/dts/socfpga_arria5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5.dtsi
arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
arch/arm/boot/dts/ste-dbx5x0.dtsi
arch/arm/boot/dts/ste-nomadik-nhk15.dts [new file with mode: 0644]
arch/arm/boot/dts/ste-nomadik-s8815.dts
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
arch/arm/boot/dts/stih407-b2120.dts
arch/arm/boot/dts/stih407-clock.dtsi
arch/arm/boot/dts/stih407-family.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stih407.dtsi [deleted file]
arch/arm/boot/dts/stih410-b2120.dts [new file with mode: 0644]
arch/arm/boot/dts/stih410-clock.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stih410-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stih410.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stih415-pinctrl.dtsi
arch/arm/boot/dts/stih415.dtsi
arch/arm/boot/dts/stih416-b2020.dts
arch/arm/boot/dts/stih416-b2020e.dts
arch/arm/boot/dts/stih416-pinctrl.dtsi
arch/arm/boot/dts/stih416.dtsi
arch/arm/boot/dts/stih41x-b2000.dtsi
arch/arm/boot/dts/stih41x-b2020.dtsi
arch/arm/boot/dts/stih41x-b2020x.dtsi
arch/arm/boot/dts/stihxxx-b2120.dtsi [new file with mode: 0644]
arch/arm/boot/dts/sun4i-a10-a1000.dts
arch/arm/boot/dts/sun4i-a10-ba10-tvbox.dts
arch/arm/boot/dts/sun4i-a10-cubieboard.dts
arch/arm/boot/dts/sun4i-a10-hackberry.dts
arch/arm/boot/dts/sun4i-a10-inet97fv2.dts
arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
arch/arm/boot/dts/sun4i-a10-pcduino.dts
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts
arch/arm/boot/dts/sun5i-a10s.dtsi
arch/arm/boot/dts/sun5i-a13-hsg-h702.dts
arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
arch/arm/boot/dts/sun5i-a13-olinuxino.dts
arch/arm/boot/dts/sun6i-a31-app4-evb1.dts
arch/arm/boot/dts/sun6i-a31-colombus.dts
arch/arm/boot/dts/sun6i-a31-hummingbird.dts
arch/arm/boot/dts/sun6i-a31-m9.dts
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20-bananapi.dts [new file with mode: 0644]
arch/arm/boot/dts/sun7i-a20-cubietruck.dts
arch/arm/boot/dts/sun7i-a20-i12-tvbox.dts
arch/arm/boot/dts/sun7i-a20-m3.dts [new file with mode: 0644]
arch/arm/boot/dts/sun7i-a20-olinuxino-lime.dts
arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts [new file with mode: 0644]
arch/arm/boot/dts/sun7i-a20-pcduino3.dts
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a23-ippo-q8h-v5.dts
arch/arm/boot/dts/sun8i-a23.dtsi
arch/arm/boot/dts/sun9i-a80-optimus.dts [new file with mode: 0644]
arch/arm/boot/dts/sun9i-a80.dtsi [new file with mode: 0644]
arch/arm/boot/dts/sunxi-common-regulators.dtsi
arch/arm/boot/dts/tegra114-dalmore.dts
arch/arm/boot/dts/tegra114-roth.dts
arch/arm/boot/dts/tegra114-tn7.dts
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra124-jetson-tk1.dts
arch/arm/boot/dts/tegra124-nyan-big.dts
arch/arm/boot/dts/tegra124-venice2.dts
arch/arm/boot/dts/tegra124.dtsi
arch/arm/boot/dts/tegra20-harmony.dts
arch/arm/boot/dts/tegra20-iris-512.dts
arch/arm/boot/dts/tegra20-medcom-wide.dts
arch/arm/boot/dts/tegra20-paz00.dts
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-tamonten.dtsi
arch/arm/boot/dts/tegra20-trimslice.dts
arch/arm/boot/dts/tegra20-ventana.dts
arch/arm/boot/dts/tegra20-whistler.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-apalis-eval.dts
arch/arm/boot/dts/tegra30-beaver.dts
arch/arm/boot/dts/tegra30-cardhu.dtsi
arch/arm/boot/dts/tegra30-colibri-eval-v3.dts
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/vf-colibri-eval-v3.dtsi [new file with mode: 0644]
arch/arm/boot/dts/vf-colibri.dtsi [new file with mode: 0644]
arch/arm/boot/dts/vf500-colibri-eval-v3.dts [new file with mode: 0644]
arch/arm/boot/dts/vf500-colibri.dtsi [new file with mode: 0644]
arch/arm/boot/dts/vf500.dtsi [new file with mode: 0644]
arch/arm/boot/dts/vf610-colibri-eval-v3.dts
arch/arm/boot/dts/vf610-colibri.dtsi
arch/arm/boot/dts/vf610-cosmic.dts
arch/arm/boot/dts/vf610-twr.dts
arch/arm/boot/dts/vf610.dtsi
arch/arm/boot/dts/vfxxx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/zynq-7000.dtsi
arch/arm/boot/dts/zynq-parallella.dts
arch/arm/boot/dts/zynq-zc702.dts
arch/arm/boot/dts/zynq-zc706.dts
arch/arm/boot/dts/zynq-zed.dts
arch/arm/boot/dts/zynq-zybo.dts [new file with mode: 0644]
arch/arm/common/edma.c
arch/arm/configs/ape6evm_defconfig
arch/arm/configs/at91_dt_defconfig
arch/arm/configs/at91rm9200_defconfig [deleted file]
arch/arm/configs/at91sam9260_9g20_defconfig [deleted file]
arch/arm/configs/at91sam9261_9g10_defconfig [deleted file]
arch/arm/configs/at91sam9263_defconfig [deleted file]
arch/arm/configs/at91sam9g45_defconfig [deleted file]
arch/arm/configs/at91sam9rl_defconfig [deleted file]
arch/arm/configs/at91x40_defconfig [deleted file]
arch/arm/configs/bcm_defconfig
arch/arm/configs/exynos_defconfig
arch/arm/configs/hisi_defconfig
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/integrator_defconfig
arch/arm/configs/keystone_defconfig
arch/arm/configs/koelsch_defconfig [deleted file]
arch/arm/configs/multi_v5_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/mvebu_v5_defconfig
arch/arm/configs/mvebu_v7_defconfig
arch/arm/configs/nhk8815_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/sama5_defconfig
arch/arm/configs/shmobile_defconfig
arch/arm/configs/socfpga_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/configs/tegra_defconfig
arch/arm/include/asm/arch_timer.h
arch/arm/include/asm/firmware.h
arch/arm/include/asm/io.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/perf_event.h
arch/arm/include/asm/pmu.h
arch/arm/include/asm/thread_info.h
arch/arm/include/debug/asm9260.S [new file with mode: 0644]
arch/arm/include/debug/renesas-scif.S [new file with mode: 0644]
arch/arm/include/debug/sa1100.S [new file with mode: 0644]
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/Makefile
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/calls.S
arch/arm/kernel/perf_callchain.c [new file with mode: 0644]
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_cpu.c
arch/arm/kernel/perf_event_v6.c
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/perf_event_xscale.c
arch/arm/kernel/traps.c
arch/arm/kvm/mmu.c
arch/arm/mach-asm9260/Kconfig [new file with mode: 0644]
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Kconfig.non_dt [deleted file]
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/Makefile.boot
arch/arm/mach-at91/at91_aic.h [deleted file]
arch/arm/mach-at91/at91_tc.h [deleted file]
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c [deleted file]
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c [deleted file]
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c [deleted file]
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c [deleted file]
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c [deleted file]
arch/arm/mach-at91/at91sam9n12.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c [deleted file]
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/at91x40.c [deleted file]
arch/arm/mach-at91/at91x40_time.c [deleted file]
arch/arm/mach-at91/board-1arm.c [deleted file]
arch/arm/mach-at91/board-afeb-9260v1.c [deleted file]
arch/arm/mach-at91/board-cam60.c [deleted file]
arch/arm/mach-at91/board-carmeva.c [deleted file]
arch/arm/mach-at91/board-cpu9krea.c [deleted file]
arch/arm/mach-at91/board-cpuat91.c [deleted file]
arch/arm/mach-at91/board-csb337.c [deleted file]
arch/arm/mach-at91/board-csb637.c [deleted file]
arch/arm/mach-at91/board-dt-rm9200.c
arch/arm/mach-at91/board-dt-sam9.c
arch/arm/mach-at91/board-dt-sama5.c
arch/arm/mach-at91/board-eb01.c [deleted file]
arch/arm/mach-at91/board-eb9200.c [deleted file]
arch/arm/mach-at91/board-ecbat91.c [deleted file]
arch/arm/mach-at91/board-eco920.c [deleted file]
arch/arm/mach-at91/board-flexibity.c [deleted file]
arch/arm/mach-at91/board-gsia18s.c [deleted file]
arch/arm/mach-at91/board-kafa.c [deleted file]
arch/arm/mach-at91/board-kb9202.c [deleted file]
arch/arm/mach-at91/board-pcontrol-g20.c [deleted file]
arch/arm/mach-at91/board-picotux200.c [deleted file]
arch/arm/mach-at91/board-rm9200ek.c [deleted file]
arch/arm/mach-at91/board-sam9-l9260.c [deleted file]
arch/arm/mach-at91/board-sam9260ek.c [deleted file]
arch/arm/mach-at91/board-sam9261ek.c [deleted file]
arch/arm/mach-at91/board-sam9263ek.c [deleted file]
arch/arm/mach-at91/board-sam9g20ek.c [deleted file]
arch/arm/mach-at91/board-sam9m10g45ek.c [deleted file]
arch/arm/mach-at91/board-sam9rlek.c [deleted file]
arch/arm/mach-at91/board-snapper9260.c [deleted file]
arch/arm/mach-at91/board-stamp9g20.c [deleted file]
arch/arm/mach-at91/board-yl-9200.c [deleted file]
arch/arm/mach-at91/board.h [deleted file]
arch/arm/mach-at91/clock.c [deleted file]
arch/arm/mach-at91/clock.h [deleted file]
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/gpio.c [deleted file]
arch/arm/mach-at91/gpio.h [deleted file]
arch/arm/mach-at91/gsia18s.h [deleted file]
arch/arm/mach-at91/include/mach/at91_dbgu.h
arch/arm/mach-at91/include/mach/at91_ramc.h
arch/arm/mach-at91/include/mach/at91rm9200_sdramc.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9_sdramc.h [deleted file]
arch/arm/mach-at91/include/mach/at91x40.h [deleted file]
arch/arm/mach-at91/include/mach/atmel-mci.h [deleted file]
arch/arm/mach-at91/include/mach/cpu.h
arch/arm/mach-at91/include/mach/hardware.h
arch/arm/mach-at91/include/mach/uncompress.h
arch/arm/mach-at91/irq.c [deleted file]
arch/arm/mach-at91/leds.c [deleted file]
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/setup.c
arch/arm/mach-at91/soc.h
arch/arm/mach-at91/stamp9g20.h [deleted file]
arch/arm/mach-bcm/Kconfig
arch/arm/mach-bcm/Makefile
arch/arm/mach-bcm/bcm_cygnus.c [new file with mode: 0644]
arch/arm/mach-bcm/brcmstb.h [new file with mode: 0644]
arch/arm/mach-bcm/headsmp-brcmstb.S [new file with mode: 0644]
arch/arm/mach-bcm/platsmp-brcmstb.c [new file with mode: 0644]
arch/arm/mach-berlin/Kconfig
arch/arm/mach-davinci/board-da830-evm.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-mityomapl138.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/clock.c
arch/arm/mach-davinci/mux.c
arch/arm/mach-davinci/time.c
arch/arm/mach-ebsa110/include/mach/io.h
arch/arm/mach-ebsa110/io.c
arch/arm/mach-ep93xx/dma.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/exynos-pmu.h [new file with mode: 0644]
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/firmware.c
arch/arm/mach-exynos/hotplug.c [deleted file]
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/mcpm-exynos.c
arch/arm/mach-exynos/platsmp.c
arch/arm/mach-exynos/pm.c
arch/arm/mach-exynos/pmu.c
arch/arm/mach-exynos/regs-pmu.h
arch/arm/mach-exynos/sleep.S
arch/arm/mach-exynos/smc.h
arch/arm/mach-exynos/suspend.c [new file with mode: 0644]
arch/arm/mach-highbank/highbank.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/anatop.c
arch/arm/mach-imx/clk-cpu.c [new file with mode: 0644]
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/clk-pllv3.c
arch/arm/mach-imx/clk-vf610.c
arch/arm/mach-imx/clk.h
arch/arm/mach-imx/common.h
arch/arm/mach-imx/gpc.c
arch/arm/mach-imx/imx25-dt.c
arch/arm/mach-imx/imx27-dt.c
arch/arm/mach-imx/imx31-dt.c
arch/arm/mach-imx/imx35-dt.c
arch/arm/mach-imx/iomux-imx31.c
arch/arm/mach-imx/iomux-mx3.h
arch/arm/mach-imx/mach-imx50.c
arch/arm/mach-imx/mach-imx51.c
arch/arm/mach-imx/mach-imx53.c
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-ls1021a.c [new file with mode: 0644]
arch/arm/mach-imx/mach-vf610.c
arch/arm/mach-imx/mmdc.c
arch/arm/mach-imx/mxc.h
arch/arm/mach-imx/platsmp.c
arch/arm/mach-imx/pm-imx6.c
arch/arm/mach-imx/suspend-imx6.S
arch/arm/mach-imx/system.c
arch/arm/mach-integrator/Kconfig
arch/arm/mach-integrator/Makefile
arch/arm/mach-integrator/cm.h
arch/arm/mach-integrator/common.h
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/include/mach/uncompress.h [deleted file]
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-integrator/leds.c [deleted file]
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/include/mach/io.h
arch/arm/mach-keystone/Kconfig
arch/arm/mach-mediatek/Kconfig
arch/arm/mach-mediatek/mediatek.c
arch/arm/mach-meson/Kconfig
arch/arm/mach-meson/meson.c
arch/arm/mach-mvebu/Makefile
arch/arm/mach-mvebu/armada-370-xp.h
arch/arm/mach-mvebu/board-v7.c
arch/arm/mach-mvebu/coherency.c
arch/arm/mach-mvebu/coherency_ll.S
arch/arm/mach-mvebu/common.h
arch/arm/mach-mvebu/cpu-reset.c
arch/arm/mach-mvebu/headsmp-a9.S
arch/arm/mach-mvebu/platsmp-a9.c
arch/arm/mach-mvebu/platsmp.c
arch/arm/mach-mvebu/pm-board.c [new file with mode: 0644]
arch/arm/mach-mvebu/pm.c [new file with mode: 0644]
arch/arm/mach-mvebu/pmsu.c
arch/arm/mach-mvebu/pmsu.h
arch/arm/mach-mvebu/pmsu_ll.S
arch/arm/mach-nomadik/cpu-8815.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/am33xx-restart.c
arch/arm/mach-omap2/board-3430sdp.c [deleted file]
arch/arm/mach-omap2/board-am3517crane.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-cm-t3517.c
arch/arm/mach-omap2/board-flash.c
arch/arm/mach-omap2/board-flash.h
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-ti8168evm.c [deleted file]
arch/arm/mach-omap2/cclock3xxx_data.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock3xxx.c
arch/arm/mach-omap2/cm.h
arch/arm/mach-omap2/cm1_44xx.h
arch/arm/mach-omap2/cm1_54xx.h
arch/arm/mach-omap2/cm1_7xx.h
arch/arm/mach-omap2/cm2_44xx.h
arch/arm/mach-omap2/cm2_54xx.h
arch/arm/mach-omap2/cm2_7xx.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.c [deleted file]
arch/arm/mach-omap2/cm44xx.h
arch/arm/mach-omap2/cm_44xx_54xx.h [deleted file]
arch/arm/mach-omap2/cm_common.c
arch/arm/mach-omap2/cminst44xx.c
arch/arm/mach-omap2/cminst44xx.h [deleted file]
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/dpll44xx.c
arch/arm/mach-omap2/gpmc-nand.c
arch/arm/mach-omap2/gpmc-nand.h [deleted file]
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/gpmc-onenand.h [deleted file]
arch/arm/mach-omap2/gpmc-smc91x.c [deleted file]
arch/arm/mach-omap2/gpmc-smc91x.h [deleted file]
arch/arm/mach-omap2/gpmc.c [deleted file]
arch/arm/mach-omap2/gpmc.h
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/hsmmc.h
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mmc.h
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap2-restart.c
arch/arm/mach-omap2/omap3-restart.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap4-restart.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_43xx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/omap_phy_internal.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm44xx.c
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm2xxx.c
arch/arm/mach-omap2/prm2xxx.h
arch/arm/mach-omap2/prm2xxx_3xxx.c
arch/arm/mach-omap2/prm2xxx_3xxx.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_54xx.h
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/prminst44xx.c
arch/arm/mach-omap2/prminst44xx.h
arch/arm/mach-omap2/serial.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/generic.h
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/include/mach/addr-map.h
arch/arm/mach-pxa/include/mach/pxa25x.h
arch/arm/mach-pxa/include/mach/pxa27x.h
arch/arm/mach-pxa/include/mach/pxa3xx.h
arch/arm/mach-pxa/mfp-pxa2xx.c
arch/arm/mach-pxa/poodle.c
arch/arm/mach-pxa/pxa-dt.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa3xx-ulpi.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/tosa.c
arch/arm/mach-realview/Kconfig
arch/arm/mach-realview/Makefile
arch/arm/mach-realview/realview-dt.c [new file with mode: 0644]
arch/arm/mach-rockchip/headsmp.S
arch/arm/mach-rockchip/platsmp.c
arch/arm/mach-rockchip/rockchip.c
arch/arm/mach-sa1100/include/mach/debug-macro.S [deleted file]
arch/arm/mach-sa1100/pci-nanoengine.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
arch/arm/mach-shmobile/board-ape6evm.c
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-koelsch-reference.c [deleted file]
arch/arm/mach-shmobile/board-koelsch.c [deleted file]
arch/arm/mach-shmobile/board-kzm9g-reference.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-lager-reference.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen-reference.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/clock-r8a73a4.c
arch/arm/mach-shmobile/clock-r8a7740.c
arch/arm/mach-shmobile/clock-r8a7778.c
arch/arm/mach-shmobile/clock-r8a7779.c
arch/arm/mach-shmobile/clock-r8a7790.c
arch/arm/mach-shmobile/clock-r8a7791.c [deleted file]
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-shmobile/clock.c
arch/arm/mach-shmobile/clock.h
arch/arm/mach-shmobile/common.h
arch/arm/mach-shmobile/console.c
arch/arm/mach-shmobile/headsmp-scu.S
arch/arm/mach-shmobile/intc-sh7372.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-shmobile/platsmp-apmu.c
arch/arm/mach-shmobile/platsmp-apmu.h [new file with mode: 0644]
arch/arm/mach-shmobile/pm-r8a7740.c
arch/arm/mach-shmobile/r8a73a4.h
arch/arm/mach-shmobile/r8a7740.h
arch/arm/mach-shmobile/r8a7778.h
arch/arm/mach-shmobile/r8a7791.h
arch/arm/mach-shmobile/setup-emev2.c
arch/arm/mach-shmobile/setup-r7s72100.c
arch/arm/mach-shmobile/setup-r8a73a4.c
arch/arm/mach-shmobile/setup-r8a7740.c
arch/arm/mach-shmobile/setup-r8a7778.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-r8a7790.c
arch/arm/mach-shmobile/setup-r8a7791.c
arch/arm/mach-shmobile/setup-rcar-gen2.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/sh73a0.h
arch/arm/mach-shmobile/sleep-sh7372.S
arch/arm/mach-shmobile/smp-emev2.c
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-shmobile/timer.c
arch/arm/mach-socfpga/core.h
arch/arm/mach-socfpga/headsmp.S
arch/arm/mach-socfpga/platsmp.c
arch/arm/mach-socfpga/socfpga.c
arch/arm/mach-sti/Kconfig
arch/arm/mach-sunxi/Kconfig
arch/arm/mach-sunxi/platsmp.c
arch/arm/mach-sunxi/sunxi.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/cpuidle-tegra114.c
arch/arm/mach-tegra/irq.c
arch/arm/mach-tegra/reset-handler.S
arch/arm/mach-u300/dummyspichip.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/pm.c
arch/arm/mach-ux500/pm_domains.c [new file with mode: 0644]
arch/arm/mach-ux500/pm_domains.h [new file with mode: 0644]
arch/arm/mach-vexpress/Kconfig
arch/arm/mach-vexpress/Makefile
arch/arm/mach-vexpress/core.h
arch/arm/mach-vexpress/ct-ca9x4.c [deleted file]
arch/arm/mach-vexpress/include/mach/ct-ca9x4.h [deleted file]
arch/arm/mach-vexpress/include/mach/hardware.h [deleted file]
arch/arm/mach-vexpress/include/mach/irqs.h [deleted file]
arch/arm/mach-vexpress/include/mach/motherboard.h [deleted file]
arch/arm/mach-vexpress/platsmp.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-zynq/Makefile
arch/arm/mach-zynq/common.h
arch/arm/mach-zynq/hotplug.c [deleted file]
arch/arm/mm/Kconfig
arch/arm/mm/cache-l2x0.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/highmem.c
arch/arm/mm/init.c
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xscale.S
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/include/plat/map-s5p.h
arch/arm/plat-versatile/Kconfig
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/Makefile
arch/arm64/boot/dts/Makefile
arch/arm64/boot/dts/amd/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/amd/amd-overdrive.dts [new file with mode: 0644]
arch/arm64/boot/dts/amd/amd-seattle-clks.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/apm-mustang.dts [deleted file]
arch/arm64/boot/dts/apm-storm.dtsi [deleted file]
arch/arm64/boot/dts/apm/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/apm/apm-mustang.dts [new file with mode: 0644]
arch/arm64/boot/dts/apm/apm-storm.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/arm/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/arm/foundation-v8.dts [new file with mode: 0644]
arch/arm64/boot/dts/arm/juno-clocks.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/arm/juno-motherboard.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/arm/juno.dts [new file with mode: 0644]
arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts [new file with mode: 0644]
arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/cavium/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/cavium/thunder-88xx.dts [new file with mode: 0644]
arch/arm64/boot/dts/cavium/thunder-88xx.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/foundation-v8.dts [deleted file]
arch/arm64/boot/dts/include/dt-bindings [new symlink]
arch/arm64/boot/dts/rtsm_ve-aemv8a.dts [deleted file]
arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi [deleted file]
arch/arm64/boot/dts/thunder-88xx.dts [deleted file]
arch/arm64/boot/dts/thunder-88xx.dtsi [deleted file]
arch/arm64/configs/defconfig
arch/arm64/crypto/Kconfig
arch/arm64/crypto/aes-ce-ccm-glue.c
arch/arm64/crypto/aes-ce-cipher.c
arch/arm64/crypto/aes-ce-setkey.h [new file with mode: 0644]
arch/arm64/crypto/aes-glue.c
arch/arm64/include/asm/alternative-asm.h [new file with mode: 0644]
arch/arm64/include/asm/alternative.h [new file with mode: 0644]
arch/arm64/include/asm/arch_timer.h
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/cmpxchg.h
arch/arm64/include/asm/compat.h
arch/arm64/include/asm/cpu.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/dmi.h [new file with mode: 0644]
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/fixmap.h
arch/arm64/include/asm/hwcap.h
arch/arm64/include/asm/insn.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/irq.h
arch/arm64/include/asm/irq_work.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/opcodes.h [new file with mode: 0644]
arch/arm64/include/asm/percpu.h
arch/arm64/include/asm/pgalloc.h
arch/arm64/include/asm/seccomp.h [new file with mode: 0644]
arch/arm64/include/asm/tlb.h
arch/arm64/include/asm/traps.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/Makefile
arch/arm64/kernel/alternative.c [new file with mode: 0644]
arch/arm64/kernel/armv8_deprecated.c [new file with mode: 0644]
arch/arm64/kernel/cpu_errata.c [new file with mode: 0644]
arch/arm64/kernel/cpuinfo.c
arch/arm64/kernel/efi-entry.S
arch/arm64/kernel/efi.c
arch/arm64/kernel/entry-ftrace.S
arch/arm64/kernel/entry.S
arch/arm64/kernel/head.S
arch/arm64/kernel/insn.c
arch/arm64/kernel/io.c
arch/arm64/kernel/irq.c
arch/arm64/kernel/jump_label.c
arch/arm64/kernel/module.c
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/process.c
arch/arm64/kernel/psci.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/signal32.c
arch/arm64/kernel/sleep.S
arch/arm64/kernel/smp.c
arch/arm64/kernel/suspend.c
arch/arm64/kernel/sys_compat.c
arch/arm64/kernel/topology.c
arch/arm64/kernel/trace-events-emulation.h [new file with mode: 0644]
arch/arm64/kernel/traps.c
arch/arm64/kernel/vmlinux.lds.S
arch/arm64/kvm/hyp.S
arch/arm64/kvm/sys_regs.c
arch/arm64/lib/clear_user.S
arch/arm64/mm/Makefile
arch/arm64/mm/cache.S
arch/arm64/mm/dump.c [new file with mode: 0644]
arch/arm64/mm/fault.c
arch/arm64/mm/init.c
arch/arm64/mm/ioremap.c
arch/arm64/mm/mm.h
arch/arm64/mm/mmap.c
arch/arm64/mm/mmu.c
arch/arm64/mm/pgd.c
arch/arm64/net/bpf_jit.h
arch/arm64/net/bpf_jit_comp.c
arch/avr32/mach-at32ap/at32ap700x.c
arch/avr32/mach-at32ap/include/mach/atmel-mci.h [deleted file]
arch/cris/include/asm/io.h
arch/frv/include/asm/io.h
arch/ia64/include/asm/io.h
arch/ia64/include/asm/uaccess.h
arch/ia64/kernel/efi.c
arch/ia64/kvm/kvm-ia64.c
arch/m32r/include/asm/io.h
arch/m68k/atari/config.c
arch/m68k/atari/stdma.c
arch/m68k/include/asm/atari_stdma.h
arch/m68k/include/asm/io.h
arch/m68k/include/asm/io_no.h
arch/m68k/include/asm/macintosh.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
arch/m68k/mac/config.c
arch/m68k/mm/init.c
arch/m68k/sun3/config.c
arch/microblaze/Kconfig
arch/microblaze/include/asm/io.h
arch/microblaze/include/asm/tlb.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/include/uapi/asm/unistd.h
arch/microblaze/kernel/syscall_table.S
arch/microblaze/pci/pci-common.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/ath79/mach-db120.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/cavium-octeon/setup.c
arch/mips/include/asm/asmmacro-32.h
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/cop2.h
arch/mips/include/asm/fpregdef.h
arch/mips/include/asm/fpu.h
arch/mips/include/asm/ftrace.h
arch/mips/include/asm/idle.h
arch/mips/include/asm/jump_label.h
arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/r4kcache.h
arch/mips/include/asm/uaccess.h
arch/mips/include/uapi/asm/ptrace.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/kernel/bmips_vec.S
arch/mips/kernel/branch.c
arch/mips/kernel/cps-vec.S
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/genex.S
arch/mips/kernel/idle.c
arch/mips/kernel/jump_label.c
arch/mips/kernel/r2300_fpu.S
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/r6000_fpu.S
arch/mips/kernel/rtlx.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/lasat/Kconfig
arch/mips/lib/memcpy.S
arch/mips/lib/r3k_dump_tlb.c
arch/mips/lib/strnlen_user.S
arch/mips/loongson/common/Makefile
arch/mips/loongson/lemote-2f/clock.c
arch/mips/loongson/loongson-3/numa.c
arch/mips/math-emu/cp1emu.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/Makefile
arch/mips/mti-sead3/Makefile
arch/mips/mti-sead3/sead3-i2c.c
arch/mips/mti-sead3/sead3-leds.c
arch/mips/mti-sead3/sead3-pic32-bus.c [deleted file]
arch/mips/mti-sead3/sead3-pic32-i2c-drv.c [deleted file]
arch/mips/netlogic/xlp/Makefile
arch/mips/oprofile/backtrace.c
arch/mips/pci/msi-xlp.c
arch/mips/pci/pci-lantiq.c
arch/mips/pmcs-msp71xx/msp_irq.c
arch/mips/pmcs-msp71xx/msp_irq_cic.c
arch/mips/sgi-ip27/ip27-memory.c
arch/mips/sibyte/Makefile
arch/mn10300/include/asm/io.h
arch/nios2/Kconfig [new file with mode: 0644]
arch/nios2/Kconfig.debug [new file with mode: 0644]
arch/nios2/Makefile [new file with mode: 0644]
arch/nios2/boot/Makefile [new file with mode: 0644]
arch/nios2/boot/dts/3c120_devboard.dts [new file with mode: 0644]
arch/nios2/boot/install.sh [new file with mode: 0644]
arch/nios2/boot/linked_dtb.S [new file with mode: 0644]
arch/nios2/configs/3c120_defconfig [new file with mode: 0644]
arch/nios2/include/asm/Kbuild [new file with mode: 0644]
arch/nios2/include/asm/asm-macros.h [new file with mode: 0644]
arch/nios2/include/asm/asm-offsets.h [new file with mode: 0644]
arch/nios2/include/asm/cache.h [new file with mode: 0644]
arch/nios2/include/asm/cacheflush.h [new file with mode: 0644]
arch/nios2/include/asm/checksum.h [new file with mode: 0644]
arch/nios2/include/asm/cmpxchg.h [new file with mode: 0644]
arch/nios2/include/asm/cpuinfo.h [new file with mode: 0644]
arch/nios2/include/asm/delay.h [new file with mode: 0644]
arch/nios2/include/asm/dma-mapping.h [new file with mode: 0644]
arch/nios2/include/asm/elf.h [new file with mode: 0644]
arch/nios2/include/asm/entry.h [new file with mode: 0644]
arch/nios2/include/asm/io.h [new file with mode: 0644]
arch/nios2/include/asm/irq.h [new file with mode: 0644]
arch/nios2/include/asm/irqflags.h [new file with mode: 0644]
arch/nios2/include/asm/linkage.h [new file with mode: 0644]
arch/nios2/include/asm/mmu.h [new file with mode: 0644]
arch/nios2/include/asm/mmu_context.h [new file with mode: 0644]
arch/nios2/include/asm/mutex.h [new file with mode: 0644]
arch/nios2/include/asm/page.h [new file with mode: 0644]
arch/nios2/include/asm/pgalloc.h [new file with mode: 0644]
arch/nios2/include/asm/pgtable-bits.h [new file with mode: 0644]
arch/nios2/include/asm/pgtable.h [new file with mode: 0644]
arch/nios2/include/asm/processor.h [new file with mode: 0644]
arch/nios2/include/asm/ptrace.h [new file with mode: 0644]
arch/nios2/include/asm/registers.h [new file with mode: 0644]
arch/nios2/include/asm/setup.h [new file with mode: 0644]
arch/nios2/include/asm/signal.h [new file with mode: 0644]
arch/nios2/include/asm/string.h [new file with mode: 0644]
arch/nios2/include/asm/switch_to.h [new file with mode: 0644]
arch/nios2/include/asm/syscall.h [new file with mode: 0644]
arch/nios2/include/asm/syscalls.h [new file with mode: 0644]
arch/nios2/include/asm/thread_info.h [new file with mode: 0644]
arch/nios2/include/asm/timex.h [new file with mode: 0644]
arch/nios2/include/asm/tlb.h [new file with mode: 0644]
arch/nios2/include/asm/tlbflush.h [new file with mode: 0644]
arch/nios2/include/asm/traps.h [new file with mode: 0644]
arch/nios2/include/asm/uaccess.h [new file with mode: 0644]
arch/nios2/include/asm/ucontext.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/Kbuild [new file with mode: 0644]
arch/nios2/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/elf.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/signal.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/swab.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/nios2/kernel/Makefile [new file with mode: 0644]
arch/nios2/kernel/asm-offsets.c [new file with mode: 0644]
arch/nios2/kernel/cpuinfo.c [new file with mode: 0644]
arch/nios2/kernel/entry.S [new file with mode: 0644]
arch/nios2/kernel/head.S [new file with mode: 0644]
arch/nios2/kernel/insnemu.S [new file with mode: 0644]
arch/nios2/kernel/irq.c [new file with mode: 0644]
arch/nios2/kernel/misaligned.c [new file with mode: 0644]
arch/nios2/kernel/module.c [new file with mode: 0644]
arch/nios2/kernel/nios2_ksyms.c [new file with mode: 0644]
arch/nios2/kernel/process.c [new file with mode: 0644]
arch/nios2/kernel/prom.c [new file with mode: 0644]
arch/nios2/kernel/ptrace.c [new file with mode: 0644]
arch/nios2/kernel/setup.c [new file with mode: 0644]
arch/nios2/kernel/signal.c [new file with mode: 0644]
arch/nios2/kernel/sys_nios2.c [new file with mode: 0644]
arch/nios2/kernel/syscall_table.c [new file with mode: 0644]
arch/nios2/kernel/time.c [new file with mode: 0644]
arch/nios2/kernel/traps.c [new file with mode: 0644]
arch/nios2/kernel/vmlinux.lds.S [new file with mode: 0644]
arch/nios2/lib/Makefile [new file with mode: 0644]
arch/nios2/lib/delay.c [new file with mode: 0644]
arch/nios2/lib/memcpy.c [new file with mode: 0644]
arch/nios2/lib/memmove.c [new file with mode: 0644]
arch/nios2/lib/memset.c [new file with mode: 0644]
arch/nios2/mm/Makefile [new file with mode: 0644]
arch/nios2/mm/cacheflush.c [new file with mode: 0644]
arch/nios2/mm/dma-mapping.c [new file with mode: 0644]
arch/nios2/mm/extable.c [new file with mode: 0644]
arch/nios2/mm/fault.c [new file with mode: 0644]
arch/nios2/mm/init.c [new file with mode: 0644]
arch/nios2/mm/ioremap.c [new file with mode: 0644]
arch/nios2/mm/mmu_context.c [new file with mode: 0644]
arch/nios2/mm/pgtable.c [new file with mode: 0644]
arch/nios2/mm/tlb.c [new file with mode: 0644]
arch/nios2/mm/uaccess.c [new file with mode: 0644]
arch/nios2/platform/Kconfig.platform [new file with mode: 0644]
arch/nios2/platform/Makefile [new file with mode: 0644]
arch/nios2/platform/platform.c [new file with mode: 0644]
arch/parisc/include/asm/io.h
arch/parisc/include/asm/uaccess.h
arch/parisc/include/uapi/asm/bitsperlong.h
arch/parisc/include/uapi/asm/msgbuf.h
arch/parisc/include/uapi/asm/sembuf.h
arch/parisc/include/uapi/asm/shmbuf.h
arch/parisc/include/uapi/asm/signal.h
arch/parisc/include/uapi/asm/unistd.h
arch/parisc/kernel/syscall_table.S
arch/powerpc/configs/pseries_le_defconfig
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/fadump.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/perf_event.h
arch/powerpc/include/asm/pgalloc.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/syscall.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/tlb.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/eeh_pe.c
arch/powerpc/kernel/eeh_sysfs.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/fadump.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/misc.S
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/stacktrace.c
arch/powerpc/kernel/vdso32/getcpu.S
arch/powerpc/mm/copro_fault.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/slice.c
arch/powerpc/perf/hv-24x7.c
arch/powerpc/perf/hv-gpci.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/opal-hmi.c
arch/powerpc/platforms/powernv/opal-lpc.c
arch/powerpc/platforms/powernv/opal-sensor.c
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/msi_bitmap.c
arch/powerpc/xmon/xmon.c
arch/s390/configs/default_defconfig
arch/s390/configs/gcov_defconfig
arch/s390/configs/performance_defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/defconfig
arch/s390/include/asm/io.h
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/compat_wrapper.c
arch/s390/kernel/ftrace.c
arch/s390/kernel/nmi.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/uprobes.c
arch/s390/kernel/vdso32/clock_gettime.S
arch/s390/kernel/vdso32/gettimeofday.S
arch/s390/kernel/vdso64/clock_gettime.S
arch/s390/kernel/vdso64/gettimeofday.S
arch/s390/kernel/vtime.c
arch/s390/lib/probes.c
arch/s390/mm/maccess.c
arch/s390/mm/pgtable.c
arch/sh/kernel/cpu/sh3/setup-sh770x.c
arch/sparc/include/asm/atomic_32.h
arch/sparc/include/asm/cmpxchg_32.h
arch/sparc/include/asm/dma-mapping.h
arch/sparc/include/asm/io_32.h
arch/sparc/include/asm/io_64.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/include/asm/setup.h
arch/sparc/include/uapi/asm/swab.h
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/entry.h
arch/sparc/kernel/head_64.S
arch/sparc/kernel/hvtramp.S
arch/sparc/kernel/pci_schizo.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/trampoline_64.S
arch/sparc/lib/atomic32.c
arch/sparc/mm/gup.c
arch/sparc/prom/cif.S
arch/sparc/prom/init_64.c
arch/sparc/prom/p1275.c
arch/tile/include/asm/io.h
arch/x86/Kconfig
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/boot/compressed/head_32.S
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/mkpiggy.c
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/efi.h
arch/x86/include/asm/io.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/page_32_types.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/preempt.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/spinlock.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/traps.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/include/uapi/asm/vmx.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/amd_nb.c
arch/x86/kernel/apb_timer.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/microcode/amd_early.c
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/microcode/core_early.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd_ibs.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/i8259.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kvm/emulate.c
arch/x86/kvm/i8254.c
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/csum-wrappers_64.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/pageattr.c
arch/x86/platform/efi/efi-bgrt.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/efi_stub_32.S
arch/x86/platform/intel-mid/intel_mid_weak_decls.h
arch/x86/platform/intel-mid/sfi.c
arch/x86/tools/calc_run_size.pl [new file with mode: 0644]
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/p2m.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
arch/x86/xen/time.c
arch/xtensa/Kconfig
arch/xtensa/boot/dts/lx200mx.dts [new file with mode: 0644]
arch/xtensa/configs/generic_kc705_defconfig [new file with mode: 0644]
arch/xtensa/configs/smp_lx200_defconfig [new file with mode: 0644]
arch/xtensa/include/asm/io.h
arch/xtensa/include/asm/pgtable.h
arch/xtensa/include/uapi/asm/unistd.h
block/bio-integrity.c
block/blk-core.c
block/blk-merge.c
block/blk-mq-tag.c
block/blk-mq.c
block/elevator.c
block/ioprio.c
block/scsi_ioctl.c
crypto/cts.c
crypto/sha1_generic.c
crypto/sha256_generic.c
crypto/sha512_generic.c
crypto/tgr192.c
crypto/vmac.c
crypto/wp512.c
drivers/Kconfig
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/acpi_platform.c
drivers/acpi/acpica/achware.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/actables.h
drivers/acpi/acpica/amlresrc.h
drivers/acpi/acpica/evgpe.c
drivers/acpi/acpica/evgpeinit.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/evxfevnt.c
drivers/acpi/acpica/evxfgpe.c
drivers/acpi/acpica/hwgpe.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/blacklist.c
drivers/acpi/device_pm.c
drivers/acpi/ec.c
drivers/acpi/fan.c
drivers/acpi/int340x_thermal.c [new file with mode: 0644]
drivers/acpi/internal.h
drivers/acpi/scan.c
drivers/acpi/sysfs.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/amba/Kconfig [new file with mode: 0644]
drivers/ata/ahci.c
drivers/ata/libahci.c
drivers/ata/libata-scsi.c
drivers/ata/sata_fsl.c
drivers/ata/sata_nv.c
drivers/ata/sata_rcar.c
drivers/atm/solos-pci.c
drivers/base/Kconfig
drivers/base/core.c
drivers/base/dma-contiguous.c
drivers/base/power/domain.c
drivers/base/power/main.c
drivers/base/regmap/Kconfig
drivers/base/regmap/Makefile
drivers/base/regmap/regcache-flat.c
drivers/base/regmap/regcache-lzo.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-ac97.c [new file with mode: 0644]
drivers/bcma/host_pci.c
drivers/bcma/main.c
drivers/block/null_blk.c
drivers/block/nvme-scsi.c
drivers/block/rbd.c
drivers/block/sunvdc.c
drivers/block/zram/zram_drv.c
drivers/bus/Kconfig
drivers/bus/arm-cci.c
drivers/bus/brcmstb_gisb.c
drivers/bus/mvebu-mbus.c
drivers/bus/omap_l3_noc.c
drivers/bus/omap_l3_smx.c
drivers/char/hw_random/pseries-rng.c
drivers/char/mem.c
drivers/char/random.c
drivers/char/raw.c
drivers/char/virtio_console.c
drivers/clk/at91/clk-usb.c
drivers/clk/clk-divider.c
drivers/clk/clk-s2mps11.c
drivers/clk/mvebu/common.c
drivers/clk/pxa/clk-pxa27x.c
drivers/clk/qcom/mmcc-apq8084.c
drivers/clk/rockchip/clk.c
drivers/clk/samsung/clk-exynos5440.c
drivers/clk/tegra/clk-divider.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.h
drivers/clk/ti/dpll.c
drivers/clk/versatile/Makefile
drivers/clk/versatile/clk-vexpress-osc.c
drivers/clk/versatile/clk-vexpress.c [deleted file]
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/sun4i_timer.c
drivers/clocksource/time-armada-370-xp.c
drivers/clocksource/timer-atmel-pit.c
drivers/clocksource/timer-integrator-ap.c [new file with mode: 0644]
drivers/clocksource/timer-marco.c
drivers/cpufreq/cpufreq-dt.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/highbank-cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/Kconfig.mips
drivers/cpuidle/cpuidle-powernv.c
drivers/crypto/caam/key_gen.c
drivers/crypto/qat/qat_common/adf_accel_devices.h
drivers/crypto/qat/qat_common/adf_transport.c
drivers/crypto/qat/qat_common/qat_algs.c
drivers/crypto/qat/qat_common/qat_crypto.c
drivers/crypto/qat/qat_dh895xcc/adf_admin.c
drivers/crypto/qat/qat_dh895xcc/adf_drv.c
drivers/crypto/qat/qat_dh895xcc/adf_isr.c
drivers/dma/edma.c
drivers/dma/pl330.c
drivers/dma/sun6i-dma.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/cpc925_edac.c
drivers/edac/e7xxx_edac.c
drivers/edac/edac_mc.c
drivers/edac/edac_pci_sysfs.c
drivers/edac/ghes_edac.c
drivers/edac/i3000_edac.c
drivers/edac/i3200_edac.c
drivers/edac/i82443bxgx_edac.c
drivers/edac/i82860_edac.c
drivers/edac/mce_amd.c
drivers/edac/mce_amd_inj.c
drivers/edac/mv64x60_edac.c
drivers/edac/ppc4xx_edac.c
drivers/edac/x38_edac.c
drivers/firewire/core-cdev.c
drivers/firmware/dmi_scan.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/runtime-wrappers.c
drivers/firmware/efi/vars.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-dln2.c [new file with mode: 0644]
drivers/gpio/gpio-tc3589x.c
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/exynos/exynos_dp_core.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_dpi.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv50.c
drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_fence.h
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/radeon/atom.c
drivers/gpu/drm/radeon/atom.h
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_i2c.c
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/btc_dpm.h
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/cypress_dpm.c
drivers/gpu/drm/radeon/dce3_1_afmt.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600_dma.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_vm.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rs780_dpm.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv6xx_dpm.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/radeon/sumo_dpm.c
drivers/gpu/drm/radeon/trinity_dpm.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-sensor-hub.c
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/fam15h_power.c
drivers/hwmon/g762.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/ibmpowernv.c
drivers/hwmon/iio_hwmon.c
drivers/hwmon/ina2xx.c
drivers/hwmon/lm75.c
drivers/hwmon/lm95234.c
drivers/hwmon/lm95245.c
drivers/hwmon/menf21bmc_hwmon.c
drivers/hwmon/nct6775.c
drivers/hwmon/nct7802.c [new file with mode: 0644]
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/pmbus/ltc2978.c
drivers/hwmon/pmbus/pmbus.h
drivers/hwmon/pmbus/pmbus_core.c
drivers/hwmon/pwm-fan.c
drivers/hwmon/tmp401.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/algos/i2c-algo-pcf.h
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756-s4882.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-pcidrv.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-dln2.c [new file with mode: 0644]
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-iop3xx.h
drivers/i2c/busses/i2c-isch.c
drivers/i2c/busses/i2c-ismt.c
drivers/i2c/busses/i2c-nforce2-s4985.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-parport.h
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-sibyte.c
drivers/i2c/busses/i2c-simtec.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-taos-evm.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/i2c-boardinfo.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.h
drivers/i2c/i2c-dev.c
drivers/i2c/i2c-smbus.c
drivers/i2c/i2c-stub.c
drivers/iio/accel/bmc150-accel.c
drivers/iio/accel/kxcjk-1013.c
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/axp288_adc.c [new file with mode: 0644]
drivers/iio/adc/men_z188_adc.c
drivers/iio/common/st_sensors/st_sensors_buffer.c
drivers/iio/gyro/bmg160.c
drivers/iio/light/tsl4531.c
drivers/iio/proximity/as3935.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/evdev.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/opencores-kbd.c
drivers/input/keyboard/stmpe-keypad.c
drivers/input/misc/ims-pcu.c
drivers/input/misc/max77693-haptic.c
drivers/input/misc/soc_button_array.c
drivers/input/misc/twl4030-pwrbutton.c
drivers/input/mouse/alps.c
drivers/input/mouse/elantech.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/vsxxxaa.c
drivers/input/serio/altera_ps2.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/touchscreen/wm97xx-core.c
drivers/iommu/Kconfig
drivers/iommu/amd_iommu.c
drivers/iommu/arm-smmu.c
drivers/iommu/exynos-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/iommu.c
drivers/iommu/ipmmu-vmsa.c
drivers/iommu/msm_iommu.c
drivers/iommu/omap-iommu.c
drivers/iommu/shmobile-iommu.c
drivers/iommu/tegra-smmu.c
drivers/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-atmel-aic-common.c
drivers/irqchip/irq-bcm7120-l2.c
drivers/irqchip/irq-brcmstb-l2.c
drivers/irqchip/irq-gic.c
drivers/leds/led-class.c
drivers/leds/led-core.c
drivers/leds/leds-gpio-register.c
drivers/leds/leds-gpio.c
drivers/leds/leds-lp3944.c
drivers/leds/trigger/ledtrig-gpio.c
drivers/mailbox/Makefile
drivers/mailbox/mailbox.c [new file with mode: 0644]
drivers/mailbox/pl320-ipc.c
drivers/md/dm-bio-prison.c
drivers/md/dm-bio-prison.h
drivers/md/dm-bufio.c
drivers/md/dm-cache-block-types.h
drivers/md/dm-cache-metadata.c
drivers/md/dm-cache-metadata.h
drivers/md/dm-cache-policy-mq.c
drivers/md/dm-cache-target.c
drivers/md/dm-crypt.c
drivers/md/dm-ioctl.c
drivers/md/dm-raid.c
drivers/md/dm-stats.c
drivers/md/dm-stripe.c
drivers/md/dm-table.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/md/dm.h
drivers/md/md.c
drivers/md/persistent-data/dm-array.c
drivers/md/persistent-data/dm-btree-internal.h
drivers/md/persistent-data/dm-btree-spine.c
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/persistent-data/dm-transaction-manager.c
drivers/md/persistent-data/dm-transaction-manager.h
drivers/media/common/saa7146/saa7146_core.c
drivers/media/dvb-core/dvb_frontend.c
drivers/media/dvb-frontends/ds3000.c
drivers/media/dvb-frontends/sp2.c
drivers/media/dvb-frontends/tc90522.c
drivers/media/i2c/smiapp/smiapp-core.c
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/pci/solo6x10/solo6x10-core.c
drivers/media/pci/tw68/Kconfig
drivers/media/pci/tw68/tw68-core.c
drivers/media/platform/Kconfig
drivers/media/platform/exynos4-is/Kconfig
drivers/media/platform/exynos4-is/fimc-core.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-tv/Kconfig
drivers/media/platform/vivid/Kconfig
drivers/media/platform/vivid/vivid-core.c
drivers/media/platform/vivid/vivid-tpg.c
drivers/media/radio/wl128x/fmdrv_common.c
drivers/media/rc/imon.c
drivers/media/rc/ir-hix5hd2.c
drivers/media/rc/ir-rc5-decoder.c
drivers/media/rc/ir-rc6-decoder.c
drivers/media/rc/rc-ir-raw.c
drivers/media/rc/rc-main.c
drivers/media/tuners/xc5000.c
drivers/media/usb/dvb-usb-v2/af9035.c
drivers/media/usb/dvb-usb-v2/anysee.c
drivers/media/usb/em28xx/em28xx-core.c
drivers/media/usb/em28xx/em28xx-input.c
drivers/media/usb/hackrf/hackrf.c
drivers/media/usb/s2255/s2255drv.c
drivers/media/usb/usbvision/usbvision-video.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/media/usb/uvc/uvc_video.c
drivers/media/usb/uvc/uvcvideo.h
drivers/media/v4l2-core/videobuf-dma-contig.c
drivers/memory/Kconfig
drivers/memory/Makefile
drivers/memory/omap-gpmc.c [new file with mode: 0644]
drivers/memory/tegra/Kconfig [new file with mode: 0644]
drivers/memory/tegra/Makefile [new file with mode: 0644]
drivers/memory/tegra/mc.c [new file with mode: 0644]
drivers/memory/tegra/mc.h [new file with mode: 0644]
drivers/memory/tegra/tegra114.c [new file with mode: 0644]
drivers/memory/tegra/tegra124.c [new file with mode: 0644]
drivers/memory/tegra/tegra30.c [new file with mode: 0644]
drivers/memory/tegra30-mc.c [deleted file]
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptscsih.h
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ab8500-sysctrl.c
drivers/mfd/arizona-spi.c
drivers/mfd/atmel-hlcdc.c [new file with mode: 0644]
drivers/mfd/axp20x.c
drivers/mfd/da9063-core.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/dln2.c [new file with mode: 0644]
drivers/mfd/lpc_sch.c
drivers/mfd/max14577.c
drivers/mfd/max77693.c
drivers/mfd/mfd-core.c
drivers/mfd/rts5227.c
drivers/mfd/rts5249.c
drivers/mfd/rtsx_gops.c [new file with mode: 0644]
drivers/mfd/rtsx_pcr.c
drivers/mfd/rtsx_pcr.h
drivers/mfd/rtsx_usb.c
drivers/mfd/sec-core.c
drivers/mfd/sec-irq.c
drivers/mfd/stmpe.h
drivers/mfd/syscon.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc3589x.c
drivers/mfd/tc6387xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/tps65090.c
drivers/mfd/tps65217.c
drivers/mfd/twl4030-power.c
drivers/mfd/viperboard.c
drivers/mfd/wm5102-tables.c
drivers/mfd/wm5110-tables.c
drivers/mfd/wm8350-core.c
drivers/mfd/wm8997-tables.c
drivers/misc/Kconfig
drivers/misc/cxl/fault.c
drivers/misc/cxl/native.c
drivers/misc/eeprom/eeprom_93cx6.c
drivers/misc/enclosure.c
drivers/misc/vexpress-syscfg.c
drivers/mmc/card/block.c
drivers/mmc/card/mmc_test.c
drivers/mmc/card/queue.c
drivers/mmc/core/bus.c
drivers/mmc/core/core.c
drivers/mmc/core/core.h
drivers/mmc/core/debugfs.c
drivers/mmc/core/host.c
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/mmc_ops.h
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc-rockchip.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h
drivers/mmc/host/mmci.c
drivers/mmc/host/msm_sdcc.c
drivers/mmc/host/mvsdio.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-of-arasan.c
drivers/mmc/host/sdhci-pci-o2micro.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pxav2.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sunxi-mmc.c
drivers/mmc/host/toshsd.c [new file with mode: 0644]
drivers/mmc/host/toshsd.h [new file with mode: 0644]
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/devices/m25p80.c
drivers/mtd/nand/omap_elm.c
drivers/mtd/spi-nor/fsl-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/Kconfig
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_netlink.c
drivers/net/can/dev.c
drivers/net/can/m_can/Kconfig
drivers/net/can/m_can/m_can.c
drivers/net/can/rcar_can.c
drivers/net/can/sja1000/kvaser_pci.c
drivers/net/can/usb/ems_usb.c
drivers/net/can/usb/esd_usb2.c
drivers/net/can/usb/gs_usb.c
drivers/net/can/xilinx_can.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/mv88e6171.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmgenet.h
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4vf/adapter.h
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/sge.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/cisco/enic/enic_clsf.c
drivers/net/ethernet/cisco/enic/enic_main.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fs_enet/mac-fec.c
drivers/net/ethernet/freescale/fs_enet/mac-scc.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qualcomm/Kconfig
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/tx.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_ale.c
drivers/net/ethernet/ti/cpsw_ale.h
drivers/net/ethernet/ti/cpts.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ieee802154/fakehard.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/phy/dp83640.c
drivers/net/phy/marvell.c
drivers/net/phy/phy.c
drivers/net/ppp/ppp_generic.c
drivers/net/ppp/pptp.c
drivers/net/tun.c
drivers/net/usb/asix_devices.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/usb/usbnet.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/common.c
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/b43/phy_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/of.c
drivers/net/wireless/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/iwl-8000.c
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/mvm/coex.c
drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/time-event.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/11n_rxreorder.h
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/rtlwifi/core.h
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
drivers/net/wireless/rtlwifi/rtl8192ce/def.h
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/rtl8192de/sw.c
drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
drivers/net/wireless/rtlwifi/rtl8192se/def.h
drivers/net/wireless/rtlwifi/rtl8192se/hw.c
drivers/net/wireless/rtlwifi/rtl8192se/phy.c
drivers/net/wireless/rtlwifi/rtl8192se/sw.c
drivers/net/wireless/rtlwifi/rtl8192se/trx.c
drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netback/xenbus.c
drivers/net/xen-netfront.c
drivers/nubus/nubus.c
drivers/of/address.c
drivers/of/base.c
drivers/of/dynamic.c
drivers/of/fdt.c
drivers/of/of_reserved_mem.c
drivers/of/selftest.c
drivers/of/testcase-data/tests-phandle.dtsi
drivers/pci/access.c
drivers/pci/host/pci-imx6.c
drivers/pci/host/pci-tegra.c
drivers/pci/host/pci-xgene.c
drivers/pci/hotplug/pciehp_core.c
drivers/pci/msi.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.h
drivers/pci/pcie/pme.c
drivers/pci/probe.c
drivers/phy/phy-omap-usb2.c
drivers/pinctrl/pinctrl-baytrail.c
drivers/platform/x86/Kconfig
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/hp_accel.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/power/ab8500_fg.c
drivers/power/bq2415x_charger.c
drivers/power/charger-manager.c
drivers/power/power_supply_core.c
drivers/power/reset/Kconfig
drivers/power/reset/Makefile
drivers/power/reset/at91-reset.c
drivers/power/reset/imx-snvs-poweroff.c [new file with mode: 0644]
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/core.c
drivers/pwm/pwm-atmel.c
drivers/pwm/pwm-fsl-ftm.c
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-lpss-pci.c [new file with mode: 0644]
drivers/pwm/pwm-lpss-platform.c [new file with mode: 0644]
drivers/pwm/pwm-lpss.c
drivers/pwm/pwm-lpss.h [new file with mode: 0644]
drivers/pwm/pwm-rockchip.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/act8865-regulator.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/core.c
drivers/regulator/da9052-regulator.c
drivers/regulator/da9063-regulator.c
drivers/regulator/da9210-regulator.c
drivers/regulator/dummy.c
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/max1586.c
drivers/regulator/max77686.c
drivers/regulator/max77693.c
drivers/regulator/max77802.c
drivers/regulator/max8660.c
drivers/regulator/max8952.c
drivers/regulator/max8973-regulator.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/of_regulator.c
drivers/regulator/pwm-regulator.c
drivers/regulator/qcom_rpm-regulator.c
drivers/regulator/rk808-regulator.c
drivers/regulator/rn5t618-regulator.c
drivers/regulator/rt5033-regulator.c [new file with mode: 0644]
drivers/regulator/s2mpa01.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/sky81452-regulator.c
drivers/regulator/stw481x-vmmc.c
drivers/regulator/ti-abb-regulator.c
drivers/regulator/tps51632-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65090-regulator.c
drivers/regulator/tps65218-regulator.c
drivers/regulator/twl-regulator.c
drivers/regulator/vexpress.c
drivers/regulator/wm8994-regulator.c
drivers/reset/Makefile
drivers/reset/core.c
drivers/reset/reset-berlin.c [new file with mode: 0644]
drivers/reset/reset-socfpga.c
drivers/reset/sti/Kconfig
drivers/reset/sti/Makefile
drivers/reset/sti/reset-stih407.c [new file with mode: 0644]
drivers/rtc/Kconfig
drivers/rtc/class.c
drivers/rtc/rtc-at91sam9.c
drivers/rtc/rtc-bq32k.c
drivers/rtc/rtc-efi.c
drivers/rtc/rtc-lib.c
drivers/rtc/rtc-pm8xxx.c
drivers/rtc/rtc-s3c.c
drivers/s390/char/Kconfig
drivers/s390/kvm/virtio_ccw.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fc.c
drivers/s390/scsi/zfcp_fc.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-sas.c
drivers/scsi/3w-xxxx.c
drivers/scsi/53c700.c
drivers/scsi/BusLogic.c
drivers/scsi/Kconfig
drivers/scsi/Makefile
drivers/scsi/NCR5380.c
drivers/scsi/NCR5380.h
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/linit.c
drivers/scsi/advansys.c
drivers/scsi/aha152x.c
drivers/scsi/aha1740.c
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic94xx/aic94xx.h
drivers/scsi/aic94xx/aic94xx_hwi.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/aic94xx/aic94xx_task.c
drivers/scsi/am53c974.c [new file with mode: 0644]
drivers/scsi/arcmsr/arcmsr_hba.c
drivers/scsi/arm/acornscsi.c
drivers/scsi/arm/cumana_1.c
drivers/scsi/arm/fas216.c
drivers/scsi/arm/oak.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/atari_scsi.c
drivers/scsi/atari_scsi.h [deleted file]
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/bfa/bfad_debugfs.c
drivers/scsi/bfa/bfad_im.c
drivers/scsi/bnx2fc/bnx2fc_els.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2i/bnx2i_iscsi.c
drivers/scsi/ch.c
drivers/scsi/constants.c
drivers/scsi/csiostor/csio_scsi.c
drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/cxgbi/libcxgbi.h
drivers/scsi/device_handler/scsi_dh.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/device_handler/scsi_dh_emc.c
drivers/scsi/device_handler/scsi_dh_hp_sw.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/dmx3191d.c
drivers/scsi/dpt_i2o.c
drivers/scsi/dtc.c
drivers/scsi/dtc.h
drivers/scsi/eata.c
drivers/scsi/esas2r/esas2r.h
drivers/scsi/esas2r/esas2r_ioctl.c
drivers/scsi/esas2r/esas2r_main.c
drivers/scsi/esp_scsi.c
drivers/scsi/esp_scsi.h
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_fcs.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/fnic/fnic_trace.c
drivers/scsi/g_NCR5380.c
drivers/scsi/g_NCR5380.h
drivers/scsi/gdth.c
drivers/scsi/hosts.c
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h
drivers/scsi/hpsa_cmd.h
drivers/scsi/hptiop.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/ipr.c
drivers/scsi/ipr.h
drivers/scsi/ips.c
drivers/scsi/isci/init.c
drivers/scsi/isci/task.c
drivers/scsi/isci/task.h
drivers/scsi/iscsi_tcp.c
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_ata.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsas/sas_init.c
drivers/scsi/libsas/sas_internal.h
drivers/scsi/libsas/sas_scsi_host.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/mac_scsi.c
drivers/scsi/mac_scsi.h [deleted file]
drivers/scsi/megaraid.c
drivers/scsi/megaraid/megaraid_mbox.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fp.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/megaraid/megaraid_sas_fusion.h
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/mvsas/mv_init.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/mvsas/mv_sas.h
drivers/scsi/ncr53c8xx.c
drivers/scsi/osd/Kbuild
drivers/scsi/osd/Kconfig
drivers/scsi/osd/osd_debug.h
drivers/scsi/osd/osd_initiator.c
drivers/scsi/osd/osd_uld.c
drivers/scsi/osst.c
drivers/scsi/pas16.c
drivers/scsi/pas16.h
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm8001_sas.h
drivers/scsi/pmcraid.c
drivers/scsi/ps3rom.c
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_mr.c
drivers/scsi/qla2xxx/qla_nx2.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla4xxx/ql4_iocb.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_logging.h
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_trace.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/scsicam.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/ses.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/scsi/sr.h
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
drivers/scsi/stex.c
drivers/scsi/storvsc_drv.c
drivers/scsi/sun3_NCR5380.c [deleted file]
drivers/scsi/sun3_scsi.c
drivers/scsi/sun3_scsi.h
drivers/scsi/sym53c8xx_2/sym_glue.c
drivers/scsi/t128.c
drivers/scsi/t128.h
drivers/scsi/tmscsim.c [deleted file]
drivers/scsi/tmscsim.h [deleted file]
drivers/scsi/u14-34f.c
drivers/scsi/ufs/ufshcd-pltfrm.c
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h
drivers/scsi/virtio_scsi.c
drivers/scsi/vmw_pvscsi.c
drivers/scsi/wd7000.c
drivers/scsi/wd719x.c [new file with mode: 0644]
drivers/scsi/wd719x.h [new file with mode: 0644]
drivers/soc/ti/knav_qmss.h
drivers/soc/ti/knav_qmss_queue.c
drivers/soc/versatile/Kconfig
drivers/soc/versatile/Makefile
drivers/soc/versatile/soc-integrator.c [new file with mode: 0644]
drivers/soc/versatile/soc-realview.c
drivers/spi/spi-dw.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-orion.c
drivers/spi/spi-pl022.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rockchip.c
drivers/spi/spi-sirf.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/staging/android/logger.c
drivers/staging/comedi/Kconfig
drivers/staging/comedi/comedi_fops.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/impedance-analyzer/ad5933.c
drivers/staging/iio/light/isl29028.c
drivers/staging/iio/meter/ade7758.h
drivers/staging/iio/meter/ade7758_core.c
drivers/staging/iio/meter/ade7758_ring.c
drivers/staging/rtl8188eu/core/rtw_cmd.c
drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
drivers/staging/rtl8188eu/core/rtw_wlan_util.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8723au/include/rtw_eeprom.h
drivers/target/Kconfig
drivers/target/Makefile
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/loopback/tcm_loop.c
drivers/target/target_core_alua.c
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_fabric_lib.c
drivers/target/target_core_file.c
drivers/target/target_core_internal.h
drivers/target/target_core_pr.c
drivers/target/target_core_pr.h
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_tmr.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/target_core_ua.c
drivers/target/target_core_ua.h
drivers/target/target_core_user.c [new file with mode: 0644]
drivers/target/tcm_fc/tfc_sess.c
drivers/thermal/Kconfig
drivers/thermal/Makefile
drivers/thermal/cpu_cooling.c
drivers/thermal/fair_share.c
drivers/thermal/gov_bang_bang.c [new file with mode: 0644]
drivers/thermal/imx_thermal.c
drivers/thermal/int3403_thermal.c [deleted file]
drivers/thermal/int340x_thermal/Makefile [new file with mode: 0644]
drivers/thermal/int340x_thermal/acpi_thermal_rel.c [new file with mode: 0644]
drivers/thermal/int340x_thermal/acpi_thermal_rel.h [new file with mode: 0644]
drivers/thermal/int340x_thermal/int3400_thermal.c [new file with mode: 0644]
drivers/thermal/int340x_thermal/int3402_thermal.c [new file with mode: 0644]
drivers/thermal/int340x_thermal/int3403_thermal.c [new file with mode: 0644]
drivers/thermal/of-thermal.c
drivers/thermal/samsung/exynos_thermal_common.c
drivers/thermal/samsung/exynos_thermal_common.h
drivers/thermal/samsung/exynos_tmu.c
drivers/thermal/samsung/exynos_tmu.h
drivers/thermal/samsung/exynos_tmu_data.c
drivers/thermal/samsung/exynos_tmu_data.h
drivers/thermal/st/st_thermal.c
drivers/thermal/step_wise.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_mtk.c
drivers/tty/serial/Kconfig
drivers/tty/serial/of_serial.c
drivers/tty/serial/serial_core.c
drivers/tty/tty_io.c
drivers/tty/vt/consolemap.c
drivers/uio/uio.c
drivers/usb/chipidea/core.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/gadget.h
drivers/usb/dwc3/trace.h
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_acm.c
drivers/usb/gadget/function/f_eem.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/function/f_loopback.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/gadget/function/f_obex.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/gadget/function/f_rndis.c
drivers/usb/gadget/function/f_subset.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/f_uvc.c
drivers/usb/gadget/function/uvc_video.c
drivers/usb/gadget/legacy/tcm_usb_gadget.c
drivers/usb/gadget/udc/Kconfig
drivers/usb/gadget/udc/udc-core.c
drivers/usb/host/Kconfig
drivers/usb/host/hwa-hc.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_dsps.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/keyspan.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/ssu100.c
drivers/usb/storage/debug.c
drivers/usb/storage/initializers.c
drivers/usb/storage/realtek_cr.c
drivers/usb/storage/transport.c
drivers/usb/storage/uas.c
drivers/usb/storage/unusual_uas.h
drivers/vhost/scsi.c
drivers/video/backlight/Kconfig
drivers/video/console/fbcon.c
drivers/video/console/vgacon.c
drivers/video/fbdev/Kconfig
drivers/video/fbdev/atmel_lcdfb.c
drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c
drivers/video/fbdev/omap2/displays-new/connector-dvi.c
drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
drivers/video/fbdev/omap2/displays-new/panel-dpi.c
drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c
drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
drivers/video/fbdev/omap2/dss/apply.c
drivers/video/fbdev/omap2/dss/dispc.c
drivers/video/fbdev/omap2/dss/dispc.h
drivers/video/fbdev/omap2/dss/dpi.c
drivers/video/fbdev/omap2/dss/dsi.c
drivers/video/fbdev/omap2/dss/dss.c
drivers/video/fbdev/omap2/dss/hdmi4.c
drivers/video/fbdev/omap2/dss/hdmi5.c
drivers/video/fbdev/omap2/dss/hdmi_pll.c
drivers/video/fbdev/omap2/dss/rfbi.c
drivers/video/fbdev/omap2/dss/sdi.c
drivers/video/fbdev/omap2/dss/venc.c
drivers/video/fbdev/omap2/omapfb/omapfb-main.c
drivers/w1/masters/omap_hdq.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/booke_wdt.c
drivers/watchdog/cadence_wdt.c [new file with mode: 0644]
drivers/watchdog/da9063_wdt.c [new file with mode: 0644]
drivers/watchdog/dw_wdt.c
drivers/watchdog/imx2_wdt.c
drivers/watchdog/meson_wdt.c [new file with mode: 0644]
drivers/watchdog/of_xilinx_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/qcom-wdt.c [new file with mode: 0644]
drivers/watchdog/rn5t618_wdt.c [new file with mode: 0644]
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/stmp3xxx_rtc_wdt.c
drivers/watchdog/sunxi_wdt.c
drivers/watchdog/ts72xx_wdt.c
drivers/xen/balloon.c
drivers/xen/efi.c
drivers/xen/pci.c
drivers/xen/xen-scsiback.c
fs/Kconfig
fs/Makefile
fs/aio.c
fs/block_dev.c
fs/btrfs/compression.c
fs/btrfs/compression.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file-item.c
fs/btrfs/ioctl.c
fs/btrfs/locking.c
fs/btrfs/locking.h
fs/btrfs/lzo.c
fs/btrfs/super.c
fs/btrfs/tree-log.c
fs/btrfs/zlib.c
fs/buffer.c
fs/ceph/caps.c
fs/dcache.c
fs/ecryptfs/main.c
fs/exofs/Kbuild
fs/exofs/common.h
fs/exofs/dir.c
fs/exofs/exofs.h
fs/exofs/file.c
fs/exofs/inode.c
fs/exofs/namei.c
fs/exofs/ore.c
fs/exofs/ore_raid.c
fs/exofs/ore_raid.h
fs/exofs/super.c
fs/exofs/symlink.c
fs/exofs/sys.c
fs/ext3/super.c
fs/ext4/balloc.c
fs/ext4/bitmap.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/ext4_extents.h
fs/ext4/ext4_jbd2.c
fs/ext4/ext4_jbd2.h
fs/ext4/extents.c
fs/ext4/extents_status.c
fs/ext4/extents_status.h
fs/ext4/file.c
fs/ext4/ialloc.c
fs/ext4/indirect.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/mmp.c
fs/ext4/move_extent.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/fat/namei_vfat.c
fs/internal.h
fs/isofs/inode.c
fs/isofs/namei.c
fs/jbd/journal.c
fs/jbd/revoke.c
fs/jbd2/checkpoint.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/revoke.c
fs/namei.c
fs/namespace.c
fs/nfs/blocklayout/blocklayout.c
fs/nfs/blocklayout/rpc_pipefs.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/filelayout/filelayout.c
fs/nfs/inode.c
fs/nfs/netns.h
fs/nfs/nfs4proc.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/objlayout/objlayout.c
fs/nfs/objlayout/objlayout.h
fs/nfs/objlayout/pnfs_osd_xdr_cli.c
fs/nfs/write.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfsd.h
fs/notify/fsnotify.c
fs/notify/fsnotify.h
fs/notify/inode_mark.c
fs/notify/inotify/inotify_user.c
fs/notify/mark.c
fs/notify/vfsmount_mark.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/namei.c
fs/open.c
fs/overlayfs/Kconfig [new file with mode: 0644]
fs/overlayfs/Makefile [new file with mode: 0644]
fs/overlayfs/copy_up.c [new file with mode: 0644]
fs/overlayfs/dir.c [new file with mode: 0644]
fs/overlayfs/inode.c [new file with mode: 0644]
fs/overlayfs/overlayfs.h [new file with mode: 0644]
fs/overlayfs/readdir.c [new file with mode: 0644]
fs/overlayfs/super.c [new file with mode: 0644]
fs/quota/dquot.c
fs/splice.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_itable.h
include/acpi/acnames.h
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/asm-generic/futex.h
include/asm-generic/io.h
include/asm-generic/preempt.h
include/asm-generic/seccomp.h [new file with mode: 0644]
include/asm-generic/tlb.h
include/drm/drm_pciids.h
include/dt-bindings/arm/ux500_pm_domains.h [new file with mode: 0644]
include/dt-bindings/clock/imx5-clock.h
include/dt-bindings/clock/imx6qdl-clock.h
include/dt-bindings/clock/qcom,mmcc-apq8084.h
include/dt-bindings/clock/r8a7740-clock.h
include/dt-bindings/clock/r8a7790-clock.h
include/dt-bindings/clock/r8a7791-clock.h
include/dt-bindings/clock/r8a7794-clock.h
include/dt-bindings/clock/stih407-clks.h [new file with mode: 0644]
include/dt-bindings/clock/stih410-clks.h [new file with mode: 0644]
include/dt-bindings/clock/tegra114-car.h
include/dt-bindings/clock/tegra124-car.h
include/dt-bindings/clock/tegra20-car.h
include/dt-bindings/clock/vf610-clock.h
include/dt-bindings/memory/tegra114-mc.h [new file with mode: 0644]
include/dt-bindings/memory/tegra124-mc.h [new file with mode: 0644]
include/dt-bindings/memory/tegra30-mc.h [new file with mode: 0644]
include/dt-bindings/pinctrl/dra.h
include/dt-bindings/regulator/maxim,max77802.h [new file with mode: 0644]
include/dt-bindings/reset-controller/stih407-resets.h [new file with mode: 0644]
include/linux/acpi.h
include/linux/atmel-mci.h
include/linux/audit.h
include/linux/bitops.h
include/linux/blk-mq.h
include/linux/blkdev.h
include/linux/bootmem.h
include/linux/buffer_head.h
include/linux/can/dev.h
include/linux/clk-provider.h
include/linux/clk/ti.h
include/linux/clocksource.h
include/linux/cma.h
include/linux/compiler-gcc4.h
include/linux/compiler-gcc5.h
include/linux/cpufreq-dt.h [new file with mode: 0644]
include/linux/cpufreq.h
include/linux/crash_dump.h
include/linux/device-mapper.h
include/linux/edac.h
include/linux/eeprom_93cx6.h
include/linux/efi.h
include/linux/freezer.h
include/linux/fs.h
include/linux/i2c/pmbus.h
include/linux/iio/events.h
include/linux/inetdevice.h
include/linux/init_task.h
include/linux/iommu.h
include/linux/jbd2.h
include/linux/kernel.h
include/linux/kernel_stat.h
include/linux/kgdb.h
include/linux/khugepaged.h
include/linux/kvm_host.h
include/linux/leds.h
include/linux/libata.h
include/linux/mailbox.h [deleted file]
include/linux/mailbox_client.h [new file with mode: 0644]
include/linux/mailbox_controller.h [new file with mode: 0644]
include/linux/mbus.h
include/linux/memcontrol.h
include/linux/memory.h
include/linux/mfd/abx500/ab8500-sysctrl.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/atmel-hlcdc.h [new file with mode: 0644]
include/linux/mfd/axp20x.h
include/linux/mfd/core.h
include/linux/mfd/dln2.h [new file with mode: 0644]
include/linux/mfd/max77686.h
include/linux/mfd/max77693-private.h
include/linux/mfd/rtsx_pci.h
include/linux/mfd/samsung/core.h
include/linux/mfd/samsung/s2mps13.h [new file with mode: 0644]
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
include/linux/mfd/tc3589x.h
include/linux/mm.h
include/linux/mmc/card.h
include/linux/mmc/core.h
include/linux/mmc/dw_mmc.h
include/linux/mmc/host.h
include/linux/mmc/mmc.h
include/linux/mmc/sdhci.h
include/linux/mmc/sdio_func.h
include/linux/mmzone.h
include/linux/mount.h
include/linux/mtd/spi-nor.h
include/linux/nfs_xdr.h
include/linux/of.h
include/linux/of_reserved_mem.h
include/linux/omap-gpmc.h [new file with mode: 0644]
include/linux/oom.h
include/linux/page-isolation.h
include/linux/pci-acpi.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/percpu-refcount.h
include/linux/perf_event.h
include/linux/pl320-ipc.h [new file with mode: 0644]
include/linux/platform_data/hsmmc-omap.h [new file with mode: 0644]
include/linux/platform_data/mmc-atmel-mci.h [new file with mode: 0644]
include/linux/platform_data/mmc-omap.h
include/linux/platform_data/pxa_sdhci.h
include/linux/platform_data/serial-omap.h
include/linux/pm_domain.h
include/linux/pm_qos.h
include/linux/pnfs_osd_xdr.h
include/linux/power/charger-manager.h
include/linux/power_supply.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/regmap.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/of_regulator.h
include/linux/reset-controller.h
include/linux/reset.h
include/linux/ring_buffer.h
include/linux/rtc.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/string.h
include/linux/thermal.h
include/linux/time.h
include/linux/timekeeping.h
include/linux/uio_driver.h
include/linux/uprobes.h
include/linux/usb/usbnet.h
include/linux/vexpress.h
include/linux/wait.h
include/linux/watchdog.h
include/net/9p/transport.h
include/net/inet_common.h
include/net/ipv6.h
include/net/netfilter/ipv4/nf_reject.h
include/net/netfilter/ipv6/nf_reject.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nft_masq.h
include/net/sock.h
include/net/udp_tunnel.h
include/net/vxlan.h
include/scsi/libfc.h
include/scsi/libiscsi.h
include/scsi/libsas.h
include/scsi/osd_initiator.h
include/scsi/osd_ore.h
include/scsi/osd_protocol.h
include/scsi/osd_sec.h
include/scsi/osd_sense.h
include/scsi/osd_types.h
include/scsi/scsi.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_dbg.h
include/scsi/scsi_device.h
include/scsi/scsi_driver.h
include/scsi/scsi_eh.h
include/scsi/scsi_host.h
include/scsi/scsi_ioctl.h
include/scsi/scsi_tcq.h
include/scsi/scsi_transport_spi.h
include/scsi/sg.h
include/soc/at91/at91rm9200_sdramc.h [new file with mode: 0644]
include/soc/at91/at91sam9_ddrsdr.h [new file with mode: 0644]
include/soc/at91/at91sam9_sdramc.h [new file with mode: 0644]
include/soc/tegra/mc.h [new file with mode: 0644]
include/sound/pcm.h
include/sound/soc-dpcm.h
include/target/target_core_base.h
include/trace/events/ext4.h
include/trace/events/rcu.h
include/trace/events/sched.h
include/trace/events/scsi.h
include/trace/events/target.h
include/trace/events/thermal.h [new file with mode: 0644]
include/uapi/linux/Kbuild
include/uapi/linux/dm-ioctl.h
include/uapi/linux/elf-em.h
include/uapi/linux/elf.h
include/uapi/linux/fs.h
include/uapi/linux/if_bridge.h
include/uapi/linux/input.h
include/uapi/linux/perf_event.h
include/uapi/linux/sched.h
include/uapi/linux/target_core_user.h [new file with mode: 0644]
include/uapi/linux/v4l2-dv-timings.h
include/uapi/sound/asound.h
init/Kconfig
init/main.c
ipc/sem.c
kernel/Makefile
kernel/audit.c
kernel/audit_tree.c
kernel/bpf/Makefile
kernel/bpf/core.c
kernel/bpf/verifier.c
kernel/context_tracking.c
kernel/cpu.c
kernel/cpuset.c
kernel/events/core.c
kernel/events/hw_breakpoint.c
kernel/events/uprobes.c
kernel/exit.c
kernel/fork.c
kernel/freezer.c
kernel/futex.c
kernel/gcov/Kconfig
kernel/kmod.c
kernel/locking/mutex.c
kernel/module.c
kernel/panic.c
kernel/power/hibernate.c
kernel/power/process.c
kernel/power/qos.c
kernel/power/suspend.c
kernel/rcu/Makefile
kernel/rcu/rcu.h
kernel/rcu/rcutorture.c
kernel/rcu/tiny.c
kernel/rcu/tree.c
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
kernel/rcu/update.c
kernel/sched/completion.c
kernel/sched/core.c
kernel/sched/cpudeadline.h
kernel/sched/cpupri.h
kernel/sched/deadline.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/idle_task.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/sched/stop_task.c
kernel/sched/wait.c
kernel/signal.c
kernel/smpboot.c
kernel/softirq.c
kernel/sysctl.c
kernel/time/Makefile
kernel/time/clockevents.c
kernel/time/posix-cpu-timers.c
kernel/time/posix-timers.c
kernel/time/test_udelay.c [new file with mode: 0644]
kernel/time/tick-sched.c
kernel/time/time.c
kernel/time/timekeeping.c
kernel/time/timer.c
kernel/time/udelay_test.c [deleted file]
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_syscalls.c
lib/Kconfig.debug
lib/Makefile
lib/bitmap.c
lib/cmdline.c
lib/genalloc.c
lib/rhashtable.c
lib/scatterlist.c
lib/show_mem.c
lib/string.c
mm/balloon_compaction.c
mm/bootmem.c
mm/cma.c
mm/compaction.c
mm/frontswap.c
mm/huge_memory.c
mm/internal.h
mm/iov_iter.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mmap.c
mm/nobootmem.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_cgroup.c
mm/page_isolation.c
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/slab_common.c
mm/truncate.c
mm/vmpressure.c
net/Kconfig
net/bluetooth/rfcomm/core.c
net/bridge/br_forward.c
net/bridge/br_multicast.c
net/bridge/br_netfilter.c
net/bridge/br_netlink.c
net/bridge/netfilter/nf_tables_bridge.c
net/bridge/netfilter/nft_reject_bridge.c
net/ceph/auth_x.c
net/ceph/crypto.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/dev.c
net/core/ethtool.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/tso.c
net/dcb/dcbnl.c
net/dsa/dsa.c
net/dsa/slave.c
net/ipv4/af_inet.c
net/ipv4/fib_rules.c
net/ipv4/fou.c
net/ipv4/geneve.c
net/ipv4/gre_offload.c
net/ipv4/igmp.c
net/ipv4/inet_fragment.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_vti.c
net/ipv4/netfilter/nf_reject_ipv4.c
net/ipv4/netfilter/nft_masq_ipv4.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_output.c
net/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_udp_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ip6mr.c
net/ipv6/mcast.c
net/ipv6/netfilter/nf_reject_ipv6.c
net/ipv6/netfilter/nft_masq_ipv6.c
net/ipv6/output_core.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/ipv6/xfrm6_policy.c
net/ipx/af_ipx.c
net/irda/af_irda.c
net/mac80211/aes_ccm.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/rate.c
net/mac80211/rc80211_minstrel_debugfs.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rc80211_minstrel_ht_debugfs.c
net/mac80211/rx.c
net/mac80211/spectmgmt.c
net/mac80211/sta_info.h
net/mpls/Makefile
net/mpls/mpls_gso.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/nft_compat.c
net/netfilter/nft_masq.c
net/netfilter/nft_nat.c
net/netlink/af_netlink.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow_netlink.c
net/packet/af_packet.c
net/sched/sch_api.c
net/sched/sch_pie.c
net/sctp/auth.c
net/sctp/sm_make_chunk.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/svcsock.c
net/tipc/node.c
net/tipc/node.h
net/tipc/socket.c
net/wireless/nl80211.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
samples/bpf/test_verifier.c
scripts/Kbuild.include
scripts/Makefile.dtbinst [new file with mode: 0644]
scripts/Makefile.lib
security/integrity/evm/evm_main.c
security/integrity/ima/ima_appraise.c
security/integrity/integrity.h
security/keys/internal.h
security/keys/keyctl.c
security/keys/keyring.c
security/keys/request_key.c
security/keys/request_key_auth.c
security/selinux/hooks.c
sound/core/pcm.c
sound/core/pcm_compat.c
sound/core/pcm_misc.c
sound/core/pcm_native.c
sound/firewire/bebob/bebob_focusrite.c
sound/firewire/bebob/bebob_stream.c
sound/firewire/bebob/bebob_terratec.c
sound/pci/ad1889.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/hda_priv.h
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/codecs/adau1761.c
sound/soc/codecs/cs42l51-i2c.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/cs42l51.h
sound/soc/codecs/es8328-i2c.c
sound/soc/codecs/max98090.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5670.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/sgtl5000.h
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/fsl_asrc.c
sound/soc/fsl/fsl_esai.c
sound/soc/intel/sst-haswell-pcm.c
sound/soc/rockchip/rockchip_i2s.c
sound/soc/s6000/Kconfig [deleted file]
sound/soc/s6000/Makefile [deleted file]
sound/soc/s6000/s6000-i2s.c [deleted file]
sound/soc/s6000/s6000-i2s.h [deleted file]
sound/soc/s6000/s6000-pcm.c [deleted file]
sound/soc/s6000/s6000-pcm.h [deleted file]
sound/soc/s6000/s6105-ipcam.c [deleted file]
sound/soc/samsung/snow.c
sound/soc/sh/fsi.c
sound/soc/sh/rcar/core.c
sound/soc/soc-core.c
sound/soc/soc-pcm.c
sound/usb/card.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/quirks-table.h
sound/usb/quirks.c
tools/lib/traceevent/plugin_scsi.c
tools/perf/.gitignore
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Makefile.perf
tools/perf/arch/powerpc/util/skip-callchain-idx.c
tools/perf/builtin-diff.c
tools/perf/builtin-inject.c
tools/perf/builtin-kvm.c
tools/perf/builtin-probe.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-timechart.c
tools/perf/builtin-trace.c
tools/perf/config/Makefile
tools/perf/config/Makefile.arch
tools/perf/config/feature-checks/Makefile
tools/perf/config/feature-checks/test-all.c
tools/perf/config/feature-checks/test-compile.c [new file with mode: 0644]
tools/perf/config/feature-checks/test-zlib.c [new file with mode: 0644]
tools/perf/perf-read-vdso.c [new file with mode: 0644]
tools/perf/perf-sys.h
tools/perf/perf.h
tools/perf/scripts/python/bin/export-to-postgresql-record [new file with mode: 0644]
tools/perf/scripts/python/bin/export-to-postgresql-report [new file with mode: 0644]
tools/perf/scripts/python/export-to-postgresql.py [new file with mode: 0644]
tools/perf/tests/builtin-test.c
tools/perf/tests/code-reading.c
tools/perf/tests/dwarf-unwind.c
tools/perf/tests/hists_filter.c
tools/perf/tests/mmap-thread-lookup.c
tools/perf/tests/sample-parsing.c
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/hists.c
tools/perf/ui/stdio/hist.c
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/build-id.c
tools/perf/util/build-id.h
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/comm.h
tools/perf/util/db-export.c [new file with mode: 0644]
tools/perf/util/db-export.h [new file with mode: 0644]
tools/perf/util/debug.c
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/find-vdso-map.c [new file with mode: 0644]
tools/perf/util/header.c
tools/perf/util/header.h
tools/perf/util/include/linux/bitmap.h
tools/perf/util/include/linux/bitops.h
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/parse-events.c
tools/perf/util/parse-options.c
tools/perf/util/parse-options.h
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/probe-event.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/sort.c
tools/perf/util/srcline.c
tools/perf/util/symbol-elf.c
tools/perf/util/symbol-minimal.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/thread-stack.c [new file with mode: 0644]
tools/perf/util/thread-stack.h [new file with mode: 0644]
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/tool.h
tools/perf/util/unwind-libdw.c
tools/perf/util/unwind-libunwind.c
tools/perf/util/unwind.h
tools/perf/util/util.h
tools/perf/util/vdso.c
tools/perf/util/vdso.h
tools/perf/util/zlib.c [new file with mode: 0644]
tools/power/acpi/os_specific/service_layers/osunixxf.c
tools/power/acpi/tools/acpidump/apdump.c
tools/testing/selftests/ftrace/ftracetest
tools/testing/selftests/net/psock_fanout.c
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
tools/testing/selftests/rcutorture/bin/kvm.sh
tools/testing/selftests/rcutorture/configs/rcu/TINY02
tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE01
tools/testing/selftests/rcutorture/configs/rcu/TREE02
tools/testing/selftests/rcutorture/configs/rcu/TREE02-T
tools/testing/selftests/rcutorture/configs/rcu/TREE03
tools/testing/selftests/rcutorture/configs/rcu/TREE04
tools/testing/selftests/rcutorture/configs/rcu/TREE05
tools/testing/selftests/rcutorture/configs/rcu/TREE05.boot
tools/testing/selftests/rcutorture/configs/rcu/TREE06
tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE07
tools/testing/selftests/rcutorture/configs/rcu/TREE08
tools/testing/selftests/rcutorture/configs/rcu/TREE08-T
tools/testing/selftests/rcutorture/configs/rcu/TREE08.boot
tools/testing/selftests/rcutorture/configs/rcu/TREE09
tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH [deleted file]
tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh [deleted file]
tools/testing/selftests/rcutorture/doc/TINY_RCU.txt
tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
virt/kvm/arm/vgic.c
virt/kvm/iommu.c
virt/kvm/kvm_main.c
virt/kvm/vfio.c
virt/kvm/vfio.h

index b9688de8455bb1577ef923af907bcbf86da0f0e4..7049a2b5035950f3d08dc9e8595a7d40e73036e6 100644 (file)
@@ -55,12 +55,12 @@ Description:        Interface for making ib_srp connect to a new target.
                  only safe with partial memory descriptor list support enabled
                  (allow_ext_sg=1).
                * comp_vector, a number in the range 0..n-1 specifying the
-                 MSI-X completion vector. Some HCA's allocate multiple (n)
-                 MSI-X vectors per HCA port. If the IRQ affinity masks of
-                 these interrupts have been configured such that each MSI-X
-                 interrupt is handled by a different CPU then the comp_vector
-                 parameter can be used to spread the SRP completion workload
-                 over multiple CPU's.
+                 MSI-X completion vector of the first RDMA channel. Some
+                 HCA's allocate multiple (n) MSI-X vectors per HCA port. If
+                 the IRQ affinity masks of these interrupts have been
+                 configured such that each MSI-X interrupt is handled by a
+                 different CPU then the comp_vector parameter can be used to
+                 spread the SRP completion workload over multiple CPU's.
                * tl_retry_count, a number in the range 2..7 specifying the
                  IB RC retry count.
                * queue_size, the maximum number of commands that the
@@ -88,6 +88,13 @@ Description: Whether ib_srp is allowed to include a partial memory
                descriptor list in an SRP_CMD when communicating with an SRP
                target.
 
+What:          /sys/class/scsi_host/host<n>/ch_count
+Date:          April 1, 2015
+KernelVersion: 3.19
+Contact:       linux-rdma@vger.kernel.org
+Description:   Number of RDMA channels used for communication with the SRP
+               target.
+
 What:          /sys/class/scsi_host/host<n>/cmd_sg_entries
 Date:          May 19, 2011
 KernelVersion: 2.6.39
@@ -95,6 +102,12 @@ Contact:    linux-rdma@vger.kernel.org
 Description:   Maximum number of data buffer descriptors that may be sent to
                the target in a single SRP_CMD request.
 
+What:          /sys/class/scsi_host/host<n>/comp_vector
+Date:          September 2, 2013
+KernelVersion: 3.11
+Contact:       linux-rdma@vger.kernel.org
+Description:   Completion vector used for the first RDMA channel.
+
 What:          /sys/class/scsi_host/host<n>/dgid
 Date:          June 17, 2006
 KernelVersion: 2.6.17
index c2b7d1154bec62559790d619320eb5f75cbc4645..cac3930bdb04d991a64e4925dc2657ad55c2fbd6 100644 (file)
@@ -20,4 +20,4 @@ Date:         November 2007
 Contact:       Konrad Rzeszutek <ketuzsezr@darnok.org>
 Description:   The /sys/firmware/ibft/ethernetX directory will contain
                files that expose the iSCSI Boot Firmware Table NIC data.
-               This can this can the IP address, MAC, and gateway of the NIC.
+               Usually this contains the IP address, MAC, and gateway of the NIC.
index df2962d9e11e1f79e84779557c68bc73ea0f1670..8bf7c6191296f6790bd98836711e73d34deddb9a 100644 (file)
@@ -25,7 +25,7 @@ GENFILES := $(addprefix $(MEDIA_OBJ_DIR)/, $(MEDIA_TEMP))
 PHONY += cleanmediadocs
 
 cleanmediadocs:
-       -@rm `find $(MEDIA_OBJ_DIR) -type l` $(GENFILES) $(OBJIMGFILES) 2>/dev/null
+       -@rm -f `find $(MEDIA_OBJ_DIR) -type l` $(GENFILES) $(OBJIMGFILES) 2>/dev/null
 
 $(obj)/media_api.xml: $(GENFILES) FORCE
 
index 07ffc76553ba098490cbba874f6f513f8981222e..0a2debfa68f616fa0aa15afc53687edfe1484263 100644 (file)
@@ -2566,6 +2566,10 @@ fields changed from _s32 to _u32.
          <para>Added compound control types and &VIDIOC-QUERY-EXT-CTRL;.
          </para>
         </listitem>
+      </orderedlist>
+    </section>
+
+    <section>
       <title>V4L2 in Linux 3.18</title>
       <orderedlist>
        <listitem>
index 57cf5efb044da7f3c29586466455eaa1b55a77ae..93aa8604630e769dd531fe8856c59d6d7390e6cc 100644 (file)
@@ -324,7 +324,6 @@ tree, they need to be integration-tested.  For this purpose, a special
 testing repository exists into which virtually all subsystem trees are
 pulled on an almost daily basis:
        http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
-       http://linux.f-seidel.de/linux-next/pmwiki/
 
 This way, the -next kernel gives a summary outlook onto what will be
 expected to go into the mainline kernel at the next merge period.
index bf778332a28f8e8332bcdde2a32772c555e83498..745f429fda7938f499fce4388309c39bf6bfeef6 100644 (file)
@@ -36,7 +36,7 @@ o     How can the updater tell when a grace period has completed
        executed in user mode, or executed in the idle loop, we can
        safely free up that item.
 
-       Preemptible variants of RCU (CONFIG_TREE_PREEMPT_RCU) get the
+       Preemptible variants of RCU (CONFIG_PREEMPT_RCU) get the
        same effect, but require that the readers manipulate CPU-local
        counters.  These counters allow limited types of blocking within
        RCU read-side critical sections.  SRCU also uses CPU-local
@@ -81,7 +81,7 @@ o     I hear that RCU is patented?  What is with that?
 o      I hear that RCU needs work in order to support realtime kernels?
 
        This work is largely completed.  Realtime-friendly RCU can be
-       enabled via the CONFIG_TREE_PREEMPT_RCU kernel configuration
+       enabled via the CONFIG_PREEMPT_RCU kernel configuration
        parameter.  However, work is in progress for enabling priority
        boosting of preempted RCU read-side critical sections.  This is
        needed if you have CPU-bound realtime threads.
index ef5a2fd4ff70dabe66f8688d3bdca27d179429b6..ed186a902d312a23913bb3e4ba0f272306fd1cb3 100644 (file)
@@ -26,12 +26,6 @@ CONFIG_RCU_CPU_STALL_TIMEOUT
        Stall-warning messages may be enabled and disabled completely via
        /sys/module/rcupdate/parameters/rcu_cpu_stall_suppress.
 
-CONFIG_RCU_CPU_STALL_VERBOSE
-
-       This kernel configuration parameter causes the stall warning to
-       also dump the stacks of any tasks that are blocking the current
-       RCU-preempt grace period.
-
 CONFIG_RCU_CPU_STALL_INFO
 
        This kernel configuration parameter causes the stall warning to
@@ -77,7 +71,7 @@ This message indicates that CPU 5 detected that it was causing a stall,
 and that the stall was affecting RCU-sched.  This message will normally be
 followed by a stack dump of the offending CPU.  On TREE_RCU kernel builds,
 RCU and RCU-sched are implemented by the same underlying mechanism,
-while on TREE_PREEMPT_RCU kernel builds, RCU is instead implemented
+while on PREEMPT_RCU kernel builds, RCU is instead implemented
 by rcu_preempt_state.
 
 On the other hand, if the offending CPU fails to print out a stall-warning
@@ -89,7 +83,7 @@ INFO: rcu_bh_state detected stalls on CPUs/tasks: { 3 5 } (detected by 2, 2502 j
 This message indicates that CPU 2 detected that CPUs 3 and 5 were both
 causing stalls, and that the stall was affecting RCU-bh.  This message
 will normally be followed by stack dumps for each CPU.  Please note that
-TREE_PREEMPT_RCU builds can be stalled by tasks as well as by CPUs,
+PREEMPT_RCU builds can be stalled by tasks as well as by CPUs,
 and that the tasks will be indicated by PID, for example, "P3421".
 It is even possible for a rcu_preempt_state stall to be caused by both
 CPUs -and- tasks, in which case the offending CPUs and tasks will all
@@ -205,10 +199,10 @@ o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
 o      A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
        is running at a higher priority than the RCU softirq threads.
        This will prevent RCU callbacks from ever being invoked,
-       and in a CONFIG_TREE_PREEMPT_RCU kernel will further prevent
+       and in a CONFIG_PREEMPT_RCU kernel will further prevent
        RCU grace periods from ever completing.  Either way, the
        system will eventually run out of memory and hang.  In the
-       CONFIG_TREE_PREEMPT_RCU case, you might see stall-warning
+       CONFIG_PREEMPT_RCU case, you might see stall-warning
        messages.
 
 o      A hardware or software issue shuts off the scheduler-clock
index 910870b15acd25d1b548001759f11e589cd671eb..b63b9bb3bc0c4dc24064599055f976ac00e0ee85 100644 (file)
@@ -8,7 +8,7 @@ The following sections describe the debugfs files and formats, first
 for rcutree and next for rcutiny.
 
 
-CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats
+CONFIG_TREE_RCU and CONFIG_PREEMPT_RCU debugfs Files and Formats
 
 These implementations of RCU provide several debugfs directories under the
 top-level directory "rcu":
@@ -18,7 +18,7 @@ rcu/rcu_preempt
 rcu/rcu_sched
 
 Each directory contains files for the corresponding flavor of RCU.
-Note that rcu/rcu_preempt is only present for CONFIG_TREE_PREEMPT_RCU.
+Note that rcu/rcu_preempt is only present for CONFIG_PREEMPT_RCU.
 For CONFIG_TREE_RCU, the RCU flavor maps onto the RCU-sched flavor,
 so that activity for both appears in rcu/rcu_sched.
 
index e48c57f1943bab162530416afb35f3acdff1729d..88dfce182f660904a609aa97e670a4ce87659985 100644 (file)
@@ -137,7 +137,7 @@ rcu_read_lock()
        Used by a reader to inform the reclaimer that the reader is
        entering an RCU read-side critical section.  It is illegal
        to block while in an RCU read-side critical section, though
-       kernels built with CONFIG_TREE_PREEMPT_RCU can preempt RCU
+       kernels built with CONFIG_PREEMPT_RCU can preempt RCU
        read-side critical sections.  Any RCU-protected data structure
        accessed during an RCU read-side critical section is guaranteed to
        remain unreclaimed for the full duration of that critical section.
index 482c74947de02939eebfca089a344373707bf69d..1fa1caa198eb2e46be93b8f957c0c3513ed45988 100644 (file)
@@ -483,12 +483,10 @@ have been included in the discussion
 
 14) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes:
 
-If this patch fixes a problem reported by somebody else, consider adding a
-Reported-by: tag to credit the reporter for their contribution.  Please
-note that this tag should not be added without the reporter's permission,
-especially if the problem was not reported in a public forum.  That said,
-if we diligently credit our bug reporters, they will, hopefully, be
-inspired to help us again in the future.
+The Reported-by tag gives credit to people who find bugs and report them and it
+hopefully inspires them to help us again in the future.  Please note that if
+the bug was reported in private, then ask for permission first before using the
+Reported-by tag.
 
 A Tested-by: tag indicates that the patch has been successfully tested (in
 some environment) by the person named.  This tag informs maintainers that
index c2e468fe7b0be00979562b9c3f0d371a24d8cb67..da6713adac8acffc5924d447473351ab84c2d289 100644 (file)
@@ -7,32 +7,14 @@ world, which changes the way some things have to be initialized. This makes
 a need to provide an interface for such platforms to specify available firmware
 operations and call them when needed.
 
-Firmware operations can be specified using struct firmware_ops
-
-       struct firmware_ops {
-               /*
-               * Enters CPU idle mode
-               */
-               int (*do_idle)(void);
-               /*
-               * Sets boot address of specified physical CPU
-               */
-               int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr);
-               /*
-               * Boots specified physical CPU
-               */
-               int (*cpu_boot)(int cpu);
-               /*
-               * Initializes L2 cache
-               */
-               int (*l2x0_init)(void);
-       };
-
-and then registered with register_firmware_ops function
+Firmware operations can be specified by filling in a struct firmware_ops
+with appropriate callbacks and then registering it with register_firmware_ops()
+function.
 
        void register_firmware_ops(const struct firmware_ops *ops)
 
-the ops pointer must be non-NULL.
+The ops pointer must be non-NULL. More information about struct firmware_ops
+and its members can be found in arch/arm/include/asm/firmware.h header.
 
 There is a default, empty set of operations provided, so there is no need to
 set anything if platform does not require firmware operations.
index 7945238453edb58444f09938bc251150a2e4a0aa..e68d163df33dbcd7ea96a503528d047f5ac7855c 100644 (file)
@@ -37,16 +37,26 @@ SunXi family
           http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf
 
       - Allwinner A23
-        + Not Supported
+        + Datasheet
+          http://dl.linux-sunxi.org/A23/A23%20Datasheet%20V1.0%2020130830.pdf
+        + User Manual
+          http://dl.linux-sunxi.org/A23/A23%20User%20Manual%20V1.0%2020130830.pdf
 
     * Quad ARM Cortex-A7 based SoCs
       - Allwinner A31 (sun6i)
         + Datasheet
-          http://dl.linux-sunxi.org/A31/A31%20Datasheet%20-%20v1.00%20(2012-12-24).pdf
+          http://dl.linux-sunxi.org/A31/A3x_release_document/A31/IC/A31%20datasheet%20V1.3%2020131106.pdf
+        + User Manual
+          http://dl.linux-sunxi.org/A31/A3x_release_document/A31/IC/A31%20user%20manual%20V1.1%2020130630.pdf
 
       - Allwinner A31s (sun6i)
         + Not Supported
+        + Datasheet
+          http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20datasheet%20V1.3%2020131106.pdf
+        + User Manual
+          http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20User%20Manual%20%20V1.0%2020130322.pdf
 
     * Quad ARM Cortex-A15, Quad ARM Cortex-A7 based SoCs
       - Allwinner A80
-        + Not Supported
\ No newline at end of file
+        + Datasheet
+         http://dl.linux-sunxi.org/A80/A80_Datasheet_Revision_1.0_0404.pdf
diff --git a/Documentation/arm64/legacy_instructions.txt b/Documentation/arm64/legacy_instructions.txt
new file mode 100644 (file)
index 0000000..a3b3da2
--- /dev/null
@@ -0,0 +1,45 @@
+The arm64 port of the Linux kernel provides infrastructure to support
+emulation of instructions which have been deprecated, or obsoleted in
+the architecture. The infrastructure code uses undefined instruction
+hooks to support emulation. Where available it also allows turning on
+the instruction execution in hardware.
+
+The emulation mode can be controlled by writing to sysctl nodes
+(/proc/sys/abi). The following explains the different execution
+behaviours and the corresponding values of the sysctl nodes -
+
+* Undef
+  Value: 0
+  Generates undefined instruction abort. Default for instructions that
+  have been obsoleted in the architecture, e.g., SWP
+
+* Emulate
+  Value: 1
+  Uses software emulation. To aid migration of software, in this mode
+  usage of emulated instruction is traced as well as rate limited
+  warnings are issued. This is the default for deprecated
+  instructions, .e.g., CP15 barriers
+
+* Hardware Execution
+  Value: 2
+  Although marked as deprecated, some implementations may support the
+  enabling/disabling of hardware support for the execution of these
+  instructions. Using hardware execution generally provides better
+  performance, but at the loss of ability to gather runtime statistics
+  about the use of the deprecated instructions.
+
+The default mode depends on the status of the instruction in the
+architecture. Deprecated instructions should default to emulation
+while obsolete instructions must be undefined by default.
+
+Supported legacy instructions
+-----------------------------
+* SWP{B}
+Node: /proc/sys/abi/swp
+Status: Obsolete
+Default: Undef (0)
+
+* CP15 Barriers
+Node: /proc/sys/abi/cp15_barrier
+Status: Deprecated
+Default: Emulate (1)
index 344e85cc73239fedf081db50ed958a8f51f57e8e..d7273a5f64566f3acfe009231cab43c05fd1e9a5 100644 (file)
@@ -17,7 +17,7 @@ User addresses have bits 63:48 set to 0 while the kernel addresses have
 the same bits set to 1. TTBRx selection is given by bit 63 of the
 virtual address. The swapper_pg_dir contains only kernel (global)
 mappings while the user pgd contains only user (non-global) mappings.
-The swapper_pgd_dir address is written to TTBR1 and never written to
+The swapper_pg_dir address is written to TTBR1 and never written to
 TTBR0.
 
 
index 68542fe13b850e9afb473da8ada4220a019d7ee4..183e41bdcb69b5e05224cfe46dfaa427907482bf 100644 (file)
@@ -7,12 +7,13 @@
 maintainers on how to implement atomic counter, bitops, and spinlock
 interfaces properly.
 
-       The atomic_t type should be defined as a signed integer.
-Also, it should be made opaque such that any kind of cast to a normal
-C integer type will fail.  Something like the following should
-suffice:
+       The atomic_t type should be defined as a signed integer and
+the atomic_long_t type as a signed long integer.  Also, they should
+be made opaque such that any kind of cast to a normal C integer type
+will fail.  Something like the following should suffice:
 
        typedef struct { int counter; } atomic_t;
+       typedef struct { long counter; } atomic_long_t;
 
 Historically, counter has been declared volatile.  This is now discouraged.
 See Documentation/volatile-considered-harmful.txt for the complete rationale.
@@ -37,6 +38,9 @@ initializer is used before runtime.  If the initializer is used at runtime, a
 proper implicit or explicit read memory barrier is needed before reading the
 value with atomic_read from another thread.
 
+As with all of the atomic_ interfaces, replace the leading "atomic_"
+with "atomic_long_" to operate on atomic_long_t.
+
 The second interface can be used at runtime, as in:
 
        struct foo { atomic_t counter; };
index 2101e718670d0248110caa4320e51e83c715fad2..6b972b287795b73d84fa7a390d34aaec821163e1 100644 (file)
@@ -827,10 +827,6 @@ but in the event of any barrier requests in the tag queue we need to ensure
 that requests are restarted in the order they were queue. This may happen
 if the driver needs to use blk_queue_invalidate_tags().
 
-Tagging also defines a new request flag, REQ_QUEUED. This is set whenever
-a request is currently tagged. You should not use this flag directly,
-blk_rq_tagged(rq) is the portable way to do so.
-
 3.3 I/O Submission
 
 The routine submit_bio() is used to submit a single io. Higher level i/o
index 2e0617936e8f7f7624d0920be7ff3ae3d6217f68..c24e156a611842017eeae45ce267c821e28174e8 100644 (file)
@@ -289,10 +289,6 @@ lists when they are assembled; they can be downloaded from:
 
        http://www.kernel.org/pub/linux/kernel/next/
 
-Some information about linux-next has been gathered at:
-
-       http://linux.f-seidel.de/linux-next/pmwiki/
-
 Linux-next has become an integral part of the kernel development process;
 all patches merged during a given merge window should really have found
 their way into linux-next some time before the merge window opens.
index 1990ab4b4949663852863aea0f2ece0c6341807d..caef69022e9c2a11d77221f8386a7091ada26b0a 100644 (file)
@@ -22,10 +22,6 @@ Beyond that, a valuable resource for kernel developers is:
 
        http://kernelnewbies.org/
 
-Information about the linux-next tree gathers at:
-
-       http://linux.f-seidel.de/linux-next/pmwiki/
-
 And, of course, one should not forget http://kernel.org/, the definitive
 location for kernel release information.
 
index 66c2774c0c64c0e8bf3a9aadc2a6f1b8102b5a12..0d124a9718013be38c6ddbe404f15b9a251fa204 100644 (file)
@@ -47,20 +47,26 @@ Message and constructor argument pairs are:
        'discard_promote_adjustment <value>'
 
 The sequential threshold indicates the number of contiguous I/Os
-required before a stream is treated as sequential.  The random threshold
+required before a stream is treated as sequential.  Once a stream is
+considered sequential it will bypass the cache.  The random threshold
 is the number of intervening non-contiguous I/Os that must be seen
 before the stream is treated as random again.
 
 The sequential and random thresholds default to 512 and 4 respectively.
 
-Large, sequential ios are probably better left on the origin device
-since spindles tend to have good bandwidth. The io_tracker counts
-contiguous I/Os to try to spot when the io is in one of these sequential
-modes.
-
-Internally the mq policy maintains a promotion threshold variable.  If
-the hit count of a block not in the cache goes above this threshold it
-gets promoted to the cache.  The read, write and discard promote adjustment
+Large, sequential I/Os are probably better left on the origin device
+since spindles tend to have good sequential I/O bandwidth.  The
+io_tracker counts contiguous I/Os to try to spot when the I/O is in one
+of these sequential modes.  But there are use-cases for wanting to
+promote sequential blocks to the cache (e.g. fast application startup).
+If sequential threshold is set to 0 the sequential I/O detection is
+disabled and sequential I/O will no longer implicitly bypass the cache.
+Setting the random threshold to 0 does _not_ disable the random I/O
+stream detection.
+
+Internally the mq policy determines a promotion threshold.  If the hit
+count of a block not in the cache goes above this threshold it gets
+promoted to the cache.  The read, write and discard promote adjustment
 tunables allow you to tweak the promotion threshold by adding a small
 value based on the io type.  They default to 4, 8 and 1 respectively.
 If you're trying to quickly warm a new cache device you may wish to
index 7eece72b1a350ad1d80093731abfdb508c407519..8fe815046140becdbc594545d6677b8800b6a541 100644 (file)
@@ -2,7 +2,9 @@ Amlogic MesonX device tree bindings
 -------------------------------------------
 
 Boards with the Amlogic Meson6 SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,meson6"
 
-Required root node property:
-
-compatible = "amlogic,meson6";
+Boards with the Amlogic Meson8 SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,meson8";
index 37b2cafa4e52703b516d8c163653ae58106ad990..256b4d8bab7b93d49330c7db5334eb05e8979904 100644 (file)
@@ -22,6 +22,14 @@ to deliver its interrupts via SPIs.
 - always-on : a boolean property. If present, the timer is powered through an
   always-on power domain, therefore it never loses context.
 
+** Optional properties:
+
+- arm,cpu-registers-not-fw-configured : Firmware does not initialize
+  any of the generic timer CPU registers, which contain their
+  architecturally-defined reset values. Only supported for 32-bit
+  systems which follow the ARMv7 architected reset values.
+
+
 Example:
 
        timer {
index c554ed3d44fb7c77f8ae19c441a57f5d05853ef8..556c8665fdbf0aa5b89e4a0818b66e30b702f3e9 100644 (file)
@@ -92,3 +92,68 @@ Required nodes:
 - core-module: the root node to the Versatile platforms must have
   a core-module with regs and the compatible strings
   "arm,core-module-versatile", "syscon"
+
+ARM RealView Boards
+-------------------
+The RealView boards cover tailored evaluation boards that are used to explore
+the ARM11 and Cortex A-8 and Cortex A-9 processors.
+
+Required properties (in root node):
+       /* RealView Emulation Baseboard */
+       compatible = "arm,realview-eb";
+        /* RealView Platform Baseboard for ARM1176JZF-S */
+       compatible = "arm,realview-pb1176";
+       /* RealView Platform Baseboard for ARM11 MPCore */
+       compatible = "arm,realview-pb11mp";
+       /* RealView Platform Baseboard for Cortex A-8 */
+       compatible = "arm,realview-pba8";
+       /* RealView Platform Baseboard Explore for Cortex A-9 */
+       compatible = "arm,realview-pbx";
+
+Required nodes:
+
+- soc: some node of the RealView platforms must be the SoC
+  node that contain the SoC-specific devices, withe the compatible
+  string set to one of these tuples:
+   "arm,realview-eb-soc", "simple-bus"
+   "arm,realview-pb1176-soc", "simple-bus"
+   "arm,realview-pb11mp-soc", "simple-bus"
+   "arm,realview-pba8-soc", "simple-bus"
+   "arm,realview-pbx-soc", "simple-bus"
+
+- syscon: some subnode of the RealView SoC node must be a
+  system controller node pointing to the control registers,
+  with the compatible string set to one of these tuples:
+   "arm,realview-eb-syscon", "syscon"
+   "arm,realview-pb1176-syscon", "syscon"
+   "arm,realview-pb11mp-syscon", "syscon"
+   "arm,realview-pba8-syscon", "syscon"
+   "arm,realview-pbx-syscon", "syscon"
+
+  Required properties for the system controller:
+  - regs: the location and size of the system controller registers,
+    one range of 0x1000 bytes.
+
+Example:
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "skeleton.dtsi"
+
+/ {
+       model = "ARM RealView PB1176 with device tree";
+       compatible = "arm,realview-pb1176";
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "arm,realview-pb1176-soc", "simple-bus";
+               ranges;
+
+               syscon: syscon@10000000 {
+                       compatible = "arm,realview-syscon", "syscon";
+                       reg = <0x10000000 0x1000>;
+               };
+
+       };
+};
diff --git a/Documentation/devicetree/bindings/arm/bcm/cygnus.txt b/Documentation/devicetree/bindings/arm/bcm/cygnus.txt
new file mode 100644 (file)
index 0000000..4c77169
--- /dev/null
@@ -0,0 +1,31 @@
+Broadcom Cygnus device tree bindings
+------------------------------------
+
+
+Boards with Cygnus SoCs shall have the following properties:
+
+Required root node property:
+
+BCM11300
+compatible = "brcm,bcm11300", "brcm,cygnus";
+
+BCM11320
+compatible = "brcm,bcm11320", "brcm,cygnus";
+
+BCM11350
+compatible = "brcm,bcm11350", "brcm,cygnus";
+
+BCM11360
+compatible = "brcm,bcm11360", "brcm,cygnus";
+
+BCM58300
+compatible = "brcm,bcm58300", "brcm,cygnus";
+
+BCM58302
+compatible = "brcm,bcm58302", "brcm,cygnus";
+
+BCM58303
+compatible = "brcm,bcm58303", "brcm,cygnus";
+
+BCM58305
+compatible = "brcm,bcm58305", "brcm,cygnus";
index fc446347ab6db4be375cb8125647b8585cba54ae..b2aacbe16ed9af08a616bee7907f7d5890624c2e 100644 (file)
@@ -227,6 +227,15 @@ nodes to be present and contain the properties described below.
                        # List of phandles to idle state nodes supported
                          by this cpu [3].
 
+       - rockchip,pmu
+               Usage: optional for systems that have an "enable-method"
+                      property value of "rockchip,rk3066-smp"
+                      While optional, it is the preferred way to get access to
+                      the cpu-core power-domains.
+               Value type: <phandle>
+               Definition: Specifies the syscon node controlling the cpu core
+                           power domains.
+
 Example 1 (dual-cluster big.LITTLE system 32-bit):
 
        cpus {
index e935d7d4ac432fa0f20665d45758bb50500054b2..4e8b7df7fc62d84b505f165aaf3067a8417c8cee 100644 (file)
@@ -74,3 +74,41 @@ Required root node properties:
 i.MX6q generic board
 Required root node properties:
     - compatible = "fsl,imx6q";
+
+
+Freescale LS1021A Platform Device Tree Bindings
+------------------------------------------------
+
+Required root node compatible properties:
+  - compatible = "fsl,ls1021a";
+
+Freescale LS1021A SoC-specific Device Tree Bindings
+-------------------------------------------
+
+Freescale SCFG
+  SCFG is the supplemental configuration unit, that provides SoC specific
+configuration and status registers for the chip. Such as getting PEX port
+status.
+  Required properties:
+  - compatible: should be "fsl,ls1021a-scfg"
+  - reg: should contain base address and length of SCFG memory-mapped registers
+
+Example:
+       scfg: scfg@1570000 {
+               compatible = "fsl,ls1021a-scfg";
+               reg = <0x0 0x1570000 0x0 0x10000>;
+       };
+
+Freescale DCFG
+  DCFG is the device configuration unit, that provides general purpose
+configuration and status for the device. Such as setting the secondary
+core start address and release the secondary core from holdoff and startup.
+  Required properties:
+  - compatible: should be "fsl,ls1021a-dcfg"
+  - reg : should contain base address and length of DCFG memory-mapped registers
+
+Example:
+       dcfg: dcfg@1ee0000 {
+               compatible = "fsl,ls1021a-dcfg";
+               reg = <0x0 0x1ee0000 0x0 0x10000>;
+       };
index c7d2fa15667826ac5d30455e89dc213085735759..b38608af66db5b9ab93e0cf59b55ffad44793baf 100644 (file)
@@ -17,6 +17,7 @@ Main node required properties:
        "arm,cortex-a7-gic"
        "arm,arm11mp-gic"
        "brcm,brahma-b15-gic"
+       "arm,arm1176jzf-devchip-gic"
 - 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 904de5781f44d9dd10efae916101e1fac7835274..a99eb9eb14c0713809c388c43a863c2c37f41784 100644 (file)
@@ -106,11 +106,21 @@ Required subnode-properties:
 - groups: a list of strings describing the group names.
 - function: a string describing the function used to mux the groups.
 
+* Reset controller binding
+
+A reset controller is part of the chip control registers set. The chip control
+node also provides the reset. The register set is not at the same offset between
+Berlin SoCs.
+
+Required property:
+- #reset-cells: must be set to 2
+
 Example:
 
 chip: chip-control@ea0000 {
        compatible = "marvell,berlin2-chip-ctrl";
        #clock-cells = <1>;
+       #reset-cells = <2>;
        reg = <0xea0000 0x400>;
        clocks = <&refclk>, <&externaldev 0>;
        clock-names = "refclk", "video_ext0";
index fa252261dfaf888386f14e2117695a7599dba862..3be40139cfbbe85d8aaf5ce42bdc080d483535c1 100644 (file)
@@ -1,10 +1,14 @@
-Mediatek MT6589 Platforms Device Tree Bindings
+MediaTek mt65xx & mt81xx Platforms Device Tree Bindings
 
-Boards with a SoC of the Mediatek MT6589 shall have the following property:
+Boards with a MediaTek mt65xx/mt81xx SoC shall have the following property:
 
 Required root node property:
 
-compatible: must contain "mediatek,mt6589"
+compatible: Must contain one of
+   "mediatek,mt6589"
+   "mediatek,mt6592"
+   "mediatek,mt8127"
+   "mediatek,mt8135"
 
 
 Supported boards:
@@ -12,3 +16,12 @@ Supported boards:
 - bq Aquaris5 smart phone:
     Required root node properties:
       - compatible = "mundoreader,bq-aquaris5", "mediatek,mt6589";
+- Evaluation board for MT6592:
+    Required root node properties:
+      - compatible = "mediatek,mt6592-evb", "mediatek,mt6592";
+- MTK mt8127 tablet moose EVB:
+    Required root node properties:
+      - compatible = "mediatek,mt8127-moose", "mediatek,mt8127";
+- MTK mt8135 tablet EVB:
+    Required root node properties:
+      - compatible = "mediatek,mt8135-evbp1", "mediatek,mt8135";
index ddd9bcdf889c3f7ad5d2090048f3e2d9c149238c..4f6a82cef1d1a4f74a22304fb62c7abf48897ae1 100644 (file)
@@ -132,6 +132,9 @@ Boards:
 - AM335X Bone : Low cost community board
   compatible = "ti,am335x-bone", "ti,am33xx", "ti,omap3"
 
+- AM335X OrionLXm : Substation Automation Platform
+  compatible = "novatech,am335x-lxm", "ti,am33xx"
+
 - OMAP5 EVM : Evaluation Module
   compatible = "ti,omap5-evm", "ti,omap5"
 
index 857f12636eb28b58d6eacbaf29f9314c0670f3bd..eaa3d1a0eb0598bb283355b203c404f15621964a 100644 (file)
@@ -1,6 +1,10 @@
 Rockchip platforms device tree bindings
 ---------------------------------------
 
+- MarsBoard RK3066 board:
+    Required root node properties:
+      - compatible = "haoyu,marsboard-rk3066", "rockchip,rk3066a";
+
 - bq Curie 2 tablet:
     Required root node properties:
       - compatible = "mundoreader,bq-curie2", "rockchip,rk3066a";
index 2168ed31e1b0872ffa7efbb838a571e3ebbef7b6..43589d2466a7461911677c702dc8d206f8bdafa6 100644 (file)
@@ -1,11 +1,20 @@
-* Samsung's Exynos4210 based SMDKV310 evaluation board
-
-SMDKV310 evaluation board is based on Samsung's Exynos4210 SoC.
+* Samsung's Exynos SoC based boards
 
 Required root node properties:
     - compatible = should be one or more of the following.
-        (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
-        (b) "samsung,exynos4210"  - for boards based on Exynos4210 SoC.
+       - "samsung,monk"        - for Exynos3250-based Samsung Simband board.
+       - "samsung,rinato"      - for Exynos3250-based Samsung Gear2 board.
+       - "samsung,smdkv310"    - for Exynos4210-based Samsung SMDKV310 eval board.
+       - "samsung,trats"       - for Exynos4210-based Tizen Reference board.
+       - "samsung,universal_c210" - for Exynos4210-based Samsung board.
+       - "samsung,smdk4412",   - for Exynos4412-based Samsung SMDK4412 eval board.
+       - "samsung,trats2"      - for Exynos4412-based Tizen Reference board.
+       - "samsung,smdk5250"    - for Exynos5250-based Samsung SMDK5250 eval board.
+       - "samsung,xyref5260"   - for Exynos5260-based Samsung board.
+       - "samsung,smdk5410"    - for Exynos5410-based Samsung SMDK5410 eval board.
+       - "samsung,smdk5420"    - for Exynos5420-based Samsung SMDK5420 eval board.
+       - "samsung,sd5v1"       - for Exynos5440-based Samsung board.
+       - "samsung,ssdk5440"    - for Exynos5440-based Samsung board.
 
 Optional:
     - firmware node, specifying presence and type of secure firmware:
index 6256ec31666d51cb833c5d78ecfcf30293cefed2..2fdff5a806cfb76b5c43de6a65bc0292898fd710 100644 (file)
@@ -10,6 +10,12 @@ Required root node property: src
 
 Boards with the Nomadik SoC include:
 
+Nomadik NHK-15 board manufactured by ST Microelectronics:
+
+Required root node property:
+
+compatible="st,nomadik-nhk-15";
+
 S8815 "MiniKit" manufactured by Calao Systems:
 
 Required root node property:
diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt
new file mode 100644 (file)
index 0000000..42941fd
--- /dev/null
@@ -0,0 +1,12 @@
+Allwinner sunXi Platforms Device Tree Bindings
+
+Each device tree must specify which Allwinner SoC it uses,
+using one of the following compatible strings:
+
+  allwinner,sun4i-a10
+  allwinner,sun5i-a10s
+  allwinner,sun5i-a13
+  allwinner,sun6i-a31
+  allwinner,sun7i-a20
+  allwinner,sun8i-a23
+  allwinner,sun9i-a80
diff --git a/Documentation/devicetree/bindings/arm/ux500/power_domain.txt b/Documentation/devicetree/bindings/arm/ux500/power_domain.txt
new file mode 100644 (file)
index 0000000..5679d17
--- /dev/null
@@ -0,0 +1,35 @@
+* ST-Ericsson UX500 PM Domains
+
+UX500 supports multiple PM domains which are used to gate power to one or
+more peripherals on the SOC.
+
+The implementation of PM domains for UX500 are based upon the generic PM domain
+and use the corresponding DT bindings.
+
+==PM domain providers==
+
+Required properties:
+ - compatible: Must be "stericsson,ux500-pm-domains".
+ - #power-domain-cells : Number of cells in a power domain specifier, must be 1.
+
+Example:
+       pm_domains: pm_domains0 {
+               compatible = "stericsson,ux500-pm-domains";
+               #power-domain-cells = <1>;
+       };
+
+==PM domain consumers==
+
+Required properties:
+ - power-domains: A phandle and PM domain specifier. Below are the list of
+               valid specifiers:
+
+               Index   Specifier
+               -----   ---------
+               0       DOMAIN_VAPE
+
+Example:
+       sdi0_per1@80126000 {
+               compatible = "arm,pl18x", "arm,primecell";
+               power-domains = <&pm_domains DOMAIN_VAPE>
+       };
index 1e6111333fa88f86a2008325637195f51d50648d..80ae87a0784bdba8f2014d51ec6b083512c1dc4f 100644 (file)
@@ -3,8 +3,10 @@
 Required properties:
 - compatible           : should contain one of the following:
                          - "renesas,sata-r8a7779" for R-Car H1
-                         - "renesas,sata-r8a7790" for R-Car H2
-                         - "renesas,sata-r8a7791" for R-Car M2
+                         - "renesas,sata-r8a7790-es1" for R-Car H2 ES1
+                         - "renesas,sata-r8a7790" for R-Car H2 other than ES1
+                         - "renesas,sata-r8a7791" for R-Car M2-W
+                         - "renesas,sata-r8a7793" for R-Car M2-N
 - reg                  : address and length of the SATA registers;
 - interrupts           : must consist of one interrupt specifier.
 
index e2d501d20c9ae2ecdeb7f8493d5b7fc97d51462a..1eceefb20f01a887933c4c5f58d2583da287f031 100644 (file)
@@ -2,7 +2,11 @@ Broadcom GISB bus Arbiter controller
 
 Required properties:
 
-- compatible: should be "brcm,gisb-arb"
+- compatible:
+    "brcm,gisb-arb" or "brcm,bcm7445-gisb-arb" for 28nm chips
+    "brcm,bcm7435-gisb-arb" for newer 40nm chips
+    "brcm,bcm7400-gisb-arb" for older 40nm chips and all 65nm chips
+    "brcm,bcm7038-gisb-arb" for 130nm chips
 - reg: specifies the base physical address and size of the registers
 - interrupt-parent: specifies the phandle to the parent interrupt controller
   this arbiter gets interrupt line from
index 5fa44f52a0b805aa9d9362d4634e3372824df2b7..5e16c3ccb061d56c846f91d95b8ec3d667f0cd43 100644 (file)
@@ -48,9 +48,12 @@ Required properties:
 - compatible:  Should be set to "marvell,mbus-controller".
 
 - reg:          Device's register space.
-               Two entries are expected (see the examples below):
-               the first one controls the devices decoding window and
-               the second one controls the SDRAM decoding window.
+               Two or three entries are expected (see the examples below):
+               the first one controls the devices decoding window,
+               the second one controls the SDRAM decoding window and
+               the third controls the MBus bridge (only with the
+               marvell,armada370-mbus and marvell,armadaxp-mbus
+               compatible strings)
 
 Example:
 
@@ -67,7 +70,7 @@ Example:
 
                        mbusc: mbus-controller@20000 {
                                compatible = "marvell,mbus-controller";
-                               reg = <0x20000 0x100>, <0x20180 0x20>;
+                               reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
                        };
 
                        /* more children ...*/
@@ -126,7 +129,7 @@ are skipped.
 
                        mbusc: mbus-controller@20000 {
                                compatible = "marvell,mbus-controller";
-                               reg = <0x20000 0x100>, <0x20180 0x20>;
+                               reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
                        };
 
                        /* more children ...*/
@@ -170,7 +173,7 @@ Using this macro, the above example would be:
 
                        mbusc: mbus-controller@20000 {
                                compatible = "marvell,mbus-controller";
-                               reg = <0x20000 0x100>, <0x20180 0x20>;
+                               reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
                        };
 
                        /* other children */
@@ -266,7 +269,7 @@ See the example below, where a more complete device tree is shown:
                        ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
 
                        mbusc: mbus-controller@20000 {
-                               reg = <0x20000 0x100>, <0x20180 0x20>;
+                               reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
                        };
 
                        interrupt-controller@20000 {
diff --git a/Documentation/devicetree/bindings/clock/bcm-cygnus-clock.txt b/Documentation/devicetree/bindings/clock/bcm-cygnus-clock.txt
new file mode 100644 (file)
index 0000000..00d26ed
--- /dev/null
@@ -0,0 +1,34 @@
+Broadcom Cygnus Clocks
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Currently various "fixed" clocks are declared for peripheral drivers that use
+the common clock framework to reference their core clocks. Proper support of
+these clocks will be added later
+
+Device tree example:
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               osc: oscillator {
+                       compatible = "fixed-clock";
+                       #clock-cells = <1>;
+                       clock-frequency = <25000000>;
+               };
+
+               apb_clk: apb_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000000>;
+               };
+
+               periph_clk: periph_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <500000000>;
+               };
+       };
index c80863d344ac0b81043edc885262cdc6d609d4df..63f9f1ac34390762b9950254ef478c9b6b6053a1 100644 (file)
@@ -5,6 +5,19 @@ Required properties:
 - reg: Address and length of the register set
 - #clock-cells: Should be <1>
 
+Optional properties:
+- clocks: list of clock identifiers which are external input clocks to the
+       given clock controller. Please refer the next section to find
+       the input clocks for a given controller.
+- clock-names: list of names of clocks which are exteral input clocks to the
+       given clock controller.
+
+Input clocks for top clock controller:
+       - sxosc (external crystal oscillator 32KHz, recommended)
+       - fxosc (external crystal oscillator 24MHz, recommended)
+       - audio_ext
+       - enet_ext
+
 The clock consumer should specify the desired clock by having the clock
 ID in its "clocks" phandle cell. See include/dt-bindings/clock/vf610-clock.h
 for the full list of VF610 clock IDs.
@@ -15,6 +28,8 @@ clks: ccm@4006b000 {
        compatible = "fsl,vf610-ccm";
        reg = <0x4006b000 0x1000>;
        #clock-cells = <1>;
+       clocks = <&sxosc>, <&fxosc>;
+       clock-names = "sxosc", "fxosc";
 };
 
 uart1: serial@40028000 {
index 1405ed071bb4fd92937c6028c5ca38e32c0faddf..e4c4d47f8137bf7f5690ae78e7190c34fe4ab2e1 100644 (file)
@@ -25,7 +25,7 @@ Required child node properties:
 - compatible: It should be either "xlnx,axi-vdma-mm2s-channel" or
        "xlnx,axi-vdma-s2mm-channel".
 - interrupts: Should contain per channel VDMA interrupts.
-- xlnx,data-width: Should contain the stream data width, take values
+- xlnx,datawidth: Should contain the stream data width, take values
        {32,64...1024}.
 
 Optional child node properties:
diff --git a/Documentation/devicetree/bindings/hwmon/ltc2978.txt b/Documentation/devicetree/bindings/hwmon/ltc2978.txt
new file mode 100644 (file)
index 0000000..ed2f09d
--- /dev/null
@@ -0,0 +1,39 @@
+ltc2978
+
+Required properties:
+- compatible: should contain one of:
+  * "lltc,ltc2974"
+  * "lltc,ltc2977"
+  * "lltc,ltc2978"
+  * "lltc,ltc3880"
+  * "lltc,ltc3883"
+  * "lltc,ltm4676"
+- reg: I2C slave address
+
+Optional properties:
+- regulators: A node that houses a sub-node for each regulator controlled by
+  the device. Each sub-node is identified using the node's name, with valid
+  values listed below. The content of each sub-node is defined by the
+  standard binding for regulators; see regulator.txt.
+
+Valid names of regulators depend on number of supplies supported per device:
+  * ltc2974 : vout0 - vout3
+  * ltc2977 : vout0 - vout7
+  * ltc2978 : vout0 - vout7
+  * ltc3880 : vout0 - vout1
+  * ltc3883 : vout0
+  * ltm4676 : vout0 - vout1
+
+Example:
+ltc2978@5e {
+       compatible = "lltc,ltc2978";
+       reg = <0x5e>;
+       regulators {
+               vout0 {
+                       regulator-name = "FPGA-2.5V";
+               };
+               vout2 {
+                       regulator-name = "FPGA-1.5V";
+               };
+       };
+};
index 278de8e64bbf591b2b9fe4350fb843679b2cdc8c..89b3250f049b6ead36b110df609a1ab340ac0fb8 100644 (file)
@@ -32,6 +32,7 @@ Optional properties:
     specified, default value is 0.
   - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
     specified, the default value in Hz is 100000.
+  - samsung,sysreg-phandle - handle to syscon used to control the system registers
 
 Example:
 
index fbde415078e6845cc5ff862a758959d64810c316..605dcca5dbec61a82f89bccb9f91a917ae283334 100644 (file)
@@ -56,6 +56,8 @@ gmt,g751              G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire In
 infineon,slb9635tt     Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz)
 infineon,slb9645tt     Infineon SLB9645 I2C TPM (new protocol, max 400khz)
 isl,isl12057           Intersil ISL12057 I2C RTC Chip
+isil,isl29028           (deprecated, use isl)
+isl,isl29028            Intersil ISL29028 Ambient Light and Proximity Sensor
 maxim,ds1050           5 Bit Programmable, Pulse-Width Modulator
 maxim,max1237          Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
 maxim,max6625          9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
index ce6a1a0720285bd9be4549d478ea49b4b985ee31..8a3c4082989906248fd4f07ee7a1493b20580794 100644 (file)
@@ -30,10 +30,6 @@ should only be used when a device has multiple interrupt parents.
   Example:
        interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
 
-A device node may contain either "interrupts" or "interrupts-extended", but not
-both. If both properties are present, then the operating system should log an
-error and use only the data in "interrupts".
-
 2) Interrupt controller nodes
 -----------------------------
 
diff --git a/Documentation/devicetree/bindings/mailbox/mailbox.txt b/Documentation/devicetree/bindings/mailbox/mailbox.txt
new file mode 100644 (file)
index 0000000..1a2cd3d
--- /dev/null
@@ -0,0 +1,38 @@
+* Generic Mailbox Controller and client driver bindings
+
+Generic binding to provide a way for Mailbox controller drivers to
+assign appropriate mailbox channel to client drivers.
+
+* Mailbox Controller
+
+Required property:
+- #mbox-cells: Must be at least 1. Number of cells in a mailbox
+               specifier.
+
+Example:
+       mailbox: mailbox {
+               ...
+               #mbox-cells = <1>;
+       };
+
+
+* Mailbox Client
+
+Required property:
+- mboxes: List of phandle and mailbox channel specifiers.
+
+Optional property:
+- mbox-names: List of identifier strings for each mailbox channel
+               required by the client. The use of this property
+               is discouraged in favor of using index in list of
+               'mboxes' while requesting a mailbox. Instead the
+               platforms may define channel indices, in DT headers,
+               to something legible.
+
+Example:
+       pwr_cntrl: power {
+               ...
+               mbox-names = "pwr-ctrl", "rpc";
+               mboxes = <&mailbox 0
+                       &mailbox 1>;
+       };
diff --git a/Documentation/devicetree/bindings/memory-controllers/mvebu-sdram-controller.txt b/Documentation/devicetree/bindings/memory-controllers/mvebu-sdram-controller.txt
new file mode 100644 (file)
index 0000000..89657d1
--- /dev/null
@@ -0,0 +1,21 @@
+Device Tree bindings for MVEBU SDRAM controllers
+
+The Marvell EBU SoCs all have a SDRAM controller. The SDRAM controller
+differs from one SoC variant to another, but they also share a number
+of commonalities.
+
+For now, this Device Tree binding documentation only documents the
+Armada XP SDRAM controller.
+
+Required properties:
+
+ - compatible: for Armada XP, "marvell,armada-xp-sdram-controller"
+ - reg: a resource specifier for the register space, which should
+   include all SDRAM controller registers as per the datasheet.
+
+Example:
+
+sdramc@1400 {
+       compatible = "marvell,armada-xp-sdram-controller";
+       reg = <0x1400 0x500>;
+};
diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt
new file mode 100644 (file)
index 0000000..f3db93c
--- /dev/null
@@ -0,0 +1,36 @@
+NVIDIA Tegra Memory Controller device tree bindings
+===================================================
+
+Required properties:
+- compatible: Should be "nvidia,tegra<chip>-mc"
+- reg: Physical base address and length of the controller's registers.
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - mc: the module's clock input
+- interrupts: The interrupt outputs from the controller.
+- #iommu-cells: Should be 1. The single cell of the IOMMU specifier defines
+  the SWGROUP of the master.
+
+This device implements an IOMMU that complies with the generic IOMMU binding.
+See ../iommu/iommu.txt for details.
+
+Example:
+--------
+
+       mc: memory-controller@0,70019000 {
+               compatible = "nvidia,tegra124-mc";
+               reg = <0x0 0x70019000 0x0 0x1000>;
+               clocks = <&tegra_car TEGRA124_CLK_MC>;
+               clock-names = "mc";
+
+               interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+
+               #iommu-cells = <1>;
+       };
+
+       sdhci@0,700b0000 {
+               compatible = "nvidia,tegra124-sdhci";
+               ...
+               iommus = <&mc TEGRA_SWGROUP_SDMMC1A>;
+       };
diff --git a/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt b/Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt
new file mode 100644 (file)
index 0000000..f64de95
--- /dev/null
@@ -0,0 +1,51 @@
+Device-Tree bindings for Atmel's HLCDC (High LCD Controller) MFD driver
+
+Required properties:
+ - compatible: value should be one of the following:
+   "atmel,sama5d3-hlcdc"
+ - reg: base address and size of the HLCDC device registers.
+ - clock-names: the name of the 3 clocks requested by the HLCDC device.
+   Should contain "periph_clk", "sys_clk" and "slow_clk".
+ - clocks: should contain the 3 clocks requested by the HLCDC device.
+ - interrupts: should contain the description of the HLCDC interrupt line
+
+The HLCDC IP exposes two subdevices:
+ - a PWM chip: see ../pwm/atmel-hlcdc-pwm.txt
+ - a Display Controller: see ../drm/atmel-hlcdc-dc.txt
+
+Example:
+
+       hlcdc: hlcdc@f0030000 {
+               compatible = "atmel,sama5d3-hlcdc";
+               reg = <0xf0030000 0x2000>;
+               clocks = <&lcdc_clk>, <&lcdck>, <&clk32k>;
+               clock-names = "periph_clk","sys_clk", "slow_clk";
+               interrupts = <36 IRQ_TYPE_LEVEL_HIGH 0>;
+               status = "disabled";
+
+               hlcdc-display-controller {
+                       compatible = "atmel,hlcdc-display-controller";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reg = <0>;
+
+                               hlcdc_panel_output: endpoint@0 {
+                                       reg = <0>;
+                                       remote-endpoint = <&panel_input>;
+                               };
+                       };
+               };
+
+               hlcdc_pwm: hlcdc-pwm {
+                       compatible = "atmel,hlcdc-pwm";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_lcd_pwm>;
+                       #pwm-cells = <3>;
+               };
+       };
index 678f3cf0b8f005759c8bdba2c3ebb34438a2ba76..75fdfaf41831d9fcd76be1b5706dadf1e2a2cb7d 100644 (file)
@@ -34,6 +34,12 @@ to get matched with their hardware counterparts as follow:
        -BUCKn  :       for BUCKs, where n can lie in range 1 to 9.
                        example: BUCK1, BUCK5, BUCK9.
 
+  Regulators which can be turned off during system suspend:
+       -LDOn   :       2, 6-8, 10-12, 14-16,
+       -BUCKn  :       1-4.
+  Use standard regulator bindings for it ('regulator-off-in-suspend').
+
+
 Example:
 
        max77686@09 {
index 11921cc417bf58584fd6c84212630dbeb6d4c62d..01e9f30fe6785f4b81eb396959961d0781b25d32 100644 (file)
@@ -27,6 +27,20 @@ Optional properties:
 
        [*] refer Documentation/devicetree/bindings/regulator/regulator.txt
 
+- haptic : The MAX77693 haptic device utilises a PWM controlled motor to provide
+  users with tactile feedback. PWM period and duty-cycle are varied in
+  order to provide the approprite level of feedback.
+
+ Required properties:
+       - compatible : Must be "maxim,max77693-hpatic"
+       - haptic-supply : power supply for the haptic motor
+       [*] refer Documentation/devicetree/bindings/regulator/regulator.txt
+       - pwms : phandle to the physical PWM(Pulse Width Modulation) device.
+        PWM properties should be named "pwms". And number of cell is different
+        for each pwm device.
+        To get more informations, please refer to documentaion.
+       [*] refer Documentation/devicetree/bindings/pwm/pwm.txt
+
 Example:
        max77693@66 {
                compatible = "maxim,max77693";
@@ -52,4 +66,11 @@ Example:
                                        regulator-boot-on;
                        };
                };
+
+               haptic {
+                       compatible = "maxim,max77693-haptic";
+                       haptic-supply = <&haptic_supply>;
+                       pwms = <&pwm 0 40000 0>;
+                       pwm-names = "haptic";
+               };
        };
index 0e4026a6cbbfc21bc40dd9e1f5596acc33416e2a..57a045016fca68b6408db6b13f472ba7c17c5e84 100644 (file)
@@ -1,5 +1,5 @@
 
-* Samsung S2MPS11, S2MPS14 and S2MPU02 Voltage and Current Regulator
+* Samsung S2MPS11, S2MPS13, S2MPS14 and S2MPU02 Voltage and Current Regulator
 
 The Samsung S2MPS11 is a multi-function device which includes voltage and
 current regulators, RTC, charger controller and other sub-blocks. It is
@@ -7,8 +7,8 @@ interfaced to the host controller using an I2C interface. Each sub-block is
 addressed by the host system using different I2C slave addresses.
 
 Required properties:
-- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic"
-              or "samsung,s2mpu02-pmic".
+- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps13-pmic"
+             or "samsung,s2mps14-pmic" or "samsung,s2mpu02-pmic".
 - reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
 
 Optional properties:
@@ -17,8 +17,8 @@ Optional properties:
 - interrupts: Interrupt specifiers for interrupt sources.
 
 Optional nodes:
-- clocks: s2mps11 and s5m8767 provide three(AP/CP/BT) buffered 32.768 KHz
-  outputs, so to register these as clocks with common clock framework
+- clocks: s2mps11, s2mps13 and s5m8767 provide three(AP/CP/BT) buffered 32.768
+  KHz outputs, so to register these as clocks with common clock framework
   instantiate a sub-node named "clocks". It uses the common clock binding
   documented in :
   [Documentation/devicetree/bindings/clock/clock-bindings.txt]
@@ -30,12 +30,12 @@ Optional nodes:
     the clock which they consume.
     Clock               ID           Devices
     ----------------------------------------------------------
-    32KhzAP            0            S2MPS11, S2MPS14, S5M8767
-    32KhzCP            1            S2MPS11, S5M8767
-    32KhzBT            2            S2MPS11, S2MPS14, S5M8767
+    32KhzAP            0            S2MPS11, S2MPS13, S2MPS14, S5M8767
+    32KhzCP            1            S2MPS11, S2MPS13, S5M8767
+    32KhzBT            2            S2MPS11, S2MPS13, S2MPS14, S5M8767
 
-  - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps14-clk",
-               "samsung,s5m8767-clk"
+  - compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps13-clk",
+               "samsung,s2mps14-clk", "samsung,s5m8767-clk"
 
 - regulators: The regulators of s2mps11 that have to be instantiated should be
 included in a sub-node named 'regulators'. Regulator nodes included in this
@@ -81,12 +81,14 @@ as per the datasheet of s2mps11.
        - LDOn
                  - valid values for n are:
                        - S2MPS11: 1 to 38
+                       - S2MPS13: 1 to 40
                        - S2MPS14: 1 to 25
                        - S2MPU02: 1 to 28
                  - Example: LDO1, LDO2, LDO28
        - BUCKn
                  - valid values for n are:
                        - S2MPS11: 1 to 10
+                       - S2MPS13: 1 to 10
                        - S2MPS14: 1 to 5
                        - S2MPU02: 1 to 7
                  - Example: BUCK1, BUCK2, BUCK9
index 6cd3525d0e09514acedaf89c1c1abeeffad7cf95..ee4fc0576c7d866b318eda917066e76e920b4f53 100644 (file)
@@ -18,6 +18,10 @@ Required Properties:
          specific extensions.
        - "samsung,exynos5420-dw-mshc": for controllers with Samsung Exynos5420
          specific extensions.
+       - "samsung,exynos7-dw-mshc": for controllers with Samsung Exynos7
+         specific extensions.
+       - "samsung,exynos7-dw-mshc-smu": for controllers with Samsung Exynos7
+         specific extensions having an SMU.
 
 * samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface
   unit (ciu) clock. This property is applicable only for Exynos5 SoC's and
diff --git a/Documentation/devicetree/bindings/mmc/img-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/img-dw-mshc.txt
new file mode 100644 (file)
index 0000000..85de99f
--- /dev/null
@@ -0,0 +1,29 @@
+* Imagination specific extensions to the Synopsys Designware Mobile Storage
+  Host Controller
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Imagination specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+       - "img,pistachio-dw-mshc": for Pistachio SoCs
+
+Example:
+
+       mmc@18142000 {
+               compatible = "img,pistachio-dw-mshc";
+               reg = <0x18142000 0x400>;
+               interrupts = <GIC_SHARED 39 IRQ_TYPE_LEVEL_HIGH>;
+
+               clocks = <&system_clk>, <&sdhost_clk>;
+               clock-names = "biu", "ciu";
+
+               fifo-depth = <0x20>;
+               bus-width = <4>;
+               num-slots = <1>;
+               disable-wp;
+       };
index 86223c3eda905ad38234ce09443148b8eb0f0a72..4dd6deb9071967355c9eab001b1c8c4d72808496 100644 (file)
@@ -12,6 +12,10 @@ Required properties:
   * for "marvell,armada-380-sdhci", two register areas. The first one
     for the SDHCI registers themselves, and the second one for the
     AXI/Mbus bridge registers of the SDHCI unit.
+- clocks: Array of clocks required for SDHCI; requires at least one for
+    I/O clock.
+- clock-names: Array of names corresponding to clocks property; shall be
+    "io" for I/O clock and "core" for optional core clock.
 
 Optional properties:
 - mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning.
@@ -23,6 +27,8 @@ sdhci@d4280800 {
        reg = <0xd4280800 0x800>;
        bus-width = <8>;
        interrupts = <27>;
+       clocks = <&chip CLKID_SDIO1XIN>, <&chip CLKID_SDIO1>;
+       clock-names = "io", "core";
        non-removable;
        mrvl,clk-delay-cycles = <31>;
 };
@@ -32,5 +38,6 @@ sdhci@d8000 {
        reg = <0xd8000 0x1000>, <0xdc000 0x100>;
        interrupts = <0 25 0x4>;
        clocks = <&gateclk 17>;
+       clock-names = "io";
        mrvl,clk-delay-cycles = <0x1F>;
 };
index 0f8487b888221e6344dec76afd6a8ffa44242306..e77e167593db2aa585ca1afbb48e4fbac0287384 100644 (file)
@@ -11,3 +11,5 @@ Optional properties:
   are supported on the device.  Valid value for SMSC LAN91c111 are
   1, 2 or 4.  If it's omitted or invalid, the size would be 2 meaning
   16-bit access only.
+- power-gpios: GPIO to control the PWRDWN pin
+- reset-gpios: GPIO to control the RESET pin
diff --git a/Documentation/devicetree/bindings/nios2/nios2.txt b/Documentation/devicetree/bindings/nios2/nios2.txt
new file mode 100644 (file)
index 0000000..d6d0a94
--- /dev/null
@@ -0,0 +1,62 @@
+* Nios II Processor Binding
+
+This binding specifies what properties available in the device tree
+representation of a Nios II Processor Core.
+
+Users can use sopc2dts tool for generating device tree sources (dts) from a
+Qsys system. See more detail in: http://www.alterawiki.com/wiki/Sopc2dts
+
+Required properties:
+
+- compatible: Compatible property value should be "altr,nios2-1.0".
+- reg: Contains CPU index.
+- interrupt-controller: Specifies that the node is an interrupt controller
+- #interrupt-cells: Specifies the number of cells needed to encode an
+               interrupt source, should be 1.
+- clock-frequency: Contains the clock frequency for CPU, in Hz.
+- dcache-line-size: Contains data cache line size.
+- icache-line-size: Contains instruction line size.
+- dcache-size: Contains data cache size.
+- icache-size: Contains instruction cache size.
+- altr,pid-num-bits: Specifies the number of bits to use to represent the process
+               identifier (PID).
+- altr,tlb-num-ways: Specifies the number of set-associativity ways in the TLB.
+- altr,tlb-num-entries: Specifies the number of entries in the TLB.
+- altr,tlb-ptr-sz: Specifies size of TLB pointer.
+- altr,has-mul: Specifies CPU hardware multipy support, should be 1.
+- altr,has-mmu: Specifies CPU support MMU support, should be 1.
+- altr,has-initda: Specifies CPU support initda instruction, should be 1.
+- altr,reset-addr: Specifies CPU reset address
+- altr,fast-tlb-miss-addr: Specifies CPU fast TLB miss exception address
+- altr,exception-addr: Specifies CPU exception address
+
+Optional properties:
+- altr,has-div: Specifies CPU hardware divide support
+- altr,implementation: Nios II core implementation, this should be "fast";
+
+Example:
+
+cpu@0x0 {
+       device_type = "cpu";
+       compatible = "altr,nios2-1.0";
+       reg = <0>;
+       interrupt-controller;
+       #interrupt-cells = <1>;
+       clock-frequency = <125000000>;
+       dcache-line-size = <32>;
+       icache-line-size = <32>;
+       dcache-size = <32768>;
+       icache-size = <32768>;
+       altr,implementation = "fast";
+       altr,pid-num-bits = <8>;
+       altr,tlb-num-ways = <16>;
+       altr,tlb-num-entries = <128>;
+       altr,tlb-ptr-sz = <7>;
+       altr,has-div = <1>;
+       altr,has-mul = <1>;
+       altr,reset-addr = <0xc2800000>;
+       altr,fast-tlb-miss-addr = <0xc7fff400>;
+       altr,exception-addr = <0xd0000020>;
+       altr,has-initda = <1>;
+       altr,has-mmu = <1>;
+};
diff --git a/Documentation/devicetree/bindings/nios2/timer.txt b/Documentation/devicetree/bindings/nios2/timer.txt
new file mode 100644 (file)
index 0000000..904a584
--- /dev/null
@@ -0,0 +1,19 @@
+Altera Timer
+
+Required properties:
+
+- compatible : should be "altr,timer-1.0"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-parent: phandle of the interrupt controller
+- interrupts : Should contain the timer interrupt number
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+       compatible = "altr,timer-1.0";
+       reg = <0x00400000 0x00000020>;
+       interrupt-parent = <&cpu>;
+       interrupts = <11>;
+       clock-frequency = <125000000>;
+};
index 41aeed38926d19e84b67f3194994ded9c584106c..f8fbe9af7b2f276350426b299c6030adb9464640 100644 (file)
@@ -7,3 +7,14 @@ And for the interrupt mapping part:
 
 Open Firmware Recommended Practice: Interrupt Mapping
 http://www.openfirmware.org/1275/practice/imap/imap0_9d.pdf
+
+Additionally to the properties specified in the above standards a host bridge
+driver implementation may support the following properties:
+
+- linux,pci-domain:
+   If present this property assigns a fixed PCI domain number to a host bridge,
+   otherwise an unstable (across boots) unique number will be assigned.
+   It is required to either not set this property at all or set it for all
+   host bridges in the system, otherwise potentially conflicting domain numbers
+   may be assigned to root buses behind different host bridges.  The domain
+   number for each host bridge in the system must be unique.
index a186181c402ba693b43c71e5f129e6cb05cfcde7..51b943cc9770e1b096e3def62c3e902c4ce02772 100644 (file)
@@ -9,7 +9,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-TZ1090-PDC's pin configuration nodes act as a container for an abitrary number
+TZ1090-PDC's pin configuration nodes act as a container for an arbitrary number
 of subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
index 4b27c99f7f9d496028ae215b7c79d3cc4b1e995b..49d0e6050940256edde1dd8a2dcc2a84c6b5f910 100644 (file)
@@ -9,7 +9,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-TZ1090's pin configuration nodes act as a container for an abitrary number of
+TZ1090's pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
index daa7689560695d1769bdf7d2064ff1f0181873d6..ac4da9fe07bd1fe28d2ceabacbca5453ff41e7a5 100644 (file)
@@ -9,7 +9,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-Lantiq's pin configuration nodes act as a container for an abitrary number of
+Lantiq's pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those group(s), and two pin configuration parameters:
index b5469db1d7adc2d4f2ff36adf6ed75e2802fe116..e89b4677567d0fcd9a4550905ea806d905d951c0 100644 (file)
@@ -9,7 +9,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-Lantiq's pin configuration nodes act as a container for an abitrary number of
+Lantiq's pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those group(s), and two pin configuration parameters:
index 61e73cde9ae9437303b7b095dc2d14c1d4966f62..3c8ce28baad63b164513875221a298dca5bb2066 100644 (file)
@@ -9,7 +9,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-Tegra's pin configuration nodes act as a container for an abitrary number of
+Tegra's pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
index c596a6ad3285acdd52d357a6e4a56cee98a7eb56..5f55be59d914a33aa71f4f432237782fd45f46ad 100644 (file)
@@ -13,7 +13,7 @@ Optional properties:
 Please refer to pinctrl-bindings.txt in this directory for details of the common
 pinctrl bindings used by client devices.
 
-SiRFprimaII's pinmux nodes act as a container for an abitrary number of subnodes.
+SiRFprimaII's pinmux nodes act as a container for an arbitrary number of subnodes.
 Each of these subnodes represents some desired configuration for a group of pins.
 
 Required subnode-properties:
index b4480d5c3aca93a99721829c604c5a823c28bc82..458615596946f6d29ccd60401f87a419fbe0e84a 100644 (file)
@@ -32,7 +32,7 @@ Required properties:
 Please refer to pinctrl-bindings.txt in this directory for details of the common
 pinctrl bindings used by client devices.
 
-SPEAr's pinmux nodes act as a container for an abitrary number of subnodes. Each
+SPEAr's pinmux nodes act as a container for an arbitrary number of subnodes. Each
 of these subnodes represents muxing for a pin, a group, or a list of pins or
 groups.
 
index 2fb90b37aa09080fec5dc37caaafd72d73548607..a7bde64798c7e33a7a84e73bb92f82d5d7fd53eb 100644 (file)
@@ -18,7 +18,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-Qualcomm's pin configuration nodes act as a container for an abitrary number of
+Qualcomm's pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
index ffafa1990a3048baaf36efce244e4c9ea4e7887f..c4ea61ac56f2fdbdd535a6123ba29c3a05acfb01 100644 (file)
@@ -47,7 +47,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-The pin configuration nodes act as a container for an abitrary number of
+The pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
index e33e4dcdce79bdfb51e17b4ab1bbb5602db569b0..6e88e91feb1130796dacf610ceb0a6969c5b0b95 100644 (file)
@@ -18,7 +18,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-Qualcomm's pin configuration nodes act as a container for an abitrary number of
+Qualcomm's pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
index 93b7de91b9f6f62d824436c003ee332705a1efdb..eb8d8aa41f2051a8be7c87e4d10c12b68f6a76d8 100644 (file)
@@ -47,7 +47,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-The pin configuration nodes act as a container for an abitrary number of
+The pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
index d2ea80dc43ebca126558ed3f97d8a395f1b63c7c..e4d6a9d20f7d0d82c684356f03397f95872ffe26 100644 (file)
@@ -18,7 +18,7 @@ Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
 phrase "pin configuration node".
 
-Qualcomm's pin configuration nodes act as a container for an abitrary number of
+Qualcomm's pin configuration nodes act as a container for an arbitrary number of
 subnodes. Each of these subnodes represents some desired configuration for a
 pin, a group, or a list of pins or groups. This configuration can include the
 mux function to select on those pin(s)/group(s), and various pin configuration
diff --git a/Documentation/devicetree/bindings/power/power-controller.txt b/Documentation/devicetree/bindings/power/power-controller.txt
new file mode 100644 (file)
index 0000000..4f7a3bc
--- /dev/null
@@ -0,0 +1,18 @@
+* Generic system power control capability
+
+Power-management integrated circuits or miscellaneous hardware components are
+sometimes able to control the system power. The device driver associated with these
+components might need to define this capability, which tells the kernel that
+it can be used to switch off the system. The corresponding device must have the
+standard property "system-power-controller" in its device node. This property
+marks the device as able to control the system power. In order to test if this
+property is found programmatically, use the helper function
+"of_device_is_system_power_controller" from of.h .
+
+Example:
+
+act8846: act8846@5 {
+        compatible = "active-semi,act8846";
+        status = "okay";
+        system-power-controller;
+}
diff --git a/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
new file mode 100644 (file)
index 0000000..dc7c9ba
--- /dev/null
@@ -0,0 +1,23 @@
+i.mx6 Poweroff Driver
+
+SNVS_LPCR in SNVS module can power off the whole system by pull
+PMIC_ON_REQ low if PMIC_ON_REQ is connected with external PMIC.
+If you don't want to use PMIC_ON_REQ as power on/off control,
+please set status='disabled' to disable this driver.
+
+Required Properties:
+-compatible: "fsl,sec-v4.0-poweroff"
+-reg: Specifies the physical address of the SNVS_LPCR register
+
+Example:
+       snvs@020cc000 {
+               compatible = "fsl,sec-v4.0-mon", "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x020cc000 0x4000>;
+               .....
+               snvs_poweroff: snvs-poweroff@38 {
+                       compatible = "fsl,sec-v4.0-poweroff";
+                       reg = <0x38 0x4>;
+               };
+       }
index 0bda229a6171d219a393d7133305a5853943bd1a..3899d6a557c15af8482f3c0574404e437b462e5d 100644 (file)
@@ -1,5 +1,20 @@
 Freescale FlexTimer Module (FTM) PWM controller
 
+The same FTM PWM device can have a different endianness on different SoCs. The
+device tree provides a property to describing this so that an operating system
+device driver can handle all variants of the device. Refer to the table below
+for the endianness of the FTM PWM block as integrated into the existing SoCs:
+
+       SoC     | FTM-PWM endianness
+       --------+-------------------
+       Vybrid  | LE
+       LS1     | BE
+       LS2     | LE
+
+Please see ../regmap/regmap.txt for more detail about how to specify endian
+modes in device tree.
+
+
 Required properties:
 - compatible: Should be "fsl,vf610-ftm-pwm".
 - reg: Physical base address and length of the controller's registers
@@ -16,7 +31,8 @@ Required properties:
 - pinctrl-names: Must contain a "default" entry.
 - pinctrl-NNN: One property must exist for each entry in pinctrl-names.
   See pinctrl/pinctrl-bindings.txt for details of the property values.
-
+- big-endian: Boolean property, required if the FTM PWM registers use a big-
+  endian rather than little-endian layout.
 
 Example:
 
@@ -32,4 +48,5 @@ pwm0: pwm@40038000 {
                        <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_pwm0_1>;
+               big-endian;
 };
index d47d15a6a2985e7f3eae08db0d9ad3986e80c227..b8be3d09ee26b7522fa373eefd1903aef8ce3d41 100644 (file)
@@ -7,8 +7,8 @@ Required properties:
    "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
  - reg: physical base address and length of the controller's registers
  - clocks: phandle and clock specifier of the PWM reference clock
- - #pwm-cells: should be 2. See pwm.txt in this directory for a
-   description of the cell format.
+ - #pwm-cells: must be 2 (rk2928) or 3 (rk3288). See pwm.txt in this directory
+   for a description of the cell format.
 
 Example:
 
index 865614b34d6fbb502625c1c1b917c0370bc78ca7..dad6358074ac51bbd4d73b102650d038053b9cf3 100644 (file)
@@ -5,6 +5,10 @@ Required properties:
 - compatible: "active-semi,act8846" or "active-semi,act8865"
 - reg: I2C slave address
 
+Optional properties:
+- system-power-controller: Telling whether or not this pmic is controlling
+  the system power. See Documentation/devicetree/bindings/power/power-controller.txt .
+
 Any standard regulator properties can be used to configure the single regulator.
 
 The valid names for regulators are:
index 5aeaffc0f1f0d415500b21a1bebb9bf2fb327fe3..79e5476444f7b4c47a75bed4659c44dffb7576e2 100644 (file)
@@ -25,6 +25,29 @@ with their hardware counterparts as follow. The valid names are:
                        example: LDO1, LDO2, LDO35.
        -BUCKn  :       for BUCKs, where n can lie in range 1 to 10.
                        example: BUCK1, BUCK5, BUCK10.
+
+The max77802 regulator supports two different operating modes: Normal and Low
+Power Mode. Some regulators support the modes to be changed at startup or by
+the consumers during normal operation while others only support to change the
+mode during system suspend. The standard regulator suspend states binding can
+be used to configure the regulator operating mode.
+
+The regulators that support the standard "regulator-initial-mode" property,
+changing their mode during normal operation are: LDOs 1, 3, 20 and 21.
+
+The possible values for "regulator-initial-mode" and "regulator-mode" are:
+       1: Normal regulator voltage output mode.
+       3: Low Power which reduces the quiescent current down to only 1uA
+
+The list of valid modes are defined in the dt-bindings/clock/maxim,max77802.h
+header and can be included by device tree source files.
+
+The standard "regulator-mode" property can only be used for regulators that
+support changing their mode to Low Power Mode during suspend. These regulators
+are: BUCKs 2-4 and LDOs 1-35. Also, it only takes effect if the regulator has
+been enabled for the given suspend state using "regulator-on-in-suspend" and
+has not been disabled for that state using "regulator-off-in-suspend".
+
 Example:
 
        max77802@09 {
@@ -36,11 +59,23 @@ Example:
                #size-cells = <0>;
 
                regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "vdd_1v0";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               regulator-initial-mode = <MAX77802_OPMODE_LP>;
+                       };
+
                        ldo11_reg: LDO11 {
                                regulator-name = "vdd_ldo11";
                                regulator-min-microvolt = <1900000>;
                                regulator-max-microvolt = <1900000>;
                                regulator-always-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-mode = <MAX77802_OPMODE_LP>;
+                               };
                        };
 
                        buck1_reg: BUCK1 {
index 86074334e342cc38ec4da009fa019b69a27ce031..abb26b58c83eea4eb60170f56700f9fa20aa8f88 100644 (file)
@@ -19,6 +19,24 @@ Optional properties:
   design requires. This property describes the total system ramp time
   required due to the combination of internal ramping of the regulator itself,
   and board design issues such as trace capacitance and load on the supply.
+- regulator-state-mem sub-root node for Suspend-to-RAM mode
+  : suspend to memory, the device goes to sleep, but all data stored in memory,
+  only some external interrupt can wake the device.
+- regulator-state-disk sub-root node for Suspend-to-DISK mode
+  : suspend to disk, this state operates similarly to Suspend-to-RAM,
+  but includes a final step of writing memory contents to disk.
+- regulator-state-[mem/disk] node has following common properties:
+       - regulator-on-in-suspend: regulator should be on in suspend state.
+       - regulator-off-in-suspend: regulator should be off in suspend state.
+       - regulator-suspend-microvolt: regulator should be set to this voltage
+         in suspend.
+       - regulator-mode: operating mode in the given suspend state.
+         The set of possible operating modes depends on the capabilities of
+         every hardware so the valid modes are documented on each regulator
+         device tree binding document.
+- regulator-initial-mode: initial operating mode. The set of possible operating
+  modes depends on the capabilities of every hardware so each device binding
+  documentation explains which values the regulator supports.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
@@ -34,6 +52,10 @@ Example:
                regulator-max-microvolt = <2500000>;
                regulator-always-on;
                vin-supply = <&vin>;
+
+               regulator-state-mem {
+                       regulator-on-in-suspend;
+               };
        };
 
 Regulator Consumers:
index 882455e9b36d52676a171e8988619c09048ad158..f9acbc1f3c6bdf0cebf3d21810f4ca5b284fab2b 100644 (file)
@@ -1,6 +1,7 @@
 SKY81452 voltage regulator
 
 Required properties:
+- regulator node named lout.
 - any required generic properties defined in regulator.txt
 
 Optional properties:
@@ -9,8 +10,9 @@ Optional properties:
 Example:
 
        regulator {
-               /* generic regulator properties */
-               regulator-name = "touch_en";
-               regulator-min-microvolt = <4500000>;
-               regulator-max-microvolt = <8000000>;
+               lout {
+                       regulator-name = "sky81452-lout";
+                       regulator-min-microvolt = <4500000>;
+                       regulator-max-microvolt = <8000000>;
+               };
        };
diff --git a/Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt b/Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt
new file mode 100644 (file)
index 0000000..54ae9f7
--- /dev/null
@@ -0,0 +1,42 @@
+STMicroelectronics STi family Sysconfig Picophy SoftReset Controller
+=============================================================================
+
+This binding describes a reset controller device that is used to enable and
+disable on-chip PicoPHY USB2 phy(s) using "softreset" control bits found in
+the STi family SoC system configuration registers.
+
+The actual action taken when softreset is asserted is hardware dependent.
+However, when asserted it may not be possible to access the hardware's
+registers and after an assert/deassert sequence the hardware's previous state
+may no longer be valid.
+
+Please refer to Documentation/devicetree/bindings/reset/reset.txt
+for common reset controller binding usage.
+
+Required properties:
+- compatible: Should be "st,stih407-picophyreset"
+- #reset-cells: 1, see below
+
+Example:
+
+       picophyreset: picophyreset-controller {
+               compatible = "st,stih407-picophyreset";
+               #reset-cells = <1>;
+       };
+
+Specifying picophyreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the picophyreset device node and an
+index specifying which channel to use, as described in
+Documentation/devicetree/bindings/reset/reset.txt.
+
+Example:
+
+       usb2_picophy0: usbpicophy@0 {
+               resets = <&picophyreset STIH407_PICOPHY0_RESET>;
+       };
+
+Macro definitions for the supported reset channels can be found in:
+include/dt-bindings/reset-controller/stih407-resets.h
diff --git a/Documentation/devicetree/bindings/rtc/atmel,at91sam9-rtc.txt b/Documentation/devicetree/bindings/rtc/atmel,at91sam9-rtc.txt
new file mode 100644 (file)
index 0000000..6ae79d1
--- /dev/null
@@ -0,0 +1,23 @@
+Atmel AT91SAM9260 Real Time Timer
+
+Required properties:
+- compatible: should be: "atmel,at91sam9260-rtt"
+- reg: should encode the memory region of the RTT controller
+- interrupts: rtt alarm/event interrupt
+- clocks: should contain the 32 KHz slow clk that will drive the RTT block.
+- atmel,rtt-rtc-time-reg: should encode the GPBR register used to store
+       the time base when the RTT is used as an RTC.
+       The first cell should point to the GPBR node and the second one
+       encode the offset within the GPBR block (or in other words, the
+       GPBR register used to store the time base).
+
+
+Example:
+
+rtt@fffffd20 {
+       compatible = "atmel,at91sam9260-rtt";
+       reg = <0xfffffd20 0x10>;
+       interrupts = <1 4 7>;
+       clocks = <&clk32k>;
+       atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
+};
index 955df60a118c5465b9884369db48533ba17af121..d556dcb8816bd9537e2359f9e4e365ec873283d2 100644 (file)
@@ -7,10 +7,20 @@ Required properties:
 
 - clocks : the clock provider of SYS_MCLK
 
+- VDDA-supply : the regulator provider of VDDA
+
+- VDDIO-supply: the regulator provider of VDDIO
+
+Optional properties:
+
+- VDDD-supply : the regulator provider of VDDD
+
 Example:
 
 codec: sgtl5000@0a {
        compatible = "fsl,sgtl5000";
        reg = <0x0a>;
        clocks = <&clks 150>;
+       VDDA-supply = <&reg_3p3v>;
+       VDDIO-supply = <&reg_3p3v>;
 };
index 042a0273b8bab819ac77e22d0274805c428aad52..b7ba01ad1426cfdb61ede7e68860087df4606a86 100644 (file)
@@ -12,6 +12,9 @@ I. For patch submitters
 
        devicetree@vger.kernel.org
 
+  3) The Documentation/ portion of the patch should come in the series before
+     the code implementing the binding.
+
 II. For kernel maintainers
 
   1) If you aren't comfortable reviewing a given binding, reply to it and ask
index 1f0f67234a917bae606b17ad2432e45d7d171895..3c67bd50aa104ee152ea22132c377dcd2e6d3673 100644 (file)
@@ -1,7 +1,10 @@
 * Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
 
 Required properties:
-- compatible : "fsl,imx6q-thermal"
+- compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX.
+  i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
+  when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature
+  is higher than panic threshold, system will auto reboot by SRC module.
 - fsl,tempmon : phandle pointer to system controller that contains TEMPMON
   control registers, e.g. ANATOP on imx6q.
 - fsl,tempmon-data : phandle pointer to fuse controller that contains TEMPMON
index 0ef00be44b0137e7435c13c57c379654937b4592..43404b197933262859e79686d5a8fa25ab12e5f3 100644 (file)
@@ -7,7 +7,10 @@ Required properties:
                            - "renesas,thermal-r8a73a4" (R-Mobile AP6)
                            - "renesas,thermal-r8a7779" (R-Car H1)
                            - "renesas,thermal-r8a7790" (R-Car H2)
-                           - "renesas,thermal-r8a7791" (R-Car M2)
+                           - "renesas,thermal-r8a7791" (R-Car M2-W)
+                           - "renesas,thermal-r8a7792" (R-Car V2H)
+                           - "renesas,thermal-r8a7793" (R-Car M2-N)
+                           - "renesas,thermal-r8a7794" (R-Car E2)
 - reg                  : Address range of the thermal registers.
                          The 1st reg will be recognized as common register
                          if it has "interrupts".
index f455182b108653b058564c517f72d6bf4d4d83f8..e9c78ce880e600c3413a4d96f5cc39d72f4d59ff 100644 (file)
@@ -2,8 +2,10 @@ Marvell Armada 370 and Armada XP Timers
 ---------------------------------------
 
 Required properties:
-- compatible: Should be either "marvell,armada-370-timer" or
-  "marvell,armada-xp-timer" as appropriate.
+- compatible: Should be one of the following
+              "marvell,armada-370-timer",
+             "marvell,armada-375-timer",
+             "marvell,armada-xp-timer".
 - interrupts: Should contain the list of Global Timer interrupts and
   then local timer interrupts
 - reg: Should contain location and length for timers register. First
@@ -13,7 +15,8 @@ Required properties:
 Clocks required for compatible = "marvell,armada-370-timer":
 - clocks : Must contain a single entry describing the clock input
 
-Clocks required for compatible = "marvell,armada-xp-timer":
+Clocks required for compatibles = "marvell,armada-xp-timer",
+                                 "marvell,armada-375-timer":
 - clocks : Must contain an entry for each entry in clock-names.
 - clock-names : Must include the following entries:
   "nbclk" (L2/coherency fabric clock),
index d9a8d5af1a21270ff2e79810c86079bac0757df2..ba0a34d97eb80261b98df15737110c614fbd28c8 100644 (file)
@@ -1,4 +1,4 @@
-* Renesas R-Car Multi-Function Timer Pulse Unit 2 (MTU2)
+* Renesas Multi-Function Timer Pulse Unit 2 (MTU2)
 
 The MTU2 is a multi-purpose, multi-channel timer/counter with configurable
 clock inputs and programmable compare match.
index 7db89fb2544411b5418caf94cb74fc16a648c188..cd5f20bf2582e742c426018d91d31c652767d7fd 100644 (file)
@@ -1,4 +1,4 @@
-* Renesas R-Car Timer Unit (TMU)
+* Renesas R-Mobile/R-Car Timer Unit (TMU)
 
 The TMU is a 32-bit timer/counter with configurable clock inputs and
 programmable compare match.
@@ -9,6 +9,8 @@ are independent. The TMU hardware supports up to three channels.
 Required Properties:
 
   - compatible: must contain one or more of the following:
+    - "renesas,tmu-r8a7740" for the r8a7740 TMU
+    - "renesas,tmu-r8a7778" for the r8a7778 TMU
     - "renesas,tmu-r8a7779" for the r8a7779 TMU
     - "renesas,tmu" for any TMU.
       This is a fallback for the above renesas,tmu-* entries
index 723999d737445274728bedde163d3534ca62339c..0d354625299c5a72bb181cc52fb66e807e9a55b0 100644 (file)
@@ -34,12 +34,14 @@ chipidea    Chipidea, Inc
 chrp   Common Hardware Reference Platform
 chunghwa       Chunghwa Picture Tubes Ltd.
 cirrus Cirrus Logic, Inc.
+cnm    Chips&Media, Inc.
 cortina        Cortina Systems, Inc.
 crystalfontz   Crystalfontz America, Inc.
 dallas Maxim Integrated Products (formerly Dallas Semiconductor)
 davicom        DAVICOM Semiconductor, Inc.
 denx   Denx Software Engineering
 digi   Digi International Inc.
+digilent       Diglent, Inc.
 dlg    Dialog Semiconductor
 dlink  D-Link Corporation
 dmo    Data Modul AG
@@ -77,6 +79,7 @@ innolux       Innolux Corporation
 intel  Intel Corporation
 intercontrol   Inter Control Group
 isee   ISEE 2007 S.L.
+isil    Intersil (deprecated, use isl)
 isl    Intersil
 karo   Ka-Ro electronics GmbH
 keymile        Keymile GmbH
@@ -90,8 +93,10 @@ lltc Linear Technology Corporation
 marvell        Marvell Technology Group Ltd.
 maxim  Maxim Integrated Products
 mediatek       MediaTek Inc.
+merrii Merrii Technology Co., Ltd.
 micrel Micrel Inc.
 microchip      Microchip Technology Inc.
+micron Micron Technology Inc.
 mitsubishi     Mitsubishi Electric Corporation
 mosaixtech     Mosaix Technologies, Inc.
 moxa   Moxa
@@ -127,6 +132,7 @@ renesas     Renesas Electronics Corporation
 ricoh  Ricoh Co. Ltd.
 rockchip       Fuzhou Rockchip Electronics Co., Ltd
 samsung        Samsung Semiconductor
+sandisk        Sandisk Corporation
 sbs    Smart Battery System
 schindler      Schindler
 seagate        Seagate Technology PLC
@@ -138,7 +144,7 @@ silergy     Silergy Corp.
 sirf   SiRF Technology, Inc.
 sitronix       Sitronix Technology Corporation
 smsc   Standard Microsystems Corporation
-snps   Synopsys, Inc.
+snps   Synopsys, Inc.
 solidrun       SolidRun
 sony   Sony Corporation
 spansion       Spansion Inc.
@@ -146,6 +152,7 @@ st  STMicroelectronics
 ste    ST-Ericsson
 stericsson     ST-Ericsson
 synology       Synology, Inc.
+tbs    TBS Technologies
 thine  THine Electronics, Inc.
 ti     Texas Instruments
 tlm    Trusted Logic Mobility
diff --git a/Documentation/devicetree/bindings/w1/omap-hdq.txt b/Documentation/devicetree/bindings/w1/omap-hdq.txt
new file mode 100644 (file)
index 0000000..fef7947
--- /dev/null
@@ -0,0 +1,17 @@
+* OMAP HDQ One wire bus master controller
+
+Required properties:
+- compatible : should be "ti,omap3-1w"
+- reg : Address and length of the register set for the device
+- interrupts : interrupt line.
+- ti,hwmods : "hdq1w"
+
+Example:
+
+- From omap3.dtsi
+  hdqw1w: 1w@480b2000 {
+       compatible = "ti,omap3-1w";
+       reg = <0x480b2000 0x1000>;
+       interrupts = <58>;
+       ti,hwmods = "hdq1w";
+  };
diff --git a/Documentation/devicetree/bindings/watchdog/cadence-wdt.txt b/Documentation/devicetree/bindings/watchdog/cadence-wdt.txt
new file mode 100644 (file)
index 0000000..c3a36ee
--- /dev/null
@@ -0,0 +1,24 @@
+Zynq Watchdog Device Tree Bindings
+-------------------------------------------
+
+Required properties:
+- compatible           : Should be "cdns,wdt-r1p2".
+- clocks               : This is pclk (APB clock).
+- interrupts           : This is wd_irq - watchdog timeout interrupt.
+- interrupt-parent     : Must be core interrupt controller.
+
+Optional properties
+- reset-on-timeout     : If this property exists, then a reset is done
+                         when watchdog times out.
+- timeout-sec          : Watchdog timeout value (in seconds).
+
+Example:
+       watchdog@f8005000 {
+               compatible = "cdns,wdt-r1p2";
+               clocks = <&clkc 45>;
+               interrupt-parent = <&intc>;
+               interrupts = <0 9 1>;
+               reg = <0xf8005000 0x1000>;
+               reset-on-timeout;
+               timeout-sec = <10>;
+       };
index e52ba2da868ce120daf7348aa15cdda02fcc34af..8dab6fd024aa4edb889b880db02225e13cb44c61 100644 (file)
@@ -7,7 +7,8 @@ Required properties:
 
 Optional property:
 - big-endian: If present the watchdog device's registers are implemented
-  in big endian mode, otherwise in little mode.
+  in big endian mode, otherwise in native mode(same with CPU), for more
+  detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
 
 Examples:
 
index 97223fddb7bdd69ed28c3ec40ea0c2986fa0cf3c..858ed9221ac4d65d77ddc8537c2761995527af52 100644 (file)
@@ -17,6 +17,18 @@ For "marvell,armada-375-wdt" and "marvell,armada-380-wdt":
 - reg          : A third entry is mandatory and should contain the
                   shared mask/unmask RSTOUT address.
 
+Clocks required for compatibles = "marvell,orion-wdt",
+                                 "marvell,armada-370-wdt":
+- clocks : Must contain a single entry describing the clock input
+
+Clocks required for compatibles = "marvell,armada-xp-wdt"
+                                 "marvell,armada-375-wdt"
+                                 "marvell,armada-380-wdt":
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "nbclk" (L2/coherency fabric clock),
+  "fixed" (Reference 25 MHz fixed-clock).
+
 Optional properties:
 
 - interrupts   : Contains the IRQ for watchdog expiration
@@ -30,4 +42,5 @@ Example:
                interrupts = <3>;
                timeout-sec = <10>;
                status = "okay";
+               clocks = <&gate_clk 7>;
        };
diff --git a/Documentation/devicetree/bindings/watchdog/meson6-wdt.txt b/Documentation/devicetree/bindings/watchdog/meson6-wdt.txt
new file mode 100644 (file)
index 0000000..9200fc2
--- /dev/null
@@ -0,0 +1,13 @@
+Meson SoCs Watchdog timer
+
+Required properties:
+
+- compatible : should be "amlogic,meson6-wdt"
+- reg : Specifies base physical address and size of the registers.
+
+Example:
+
+wdt: watchdog@c1109900 {
+       compatible = "amlogic,meson6-wdt";
+       reg = <0xc1109900 0x8>;
+};
diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.txt b/Documentation/devicetree/bindings/watchdog/qcom-wdt.txt
new file mode 100644 (file)
index 0000000..4726924
--- /dev/null
@@ -0,0 +1,24 @@
+Qualcomm Krait Processor Sub-system (KPSS) Watchdog
+---------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+                       "qcom,kpss-wdt-msm8960"
+                       "qcom,kpss-wdt-apq8064"
+                       "qcom,kpss-wdt-ipq8064"
+
+- reg : shall contain base register location and length
+- clocks : shall contain the input clock
+
+Optional properties :
+- timeout-sec : shall contain the default watchdog timeout in seconds,
+                if unset, the default timeout is 30 seconds
+
+Example:
+       watchdog@208a038 {
+               compatible = "qcom,kpss-wdt-ipq8064";
+               reg = <0x0208a038 0x40>;
+               clocks = <&sleep_clk>;
+               timeout-sec = <10>;
+       };
index cfff37511aac0e3e1f3d42f6e9805c087a8bc286..8f3d96af81d70303e5bb449ecc366a85846bdd00 100644 (file)
@@ -9,6 +9,7 @@ Required properties:
        (a) "samsung,s3c2410-wdt" for Exynos4 and previous SoCs
        (b) "samsung,exynos5250-wdt" for Exynos5250
        (c) "samsung,exynos5420-wdt" for Exynos5420
+       (c) "samsung,exynos7-wdt" for Exynos7
 
 - reg : base physical address of the controller and length of memory mapped
        region.
index 94d93b1f8b530d44ab3855cdbbdc220fa8a8c60f..b30753cbf4311641ebd0ffe62735de05b452e77a 100644 (file)
@@ -67,6 +67,7 @@ prototypes:
                                struct file *, unsigned open_flag,
                                umode_t create_mode, int *opened);
        int (*tmpfile) (struct inode *, struct dentry *, umode_t);
+       int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
 
 locking rules:
        all may block
@@ -96,6 +97,7 @@ fiemap:               no
 update_time:   no
 atomic_open:   yes
 tmpfile:       no
+dentry_open:   no
 
        Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt
new file mode 100644 (file)
index 0000000..a27c950
--- /dev/null
@@ -0,0 +1,198 @@
+Written by: Neil Brown <neilb@suse.de>
+
+Overlay Filesystem
+==================
+
+This document describes a prototype for a new approach to providing
+overlay-filesystem functionality in Linux (sometimes referred to as
+union-filesystems).  An overlay-filesystem tries to present a
+filesystem which is the result over overlaying one filesystem on top
+of the other.
+
+The result will inevitably fail to look exactly like a normal
+filesystem for various technical reasons.  The expectation is that
+many use cases will be able to ignore these differences.
+
+This approach is 'hybrid' because the objects that appear in the
+filesystem do not all appear to belong to that filesystem.  In many
+cases an object accessed in the union will be indistinguishable
+from accessing the corresponding object from the original filesystem.
+This is most obvious from the 'st_dev' field returned by stat(2).
+
+While directories will report an st_dev from the overlay-filesystem,
+all non-directory objects will report an st_dev from the lower or
+upper filesystem that is providing the object.  Similarly st_ino will
+only be unique when combined with st_dev, and both of these can change
+over the lifetime of a non-directory object.  Many applications and
+tools ignore these values and will not be affected.
+
+Upper and Lower
+---------------
+
+An overlay filesystem combines two filesystems - an 'upper' filesystem
+and a 'lower' filesystem.  When a name exists in both filesystems, the
+object in the 'upper' filesystem is visible while the object in the
+'lower' filesystem is either hidden or, in the case of directories,
+merged with the 'upper' object.
+
+It would be more correct to refer to an upper and lower 'directory
+tree' rather than 'filesystem' as it is quite possible for both
+directory trees to be in the same filesystem and there is no
+requirement that the root of a filesystem be given for either upper or
+lower.
+
+The lower filesystem can be any filesystem supported by Linux and does
+not need to be writable.  The lower filesystem can even be another
+overlayfs.  The upper filesystem will normally be writable and if it
+is it must support the creation of trusted.* extended attributes, and
+must provide valid d_type in readdir responses, so NFS is not suitable.
+
+A read-only overlay of two read-only filesystems may use any
+filesystem type.
+
+Directories
+-----------
+
+Overlaying mainly involves directories.  If a given name appears in both
+upper and lower filesystems and refers to a non-directory in either,
+then the lower object is hidden - the name refers only to the upper
+object.
+
+Where both upper and lower objects are directories, a merged directory
+is formed.
+
+At mount time, the two directories given as mount options "lowerdir" and
+"upperdir" are combined into a merged directory:
+
+  mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\
+workdir=/work /merged
+
+The "workdir" needs to be an empty directory on the same filesystem
+as upperdir.
+
+Then whenever a lookup is requested in such a merged directory, the
+lookup is performed in each actual directory and the combined result
+is cached in the dentry belonging to the overlay filesystem.  If both
+actual lookups find directories, both are stored and a merged
+directory is created, otherwise only one is stored: the upper if it
+exists, else the lower.
+
+Only the lists of names from directories are merged.  Other content
+such as metadata and extended attributes are reported for the upper
+directory only.  These attributes of the lower directory are hidden.
+
+whiteouts and opaque directories
+--------------------------------
+
+In order to support rm and rmdir without changing the lower
+filesystem, an overlay filesystem needs to record in the upper filesystem
+that files have been removed.  This is done using whiteouts and opaque
+directories (non-directories are always opaque).
+
+A whiteout is created as a character device with 0/0 device number.
+When a whiteout is found in the upper level of a merged directory, any
+matching name in the lower level is ignored, and the whiteout itself
+is also hidden.
+
+A directory is made opaque by setting the xattr "trusted.overlay.opaque"
+to "y".  Where the upper filesystem contains an opaque directory, any
+directory in the lower filesystem with the same name is ignored.
+
+readdir
+-------
+
+When a 'readdir' request is made on a merged directory, the upper and
+lower directories are each read and the name lists merged in the
+obvious way (upper is read first, then lower - entries that already
+exist are not re-added).  This merged name list is cached in the
+'struct file' and so remains as long as the file is kept open.  If the
+directory is opened and read by two processes at the same time, they
+will each have separate caches.  A seekdir to the start of the
+directory (offset 0) followed by a readdir will cause the cache to be
+discarded and rebuilt.
+
+This means that changes to the merged directory do not appear while a
+directory is being read.  This is unlikely to be noticed by many
+programs.
+
+seek offsets are assigned sequentially when the directories are read.
+Thus if
+  - read part of a directory
+  - remember an offset, and close the directory
+  - re-open the directory some time later
+  - seek to the remembered offset
+
+there may be little correlation between the old and new locations in
+the list of filenames, particularly if anything has changed in the
+directory.
+
+Readdir on directories that are not merged is simply handled by the
+underlying directory (upper or lower).
+
+
+Non-directories
+---------------
+
+Objects that are not directories (files, symlinks, device-special
+files etc.) are presented either from the upper or lower filesystem as
+appropriate.  When a file in the lower filesystem is accessed in a way
+the requires write-access, such as opening for write access, changing
+some metadata etc., the file is first copied from the lower filesystem
+to the upper filesystem (copy_up).  Note that creating a hard-link
+also requires copy_up, though of course creation of a symlink does
+not.
+
+The copy_up may turn out to be unnecessary, for example if the file is
+opened for read-write but the data is not modified.
+
+The copy_up process first makes sure that the containing directory
+exists in the upper filesystem - creating it and any parents as
+necessary.  It then creates the object with the same metadata (owner,
+mode, mtime, symlink-target etc.) and then if the object is a file, the
+data is copied from the lower to the upper filesystem.  Finally any
+extended attributes are copied up.
+
+Once the copy_up is complete, the overlay filesystem simply
+provides direct access to the newly created file in the upper
+filesystem - future operations on the file are barely noticed by the
+overlay filesystem (though an operation on the name of the file such as
+rename or unlink will of course be noticed and handled).
+
+
+Non-standard behavior
+---------------------
+
+The copy_up operation essentially creates a new, identical file and
+moves it over to the old name.  The new file may be on a different
+filesystem, so both st_dev and st_ino of the file may change.
+
+Any open files referring to this inode will access the old data and
+metadata.  Similarly any file locks obtained before copy_up will not
+apply to the copied up file.
+
+On a file opened with O_RDONLY fchmod(2), fchown(2), futimesat(2) and
+fsetxattr(2) will fail with EROFS.
+
+If a file with multiple hard links is copied up, then this will
+"break" the link.  Changes will not be propagated to other names
+referring to the same inode.
+
+Symlinks in /proc/PID/ and /proc/PID/fd which point to a non-directory
+object in overlayfs will not contain valid absolute paths, only
+relative paths leading up to the filesystem's root.  This will be
+fixed in the future.
+
+Some operations are not atomic, for example a crash during copy_up or
+rename will leave the filesystem in an inconsistent state.  This will
+be addressed in the future.
+
+Changes to underlying filesystems
+---------------------------------
+
+Offline changes, when the overlay is not mounted, are allowed to either
+the upper or the lower trees.
+
+Changes to the underlying filesystems while part of a mounted overlay
+filesystem are not allowed.  If the underlying filesystem is changed,
+the behavior of the overlay is undefined, though it will not result in
+a crash or deadlock.
index fceff7c00a3c8eb48517cf72d9e9eb1fb3ecc750..20bf204426cad3a7854866e302ce22952e58d1a5 100644 (file)
@@ -364,6 +364,7 @@ struct inode_operations {
        int (*atomic_open)(struct inode *, struct dentry *, struct file *,
                        unsigned open_flag, umode_t create_mode, int *opened);
        int (*tmpfile) (struct inode *, struct dentry *, umode_t);
+       int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -696,6 +697,12 @@ struct address_space_operations {
        but instead uses bmap to find out where the blocks in the file
        are and uses those addresses directly.
 
+  dentry_open: *WARNING: probably going away soon, do not use!* This is an
+       alternative to f_op->open(), the difference is that this method may open
+       a file not necessarily originating from the same filesystem as the one
+       i_op->open() was called on.  It may be useful for stacking filesystems
+       which want to allow native I/O directly on underlying files.
+
 
   invalidatepage: If a page has PagePrivate set, then invalidatepage
         will be called when part or all of the page is to be removed
index c6a5ff1b4641a6659b7310d74937855a215c4c9d..67691a0aa41db82387369957de586bd4a6a2c6df 100644 (file)
@@ -53,6 +53,11 @@ Supported chips:
                http://www.ti.com/product/tmp75
                http://www.ti.com/product/tmp175
                http://www.ti.com/product/tmp275
+  * NXP LM75B
+    Prefix: 'lm75b'
+    Addresses scanned: none
+    Datasheet: Publicly available at the NXP website
+               http://www.nxp.com/documents/data_sheet/LM75B.pdf
 
 Author: Frodo Looijaard <frodol@dds.nl>
 
index a0e95ddfd3725eee7fdc57570b402c65da9defc1..32b777ef224c2df1dd3bc76d3278fb92977ab087 100644 (file)
@@ -2,6 +2,10 @@ Kernel driver lm95234
 =====================
 
 Supported chips:
+  * National Semiconductor / Texas Instruments LM95233
+    Addresses scanned: I2C 0x18, 0x2a, 0x2b
+    Datasheet: Publicly available at the Texas Instruments website
+               http://www.ti.com/product/lm95233
   * National Semiconductor / Texas Instruments LM95234
     Addresses scanned: I2C 0x18, 0x4d, 0x4e
     Datasheet: Publicly available at the Texas Instruments website
@@ -13,11 +17,12 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-LM95234 is an 11-bit digital temperature sensor with a 2-wire System Management
-Bus (SMBus) interface and TrueTherm technology that can very accurately monitor
-the temperature of four remote diodes as well as its own temperature.
-The four remote diodes can be external devices such as microprocessors,
-graphics processors or diode-connected 2N3904s. The LM95234's TruTherm
+LM95233 and LM95234 are 11-bit digital temperature sensors with a 2-wire
+System Management Bus (SMBus) interface and TrueTherm technology
+that can very accurately monitor the temperature of two (LM95233)
+or four (LM95234) remote diodes as well as its own temperature.
+The remote diodes can be external devices such as microprocessors,
+graphics processors or diode-connected 2N3904s. The chip's TruTherm
 beta compensation technology allows sensing of 90 nm or 65 nm process
 thermal diodes accurately.
 
index 77eaf2812d25d71009e545de8716acfd2bc93542..d755901f58c479689ba402a2844c71e2bb267839 100644 (file)
@@ -2,10 +2,14 @@ Kernel driver lm95245
 ==================
 
 Supported chips:
-  * National Semiconductor LM95245
+  * TI LM95235
+    Addresses scanned: I2C 0x18, 0x29, 0x4c
+    Datasheet: Publicly available at the TI website
+               http://www.ti.com/lit/ds/symlink/lm95235.pdf
+  * TI / National Semiconductor LM95245
     Addresses scanned: I2C 0x18, 0x19, 0x29, 0x4c, 0x4d
-    Datasheet: Publicly available at the National Semiconductor website
-               http://www.national.com/mpf/LM/LM95245.html
+    Datasheet: Publicly available at the TI website
+               http://www.ti.com/lit/ds/symlink/lm95245.pdf
 
 
 Author: Alexander Stein <alexander.stein@systec-electronic.com>
@@ -13,10 +17,10 @@ Author: Alexander Stein <alexander.stein@systec-electronic.com>
 Description
 -----------
 
-The LM95245 is an 11-bit digital temperature sensor with a 2-wire System
+LM95235 and LM95245 are 11-bit digital temperature sensors with a 2-wire System
 Management Bus (SMBus) interface and TruTherm technology that can monitor
 the temperature of a remote diode as well as its own temperature.
-The LM95245 can be used to very accurately monitor the temperature of
+The chips can be used to very accurately monitor the temperature of
 external devices such as microprocessors.
 
 All temperature values are given in millidegrees Celsius. Local temperature
index 4e9ef60e8c6cf2751a6da67c2a367be4f1fe9994..f0dd3d2fec96da61b56d010c19a83755d320f52f 100644 (file)
@@ -8,11 +8,15 @@ Kernel driver NCT6775
 =====================
 
 Supported chips:
+  * Nuvoton NCT6102D/NCT6104D/NCT6106D
+    Prefix: 'nct6106'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from the Nuvoton web site
   * Nuvoton NCT5572D/NCT6771F/NCT6772F/NCT6775F/W83677HG-I
     Prefix: 'nct6775'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: Available from Nuvoton upon request
-  * Nuvoton NCT5577D/NCT6776D/NCT6776F
+  * Nuvoton NCT5573D/NCT5577D/NCT6776D/NCT6776F
     Prefix: 'nct6776'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: Available from Nuvoton upon request
@@ -20,6 +24,14 @@ Supported chips:
     Prefix: 'nct6779'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6791D
+    Prefix: 'nct6791'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6792D
+    Prefix: 'nct6792'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
 
 Authors:
         Guenter Roeck <linux@roeck-us.net>
diff --git a/Documentation/hwmon/nct7802 b/Documentation/hwmon/nct7802
new file mode 100644 (file)
index 0000000..2e00f5e
--- /dev/null
@@ -0,0 +1,32 @@
+Kernel driver nct7802
+=====================
+
+Supported chips:
+  * Nuvoton NCT7802Y
+    Prefix: 'nct7802'
+    Addresses scanned: I2C 0x28..0x2f
+    Datasheet: Available from Nuvoton web site
+
+Authors:
+        Guenter Roeck <linux@roeck-us.net>
+
+Description
+-----------
+
+This driver implements support for the Nuvoton NCT7802Y hardware monitoring
+chip. NCT7802Y supports 6 temperature sensors, 5 voltage sensors, and 3 fan
+speed sensors.
+
+The chip also supports intelligent fan speed control. This functionality is
+not currently supported by the driver.
+
+Tested Boards and BIOS Versions
+-------------------------------
+
+The driver has been reported to work with the following boards and
+BIOS versions.
+
+Board                  BIOS version
+---------------------------------------------------------------
+Kontron COMe-bSC2      CHR2E934.001.GGO
+Kontron COMe-bIP2      CCR2E212
index f91e3fa7e5ec5fe0df6515203d62a2f6d844ff9f..8eb88e974055f62f2c9226bcd6d98b3e8e5ea908 100644 (file)
@@ -18,6 +18,10 @@ Supported chips:
     Prefix: 'tmp432'
     Addresses scanned: I2C 0x4c, 0x4d
     Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp432.html
+  * Texas Instruments TMP435
+    Prefix: 'tmp435'
+    Addresses scanned: I2C 0x37, 0x48 - 0x4f
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html
 
 Authors:
          Hans de Goede <hdegoede@redhat.com>
@@ -27,8 +31,8 @@ Description
 -----------
 
 This driver implements support for Texas Instruments TMP401, TMP411,
-TMP431, and TMP432 chips. These chips implement one or two remote and
-one local temperature sensors. Temperature is measured in degrees
+TMP431, TMP432 and TMP435 chips. These chips implement one or two remote
+and one local temperature sensors. Temperature is measured in degrees
 Celsius. Resolution of the remote sensor is 0.0625 degree. Local
 sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not
 supported by the driver so far, so using the default resolution of 0.5
index e1ae127ed099d4934e1d7fb95f1a8ba819c1da9b..1ec0db7879d310dd3525eee439bc291a3e595c02 100644 (file)
@@ -38,22 +38,38 @@ Contents
         7.2.1 Status packet
         7.2.2 Head packet
         7.2.3 Motion packet
+ 8. Trackpoint (for Hardware version 3 and 4)
+    8.1 Registers
+    8.2 Native relative mode 6 byte packet format
+        8.2.1 Status Packet
 
 
 
 1. Introduction
    ~~~~~~~~~~~~
 
-Currently the Linux Elantech touchpad driver is aware of two different
-hardware versions unimaginatively called version 1 and version 2. Version 1
-is found in "older" laptops and uses 4 bytes per packet. Version 2 seems to
-be introduced with the EeePC and uses 6 bytes per packet, and provides
-additional features such as position of two fingers, and width of the touch.
+Currently the Linux Elantech touchpad driver is aware of four different
+hardware versions unimaginatively called version 1,version 2, version 3
+and version 4. Version 1 is found in "older" laptops and uses 4 bytes per
+packet. Version 2 seems to be introduced with the EeePC and uses 6 bytes
+per packet, and provides additional features such as position of two fingers,
+and width of the touch.  Hardware version 3 uses 6 bytes per packet (and
+for 2 fingers the concatenation of two 6 bytes packets) and allows tracking
+of up to 3 fingers. Hardware version 4 uses 6 bytes per packet, and can
+combine a status packet with multiple head or motion packets. Hardware version
+4 allows tracking up to 5 fingers.
+
+Some Hardware version 3 and version 4 also have a trackpoint which uses a
+separate packet format. It is also 6 bytes per packet.
 
 The driver tries to support both hardware versions and should be compatible
 with the Xorg Synaptics touchpad driver and its graphical configuration
 utilities.
 
+Note that a mouse button is also associated with either the touchpad or the
+trackpoint when a trackpoint is available.  Disabling the Touchpad in xorg
+(TouchPadOff=0) will also disable the buttons associated with the touchpad.
+
 Additionally the operation of the touchpad can be altered by adjusting the
 contents of some of its internal registers. These registers are represented
 by the driver as sysfs entries under /sys/bus/serio/drivers/psmouse/serio?
@@ -78,7 +94,7 @@ completeness sake.
 2. Extra knobs
    ~~~~~~~~~~~
 
-Currently the Linux Elantech touchpad driver provides two extra knobs under
+Currently the Linux Elantech touchpad driver provides three extra knobs under
 /sys/bus/serio/drivers/psmouse/serio? for the user.
 
 * debug
@@ -112,6 +128,20 @@ Currently the Linux Elantech touchpad driver provides two extra knobs under
    data consistency checking can be done. For now checking is disabled by
    default. Currently even turning it on will do nothing.
 
+* crc_enabled
+
+   Sets crc_enabled to 0/1. The name "crc_enabled" is the official name of
+   this integrity check, even though it is not an actual cyclic redundancy
+   check.
+
+   Depending on the state of crc_enabled, certain basic data integrity
+   verification is done by the driver on hardware version 3 and 4. The
+   driver will reject any packet that appears corrupted. Using this knob,
+   The state of crc_enabled can be altered with this knob.
+
+   Reading the crc_enabled value will show the active value. Echoing
+   "0" or "1" to this file will set the state to "0" or "1".
+
 /////////////////////////////////////////////////////////////////////////////
 
 3. Differentiating hardware versions
@@ -746,3 +776,42 @@ byte 5:
 
         byte 0 ~ 2 for one finger
         byte 3 ~ 5 for another
+
+
+8. Trackpoint (for Hardware version 3 and 4)
+   =========================================
+8.1 Registers
+    ~~~~~~~~~
+No special registers have been identified.
+
+8.2 Native relative mode 6 byte packet format
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+8.2.1 Status Packet
+      ~~~~~~~~~~~~~
+
+byte 0:
+   bit   7   6   5   4   3   2   1   0
+         0   0  sx  sy   0   M   R   L
+byte 1:
+   bit   7   6   5   4   3   2   1   0
+       ~sx   0   0   0   0   0   0   0
+byte 2:
+   bit   7   6   5   4   3   2   1   0
+       ~sy   0   0   0   0   0   0   0
+byte 3:
+   bit   7   6   5   4   3   2   1   0
+         0   0 ~sy ~sx   0   1   1   0
+byte 4:
+   bit   7   6   5   4   3   2   1   0
+        x7  x6  x5  x4  x3  x2  x1  x0
+byte 5:
+   bit   7   6   5   4   3   2   1   0
+        y7  y6  y5  y4  y3  y2  y1  y0
+
+
+         x and y are written in two's complement spread
+             over 9 bits with sx/sy the relative top bit and
+             x7..x0 and y7..y0 the lower bits.
+        ~sx is the inverse of sx, ~sy is the inverse of sy.
+         The sign of y is opposite to what the input driver
+             expects for a relative movement
index 7dbe5ec9d9cd08afac13797e2adac291fb703eec..838f3776c9249e2cd3d5e17c966f0fb4acdad796 100644 (file)
@@ -1015,10 +1015,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Format: {"off" | "on" | "skip[mbr]"}
 
        efi=            [EFI]
-                       Format: { "old_map" }
+                       Format: { "old_map", "nochunk", "noruntime" }
                        old_map [X86-64]: switch to the old ioremap-based EFI
                        runtime services mapping. 32-bit still uses this one by
                        default.
+                       nochunk: disable reading files in "chunks" in the EFI
+                       boot stub, as chunking can cause problems with some
+                       firmware implementations.
+                       noruntime : disable EFI runtime services support
 
        efi_no_storage_paranoia [EFI; X86]
                        Using this parameter you can use more than 50% of
@@ -1260,7 +1264,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        i8042.noloop    [HW] Disable the AUX Loopback command while probing
                             for the AUX port
        i8042.nomux     [HW] Don't check presence of an active multiplexing
-                            controller. Default: true.
+                            controller
        i8042.nopnp     [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
                             controllers
        i8042.notimeout [HW] Ignore timeout condition signalled by controller
@@ -1303,6 +1307,18 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        .cdrom .chs .ignore_cable are additional options
                        See Documentation/ide/ide.txt.
 
+       ide-generic.probe-mask= [HW] (E)IDE subsystem
+                       Format: <int>
+                       Probe mask for legacy ISA IDE ports.  Depending on
+                       platform up to 6 ports are supported, enabled by
+                       setting corresponding bits in the mask to 1.  The
+                       default value is 0x0, which has a special meaning.
+                       On systems that have PCI, it triggers scanning the
+                       PCI bus for the first and the second port, which
+                       are then probed.  On systems without PCI the value
+                       of 0x0 enables probing the two first ports as if it
+                       was 0x3.
+
        ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
                        Claim all unknown PCI IDE storage controllers.
 
@@ -1583,6 +1599,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        kmemleak=       [KNL] Boot-time kmemleak enable/disable
                        Valid arguments: on, off
                        Default: on
+                       Built with CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y,
+                       the default is off.
 
        kmemcheck=      [X86] Boot-time kmemcheck enable/disable/one-shot mode
                        Valid arguments: 0, 1, 2
@@ -2232,7 +2250,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        nodsp           [SH] Disable hardware DSP at boot time.
 
-       noefi           [X86] Disable EFI runtime services support.
+       noefi           Disable EFI runtime services support.
 
        noexec          [IA-64]
 
@@ -2922,6 +2940,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        quiescent states.  Units are jiffies, minimum
                        value is one, and maximum value is HZ.
 
+       rcutree.kthread_prio=    [KNL,BOOT]
+                       Set the SCHED_FIFO priority of the RCU
+                       per-CPU kthreads (rcuc/N). This value is also
+                       used for the priority of the RCU boost threads
+                       (rcub/N). Valid values are 1-99 and the default
+                       is 1 (the least-favored priority).
+
        rcutree.rcu_nocb_leader_stride= [KNL]
                        Set the number of NOCB kthread groups, which
                        defaults to the square root of the number of
@@ -3071,6 +3096,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        messages.  Disable with a value less than or equal
                        to zero.
 
+       rcupdate.rcu_self_test= [KNL]
+                       Run the RCU early boot self tests
+
+       rcupdate.rcu_self_test_bh= [KNL]
+                       Run the RCU bh early boot self tests
+
+       rcupdate.rcu_self_test_sched= [KNL]
+                       Run the RCU sched early boot self tests
+
        rdinit=         [KNL]
                        Format: <full_path>
                        Run specified binary instead of /init from the ramdisk,
@@ -3465,6 +3499,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        e.g. base its process migration decisions on it.
                        Default is on.
 
+       topology_updates= [KNL, PPC, NUMA]
+                       Format: {off}
+                       Specify if the kernel should ignore (off)
+                       topology updates sent by the hypervisor to this
+                       LPAR.
+
        tp720=          [HW,PS2]
 
        tpm_suspend_pcr=[HW,TPM]
@@ -3597,7 +3637,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        usb-storage.delay_use=
                        [UMS] The delay in seconds before a new device is
-                       scanned for Logical Units (default 5).
+                       scanned for Logical Units (default 1).
 
        usb-storage.quirks=
                        [UMS] A list of quirks entries to supplement or
index f4f033c8d856e44ac85ba655da2348230acd8c4e..45e777f4e41de846eb485b579d0e934e0a512d97 100644 (file)
@@ -62,6 +62,10 @@ Memory may be allocated or freed before kmemleak is initialised and
 these actions are stored in an early log buffer. The size of this buffer
 is configured via the CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE option.
 
+If CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF are enabled, the kmemleak is
+disabled by default. Passing "kmemleak=on" on the kernel command
+line enables the function. 
+
 Basic Algorithm
 ---------------
 
diff --git a/Documentation/locking/lglock.txt b/Documentation/locking/lglock.txt
new file mode 100644 (file)
index 0000000..a6971e3
--- /dev/null
@@ -0,0 +1,166 @@
+lglock - local/global locks for mostly local access patterns
+------------------------------------------------------------
+
+Origin: Nick Piggin's VFS scalability series introduced during
+       2.6.35++ [1] [2]
+Location: kernel/locking/lglock.c
+       include/linux/lglock.h
+Users: currently only the VFS and stop_machine related code
+
+Design Goal:
+------------
+
+Improve scalability of globally used large data sets that are
+distributed over all CPUs as per_cpu elements.
+
+To manage global data structures that are partitioned over all CPUs
+as per_cpu elements but can be mostly handled by CPU local actions
+lglock will be used where the majority of accesses are cpu local
+reading and occasional cpu local writing with very infrequent
+global write access.
+
+
+* deal with things locally whenever possible
+       - very fast access to the local per_cpu data
+       - reasonably fast access to specific per_cpu data on a different
+         CPU
+* while making global action possible when needed
+       - by expensive access to all CPUs locks - effectively
+         resulting in a globally visible critical section.
+
+Design:
+-------
+
+Basically it is an array of per_cpu spinlocks with the
+lg_local_lock/unlock accessing the local CPUs lock object and the
+lg_local_lock_cpu/unlock_cpu accessing a remote CPUs lock object
+the lg_local_lock has to disable preemption as migration protection so
+that the reference to the local CPUs lock does not go out of scope.
+Due to the lg_local_lock/unlock only touching cpu-local resources it
+is fast. Taking the local lock on a different CPU will be more
+expensive but still relatively cheap.
+
+One can relax the migration constraints by acquiring the current
+CPUs lock with lg_local_lock_cpu, remember the cpu, and release that
+lock at the end of the critical section even if migrated. This should
+give most of the performance benefits without inhibiting migration
+though needs careful considerations for nesting of lglocks and
+consideration of deadlocks with lg_global_lock.
+
+The lg_global_lock/unlock locks all underlying spinlocks of all
+possible CPUs (including those off-line). The preemption disable/enable
+are needed in the non-RT kernels to prevent deadlocks like:
+
+                     on cpu 1
+
+              task A          task B
+         lg_global_lock
+           got cpu 0 lock
+                 <<<< preempt <<<<
+                         lg_local_lock_cpu for cpu 0
+                           spin on cpu 0 lock
+
+On -RT this deadlock scenario is resolved by the arch_spin_locks in the
+lglocks being replaced by rt_mutexes which resolve the above deadlock
+by boosting the lock-holder.
+
+
+Implementation:
+---------------
+
+The initial lglock implementation from Nick Piggin used some complex
+macros to generate the lglock/brlock in lglock.h - they were later
+turned into a set of functions by Andi Kleen [7]. The change to functions
+was motivated by the presence of multiple lock users and also by them
+being easier to maintain than the generating macros. This change to
+functions is also the basis to eliminated the restriction of not
+being initializeable in kernel modules (the remaining problem is that
+locks are not explicitly initialized - see lockdep-design.txt)
+
+Declaration and initialization:
+-------------------------------
+
+  #include <linux/lglock.h>
+
+  DEFINE_LGLOCK(name)
+  or:
+  DEFINE_STATIC_LGLOCK(name);
+
+  lg_lock_init(&name, "lockdep_name_string");
+
+  on UP this is mapped to DEFINE_SPINLOCK(name) in both cases, note
+  also that as of 3.18-rc6 all declaration in use are of the _STATIC_
+  variant (and it seems that the non-static was never in use).
+  lg_lock_init is initializing the lockdep map only.
+
+Usage:
+------
+
+From the locking semantics it is a spinlock. It could be called a
+locality aware spinlock. lg_local_* behaves like a per_cpu
+spinlock and lg_global_* like a global spinlock.
+No surprises in the API.
+
+  lg_local_lock(*lglock);
+     access to protected per_cpu object on this CPU
+  lg_local_unlock(*lglock);
+
+  lg_local_lock_cpu(*lglock, cpu);
+     access to protected per_cpu object on other CPU cpu
+  lg_local_unlock_cpu(*lglock, cpu);
+
+  lg_global_lock(*lglock);
+     access all protected per_cpu objects on all CPUs
+  lg_global_unlock(*lglock);
+
+  There are no _trylock variants of the lglocks.
+
+Note that the lg_global_lock/unlock has to iterate over all possible
+CPUs rather than the actually present CPUs or a CPU could go off-line
+with a held lock [4] and that makes it very expensive. A discussion on
+these issues can be found at [5]
+
+Constraints:
+------------
+
+  * currently the declaration of lglocks in kernel modules is not
+    possible, though this should be doable with little change.
+  * lglocks are not recursive.
+  * suitable for code that can do most operations on the CPU local
+    data and will very rarely need the global lock
+  * lg_global_lock/unlock is *very* expensive and does not scale
+  * on UP systems all lg_* primitives are simply spinlocks
+  * in PREEMPT_RT the spinlock becomes an rt-mutex and can sleep but
+    does not change the tasks state while sleeping [6].
+  * in PREEMPT_RT the preempt_disable/enable in lg_local_lock/unlock
+    is downgraded to a migrate_disable/enable, the other
+    preempt_disable/enable are downgraded to barriers [6].
+    The deadlock noted for non-RT above is resolved due to rt_mutexes
+    boosting the lock-holder in this case which arch_spin_locks do
+    not do.
+
+lglocks were designed for very specific problems in the VFS and probably
+only are the right answer in these corner cases. Any new user that looks
+at lglocks probably wants to look at the seqlock and RCU alternatives as
+her first choice. There are also efforts to resolve the RCU issues that
+currently prevent using RCU in place of view remaining lglocks.
+
+Note on brlock history:
+-----------------------
+
+The 'Big Reader' read-write spinlocks were originally introduced by
+Ingo Molnar in 2000 (2.4/2.5 kernel series) and removed in 2003. They
+later were introduced by the VFS scalability patch set in 2.6 series
+again as the "big reader lock" brlock [2] variant of lglock which has
+been replaced by seqlock primitives or by RCU based primitives in the
+3.13 kernel series as was suggested in [3] in 2003. The brlock was
+entirely removed in the 3.13 kernel series.
+
+Link: 1 http://lkml.org/lkml/2010/8/2/81
+Link: 2 http://lwn.net/Articles/401738/
+Link: 3 http://lkml.org/lkml/2003/3/9/205
+Link: 4 https://lkml.org/lkml/2011/8/24/185
+Link: 5 http://lkml.org/lkml/2011/12/18/189
+Link: 6 https://www.kernel.org/pub/linux/kernel/projects/rt/
+        patch series - lglocks-rt.patch.patch
+Link: 7 http://lkml.org/lkml/2012/3/5/26
diff --git a/Documentation/mailbox.txt b/Documentation/mailbox.txt
new file mode 100644 (file)
index 0000000..60f43ff
--- /dev/null
@@ -0,0 +1,122 @@
+               The Common Mailbox Framework
+               Jassi Brar <jaswinder.singh@linaro.org>
+
+ This document aims to help developers write client and controller
+drivers for the API. But before we start, let us note that the
+client (especially) and controller drivers are likely going to be
+very platform specific because the remote firmware is likely to be
+proprietary and implement non-standard protocol. So even if two
+platforms employ, say, PL320 controller, the client drivers can't
+be shared across them. Even the PL320 driver might need to accommodate
+some platform specific quirks. So the API is meant mainly to avoid
+similar copies of code written for each platform. Having said that,
+nothing prevents the remote f/w to also be Linux based and use the
+same api there. However none of that helps us locally because we only
+ever deal at client's protocol level.
+ Some of the choices made during implementation are the result of this
+peculiarity of this "common" framework.
+
+
+
+       Part 1 - Controller Driver (See include/linux/mailbox_controller.h)
+
+ Allocate mbox_controller and the array of mbox_chan.
+Populate mbox_chan_ops, except peek_data() all are mandatory.
+The controller driver might know a message has been consumed
+by the remote by getting an IRQ or polling some hardware flag
+or it can never know (the client knows by way of the protocol).
+The method in order of preference is IRQ -> Poll -> None, which
+the controller driver should set via 'txdone_irq' or 'txdone_poll'
+or neither.
+
+
+       Part 2 - Client Driver (See include/linux/mailbox_client.h)
+
+ The client might want to operate in blocking mode (synchronously
+send a message through before returning) or non-blocking/async mode (submit
+a message and a callback function to the API and return immediately).
+
+
+struct demo_client {
+       struct mbox_client cl;
+       struct mbox_chan *mbox;
+       struct completion c;
+       bool async;
+       /* ... */
+};
+
+/*
+ * This is the handler for data received from remote. The behaviour is purely
+ * dependent upon the protocol. This is just an example.
+ */
+static void message_from_remote(struct mbox_client *cl, void *mssg)
+{
+       struct demo_client *dc = container_of(mbox_client,
+                                               struct demo_client, cl);
+       if (dc->aysnc) {
+               if (is_an_ack(mssg)) {
+                       /* An ACK to our last sample sent */
+                       return; /* Or do something else here */
+               } else { /* A new message from remote */
+                       queue_req(mssg);
+               }
+       } else {
+               /* Remote f/w sends only ACK packets on this channel */
+               return;
+       }
+}
+
+static void sample_sent(struct mbox_client *cl, void *mssg, int r)
+{
+       struct demo_client *dc = container_of(mbox_client,
+                                               struct demo_client, cl);
+       complete(&dc->c);
+}
+
+static void client_demo(struct platform_device *pdev)
+{
+       struct demo_client *dc_sync, *dc_async;
+       /* The controller already knows async_pkt and sync_pkt */
+       struct async_pkt ap;
+       struct sync_pkt sp;
+
+       dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL);
+       dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL);
+
+       /* Populate non-blocking mode client */
+       dc_async->cl.dev = &pdev->dev;
+       dc_async->cl.rx_callback = message_from_remote;
+       dc_async->cl.tx_done = sample_sent;
+       dc_async->cl.tx_block = false;
+       dc_async->cl.tx_tout = 0; /* doesn't matter here */
+       dc_async->cl.knows_txdone = false; /* depending upon protocol */
+       dc_async->async = true;
+       init_completion(&dc_async->c);
+
+       /* Populate blocking mode client */
+       dc_sync->cl.dev = &pdev->dev;
+       dc_sync->cl.rx_callback = message_from_remote;
+       dc_sync->cl.tx_done = NULL; /* operate in blocking mode */
+       dc_sync->cl.tx_block = true;
+       dc_sync->cl.tx_tout = 500; /* by half a second */
+       dc_sync->cl.knows_txdone = false; /* depending upon protocol */
+       dc_sync->async = false;
+
+       /* ASync mailbox is listed second in 'mboxes' property */
+       dc_async->mbox = mbox_request_channel(&dc_async->cl, 1);
+       /* Populate data packet */
+       /* ap.xxx = 123; etc */
+       /* Send async message to remote */
+       mbox_send_message(dc_async->mbox, &ap);
+
+       /* Sync mailbox is listed first in 'mboxes' property */
+       dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0);
+       /* Populate data packet */
+       /* sp.abc = 123; etc */
+       /* Send message to remote in blocking mode */
+       mbox_send_message(dc_sync->mbox, &sp);
+       /* At this point 'sp' has been sent */
+
+       /* Now wait for async chan to be done */
+       wait_for_completion(&dc_async->c);
+}
index 22a969cdd4766a2f4f3651d359cd81defdb3bd21..7ee2ae6d5451d120126a04e3deeb07c02f2f9671 100644 (file)
@@ -121,22 +121,22 @@ For example, consider the following sequence of events:
 The set of accesses as seen by the memory system in the middle can be arranged
 in 24 different combinations:
 
-       STORE A=3,      STORE B=4,      x=LOAD A->3,    y=LOAD B->4
-       STORE A=3,      STORE B=4,      y=LOAD B->4,    x=LOAD A->3
-       STORE A=3,      x=LOAD A->3,    STORE B=4,      y=LOAD B->4
-       STORE A=3,      x=LOAD A->3,    y=LOAD B->2,    STORE B=4
-       STORE A=3,      y=LOAD B->2,    STORE B=4,      x=LOAD A->3
-       STORE A=3,      y=LOAD B->2,    x=LOAD A->3,    STORE B=4
-       STORE B=4,      STORE A=3,      x=LOAD A->3,    y=LOAD B->4
+       STORE A=3,      STORE B=4,      y=LOAD A->3,    x=LOAD B->4
+       STORE A=3,      STORE B=4,      x=LOAD B->4,    y=LOAD A->3
+       STORE A=3,      y=LOAD A->3,    STORE B=4,      x=LOAD B->4
+       STORE A=3,      y=LOAD A->3,    x=LOAD B->2,    STORE B=4
+       STORE A=3,      x=LOAD B->2,    STORE B=4,      y=LOAD A->3
+       STORE A=3,      x=LOAD B->2,    y=LOAD A->3,    STORE B=4
+       STORE B=4,      STORE A=3,      y=LOAD A->3,    x=LOAD B->4
        STORE B=4, ...
        ...
 
 and can thus result in four different combinations of values:
 
-       x == 1, y == 2
-       x == 1, y == 4
-       x == 3, y == 2
-       x == 3, y == 4
+       x == 2, y == 1
+       x == 2, y == 3
+       x == 4, y == 1
+       x == 4, y == 3
 
 
 Furthermore, the stores committed by a CPU to the memory system may not be
@@ -694,6 +694,24 @@ Please note once again that the stores to 'b' differ.  If they were
 identical, as noted earlier, the compiler could pull this store outside
 of the 'if' statement.
 
+You must also be careful not to rely too much on boolean short-circuit
+evaluation.  Consider this example:
+
+       q = ACCESS_ONCE(a);
+       if (a || 1 > 0)
+               ACCESS_ONCE(b) = 1;
+
+Because the second condition is always true, the compiler can transform
+this example as following, defeating control dependency:
+
+       q = ACCESS_ONCE(a);
+       ACCESS_ONCE(b) = 1;
+
+This example underscores the need to ensure that the compiler cannot
+out-guess your code.  More generally, although ACCESS_ONCE() does force
+the compiler to actually emit code for a given load, it does not force
+the compiler to use the results.
+
 Finally, control dependencies do -not- provide transitivity.  This is
 demonstrated by two related examples, with the initial values of
 x and y both being zero:
@@ -2465,10 +2483,15 @@ functions:
      Please refer to the PCI specification for more information on interactions
      between PCI transactions.
 
- (*) readX_relaxed()
+ (*) readX_relaxed(), writeX_relaxed()
 
-     These are similar to readX(), but are not guaranteed to be ordered in any
-     way. Be aware that there is no I/O read barrier available.
+     These are similar to readX() and writeX(), but provide weaker memory
+     ordering guarantees. Specifically, they do not guarantee ordering with
+     respect to normal memory accesses (e.g. DMA buffers) nor do they guarantee
+     ordering with respect to LOCK or UNLOCK operations. If the latter is
+     required, an mmiowb() barrier can be used. Note that relaxed accesses to
+     the same peripheral are guaranteed to be ordered with respect to each
+     other.
 
  (*) ioreadX(), iowriteX()
 
index 0307e2875f2159cb669b741f9d6a949618c3a055..a476b08a43e0dac5642a0bdfba76b8523be1033e 100644 (file)
@@ -56,6 +56,13 @@ ip_forward_use_pmtu - BOOLEAN
        0 - disabled
        1 - enabled
 
+fwmark_reflect - BOOLEAN
+       Controls the fwmark of kernel-generated IPv4 reply packets that are not
+       associated with a socket for example, TCP RSTs or ICMP echo replies).
+       If unset, these packets have a fwmark of zero. If set, they have the
+       fwmark of the packet they are replying to.
+       Default: 0
+
 route/max_size - INTEGER
        Maximum number of routes allowed in the kernel.  Increase
        this when using large numbers of interfaces and/or routes.
@@ -1201,6 +1208,13 @@ conf/all/forwarding - BOOLEAN
 proxy_ndp - BOOLEAN
        Do proxy ndp.
 
+fwmark_reflect - BOOLEAN
+       Controls the fwmark of kernel-generated IPv6 reply packets that are not
+       associated with a socket for example, TCP RSTs or ICMPv6 echo replies).
+       If unset, these packets have a fwmark of zero. If set, they have the
+       fwmark of the packet they are replying to.
+       Default: 0
+
 conf/interface/*:
        Change special settings per interface.
 
index 412f45ca2d73e3cd31a487e5fe13b73fc552d9f5..1d6d02d6ba52b531642436e8a6d8c0640af5467d 100644 (file)
@@ -136,7 +136,7 @@ SOF_TIMESTAMPING_OPT_ID:
 
   This option is implemented only for transmit timestamps. There, the
   timestamp is always looped along with a struct sock_extended_err.
-  The option modifies field ee_info to pass an id that is unique
+  The option modifies field ee_data to pass an id that is unique
   among all possibly concurrently outstanding timestamp requests for
   that socket. In practice, it is a monotonically increasing u32
   (that wraps).
diff --git a/Documentation/nios2/README b/Documentation/nios2/README
new file mode 100644 (file)
index 0000000..054a67d
--- /dev/null
@@ -0,0 +1,23 @@
+Linux on the Nios II architecture
+=================================
+
+This is a port of Linux to Nios II (nios2) processor.
+
+In order to compile for Nios II, you need a version of GCC with support for the generic
+system call ABI. Please see this link for more information on how compiling and booting
+software for the Nios II platform:
+http://www.rocketboards.org/foswiki/Documentation/NiosIILinuxUserManual
+
+For reference, please see the following link:
+http://www.altera.com/literature/lit-nio2.jsp
+
+What is Nios II?
+================
+Nios II is a 32-bit embedded-processor architecture designed specifically for the
+Altera family of FPGAs. In order to support Linux, Nios II needs to be configured
+with MMU and hardware multiplier enabled.
+
+Nios II ABI
+===========
+Please refer to chapter "Application Binary Interface" in Nios II Processor Reference
+Handbook.
index a5da5c7e7128bce8ff79beb019444c861fa1b68a..129f7c0e14839837e1ff4c1adc53544548a7d9a9 100644 (file)
@@ -5,7 +5,8 @@ performance expectations by drivers, subsystems and user space applications on
 one of the parameters.
 
 Two different PM QoS frameworks are available:
-1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput.
+1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput,
+memory_bandwidth.
 2. the per-device PM QoS framework provides the API to manage the per-device latency
 constraints and PM QoS flags.
 
@@ -13,6 +14,7 @@ Each parameters have defined units:
  * latency: usec
  * timeout: usec
  * throughput: kbs (kilo bit / sec)
+ * memory bandwidth: mbs (mega bit / sec)
 
 
 1. PM QoS framework
index 3e3232dcb2b828eb4dd5e73a81daf898f7e82e5f..2948b7b124b92c8412929d53533526c5ef704d13 100644 (file)
@@ -1,5 +1,5 @@
 # List of programs to build
-hostprogs-y := disable-tsc-ctxt-sw-stress-test disable-tsc-on-off-stress-test disable-tsc-test
+hostprogs-$(CONFIG_X86) := disable-tsc-ctxt-sw-stress-test disable-tsc-on-off-stress-test disable-tsc-test
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 
diff --git a/Documentation/ptp/testptp.mk b/Documentation/ptp/testptp.mk
new file mode 100644 (file)
index 0000000..4ef2d97
--- /dev/null
@@ -0,0 +1,33 @@
+# PTP 1588 clock support - User space test program
+#
+# Copyright (C) 2010 OMICRON electronics GmbH
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+CC        = $(CROSS_COMPILE)gcc
+INC       = -I$(KBUILD_OUTPUT)/usr/include
+CFLAGS    = -Wall $(INC)
+LDLIBS    = -lrt
+PROGS     = testptp
+
+all: $(PROGS)
+
+testptp: testptp.o
+
+clean:
+       rm -f testptp.o
+
+distclean: clean
+       rm -f $(PROGS)
index 3cc9c7843e154c19ebb2825f4704b2d1aa47b57a..8cac6492aade7c41cc1cffafc4b4d0500ff9d624 100644 (file)
@@ -226,9 +226,6 @@ static int register_sas_ha(struct my_sas_ha *my_ha)
        my_ha->sas_ha.lldd_dev_found = my_dev_found;
        my_ha->sas_ha.lldd_dev_gone = my_dev_gone;
 
-       my_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num; (1)
-
-       my_ha->sas_ha.lldd_queue_size = ha_can_queue;
        my_ha->sas_ha.lldd_execute_task = my_execute_task;
 
        my_ha->sas_ha.lldd_abort_task     = my_abort_task;
@@ -247,28 +244,6 @@ static int register_sas_ha(struct my_sas_ha *my_ha)
        return sas_register_ha(&my_ha->sas_ha);
 }
 
-(1) This is normally a LLDD parameter, something of the
-lines of a task collector.  What it tells the SAS Layer is
-whether the SAS layer should run in Direct Mode (default:
-value 0 or 1) or Task Collector Mode (value greater than 1).
-
-In Direct Mode, the SAS Layer calls Execute Task as soon as
-it has a command to send to the SDS, _and_ this is a single
-command, i.e. not linked.
-
-Some hardware (e.g. aic94xx) has the capability to DMA more
-than one task at a time (interrupt) from host memory.  Task
-Collector Mode is an optional feature for HAs which support
-this in their hardware.  (Again, it is completely optional
-even if your hardware supports it.)
-
-In Task Collector Mode, the SAS Layer would do _natural_
-coalescing of tasks and at the appropriate moment it would
-call your driver to DMA more than one task in a single HA
-interrupt. DMBS may want to use this by insmod/modprobe
-setting the lldd_max_execute_num to something greater than
-1.
-
 (2) SAS 1.1 does not define I_T Nexus Reset TMF.
 
 Events
@@ -325,71 +300,22 @@ PHYE_SPINUP_HOLD -- SATA is present, COMWAKE not sent.
 
 The Execute Command SCSI RPC:
 
-       int (*lldd_execute_task)(struct sas_task *, int num,
-                                unsigned long gfp_flags);
+       int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags);
 
-Used to queue a task to the SAS LLDD.  @task is the tasks to
-be executed.  @num should be the number of tasks being
-queued at this function call (they are linked listed via
-task::list), @gfp_mask should be the gfp_mask defining the
-context of the caller.
+Used to queue a task to the SAS LLDD.  @task is the task to be executed.
+@gfp_mask is the gfp_mask defining the context of the caller.
 
 This function should implement the Execute Command SCSI RPC,
-or if you're sending a SCSI Task as linked commands, you
-should also use this function.
 
-That is, when lldd_execute_task() is called, the command(s)
+That is, when lldd_execute_task() is called, the command
 go out on the transport *immediately*.  There is *no*
 queuing of any sort and at any level in a SAS LLDD.
 
-The use of task::list is two-fold, one for linked commands,
-the other discussed below.
-
-It is possible to queue up more than one task at a time, by
-initializing the list element of struct sas_task, and
-passing the number of tasks enlisted in this manner in num.
-
 Returns: -SAS_QUEUE_FULL, -ENOMEM, nothing was queued;
         0, the task(s) were queued.
 
-If you want to pass num > 1, then either
-A) you're the only caller of this function and keep track
-   of what you've queued to the LLDD, or
-B) you know what you're doing and have a strategy of
-   retrying.
-
-As opposed to queuing one task at a time (function call),
-batch queuing of tasks, by having num > 1, greatly
-simplifies LLDD code, sequencer code, and _hardware design_,
-and has some performance advantages in certain situations
-(DBMS).
-
-The LLDD advertises if it can take more than one command at
-a time at lldd_execute_task(), by setting the
-lldd_max_execute_num parameter (controlled by "collector"
-module parameter in aic94xx SAS LLDD).
-
-You should leave this to the default 1, unless you know what
-you're doing.
-
-This is a function of the LLDD, to which the SAS layer can
-cater to.
-
-int lldd_queue_size
-       The host adapter's queue size.  This is the maximum
-number of commands the lldd can have pending to domain
-devices on behalf of all upper layers submitting through
-lldd_execute_task().
-
-You really want to set this to something (much) larger than
-1.
-
-This _really_ has absolutely nothing to do with queuing.
-There is no queuing in SAS LLDDs.
-
 struct sas_task {
        dev -- the device this task is destined to
-       list -- must be initialized (INIT_LIST_HEAD)
        task_proto -- _one_ of enum sas_proto
        scatter -- pointer to scatter gather list array
        num_scatter -- number of elements in scatter
index da162f7fd5f5182893e249ac6423865fe627facf..5a9879bad07357a459aa9e9ba36a7686b090f0f3 100644 (file)
@@ -184,8 +184,7 @@ Any problems, questions, bug reports, lonely OSD nights, please email:
 More up-to-date information can be found on:
 http://open-osd.org
 
-Boaz Harrosh <bharrosh@panasas.com>
-Benny Halevy <bhalevy@panasas.com>
+Boaz Harrosh <ooo@electrozaur.com>
 
 References
 ==========
index d6a9bdeee7f241cda2a60d77d875357a442c91f4..731bc4f4c5e64a1ef0a4fce0ea3bf352f8f4c389 100644 (file)
@@ -149,7 +149,7 @@ scsi_add_host()  ---->
 scsi_scan_host()  -------+
                          |
                     slave_alloc()
-                    slave_configure() -->  scsi_adjust_queue_depth()
+                    slave_configure() -->  scsi_change_queue_depth()
                          |
                     slave_alloc()
                     slave_configure()
@@ -159,7 +159,7 @@ scsi_scan_host()  -------+
 ------------------------------------------------------------
 
 If the LLD wants to adjust the default queue settings, it can invoke
-scsi_adjust_queue_depth() in its slave_configure() routine.
+scsi_change_queue_depth() in its slave_configure() routine.
 
 *** For scsi devices that the mid level tries to scan but do not
     respond, a slave_alloc(), slave_destroy() pair is called.
@@ -203,7 +203,7 @@ LLD                   mid level                    LLD
 scsi_add_device()  ------+
                          |
                     slave_alloc()
-                    slave_configure()   [--> scsi_adjust_queue_depth()]
+                    slave_configure()   [--> scsi_change_queue_depth()]
 ------------------------------------------------------------
 
 In a similar fashion, an LLD may become aware that a SCSI device has been
@@ -261,7 +261,7 @@ init_this_scsi_driver() ----+
                             |                scsi_register()
                             |
                       slave_alloc()
-                      slave_configure()  -->  scsi_adjust_queue_depth()
+                      slave_configure()  -->  scsi_change_queue_depth()
                       slave_alloc()   ***
                       slave_destroy() ***
                             |
@@ -271,9 +271,9 @@ init_this_scsi_driver() ----+
                       slave_destroy() ***
 ------------------------------------------------------------
 
-The mid level invokes scsi_adjust_queue_depth() with tagged queuing off and
-"cmd_per_lun" for that host as the queue length. These settings can be
-overridden by a slave_configure() supplied by the LLD.
+The mid level invokes scsi_change_queue_depth() with "cmd_per_lun" for that
+host as the queue length. These settings can be overridden by a
+slave_configure() supplied by the LLD.
 
 *** For scsi devices that the mid level tries to scan but do not
     respond, a slave_alloc(), slave_destroy() pair is called.
@@ -366,13 +366,11 @@ is initialized. The functions below are listed alphabetically and their
 names all start with "scsi_".
 
 Summary:
-   scsi_activate_tcq - turn on tag command queueing
    scsi_add_device - creates new scsi device (lu) instance
    scsi_add_host - perform sysfs registration and set up transport class
-   scsi_adjust_queue_depth - change the queue depth on a SCSI device
+   scsi_change_queue_depth - change the queue depth on a SCSI device
    scsi_bios_ptable - return copy of block device's partition table
    scsi_block_requests - prevent further commands being queued to given host
-   scsi_deactivate_tcq - turn off tag command queueing
    scsi_host_alloc - return a new scsi_host instance whose refcount==1
    scsi_host_get - increments Scsi_Host instance's refcount
    scsi_host_put - decrements Scsi_Host instance's refcount (free if 0)
@@ -389,24 +387,6 @@ Summary:
 
 Details:
 
-/**
- * scsi_activate_tcq - turn on tag command queueing ("ordered" task attribute)
- * @sdev:       device to turn on TCQ for
- * @depth:      queue depth
- *
- *      Returns nothing
- *
- *      Might block: no
- *
- *      Notes: Eventually, it is hoped depth would be the maximum depth
- *      the device could cope with and the real queue depth
- *      would be adjustable from 0 to depth.
- *
- *      Defined (inline) in: include/scsi/scsi_tcq.h
- **/
-void scsi_activate_tcq(struct scsi_device *sdev, int depth)
-
-
 /**
  * scsi_add_device - creates new scsi device (lu) instance
  * @shost:   pointer to scsi host instance
@@ -456,11 +436,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device * dev)
 
 
 /**
- * scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device
+ * scsi_change_queue_depth - allow LLD to change queue depth on a SCSI device
  * @sdev:       pointer to SCSI device to change queue depth on
- * @tagged:     0 - no tagged queuing
- *              MSG_SIMPLE_TAG - simple tagged queuing
- *              MSG_ORDERED_TAG - ordered tagged queuing
  * @tags        Number of tags allowed if tagged queuing enabled,
  *              or number of commands the LLD can queue up
  *              in non-tagged mode (as per cmd_per_lun).
@@ -471,15 +448,12 @@ int scsi_add_host(struct Scsi_Host *shost, struct device * dev)
  *
  *      Notes: Can be invoked any time on a SCSI device controlled by this
  *      LLD. [Specifically during and after slave_configure() and prior to
- *      slave_destroy().] Can safely be invoked from interrupt code. Actual
- *      queue depth change may be delayed until the next command is being
- *      processed. See also scsi_activate_tcq() and scsi_deactivate_tcq().
+ *      slave_destroy().] Can safely be invoked from interrupt code.
  *
  *      Defined in: drivers/scsi/scsi.c [see source code for more notes]
  *
  **/
-void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged, 
-                             int tags)
+int scsi_change_queue_depth(struct scsi_device *sdev, int tags)
 
 
 /**
@@ -514,20 +488,6 @@ unsigned char *scsi_bios_ptable(struct block_device *dev)
 void scsi_block_requests(struct Scsi_Host * shost)
 
 
-/**
- * scsi_deactivate_tcq - turn off tag command queueing
- * @sdev:       device to turn off TCQ for
- * @depth:      queue depth (stored in sdev)
- *
- *      Returns nothing
- *
- *      Might block: no
- *
- *      Defined (inline) in: include/scsi/scsi_tcq.h
- **/
-void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
-
-
 /**
  * scsi_host_alloc - create a scsi host adapter instance and perform basic
  *                   initialization.
@@ -1254,7 +1214,7 @@ of interest:
                    for disk firmware uploads.
     cmd_per_lun  - maximum number of commands that can be queued on devices
                    controlled by the host. Overridden by LLD calls to
-                   scsi_adjust_queue_depth().
+                   scsi_change_queue_depth().
     unchecked_isa_dma - 1=>only use bottom 16 MB of ram (ISA DMA addressing
                    restriction), 0=>can use full 32 bit (or better) DMA
                    address space
@@ -1294,7 +1254,7 @@ struct scsi_cmnd
 Instances of this structure convey SCSI commands to the LLD and responses
 back to the mid level. The SCSI mid level will ensure that no more SCSI
 commands become queued against the LLD than are indicated by
-scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will
+scsi_change_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will
 be at least one instance of struct scsi_cmnd available for each SCSI device.
 Members of interest:
     cmnd         - array containing SCSI command
index f346abbdd6ff3a7aa16acb197e4dbe7b57d469ea..0d5bdb153d3b32582a7a3a6338e7c2e1d789d259 100644 (file)
@@ -506,9 +506,11 @@ user does not request data that far.)
 
 DEBUGGING HINTS
 
-To enable debugging messages, edit st.c and #define DEBUG 1. As seen
-above, debugging can be switched off with an ioctl if debugging is
-compiled into the driver. The debugging output is not voluminous.
+Debugging code is now compiled in by default but debugging is turned off
+with the kernel module parameter debug_flag defaulting to 0.  Debugging
+can still be switched on and off with an ioctl.  To enable debug at
+module load time add debug_flag=1 to the module load options, the
+debugging output is not voluminous.
 
 If the tape seems to hang, I would be very interested to hear where
 the driver is waiting. With the command 'ps -l' you can see the state
diff --git a/Documentation/scsi/wd719x.txt b/Documentation/scsi/wd719x.txt
new file mode 100644 (file)
index 0000000..0816b02
--- /dev/null
@@ -0,0 +1,21 @@
+Driver for Western Digital WD7193, WD7197 and WD7296 SCSI cards
+---------------------------------------------------------------
+
+The card requires firmware that can be cut out of the Windows NT driver that
+can be downloaded from WD at:
+http://support.wdc.com/product/download.asp?groupid=801&sid=27&lang=en
+
+There is no license anywhere in the file or on the page - so the firmware
+probably cannot be added to linux-firmware.
+
+This script downloads and extracts the firmware, creating wd719x-risc.bin and
+d719x-wcs.bin files. Put them in /lib/firmware/.
+
+#!/bin/sh
+wget http://support.wdc.com/download/archive/pciscsi.exe
+lha xi pciscsi.exe pci-scsi.exe
+lha xi pci-scsi.exe nt/wd7296a.sys
+rm pci-scsi.exe
+dd if=wd7296a.sys of=wd719x-risc.bin bs=1 skip=5760 count=14336
+dd if=wd7296a.sys of=wd719x-wcs.bin bs=1 skip=20096 count=514
+rm wd7296a.sys
diff --git a/Documentation/target/tcmu-design.txt b/Documentation/target/tcmu-design.txt
new file mode 100644 (file)
index 0000000..5518465
--- /dev/null
@@ -0,0 +1,378 @@
+Contents:
+
+1) TCM Userspace Design
+  a) Background
+  b) Benefits
+  c) Design constraints
+  d) Implementation overview
+     i. Mailbox
+     ii. Command ring
+     iii. Data Area
+  e) Device discovery
+  f) Device events
+  g) Other contingencies
+2) Writing a user pass-through handler
+  a) Discovering and configuring TCMU uio devices
+  b) Waiting for events on the device(s)
+  c) Managing the command ring
+3) Command filtering and pass_level
+4) A final note
+
+
+TCM Userspace Design
+--------------------
+
+TCM is another name for LIO, an in-kernel iSCSI target (server).
+Existing TCM targets run in the kernel.  TCMU (TCM in Userspace)
+allows userspace programs to be written which act as iSCSI targets.
+This document describes the design.
+
+The existing kernel provides modules for different SCSI transport
+protocols.  TCM also modularizes the data storage.  There are existing
+modules for file, block device, RAM or using another SCSI device as
+storage.  These are called "backstores" or "storage engines".  These
+built-in modules are implemented entirely as kernel code.
+
+Background:
+
+In addition to modularizing the transport protocol used for carrying
+SCSI commands ("fabrics"), the Linux kernel target, LIO, also modularizes
+the actual data storage as well. These are referred to as "backstores"
+or "storage engines". The target comes with backstores that allow a
+file, a block device, RAM, or another SCSI device to be used for the
+local storage needed for the exported SCSI LUN. Like the rest of LIO,
+these are implemented entirely as kernel code.
+
+These backstores cover the most common use cases, but not all. One new
+use case that other non-kernel target solutions, such as tgt, are able
+to support is using Gluster's GLFS or Ceph's RBD as a backstore. The
+target then serves as a translator, allowing initiators to store data
+in these non-traditional networked storage systems, while still only
+using standard protocols themselves.
+
+If the target is a userspace process, supporting these is easy. tgt,
+for example, needs only a small adapter module for each, because the
+modules just use the available userspace libraries for RBD and GLFS.
+
+Adding support for these backstores in LIO is considerably more
+difficult, because LIO is entirely kernel code. Instead of undertaking
+the significant work to port the GLFS or RBD APIs and protocols to the
+kernel, another approach is to create a userspace pass-through
+backstore for LIO, "TCMU".
+
+
+Benefits:
+
+In addition to allowing relatively easy support for RBD and GLFS, TCMU
+will also allow easier development of new backstores. TCMU combines
+with the LIO loopback fabric to become something similar to FUSE
+(Filesystem in Userspace), but at the SCSI layer instead of the
+filesystem layer. A SUSE, if you will.
+
+The disadvantage is there are more distinct components to configure, and
+potentially to malfunction. This is unavoidable, but hopefully not
+fatal if we're careful to keep things as simple as possible.
+
+Design constraints:
+
+- Good performance: high throughput, low latency
+- Cleanly handle if userspace:
+   1) never attaches
+   2) hangs
+   3) dies
+   4) misbehaves
+- Allow future flexibility in user & kernel implementations
+- Be reasonably memory-efficient
+- Simple to configure & run
+- Simple to write a userspace backend
+
+
+Implementation overview:
+
+The core of the TCMU interface is a memory region that is shared
+between kernel and userspace. Within this region is: a control area
+(mailbox); a lockless producer/consumer circular buffer for commands
+to be passed up, and status returned; and an in/out data buffer area.
+
+TCMU uses the pre-existing UIO subsystem. UIO allows device driver
+development in userspace, and this is conceptually very close to the
+TCMU use case, except instead of a physical device, TCMU implements a
+memory-mapped layout designed for SCSI commands. Using UIO also
+benefits TCMU by handling device introspection (e.g. a way for
+userspace to determine how large the shared region is) and signaling
+mechanisms in both directions.
+
+There are no embedded pointers in the memory region. Everything is
+expressed as an offset from the region's starting address. This allows
+the ring to still work if the user process dies and is restarted with
+the region mapped at a different virtual address.
+
+See target_core_user.h for the struct definitions.
+
+The Mailbox:
+
+The mailbox is always at the start of the shared memory region, and
+contains a version, details about the starting offset and size of the
+command ring, and head and tail pointers to be used by the kernel and
+userspace (respectively) to put commands on the ring, and indicate
+when the commands are completed.
+
+version - 1 (userspace should abort if otherwise)
+flags - none yet defined.
+cmdr_off - The offset of the start of the command ring from the start
+of the memory region, to account for the mailbox size.
+cmdr_size - The size of the command ring. This does *not* need to be a
+power of two.
+cmd_head - Modified by the kernel to indicate when a command has been
+placed on the ring.
+cmd_tail - Modified by userspace to indicate when it has completed
+processing of a command.
+
+The Command Ring:
+
+Commands are placed on the ring by the kernel incrementing
+mailbox.cmd_head by the size of the command, modulo cmdr_size, and
+then signaling userspace via uio_event_notify(). Once the command is
+completed, userspace updates mailbox.cmd_tail in the same way and
+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.
+
+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.
+
+The Data Area:
+
+This is shared-memory space after the command ring. The organization
+of this area is not defined in the TCMU interface, and userspace
+should access only the parts referenced by pending iovs.
+
+
+Device Discovery:
+
+Other devices may be using UIO besides TCMU. Unrelated user processes
+may also be handling different sets of TCMU devices. TCMU userspace
+processes must find their devices by scanning sysfs
+class/uio/uio*/name. For TCMU devices, these names will be of the
+format:
+
+tcm-user/<hba_num>/<device_name>/<subtype>/<path>
+
+where "tcm-user" is common for all TCMU-backed UIO devices. <hba_num>
+and <device_name> allow userspace to find the device's path in the
+kernel target's configfs tree. Assuming the usual mount point, it is
+found at:
+
+/sys/kernel/config/target/core/user_<hba_num>/<device_name>
+
+This location contains attributes such as "hw_block_size", that
+userspace needs to know for correct operation.
+
+<subtype> will be a userspace-process-unique string to identify the
+TCMU device as expecting to be backed by a certain handler, and <path>
+will be an additional handler-specific string for the user process to
+configure the device, if needed. The name cannot contain ':', due to
+LIO limitations.
+
+For all devices so discovered, the user handler opens /dev/uioX and
+calls mmap():
+
+mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)
+
+where size must be equal to the value read from
+/sys/class/uio/uioX/maps/map0/size.
+
+
+Device Events:
+
+If a new device is added or removed, a notification will be broadcast
+over netlink, using a generic netlink family name of "TCM-USER" and a
+multicast group named "config". This will include the UIO name as
+described in the previous section, as well as the UIO minor
+number. This should allow userspace to identify both the UIO device and
+the LIO device, so that after determining the device is supported
+(based on subtype) it can take the appropriate action.
+
+
+Other contingencies:
+
+Userspace handler process never attaches:
+
+- TCMU will post commands, and then abort them after a timeout period
+  (30 seconds.)
+
+Userspace handler process is killed:
+
+- It is still possible to restart and re-connect to TCMU
+  devices. Command ring is preserved. However, after the timeout period,
+  the kernel will abort pending tasks.
+
+Userspace handler process hangs:
+
+- The kernel will abort pending tasks after a timeout period.
+
+Userspace handler process is malicious:
+
+- The process can trivially break the handling of devices it controls,
+  but should not be able to access kernel memory outside its shared
+  memory areas.
+
+
+Writing a user pass-through handler (with example code)
+-------------------------------------------------------
+
+A user process handing a TCMU device must support the following:
+
+a) Discovering and configuring TCMU uio devices
+b) Waiting for events on the device(s)
+c) Managing the command ring: Parsing operations and commands,
+   performing work as needed, setting response fields (scsi_status and
+   possibly sense_buffer), updating cmd_tail, and notifying the kernel
+   that work has been finished
+
+First, consider instead writing a plugin for tcmu-runner. tcmu-runner
+implements all of this, and provides a higher-level API for plugin
+authors.
+
+TCMU is designed so that multiple unrelated processes can manage TCMU
+devices separately. All handlers should make sure to only open their
+devices, based opon a known subtype string.
+
+a) Discovering and configuring TCMU UIO devices:
+
+(error checking omitted for brevity)
+
+int fd, dev_fd;
+char buf[256];
+unsigned long long map_len;
+void *map;
+
+fd = open("/sys/class/uio/uio0/name", O_RDONLY);
+ret = read(fd, buf, sizeof(buf));
+close(fd);
+buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
+
+/* we only want uio devices whose name is a format we expect */
+if (strncmp(buf, "tcm-user", 8))
+       exit(-1);
+
+/* Further checking for subtype also needed here */
+
+fd = open(/sys/class/uio/%s/maps/map0/size, O_RDONLY);
+ret = read(fd, buf, sizeof(buf));
+close(fd);
+str_buf[ret-1] = '\0'; /* null-terminate and chop off the \n */
+
+map_len = strtoull(buf, NULL, 0);
+
+dev_fd = open("/dev/uio0", O_RDWR);
+map = mmap(NULL, map_len, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, 0);
+
+
+b) Waiting for events on the device(s)
+
+while (1) {
+  char buf[4];
+
+  int ret = read(dev_fd, buf, 4); /* will block */
+
+  handle_device_events(dev_fd, map);
+}
+
+
+c) Managing the command ring
+
+#include <linux/target_core_user.h>
+
+int handle_device_events(int fd, void *map)
+{
+  struct tcmu_mailbox *mb = map;
+  struct tcmu_cmd_entry *ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
+  int did_some_work = 0;
+
+  /* Process events from cmd ring until we catch up with cmd_head */
+  while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {
+
+    if (tcmu_hdr_get_op(&ent->hdr) == TCMU_OP_CMD) {
+      uint8_t *cdb = (void *)mb + ent->req.cdb_off;
+      bool success = true;
+
+      /* Handle command here. */
+      printf("SCSI opcode: 0x%x\n", cdb[0]);
+
+      /* Set response fields */
+      if (success)
+        ent->rsp.scsi_status = SCSI_NO_SENSE;
+      else {
+        /* Also fill in rsp->sense_buffer here */
+        ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
+      }
+    }
+    else {
+      /* Do nothing for PAD entries */
+    }
+
+    /* update cmd_tail */
+    mb->cmd_tail = (mb->cmd_tail + tcmu_hdr_get_len(&ent->hdr)) % mb->cmdr_size;
+    ent = (void *) mb + mb->cmdr_off + mb->cmd_tail;
+    did_some_work = 1;
+  }
+
+  /* Notify the kernel that work has been finished */
+  if (did_some_work) {
+    uint32_t buf = 0;
+
+    write(fd, &buf, 4);
+  }
+
+  return 0;
+}
+
+
+Command filtering and pass_level
+--------------------------------
+
+TCMU supports a "pass_level" option with valid values of 0 or 1.  When
+the value is 0 (the default), nearly all SCSI commands received for
+the device are passed through to the handler. This allows maximum
+flexibility but increases the amount of code required by the handler,
+to support all mandatory SCSI commands. If pass_level is set to 1,
+then only IO-related commands are presented, and the rest are handled
+by LIO's in-kernel command emulation. The commands presented at level
+1 include all versions of:
+
+READ
+WRITE
+WRITE_VERIFY
+XDWRITEREAD
+WRITE_SAME
+COMPARE_AND_WRITE
+SYNCHRONIZE_CACHE
+UNMAP
+
+
+A final note
+------------
+
+Please be careful to return codes as defined by the SCSI
+specifications. These are different than some values defined in the
+scsi/scsi.h include file. For example, CHECK CONDITION's status code
+is 2, not 1.
index 2b99e57207c161db7fa442f16ff99e16414a1a79..ee075c3d21248cff5f409585116c3ab52af6a575 100644 (file)
@@ -10,3 +10,6 @@ always := $(hostprogs-y)
 HOSTCFLAGS := -I$(objtree)/usr/include -std=gnu99
 HOSTCFLAGS_vdso_standalone_test_x86.o := -fno-asynchronous-unwind-tables -fno-stack-protector
 HOSTLOADLIBES_vdso_standalone_test_x86 := -nostdlib
+ifeq ($(CONFIG_X86_32),y)
+HOSTLOADLIBES_vdso_standalone_test_x86 += -lgcc_s
+endif
index d46240265c5001b767c0ba0da8c4397646d6f0c1..93b0ebf8cc38d06327732962a36e5005f948817e 100644 (file)
@@ -63,7 +63,7 @@ static inline void linux_exit(int code)
        x86_syscall3(__NR_exit, code, 0, 0);
 }
 
-void to_base10(char *lastdig, uint64_t n)
+void to_base10(char *lastdig, time_t n)
 {
        while (n) {
                *lastdig = (n % 10) + '0';
index eeb11a28e4fcbc96c4c3456eb2fbde71506a59eb..e5a940e3d304dbccbc673bfa990f76919a56bb8a 100644 (file)
@@ -221,12 +221,11 @@ ccs_out_mode: specify the allowed video output crop/compose/scaling combination
                       key, not quality.
 
 multiplanar: select whether each device instance supports multi-planar formats,
-       and thus the V4L2 multi-planar API. By default the first device instance
-       is single-planar, the second multi-planar, and it keeps alternating.
+       and thus the V4L2 multi-planar API. By default device instances are
+       single-planar.
 
        This module option can override that for each instance. Values are:
 
-               0: use alternating single and multi-planar devices.
                1: this is a single-planar instance.
                2: this is a multi-planar instance.
 
@@ -975,9 +974,8 @@ is set, then the alpha component is only used for the color red and set to
 0 otherwise.
 
 The driver has to be configured to support the multiplanar formats. By default
-the first driver instance is single-planar, the second is multi-planar, and it
-keeps alternating. This can be changed by setting the multiplanar module option,
-see section 1 for more details on that option.
+the driver instances are single-planar. This can be changed by setting the
+multiplanar module option, see section 1 for more details on that option.
 
 If the driver instance is using the multiplanar formats/API, then the first
 single planar format (YUYV) and the multiplanar NV16M and NV61M formats the
@@ -1021,7 +1019,7 @@ the output overlay for the video output, turn on video looping and capture
 to see the blended framebuffer overlay that's being written to by the second
 instance. This setup would require the following commands:
 
-       $ sudo modprobe vivid n_devs=2 node_types=0x10101,0x1 multiplanar=1,1
+       $ sudo modprobe vivid n_devs=2 node_types=0x10101,0x1
        $ v4l2-ctl -d1 --find-fb
        /dev/fb1 is the framebuffer associated with base address 0x12800000
        $ sudo v4l2-ctl -d2 --set-fbuf fb=1
index bdd4bb97fff709114f8374082b670e9f32ade7f9..b64e0af9cc56f676d731b7ad3436f15a498ca147 100644 (file)
@@ -274,7 +274,7 @@ This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
 /mnt/huge.  Any files created on /mnt/huge uses huge pages.  The uid and gid
 options sets the owner and group of the root of the file system.  By default
 the uid and gid of the current process are taken.  The mode option sets the
-mode of root of file system to value & 0777.  This value is given in octal.
+mode of root of file system to value & 01777.  This value is given in octal.
 By default the value 0755 is picked. The size option sets the maximum value of
 memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
 rounded down to HPAGE_SIZE.  The option nr_inodes sets the maximum number of
index a20df9bf8ab0efc22f5ced80f39ff2b4f429a89c..0d6469a2cf708d66f7a2a050237c1f250d64f96f 100644 (file)
@@ -861,6 +861,7 @@ W:  http://maxim.org.za/at91_26.html
 W:     http://www.linux4sam.org
 S:     Supported
 F:     arch/arm/mach-at91/
+F:     include/soc/at91/
 F:     arch/arm/boot/dts/at91*.dts
 F:     arch/arm/boot/dts/at91*.dtsi
 F:     arch/arm/boot/dts/sama*.dts
@@ -1308,30 +1309,22 @@ F:      drivers/*/*rockchip*
 F:     drivers/*/*/*rockchip*
 F:     sound/soc/rockchip/
 
-ARM/SAMSUNG ARM ARCHITECTURES
-M:     Ben Dooks <ben-linux@fluff.org>
-M:     Kukjin Kim <kgene.kim@samsung.com>
+ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
+M:     Kukjin Kim <kgene@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
-W:     http://www.fluff.org/ben/linux/
 S:     Maintained
 F:     arch/arm/boot/dts/s3c*
 F:     arch/arm/boot/dts/exynos*
 F:     arch/arm/plat-samsung/
 F:     arch/arm/mach-s3c24*/
 F:     arch/arm/mach-s3c64xx/
+F:     arch/arm/mach-s5p*/
+F:     arch/arm/mach-exynos*/
 F:     drivers/*/*s3c2410*
 F:     drivers/*/*/*s3c2410*
 F:     drivers/spi/spi-s3c*
 F:     sound/soc/samsung/*
-
-ARM/S5P EXYNOS ARM ARCHITECTURES
-M:     Kukjin Kim <kgene.kim@samsung.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
-S:     Maintained
-F:     arch/arm/mach-s5p*/
-F:     arch/arm/mach-exynos*/
 N:     exynos
 
 ARM/SAMSUNG MOBILE MACHINE SUPPORT
@@ -1381,12 +1374,12 @@ 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/koelsch_defconfig
 F:     arch/arm/configs/kzm9g_defconfig
 F:     arch/arm/configs/lager_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
 F:     arch/arm/mach-shmobile/
 F:     drivers/sh/
 
@@ -1430,6 +1423,7 @@ F:        drivers/tty/serial/st-asc.c
 F:     drivers/usb/dwc3/dwc3-st.c
 F:     drivers/usb/host/ehci-st.c
 F:     drivers/usb/host/ohci-st.c
+F:     drivers/ata/ahci_st.c
 
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -1503,6 +1497,19 @@ S:       Maintained
 F:     drivers/clk/ux500/
 F:     include/linux/platform_data/clk-ux500.h
 
+ARM/VERSATILE EXPRESS PLATFORM
+M:     Liviu Dudau <liviu.dudau@arm.com>
+M:     Sudeep Holla <sudeep.holla@arm.com>
+M:     Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/boot/dts/vexpress*
+F:     arch/arm/mach-vexpress/
+F:     */*/vexpress*
+F:     */*/*/vexpress*
+F:     drivers/clk/versatile/clk-vexpress-osc.c
+F:     drivers/clocksource/versatile.c
+
 ARM/VFP SUPPORT
 M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1543,6 +1550,7 @@ F:        arch/arm/mach-pxa/include/mach/z2.h
 
 ARM/ZYNQ ARCHITECTURE
 M:     Michal Simek <michal.simek@xilinx.com>
+R:     Sören Brinkmann <soren.brinkmann@xilinx.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://wiki.xilinx.com
 T:     git git://git.xilinx.com/linux-xlnx.git
@@ -1749,6 +1757,13 @@ M:       Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Supported
 F:     drivers/spi/spi-atmel.*
 
+ATMEL SSC DRIVER
+M:     Bo Shen <voice.shen@atmel.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Supported
+F:     drivers/misc/atmel-ssc.c
+F:     include/linux/atmel-ssc.h
+
 ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1820,7 +1835,7 @@ F:        include/net/ax25.h
 F:     net/ax25/
 
 AZ6007 DVB DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -2064,8 +2079,9 @@ F:        drivers/clocksource/bcm_kona_timer.c
 
 BROADCOM BCM2835 ARM ARCHITECTURE
 M:     Stephen Warren <swarren@wwwdotorg.org>
+M:     Lee Jones <lee@kernel.org>
 L:     linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
 S:     Maintained
 N:     bcm2835
 
@@ -2088,10 +2104,13 @@ F:      arch/arm/include/debug/bcm63xx.S
 BROADCOM BCM7XXX ARM ARCHITECTURE
 M:     Marc Carino <marc.ceeeee@gmail.com>
 M:     Brian Norris <computersforpeace@gmail.com>
+M:     Gregory Fong <gregory.0xf0@gmail.com>
+M:     Florian Fainelli <f.fainelli@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-bcm/*brcmstb*
 F:     arch/arm/boot/dts/bcm7*.dts*
+F:     drivers/bus/brcmstb_gisb.c
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M:     Prashant Sreedharan <prashant@broadcom.com>
@@ -2122,6 +2141,20 @@ L:       linux-scsi@vger.kernel.org
 S:     Supported
 F:     drivers/scsi/bnx2i/
 
+BROADCOM CYGNUS/IPROC ARM ARCHITECTURE
+M:     Ray Jui <rjui@broadcom.com>
+M:     Scott Branden <sbranden@broadcom.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     bcm-kernel-feedback-list@broadcom.com
+T:     git git://git.github.com/brcm/linux.git
+S:     Maintained
+N:     iproc
+N:     cygnus
+N:     bcm9113*
+N:     bcm9583*
+N:     bcm583*
+N:     bcm113*
+
 BROADCOM KONA GPIO DRIVER
 M:     Ray Jui <rjui@broadcom.com>
 L:     bcm-kernel-feedback-list@broadcom.com
@@ -2189,7 +2222,7 @@ F:        Documentation/filesystems/btrfs.txt
 F:     fs/btrfs/
 
 BTTV VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -2710,7 +2743,7 @@ F:        drivers/media/common/cx2341x*
 F:     include/media/cx2341x*
 
 CX88 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -2735,6 +2768,13 @@ W:       http://www.chelsio.com
 S:     Supported
 F:     drivers/net/ethernet/chelsio/cxgb3/
 
+CXGB3 ISCSI DRIVER (CXGB3I)
+M:      Karen Xie <kxie@chelsio.com>
+L:      linux-scsi@vger.kernel.org
+W:      http://www.chelsio.com
+S:      Supported
+F:      drivers/scsi/cxgbi/cxgb3i
+
 CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
 M:     Steve Wise <swise@chelsio.com>
 L:     linux-rdma@vger.kernel.org
@@ -2749,6 +2789,13 @@ W:       http://www.chelsio.com
 S:     Supported
 F:     drivers/net/ethernet/chelsio/cxgb4/
 
+CXGB4 ISCSI DRIVER (CXGB4I)
+M:      Karen Xie <kxie@chelsio.com>
+L:      linux-scsi@vger.kernel.org
+W:      http://www.chelsio.com
+S:      Supported
+F:      drivers/scsi/cxgbi/cxgb4i
+
 CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
 M:     Steve Wise <swise@chelsio.com>
 L:     linux-rdma@vger.kernel.org
@@ -2839,11 +2886,10 @@ F:      Documentation/networking/dmfe.txt
 F:     drivers/net/ethernet/dec/tulip/dmfe.c
 
 DC390/AM53C974 SCSI driver
-M:     Kurt Garloff <garloff@suse.de>
-W:     http://www.garloff.de/kurt/linux/dc390/
-M:     Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+M:     Hannes Reinecke <hare@suse.de>
+L:     linux-scsi@vger.kernel.org
 S:     Maintained
-F:     drivers/scsi/tmscsim.*
+F:     drivers/scsi/am53c974.c
 
 DC395x SCSI driver
 M:     Oliver Neukum <oliver@neukum.org>
@@ -3379,7 +3425,7 @@ F:        fs/ecryptfs/
 EDAC-CORE
 M:     Doug Thompson <dougthompson@xmission.com>
 M:     Borislav Petkov <bp@alien8.de>
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Supported
@@ -3428,7 +3474,7 @@ S:        Maintained
 F:     drivers/edac/e7xxx_edac.c
 
 EDAC-GHES
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
@@ -3456,21 +3502,21 @@ S:      Maintained
 F:     drivers/edac/i5000_edac.c
 
 EDAC-I5400
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i5400_edac.c
 
 EDAC-I7300
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i7300_edac.c
 
 EDAC-I7CORE
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
@@ -3513,7 +3559,7 @@ S:        Maintained
 F:     drivers/edac/r82600_edac.c
 
 EDAC-SBRIDGE
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
 S:     Maintained
@@ -3573,7 +3619,7 @@ S:        Maintained
 F:     drivers/net/ethernet/ibm/ehea/
 
 EM28XX VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -4305,8 +4351,10 @@ F:       Documentation/blockdev/cpqarray.txt
 F:     drivers/block/cpqarray.*
 
 HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
-M:     "Stephen M. Cameron" <scameron@beardog.cce.hp.com>
+M:     Don Brace <don.brace@pmcs.com>
 L:     iss_storagedev@hp.com
+L:     storagedev@pmcs.com
+L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     Documentation/scsi/hpsa.txt
 F:     drivers/scsi/hpsa*.[ch]
@@ -4314,8 +4362,10 @@ F:       include/linux/cciss*.h
 F:     include/uapi/linux/cciss*.h
 
 HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
-M:     Mike Miller <mike.miller@hp.com>
+M:     Don Brace <don.brace@pmcs.com>
 L:     iss_storagedev@hp.com
+L:     storagedev@pmcs.com
+L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     Documentation/blockdev/cciss.txt
 F:     drivers/block/cciss*
@@ -4601,7 +4651,7 @@ S:        Supported
 F:     drivers/crypto/nx/
 
 IBM Power 842 compression accelerator
-M:     Nathan Fontenot <nfont@linux.vnet.ibm.com>
+M:     Dan Streetman <ddstreet@us.ibm.com>
 S:     Supported
 F:     drivers/crypto/nx/nx-842.c
 F:     include/linux/nx842.h
@@ -4703,6 +4753,7 @@ L:        linux-iio@vger.kernel.org
 S:     Maintained
 F:     drivers/iio/
 F:     drivers/staging/iio/
+F:     include/linux/iio/
 
 IKANOS/ADI EAGLE ADSL USB DRIVER
 M:     Matthieu Castet <castet.matthieu@free.fr>
@@ -5834,6 +5885,14 @@ S:       Maintained
 F:     drivers/net/macvlan.c
 F:     include/linux/if_macvlan.h
 
+MAILBOX API
+M:     Jassi Brar <jassisinghbrar@gmail.com>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+F:     drivers/mailbox/
+F:     include/linux/mailbox_client.h
+F:     include/linux/mailbox_controller.h
+
 MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
 M:     Michael Kerrisk <mtk.manpages@gmail.com>
 W:     http://www.kernel.org/doc/man-pages
@@ -5926,7 +5985,7 @@ S:        Maintained
 F:     drivers/media/radio/radio-maxiradio*
 
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 P:     LinuxTV.org Project
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
@@ -5955,10 +6014,13 @@ W:      http://linuxtv.org
 S:     Odd Fixes
 F:     drivers/media/parport/pms*
 
-MEGARAID SCSI DRIVERS
-M:     Neela Syam Kolli <megaraidlinux@lsi.com>
+MEGARAID SCSI/SAS DRIVERS
+M:     Kashyap Desai <kashyap.desai@avagotech.com>
+M:     Sumit Saxena <sumit.saxena@avagotech.com>
+M:     Uday Lingala <uday.lingala@avagotech.com>
+L:     megaraidlinux.pdl@avagotech.com
 L:     linux-scsi@vger.kernel.org
-W:     http://megaraid.lsilogic.com
+W:     http://www.lsi.com
 S:     Maintained
 F:     Documentation/scsi/megaraid.txt
 F:     drivers/scsi/megaraid.*
@@ -6269,7 +6331,6 @@ F:        drivers/scsi/g_NCR5380.*
 F:     drivers/scsi/g_NCR5380_mmio.c
 F:     drivers/scsi/mac_scsi.*
 F:     drivers/scsi/pas16.*
-F:     drivers/scsi/sun3_NCR5380.c
 F:     drivers/scsi/sun3_scsi.*
 F:     drivers/scsi/sun3_scsi_vme.c
 F:     drivers/scsi/t128.*
@@ -6525,6 +6586,13 @@ S:       Maintained
 F:     Documentation/scsi/NinjaSCSI.txt
 F:     drivers/scsi/nsp32*
 
+NIOS2 ARCHITECTURE
+M:     Ley Foon Tan <lftan@altera.com>
+L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
+T:     git git://git.rocketboards.org/linux-socfpga.git
+S:     Maintained
+F:     arch/nios2/
+
 NTB DRIVER
 M:     Jon Mason <jdmason@kudzu.us>
 M:     Dave Jiang <dave.jiang@intel.com>
@@ -6575,6 +6643,23 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
 S:     Maintained
 F:     arch/arm/*omap*/
 F:     drivers/i2c/busses/i2c-omap.c
+F:     drivers/irqchip/irq-omap-intc.c
+F:     drivers/mfd/*omap*.c
+F:     drivers/mfd/menelaus.c
+F:     drivers/mfd/palmas.c
+F:     drivers/mfd/tps65217.c
+F:     drivers/mfd/tps65218.c
+F:     drivers/mfd/tps65910.c
+F:     drivers/mfd/twl-core.[ch]
+F:     drivers/mfd/twl4030*.c
+F:     drivers/mfd/twl6030*.c
+F:     drivers/mfd/twl6040*.c
+F:     drivers/regulator/palmas-regulator*.c
+F:     drivers/regulator/pbias-regulator.c
+F:     drivers/regulator/tps65217-regulator.c
+F:     drivers/regulator/tps65218-regulator.c
+F:     drivers/regulator/tps65910-regulator.c
+F:     drivers/regulator/twl-regulator.c
 F:     include/linux/i2c-omap.h
 
 OMAP DEVICE TREE SUPPORT
@@ -6585,6 +6670,9 @@ L:        devicetree@vger.kernel.org
 S:     Maintained
 F:     arch/arm/boot/dts/*omap*
 F:     arch/arm/boot/dts/*am3*
+F:     arch/arm/boot/dts/*am4*
+F:     arch/arm/boot/dts/*am5*
+F:     arch/arm/boot/dts/*dra7*
 
 OMAP CLOCK FRAMEWORK SUPPORT
 M:     Paul Walmsley <paul@pwsan.com>
@@ -6614,6 +6702,14 @@ L:       linux-omap@vger.kernel.org
 S:     Maintained
 F:     sound/soc/omap/
 
+OMAP GENERAL PURPOSE MEMORY CONTROLLER SUPPORT
+M:     Roger Quadros <rogerq@ti.com>
+M:     Tony Lindgren <tony@atomide.com>
+L:     linux-omap@vger.kernel.org
+S:     Maintained
+F:     drivers/memory/omap-gpmc.c
+F:     arch/arm/mach-omap2/*gpmc*
+
 OMAP FRAMEBUFFER SUPPORT
 M:     Tomi Valkeinen <tomi.valkeinen@ti.com>
 L:     linux-fbdev@vger.kernel.org
@@ -6822,7 +6918,7 @@ S:        Orphan
 F:     drivers/net/wireless/orinoco/
 
 OSD LIBRARY and FILESYSTEM
-M:     Boaz Harrosh <bharrosh@panasas.com>
+M:     Boaz Harrosh <ooo@electrozaur.com>
 M:     Benny Halevy <bhalevy@primarydata.com>
 L:     osd-dev@open-osd.org
 W:     http://open-osd.org
@@ -6832,6 +6928,14 @@ F:       drivers/scsi/osd/
 F:     include/scsi/osd_*
 F:     fs/exofs/
 
+OVERLAY FILESYSTEM
+M:     Miklos Szeredi <miklos@szeredi.hu>
+L:     linux-unionfs@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git
+S:     Supported
+F:     fs/overlayfs/
+F:     Documentation/filesystems/overlayfs.txt
+
 P54 WIRELESS DRIVER
 M:     Christian Lamparter <chunkeey@googlemail.com>
 L:     linux-wireless@vger.kernel.org
@@ -7153,6 +7257,7 @@ F:        drivers/crypto/picoxcell*
 
 PIN CONTROL SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
+L:     linux-gpio@vger.kernel.org
 S:     Maintained
 F:     drivers/pinctrl/
 F:     include/linux/pinctrl/
@@ -7948,7 +8053,7 @@ S:        Odd Fixes
 F:     drivers/media/i2c/saa6588*
 
 SAA7134 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -8406,7 +8511,7 @@ S:        Maintained
 F:     drivers/media/radio/si4713/radio-usb-si4713.c
 
 SIANO DVB DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -8457,7 +8562,6 @@ F:        arch/arm/mach-s3c24xx/bast-irq.c
 TI DAVINCI MACHINE SUPPORT
 M:     Sekhar Nori <nsekhar@ti.com>
 M:     Kevin Hilman <khilman@deeprootsystems.com>
-L:     davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
 T:     git git://gitorious.org/linux-davinci/linux-davinci.git
 Q:     http://patchwork.kernel.org/project/linux-davinci/list/
 S:     Supported
@@ -8467,7 +8571,6 @@ F:        drivers/i2c/busses/i2c-davinci.c
 TI DAVINCI SERIES MEDIA DRIVER
 M:     Lad, Prabhakar <prabhakar.csengg@gmail.com>
 L:     linux-media@vger.kernel.org
-L:     davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
 W:     http://linuxtv.org/
 Q:     http://patchwork.linuxtv.org/project/linux-media/list/
 T:     git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
@@ -8619,7 +8722,9 @@ S:        Maintained
 F:     drivers/leds/leds-net48xx.c
 
 SOFTLOGIC 6x10 MPEG CODEC
-M:     Ismael Luceno <ismael.luceno@corp.bluecherry.net>
+M:     Bluecherry Maintainers <maintainers@bluecherrydvr.com>
+M:     Andrey Utkin <andrey.utkin@corp.bluecherry.net>
+M:     Andrey Utkin <andrey.krieger.utkin@gmail.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
 F:     drivers/media/pci/solo6x10/
@@ -9093,7 +9198,7 @@ S:        Maintained
 F:     drivers/media/i2c/tda9840*
 
 TEA5761 TUNER DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -9101,7 +9206,7 @@ S:        Odd fixes
 F:     drivers/media/tuners/tea5761.*
 
 TEA5767 TUNER DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -9413,7 +9518,7 @@ F:        include/linux/shmem_fs.h
 F:     mm/shmem.c
 
 TM6000 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -9584,7 +9689,6 @@ F:     drivers/staging/unisys/
 
 UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
 M:     Vinayak Holikatti <vinholikatti@gmail.com>
-M:     Santosh Y <santoshsy@gmail.com>
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     Documentation/scsi/ufs.txt
@@ -9678,11 +9782,6 @@ S:       Maintained
 F:     Documentation/hid/hiddev.txt
 F:     drivers/hid/usbhid/
 
-USB/IP DRIVERS
-L:     linux-usb@vger.kernel.org
-S:     Orphan
-F:     drivers/staging/usbip/
-
 USB ISP116X DRIVER
 M:     Olav Kongas <ok@artecdesign.ee>
 L:     linux-usb@vger.kernel.org
@@ -10240,7 +10339,7 @@ S:      Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
 
 XC2028/3028 TUNER DRIVER
-M:     Mauro Carvalho Chehab <m.chehab@samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
index 05d67af376c5ed73f911deabf130817a8521cdeb..fd80c6e9bc2367f79f47edebb15649d23d341791 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 18
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
-NAME = Shuffling Zombie Juror
+EXTRAVERSION =
+NAME = Diseased Newt
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -297,7 +297,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 
 HOSTCC       = gcc
 HOSTCXX      = g++
-HOSTCFLAGS   = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
+HOSTCFLAGS   = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89
 HOSTCXXFLAGS = -O2
 
 ifeq ($(shell $(HOSTCC) -v 2>&1 | grep -c "clang version"), 1)
@@ -401,7 +401,8 @@ KBUILD_CPPFLAGS := -D__KERNEL__
 KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common \
                   -Werror-implicit-function-declaration \
-                  -Wno-format-security
+                  -Wno-format-security \
+                  -std=gnu89
 
 KBUILD_AFLAGS_KERNEL :=
 KBUILD_CFLAGS_KERNEL :=
index 9596b0ab108d14de64763a0b7dfded5a7cddd4f3..fe44b24946094d7ee7b0ea3add74c61c73f3a15a 100644 (file)
@@ -9,6 +9,7 @@
 config ARC
        def_bool y
        select BUILDTIME_EXTABLE_SORT
+       select COMMON_CLK
        select CLONE_BACKWARDS
        # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
        select DEVTMPFS if !INITRAMFS_SOURCE=""
@@ -73,9 +74,6 @@ config STACKTRACE_SUPPORT
 config HAVE_LATENCYTOP_SUPPORT
        def_bool y
 
-config NO_DMA
-       def_bool n
-
 source "init/Kconfig"
 source "kernel/Kconfig.freezer"
 
@@ -354,7 +352,7 @@ config ARC_CURR_IN_REG
          kernel mode. This saves memory access for each such access
 
 
-config ARC_MISALIGN_ACCESS
+config ARC_EMUL_UNALIGNED
        bool "Emulate unaligned memory access (userspace only)"
        select SYSCTL_ARCH_UNALIGN_NO_WARN
        select SYSCTL_ARCH_UNALIGN_ALLOW
index 8c0b1aa56f7ef0f885bb51a94ff6291c867bbf82..10bc3d4e8a443b891007f9d10b01bb2072413342 100644 (file)
@@ -25,7 +25,6 @@ ifdef CONFIG_ARC_CURR_IN_REG
 LINUXINCLUDE   +=  -include ${src}/arch/arc/include/asm/current.h
 endif
 
-upto_gcc42    :=  $(call cc-ifversion, -le, 0402, y)
 upto_gcc44    :=  $(call cc-ifversion, -le, 0404, y)
 atleast_gcc44 :=  $(call cc-ifversion, -ge, 0404, y)
 atleast_gcc48 :=  $(call cc-ifversion, -ge, 0408, y)
@@ -60,25 +59,11 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN)    += -EB
 # --build-id w/o "-marclinux". Default arc-elf32-ld is OK
 ldflags-$(upto_gcc44)                  += -marclinux
 
-ARC_LIBGCC                             := -mA7
-cflags-$(CONFIG_ARC_HAS_HW_MPY)                += -multcost=16
-
 ifndef CONFIG_ARC_HAS_HW_MPY
        cflags-y        += -mno-mpy
-
-# newlib for ARC700 assumes MPY to be always present, which is generally true
-# However, if someone really doesn't want MPY, we need to use the 600 ver
-# which coupled with -mno-mpy will use mpy emulation
-# With gcc 4.4.7, -mno-mpy is enough to make any other related adjustments,
-# e.g. increased cost of MPY. With gcc 4.2.1 this had to be explicitly hinted
-
-       ifeq ($(upto_gcc42),y)
-               ARC_LIBGCC      := -marc600
-               cflags-y        += -multcost=30
-       endif
 endif
 
-LIBGCC := $(shell $(CC) $(ARC_LIBGCC) $(cflags-y) --print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
 
 # Modules with short calls might break for calls into builtin-kernel
 KBUILD_CFLAGS_MODULE   += -mlong-calls
index 6b57475967a6f7abef31275a9e63f090468399bb..757e0c62c4f98c18139d3ce71c008467549b87ef 100644 (file)
                serial0 = &arcuart0;
        };
 
-       memory {
-               device_type = "memory";
-               reg = <0x00000000 0x10000000>;  /* 256M */
-       };
-
        fpga {
                compatible = "simple-bus";
                #address-cells = <1>;
index 4f31b2eb5cdf680cb6b26dbae5aa0119d39bef33..cfaedd9c61c99d89f42c50ea694cfda48f2a2b18 100644 (file)
                /* this is for console on PGU */
                /* bootargs = "console=tty0 consoleblank=0"; */
                /* this is for console on serial */
-               bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug";
+               bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug";
        };
 
        aliases {
                serial0 = &uart0;
        };
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x10000000>;  /* 256M */
-       };
-
        fpga {
                compatible = "simple-bus";
                #address-cells = <1>;
index e283aa586934cdb33a2be23955e82bfce5e74394..ef4d3bc7b6c05fdaa414c3c0312bfb829ab769e9 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
 # CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
 CONFIG_PREEMPT=y
index 5276a52f6a2f45494ad1f83545b59e91718a07c6..49c93011ab96ed322cf3bf35b729ee5a0fa40c81 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
 # CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
 CONFIG_PREEMPT=y
index c01ba35a4effc12b9598740d3eff14d234bf753e..278dacf2a3f94c66830815572a28d2f754e6abc8 100644 (file)
@@ -21,7 +21,6 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_FPGA_LEGACY=y
-CONFIG_ARC_BOARD_ML509=y
 # CONFIG_ARC_IDE is not set
 # CONFIG_ARCTANGENT_EMAC is not set
 # CONFIG_ARC_HAS_RTSC is not set
index 372466b371bf8c855944b2007efaa0ec7ba69fcf..be33db8a2ee3c3af4ea3d2c9670d4388933a1969 100644 (file)
@@ -9,19 +9,16 @@
 #ifndef _ASM_ARC_ARCREGS_H
 #define _ASM_ARC_ARCREGS_H
 
-#ifdef __KERNEL__
-
 /* Build Configuration Registers */
 #define ARC_REG_DCCMBASE_BCR   0x61    /* DCCM Base Addr */
 #define ARC_REG_CRC_BCR                0x62
-#define ARC_REG_DVFB_BCR       0x64
-#define ARC_REG_EXTARITH_BCR   0x65
 #define ARC_REG_VECBASE_BCR    0x68
 #define ARC_REG_PERIBASE_BCR   0x69
-#define ARC_REG_FP_BCR         0x6B    /* Single-Precision FPU */
-#define ARC_REG_DPFP_BCR       0x6C    /* Dbl Precision FPU */
+#define ARC_REG_FP_BCR         0x6B    /* ARCompact: Single-Precision FPU */
+#define ARC_REG_DPFP_BCR       0x6C    /* ARCompact: Dbl Precision FPU */
 #define ARC_REG_DCCM_BCR       0x74    /* DCCM Present + SZ */
 #define ARC_REG_TIMERS_BCR     0x75
+#define ARC_REG_AP_BCR         0x76
 #define ARC_REG_ICCM_BCR       0x78
 #define ARC_REG_XY_MEM_BCR     0x79
 #define ARC_REG_MAC_BCR                0x7a
@@ -31,6 +28,9 @@
 #define ARC_REG_MIXMAX_BCR     0x7e
 #define ARC_REG_BARREL_BCR     0x7f
 #define ARC_REG_D_UNCACH_BCR   0x6A
+#define ARC_REG_BPU_BCR                0xc0
+#define ARC_REG_ISA_CFG_BCR    0xc1
+#define ARC_REG_SMART_BCR      0xFF
 
 /* status32 Bits Positions */
 #define STATUS_AE_BIT          5       /* Exception active */
 #define PAGES_TO_KB(n_pages)   ((n_pages) << (PAGE_SHIFT - 10))
 #define PAGES_TO_MB(n_pages)   (PAGES_TO_KB(n_pages) >> 10)
 
-#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
-/* These DPFP regs need to be saved/restored across ctx-sw */
-struct arc_fpu {
-       struct {
-               unsigned int l, h;
-       } aux_dpfp[2];
-};
-#endif
 
 /*
  ***************************************************************
@@ -212,27 +204,19 @@ struct bcr_identity {
 #endif
 };
 
-#define EXTN_SWAP_VALID     0x1
-#define EXTN_NORM_VALID     0x2
-#define EXTN_MINMAX_VALID   0x2
-#define EXTN_BARREL_VALID   0x2
-
-struct bcr_extn {
+struct bcr_isa {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad:20, crc:1, ext_arith:2, mul:2, barrel:2, minmax:2,
-                    norm:2, swap:1;
+       unsigned int pad1:23, atomic1:1, ver:8;
 #else
-       unsigned int swap:1, norm:2, minmax:2, barrel:2, mul:2, ext_arith:2,
-                    crc:1, pad:20;
+       unsigned int ver:8, atomic1:1, pad1:23;
 #endif
 };
 
-/* DSP Options Ref Manual */
-struct bcr_extn_mac_mul {
+struct bcr_mpy {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad:16, type:8, ver:8;
+       unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8;
 #else
-       unsigned int ver:8, type:8, pad:16;
+       unsigned int ver:8, type:2, cycles:2, dsp:4, x1616:8, pad:8;
 #endif
 };
 
@@ -251,6 +235,7 @@ struct bcr_perip {
        unsigned int pad:8, sz:8, pad2:8, start:8;
 #endif
 };
+
 struct bcr_iccm {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int base:16, pad:5, sz:3, ver:8;
@@ -277,8 +262,8 @@ struct bcr_dccm {
 #endif
 };
 
-/* Both SP and DP FPU BCRs have same format */
-struct bcr_fp {
+/* ARCompact: Both SP and DP FPU BCRs have same format */
+struct bcr_fp_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int fast:1, ver:8;
 #else
@@ -286,6 +271,30 @@ struct bcr_fp {
 #endif
 };
 
+struct bcr_timer {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:15, rtsc:1, pad1:6, t1:1, t0:1, ver:8;
+#else
+       unsigned int ver:8, t0:1, t1:1, pad1:6, rtsc:1, pad2:15;
+#endif
+};
+
+struct bcr_bpu_arcompact {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:19, fam:1, pad:2, ent:2, ver:8;
+#else
+       unsigned int ver:8, ent:2, pad:2, fam:1, pad2:19;
+#endif
+};
+
+struct bcr_generic {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:24, ver:8;
+#else
+       unsigned int ver:8, pad:24;
+#endif
+};
+
 /*
  *******************************************************************
  * Generic structures to hold build configuration used at runtime
@@ -299,6 +308,10 @@ struct cpuinfo_arc_cache {
        unsigned int sz_k:8, line_len:8, assoc:4, ver:4, alias:1, vipt:1, pad:6;
 };
 
+struct cpuinfo_arc_bpu {
+       unsigned int ver, full, num_cache, num_pred;
+};
+
 struct cpuinfo_arc_ccm {
        unsigned int base_addr, sz;
 };
@@ -306,21 +319,25 @@ struct cpuinfo_arc_ccm {
 struct cpuinfo_arc {
        struct cpuinfo_arc_cache icache, dcache;
        struct cpuinfo_arc_mmu mmu;
+       struct cpuinfo_arc_bpu bpu;
        struct bcr_identity core;
-       unsigned int timers;
+       struct bcr_isa isa;
+       struct bcr_timer timers;
        unsigned int vec_base;
        unsigned int uncached_base;
        struct cpuinfo_arc_ccm iccm, dccm;
-       struct bcr_extn extn;
+       struct {
+               unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, pad1:3,
+                            fpu_sp:1, fpu_dp:1, pad2:6,
+                            debug:1, ap:1, smart:1, rtt:1, pad3:4,
+                            pad4:8;
+       } extn;
+       struct bcr_mpy extn_mpy;
        struct bcr_extn_xymem extn_xymem;
-       struct bcr_extn_mac_mul extn_mac_mul;
-       struct bcr_fp fp, dpfp;
 };
 
 extern struct cpuinfo_arc cpuinfo_arc700[];
 
 #endif /* __ASEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_ARC_ARCREGS_H */
index 173f303a868f20854cbdcc598cf991e4f6d6d0e5..067551b6920af99fe733f1f13d4aee8b1903a77b 100644 (file)
@@ -9,8 +9,6 @@
 #ifndef _ASM_ARC_ATOMIC_H
 #define _ASM_ARC_ATOMIC_H
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -170,5 +168,3 @@ ATOMIC_OP(and, &=, and)
 #endif
 
 #endif
-
-#endif
index ebc0cf3164dcc6b3a1f8a14c0ba7df66ee05648f..1a5bf07eefe2d445861ecafd2ac03b0b36e9c458 100644 (file)
@@ -13,8 +13,6 @@
 #error only <linux/bitops.h> can be included directly
 #endif
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -508,6 +506,4 @@ static inline __attribute__ ((const)) int __ffs(unsigned long word)
 
 #endif /* !__ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #endif
index 5b18e94c6678cd2b9eda3eace0dff4f9dd35585c..ea022d47896cef2761bbb8a147844c506f358621 100644 (file)
@@ -21,10 +21,9 @@ void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
                            unsigned long address);
 void die(const char *str, struct pt_regs *regs, unsigned long address);
 
-#define BUG()  do {                            \
-       dump_stack();                                   \
-       pr_warn("Kernel BUG in %s: %s: %d!\n",  \
-               __FILE__, __func__,  __LINE__); \
+#define BUG()  do {                                                            \
+       pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+       dump_stack();                                                           \
 } while (0)
 
 #define HAVE_ARCH_BUG
index b3c750979aa1c84051e6b2a684bdb0accc043c6c..7861255da32d64aa62e03d6fa881f84d9abf3b2f 100644 (file)
@@ -20,7 +20,7 @@
 #define CACHE_LINE_MASK                (~(L1_CACHE_BYTES - 1))
 
 /*
- * ARC700 doesn't cache any access in top 256M.
+ * ARC700 doesn't cache any access in top 1G (0xc000_0000 to 0xFFFF_FFFF)
  * Ideal for wiring memory mapped peripherals as we don't need to do
  * explicit uncached accesses (LD.di/ST.di) hence more portable drivers
  */
index 87b918585c4adc94d530059679e8360f8687f3b6..c2453ee628013700d899a8a47553c7d51a4e6cef 100644 (file)
@@ -12,8 +12,6 @@
 #ifndef _ASM_ARC_CURRENT_H
 #define _ASM_ARC_CURRENT_H
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #ifdef CONFIG_ARC_CURR_IN_REG
@@ -27,6 +25,4 @@ register struct task_struct *curr_arc asm("r25");
 
 #endif /* ! __ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_ARC_CURRENT_H */
index 334ce7017a18e937961e81c00b97acfc9779b316..cabd518cb253d95e3bf532d07bfbc5c2214d19fc 100644 (file)
@@ -13,8 +13,6 @@
 #include <asm/byteorder.h>
 #include <asm/page.h>
 
-#define PCI_IOBASE ((void __iomem *)0)
-
 extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
 extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
                                  unsigned long flags);
index 587df8236e8b4c91e896893522f7b060c3cc6d0d..742816f1b2101e2e8ef090ea9d14d444ae97aec8 100644 (file)
@@ -15,8 +15,6 @@
  *  -Conditionally disable interrupts (if they are not enabled, don't disable)
 */
 
-#ifdef __KERNEL__
-
 #include <asm/arcregs.h>
 
 /* status32 Reg bits related to Interrupt Handling */
@@ -169,6 +167,4 @@ static inline int arch_irqs_disabled(void)
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* KERNEL */
-
 #endif
index b65fca7ffeb5e70d5e72e8bf011fc7834d9d33ea..fea9316341366e92c270ef135f5888664797ca76 100644 (file)
@@ -19,7 +19,7 @@
  * register API yet */
 #undef DBG_MAX_REG_NUM
 
-#define GDB_MAX_REGS           39
+#define GDB_MAX_REGS           87
 
 #define BREAK_INSTR_SIZE       2
 #define CACHE_FLUSH_IS_SAFE    1
@@ -33,23 +33,27 @@ static inline void arch_kgdb_breakpoint(void)
 
 extern void kgdb_trap(struct pt_regs *regs);
 
-enum arc700_linux_regnums {
+/* This is the numbering of registers according to the GDB. See GDB's
+ * arc-tdep.h for details.
+ *
+ * Registers are ordered for GDB 7.5. It is incompatible with GDB 6.8. */
+enum arc_linux_regnums {
        _R0             = 0,
        _R1, _R2, _R3, _R4, _R5, _R6, _R7, _R8, _R9, _R10, _R11, _R12, _R13,
        _R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, _R23, _R24,
        _R25, _R26,
-       _BTA            = 27,
-       _LP_START       = 28,
-       _LP_END         = 29,
-       _LP_COUNT       = 30,
-       _STATUS32       = 31,
-       _BLINK          = 32,
-       _FP             = 33,
-       __SP            = 34,
-       _EFA            = 35,
-       _RET            = 36,
-       _ORIG_R8        = 37,
-       _STOP_PC        = 38
+       _FP             = 27,
+       __SP            = 28,
+       _R30            = 30,
+       _BLINK          = 31,
+       _LP_COUNT       = 60,
+       _STOP_PC        = 64,
+       _RET            = 64,
+       _LP_START       = 65,
+       _LP_END         = 66,
+       _STATUS32       = 67,
+       _ECR            = 76,
+       _BTA            = 82,
 };
 
 #else
index 82588f3ba77f6b940fd8aa607af34d049614a993..210fe97464c386e91d004fa87d624a83a3e16403 100644 (file)
 #ifndef __ASM_ARC_PROCESSOR_H
 #define __ASM_ARC_PROCESSOR_H
 
-#ifdef __KERNEL__
-
 #ifndef __ASSEMBLY__
 
 #include <asm/ptrace.h>
 
+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
+/* These DPFP regs need to be saved/restored across ctx-sw */
+struct arc_fpu {
+       struct {
+               unsigned int l, h;
+       } aux_dpfp[2];
+};
+#endif
+
 /* Arch specific stuff which needs to be saved per task.
  * However these items are not so important so as to earn a place in
  * struct thread_info
@@ -128,6 +135,4 @@ extern unsigned int get_wchan(struct task_struct *p);
  */
 #define TASK_UNMAPPED_BASE      (TASK_SIZE / 3)
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_ARC_PROCESSOR_H */
index e10f8cef56a8efcaaaf1ff77190ed8125b2d3e1a..6e3ef5ba4f74adca5d4fd1ed78440579166b4b64 100644 (file)
@@ -29,7 +29,6 @@ struct cpuinfo_data {
 };
 
 extern int root_mountflags, end_mem;
-extern int running_on_hw;
 
 void setup_processor(void);
 void __init setup_arch_memory(void);
index 5d06eee43ea9a18ddd8876ac66c7c6d5fed29ec6..3845b9e94f69b0ee5dbda11fe9467c3d4b517aed 100644 (file)
@@ -59,7 +59,15 @@ struct plat_smp_ops {
 /* TBD: stop exporting it for direct population by platform */
 extern struct plat_smp_ops  plat_smp_ops;
 
-#endif  /* CONFIG_SMP */
+#else /* CONFIG_SMP */
+
+static inline void smp_init_cpus(void) {}
+static inline const char *arc_platform_smp_cpuinfo(void)
+{
+       return "";
+}
+
+#endif  /* !CONFIG_SMP */
 
 /*
  * ARC700 doesn't support atomic Read-Modify-Write ops.
index 87676c8f14121e18f178a97ad8475f75b1c7f007..95822b550a18add505329b958035aaa87be7d66d 100644 (file)
@@ -17,8 +17,6 @@
 
 #include <linux/types.h>
 
-#ifdef __KERNEL__
-
 #define __HAVE_ARCH_MEMSET
 #define __HAVE_ARCH_MEMCPY
 #define __HAVE_ARCH_MEMCMP
@@ -36,5 +34,4 @@ extern char *strcpy(char *dest, const char *src);
 extern int strcmp(const char *cs, const char *ct);
 extern __kernel_size_t strlen(const char *);
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_ARC_STRING_H */
index dd785befe7fd1eaa3b6b7d5df5ee8ef77e849587..e56f9fcc558133277ca03d93461a56da5f02a4b9 100644 (file)
@@ -9,8 +9,6 @@
 #ifndef _ASM_ARC_SYSCALLS_H
 #define _ASM_ARC_SYSCALLS_H  1
 
-#ifdef __KERNEL__
-
 #include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
@@ -22,6 +20,4 @@ int sys_arc_gettls(void);
 
 #include <asm-generic/syscalls.h>
 
-#endif /* __KERNEL__ */
-
 #endif
index 45be2167201183172695d0a788c0b20b87ec7ce2..02bc5ec0fb2e4e813249aeb42d04bb97aea8f4e9 100644 (file)
@@ -16,8 +16,6 @@
 #ifndef _ASM_THREAD_INFO_H
 #define _ASM_THREAD_INFO_H
 
-#ifdef __KERNEL__
-
 #include <asm/page.h>
 
 #ifdef CONFIG_16KSTACKS
@@ -114,6 +112,4 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
  * syscall, so all that reamins to be tested is _TIF_WORK_MASK
  */
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_THREAD_INFO_H */
index 3e5f071bc00c7541cebf06ea00855ad53719d359..6da6b4edaeda56801e31cbd0ef5291bfdbe43d67 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm-generic/unaligned.h>
 #include <asm/ptrace.h>
 
-#ifdef CONFIG_ARC_MISALIGN_ACCESS
+#ifdef CONFIG_ARC_EMUL_UNALIGNED
 int misaligned_fixup(unsigned long address, struct pt_regs *regs,
                     struct callee_regs *cregs);
 #else
index 8004b4fa64615cd3c570219e8e5575848e4c99ac..113f2033da9f096a45588a40b00193c8305cf693 100644 (file)
@@ -16,7 +16,7 @@ obj-$(CONFIG_MODULES)                 += arcksyms.o module.o
 obj-$(CONFIG_SMP)                      += smp.o
 obj-$(CONFIG_ARC_DW2_UNWIND)           += unwind.o
 obj-$(CONFIG_KPROBES)                  += kprobes.o
-obj-$(CONFIG_ARC_MISALIGN_ACCESS)      += unaligned.o
+obj-$(CONFIG_ARC_EMUL_UNALIGNED)       += unaligned.o
 obj-$(CONFIG_KGDB)                     += kgdb.o
 obj-$(CONFIG_ARC_METAWARE_HLINK)       += arc_hostlink.o
 obj-$(CONFIG_PERF_EVENTS)              += perf_event.o
index b8a549c4f54071f97d26c473a9dca532e1db8b41..3b7cd4864ba20fa67896de08913395d9978a2dd5 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/uaccess.h>
 #include <asm/disasm.h>
 
-#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
+#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_EMUL_UNALIGNED) || \
        defined(CONFIG_KPROBES)
 
 /* disasm_instr: Analyses instruction at addr, stores
@@ -535,4 +535,4 @@ int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
        return instr.is_branch;
 }
 
-#endif /* CONFIG_KGDB || CONFIG_ARC_MISALIGN_ACCESS || CONFIG_KPROBES */
+#endif /* CONFIG_KGDB || CONFIG_ARC_EMUL_UNALIGNED || CONFIG_KPROBES */
index 4d2481bd8b98dc9e1017b953afafcdf3379c3c27..b0e8666fdccc755ac11763a3bf0b6594f4ed628a 100644 (file)
@@ -91,16 +91,6 @@ stext:
        st      r0, [@uboot_tag]
        st      r2, [@uboot_arg]
 
-       ; Identify if running on ISS vs Silicon
-       ;       IDENTITY Reg [ 3  2  1  0 ]
-       ;       (chip-id)      ^^^^^            ==> 0xffff for ISS
-       lr      r0, [identity]
-       lsr     r3, r0, 16
-       cmp     r3, 0xffff
-       mov.z   r4, 0
-       mov.nz  r4, 1
-       st      r4, [@running_on_hw]
-
        ; setup "current" tsk and optionally cache it in dedicated r25
        mov     r9, @init_task
        SET_CURR_TASK_ON_CPU  r9, r0    ; r9 = tsk, r0 = scratch
index a2ff5c5d1450a7e58a11e2a771e42e93f01ce8e8..ecf6a78693758ba1eecb88a868b8c9d431f52f16 100644 (file)
@@ -158,11 +158,6 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
        return -1;
 }
 
-unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
-{
-       return instruction_pointer(regs);
-}
-
 int kgdb_arch_init(void)
 {
        single_step_data.armed = 0;
index b9a5685a990e25d3aeaec535e7a24bd3c991a019..ae1c485cbc68ea116d84a0625050c0ab80fea89c 100644 (file)
@@ -244,25 +244,23 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                pr_err("This core does not have performance counters!\n");
                return -ENODEV;
        }
+       BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS);
 
-       arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu),
-                              GFP_KERNEL);
+       READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
+       if (!cc_bcr.v) {
+               pr_err("Performance counters exist, but no countable conditions?\n");
+               return -ENODEV;
+       }
+
+       arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
        if (!arc_pmu)
                return -ENOMEM;
 
        arc_pmu->n_counters = pct_bcr.c;
-       BUG_ON(arc_pmu->n_counters > ARC_PMU_MAX_HWEVENTS);
-
        arc_pmu->counter_size = 32 + (pct_bcr.s << 4);
-       pr_info("ARC PMU found with %d counters of size %d bits\n",
-               arc_pmu->n_counters, arc_pmu->counter_size);
-
-       READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-
-       if (!cc_bcr.v)
-               pr_err("Strange! Performance counters exist, but no countable conditions?\n");
 
-       pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c);
+       pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
+               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++)
index 119dddb752b2892ff81a7ab7ce43011eef056b35..252bf603db9c7db023d75b5374580d8f5325c85d 100644 (file)
@@ -13,7 +13,9 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
+#include <linux/clk-provider.h>
 #include <linux/of_fdt.h>
+#include <linux/of_platform.h>
 #include <linux/cache.h>
 #include <asm/sections.h>
 #include <asm/arcregs.h>
 #include <asm/unwind.h>
 #include <asm/clk.h>
 #include <asm/mach_desc.h>
+#include <asm/smp.h>
 
 #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
 
-int running_on_hw = 1; /* vs. on ISS */
-
 /* Part of U-boot ABI: see head.S */
 int __initdata uboot_tag;
 char __initdata *uboot_arg;
@@ -42,26 +43,26 @@ struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
 static void read_arc_build_cfg_regs(void)
 {
        struct bcr_perip uncached_space;
+       struct bcr_generic bcr;
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        FIX_PTR(cpu);
 
        READ_BCR(AUX_IDENTITY, cpu->core);
+       READ_BCR(ARC_REG_ISA_CFG_BCR, cpu->isa);
 
-       cpu->timers = read_aux_reg(ARC_REG_TIMERS_BCR);
+       READ_BCR(ARC_REG_TIMERS_BCR, cpu->timers);
        cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
 
        READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
        cpu->uncached_base = uncached_space.start << 24;
 
-       cpu->extn.mul = read_aux_reg(ARC_REG_MUL_BCR);
-       cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR);
-       cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR);
-       cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR);
-       cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR);
-       READ_BCR(ARC_REG_MAC_BCR, cpu->extn_mac_mul);
+       READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy);
 
-       cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR);
-       cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR);
+       cpu->extn.norm = read_aux_reg(ARC_REG_NORM_BCR) > 1 ? 1 : 0; /* 2,3 */
+       cpu->extn.barrel = read_aux_reg(ARC_REG_BARREL_BCR) > 1 ? 1 : 0; /* 2,3 */
+       cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0;        /* 1,3 */
+       cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0;
+       cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */
 
        /* Note that we read the CCM BCRs independent of kernel config
         * This is to catch the cases where user doesn't know that
@@ -95,43 +96,76 @@ static void read_arc_build_cfg_regs(void)
        read_decode_mmu_bcr();
        read_decode_cache_bcr();
 
-       READ_BCR(ARC_REG_FP_BCR, cpu->fp);
-       READ_BCR(ARC_REG_DPFP_BCR, cpu->dpfp);
+       {
+               struct bcr_fp_arcompact sp, dp;
+               struct bcr_bpu_arcompact bpu;
+
+               READ_BCR(ARC_REG_FP_BCR, sp);
+               READ_BCR(ARC_REG_DPFP_BCR, dp);
+               cpu->extn.fpu_sp = sp.ver ? 1 : 0;
+               cpu->extn.fpu_dp = dp.ver ? 1 : 0;
+
+               READ_BCR(ARC_REG_BPU_BCR, bpu);
+               cpu->bpu.ver = bpu.ver;
+               cpu->bpu.full = bpu.fam ? 1 : 0;
+               if (bpu.ent) {
+                       cpu->bpu.num_cache = 256 << (bpu.ent - 1);
+                       cpu->bpu.num_pred = 256 << (bpu.ent - 1);
+               }
+       }
+
+       READ_BCR(ARC_REG_AP_BCR, bcr);
+       cpu->extn.ap = bcr.ver ? 1 : 0;
+
+       READ_BCR(ARC_REG_SMART_BCR, bcr);
+       cpu->extn.smart = bcr.ver ? 1 : 0;
+
+       cpu->extn.debug = cpu->extn.ap | cpu->extn.smart;
 }
 
 static const struct cpuinfo_data arc_cpu_tbl[] = {
-       { {0x10, "ARCTangent A5"}, 0x1F},
        { {0x20, "ARC 600"      }, 0x2F},
        { {0x30, "ARC 700"      }, 0x33},
        { {0x34, "ARC 700 R4.10"}, 0x34},
+       { {0x35, "ARC 700 R4.11"}, 0x35},
        { {0x00, NULL           } }
 };
 
+#define IS_AVAIL1(v, str)      ((v) ? str : "")
+#define IS_USED(cfg)           (IS_ENABLED(cfg) ? "" : "(not used) ")
+#define IS_AVAIL2(v, str, cfg)  IS_AVAIL1(v, str), IS_AVAIL1(v, IS_USED(cfg))
+
 static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 {
-       int n = 0;
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
        struct bcr_identity *core = &cpu->core;
        const struct cpuinfo_data *tbl;
-       int be = 0;
-#ifdef CONFIG_CPU_BIG_ENDIAN
-       be = 1;
-#endif
+       char *isa_nm;
+       int i, be, atomic;
+       int n = 0;
+
        FIX_PTR(cpu);
 
+       {
+               isa_nm = "ARCompact";
+               be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
+
+               atomic = cpu->isa.atomic1;
+               if (!cpu->isa.ver)      /* ISA BCR absent, use Kconfig info */
+                       atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
+       }
+
        n += scnprintf(buf + n, len - n,
-                      "\nARC IDENTITY\t: Family [%#02x]"
-                      " Cpu-id [%#02x] Chip-id [%#4x]\n",
-                      core->family, core->cpu_id,
-                      core->chip_id);
+                      "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n",
+                      core->family, core->cpu_id, core->chip_id);
 
        for (tbl = &arc_cpu_tbl[0]; tbl->info.id != 0; tbl++) {
                if ((core->family >= tbl->info.id) &&
                    (core->family <= tbl->up_range)) {
                        n += scnprintf(buf + n, len - n,
-                                      "processor\t: %s %s\n",
-                                      tbl->info.str,
-                                      be ? "[Big Endian]" : "");
+                                      "processor [%d]\t: %s (%s ISA) %s\n",
+                                      cpu_id, tbl->info.str, isa_nm,
+                                      IS_AVAIL1(be, "[Big-Endian]"));
                        break;
                }
        }
@@ -143,34 +177,35 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                       (unsigned int)(arc_get_core_freq() / 1000000),
                       (unsigned int)(arc_get_core_freq() / 10000) % 100);
 
-       n += scnprintf(buf + n, len - n, "Timers\t\t: %s %s\n",
-                      (cpu->timers & 0x200) ? "TIMER1" : "",
-                      (cpu->timers & 0x100) ? "TIMER0" : "");
+       n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
+                      IS_AVAIL1(cpu->timers.t0, "Timer0 "),
+                      IS_AVAIL1(cpu->timers.t1, "Timer1 "),
+                      IS_AVAIL2(cpu->timers.rtsc, "64-bit RTSC ", CONFIG_ARC_HAS_RTSC));
 
-       n += scnprintf(buf + n, len - n, "Vect Tbl Base\t: %#x\n",
-                      cpu->vec_base);
+       n += i = scnprintf(buf + n, len - n, "%s%s",
+                          IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC));
 
-       n += scnprintf(buf + n, len - n, "UNCACHED Base\t: %#x\n",
-                      cpu->uncached_base);
+       if (i)
+               n += scnprintf(buf + n, len - n, "\n\t\t: ");
 
-       return buf;
-}
+       n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
+                      IS_AVAIL1(cpu->extn_mpy.ver, "mpy "),
+                      IS_AVAIL1(cpu->extn.norm, "norm "),
+                      IS_AVAIL1(cpu->extn.barrel, "barrel-shift "),
+                      IS_AVAIL1(cpu->extn.swap, "swap "),
+                      IS_AVAIL1(cpu->extn.minmax, "minmax "),
+                      IS_AVAIL1(cpu->extn.crc, "crc "),
+                      IS_AVAIL2(1, "swape", CONFIG_ARC_HAS_SWAPE));
 
-static const struct id_to_str mul_type_nm[] = {
-       { 0x0, "N/A"},
-       { 0x1, "32x32 (spl Result Reg)" },
-       { 0x2, "32x32 (ANY Result Reg)" }
-};
+       if (cpu->bpu.ver)
+               n += scnprintf(buf + n, len - n,
+                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d\n",
+                             IS_AVAIL1(cpu->bpu.full, "full"),
+                             IS_AVAIL1(!cpu->bpu.full, "partial"),
+                             cpu->bpu.num_cache, cpu->bpu.num_pred);
 
-static const struct id_to_str mac_mul_nm[] = {
-       {0x0, "N/A"},
-       {0x1, "N/A"},
-       {0x2, "Dual 16 x 16"},
-       {0x3, "N/A"},
-       {0x4, "32x16"},
-       {0x5, "N/A"},
-       {0x6, "Dual 16x16 and 32x16"}
-};
+       return buf;
+}
 
 static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
 {
@@ -178,67 +213,46 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
 
        FIX_PTR(cpu);
-#define IS_AVAIL1(var, str)    ((var) ? str : "")
-#define IS_AVAIL2(var, str)    ((var == 0x2) ? str : "")
-#define IS_USED(cfg)           (IS_ENABLED(cfg) ? "(in-use)" : "(not used)")
 
        n += scnprintf(buf + n, len - n,
-                      "Extn [700-Base]\t: %s %s %s %s %s %s\n",
-                      IS_AVAIL2(cpu->extn.norm, "norm,"),
-                      IS_AVAIL2(cpu->extn.barrel, "barrel-shift,"),
-                      IS_AVAIL1(cpu->extn.swap, "swap,"),
-                      IS_AVAIL2(cpu->extn.minmax, "minmax,"),
-                      IS_AVAIL1(cpu->extn.crc, "crc,"),
-                      IS_AVAIL2(cpu->extn.ext_arith, "ext-arith"));
-
-       n += scnprintf(buf + n, len - n, "Extn [700-MPY]\t: %s",
-                      mul_type_nm[cpu->extn.mul].str);
-
-       n += scnprintf(buf + n, len - n, "   MAC MPY: %s\n",
-                      mac_mul_nm[cpu->extn_mac_mul.type].str);
-
-       if (cpu->core.family == 0x34) {
-               n += scnprintf(buf + n, len - n,
-               "Extn [700-4.10]\t: LLOCK/SCOND %s, SWAPE %s, RTSC %s\n",
-                              IS_USED(CONFIG_ARC_HAS_LLSC),
-                              IS_USED(CONFIG_ARC_HAS_SWAPE),
-                              IS_USED(CONFIG_ARC_HAS_RTSC));
-       }
-
-       n += scnprintf(buf + n, len - n, "Extn [CCM]\t: %s",
-                      !(cpu->dccm.sz || cpu->iccm.sz) ? "N/A" : "");
-
-       if (cpu->dccm.sz)
-               n += scnprintf(buf + n, len - n, "DCCM: @ %x, %d KB ",
-                              cpu->dccm.base_addr, TO_KB(cpu->dccm.sz));
-
-       if (cpu->iccm.sz)
-               n += scnprintf(buf + n, len - n, "ICCM: @ %x, %d KB",
+                      "Vector Table\t: %#x\nUncached Base\t: %#x\n",
+                      cpu->vec_base, cpu->uncached_base);
+
+       if (cpu->extn.fpu_sp || cpu->extn.fpu_dp)
+               n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n",
+                              IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
+                              IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
+
+       if (cpu->extn.debug)
+               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n",
+                              IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
+                              IS_AVAIL1(cpu->extn.smart, "smaRT "),
+                              IS_AVAIL1(cpu->extn.rtt, "RTT "));
+
+       if (cpu->dccm.sz || cpu->iccm.sz)
+               n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
+                              cpu->dccm.base_addr, TO_KB(cpu->dccm.sz),
                               cpu->iccm.base_addr, TO_KB(cpu->iccm.sz));
 
-       n += scnprintf(buf + n, len - n, "\nExtn [FPU]\t: %s",
-                      !(cpu->fp.ver || cpu->dpfp.ver) ? "N/A" : "");
-
-       if (cpu->fp.ver)
-               n += scnprintf(buf + n, len - n, "SP [v%d] %s",
-                              cpu->fp.ver, cpu->fp.fast ? "(fast)" : "");
-
-       if (cpu->dpfp.ver)
-               n += scnprintf(buf + n, len - n, "DP [v%d] %s",
-                              cpu->dpfp.ver, cpu->dpfp.fast ? "(fast)" : "");
-
-       n += scnprintf(buf + n, len - n, "\n");
-
        n += scnprintf(buf + n, len - n,
                       "OS ABI [v3]\t: no-legacy-syscalls\n");
 
        return buf;
 }
 
-static void arc_chk_ccms(void)
+static void arc_chk_core_config(void)
 {
-#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+       int fpu_enabled;
+
+       if (!cpu->timers.t0)
+               panic("Timer0 is not present!\n");
+
+       if (!cpu->timers.t1)
+               panic("Timer1 is not present!\n");
+
+       if (IS_ENABLED(CONFIG_ARC_HAS_RTSC) && !cpu->timers.rtsc)
+               panic("RTSC is not present\n");
 
 #ifdef CONFIG_ARC_HAS_DCCM
        /*
@@ -256,33 +270,20 @@ static void arc_chk_ccms(void)
        if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
                panic("Linux built with incorrect ICCM Size\n");
 #endif
-#endif
-}
 
-/*
- * Ensure that FP hardware and kernel config match
- * -If hardware contains DPFP, kernel needs to save/restore FPU state
- *  across context switches
- * -If hardware lacks DPFP, but kernel configured to save FPU state then
- *  kernel trying to access non-existant DPFP regs will crash
- *
- * We only check for Dbl precision Floating Point, because only DPFP
- * hardware has dedicated regs which need to be saved/restored on ctx-sw
- * (Single Precision uses core regs), thus kernel is kind of oblivious to it
- */
-static void arc_chk_fpu(void)
-{
-       struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+       /*
+        * FP hardware/software config sanity
+        * -If hardware contains DPFP, kernel needs to save/restore FPU state
+        * -If not, it will crash trying to save/restore the non-existant regs
+        *
+        * (only DPDP checked since SP has no arch visible regs)
+        */
+       fpu_enabled = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE);
 
-       if (cpu->dpfp.ver) {
-#ifndef CONFIG_ARC_FPU_SAVE_RESTORE
-               pr_warn("DPFP support broken in this kernel...\n");
-#endif
-       } else {
-#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
-               panic("H/w lacks DPFP support, apps won't work\n");
-#endif
-       }
+       if (cpu->extn.fpu_dp && !fpu_enabled)
+               pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
+       else if (!cpu->extn.fpu_dp && fpu_enabled)
+               panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
 }
 
 /*
@@ -303,15 +304,11 @@ void setup_processor(void)
 
        arc_mmu_init();
        arc_cache_init();
-       arc_chk_ccms();
 
        printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));
-
-#ifdef CONFIG_SMP
        printk(arc_platform_smp_cpuinfo());
-#endif
 
-       arc_chk_fpu();
+       arc_chk_core_config();
 }
 
 static inline int is_kernel(unsigned long addr)
@@ -360,11 +357,7 @@ void __init setup_arch(char **cmdline_p)
                machine_desc->init_early();
 
        setup_processor();
-
-#ifdef CONFIG_SMP
        smp_init_cpus();
-#endif
-
        setup_arch_memory();
 
        /* copy flat DT out of .init and then unflatten it */
@@ -385,7 +378,13 @@ void __init setup_arch(char **cmdline_p)
 
 static int __init customize_machine(void)
 {
-       /* Add platform devices */
+       of_clk_init(NULL);
+       /*
+        * Traverses flattened DeviceTree - registering platform devices
+        * (if any) complete with their resources
+        */
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
        if (machine_desc->init_machine)
                machine_desc->init_machine();
 
@@ -419,19 +418,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
        seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE));
 
-       seq_printf(m, "Bogo MIPS : \t%lu.%02lu\n",
+       seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n",
                   loops_per_jiffy / (500000 / HZ),
                   (loops_per_jiffy / (5000 / HZ)) % 100);
 
        seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
        seq_printf(m, arc_cache_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
        seq_printf(m, arc_extn_mumbojumbo(cpu_id, str, PAGE_SIZE));
-
-#ifdef CONFIG_SMP
        seq_printf(m, arc_platform_smp_cpuinfo());
-#endif
 
        free_page((unsigned long)str);
 done:
index dcd317c47d098f0fef9391d8173cff82a1b96ba7..d01df0c517a2044ddc15f5fdb895303aa3de56bb 100644 (file)
@@ -101,7 +101,7 @@ void __weak arc_platform_smp_wait_to_boot(int cpu)
 
 const char *arc_platform_smp_cpuinfo(void)
 {
-       return plat_smp_ops.info;
+       return plat_smp_ops.info ? : "";
 }
 
 /*
index 9e1142729fd14c003c4f302a8305de1d735ab7a2..8c3a3e02ba92c8adbc368dba9a3cd283f32c3e72 100644 (file)
@@ -530,16 +530,9 @@ EXPORT_SYMBOL(dma_cache_wback);
  */
 void flush_icache_range(unsigned long kstart, unsigned long kend)
 {
-       unsigned int tot_sz, off, sz;
-       unsigned long phy, pfn;
+       unsigned int tot_sz;
 
-       /* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
-
-       /* This is not the right API for user virtual address */
-       if (kstart < TASK_SIZE) {
-               BUG_ON("Flush icache range for user virtual addr space");
-               return;
-       }
+       WARN(kstart < TASK_SIZE, "%s() can't handle user vaddr", __func__);
 
        /* Shortcut for bigger flush ranges.
         * Here we don't care if this was kernel virtual or phy addr
@@ -572,6 +565,9 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
         *     straddles across 2 virtual pages and hence need for loop
         */
        while (tot_sz > 0) {
+               unsigned int off, sz;
+               unsigned long phy, pfn;
+
                off = kstart % PAGE_SIZE;
                pfn = vmalloc_to_pfn((void *)kstart);
                phy = (pfn << PAGE_SHIFT) + off;
index e1acf0ce56479d63be92629ad7b7c19c2ddd8950..7f47d2a56f44374e00939e6742ed6717c452c58a 100644 (file)
@@ -609,14 +609,12 @@ char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len)
        int n = 0;
        struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu;
 
-       n += scnprintf(buf + n, len - n, "ARC700 MMU [v%x]\t: %dk PAGE, ",
-                      p_mmu->ver, TO_KB(p_mmu->pg_sz));
-
        n += scnprintf(buf + n, len - n,
-                      "J-TLB %d (%dx%d), uDTLB %d, uITLB %d, %s\n",
+                     "MMU [v%x]\t: %dk PAGE, JTLB %d (%dx%d), uDTLB %d, uITLB %d %s\n",
+                      p_mmu->ver, TO_KB(p_mmu->pg_sz),
                       p_mmu->num_tlb, p_mmu->sets, p_mmu->ways,
                       p_mmu->u_dtlb, p_mmu->u_itlb,
-                      IS_ENABLED(CONFIG_ARC_MMU_SASID) ? "SASID" : "");
+                      IS_ENABLED(CONFIG_ARC_MMU_SASID) ? ",SASID" : "");
 
        return buf;
 }
index b9f34cf55acf47c653d6d6b7e5c09adde2d9d324..217593a7075134f72d3aa2dafcbc4e585ec5cf05 100644 (file)
@@ -8,7 +8,7 @@
 
 menuconfig ARC_PLAT_FPGA_LEGACY
        bool "\"Legacy\" ARC FPGA dev Boards"
-       select ISS_SMP_EXTN if SMP
+       select ARC_HAS_COH_CACHES if SMP
        help
          Support for ARC development boards, provided by Synopsys.
          These are based on FPGA or ISS. e.g.
@@ -18,17 +18,6 @@ menuconfig ARC_PLAT_FPGA_LEGACY
 
 if ARC_PLAT_FPGA_LEGACY
 
-config ARC_BOARD_ANGEL4
-       bool "ARC Angel4"
-       default y
-       help
-         ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
-
-config ARC_BOARD_ML509
-       bool "ML509"
-       help
-         ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
-
 config ISS_SMP_EXTN
        bool "ARC SMP Extensions (ISS Models only)"
        default n
diff --git a/arch/arc/plat-arcfpga/include/plat/irq.h b/arch/arc/plat-arcfpga/include/plat/irq.h
deleted file mode 100644 (file)
index 2c9dea6..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
- *
- * vineetg: Feb 2009
- *  -For AA4 board, IRQ assignments to peripherals
- */
-
-#ifndef __PLAT_IRQ_H
-#define __PLAT_IRQ_H
-
-#define UART0_IRQ      5
-#define UART1_IRQ      10
-#define UART2_IRQ      11
-
-#define IDE_IRQ                13
-#define PCI_IRQ                14
-#define PS2_IRQ                15
-
-#ifdef CONFIG_SMP
-#define IDU_INTERRUPT_0 16
-#endif
-
-#endif
diff --git a/arch/arc/plat-arcfpga/include/plat/memmap.h b/arch/arc/plat-arcfpga/include/plat/memmap.h
deleted file mode 100644 (file)
index 5c78e61..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
- *
- * vineetg: Feb 2009
- *  -For AA4 board, System Memory Map for Peripherals etc
- */
-
-#ifndef __PLAT_MEMMAP_H
-#define __PLAT_MEMMAP_H
-
-#define UART0_BASE              0xC0FC1000
-#define UART1_BASE              0xC0FC1100
-
-#define IDE_CONTROLLER_BASE     0xC0FC9000
-
-#define AHB_PCI_HOST_BRG_BASE   0xC0FD0000
-
-#define PGU_BASEADDR            0xC0FC8000
-#define VLCK_ADDR               0xC0FCF028
-
-#define BVCI_LAT_UNIT_BASE      0xC0FED000
-
-#define PS2_BASE_ADDR          0xC0FCC000
-
-#endif
index 1038949a99a177a0c5e4429be113332268f20f29..afc88254acc1bb74763141008987e9f38f96cb81 100644 (file)
@@ -8,37 +8,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/types.h>
 #include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/console.h>
-#include <linux/of_platform.h>
-#include <asm/setup.h>
-#include <asm/clk.h>
 #include <asm/mach_desc.h>
-#include <plat/memmap.h>
 #include <plat/smp.h>
-#include <plat/irq.h>
-
-static void __init plat_fpga_early_init(void)
-{
-       pr_info("[plat-arcfpga]: registering early dev resources\n");
-
-#ifdef CONFIG_ISS_SMP_EXTN
-       iss_model_init_early_smp();
-#endif
-}
-
-static void __init plat_fpga_populate_dev(void)
-{
-       /*
-        * Traverses flattened DeviceTree - registering platform devices
-        * (if any) complete with their resources
-        */
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
 
 /*----------------------- Machine Descriptions ------------------------------
  *
@@ -48,41 +20,26 @@ static void __init plat_fpga_populate_dev(void)
  * callback set, by matching the DT compatible name.
  */
 
-static const char *aa4_compat[] __initconst = {
+static const char *legacy_fpga_compat[] __initconst = {
        "snps,arc-angel4",
-       NULL,
-};
-
-MACHINE_START(ANGEL4, "angel4")
-       .dt_compat      = aa4_compat,
-       .init_early     = plat_fpga_early_init,
-       .init_machine   = plat_fpga_populate_dev,
-#ifdef CONFIG_ISS_SMP_EXTN
-       .init_smp       = iss_model_init_smp,
-#endif
-MACHINE_END
-
-static const char *ml509_compat[] __initconst = {
        "snps,arc-ml509",
        NULL,
 };
 
-MACHINE_START(ML509, "ml509")
-       .dt_compat      = ml509_compat,
-       .init_early     = plat_fpga_early_init,
-       .init_machine   = plat_fpga_populate_dev,
-#ifdef CONFIG_SMP
+MACHINE_START(LEGACY_FPGA, "legacy_fpga")
+       .dt_compat      = legacy_fpga_compat,
+#ifdef CONFIG_ISS_SMP_EXTN
+       .init_early     = iss_model_init_early_smp,
        .init_smp       = iss_model_init_smp,
 #endif
 MACHINE_END
 
-static const char *nsimosci_compat[] __initconst = {
+static const char *simulation_compat[] __initconst = {
+       "snps,nsim",
        "snps,nsimosci",
        NULL,
 };
 
-MACHINE_START(NSIMOSCI, "nsimosci")
-       .dt_compat      = nsimosci_compat,
-       .init_early     = NULL,
-       .init_machine   = plat_fpga_populate_dev,
+MACHINE_START(SIMULATION, "simulation")
+       .dt_compat      = simulation_compat,
 MACHINE_END
index 92bad9122077dc00b22fc82c6e22be8f5219787b..64797ba3bbe3eed4487fd20911b86e60f3ef0486 100644 (file)
 
 #include <linux/smp.h>
 #include <linux/irq.h>
-#include <plat/irq.h>
 #include <plat/smp.h>
 
+#define IDU_INTERRUPT_0 16
+
 static char smp_cpuinfo_buf[128];
 
 /*
index 6994c188dc88c82bbc256f6835c6e54b6107545a..d14b3d3c5dfdd9b51d0f1bd819dab2c00f1f57fa 100644 (file)
@@ -18,7 +18,6 @@
 
 menuconfig ARC_PLAT_TB10X
        bool "Abilis TB10x"
-       select COMMON_CLK
        select PINCTRL
        select PINCTRL_TB10X
        select PINMUX
index 06cb309294608a6753652049e7c4f3df6d8f8ada..da0ac0960a4b7c992c8e7ad6ad5690f212540b1e 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-
 #include <linux/init.h>
-#include <linux/of_platform.h>
-#include <linux/clk-provider.h>
-#include <linux/pinctrl/consumer.h>
-
 #include <asm/mach_desc.h>
 
-
-static void __init tb10x_platform_init(void)
-{
-       of_clk_init(NULL);
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char *tb10x_compat[] __initdata = {
        "abilis,arc-tb10x",
        NULL,
@@ -41,5 +29,4 @@ static const char *tb10x_compat[] __initdata = {
 
 MACHINE_START(TB10x, "tb10x")
        .dt_compat      = tb10x_compat,
-       .init_machine   = tb10x_platform_init,
 MACHINE_END
index 89c4b5ccc68df8200aeff85bf89adaf87ce24e12..c8424a85bc0453748103518743f3bab68f81d77b 100644 (file)
@@ -320,24 +320,6 @@ config ARCH_MULTIPLATFORM
        select SPARSE_IRQ
        select USE_OF
 
-config ARCH_INTEGRATOR
-       bool "ARM Ltd. Integrator family"
-       select ARM_AMBA
-       select ARM_PATCH_PHYS_VIRT if MMU
-       select AUTO_ZRELADDR
-       select COMMON_CLK
-       select COMMON_CLK_VERSATILE
-       select GENERIC_CLOCKEVENTS
-       select HAVE_TCM
-       select ICST
-       select MULTI_IRQ_HANDLER
-       select PLAT_VERSATILE
-       select SPARSE_IRQ
-       select USE_OF
-       select VERSATILE_FPGA_IRQ
-       help
-         Support for ARM's Integrator platform.
-
 config ARCH_REALVIEW
        bool "ARM Ltd. RealView family"
        select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -350,6 +332,7 @@ config ARCH_REALVIEW
        select ICST
        select NEED_MACH_MEMORY_H
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_SCHED_CLOCK
        help
          This enables support for ARM Ltd RealView boards.
 
@@ -365,6 +348,7 @@ config ARCH_VERSATILE
        select ICST
        select PLAT_VERSATILE
        select PLAT_VERSATILE_CLOCK
+       select PLAT_VERSATILE_SCHED_CLOCK
        select VERSATILE_FPGA_IRQ
        help
          This enables support for ARM Ltd Versatile board.
@@ -376,10 +360,11 @@ config ARCH_AT91
        select IRQ_DOMAIN
        select NEED_MACH_IO_H if PCCARD
        select PINCTRL
-       select PINCTRL_AT91 if USE_OF
+       select PINCTRL_AT91
+       select USE_OF
        help
          This enables support for systems based on Atmel
-         AT91RM9200 and AT91SAM9* processors.
+         AT91RM9200, AT91SAM9 and SAMA5 processors.
 
 config ARCH_CLPS711X
        bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
@@ -854,6 +839,8 @@ config ARCH_VIRT
 #
 source "arch/arm/mach-mvebu/Kconfig"
 
+source "arch/arm/mach-asm9260/Kconfig"
+
 source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-axxia/Kconfig"
@@ -1259,9 +1246,6 @@ source "arch/arm/common/Kconfig"
 
 menu "Bus support"
 
-config ARM_AMBA
-       bool
-
 config ISA
        bool
        help
index 03dc4c1a8736e78e5878298b9ff0c797e67f57fb..f9295a4e10363b09cd12de523b6a2bc158a48c5b 100644 (file)
@@ -93,6 +93,27 @@ choice
        prompt "Kernel low-level debugging port"
        depends on DEBUG_LL
 
+       config DEBUG_ASM9260_UART
+               bool "Kernel low-level debugging via asm9260 UART"
+               depends on MACH_ASM9260
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to an UART or USART port on asm9260 based
+                 machines.
+
+                   DEBUG_UART_PHYS | DEBUG_UART_VIRT
+
+                   0x80000000      | 0xf0000000     | UART0
+                   0x80004000      | 0xf0004000     | UART1
+                   0x80008000      | 0xf0008000     | UART2
+                   0x8000c000      | 0xf000c000     | UART3
+                   0x80010000      | 0xf0010000     | UART4
+                   0x80014000      | 0xf0014000     | UART5
+                   0x80018000      | 0xf0018000     | UART6
+                   0x8001c000      | 0xf001c000     | UART7
+                   0x80020000      | 0xf0020000     | UART8
+                   0x80024000      | 0xf0024000     | UART9
+
        config AT91_DEBUG_LL_DBGU0
                bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10 and 9rl"
                depends on HAVE_AT91_DBGU0
@@ -113,7 +134,7 @@ choice
        config DEBUG_BCM_5301X
                bool "Kernel low-level debugging on BCM5301X UART1"
                depends on ARCH_BCM_5301X
-               select DEBUG_UART_PL01X
+               select DEBUG_UART_8250
 
        config DEBUG_BCM_KONA_UART
                bool "Kernel low-level debugging messages via BCM KONA UART"
@@ -139,6 +160,17 @@ choice
                  Say Y here if you want kernel low-level debugging support
                  on Marvell Berlin SoC based platforms.
 
+       config DEBUG_BRCMSTB_UART
+               bool "Use BRCMSTB UART for low-level debug"
+               depends on ARCH_BRCMSTB
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to the first serial port on these devices.
+
+                 If you have a Broadcom STB chip and would like early print
+                 messages to appear over the UART, select this option.
+
        config DEBUG_CLPS711X_UART1
                bool "Kernel low-level debugging messages via UART1"
                depends on ARCH_CLPS711X
@@ -653,6 +685,64 @@ choice
                  Say Y here if you want kernel low-level debugging support
                  on Rockchip RK32xx based platforms.
 
+       config DEBUG_R7S72100_SCIF2
+               bool "Kernel low-level debugging messages via SCIF2 on R7S72100"
+               depends on ARCH_R7S72100
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 via SCIF2 on Renesas RZ/A1H (R7S72100).
+
+       config DEBUG_RCAR_GEN1_SCIF0
+               bool "Kernel low-level debugging messages via SCIF0 on R8A7778"
+               depends on ARCH_R8A7778
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 via SCIF0 on Renesas R-Car M1A (R8A7778).
+
+       config DEBUG_RCAR_GEN1_SCIF2
+               bool "Kernel low-level debugging messages via SCIF2 on R8A7779"
+               depends on ARCH_R8A7779
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 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)"
+               depends on ARCH_R8A7790 || ARCH_R8A7791 || ARCH_R8A7793
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 via SCIF0 on Renesas R-Car H2 (R8A7790), M2-W (R8A7791), or
+                 M2-N (R8A7793).
+
+       config DEBUG_RCAR_GEN2_SCIF2
+               bool "Kernel low-level debugging messages via SCIF2 on R8A7794"
+               depends on ARCH_R8A7794
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 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
+               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).
+
+       config DEBUG_RMOBILE_SCIFA1
+               bool "Kernel low-level debugging messages via SCIFA1 on R8A7740"
+               depends on ARCH_R8A7740
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 via SCIFA1 on Renesas R-Mobile A1 (R8A7740).
+
+       config DEBUG_RMOBILE_SCIFA4
+               bool "Kernel low-level debugging messages via SCIFA4 on SH73A0"
+               depends on ARCH_SH73A0
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 via SCIFA4 on Renesas SH-Mobile AG5 (SH73A0).
+
        config DEBUG_S3C_UART0
                depends on PLAT_SAMSUNG
                select DEBUG_EXYNOS_UART if ARCH_EXYNOS
@@ -723,6 +813,14 @@ choice
                  their output to UART 2. The port must have been initialised
                  by the boot-loader before use.
 
+       config DEBUG_SA1100
+               depends on ARCH_SA1100
+               bool "Use SA1100 UARTs for low-level debug"
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 on SA-11x0 UART ports. The kernel will check for the first
+                 enabled UART in a sequence 3-1-2.
+
        config DEBUG_SOCFPGA_UART
                depends on ARCH_SOCFPGA
                bool "Use SOCFPGA UART for low-level debug"
@@ -731,6 +829,14 @@ choice
                  Say Y here if you want kernel low-level debugging support
                  on SOCFPGA based platforms.
 
+       config DEBUG_SUN9I_UART0
+               bool "Kernel low-level debugging messages via sun9i UART0"
+               depends on MACH_SUN9I
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 on Allwinner A80 based platforms on the UART0.
+
        config DEBUG_SUNXI_UART0
                bool "Kernel low-level debugging messages via sunXi UART0"
                depends on ARCH_SUNXI
@@ -866,6 +972,22 @@ choice
                  Say Y here if you want kernel low-level debugging support
                  for Mediatek mt6589 based platforms on UART0.
 
+       config DEBUG_MT8127_UART0
+               bool "Mediatek mt8127 UART0"
+               depends on ARCH_MEDIATEK
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 for Mediatek mt8127 based platforms on UART0.
+
+       config DEBUG_MT8135_UART3
+               bool "Mediatek mt8135 UART3"
+               depends on ARCH_MEDIATEK
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 for Mediatek mt8135 based platforms on UART3.
+
        config DEBUG_VEXPRESS_UART0_DETECT
                bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
                depends on ARCH_VEXPRESS && CPU_CP15_MMU
@@ -1041,7 +1163,9 @@ config DEBUG_STI_UART
 
 config DEBUG_LL_INCLUDE
        string
+       default "debug/sa1100.S" if DEBUG_SA1100
        default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
+       default "debug/asm9260.S" if DEBUG_ASM9260_UART
        default "debug/clps711x.S" if DEBUG_CLPS711X_UART1 || DEBUG_CLPS711X_UART2
        default "debug/meson.S" if DEBUG_MESON_UARTAO
        default "debug/pl01x.S" if DEBUG_LL_UART_PL01X || DEBUG_UART_PL01X
@@ -1061,6 +1185,14 @@ config DEBUG_LL_INCLUDE
                                 DEBUG_IMX6SX_UART
        default "debug/msm.S" if DEBUG_MSM_UART || DEBUG_QCOM_UARTDM
        default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
+       default "debug/renesas-scif.S" if DEBUG_R7S72100_SCIF2
+       default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF0
+       default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF2
+       default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF0
+       default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF2
+       default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA0
+       default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA1
+       default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA4
        default "debug/s3c24xx.S" if DEBUG_S3C24XX_UART
        default "debug/s5pv210.S" if DEBUG_S5PV210_UART
        default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1
@@ -1106,6 +1238,7 @@ config DEBUG_UART_PHYS
        default 0x02530c00 if DEBUG_KEYSTONE_UART0
        default 0x02531000 if DEBUG_KEYSTONE_UART1
        default 0x03010fe0 if ARCH_RPC
+       default 0x07000000 if DEBUG_SUN9I_UART0
        default 0x10009000 if DEBUG_REALVIEW_STD_PORT || \
                                DEBUG_VEXPRESS_UART0_CA9
        default 0x1010c000 if DEBUG_REALVIEW_PB1176_PORT
@@ -1113,7 +1246,9 @@ config DEBUG_UART_PHYS
        default 0x10126000 if DEBUG_RK3X_UART1
        default 0x101f1000 if ARCH_VERSATILE
        default 0x101fb000 if DEBUG_NOMADIK_UART
+       default 0x11002000 if DEBUG_MT8127_UART0
        default 0x11006000 if DEBUG_MT6589_UART0
+       default 0x11009000 if DEBUG_MT8135_UART3
        default 0x16000000 if ARCH_INTEGRATOR
        default 0x18000300 if DEBUG_BCM_5301X
        default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1
@@ -1135,6 +1270,7 @@ config DEBUG_UART_PHYS
        default 0x78000000 if DEBUG_CNS3XXX
        default 0x7c0003f8 if FOOTBRIDGE
        default 0x78000000 if DEBUG_CNS3XXX
+       default 0x80010000 if DEBUG_ASM9260_UART
        default 0x80070000 if DEBUG_IMX23_UART
        default 0x80074000 if DEBUG_IMX28_UART
        default 0x80230000 if DEBUG_PICOXCELL_UART
@@ -1152,7 +1288,14 @@ config DEBUG_UART_PHYS
        default 0xd4018000 if DEBUG_MMP_UART3
        default 0xe0000000 if ARCH_SPEAR13XX
        default 0xe4007000 if DEBUG_HIP04_UART
+       default 0xe6c40000 if DEBUG_RMOBILE_SCIFA0
+       default 0xe6c50000 if DEBUG_RMOBILE_SCIFA1
+       default 0xe6c80000 if DEBUG_RMOBILE_SCIFA4
+       default 0xe6e58000 if DEBUG_RCAR_GEN2_SCIF2
+       default 0xe6e60000 if DEBUG_RCAR_GEN2_SCIF0
+       default 0xe8008000 if DEBUG_R7S72100_SCIF2
        default 0xf0000be0 if ARCH_EBSA110
+       default 0xf040ab00 if DEBUG_BRCMSTB_UART
        default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE
        default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \
                                ARCH_ORION5X
@@ -1164,32 +1307,42 @@ config DEBUG_UART_PHYS
        default 0xff690000 if DEBUG_RK32_UART2
        default 0xffc02000 if DEBUG_SOCFPGA_UART
        default 0xffd82340 if ARCH_IOP13XX
+       default 0xffe40000 if DEBUG_RCAR_GEN1_SCIF0
+       default 0xffe42000 if DEBUG_RCAR_GEN1_SCIF2
        default 0xfff36000 if DEBUG_HIGHBANK_UART
        default 0xfffe8600 if DEBUG_UART_BCM63XX
        default 0xfffff700 if ARCH_IOP33X
        depends on 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_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
-               DEBUG_UART_BCM63XX
+               DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \
+               DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \
+               DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
+               DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
+               DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
+               DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
 
 config DEBUG_UART_VIRT
        hex "Virtual base address of debug 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
        default 0xf0201000 if DEBUG_BCM2835
        default 0xf1000300 if DEBUG_BCM_5301X
+       default 0xf1002000 if DEBUG_MT8127_UART0
        default 0xf1006000 if DEBUG_MT6589_UART0
+       default 0xf1009000 if DEBUG_MT8135_UART3
        default 0xf11f1000 if ARCH_VERSATILE
        default 0xf1600000 if ARCH_INTEGRATOR
        default 0xf1c28000 if DEBUG_SUNXI_UART0
        default 0xf1c28400 if DEBUG_SUNXI_UART1
        default 0xf1f02800 if DEBUG_SUNXI_R_UART
-       default 0xf2100000 if DEBUG_PXA_UART1
+       default 0xf6200000 if DEBUG_PXA_UART1
        default 0xf4090000 if ARCH_LPC32XX
        default 0xf4200000 if ARCH_GEMINI
+       default 0xf7000000 if DEBUG_SUN9I_UART0
        default 0xf7000000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART0 || \
                                DEBUG_S3C2410_UART0)
        default 0xf7004000 if DEBUG_S3C24XX_UART && (DEBUG_S3C_UART1 || \
@@ -1204,6 +1357,7 @@ config DEBUG_UART_VIRT
        default 0xfb002000 if DEBUG_CNS3XXX
        default 0xfb009000 if DEBUG_REALVIEW_STD_PORT
        default 0xfb10c000 if DEBUG_REALVIEW_PB1176_PORT
+       default 0xfc40ab00 if DEBUG_BRCMSTB_UART
        default 0xfcfe8600 if DEBUG_UART_BCM63XX
        default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
        default 0xfd000000 if ARCH_SPEAR13XX
@@ -1244,12 +1398,12 @@ config DEBUG_UART_VIRT
        depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
                DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
                DEBUG_MSM_UART || DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
-               DEBUG_UART_BCM63XX
+               DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART
 
 config DEBUG_UART_8250_SHIFT
        int "Register offset shift for the 8250 debug UART"
        depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
-       default 0 if FOOTBRIDGE || ARCH_IOP32X
+       default 0 if FOOTBRIDGE || ARCH_IOP32X || DEBUG_BCM_5301X
        default 2
 
 config DEBUG_UART_8250_WORD
@@ -1260,7 +1414,8 @@ config DEBUG_UART_8250_WORD
                ARCH_KEYSTONE || \
                DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
                DEBUG_DAVINCI_DA8XX_UART2 || \
-               DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2
+               DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2 || \
+               DEBUG_BRCMSTB_UART
 
 config DEBUG_UART_8250_FLOW_CONTROL
        bool "Enable flow control for 8250 UART"
index 034a94904d69e5578e3792408368ebc6c1d08a77..c1785eec2cf772e582b48fade2b7694748d381cb 100644 (file)
@@ -312,8 +312,12 @@ $(INSTALL_TARGETS):
        $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
 
 PHONY += dtbs dtbs_install
-dtbs dtbs_install: prepare scripts
-       $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $@
+
+dtbs: prepare scripts
+       $(Q)$(MAKE) $(build)=$(boot)/dts
+
+dtbs_install:
+       $(Q)$(MAKE) $(dtbinst)=$(boot)/dts
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
index 413fd94b53012dacc6596d2e9b225c04a7dab97a..68be9017593df10f235ca228a6837aaa11f5c818 100644 (file)
@@ -397,8 +397,7 @@ dtb_check_done:
                add     sp, sp, r6
 #endif
 
-               tst     r4, #1
-               bleq    cache_clean_flush
+               bl      cache_clean_flush
 
                adr     r0, BSYM(restart)
                add     r0, r0, r6
@@ -1047,6 +1046,8 @@ cache_clean_flush:
                b       call_cache_fn
 
 __armv4_mpu_cache_flush:
+               tst     r4, #1
+               movne   pc, lr
                mov     r2, #1
                mov     r3, #0
                mcr     p15, 0, ip, c7, c6, 0   @ invalidate D cache
@@ -1064,6 +1065,8 @@ __armv4_mpu_cache_flush:
                mov     pc, lr
                
 __fa526_cache_flush:
+               tst     r4, #1
+               movne   pc, lr
                mov     r1, #0
                mcr     p15, 0, r1, c7, c14, 0  @ clean and invalidate D cache
                mcr     p15, 0, r1, c7, c5, 0   @ flush I cache
@@ -1072,13 +1075,16 @@ __fa526_cache_flush:
 
 __armv6_mmu_cache_flush:
                mov     r1, #0
-               mcr     p15, 0, r1, c7, c14, 0  @ clean+invalidate D
+               tst     r4, #1
+               mcreq   p15, 0, r1, c7, c14, 0  @ clean+invalidate D
                mcr     p15, 0, r1, c7, c5, 0   @ invalidate I+BTB
-               mcr     p15, 0, r1, c7, c15, 0  @ clean+invalidate unified
+               mcreq   p15, 0, r1, c7, c15, 0  @ clean+invalidate unified
                mcr     p15, 0, r1, c7, c10, 4  @ drain WB
                mov     pc, lr
 
 __armv7_mmu_cache_flush:
+               tst     r4, #1
+               bne     iflush
                mrc     p15, 0, r10, c0, c1, 5  @ read ID_MMFR1
                tst     r10, #0xf << 16         @ hierarchical cache (ARMv7)
                mov     r10, #0
@@ -1139,6 +1145,8 @@ iflush:
                mov     pc, lr
 
 __armv5tej_mmu_cache_flush:
+               tst     r4, #1
+               movne   pc, lr
 1:             mrc     p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache
                bne     1b
                mcr     p15, 0, r0, c7, c5, 0   @ flush I cache
@@ -1146,6 +1154,8 @@ __armv5tej_mmu_cache_flush:
                mov     pc, lr
 
 __armv4_mmu_cache_flush:
+               tst     r4, #1
+               movne   pc, lr
                mov     r2, #64*1024            @ default: 32K dcache size (*2)
                mov     r11, #32                @ default: 32 byte line size
                mrc     p15, 0, r3, c0, c0, 1   @ read cache type
@@ -1179,6 +1189,8 @@ no_cache_id:
 
 __armv3_mmu_cache_flush:
 __armv3_mpu_cache_flush:
+               tst     r4, #1
+               movne   pc, lr
                mov     r1, #0
                mcr     p15, 0, r1, c7, c0, 0   @ invalidate whole cache v3
                mov     pc, lr
index 38c89cafa1ab8ea3ee682b8ccb0c02af8739f785..6a3d9a6c4497915587d4deceac8829e4736ea3f0 100644 (file)
@@ -54,8 +54,17 @@ dtb-$(CONFIG_ARCH_AT91)      += at91-sama5d4ek.dtb
 dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb
 dtb-$(CONFIG_ARCH_AXXIA) += axm5516-amarillo.dtb
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
-dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb
+dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b-plus.dtb
+dtb-$(CONFIG_ARCH_BCM_5301X) += \
+       bcm4708-buffalo-wzr-1750dhp.dtb \
+       bcm4708-netgear-r6250.dtb \
+       bcm4708-netgear-r6300-v2.dtb \
+       bcm47081-asus-rt-n18u.dtb \
+       bcm47081-buffalo-wzr-600dhp2.dtb
 dtb-$(CONFIG_ARCH_BCM_63XX) += bcm963138dvt.dtb
+dtb-$(CONFIG_ARCH_BCM_CYGNUS) += bcm911360_entphn.dtb \
+       bcm911360k.dtb \
+       bcm958300k.dtb
 dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm28155-ap.dtb \
        bcm21664-garnet.dtb
 dtb-$(CONFIG_ARCH_BERLIN) += \
@@ -67,7 +76,9 @@ dtb-$(CONFIG_ARCH_BRCMSTB) += \
 dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
        da850-evm.dtb
 dtb-$(CONFIG_ARCH_EFM32) += efm32gg-dk3750.dtb
-dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
+dtb-$(CONFIG_ARCH_EXYNOS) += exynos3250-monk.dtb \
+       exynos3250-rinato.dtb \
+       exynos4210-origen.dtb \
        exynos4210-smdkv310.dtb \
        exynos4210-trats.dtb \
        exynos4210-universal_c210.dtb \
@@ -81,6 +92,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
        exynos5250-arndale.dtb \
        exynos5250-smdk5250.dtb \
        exynos5250-snow.dtb \
+       exynos5250-spring.dtb \
        exynos5260-xyref5260.dtb \
        exynos5410-smdk5410.dtb \
        exynos5420-arndale-octa.dtb \
@@ -104,6 +116,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
        kirkwood-d2net.dtb \
        kirkwood-db-88f6281.dtb \
        kirkwood-db-88f6282.dtb \
+       kirkwood-dir665.dtb \
        kirkwood-dns320.dtb \
        kirkwood-dns325.dtb \
        kirkwood-dockstar.dtb \
@@ -240,6 +253,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
        imx6q-sabrelite.dtb \
        imx6q-sabresd.dtb \
        imx6q-sbc6x.dtb \
+       imx6q-tbs2910.dtb \
        imx6q-udoo.dtb \
        imx6q-wandboard.dtb \
        imx6q-wandboard-revb1.dtb \
@@ -250,6 +264,9 @@ dtb-$(CONFIG_ARCH_MXC) += \
        imx6q-tx6q-1110.dtb \
        imx6sl-evk.dtb \
        imx6sx-sdb.dtb \
+       ls1021a-qds.dtb \
+       ls1021a-twr.dtb \
+       vf500-colibri-eval-v3.dtb \
        vf610-colibri-eval-v3.dtb \
        vf610-cosmic.dtb \
        vf610-twr.dtb
@@ -274,7 +291,8 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
        imx28-m28evk.dtb \
        imx28-sps1.dtb \
        imx28-tx28.dtb
-dtb-$(CONFIG_ARCH_NOMADIK) += ste-nomadik-s8815.dtb
+dtb-$(CONFIG_ARCH_NOMADIK) += ste-nomadik-s8815.dtb \
+       ste-nomadik-nhk15.dtb
 dtb-$(CONFIG_ARCH_NSPIRE) += nspire-cx.dtb \
        nspire-tp.dtb \
        nspire-clp.dtb
@@ -302,7 +320,9 @@ dtb-$(CONFIG_ARCH_OMAP3) += am3517-craneboard.dtb \
        omap3-ha.dtb \
        omap3-ha-lcd.dtb \
        omap3-igep0020.dtb \
+       omap3-igep0020-rev-f.dtb \
        omap3-igep0030.dtb \
+       omap3-igep0030-rev-g.dtb \
        omap3-ldp.dtb \
        omap3-lilly-dbb056.dtb \
        omap3-n900.dtb \
@@ -331,7 +351,8 @@ dtb-$(CONFIG_SOC_AM33XX) += am335x-base0033.dtb \
        am335x-evm.dtb \
        am335x-evmsk.dtb \
        am335x-nano.dtb \
-       am335x-pepper.dtb
+       am335x-pepper.dtb \
+       am335x-lxm.dtb
 dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \
        omap4-panda.dtb \
        omap4-panda-a4.dtb \
@@ -347,6 +368,7 @@ dtb-$(CONFIG_SOC_OMAP5) += omap5-cm-t54.dtb \
        omap5-sbc-t54.dtb \
        omap5-uevm.dtb
 dtb-$(CONFIG_SOC_DRA7XX) += dra7-evm.dtb \
+       am57xx-beagle-x15.dtb \
        dra72-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-d2-network.dtb \
        orion5x-lacie-ethernet-disk-mini-v2.dtb \
@@ -363,8 +385,10 @@ dtb-$(CONFIG_ARCH_QCOM) += \
        qcom-msm8660-surf.dtb \
        qcom-msm8960-cdp.dtb \
        qcom-msm8974-sony-xperia-honami.dtb
+dtb-$(CONFIG_ARCH_REALVIEW) += arm-realview-pb1176.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
        rk3066a-bqcurie2.dtb \
+       rk3066a-marsboard.dtb \
        rk3188-radxarock.dtb \
        rk3288-evb-act8846.dtb \
        rk3288-evb-rk808.dtb
@@ -376,27 +400,27 @@ dtb-$(CONFIG_ARCH_S5PV210) += s5pv210-aquila.dtb \
        s5pv210-smdkc110.dtb \
        s5pv210-smdkv210.dtb \
        s5pv210-torbreck.dtb
-dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += r7s72100-genmai.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 \
-       r8a7791-koelsch.dtb \
        r8a7790-lager.dtb \
+       sh7372-mackerel.dtb \
        sh73a0-kzm9g.dtb \
-       sh73a0-kzm9g-reference.dtb \
-       r8a73a4-ape6evm.dtb \
-       r8a73a4-ape6evm-reference.dtb \
-       sh7372-mackerel.dtb
+       sh73a0-kzm9g-reference.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \
        r7s72100-genmai.dtb \
        r8a7740-armadillo800eva.dtb \
+       r8a7779-marzen.dtb \
+       r8a7790-lager.dtb \
        r8a7791-henninger.dtb \
        r8a7791-koelsch.dtb \
-       r8a7790-lager.dtb \
-       r8a7779-marzen.dtb \
        r8a7794-alt.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_arria5_socdk.dtb \
+       socfpga_arria10_socdk.dtb \
        socfpga_cyclone5_socdk.dtb \
        socfpga_cyclone5_sockit.dtb \
        socfpga_cyclone5_socrates.dtb \
@@ -409,6 +433,7 @@ dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
        spear320-hmi.dtb
 dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
 dtb-$(CONFIG_ARCH_STI)+= stih407-b2120.dtb \
+       stih410-b2120.dtb \
        stih415-b2000.dtb \
        stih415-b2020.dtb \
        stih416-b2000.dtb \
@@ -435,15 +460,20 @@ dtb-$(CONFIG_MACH_SUN6I) += \
        sun6i-a31-hummingbird.dtb \
        sun6i-a31-m9.dtb
 dtb-$(CONFIG_MACH_SUN7I) += \
+       sun7i-a20-bananapi.dtb \
        sun7i-a20-cubieboard2.dtb \
        sun7i-a20-cubietruck.dtb \
        sun7i-a20-hummingbird.dtb \
        sun7i-a20-i12-tvbox.dtb \
+       sun7i-a20-m3.dtb \
        sun7i-a20-olinuxino-lime.dtb \
+       sun7i-a20-olinuxino-lime2.dtb \
        sun7i-a20-olinuxino-micro.dtb \
        sun7i-a20-pcduino3.dtb
 dtb-$(CONFIG_MACH_SUN8I) += \
        sun8i-a23-ippo-q8h-v5.dtb
+dtb-$(CONFIG_MACH_SUN9I) += \
+       sun9i-a80-optimus.dtb
 dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
        tegra20-iris-512.dtb \
        tegra20-medcom-wide.dtb \
@@ -489,13 +519,15 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
        zynq-parallella.dtb \
        zynq-zc702.dtb \
        zynq-zc706.dtb \
-       zynq-zed.dtb
+       zynq-zed.dtb \
+       zynq-zybo.dtb
 dtb-$(CONFIG_MACH_ARMADA_370) += \
        armada-370-db.dtb \
        armada-370-mirabox.dtb \
        armada-370-netgear-rn102.dtb \
        armada-370-netgear-rn104.dtb \
-       armada-370-rd.dtb
+       armada-370-rd.dtb \
+       armada-370-synology-ds213j.dtb
 dtb-$(CONFIG_MACH_ARMADA_375) += \
        armada-375-db.dtb
 dtb-$(CONFIG_MACH_ARMADA_38X) += \
@@ -508,24 +540,20 @@ dtb-$(CONFIG_MACH_ARMADA_XP) += \
        armada-xp-lenovo-ix4-300d.dtb \
        armada-xp-matrix.dtb \
        armada-xp-netgear-rn2120.dtb \
-       armada-xp-openblocks-ax3-4.dtb
+       armada-xp-openblocks-ax3-4.dtb \
+       armada-xp-synology-ds414.dtb
 dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \
        dove-cubox.dtb \
        dove-cubox-es.dtb \
        dove-d2plug.dtb \
        dove-d3plug.dtb \
        dove-dove-db.dtb
-dtb-$(CONFIG_ARCH_MEDIATEK) += mt6589-aquaris5.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt6589-aquaris5.dtb \
+       mt6592-evb.dtb \
+       mt8127-moose.dtb \
+       mt8135-evbp1.dtb
 
-targets += dtbs dtbs_install
-targets += $(dtb-y)
 endif
 
-# *.dtb used to be generated in the directory above. Clean out the
-# old build results so people don't accidentally use them.
-dtbs: $(addprefix $(obj)/, $(dtb-y))
-       $(Q)rm -f $(obj)/../*.dtb
-
-clean-files := *.dtb
-
-dtbs_install: $(addsuffix _dtbinst_, $(dtb-y))
+always         := $(dtb-y)
+clean-files    := *.dtb
index e2156a583de76a2cd67dcbc06593fb192caaf7e4..54f118c08db8eefbe69308fac3f6d8ed76640083 100644 (file)
                        0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
                >;
        };
+
+       dcan1_pins_default: dcan1_pins_default {
+               pinctrl-single,pins = <
+                       0x168 (PIN_OUTPUT | MUX_MODE2) /* uart0_ctsn.d_can1_tx */
+                       0x16c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart0_rtsn.d_can1_rx */
+               >;
+       };
 };
 
 &uart0 {
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&nandflash_pins_s0>;
-       ranges = <0 0 0x08000000 0x10000000>;   /* CS0: NAND */
+       ranges = <0 0 0x08000000 0x1000000>;    /* CS0: 16MB for NAND */
        nand@0,0 {
-               reg = <0 0 0>; /* CS0, offset 0 */
+               reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
                ti,nand-ecc-opt = "bch8";
                ti,elm-id = <&elm>;
                nand-bus-width = <8>;
                        reg = <0x00060000 0x00020000>;
                };
                partition@4 {
-                       label = "NAND.u-boot-spl";
+                       label = "NAND.u-boot-spl-os";
                        reg = <0x00080000 0x00040000>;
                };
                partition@5 {
 &aes {
        status = "okay";
 };
+
+&dcan1 {
+       status = "disabled";    /* Enable only if Profile 1 is selected */
+       pinctrl-names = "default";
+       pinctrl-0 = <&dcan1_pins_default>;
+};
index a1a0cc5eb35cb8ac9851591bb5b7b6fcc69f483c..c0e1135256cca7b781504e4df587a2ebd7768294 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&nandflash_pins>;
 
-       ranges = <0 0 0x08000000 0x10000000>;   /* CS0: NAND */
+       ranges = <0 0 0x08000000 0x1000000>;    /* CS0: 16MB for NAND */
 
        nand@0,0 {
-               reg = <0 0 0>; /* CS0, offset 0 */
+               reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
                nand-bus-width = <8>;
                ti,nand-ecc-opt = "bch8";
                gpmc,device-width = <1>;
diff --git a/arch/arm/boot/dts/am335x-lxm.dts b/arch/arm/boot/dts/am335x-lxm.dts
new file mode 100644 (file)
index 0000000..7266a00
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2014 NovaTech LLC - http://www.novatechweb.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+       model = "NovaTech OrionLXm";
+       compatible = "novatech,am335x-lxm", "ti,am33xx";
+
+       cpus {
+               cpu@0 {
+                       cpu0-supply = <&vdd1_reg>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000>; /* 512 MB */
+       };
+
+       /* Power supply provides a fixed 5V @2A */
+       vbat: fixedregulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "vbat";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+       };
+
+       /* Power supply provides a fixed 3.3V @3A */
+       vmmcsd_fixed: fixedregulator@1 {
+               compatible = "regulator-fixed";
+               regulator-name = "vmmcsd_fixed";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+       };
+};
+
+&am33xx_pinmux {
+       mmc1_pins: pinmux_mmc1_pins {
+               pinctrl-single,pins = <
+                       0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)     /* mmc0_dat3 */
+                       0xf4 (PIN_INPUT_PULLUP | MUX_MODE0)     /* mmc0_dat2 */
+                       0xf8 (PIN_INPUT_PULLUP | MUX_MODE0)     /* mmc0_dat1 */
+                       0xfc (PIN_INPUT_PULLUP | MUX_MODE0)     /* mmc0_dat0 */
+                       0x100 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mmc0_clk */
+                       0x104 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mmc0_cmd */
+               >;
+       };
+
+       i2c0_pins: pinmux_i2c0_pins {
+               pinctrl-single,pins = <
+                       0x188 (PIN_INPUT | MUX_MODE0)   /* i2c0_sda.i2c0_sda */
+                       0x18c (PIN_INPUT | MUX_MODE0)   /* i2c0_scl.i2c0_scl */
+               >;
+       };
+
+       cpsw_default: cpsw_default {
+               pinctrl-single,pins = <
+                       /* Slave 1 */
+                       0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii1_int */
+                       0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1)  /* rmii1_crs_dv */
+                       0x110 (PIN_INPUT_PULLDOWN | MUX_MODE1)  /* rmii1_rxer */
+                       0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* rmii1_txen */
+                       0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* rmii1_td1 */
+                       0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* rmii1_td0 */
+                       0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1)  /* rmii1_rd1 */
+                       0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1)  /* rmii1_rd0 */
+                       0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0)  /* rmii1_refclk */
+
+                       /* Slave 2 */
+                       0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)  /* rmii2_txen */
+                       0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)  /* rmii2_td1 */
+                       0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)  /* rmii2_td0 */
+                       0x68 (PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_rd1 */
+                       0x6c (PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_rd0 */
+                       0x70 (PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_crs_dv */
+                       0x74 (PIN_INPUT_PULLDOWN | MUX_MODE3)   /* rmii2_rxer */
+                       0x78 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_int */
+                       0x108 (PIN_INPUT_PULLDOWN | MUX_MODE1)  /* rmii2_refclk */
+               >;
+       };
+
+       cpsw_sleep: cpsw_sleep {
+               pinctrl-single,pins = <
+                       /* Slave 1 reset value */
+                       0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii1_int */
+                       0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_crs_dv */
+                       0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_rxer */
+                       0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_txen */
+                       0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_td1 */
+                       0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_td0 */
+                       0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_rd1 */
+                       0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_rd0 */
+                       0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii1_refclk */
+
+                       /* Slave 2 reset value*/
+                       0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_txen */
+                       0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_td1 */
+                       0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_td0 */
+                       0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_rd1 */
+                       0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_rd0 */
+                       0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_crs_dv */
+                       0x74 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_rxer */
+                       0x78 (PIN_INPUT_PULLDOWN | MUX_MODE7)   /* rmii2_int */
+                       0x108 (PIN_INPUT_PULLDOWN | MUX_MODE7)  /* rmii2_refclk */
+               >;
+       };
+
+       davinci_mdio_default: davinci_mdio_default {
+               pinctrl-single,pins = <
+                       /* MDIO */
+                       0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)    /* mdio_data.mdio_data */
+                       0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)                   /* mdio_clk.mdio_clk */
+               >;
+       };
+
+       davinci_mdio_sleep: davinci_mdio_sleep {
+               pinctrl-single,pins = <
+                       /* MDIO reset value */
+                       0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+               >;
+       };
+
+       emmc_pins: pinmux_emmc_pins {
+               pinctrl-single,pins = <
+                       0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+                       0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+                       0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+                       0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+                       0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+                       0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+                       0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+                       0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+                       0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+                       0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+               >;
+       };
+
+       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 */
+               >;
+       };
+};
+
+&i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c0_pins>;
+
+       status = "okay";
+       clock-frequency = <400000>;
+
+       serial_config1: serial_config1@20 {
+               compatible = "nxp,pca9539";
+               reg = <0x20>;
+       };
+
+       serial_config2: serial_config2@21 {
+               compatible = "nxp,pca9539";
+               reg = <0x21>;
+       };
+
+       tps: tps@2d {
+               compatible = "ti,tps65910";
+               reg = <0x2d>;
+       };
+};
+
+/include/ "tps65910.dtsi"
+
+&tps {
+       vcc1-supply = <&vbat>;
+       vcc2-supply = <&vbat>;
+       vcc3-supply = <&vbat>;
+       vcc4-supply = <&vbat>;
+       vcc5-supply = <&vbat>;
+       vcc6-supply = <&vbat>;
+       vcc7-supply = <&vbat>;
+       vccio-supply = <&vbat>;
+
+       regulators {
+               /* vrtc - unused */
+
+               vio_reg: regulator@1 {
+                       regulator-name = "vio_1v5,ddr";
+                       regulator-min-microvolt = <1500000>;
+                       regulator-max-microvolt = <1500000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               vdd1_reg: regulator@2 {
+                       regulator-name = "vdd1,mpu";
+                       regulator-min-microvolt = <600000>;
+                       regulator-max-microvolt = <1500000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               vdd2_reg: regulator@3 {
+                       regulator-name = "vdd2_1v1,core";
+                       regulator-min-microvolt = <1100000>;
+                       regulator-max-microvolt = <1100000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               /* vdd3 - unused */
+
+               /* vdig1 - unused */
+
+               vdig2_reg: regulator@6 {
+                       regulator-name = "vdig2_1v8,vdds_pll";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               /* vpll - unused */
+
+               vdac_reg: regulator@8 {
+                       regulator-name = "vdac_1v8,vdds";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               vaux1_reg: regulator@9 {
+                       regulator-name = "vaux1_1v8,usb";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               vaux2_reg: regulator@10 {
+                       regulator-name = "vaux2_3v3,io";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               vaux33_reg: regulator@11 {
+                       regulator-name = "vaux33_3v3,usb";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               vmmc_reg: regulator@12 {
+                       regulator-name = "vmmc_3v3,io";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+       };
+};
+
+&sham {
+       status = "okay";
+};
+
+&aes {
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+
+       status = "okay";
+};
+
+&usb {
+       status = "okay";
+};
+
+&usb_ctrl_mod {
+       status = "okay";
+};
+
+&usb0_phy {
+       status = "okay";
+};
+
+&usb1_phy {
+       status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+       dr_mode = "host";
+};
+
+&usb1 {
+       status = "okay";
+       dr_mode = "host";
+};
+
+&cppi41dma  {
+       status = "okay";
+};
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <5>;
+       phy-mode = "rmii";
+       dual_emac_res_vlan = <2>;
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <4>;
+       phy-mode = "rmii";
+       dual_emac_res_vlan = <3>;
+};
+
+&mac {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cpsw_default>;
+       pinctrl-1 = <&cpsw_sleep>;
+       dual_emac = <1>;
+       status = "okay";
+};
+
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+       status = "okay";
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&vmmcsd_fixed>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&emmc_pins>;
+       vmmc-supply = <&vmmcsd_fixed>;
+       bus-width = <8>;
+       ti,non-removable;
+       status = "okay";
+};
+
index 831810583823b78f735a11b354c715461f376401..befe713b3e1bb01c1d1232854cd8f8a7142fd7ae 100644 (file)
                };
        };
 
+       am33xx_control_module: control_module@4a002000 {
+               compatible = "syscon";
+               reg = <0x44e10000 0x7fc>;
+       };
+
        am33xx_pinmux: pinmux@44e10800 {
                compatible = "pinctrl-single";
                reg = <0x44e10800 0x0238>;
                        reg = <0x44e09000 0x2000>;
                        interrupts = <72>;
                        status = "disabled";
+                       dmas = <&edma 26>, <&edma 27>;
+                       dma-names = "tx", "rx";
                };
 
                uart1: serial@48022000 {
                        reg = <0x48022000 0x2000>;
                        interrupts = <73>;
                        status = "disabled";
+                       dmas = <&edma 28>, <&edma 29>;
+                       dma-names = "tx", "rx";
                };
 
                uart2: serial@48024000 {
                        reg = <0x48024000 0x2000>;
                        interrupts = <74>;
                        status = "disabled";
+                       dmas = <&edma 30>, <&edma 31>;
+                       dma-names = "tx", "rx";
                };
 
                uart3: serial@481a6000 {
                        interrupts = <91>;
                };
 
-               dcan0: d_can@481cc000 {
-                       compatible = "bosch,d_can";
+               dcan0: can@481cc000 {
+                       compatible = "ti,am3352-d_can";
                        ti,hwmods = "d_can0";
-                       reg = <0x481cc000 0x2000
-                               0x44e10644 0x4>;
+                       reg = <0x481cc000 0x2000>;
+                       clocks = <&dcan0_fck>;
+                       clock-names = "fck";
+                       syscon-raminit = <&am33xx_control_module 0x644 0>;
                        interrupts = <52>;
                        status = "disabled";
                };
 
-               dcan1: d_can@481d0000 {
-                       compatible = "bosch,d_can";
+               dcan1: can@481d0000 {
+                       compatible = "ti,am3352-d_can";
                        ti,hwmods = "d_can1";
-                       reg = <0x481d0000 0x2000
-                               0x44e10644 0x4>;
+                       reg = <0x481d0000 0x2000>;
+                       clocks = <&dcan1_fck>;
+                       clock-names = "fck";
+                       syscon-raminit = <&am33xx_control_module 0x644 1>;
                        interrupts = <55>;
                        status = "disabled";
                };
                        reg = <0x480C8000 0x200>;
                        interrupts = <77>;
                        ti,hwmods = "mailbox";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <8>;
                        mbox_wkupm3: wkup_m3 {
index 46660ffd2b65bbe90100b2b251b29fb6528afe31..d42d7865dd53b1c3b3d7ca4c7ff5d508094cd859 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>;
                        reg = <0x480C8000 0x200>;
                        interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <8>;
                        mbox_wkupm3: wkup_m3 {
                        };
                };
 
+               tscadc: tscadc@44e0d000 {
+                       compatible = "ti,am3359-tscadc";
+                       reg = <0x44e0d000 0x1000>;
+                       ti,hwmods = "adc_tsc";
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&adc_tsc_fck>;
+                       clock-names = "fck";
+                       status = "disabled";
+
+                       tsc {
+                               compatible = "ti,am3359-tsc";
+                       };
+
+                       adc {
+                               #io-channel-cells = <1>;
+                               compatible = "ti,am3359-adc";
+                       };
+
+               };
+
                sham: sham@53100000 {
                        compatible = "ti,omap5-sham";
                        ti,hwmods = "sham";
                        compatible = "mmio-sram";
                        reg = <0x40300000 0x40000>; /* 256k */
                };
+
+               dcan0: can@481cc000 {
+                       compatible = "ti,am4372-d_can", "ti,am3352-d_can";
+                       ti,hwmods = "d_can0";
+                       clocks = <&dcan0_fck>;
+                       clock-names = "fck";
+                       reg = <0x481cc000 0x2000>;
+                       syscon-raminit = <&am43xx_control_module 0x644 0>;
+                       interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               dcan1: can@481d0000 {
+                       compatible = "ti,am4372-d_can", "ti,am3352-d_can";
+                       ti,hwmods = "d_can1";
+                       clocks = <&dcan1_fck>;
+                       clock-names = "fck";
+                       reg = <0x481d0000 0x2000>;
+                       syscon-raminit = <&am43xx_control_module 0x644 1>;
+                       interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
        };
 };
 
index e7ac47fa6615e33ee52e3ef58025721f49c7eb08..7eaae4cf9f89e724c2ea936b21118d5e60f97dba 100644 (file)
                        0x238 (PIN_OUTPUT_PULLUP | MUX_MODE7)
                >;
        };
+
+       dcan0_default: dcan0_default_pins {
+               pinctrl-single,pins = <
+                       0x178 (PIN_OUTPUT | MUX_MODE2)          /* uart1_ctsn.d_can0_tx */
+                       0x17c (PIN_INPUT_PULLUP | MUX_MODE2)    /* uart1_rtsn.d_can0_rx */
+               >;
+       };
+
+       dcan1_default: dcan1_default_pins {
+               pinctrl-single,pins = <
+                       0x180 (PIN_OUTPUT | MUX_MODE2)          /* uart1_rxd.d_can1_tx */
+                       0x184 (PIN_INPUT_PULLUP | MUX_MODE2)    /* uart1_txd.d_can1_rx */
+               >;
+       };
 };
 
 &i2c0 {
                dcdc3: regulator-dcdc3 {
                        compatible = "ti,tps65218-dcdc3";
                        regulator-name = "vdcdc3";
-                       regulator-min-microvolt = <1350000>;
-                       regulator-max-microvolt = <1350000>;
+                       regulator-min-microvolt = <1500000>;
+                       regulator-max-microvolt = <1500000>;
                        regulator-boot-on;
                        regulator-always-on;
                };
        status = "okay";
 };
 
+&tscadc {
+       status = "okay";
+
+       adc {
+               ti,adc-channels = <0 1 2 3 4 5 6 7>;
+       };
+};
+
 &ecap0 {
        status = "okay";
        pinctrl-names = "default";
                };
        };
 };
+
+&dcan0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&dcan0_default>;
+       status = "okay";
+};
+
+&dcan1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&dcan1_default>;
+       status = "okay";
+};
index 859ff3d620ee6734bcd0e802cf53fd8b94069547..87aa4f3b8b3d516807cb9446313283df2c0860b0 100644 (file)
                dcdc3: regulator-dcdc3 {
                        compatible = "ti,tps65218-dcdc3";
                        regulator-name = "vdds_ddr";
-                       regulator-min-microvolt = <1350000>;
-                       regulator-max-microvolt = <1350000>;
+                       regulator-min-microvolt = <1500000>;
+                       regulator-max-microvolt = <1500000>;
                        regulator-boot-on;
                        regulator-always-on;
                };
index ac3e4859935f1ad31da67107eda970eec6f526ba..662261d6b2cab57e8d2b1a55845a463d76fcbdd2 100644 (file)
                dcdc3: regulator-dcdc3 {
                        compatible = "ti,tps65218-dcdc3";
                        regulator-name = "vdcdc3";
-                       regulator-min-microvolt = <1350000>;
-                       regulator-max-microvolt = <1350000>;
+                       regulator-min-microvolt = <1500000>;
+                       regulator-max-microvolt = <1500000>;
                        regulator-boot-on;
                        regulator-always-on;
                };
        status = "okay";        /* Disable QSPI when enabling GPMC (NAND) */
        pinctrl-names = "default";
        pinctrl-0 = <&nand_flash_x8>;
-       ranges = <0 0 0x08000000 0x10000000>;   /* CS0: NAND */
+       ranges = <0 0 0x08000000 0x1000000>;    /* CS0: 16MB for NAND */
        nand@0,0 {
-               reg = <0 0 0>; /* CS0, offset 0 */
+               reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
                ti,nand-ecc-opt = "bch16";
                ti,elm-id = <&elm>;
                nand-bus-width = <8>;
        status = "okay";
 };
 
+&tscadc {
+       status = "okay";
+
+       adc {
+               ti,adc-channels = <0 1 2 3 4 5 6 7>;
+       };
+};
+
 &ecap0 {
                status = "okay";
                pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
new file mode 100644 (file)
index 0000000..49edbda
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "dra74x.dtsi"
+#include <dt-bindings/clk/ti-dra7-atl.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+       model = "TI AM5728 BeagleBoard-X15";
+       compatible = "ti,am572x-beagle-x15", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7";
+
+       aliases {
+               rtc0 = &mcp_rtc;
+               rtc1 = &tps659038_rtc;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x80000000>;
+       };
+
+       vdd_3v3: fixedregulator-vdd_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd_3v3";
+               vin-supply = <&regen1>;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vtt_fixed: fixedregulator-vtt {
+               /* TPS51200 */
+               compatible = "regulator-fixed";
+               regulator-name = "vtt_fixed";
+               vin-supply = <&smps3_reg>;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+               regulator-boot-on;
+               enable-active-high;
+               gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&leds_pins_default>;
+
+               led@0 {
+                       label = "beagle-x15:usr0";
+                       gpios = <&gpio7 9 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "off";
+               };
+
+               led@1 {
+                       label = "beagle-x15:usr1";
+                       gpios = <&gpio7 8 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "cpu0";
+                       default-state = "off";
+               };
+
+               led@2 {
+                       label = "beagle-x15:usr2";
+                       gpios = <&gpio7 14 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "mmc0";
+                       default-state = "off";
+               };
+
+               led@3 {
+                       label = "beagle-x15:usr3";
+                       gpios = <&gpio7 15 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "ide-disk";
+                       default-state = "off";
+               };
+       };
+};
+
+&dra7_pmx_core {
+       leds_pins_default: leds_pins_default {
+               pinctrl-single,pins = <
+                       0x3a8 (PIN_OUTPUT | MUX_MODE14) /* spi1_d1.gpio7_8 */
+                       0x3ac (PIN_OUTPUT | MUX_MODE14) /* spi1_d0.gpio7_9 */
+                       0x3c0 (PIN_OUTPUT | MUX_MODE14) /* spi2_sclk.gpio7_14 */
+                       0x3c4 (PIN_OUTPUT | MUX_MODE14) /* spi2_d1.gpio7_15 */
+               >;
+       };
+
+       i2c1_pins_default: i2c1_pins_default {
+               pinctrl-single,pins = <
+                       0x400 (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c1_sda.sda */
+                       0x404 (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c1_scl.scl */
+               >;
+       };
+
+       i2c3_pins_default: i2c3_pins_default {
+               pinctrl-single,pins = <
+                       0x2a4 (PIN_INPUT| MUX_MODE10)   /* mcasp1_aclkx.i2c3_sda */
+                       0x2a8 (PIN_INPUT| MUX_MODE10)   /* mcasp1_fsx.i2c3_scl */
+               >;
+       };
+
+       uart3_pins_default: uart3_pins_default {
+               pinctrl-single,pins = <
+                       0x248 (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_rxd.rxd */
+                       0x24c (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_txd.txd */
+               >;
+       };
+
+       mmc1_pins_default: mmc1_pins_default {
+               pinctrl-single,pins = <
+                       0x36c (PIN_INPUT | MUX_MODE14)  /* mmc1sdcd.gpio219 */
+                       0x354 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
+                       0x358 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
+                       0x35c (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
+                       0x360 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
+                       0x364 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
+                       0x368 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
+               >;
+       };
+
+       mmc2_pins_default: mmc2_pins_default {
+               pinctrl-single,pins = <
+                       0x9c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
+                       0xb0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
+                       0xa0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
+                       0xa4 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
+                       0xa8 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
+                       0xac (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
+                       0x8c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
+                       0x90 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
+                       0x94 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
+                       0x98 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
+               >;
+       };
+
+       tps659038_pins_default: tps659038_pins_default {
+               pinctrl-single,pins = <
+                       0x418 (PIN_INPUT_PULLUP | MUX_MODE14)   /* wakeup0.gpio1_0 */
+               >;
+       };
+
+       tmp102_pins_default: tmp102_pins_default {
+               pinctrl-single,pins = <
+                       0x3C8 (PIN_INPUT_PULLUP | MUX_MODE14)   /* spi2_d0.gpio7_16 */
+               >;
+       };
+
+       mcp79410_pins_default: mcp79410_pins_default {
+               pinctrl-single,pins = <
+                       0x424 (PIN_INPUT_PULLUP | MUX_MODE1)    /* wakeup3.sys_nirq1 */
+               >;
+       };
+
+       usb1_pins: pinmux_usb1_pins {
+               pinctrl-single,pins = <
+                       0x280 (PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
+               >;
+       };
+
+};
+
+&i2c1 {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins_default>;
+       clock-frequency = <400000>;
+
+       tps659038: tps659038@58 {
+               compatible = "ti,tps659038";
+               reg = <0x58>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&tps659038_pins_default>;
+
+               #interrupt-cells = <2>;
+               interrupt-controller;
+
+               ti,system-power-controller;
+
+               tps659038_pmic {
+                       compatible = "ti,tps659038-pmic";
+
+                       regulators {
+                               smps12_reg: smps12 {
+                                       /* VDD_MPU */
+                                       regulator-name = "smps12";
+                                       regulator-min-microvolt = < 850000>;
+                                       regulator-max-microvolt = <1250000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               smps3_reg: smps3 {
+                                       /* VDD_DDR */
+                                       regulator-name = "smps3";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               smps45_reg: smps45 {
+                                       /* VDD_DSPEVE, VDD_IVA, VDD_GPU */
+                                       regulator-name = "smps45";
+                                       regulator-min-microvolt = < 850000>;
+                                       regulator-max-microvolt = <1150000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               smps6_reg: smps6 {
+                                       /* VDD_CORE */
+                                       regulator-name = "smps6";
+                                       regulator-min-microvolt = <850000>;
+                                       regulator-max-microvolt = <1030000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               /* SMPS7 unused */
+
+                               smps8_reg: smps8 {
+                                       /* VDD_1V8 */
+                                       regulator-name = "smps8";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               /* SMPS9 unused */
+
+                               ldo1_reg: ldo1 {
+                                       /* VDD_SD  */
+                                       regulator-name = "ldo1";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-boot-on;
+                               };
+
+                               ldo2_reg: ldo2 {
+                                       /* VDD_SHV5 */
+                                       regulator-name = "ldo2";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               ldo3_reg: ldo3 {
+                                       /* VDDA_1V8_PHY */
+                                       regulator-name = "ldo3";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               ldo9_reg: ldo9 {
+                                       /* VDD_RTC */
+                                       regulator-name = "ldo9";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               ldoln_reg: ldoln {
+                                       /* VDDA_1V8_PLL */
+                                       regulator-name = "ldoln";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               ldousb_reg: ldousb {
+                                       /* VDDA_3V_USB: VDDA_USBHS33 */
+                                       regulator-name = "ldousb";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-boot-on;
+                               };
+
+                               regen1: regen1 {
+                                       /* VDD_3V3_ON */
+                                       regulator-name = "regen1";
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                               };
+                       };
+               };
+
+               tps659038_rtc: tps659038_rtc {
+                       compatible = "ti,palmas-rtc";
+                       interrupt-parent = <&tps659038>;
+                       interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+                       wakeup-source;
+               };
+
+               tps659038_pwr_button: tps659038_pwr_button {
+                       compatible = "ti,palmas-pwrbutton";
+                       interrupt-parent = <&tps659038>;
+                       interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+                       wakeup-source;
+                       ti,palmas-long-press-seconds = <12>;
+               };
+       };
+
+       tmp102: tmp102@48 {
+               compatible = "ti,tmp102";
+               reg = <0x48>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&tmp102_pins_default>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
+
+&i2c3 {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c3_pins_default>;
+       clock-frequency = <400000>;
+
+       mcp_rtc: rtc@6f {
+               compatible = "microchip,mcp7941x";
+               reg = <0x6f>;
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_LOW>;  /* IRQ_SYS_1N */
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&mcp79410_pins_default>;
+
+               vcc-supply = <&vdd_3v3>;
+               wakeup-source;
+       };
+};
+
+&gpio7 {
+       ti,no-reset-on-init;
+       ti,no-idle-on-init;
+};
+
+&cpu0 {
+       cpu0-supply = <&smps12_reg>;
+       voltage-tolerance = <1>;
+};
+
+&uart3 {
+       status = "okay";
+       interrupts-extended = <&gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+                             <&dra7_pmx_core 0x248>;
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart3_pins_default>;
+};
+
+&mmc1 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins_default>;
+
+       vmmc-supply = <&ldo1_reg>;
+       vmmc_aux-supply = <&vdd_3v3>;
+       pbias-supply = <&pbias_mmc_reg>;
+       bus-width = <4>;
+       cd-gpios = <&gpio6 27 0>; /* gpio 219 */
+};
+
+&mmc2 {
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins_default>;
+
+       vmmc-supply = <&vdd_3v3>;
+       bus-width = <8>;
+       ti,non-removable;
+       cap-mmc-dual-data-rate;
+};
+
+&sata {
+       status = "okay";
+};
+
+&usb2_phy1 {
+       phy-supply = <&ldousb_reg>;
+};
+
+&usb1 {
+       dr_mode = "host";
+       pinctrl-names = "default";
+       pinctrl-0 = <&usb1_pins>;
+};
diff --git a/arch/arm/boot/dts/arm-realview-pb1176.dts b/arch/arm/boot/dts/arm-realview-pb1176.dts
new file mode 100644 (file)
index 0000000..ff26c7e
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2014 Linaro Ltd
+ *
+ * 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/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "skeleton.dtsi"
+
+/ {
+       model = "ARM RealView PB1176";
+       compatible = "arm,realview-pb1176";
+
+       chosen { };
+
+       aliases {
+               serial0 = &pb1176_serial0;
+               serial1 = &pb1176_serial1;
+               serial2 = &pb1176_serial2;
+               serial3 = &pb1176_serial3;
+               serial4 = &fpga_serial;
+       };
+
+       memory {
+               /* 128 MiB memory @ 0x0 */
+               reg = <0x00000000 0x08000000>;
+       };
+
+       /* The voltage to the MMC card is hardwired at 3.3V */
+       vmmc: fixedregulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "vmmc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+        };
+
+       xtal24mhz: xtal24mhz@24M {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <24000000>;
+       };
+
+       timclk: timclk@1M {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clock-div = <24>;
+               clock-mult = <1>;
+               clocks = <&xtal24mhz>;
+       };
+
+       mclk: mclk@24M {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clock-div = <1>;
+               clock-mult = <1>;
+               clocks = <&xtal24mhz>;
+       };
+
+       kmiclk: kmiclk@24M {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clock-div = <1>;
+               clock-mult = <1>;
+               clocks = <&xtal24mhz>;
+       };
+
+       sspclk: sspclk@24M {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clock-div = <1>;
+               clock-mult = <1>;
+               clocks = <&xtal24mhz>;
+       };
+
+       uartclk: uartclk@24M {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clock-div = <1>;
+               clock-mult = <1>;
+               clocks = <&xtal24mhz>;
+       };
+
+       /* FIXME: this actually hangs off the PLL clocks */
+       pclk: pclk@0 {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "arm,realview-pb1176-soc", "simple-bus";
+               regmap = <&syscon>;
+               ranges;
+
+               syscon: syscon@10000000 {
+                       compatible = "arm,realview-pb1176-syscon", "syscon";
+                       reg = <0x10000000 0x1000>;
+
+                       led@08.0 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x01>;
+                               label = "versatile:0";
+                               linux,default-trigger = "heartbeat";
+                               default-state = "on";
+                       };
+                       led@08.1 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x02>;
+                               label = "versatile:1";
+                               linux,default-trigger = "mmc0";
+                               default-state = "off";
+                       };
+                       led@08.2 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x04>;
+                               label = "versatile:2";
+                               linux,default-trigger = "cpu0";
+                               default-state = "off";
+                       };
+                       led@08.3 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x08>;
+                               label = "versatile:3";
+                               default-state = "off";
+                       };
+                       led@08.4 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x10>;
+                               label = "versatile:4";
+                               default-state = "off";
+                       };
+                       led@08.5 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x20>;
+                               label = "versatile:5";
+                               default-state = "off";
+                       };
+                       led@08.6 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x40>;
+                               label = "versatile:6";
+                               default-state = "off";
+                       };
+                       led@08.7 {
+                               compatible = "register-bit-led";
+                               offset = <0x08>;
+                               mask = <0x80>;
+                               label = "versatile:7";
+                               default-state = "off";
+                       };
+               };
+
+               /* Primary DevChip GIC synthesized with the CPU */
+               intc_dc1176: interrupt-controller@10120000 {
+                       compatible = "arm,arm1176jzf-devchip-gic", "arm,arm11mp-gic";
+                       #interrupt-cells = <3>;
+                       #address-cells = <1>;
+                       interrupt-controller;
+                       reg = <0x10121000 0x1000>,
+                             <0x10120000 0x100>;
+               };
+
+               L2: l2-cache {
+                       compatible = "arm,l220-cache";
+                       reg = <0x10110000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>;
+                       cache-unified;
+                       cache-level = <2>;
+                       /*
+                        * Override default cache size, sets and
+                        * associativity as these may be erroneously set
+                        * up by boot loader(s).
+                        */
+                       arm,override-auxreg;
+                       cache-size = <131072>; // 128kB
+                       cache-sets = <512>;
+                       cache-line-size = <32>;
+               };
+
+               pmu {
+                       compatible = "arm,arm1176-pmu";
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               timer01: timer@10104000 {
+                       compatible = "arm,sp804", "arm,primecell";
+                       reg = <0x10104000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>, <0 9 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&timclk>, <&timclk>, <&pclk>;
+                       clock-names = "timer1", "timer2", "apb_pclk";
+               };
+
+               timer23: timer@10105000 {
+                       compatible = "arm,sp804", "arm,primecell";
+                       reg = <0x10105000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+                       arm,sp804-has-irq = <1>;
+                       clocks = <&timclk>, <&timclk>, <&pclk>;
+                       clock-names = "timer1", "timer2", "apb_pclk";
+               };
+
+               pb1176_rtc: rtc@10108000 {
+                       compatible = "arm,pl031", "arm,primecell";
+                       reg = <0x10108000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&pclk>;
+                       clock-names = "apb_pclk";
+               };
+
+               pb1176_gpio0: gpio@1010a000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x1010a000 0x1000>;
+                       gpio-controller;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 16 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&pclk>;
+                       clock-names = "apb_pclk";
+               };
+
+               pb1176_ssp: ssp@1010b000 {
+                       compatible = "arm,pl022", "arm,primecell";
+                       reg = <0x1010b000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&sspclk>, <&pclk>;
+                       clock-names = "SSPCLK", "apb_pclk";
+               };
+
+               pb1176_serial0: serial@1010c000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x1010c000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&uartclk>, <&pclk>;
+                       clock-names = "uartclk", "apb_pclk";
+               };
+
+               pb1176_serial1: serial@1010d000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x1010d000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&uartclk>, <&pclk>;
+                       clock-names = "uartclk", "apb_pclk";
+               };
+
+               pb1176_serial2: serial@1010e000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x1010e000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&uartclk>, <&pclk>;
+                       clock-names = "uartclk", "apb_pclk";
+               };
+
+               pb1176_serial3: serial@1010f000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x1010f000 0x1000>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&uartclk>, <&pclk>;
+                       clock-names = "uartclk", "apb_pclk";
+               };
+       };
+
+       /* These peripherals are inside the FPGA rather than the DevChip */
+       fpga {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               ranges;
+
+               fpga_mci: mmcsd@10005000 {
+                       compatible = "arm,pl18x", "arm,primecell";
+                       reg = <0x10005000 0x1000>;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 1 IRQ_TYPE_LEVEL_HIGH>,
+                                       <0 2 IRQ_TYPE_LEVEL_HIGH>;
+                       /* Due to frequent FIFO overruns, use just 500 kHz */
+                       max-frequency = <500000>;
+                       bus-width = <4>;
+                       cap-sd-highspeed;
+                       cap-mmc-highspeed;
+                       clocks = <&mclk>, <&pclk>;
+                       clock-names = "mclk", "apb_pclk";
+                       vmmc-supply = <&vmmc>;
+                       cd-gpios = <&fpga_gpio1 0 GPIO_ACTIVE_LOW>;
+                       wp-gpios = <&fpga_gpio1 1 GPIO_ACTIVE_HIGH>;
+               };
+
+               fpga_kmi0: kmi@10006000 {
+                       compatible = "arm,pl050", "arm,primecell";
+                       reg = <0x10006000 0x1000>;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&kmiclk>, <&pclk>;
+                       clock-names = "KMIREFCLK", "apb_pclk";
+               };
+
+               fpga_kmi1: kmi@10007000 {
+                       compatible = "arm,pl050", "arm,primecell";
+                       reg = <0x10007000 0x1000>;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&kmiclk>, <&pclk>;
+                       clock-names = "KMIREFCLK", "apb_pclk";
+               };
+
+               fpga_charlcd: charlcd@10008000 {
+                       compatible = "arm,versatile-lcd";
+                       reg = <0x10008000 0x1000>;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&pclk>;
+                       clock-names = "apb_pclk";
+               };
+
+               fpga_serial: serial@10009000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x10009000 0x1000>;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&uartclk>, <&pclk>;
+                       clock-names = "uartclk", "apb_pclk";
+               };
+
+               /* This GIC on the board is cascaded off the DevChip GIC */
+               intc_fpga1176: interrupt-controller@10040000 {
+                       compatible = "arm,arm1176jzf-devchip-gic", "arm,arm11mp-gic";
+                       #interrupt-cells = <3>;
+                       #address-cells = <1>;
+                       interrupt-controller;
+                       reg = <0x10041000 0x1000>,
+                             <0x10040000 0x100>;
+                       interrupt-parent = <&intc_dc1176>;
+                       interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               fpga_gpio0: gpio@10014000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x10014000 0x1000>;
+                       gpio-controller;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&pclk>;
+                       clock-names = "apb_pclk";
+               };
+
+               fpga_gpio1: gpio@10015000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x10015000 0x1000>;
+                       gpio-controller;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&pclk>;
+                       clock-names = "apb_pclk";
+               };
+
+               fpga_rtc: rtc@10017000 {
+                       compatible = "arm,pl031", "arm,primecell";
+                       reg = <0x10017000 0x1000>;
+                       interrupt-parent = <&intc_fpga1176>;
+                       interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&pclk>;
+                       clock-names = "apb_pclk";
+               };
+
+
+       };
+};
index a495e5821ab80c779d916f600724492d6771e25a..1466580be2954996c43fc189bc263967b37a49fc 100644 (file)
@@ -75,6 +75,7 @@
                                clock-frequency = <100000>;
                                status = "okay";
                                audio_codec: audio-codec@4a {
+                                       #sound-dai-cells = <0>;
                                        compatible = "cirrus,cs42l51";
                                        reg = <0x4a>;
                                };
                                broken-cd;
                        };
 
-                       pinctrl {
-                               /*
-                                * These pins might be muxed as I2S by
-                                * the bootloader, but it conflicts
-                                * with the real I2S pins that are
-                                * muxed using i2s_pins. We must mux
-                                * those pins to a function other than
-                                * I2S.
-                                */
-                               pinctrl-0 = <&hog_pins1 &hog_pins2>;
-                               pinctrl-names = "default";
-
-                               hog_pins1: hog-pins1 {
-                                       marvell,pins = "mpp6",  "mpp8", "mpp10",
-                                                      "mpp12", "mpp13";
-                                       marvell,function = "gpio";
-                               };
-
-                               hog_pins2: hog-pins2 {
-                                       marvell,pins = "mpp5", "mpp7", "mpp9";
-                                       marvell,function = "gpo";
-                               };
-                       };
-
                        usb@50000 {
                                status = "okay";
                        };
                        };
 
                        spi0: spi@10600 {
+                               pinctrl-0 = <&spi0_pins2>;
+                               pinctrl-names = "default";
                                status = "okay";
 
                                spi-flash@0 {
        };
 
        sound {
-             compatible = "marvell,a370db-audio";
-             marvell,audio-controller = <&audio_controller>;
-             marvell,audio-codec = <&audio_codec &spdif_out &spdif_in>;
-             status = "okay";
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "Armada 370 DB Audio";
+               simple-audio-card,mclk-fs = <256>;
+               simple-audio-card,widgets =
+                       "Headphone", "Out Jack",
+                       "Line", "In Jack";
+               simple-audio-card,routing =
+                       "Out Jack", "HPL",
+                       "Out Jack", "HPR",
+                       "AIN1L", "In Jack",
+                       "AIN1L", "In Jack";
+               status = "okay";
+
+               simple-audio-card,dai-link@0 {
+                       format = "i2s";
+                       cpu {
+                               sound-dai = <&audio_controller 0>;
+                       };
+
+                       codec {
+                               sound-dai = <&audio_codec>;
+                       };
+               };
+
+               simple-audio-card,dai-link@1 {
+                       format = "i2s";
+                       cpu {
+                               sound-dai = <&audio_controller 1>;
+                       };
+
+                       codec {
+                               sound-dai = <&spdif_out>;
+                       };
+               };
+
+               simple-audio-card,dai-link@2 {
+                       format = "i2s";
+                       cpu {
+                               sound-dai = <&audio_controller 1>;
+                       };
+
+                       codec {
+                               sound-dai = <&spdif_in>;
+                       };
+               };
        };
 
        spdif_out: spdif-out {
-             compatible = "linux,spdif-dit";
+               #sound-dai-cells = <0>;
+               compatible = "linux,spdif-dit";
        };
 
        spdif_in: spdif-in {
-             compatible = "linux,spdif-dir";
+               #sound-dai-cells = <0>;
+               compatible = "linux,spdif-dir";
+       };
+};
+
+&pinctrl {
+       /*
+        * These pins might be muxed as I2S by
+        * the bootloader, but it conflicts
+        * with the real I2S pins that are
+        * muxed using i2s_pins. We must mux
+        * those pins to a function other than
+        * I2S.
+        */
+       pinctrl-0 = <&hog_pins1 &hog_pins2>;
+       pinctrl-names = "default";
+
+       hog_pins1: hog-pins1 {
+               marvell,pins = "mpp6",  "mpp8", "mpp10",
+                              "mpp12", "mpp13";
+               marvell,function = "gpio";
+       };
+
+       hog_pins2: hog-pins2 {
+               marvell,pins = "mpp5", "mpp7", "mpp9";
+               marvell,function = "gpo";
        };
 };
index 2b6d24e0d1e8a2a33a879bea7689514f840f95dc..e1b0eb6b091ffa04814e41401d57e3c65d7e961a 100644 (file)
                                status = "okay";
                        };
 
-                       pinctrl {
-                               pwr_led_pin: pwr-led-pin {
-                                       marvell,pins = "mpp63";
-                                       marvell,function = "gpo";
-                               };
-
-                               stat_led_pins: stat-led-pins {
-                                       marvell,pins = "mpp64", "mpp65";
-                                       marvell,function = "gpio";
-                               };
-                       };
-
                        gpio_leds {
                                compatible = "gpio-leds";
                                pinctrl-names = "default";
                };
        };
 };
+
+&pinctrl {
+       pwr_led_pin: pwr-led-pin {
+               marvell,pins = "mpp63";
+               marvell,function = "gpo";
+       };
+
+       stat_led_pins: stat-led-pins {
+               marvell,pins = "mpp64", "mpp65";
+               marvell,function = "gpio";
+       };
+};
+
index 3aebd93cc33c864538475216b8f51fb9e49b4ce7..4e24932c6e30709831c54a866445f97d0cb53514 100644 (file)
@@ -35,7 +35,7 @@
                pcie-controller {
                        status = "okay";
 
-                       /* Connected to Marvell SATA controller */
+                       /* Connected to Marvell 88SE9170 SATA controller */
                        pcie@1,0 {
                                /* Port 0, Lane 0 */
                                status = "okay";
                                status = "okay";
                        };
 
+                       /* eSATA interface */
                        sata@a0000 {
-                               nr-ports = <2>;
+                               nr-ports = <1>;
                                status = "okay";
                        };
 
-                       pinctrl {
-                               power_led_pin: power-led-pin {
-                                       marvell,pins = "mpp57";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata1_led_pin: sata1-led-pin {
-                                       marvell,pins = "mpp15";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata2_led_pin: sata2-led-pin {
-                                       marvell,pins = "mpp14";
-                                       marvell,function = "gpio";
-                               };
-
-                               backup_led_pin: backup-led-pin {
-                                       marvell,pins = "mpp56";
-                                       marvell,function = "gpio";
-                               };
-
-                               backup_button_pin: backup-button-pin {
-                                       marvell,pins = "mpp58";
-                                       marvell,function = "gpio";
-                               };
-
-                               power_button_pin: power-button-pin {
-                                       marvell,pins = "mpp62";
-                                       marvell,function = "gpio";
-                               };
-
-                               reset_button_pin: reset-button-pin {
-                                       marvell,pins = "mpp6";
-                                       marvell,function = "gpio";
-                               };
-
-                               poweroff: poweroff {
-                                       marvell,pins = "mpp8";
-                                       marvell,function = "gpio";
-                               };
-                       };
-
                        mdio {
                                pinctrl-0 = <&mdio_pins>;
                                pinctrl-names = "default";
                        default-state = "keep";
                };
 
-               green-sata1-led {
-                       label = "rn102:green:sata1";
+               blue-sata1-led {
+                       label = "rn102:blue:sata1";
                        gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
-               green-sata2-led {
-                       label = "rn102:green:sata2";
+               blue-sata2-led {
+                       label = "rn102:blue:sata2";
                        gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
 
-               green-backup-led {
-                       label = "rn102:green:backup";
+               blue-backup-led {
+                       label = "rn102:blue:backup";
                        gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
                        default-state = "on";
                };
                gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
        };
 };
+
+&pinctrl {
+       power_led_pin: power-led-pin {
+               marvell,pins = "mpp57";
+               marvell,function = "gpio";
+       };
+
+       sata1_led_pin: sata1-led-pin {
+               marvell,pins = "mpp15";
+               marvell,function = "gpio";
+       };
+
+       sata2_led_pin: sata2-led-pin {
+               marvell,pins = "mpp14";
+               marvell,function = "gpio";
+       };
+
+       backup_led_pin: backup-led-pin {
+               marvell,pins = "mpp56";
+               marvell,function = "gpio";
+       };
+
+       backup_button_pin: backup-button-pin {
+               marvell,pins = "mpp58";
+               marvell,function = "gpio";
+       };
+
+       power_button_pin: power-button-pin {
+               marvell,pins = "mpp62";
+               marvell,function = "gpio";
+       };
+
+       reset_button_pin: reset-button-pin {
+               marvell,pins = "mpp6";
+               marvell,function = "gpio";
+       };
+
+       poweroff: poweroff {
+               marvell,pins = "mpp8";
+               marvell,function = "gpio";
+       };
+};
index c2f414bb9aba9aee392aaceee43fb68ef0330116..30586e47986a9738321b2a6d2a085dbc514f600f 100644 (file)
                                status = "okay";
                        };
 
-                       pinctrl {
-                               poweroff: poweroff {
-                                       marvell,pins = "mpp60";
-                                       marvell,function = "gpio";
-                               };
-
-                               backup_button_pin: backup-button-pin {
-                                       marvell,pins = "mpp52";
-                                       marvell,function = "gpio";
-                               };
-
-                               power_button_pin: power-button-pin {
-                                       marvell,pins = "mpp62";
-                                       marvell,function = "gpio";
-                               };
-
-                               backup_led_pin: backup-led-pin {
-                                       marvell,pins = "mpp63";
-                                       marvell,function = "gpo";
-                               };
-
-                               power_led_pin: power-led-pin {
-                                       marvell,pins = "mpp64";
-                                       marvell,function = "gpio";
-                               };
-
-                               reset_button_pin: reset-button-pin {
-                                       marvell,pins = "mpp65";
-                                       marvell,function = "gpio";
-                               };
-                       };
-
                        mdio {
                                pinctrl-0 = <&mdio_pins>;
                                pinctrl-names = "default";
                gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
        };
 };
+
+&pinctrl {
+       poweroff: poweroff {
+               marvell,pins = "mpp60";
+               marvell,function = "gpio";
+       };
+
+       backup_button_pin: backup-button-pin {
+               marvell,pins = "mpp52";
+               marvell,function = "gpio";
+       };
+
+       power_button_pin: power-button-pin {
+               marvell,pins = "mpp62";
+               marvell,function = "gpio";
+       };
+
+       backup_led_pin: backup-led-pin {
+               marvell,pins = "mpp63";
+               marvell,function = "gpo";
+       };
+
+       power_led_pin: power-led-pin {
+               marvell,pins = "mpp64";
+               marvell,function = "gpio";
+       };
+
+       reset_button_pin: reset-button-pin {
+               marvell,pins = "mpp65";
+               marvell,function = "gpio";
+       };
+};
index f57a8f841498415fa33c7075df0ab0df3f087c8d..394308951ed9e02e7328396ca17e3fd5cb90de34 100644 (file)
                };
 
                internal-regs {
-                       pinctrl {
-                               fan_pins: fan-pins {
-                                       marvell,pins = "mpp8";
-                                       marvell,function = "gpio";
-                               };
-
-                               led_pins: led-pins {
-                                       marvell,pins = "mpp32";
-                                       marvell,function = "gpio";
-                               };
-                       };
-
                        serial@12000 {
                                status = "okay";
                        };
                                phy0: ethernet-phy@0 {
                                        reg = <0>;
                                };
-
-                               phy1: ethernet-phy@1 {
-                                       reg = <1>;
-                               };
                        };
 
                        ethernet@70000 {
                                pinctrl-0 = <&ge1_rgmii_pins>;
                                pinctrl-names = "default";
                                status = "okay";
-                               phy = <&phy1>;
                                phy-mode = "rgmii-id";
+                               fixed-link {
+                                          speed = <1000>;
+                                          full-duplex;
+                               };
                        };
 
                        mvsdio@d4000 {
                        };
                };
        };
+
+       dsa@0 {
+               compatible = "marvell,dsa";
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               dsa,ethernet = <&eth1>;
+               dsa,mii-bus = <&mdio>;
+
+               switch@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x10 0>; /* MDIO address 16, switch 0 in tree */
+
+                       port@0 {
+                               reg = <0>;
+                               label = "lan0";
+                       };
+
+                       port@1 {
+                              reg = <1>;
+                              label = "lan1";
+                       };
+
+                       port@2 {
+                              reg = <2>;
+                              label = "lan2";
+                       };
+
+                       port@3 {
+                              reg = <3>;
+                              label = "lan3";
+                       };
+
+                       port@5 {
+                             reg = <5>;
+                             label = "cpu";
+                       };
+               };
+        };
  };
+
+&pinctrl {
+       fan_pins: fan-pins {
+               marvell,pins = "mpp8";
+               marvell,function = "gpio";
+       };
+
+       led_pins: led-pins {
+               marvell,pins = "mpp32";
+               marvell,function = "gpio";
+       };
+};
diff --git a/arch/arm/boot/dts/armada-370-synology-ds213j.dts b/arch/arm/boot/dts/armada-370-synology-ds213j.dts
new file mode 100644 (file)
index 0000000..70fecde
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Device Tree file for Synology DS213j
+ *
+ * Copyright (C) 2014, Arnaud EBALARD <arno@natisbad.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.
+ *
+ * Note: this Device Tree assumes that the bootloader has remapped the
+ * internal registers to 0xf1000000 (instead of the old 0xd0000000).
+ * The 0xf1000000 is the default used by the recent, DT-capable, U-Boot
+ * bootloaders provided by Marvell. It is used in recent versions of
+ * DSM software provided by Synology. Nonetheless, some earlier boards
+ * were delivered with an older version of u-boot that left internal
+ * registers mapped at 0xd0000000. If you have such a device you will
+ * not be able to directly boot a kernel based on this Device Tree. In
+ * that case, the preferred solution is to update your bootloader (e.g.
+ * by upgrading to latest version of DSM, or building a new one and
+ * installing it from u-boot prompt) or adjust the Devive Tree
+ * (s/0xf1000000/0xd0000000/ in 'ranges' below).
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-370.dtsi"
+
+/ {
+       model = "Synology DS213j";
+       compatible = "synology,ds213j", "marvell,armada370",
+                    "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = &uart0;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>; /* 512 MB */
+       };
+
+       soc {
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+                         MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
+
+               internal-regs {
+
+                       /* RTC provided by Seiko S-35390A I2C RTC chip below */
+                       rtc@10300 {
+                               status = "disabled";
+                       };
+
+                       spi0: spi@10600 {
+                               status = "okay";
+
+                               spi-flash@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       compatible = "micron,n25q064";
+                                       reg = <0>; /* Chip select 0 */
+                                       spi-max-frequency = <20000000>;
+
+                                       /*
+                                        * Warning!
+                                        *
+                                        * Synology u-boot uses its compiled-in environment
+                                        * and it seems Synology did not care to change u-boot
+                                        * default configuration in order to allow saving a
+                                        * modified environment at a sensible location. So,
+                                        * if you do a 'saveenv' under u-boot, your modified
+                                        * environment will be saved at 1MB after the start
+                                        * of the flash, i.e. in the middle of the uImage.
+                                        * For that reason, it is strongly advised not to
+                                        * change the default environment, unless you know
+                                        * what you are doing.
+                                        */
+                                       partition@00000000 { /* u-boot */
+                                               label = "RedBoot";
+                                               reg = <0x00000000 0x000c0000>; /* 768KB */
+                                       };
+
+                                       partition@000c0000 { /* uImage */
+                                               label = "zImage";
+                                               reg = <0x000c0000 0x002d0000>; /* 2880KB */
+                                       };
+
+                                       partition@00390000 { /* uInitramfs */
+                                               label = "rd.gz";
+                                               reg = <0x00390000 0x00440000>; /* 4250KB */
+                                       };
+
+                                       partition@007d0000 { /* MAC address and serial number */
+                                               label = "vendor";
+                                               reg = <0x007d0000 0x00010000>; /* 64KB */
+                                       };
+
+                                       partition@007e0000 {
+                                               label = "RedBoot config";
+                                               reg = <0x007e0000 0x00010000>; /* 64KB */
+                                       };
+
+                                       partition@007f0000 {
+                                               label = "FIS directory";
+                                               reg = <0x007f0000 0x00010000>; /* 64KB */
+                                       };
+                               };
+                       };
+
+                       i2c@11000 {
+                               compatible = "marvell,mv64xxx-i2c";
+                               pinctrl-0 = <&i2c0_pins>;
+                               pinctrl-names = "default";
+                               clock-frequency = <400000>;
+                               status = "okay";
+
+                               /* Main device RTC chip */
+                               s35390a: s35390a@30 {
+                                        compatible = "sii,s35390a";
+                                        reg = <0x30>;
+                               };
+                       };
+
+                       /* Connected to a header on device's PCB */
+                       serial@12000 {
+                               status = "okay";
+                       };
+
+                       /* Connected to a TI MSP430F2111 for power control */
+                       serial@12100 {
+                               status = "okay";
+                       };
+
+                       poweroff@12100 {
+                               compatible = "synology,power-off";
+                               reg = <0x12100 0x100>;
+                               clocks = <&coreclk 0>;
+                       };
+
+                       /* rear USB port, near reset button */
+                       usb@50000 {
+                               status = "okay";
+                       };
+
+                       /* rear USB port, near RJ45 port */
+                       usb@51000 {
+                               status = "okay";
+                       };
+
+                       mdio {
+                               phy1: ethernet-phy@1 { /* Marvell 88E1512 */
+                                       reg = <1>;
+                               };
+                       };
+
+                       ethernet@70000 {
+                              status = "okay";
+                              phy = <&phy1>;
+                              phy-mode = "sgmii";
+                       };
+
+                       sata@a0000 {
+                               nr-ports = <2>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       gpio-fan-32-38 {
+               status = "okay";
+               compatible = "gpio-fan";
+               pinctrl-0 = <&fan_ctrl_low_pin &fan_ctrl_mid_pin
+                            &fan_ctrl_high_pin &fan_alarm_pin>;
+               pinctrl-names = "default";
+               gpios = <&gpio1 31 GPIO_ACTIVE_HIGH
+                        &gpio2  0 GPIO_ACTIVE_HIGH
+                        &gpio2  1 GPIO_ACTIVE_HIGH>;
+               alarm-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+               gpio-fan,speed-map = <    0 0
+                                      1000 1
+                                      1150 2
+                                      1350 4
+                                      1500 3
+                                      1650 5
+                                      1750 6
+                                      1900 7 >;
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               pinctrl-0 = <&disk1_led_pin
+                            &disk2_led_pin>;
+               pinctrl-names = "default";
+
+               disk1-led-amber {
+                       label = "synology:amber:disk1";
+                       gpios = <&gpio0 31 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+               };
+
+               disk2-led-amber {
+                       label = "synology:amber:disk2";
+                       gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-0 = <&sata1_pwr_pin &sata2_pwr_pin>;
+               pinctrl-names = "default";
+
+               sata1_regulator: sata1-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "SATA1 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       startup-delay-us = <2000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+               };
+
+               sata2_regulator: sata2-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "SATA2 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       startup-delay-us = <4000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
+
+&pinctrl {
+       disk1_led_pin: disk1-led-pin {
+               marvell,pins = "mpp31";
+               marvell,function = "gpio";
+       };
+
+       disk2_led_pin: disk2-led-pin {
+               marvell,pins = "mpp32";
+               marvell,function = "gpio";
+       };
+
+       sata1_pwr_pin: sata1-pwr-pin {
+               marvell,pins = "mpp37";
+               marvell,function = "gpio";
+       };
+
+       sata2_pwr_pin: sata2-pwr-pin {
+               marvell,pins = "mpp62";
+               marvell,function = "gpio";
+       };
+
+       sata1_pres_pin: sata1-pres-pin {
+               marvell,pins = "mpp60";
+               marvell,function = "gpio";
+       };
+
+       sata2_pres_pin: sata2-pres-pin {
+               marvell,pins = "mpp48";
+               marvell,function = "gpio";
+       };
+
+       syno_id_bit0_pin: syno-id-bit0-pin {
+               marvell,pins = "mpp55";
+               marvell,function = "gpio";
+       };
+
+       syno_id_bit1_pin: syno-id-bit1-pin {
+               marvell,pins = "mpp56";
+               marvell,function = "gpio";
+       };
+
+       syno_id_bit2_pin: syno-id-bit2-pin {
+               marvell,pins = "mpp57";
+               marvell,function = "gpio";
+       };
+
+       syno_id_bit3_pin: syno-id-bit3-pin {
+               marvell,pins = "mpp58";
+               marvell,function = "gpio";
+       };
+
+       fan_ctrl_low_pin: fan-ctrl-low-pin {
+               marvell,pins = "mpp65";
+               marvell,function = "gpio";
+       };
+
+       fan_ctrl_mid_pin: fan-ctrl-mid-pin {
+               marvell,pins = "mpp64";
+               marvell,function = "gpio";
+       };
+
+       fan_ctrl_high_pin: fan-ctrl-high-pin {
+               marvell,pins = "mpp63";
+               marvell,function = "gpo";
+       };
+
+       fan_alarm_pin: fan-alarm-pin {
+               marvell,pins = "mpp38";
+               marvell,function = "gpio";
+       };
+};
index 83286ec9702cf695e8470fe7ff82ef845210f781..1af428602748e7e53f2c6a7b12f001959afd4a07 100644 (file)
                                status = "disabled";
                        };
 
-                       serial@12000 {
+                       uart0: serial@12000 {
                                compatible = "snps,dw-apb-uart";
                                reg = <0x12000 0x100>;
                                reg-shift = <2>;
                                clocks = <&coreclk 0>;
                                status = "disabled";
                        };
-                       serial@12100 {
+
+                       uart1: serial@12100 {
                                compatible = "snps,dw-apb-uart";
                                reg = <0x12100 0x100>;
                                reg-shift = <2>;
                                status = "disabled";
                        };
 
+                       pinctrl: pin-ctrl@18000 {
+                               reg = <0x18000 0x38>;
+                       };
+
                        coredivclk: corediv-clock@18740 {
                                compatible = "marvell,armada-370-corediv-clock";
                                reg = <0x18740 0xc>;
 
                        mbusc: mbus-controller@20000 {
                                compatible = "marvell,mbus-controller";
-                               reg = <0x20000 0x100>, <0x20180 0x20>;
+                               reg = <0x20000 0x100>, <0x20180 0x20>,
+                                     <0x20250 0x8>;
                        };
 
                        mpic: interrupt-controller@20000 {
                                status = "disabled";
                        };
 
-                       mdio {
+                       mdio: mdio {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "marvell,orion-mdio";
index 6b3c23b1e138e8ef260cf122f4cd677d5ec282b8..fdb3c12a6139a7d334879f3a04f214285e9a465b 100644 (file)
                                compatible = "marvell,aurora-outer-cache";
                                reg = <0x08000 0x1000>;
                                cache-id-part = <0x100>;
+                               cache-unified;
                                wt-override;
                        };
 
-                       i2c0: i2c@11000 {
-                               reg = <0x11000 0x20>;
+                       /*
+                        * Default SPI pinctrl setting, can be overwritten on
+                        * board level if a different configuration is used.
+                        */
+                       spi0: spi@10600 {
+                               pinctrl-0 = <&spi0_pins1>;
+                               pinctrl-names = "default";
                        };
 
-                       i2c1: i2c@11100 {
-                               reg = <0x11100 0x20>;
+                       spi1: spi@10680 {
+                               pinctrl-0 = <&spi1_pins>;
+                               pinctrl-names = "default";
                        };
 
-                       system-controller@18200 {
-                               compatible = "marvell,armada-370-xp-system-controller";
-                               reg = <0x18200 0x100>;
+                       i2c0: i2c@11000 {
+                               reg = <0x11000 0x20>;
                        };
 
-                       pinctrl {
-                               compatible = "marvell,mv88f6710-pinctrl";
-                               reg = <0x18000 0x38>;
-
-                               sdio_pins1: sdio-pins1 {
-                                       marvell,pins = "mpp9",  "mpp11", "mpp12",
-                                                       "mpp13", "mpp14", "mpp15";
-                                       marvell,function = "sd0";
-                               };
-
-                               sdio_pins2: sdio-pins2 {
-                                       marvell,pins = "mpp47", "mpp48", "mpp49",
-                                                       "mpp50", "mpp51", "mpp52";
-                                       marvell,function = "sd0";
-                               };
-
-                               sdio_pins3: sdio-pins3 {
-                                       marvell,pins = "mpp48", "mpp49", "mpp50",
-                                                       "mpp51", "mpp52", "mpp53";
-                                       marvell,function = "sd0";
-                               };
-
-                               i2c0_pins: i2c0-pins {
-                                       marvell,pins = "mpp2", "mpp3";
-                                       marvell,function = "i2c0";
-                               };
-
-                               i2s_pins1: i2s-pins1 {
-                                       marvell,pins = "mpp5", "mpp6", "mpp7",
-                                                      "mpp8", "mpp9", "mpp10",
-                                                      "mpp12", "mpp13";
-                                       marvell,function = "audio";
-                               };
-
-                               i2s_pins2: i2s-pins2 {
-                                       marvell,pins = "mpp49", "mpp47", "mpp50",
-                                                      "mpp59", "mpp57", "mpp61",
-                                                      "mpp62", "mpp60", "mpp58";
-                                       marvell,function = "audio";
-                               };
-
-                               mdio_pins: mdio-pins {
-                                       marvell,pins = "mpp17", "mpp18";
-                                       marvell,function = "ge";
-                               };
-
-                               ge0_rgmii_pins: ge0-rgmii-pins {
-                                       marvell,pins = "mpp5", "mpp6", "mpp7", "mpp8",
-                                                      "mpp9", "mpp10", "mpp11", "mpp12",
-                                                      "mpp13", "mpp14", "mpp15", "mpp16";
-                                       marvell,function = "ge0";
-                               };
-
-                               ge1_rgmii_pins: ge1-rgmii-pins {
-                                       marvell,pins = "mpp19", "mpp20", "mpp21", "mpp22",
-                                                      "mpp23", "mpp24", "mpp25", "mpp26",
-                                                      "mpp27", "mpp28", "mpp29", "mpp30";
-                                       marvell,function = "ge1";
-                               };
+                       i2c1: i2c@11100 {
+                               reg = <0x11100 0x20>;
                        };
 
                        gpio0: gpio@18100 {
                                interrupts = <91>;
                        };
 
+                       /*
+                        * Default UART pinctrl setting without RTS/CTS, can
+                        * be overwritten on board level if a different
+                        * configuration is used.
+                        */
+                       uart0: serial@12000 {
+                               pinctrl-0 = <&uart0_pins>;
+                               pinctrl-names = "default";
+                       };
+
+                       uart1: serial@12100 {
+                               pinctrl-0 = <&uart1_pins>;
+                               pinctrl-names = "default";
+                       };
+
+                       system-controller@18200 {
+                               compatible = "marvell,armada-370-xp-system-controller";
+                               reg = <0x18200 0x100>;
+                       };
+
                        gateclk: clock-gating-control@18220 {
                                compatible = "marvell,armada-370-gating-clock";
                                reg = <0x18220 0x4>;
                        };
 
                        audio_controller: audio-controller@30000 {
+                               #sound-dai-cells = <1>;
                                compatible = "marvell,armada370-audio";
                                reg = <0x30000 0x4000>;
                                interrupts = <93>;
                };
        };
 };
+
+&pinctrl {
+       compatible = "marvell,mv88f6710-pinctrl";
+
+       spi0_pins1: spi0-pins1 {
+               marvell,pins = "mpp33", "mpp34",
+                              "mpp35", "mpp36";
+               marvell,function = "spi0";
+       };
+
+       spi0_pins2: spi0_pins2 {
+               marvell,pins = "mpp32", "mpp63",
+                              "mpp64", "mpp65";
+               marvell,function = "spi0";
+       };
+
+       spi1_pins: spi1-pins {
+               marvell,pins = "mpp49", "mpp50",
+                              "mpp51", "mpp52";
+               marvell,function = "spi1";
+       };
+
+       uart0_pins: uart0-pins {
+               marvell,pins = "mpp0", "mpp1";
+               marvell,function = "uart0";
+       };
+
+       uart1_pins: uart1-pins {
+               marvell,pins = "mpp41", "mpp42";
+               marvell,function = "uart1";
+       };
+
+       sdio_pins1: sdio-pins1 {
+               marvell,pins = "mpp9",  "mpp11", "mpp12",
+                               "mpp13", "mpp14", "mpp15";
+               marvell,function = "sd0";
+       };
+
+       sdio_pins2: sdio-pins2 {
+               marvell,pins = "mpp47", "mpp48", "mpp49",
+                               "mpp50", "mpp51", "mpp52";
+               marvell,function = "sd0";
+       };
+
+       sdio_pins3: sdio-pins3 {
+               marvell,pins = "mpp48", "mpp49", "mpp50",
+                               "mpp51", "mpp52", "mpp53";
+               marvell,function = "sd0";
+       };
+
+       i2c0_pins: i2c0-pins {
+               marvell,pins = "mpp2", "mpp3";
+               marvell,function = "i2c0";
+       };
+
+       i2s_pins1: i2s-pins1 {
+               marvell,pins = "mpp5", "mpp6", "mpp7",
+                              "mpp8", "mpp9", "mpp10",
+                              "mpp12", "mpp13";
+               marvell,function = "audio";
+       };
+
+       i2s_pins2: i2s-pins2 {
+               marvell,pins = "mpp49", "mpp47", "mpp50",
+                              "mpp59", "mpp57", "mpp61",
+                              "mpp62", "mpp60", "mpp58";
+               marvell,function = "audio";
+       };
+
+       mdio_pins: mdio-pins {
+               marvell,pins = "mpp17", "mpp18";
+               marvell,function = "ge";
+       };
+
+       ge0_rgmii_pins: ge0-rgmii-pins {
+               marvell,pins = "mpp5", "mpp6", "mpp7", "mpp8",
+                              "mpp9", "mpp10", "mpp11", "mpp12",
+                              "mpp13", "mpp14", "mpp15", "mpp16";
+               marvell,function = "ge0";
+       };
+
+       ge1_rgmii_pins: ge1-rgmii-pins {
+               marvell,pins = "mpp19", "mpp20", "mpp21", "mpp22",
+                              "mpp23", "mpp24", "mpp25", "mpp26",
+                              "mpp27", "mpp28", "mpp29", "mpp30";
+               marvell,function = "ge1";
+       };
+};
index de6571445cef7140da63ed0cf54a4952fcdab6a1..9721e55384ce086a52ac3c0e93b25c7b4e2c3b4f 100644 (file)
                        #clock-cells = <0>;
                        clock-frequency = <2000000000>;
                };
+               /* 25 MHz reference crystal */
+               refclk: oscillator {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <25000000>;
+               };
        };
 
        cpus {
                                                      <&gic  GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
                                                      <&mpic 5>,
                                                      <&mpic 6>;
-                               clocks = <&coreclk 0>;
+                               clocks = <&coreclk 0>, <&refclk>;
+                               clock-names = "nbclk", "fixed";
                        };
 
                        watchdog@20300 {
                                compatible = "marvell,armada-375-wdt";
                                reg = <0x20300 0x34>, <0x20704 0x4>, <0x18254 0x4>;
-                               clocks = <&coreclk 0>;
+                               clocks = <&coreclk 0>, <&refclk>;
+                               clock-names = "nbclk", "fixed";
                        };
 
                        cpurst@20800 {
index 1af886f1e4864adad3f0d210b8dbc146a468fdd7..2aaa9d2ac284121c39bdc91236b4c8dc95794b06 100644 (file)
                        };
 
                        sdhci@d8000 {
-                               clock-frequency = <200000000>;
                                broken-cd;
                                wp-inverted;
                                bus-width = <8>;
                                status = "okay";
+                               no-1-8-v;
                        };
 
                        usb3@f0000 {
index 242d0ecc99f33e178fdef408820b8623880fb3bf..74391dace9e74b6d0a49259ee8bbc33054a60525 100644 (file)
@@ -25,9 +25,9 @@
        aliases {
                gpio0 = &gpio0;
                gpio1 = &gpio1;
-               eth0 = &eth0;
-               eth1 = &eth1;
-               eth2 = &eth2;
+               ethernet0 = &eth0;
+               ethernet1 = &eth1;
+               ethernet2 = &eth2;
        };
 
        soc {
index a55a97a705056a72a0e480c9c6a60fc4c1a50381..ca0200e207510c485ce9f79d2ee19200783678f0 100644 (file)
                };
 
                internal-regs {
-                       pinctrl {
-                               pinctrl-0 = <&pmx_phy_int>;
-                               pinctrl-names = "default";
-
-                               pmx_ge0: pmx-ge0 {
-                                       marvell,pins = "mpp0", "mpp1", "mpp2", "mpp3",
-                                                      "mpp4", "mpp5", "mpp6", "mpp7",
-                                                      "mpp8", "mpp9", "mpp10", "mpp11";
-                                       marvell,function = "ge0";
-                               };
-
-                               pmx_ge1: pmx-ge1 {
-                                       marvell,pins = "mpp12", "mpp13", "mpp14", "mpp15",
-                                                      "mpp16", "mpp17", "mpp18", "mpp19",
-                                                      "mpp20", "mpp21", "mpp22", "mpp23";
-                                       marvell,function = "ge1";
-                               };
-
-                               pmx_keys: pmx-keys {
-                                       marvell,pins = "mpp33";
-                                       marvell,function = "gpio";
-                               };
-
-                               pmx_spi: pmx-spi {
-                                       marvell,pins = "mpp36", "mpp37", "mpp38", "mpp39";
-                                       marvell,function = "spi";
-                               };
-
-                               pmx_phy_int: pmx-phy-int {
-                                       marvell,pins = "mpp32";
-                                       marvell,function = "gpio";
-                               };
-                       };
-
                        serial@12000 {
                                status = "okay";
                        };
                        };
 
                        ethernet@70000 {
-                               pinctrl-0 = <&pmx_ge0>;
+                               pinctrl-0 = <&ge0_rgmii_pins>;
                                pinctrl-names = "default";
                                status = "okay";
                                phy = <&phy0>;
                                phy-mode = "rgmii-id";
                        };
                        ethernet@74000 {
-                               pinctrl-0 = <&pmx_ge1>;
+                               pinctrl-0 = <&ge1_rgmii_pins>;
                                pinctrl-names = "default";
                                status = "okay";
                                phy = <&phy1>;
 
                        spi0: spi@10600 {
                                status = "okay";
-                               pinctrl-0 = <&pmx_spi>;
-                               pinctrl-names = "default";
 
                                spi-flash@0 {
                                        #address-cells = <1>;
                compatible = "gpio-keys";
                #address-cells = <1>;
                #size-cells = <0>;
-               pinctrl-0 = <&pmx_keys>;
+               pinctrl-0 = <&keys_pin>;
                pinctrl-names = "default";
 
                button@1 {
                };
        };
 };
+
+&pinctrl {
+       pinctrl-0 = <&phy_int_pin>;
+       pinctrl-names = "default";
+
+       keys_pin: keys-pin {
+               marvell,pins = "mpp33";
+               marvell,function = "gpio";
+       };
+
+       phy_int_pin: phy-int-pin {
+               marvell,pins = "mpp32";
+               marvell,function = "gpio";
+       };
+};
index 0478c55ca6567a6e780098598ef0a36d2fb223ea..ea8673647494d907a096e841baeeec2ea59ff36f 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "armada-xp-mv78460.dtsi"
 
 / {
                      <0x00000001 0x00000000 0x00000001 0x00000000>;
        };
 
+       cpus {
+               pm_pic {
+                       ctrl-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>,
+                                    <&gpio0 17 GPIO_ACTIVE_LOW>,
+                                    <&gpio0 18 GPIO_ACTIVE_LOW>;
+               };
+       };
+
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
                        serial@12300 {
                                status = "okay";
                        };
-
+                       pinctrl {
+                               pinctrl-0 = <&pic_pins>;
+                               pinctrl-names = "default";
+                               pic_pins: pic-pins-0 {
+                                       marvell,pins = "mpp16", "mpp17",
+                                                      "mpp18";
+                                       marvell,function = "gpio";
+                               };
+                       };
                        sata@a0000 {
                                nr-ports = <2>;
                                status = "okay";
index 469cf7137595fe80bd12086be4eb9eada5b2bdb4..a2ef93c1eb10fc91af16eeabef84cd031c25d689 100644 (file)
@@ -22,7 +22,7 @@
 
        chosen {
                bootargs = "console=ttyS0,115200 earlyprintk";
-               stdout-path = "/soc/internal-regs/serial@12000";
+               stdout-path = &uart0;
        };
 
        memory {
                };
 
                internal-regs {
-                       pinctrl {
-                               poweroff_pin: poweroff-pin {
-                                       marvell,pins = "mpp24";
-                                       marvell,function = "gpio";
-                               };
-
-                               power_button_pin: power-button-pin {
-                                       marvell,pins = "mpp44";
-                                       marvell,function = "gpio";
-                               };
-
-                               reset_button_pin: reset-button-pin {
-                                       marvell,pins = "mpp45";
-                                       marvell,function = "gpio";
-                               };
-                               select_button_pin: select-button-pin {
-                                       marvell,pins = "mpp41";
-                                       marvell,function = "gpio";
-                               };
-
-                               scroll_button_pin: scroll-button-pin {
-                                       marvell,pins = "mpp42";
-                                       marvell,function = "gpio";
-                               };
-
-                               hdd_led_pin: hdd-led-pin {
-                                       marvell,pins = "mpp26";
-                                       marvell,function = "gpio";
-                               };
-                       };
-
                        serial@12000 {
                                status = "okay";
                        };
                        };
 
                        ethernet@70000 {
+                               pinctrl-0 = <&ge0_rgmii_pins>;
+                               pinctrl-names = "default";
                                status = "okay";
                                phy = <&phy0>;
                                phy-mode = "rgmii-id";
                        };
 
                        ethernet@74000 {
+                               pinctrl-0 = <&ge1_rgmii_pins>;
+                               pinctrl-names = "default";
                                status = "okay";
                                phy = <&phy1>;
                                phy-mode = "rgmii-id";
                                        reg = <0x2e>;
                                };
 
+                               eeprom@50 {
+                                       compatible = "atmel,24c64";
+                                       reg = <0x50>;
+                               };
+
                                pcf8563@51 {
                                        compatible = "nxp,pcf8563";
                                        reg = <0x51>;
                        gpio-controller;
                        #gpio-cells = <2>;
                        reg = <0>;
-                       registers-number = <2>;
+                       registers-number = <1>;
                        spi-max-frequency = <100000>;
                };
        };
                gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
        };
 };
+
+&pinctrl {
+       poweroff_pin: poweroff-pin {
+               marvell,pins = "mpp24";
+               marvell,function = "gpio";
+       };
+
+       power_button_pin: power-button-pin {
+               marvell,pins = "mpp44";
+               marvell,function = "gpio";
+       };
+
+       reset_button_pin: reset-button-pin {
+               marvell,pins = "mpp45";
+               marvell,function = "gpio";
+       };
+       select_button_pin: select-button-pin {
+               marvell,pins = "mpp41";
+               marvell,function = "gpio";
+       };
+
+       scroll_button_pin: scroll-button-pin {
+               marvell,pins = "mpp42";
+               marvell,function = "gpio";
+       };
+
+       hdd_led_pin: hdd-led-pin {
+               marvell,pins = "mpp26";
+               marvell,function = "gpio";
+       };
+};
index 2592e1c13560039c0a1396b63026934b12bb305c..281ccd24295caa3d7b7f595a1d3c32c117a63d17 100644 (file)
                };
 
                internal-regs {
-                       pinctrl {
-                               compatible = "marvell,mv78230-pinctrl";
-                               reg = <0x18000 0x38>;
-
-                               sdio_pins: sdio-pins {
-                                       marvell,pins = "mpp30", "mpp31", "mpp32",
-                                                      "mpp33", "mpp34", "mpp35";
-                                       marvell,function = "sd0";
-                               };
-                       };
-
                        gpio0: gpio@18100 {
                                compatible = "marvell,orion-gpio";
                                reg = <0x18100 0x40>;
                };
        };
 };
+
+&pinctrl {
+       compatible = "marvell,mv78230-pinctrl";
+};
index 480e237a870fa42c86dca6ab7dd5585d6345956a..d7a8d0b0f385e090210c9171cf609baec68cb0c0 100644 (file)
                };
 
                internal-regs {
-                       pinctrl {
-                               compatible = "marvell,mv78260-pinctrl";
-                               reg = <0x18000 0x38>;
-
-                               sdio_pins: sdio-pins {
-                                       marvell,pins = "mpp30", "mpp31", "mpp32",
-                                                      "mpp33", "mpp34", "mpp35";
-                                       marvell,function = "sd0";
-                               };
-                       };
-
                        gpio0: gpio@18100 {
                                compatible = "marvell,orion-gpio";
                                reg = <0x18100 0x40>;
                };
        };
 };
+
+&pinctrl {
+       compatible = "marvell,mv78260-pinctrl";
+};
index 2c7b1fef470350714a9f9c5df7b25f42708019de..9c40c130d11ad3589442d518632b3c22be1255cd 100644 (file)
                };
 
                internal-regs {
-                       pinctrl {
-                               compatible = "marvell,mv78460-pinctrl";
-                               reg = <0x18000 0x38>;
-
-                               sdio_pins: sdio-pins {
-                                       marvell,pins = "mpp30", "mpp31", "mpp32",
-                                                      "mpp33", "mpp34", "mpp35";
-                                       marvell,function = "sd0";
-                               };
-                       };
-
                        gpio0: gpio@18100 {
                                compatible = "marvell,orion-gpio";
                                reg = <0x18100 0x40>;
                };
        };
 };
+
+&pinctrl {
+       compatible = "marvell,mv78460-pinctrl";
+};
index 7d8f32873e82903d11307afcd3b1b3e75142990f..d81430aa4ab32701fcdeb6982312c5ad65d91d8f 100644 (file)
                };
 
                internal-regs {
-                       pinctrl {
-                               poweroff: poweroff {
-                                       marvell,pins = "mpp42";
-                                       marvell,function = "gpio";
-                               };
-
-                               power_button_pin: power-button-pin {
-                                       marvell,pins = "mpp27";
-                                       marvell,function = "gpio";
-                               };
-
-                               reset_button_pin: reset-button-pin {
-                                       marvell,pins = "mpp41";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata1_led_pin: sata1-led-pin {
-                                       marvell,pins = "mpp31";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata2_led_pin: sata2-led-pin {
-                                       marvell,pins = "mpp40";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata3_led_pin: sata3-led-pin {
-                                       marvell,pins = "mpp44";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata4_led_pin: sata4-led-pin {
-                                       marvell,pins = "mpp47";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata1_power_pin: sata1-power-pin {
-                                       marvell,pins = "mpp24";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata2_power_pin: sata2-power-pin {
-                                       marvell,pins = "mpp25";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata3_power_pin: sata3-power-pin {
-                                       marvell,pins = "mpp26";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata4_power_pin: sata4-power-pin {
-                                       marvell,pins = "mpp28";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata1_pres_pin: sata1-pres-pin {
-                                       marvell,pins = "mpp32";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata2_pres_pin: sata2-pres-pin {
-                                       marvell,pins = "mpp33";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata3_pres_pin: sata3-pres-pin {
-                                       marvell,pins = "mpp34";
-                                       marvell,function = "gpio";
-                               };
-
-                               sata4_pres_pin: sata4-pres-pin {
-                                       marvell,pins = "mpp35";
-                                       marvell,function = "gpio";
-                               };
-
-                               err_led_pin: err-led-pin {
-                                       marvell,pins = "mpp45";
-                                       marvell,function = "gpio";
-                               };
+                       /* Two rear eSATA ports */
+                       sata@a0000 {
+                               nr-ports = <2>;
+                               status = "okay";
                        };
 
                        serial@12000 {
                gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
        };
 };
+
+&pinctrl {
+       poweroff: poweroff {
+               marvell,pins = "mpp42";
+               marvell,function = "gpio";
+       };
+
+       power_button_pin: power-button-pin {
+               marvell,pins = "mpp27";
+               marvell,function = "gpio";
+       };
+
+       reset_button_pin: reset-button-pin {
+               marvell,pins = "mpp41";
+               marvell,function = "gpio";
+       };
+
+       sata1_led_pin: sata1-led-pin {
+               marvell,pins = "mpp31";
+               marvell,function = "gpio";
+       };
+
+       sata2_led_pin: sata2-led-pin {
+               marvell,pins = "mpp40";
+               marvell,function = "gpio";
+       };
+
+       sata3_led_pin: sata3-led-pin {
+               marvell,pins = "mpp44";
+               marvell,function = "gpio";
+       };
+
+       sata4_led_pin: sata4-led-pin {
+               marvell,pins = "mpp47";
+               marvell,function = "gpio";
+       };
+
+       sata1_power_pin: sata1-power-pin {
+               marvell,pins = "mpp24";
+               marvell,function = "gpio";
+       };
+
+       sata2_power_pin: sata2-power-pin {
+               marvell,pins = "mpp25";
+               marvell,function = "gpio";
+       };
+
+       sata3_power_pin: sata3-power-pin {
+               marvell,pins = "mpp26";
+               marvell,function = "gpio";
+       };
+
+       sata4_power_pin: sata4-power-pin {
+               marvell,pins = "mpp28";
+               marvell,function = "gpio";
+       };
+
+       sata1_pres_pin: sata1-pres-pin {
+               marvell,pins = "mpp32";
+               marvell,function = "gpio";
+       };
+
+       sata2_pres_pin: sata2-pres-pin {
+               marvell,pins = "mpp33";
+               marvell,function = "gpio";
+       };
+
+       sata3_pres_pin: sata3-pres-pin {
+               marvell,pins = "mpp34";
+               marvell,function = "gpio";
+       };
+
+       sata4_pres_pin: sata4-pres-pin {
+               marvell,pins = "mpp35";
+               marvell,function = "gpio";
+       };
+
+       err_led_pin: err-led-pin {
+               marvell,pins = "mpp45";
+               marvell,function = "gpio";
+       };
+};
index 4e5a59ee150151f8867ed329a6e05e4f580a3b8c..6f6b0916df4874c8d626e3ac46a810e936878960 100644 (file)
                        serial@12100 {
                                status = "okay";
                        };
-                       pinctrl {
-                               led_pins: led-pins-0 {
-                                       marvell,pins = "mpp49", "mpp51", "mpp53";
-                                       marvell,function = "gpio";
-                               };
-                       };
+
                        leds {
                                compatible = "gpio-leds";
                                pinctrl-names = "default";
                };
        };
 };
+
+&pinctrl {
+       led_pins: led-pins-0 {
+               marvell,pins = "mpp49", "mpp51", "mpp53";
+               marvell,function = "gpio";
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp-synology-ds414.dts b/arch/arm/boot/dts/armada-xp-synology-ds414.dts
new file mode 100644 (file)
index 0000000..749fdba
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Device Tree file for Synology DS414
+ *
+ * Copyright (C) 2014, Arnaud EBALARD <arno@natisbad.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.
+ *
+ * Note: this Device Tree assumes that the bootloader has remapped the
+ * internal registers to 0xf1000000 (instead of the old 0xd0000000).
+ * The 0xf1000000 is the default used by the recent, DT-capable, U-Boot
+ * bootloaders provided by Marvell. It is used in recent versions of
+ * DSM software provided by Synology. Nonetheless, some earlier boards
+ * were delivered with an older version of u-boot that left internal
+ * registers mapped at 0xd0000000. If you have such a device you will
+ * not be able to directly boot a kernel based on this Device Tree. In
+ * that case, the preferred solution is to update your bootloader (e.g.
+ * by upgrading to latest version of DSM, or building a new one and
+ * installing it from u-boot prompt) or adjust the Devive Tree
+ * (s/0xf1000000/0xd0000000/ in 'ranges' below).
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-xp-mv78230.dtsi"
+
+/ {
+       model = "Synology DS414";
+       compatible = "synology,ds414", "marvell,armadaxp-mv78230",
+                    "marvell,armadaxp", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = &uart0;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0 0x00000000 0 0x40000000>; /* 1GB */
+       };
+
+       soc {
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+                         MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+               pcie-controller {
+                       status = "okay";
+
+                       /*
+                        * Connected to Marvell 88SX7042 SATA-II controller
+                        * handling the four disks.
+                        */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+
+                       /*
+                        * Connected to EtronTech EJ168A XHCI controller
+                        * providing the two rear USB 3.0 ports.
+                        */
+                       pcie@5,0 {
+                               /* Port 1, Lane 0 */
+                               status = "okay";
+                       };
+               };
+
+               internal-regs {
+
+                       /* RTC is provided by Seiko S-35390A below */
+                       rtc@10300 {
+                               status = "disabled";
+                       };
+
+                       spi0: spi@10600 {
+                               status = "okay";
+
+                               spi-flash@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       compatible = "micron,n25q064";
+                                       reg = <0>; /* Chip select 0 */
+                                       spi-max-frequency = <20000000>;
+
+                                       /*
+                                        * Warning!
+                                        *
+                                        * Synology u-boot uses its compiled-in environment
+                                        * and it seems Synology did not care to change u-boot
+                                        * default configuration in order to allow saving a
+                                        * modified environment at a sensible location. So,
+                                        * if you do a 'saveenv' under u-boot, your modified
+                                        * environment will be saved at 1MB after the start
+                                        * of the flash, i.e. in the middle of the uImage.
+                                        * For that reason, it is strongly advised not to
+                                        * change the default environment, unless you know
+                                        * what you are doing.
+                                        */
+                                       partition@00000000 { /* u-boot */
+                                               label = "RedBoot";
+                                               reg = <0x00000000 0x000d0000>; /* 832KB */
+                                       };
+
+                                       partition@000c0000 { /* uImage */
+                                               label = "zImage";
+                                               reg = <0x000d0000 0x002d0000>; /* 2880KB */
+                                       };
+
+                                       partition@003a0000 { /* uInitramfs */
+                                               label = "rd.gz";
+                                               reg = <0x003a0000 0x00430000>; /* 4250KB */
+                                       };
+
+                                       partition@007d0000 { /* MAC address and serial number */
+                                               label = "vendor";
+                                               reg = <0x007d0000 0x00010000>; /* 64KB */
+                                       };
+
+                                       partition@007e0000 {
+                                               label = "RedBoot config";
+                                               reg = <0x007e0000 0x00010000>; /* 64KB */
+                                       };
+
+                                       partition@007f0000 {
+                                               label = "FIS directory";
+                                               reg = <0x007f0000 0x00010000>; /* 64KB */
+                                       };
+                               };
+                       };
+
+                       i2c@11000 {
+                               clock-frequency = <400000>;
+                               status = "okay";
+
+                               s35390a: s35390a@30 {
+                                        compatible = "sii,s35390a";
+                                        reg = <0x30>;
+                               };
+                       };
+
+                       /* Connected to a header on device's PCB. This
+                        * provides the main console for the device.
+                        *
+                        * Warning: the device may not boot with a 3.3V
+                        * USB-serial converter connected when the power
+                        * button is pressed. The converter needs to be
+                        * connected a few seconds after pressing the
+                        * power button. This is possibly due to UART0_TXD
+                        * pin being sampled at reset (bit 0 of SAR).
+                        */
+                       serial@12000 {
+                               status = "okay";
+                       };
+
+                       /* Connected to a Microchip PIC16F883 for power control */
+                       serial@12100 {
+                               status = "okay";
+                       };
+
+                       poweroff@12100 {
+                               compatible = "synology,power-off";
+                               reg = <0x12100 0x100>;
+                               clocks = <&coreclk 0>;
+                       };
+
+                       /* Front USB 2.0 port */
+                       usb@50000 {
+                               status = "okay";
+                       };
+
+                       mdio {
+                               phy0: ethernet-phy@0 { /* Marvell 88E1512 */
+                                       reg = <0>;
+                               };
+
+                               phy1: ethernet-phy@1 { /* Marvell 88E1512 */
+                                       reg = <1>;
+                               };
+                       };
+
+                       ethernet@70000 {
+                               status = "okay";
+                               pinctrl-0 = <&ge0_rgmii_pins>;
+                               pinctrl-names = "default";
+                               phy = <&phy1>;
+                               phy-mode = "rgmii-id";
+                       };
+
+                       ethernet@74000 {
+                               pinctrl-0 = <&ge1_rgmii_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                               phy = <&phy0>;
+                               phy-mode = "rgmii-id";
+                       };
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-0 = <&sata1_pwr_pin &sata2_pwr_pin
+                            &sata3_pwr_pin &sata4_pwr_pin>;
+               pinctrl-names = "default";
+
+               sata1_regulator: sata1-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "SATA1 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       startup-delay-us = <2000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+               };
+
+               sata2_regulator: sata2-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "SATA2 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       startup-delay-us = <4000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+               };
+
+               sata3_regulator: sata3-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "SATA3 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       startup-delay-us = <6000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+               };
+
+               sata4_regulator: sata4-regulator {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "SATA4 Power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       startup-delay-us = <8000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
+
+&pinctrl {
+       sata1_pwr_pin: sata1-pwr-pin {
+               marvell,pins = "mpp42";
+               marvell,function = "gpio";
+       };
+
+       sata2_pwr_pin: sata2-pwr-pin {
+               marvell,pins = "mpp44";
+               marvell,function = "gpio";
+       };
+
+       sata3_pwr_pin: sata3-pwr-pin {
+               marvell,pins = "mpp45";
+               marvell,function = "gpio";
+       };
+
+       sata4_pwr_pin: sata4-pwr-pin {
+               marvell,pins = "mpp46";
+               marvell,function = "gpio";
+       };
+
+       sata1_pres_pin: sata1-pres-pin {
+               marvell,pins = "mpp34";
+               marvell,function = "gpio";
+       };
+
+       sata2_pres_pin: sata2-pres-pin {
+               marvell,pins = "mpp35";
+               marvell,function = "gpio";
+       };
+
+       sata3_pres_pin: sata3-pres-pin {
+               marvell,pins = "mpp40";
+               marvell,function = "gpio";
+       };
+
+       sata4_pres_pin: sata4-pres-pin {
+               marvell,pins = "mpp41";
+               marvell,function = "gpio";
+       };
+
+       syno_id_bit0_pin: syno-id-bit0-pin {
+               marvell,pins = "mpp26";
+               marvell,function = "gpio";
+       };
+
+       syno_id_bit1_pin: syno-id-bit1-pin {
+               marvell,pins = "mpp28";
+               marvell,function = "gpio";
+       };
+
+       syno_id_bit2_pin: syno-id-bit2-pin {
+               marvell,pins = "mpp29";
+               marvell,function = "gpio";
+       };
+
+       fan1_alarm_pin: fan1-alarm-pin {
+               marvell,pins = "mpp33";
+               marvell,function = "gpio";
+       };
+
+       fan2_alarm_pin: fan2-alarm-pin {
+               marvell,pins = "mpp32";
+               marvell,function = "gpio";
+       };
+};
index bff9f6c18db1358dd7d70aa9b9de0e40c054da20..62c3ba958b39ed384717f3756a568b5159fcdb23 100644 (file)
                };
 
                internal-regs {
+                       sdramc@1400 {
+                               compatible = "marvell,armada-xp-sdram-controller";
+                               reg = <0x1400 0x500>;
+                       };
+
                        L2: l2-cache {
                                compatible = "marvell,aurora-system-cache";
                                reg = <0x08000 0x1000>;
                                cache-id-part = <0x100>;
+                               cache-unified;
                                wt-override;
                        };
 
+                       spi0: spi@10600 {
+                               pinctrl-0 = <&spi0_pins>;
+                               pinctrl-names = "default";
+                       };
+
                        i2c0: i2c@11000 {
                                compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
                                reg = <0x11000 0x100>;
                                reg = <0x11100 0x100>;
                        };
 
-                       serial@12200 {
+                       uart2: serial@12200 {
                                compatible = "snps,dw-apb-uart";
+                               pinctrl-0 = <&uart2_pins>;
+                               pinctrl-names = "default";
                                reg = <0x12200 0x100>;
                                reg-shift = <2>;
                                interrupts = <43>;
                                clocks = <&coreclk 0>;
                                status = "disabled";
                        };
-                       serial@12300 {
+
+                       uart3: serial@12300 {
                                compatible = "snps,dw-apb-uart";
+                               pinctrl-0 = <&uart3_pins>;
+                               pinctrl-names = "default";
                                reg = <0x12300 0x100>;
                                reg-shift = <2>;
                                interrupts = <44>;
                };
        };
 };
+
+&pinctrl {
+       ge0_gmii_pins: ge0-gmii-pins {
+               marvell,pins =
+                    "mpp0",  "mpp1",  "mpp2",  "mpp3",
+                    "mpp4",  "mpp5",  "mpp6",  "mpp7",
+                    "mpp8",  "mpp9",  "mpp10", "mpp11",
+                    "mpp12", "mpp13", "mpp14", "mpp15",
+                    "mpp16", "mpp17", "mpp18", "mpp19",
+                    "mpp20", "mpp21", "mpp22", "mpp23";
+               marvell,function = "ge0";
+       };
+
+       ge0_rgmii_pins: ge0-rgmii-pins {
+               marvell,pins =
+                    "mpp0", "mpp1", "mpp2", "mpp3",
+                    "mpp4", "mpp5", "mpp6", "mpp7",
+                    "mpp8", "mpp9", "mpp10", "mpp11";
+               marvell,function = "ge0";
+       };
+
+       ge1_rgmii_pins: ge1-rgmii-pins {
+               marvell,pins =
+                    "mpp12", "mpp13", "mpp14", "mpp15",
+                    "mpp16", "mpp17", "mpp18", "mpp19",
+                    "mpp20", "mpp21", "mpp22", "mpp23";
+               marvell,function = "ge1";
+       };
+
+       sdio_pins: sdio-pins {
+               marvell,pins = "mpp30", "mpp31", "mpp32",
+                              "mpp33", "mpp34", "mpp35";
+               marvell,function = "sd0";
+       };
+
+       spi0_pins: spi0-pins {
+               marvell,pins = "mpp36", "mpp37",
+                              "mpp38", "mpp39";
+               marvell,function = "spi";
+       };
+
+       uart2_pins: uart2-pins {
+               marvell,pins = "mpp42", "mpp43";
+               marvell,function = "uart2";
+       };
+
+       uart3_pins: uart3-pins {
+               marvell,pins = "mpp44", "mpp45";
+               marvell,function = "uart3";
+       };
+};
index d68b3c4862bc22011df225b12caf4c3eab1758e1..653e4395b7cbe6bcf6b6e4dd1af442d1473a7852 100644 (file)
                                        interrupts-extended = <&pmc AT91_PMC_LOCKB>;
                                        clocks = <&main>;
                                        reg = <1>;
-                                       atmel,clk-input-range = <1000000 5000000>;
+                                       atmel,clk-input-range = <1000000 32000000>;
                                        #atmel,pll-clk-output-range-cells = <4>;
-                                       atmel,pll-clk-output-ranges = <70000000 130000000 1 1>;
+                                       atmel,pll-clk-output-ranges = <80000000 200000000 0 1>,
+                                                               <190000000 240000000 2 1>;
                                };
 
                                mck: masterck {
                                        };
                                };
 
+                               can {
+                                       pinctrl_can_rx_tx: can_rx_tx {
+                                               atmel,pins =
+                                                       <AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* CANRX, conflicts with IRQ0 */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* CANTX, conflicts with PCK0 */
+                                       };
+                               };
+
                                pioA: gpio@fffff200 {
                                        compatible = "atmel,at91rm9200-gpio";
                                        reg = <0xfffff200 0x200>;
                                clock-names = "pwm_clk";
                                status = "disabled";
                        };
+
+                       can: can@fffac000 {
+                               compatible = "atmel,at91sam9263-can";
+                               reg = <0xfffac000 0x300>;
+                               interrupts = <12 IRQ_TYPE_LEVEL_HIGH 3>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_can_rx_tx>;
+                               clocks = <&can_clk>;
+                               clock-names = "can_clk";
+                               status = "disabled";
+                       };
                };
 
                fb0: fb@0x00700000 {
index c2554219f7a4eb736c2f46f6ce36175311d5d530..3c5fa3388997078dd206dfb5cb05a35a1752e963 100644 (file)
@@ -10,6 +10,7 @@
 #include "at91sam9x5_usart3.dtsi"
 #include "at91sam9x5_macb0.dtsi"
 #include "at91sam9x5_macb1.dtsi"
+#include "at91sam9x5_can.dtsi"
 
 / {
        model = "Atmel AT91SAM9X25 SoC";
index 8eac66ce0ab7766f76476d836488f7374f1b4a90..499cdc81f4c07ce352a92a3c0bb1a7029b8c98ea 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "at91sam9x5.dtsi"
 #include "at91sam9x5_macb0.dtsi"
+#include "at91sam9x5_can.dtsi"
 
 / {
        model = "Atmel AT91SAM9X35 SoC";
index 726274f7959b6a00fdcd992b726b758688898bd1..bbb3ba65165f5b7f2ca132ab2787c87da2b25897 100644 (file)
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_dbgu>;
+                               dmas = <&dma1 1 AT91_DMA_CFG_PER_ID(8)>,
+                                      <&dma1 1 (AT91_DMA_CFG_PER_ID(9) | AT91_DMA_CFG_FIFOCFG_ASAP)>;
+                               dma-names = "tx", "rx";
                                clocks = <&mck>;
                                clock-names = "usart";
                                status = "disabled";
                                interrupts = <5 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart0>;
+                               dmas = <&dma0 1 AT91_DMA_CFG_PER_ID(3)>,
+                                      <&dma0 1 (AT91_DMA_CFG_PER_ID(4) | AT91_DMA_CFG_FIFOCFG_ASAP)>;
+                               dma-names = "tx", "rx";
                                clocks = <&usart0_clk>;
                                clock-names = "usart";
                                status = "disabled";
                                interrupts = <6 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart1>;
+                               dmas = <&dma0 1 AT91_DMA_CFG_PER_ID(5)>,
+                                      <&dma0 1 (AT91_DMA_CFG_PER_ID(6) | AT91_DMA_CFG_FIFOCFG_ASAP)>;
+                               dma-names = "tx", "rx";
                                clocks = <&usart1_clk>;
                                clock-names = "usart";
                                status = "disabled";
                                interrupts = <7 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart2>;
+                               dmas = <&dma1 1 AT91_DMA_CFG_PER_ID(12)>,
+                                      <&dma1 1 (AT91_DMA_CFG_PER_ID(13) | AT91_DMA_CFG_FIFOCFG_ASAP)>;
+                               dma-names = "tx", "rx";
                                clocks = <&usart2_clk>;
                                clock-names = "usart";
                                status = "disabled";
index f44ab7702a12fd668092d70cca6767e26a4f7c2e..8eb2f9c1b97847d94db2cf58b57f5c82b423832f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sam9x5_macb0.dtsi - Device Tree Include file for AT91SAM9x5 SoC with 1
+ * at91sam9x5_can.dtsi - Device Tree Include file for AT91SAM9x5 SoC with 1
  * Ethernet interface.
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
                                                reg = <29>;
                                        };
 
-                                        can1_clk: can1_clk {
-                                                #clock-cells = <0>;
-                                                reg = <30>;
-                                        };
+                                       can1_clk: can1_clk {
+                                               #clock-cells = <0>;
+                                               reg = <30>;
+                                       };
+                               };
+                       };
+
+                       can0: can@f8000000 {
+                               compatible = "atmel,at91sam9x5-can";
+                               reg = <0xf8000000 0x300>;
+                               interrupts = <29 IRQ_TYPE_LEVEL_HIGH 3>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_can0_rx_tx>;
+                               clocks = <&can0_clk>;
+                               clock-names = "can_clk";
+                               status = "disabled";
+                       };
+
+                       can1: can@f8004000 {
+                               compatible = "atmel,at91sam9x5-can";
+                               reg = <0xf8004000 0x300>;
+                               interrupts = <30 IRQ_TYPE_LEVEL_HIGH 3>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_can1_rx_tx>;
+                               clocks = <&can1_clk>;
+                               clock-names = "can_clk";
+                               status = "disabled";
+                       };
+
+                       pinctrl@fffff400 {
+                               can0 {
+                                       pinctrl_can0_rx_tx: can0_rx_tx {
+                                               atmel,pins =
+                                                       <AT91_PIOA 9 AT91_PERIPH_B AT91_PINCTRL_NONE    /* CANRX0, conflicts with DRXD */
+                                                       AT91_PIOA 10 AT91_PERIPH_B AT91_PINCTRL_NONE>;  /* CANTX0, conflicts with DTXD */
+                                       };
+                               };
+
+                               can1 {
+                                       pinctrl_can1_rx_tx: can1_rx_tx {
+                                               atmel,pins =
+                                                       <AT91_PIOA 6 AT91_PERIPH_B AT91_PINCTRL_NONE    /* CANRX1, conflicts with RXD1 */
+                                                       AT91_PIOA 5 AT91_PERIPH_B AT91_PINCTRL_NONE>;   /* CANTX1, conflicts with TXD1 */
+                                       };
                                };
                        };
                };
index 140217a5438460ffb7cd23d327a6635522bf49a1..43bb5b51caa6644968c616157119d79d21530ab8 100644 (file)
@@ -57,6 +57,9 @@
                                interrupts = <8 IRQ_TYPE_LEVEL_HIGH 5>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_usart3>;
+                               dmas = <&dma1 1 AT91_DMA_CFG_PER_ID(14)>,
+                                      <&dma1 1 (AT91_DMA_CFG_PER_ID(15) | AT91_DMA_CFG_FIFOCFG_ASAP)>;
+                               dma-names = "tx", "rx";
                                clocks = <&usart3_clk>;
                                clock-names = "usart";
                                status = "disabled";
index bb22842a08261a9b33474313681592de6887faab..29598667420b83766c0e8fa0b05960d008f6007e 100644 (file)
                                reg = <0x90020000 0x10000>;
                                interrupts = <31>;
                                clocks = <&clks 35>;
+                               resets = <&rstc 6>;
                        };
                };
 
                                #address-cells = <1>;
                                #size-cells = <0>;
                                clocks = <&clks 19>;
+                               resets = <&rstc 26>;
                                status = "disabled";
                        };
 
                                #address-cells = <1>;
                                #size-cells = <0>;
                                clocks = <&clks 20>;
+                               resets = <&rstc 27>;
                                status = "disabled";
                        };
 
                                                 sirf,function = "sdmmc5";
                                         };
                                 };
+                               i2s_mclk_pins_a: i2s_mclk@0 {
+                                        i2s_mclk {
+                                                sirf,pins = "i2smclkgrp";
+                                                sirf,function = "i2s_mclk";
+                                        };
+                                };
+                               i2s_ext_clk_input_pins_a: i2s_ext_clk_input@0 {
+                                        i2s_ext_clk_input {
+                                                sirf,pins = "i2s_ext_clk_inputgrp";
+                                                sirf,function = "i2s_ext_clk_input";
+                                        };
+                                };
                                 i2s_pins_a: i2s@0 {
                                         i2s {
                                                 sirf,pins = "i2sgrp";
diff --git a/arch/arm/boot/dts/bcm-cygnus-clock.dtsi b/arch/arm/boot/dts/bcm-cygnus-clock.dtsi
new file mode 100644 (file)
index 0000000..60d8389
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2014 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.
+ */
+
+clocks {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges;
+
+       osc: oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <1>;
+               clock-frequency = <25000000>;
+       };
+
+       apb_clk: apb_clk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <1000000000>;
+       };
+
+       periph_clk: periph_clk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <500000000>;
+       };
+
+       sdio_clk: lcpll_ch2 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <200000000>;
+       };
+
+       axi81_clk: axi81_clk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+       };
+
+       keypad_clk: keypad_clk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <31806>;
+       };
+
+       adc_clk: adc_clk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <1562500>;
+       };
+
+       pwm_clk: pwm_clk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <1000000>;
+       };
+
+       lcd_clk: mipipll_ch1 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+       };
+};
diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi
new file mode 100644 (file)
index 0000000..5126f9e
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2014 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.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "skeleton.dtsi"
+
+/ {
+       compatible = "brcm,cygnus";
+       model = "Broadcom Cygnus SoC";
+       interrupt-parent = <&gic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
+                       reg = <0x0>;
+               };
+       };
+
+       /include/ "bcm-cygnus-clock.dtsi"
+
+       amba {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "arm,amba-bus", "simple-bus";
+               interrupt-parent = <&gic>;
+               ranges;
+
+               wdt@18009000 {
+                        compatible = "arm,sp805" , "arm,primecell";
+                        reg = <0x18009000 0x1000>;
+                        interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+                        clocks = <&axi81_clk>;
+                        clock-names = "apb_pclk";
+               };
+       };
+
+       uart0: serial@18020000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x18020000 0x100>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&axi81_clk>;
+               clock-frequency = <100000000>;
+               status = "disabled";
+       };
+
+       uart1: serial@18021000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x18021000 0x100>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&axi81_clk>;
+               clock-frequency = <100000000>;
+               status = "disabled";
+       };
+
+       uart2: serial@18022000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x18020000 0x100>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&axi81_clk>;
+               clock-frequency = <100000000>;
+               status = "disabled";
+       };
+
+       uart3: serial@18023000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x18023000 0x100>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&axi81_clk>;
+               clock-frequency = <100000000>;
+               status = "disabled";
+       };
+
+       gic: interrupt-controller@19021000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x19021000 0x1000>,
+                     <0x19020100 0x100>;
+       };
+
+       L2: l2-cache {
+               compatible = "arm,pl310-cache";
+               reg = <0x19022000 0x1000>;
+               cache-unified;
+               cache-level = <2>;
+       };
+
+       timer@19020200 {
+               compatible = "arm,cortex-a9-global-timer";
+               reg = <0x19020200 0x100>;
+               interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&periph_clk>;
+       };
+
+};
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
new file mode 100644 (file)
index 0000000..e479515
--- /dev/null
@@ -0,0 +1,30 @@
+/dts-v1/;
+/include/ "bcm2835-rpi.dtsi"
+
+/ {
+       compatible = "raspberrypi,model-b-plus", "brcm,bcm2835";
+       model = "Raspberry Pi Model B+";
+
+       leds {
+               act {
+                       gpios = <&gpio 47 0>;
+               };
+
+               pwr {
+                       label = "PWR";
+                       gpios = <&gpio 35 0>;
+                       default-state = "keep";
+                       linux,default-trigger = "default-on";
+               };
+       };
+};
+
+&gpio {
+       pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>;
+
+       /* I2S interface */
+       i2s_alt0: i2s_alt0 {
+               brcm,pins = <18 19 20 21>;
+               brcm,function = <4>; /* alt0 */
+       };
+};
index 58a0d60b95f1b9064d790b60aef80b69edb2a962..bafa46fc226a60d0c77ba6a90c2755a75c060348 100644 (file)
@@ -1,63 +1,23 @@
 /dts-v1/;
-/include/ "bcm2835.dtsi"
+/include/ "bcm2835-rpi.dtsi"
 
 / {
        compatible = "raspberrypi,model-b", "brcm,bcm2835";
        model = "Raspberry Pi Model B";
 
-       memory {
-               reg = <0 0x10000000>;
-       };
-
        leds {
-               compatible = "gpio-leds";
-
                act {
-                       label = "ACT";
                        gpios = <&gpio 16 1>;
-                       default-state = "keep";
-                       linux,default-trigger = "heartbeat";
                };
        };
 };
 
 &gpio {
-       pinctrl-names = "default";
-       pinctrl-0 = <&gpioout &alt0 &alt2 &alt3>;
-
-       gpioout: gpioout {
-               brcm,pins = <6>;
-               brcm,function = <1>; /* GPIO out */
-       };
-
-       alt0: alt0 {
-               brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>;
-               brcm,function = <4>; /* alt0 */
-       };
-
-       alt3: alt3 {
-               brcm,pins = <48 49 50 51 52 53>;
-               brcm,function = <7>; /* alt3 */
-       };
+       pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>;
 
        /* I2S interface */
-       alt2: alt2 {
+       i2s_alt2: i2s_alt2 {
                brcm,pins = <28 29 30 31>;
                brcm,function = <6>; /* alt2 */
        };
 };
-
-&i2c0 {
-       status = "okay";
-       clock-frequency = <100000>;
-};
-
-&i2c1 {
-       status = "okay";
-       clock-frequency = <100000>;
-};
-
-&sdhci {
-       status = "okay";
-       bus-width = <4>;
-};
diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
new file mode 100644 (file)
index 0000000..c706448
--- /dev/null
@@ -0,0 +1,51 @@
+/include/ "bcm2835.dtsi"
+
+/ {
+       memory {
+               reg = <0 0x10000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               act {
+                       label = "ACT";
+                       default-state = "keep";
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
+
+&gpio {
+       pinctrl-names = "default";
+
+       gpioout: gpioout {
+               brcm,pins = <6>;
+               brcm,function = <1>; /* GPIO out */
+       };
+
+       alt0: alt0 {
+               brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>;
+               brcm,function = <4>; /* alt0 */
+       };
+
+       alt3: alt3 {
+               brcm,pins = <48 49 50 51 52 53>;
+               brcm,function = <7>; /* alt3 */
+       };
+};
+
+&i2c0 {
+       status = "okay";
+       clock-frequency = <100000>;
+};
+
+&i2c1 {
+       status = "okay";
+       clock-frequency = <100000>;
+};
+
+&sdhci {
+       status = "okay";
+       bus-width = <4>;
+};
diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
new file mode 100644 (file)
index 0000000..5fc0fae
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Broadcom BCM470X / BCM5301X ARM platform code.
+ * DTS for Buffalo WZR-1750DHP
+ *
+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+/dts-v1/;
+
+#include "bcm4708.dtsi"
+
+/ {
+       compatible = "buffalo,wzr-1750dhp", "brcm,bcm4708";
+       model = "Buffalo WZR-1750DHP (BCM4708)";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <200>;
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+               };
+
+               aoss {
+                       label = "AOSS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
+               };
+
+               /* Commit mode set by switch? */
+               mode {
+                       label = "Mode";
+                       linux,code = <KEY_SETUP>;
+                       gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+               };
+
+               /* Switch: AP mode */
+               sw_ap {
+                       label = "AP";
+                       linux,code = <BTN_0>;
+                       gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+               };
+
+               eject {
+                       label = "USB eject";
+                       linux,code = <KEY_EJECTCD>;
+                       gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
index 3b5259de5a38deefe4d0c0d8d5ee001fd79090ba..4ed7de1058b7e5d5d4296d820204e5f938277294 100644 (file)
                        status = "okay";
                };
        };
+
+       leds {
+               compatible = "gpio-leds";
+
+               logo {
+                       label = "bcm53xx:white:logo";
+                       gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               power0 {
+                       label = "bcm53xx:green:power";
+                       gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+
+               power1 {
+                       label = "bcm53xx:amber:power";
+                       gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               usb {
+                       label = "bcm53xx:blue:usb";
+                       gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+
+               wireless {
+                       label = "bcm53xx:blue:wireless";
+                       gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <200>;
+
+               wps {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
+               };
+
+               rfkill {
+                       label = "WiFi";
+                       linux,code = <KEY_RFKILL>;
+                       gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
+               };
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
+               };
+       };
 };
diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
new file mode 100644 (file)
index 0000000..12fc2a0
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Broadcom BCM470X / BCM5301X ARM platform code.
+ * DTS for Netgear R6300 V2
+ *
+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+/dts-v1/;
+
+#include "bcm4708.dtsi"
+
+/ {
+       compatible = "netgear,r6300v2", "brcm,bcm4708";
+       model = "Netgear R6300 V2 (BCM4708)";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               logo {
+                       label = "bcm53xx:white:logo";
+                       gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               power0 {
+                       label = "bcm53xx:green:power";
+                       gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+
+               power1 {
+                       label = "bcm53xx:amber:power";
+                       gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               usb {
+                       label = "bcm53xx:blue:usb";
+                       gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+
+               wireless {
+                       label = "bcm53xx:blue:wireless";
+                       gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <200>;
+
+               wps {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
+               };
+
+               rfkill {
+                       label = "WiFi";
+                       linux,code = <KEY_RFKILL>;
+                       gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
+               };
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
new file mode 100644 (file)
index 0000000..fb76378
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Broadcom BCM470X / BCM5301X ARM platform code.
+ * DTS for Asus RT-N18U
+ *
+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+/dts-v1/;
+
+#include "bcm47081.dtsi"
+
+/ {
+       compatible = "asus,rt-n18u", "brcm,bcm47081", "brcm,bcm4708";
+       model = "Asus RT-N18U (BCM47081)";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       label = "bcm53xx:blue:power";
+                       gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               usb2 {
+                       label = "bcm53xx:blue:usb2";
+                       gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+
+               wan {
+                       label = "bcm53xx:blue:wan";
+                       gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               lan {
+                       label = "bcm53xx:blue:lan";
+                       gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               usb3 {
+                       label = "bcm53xx:blue:usb3";
+                       gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <200>;
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
+               };
+
+               wps {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
new file mode 100644 (file)
index 0000000..bbb414f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Broadcom BCM470X / BCM5301X ARM platform code.
+ * DTS for Buffalo WZR-600DHP2
+ *
+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+/dts-v1/;
+
+#include "bcm47081.dtsi"
+
+/ {
+       compatible = "buffalo,wzr-600dhp2", "brcm,bcm47081", "brcm,bcm4708";
+       model = "Buffalo WZR-600DHP2 (BCM47081)";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <200>;
+
+               aoss {
+                       label = "AOSS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>;
+               };
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+               };
+
+               /* Switch device mode? */
+               mode {
+                       label = "Mode";
+                       linux,code = <KEY_SETUP>;
+                       gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+               };
+
+               eject {
+                       label = "USB eject";
+                       linux,code = <KEY_EJECTCD>;
+                       gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/bcm47081.dtsi b/arch/arm/boot/dts/bcm47081.dtsi
new file mode 100644 (file)
index 0000000..f720012
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Broadcom BCM470X / BCM5301X ARM platform code.
+ * DTS for BCM47081 SoC.
+ *
+ * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcm5301x.dtsi"
+
+/ {
+       compatible = "brcm,bcm47081";
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
+                       reg = <0x0>;
+               };
+       };
+};
index 53c624f766b48525dc0da30f944b5b1ea5f7da80..78aec6270c2f5f93687f59bf47e9f6c493ea0c31 100644 (file)
@@ -8,6 +8,8 @@
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "skeleton.dtsi"
                        clock-frequency = <400000000>;
                };
        };
+
+       axi@18000000 {
+               compatible = "brcm,bus-axi";
+               reg = <0x18000000 0x1000>;
+               ranges = <0x00000000 0x18000000 0x00100000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0x000fffff 0xffff>;
+               interrupt-map = 
+                       /* ChipCommon */
+                       <0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+
+                       /* USB 2.0 Controller */
+                       <0x00021000 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
+
+                       /* USB 3.0 Controller */
+                       <0x00023000 0 &gic GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+
+                       /* Ethernet Controller 0 */
+                       <0x00024000 0 &gic GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+
+                       /* Ethernet Controller 1 */
+                       <0x00025000 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+
+                       /* Ethernet Controller 2 */
+                       <0x00026000 0 &gic GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+
+                       /* Ethernet Controller 3 */
+                       <0x00027000 0 &gic GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+
+                       /* NAND Controller */
+                       <0x00028000 0 &gic GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00028000 1 &gic GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00028000 2 &gic GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00028000 3 &gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00028000 4 &gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00028000 5 &gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00028000 6 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+                       <0x00028000 7 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+
+               chipcommon: chipcommon@0 {
+                       reg = <0x00000000 0x1000>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+       };
 };
diff --git a/arch/arm/boot/dts/bcm911360_entphn.dts b/arch/arm/boot/dts/bcm911360_entphn.dts
new file mode 100644 (file)
index 0000000..d2ee952
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2014 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 Enterprise Phone (BCM911360_ENTPHN)";
+       compatible = "brcm,bcm11360", "brcm,cygnus";
+
+       aliases {
+               serial0 = &uart3;
+       };
+
+       chosen {
+               stdout-path = &uart3;
+               bootargs = "console=ttyS0,115200";
+       };
+
+       uart3: serial@18023000 {
+               status = "okay";
+       };
+};
diff --git a/arch/arm/boot/dts/bcm911360k.dts b/arch/arm/boot/dts/bcm911360k.dts
new file mode 100644 (file)
index 0000000..9658d4f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2014 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 SVK (BCM911360K)";
+       compatible = "brcm,bcm11360", "brcm,cygnus";
+
+       aliases {
+               serial0 = &uart3;
+       };
+
+       chosen {
+               stdout-path = &uart3;
+               bootargs = "console=ttyS0,115200";
+       };
+
+       uart3: serial@18023000 {
+               status = "okay";
+       };
+};
diff --git a/arch/arm/boot/dts/bcm958300k.dts b/arch/arm/boot/dts/bcm958300k.dts
new file mode 100644 (file)
index 0000000..f1bb36f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2014 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 SVK (BCM958300K)";
+       compatible = "brcm,bcm58300", "brcm,cygnus";
+
+       aliases {
+               serial0 = &uart3;
+       };
+
+       chosen {
+               stdout-path = &uart3;
+               bootargs = "console=ttyS0,115200";
+       };
+
+       uart3: serial@18023000 {
+               status = "okay";
+       };
+};
index c72bfd468d10ce9e8af7a9b9938eb12041d7c863..86d85d8896a30f8d17895e3545138175eae9e272 100644 (file)
        };
 };
 
+&ahci { status = "okay"; };
+
+&eth1 { status = "okay"; };
+
+/* Unpopulated SATA plug on solder side */
+&sata0 { status = "okay"; };
+
+&sata_phy { status = "okay"; };
+
+/* Samsung M8G2FA 8GB eMMC */
+&sdhci2 {
+       non-removable;
+       bus-width = <8>;
+       status = "okay";
+};
+
 &uart0 { status = "okay"; };
index 9d7c810ebd0b469a842611020d4ddc5858c288d4..015a06c67c91cf2dd3801deb200f4aed409d1bf5 100644 (file)
 
                ranges = <0 0xf7000000 0x1000000>;
 
+               sdhci0: sdhci@ab0000 {
+                       compatible = "mrvl,pxav3-mmc";
+                       reg = <0xab0000 0x200>;
+                       clocks = <&chip CLKID_SDIO0XIN>, <&chip CLKID_SDIO0>;
+                       clock-names = "io", "core";
+                       interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               sdhci1: sdhci@ab0800 {
+                       compatible = "mrvl,pxav3-mmc";
+                       reg = <0xab0800 0x200>;
+                       clocks = <&chip CLKID_SDIO1XIN>, <&chip CLKID_SDIO1>;
+                       clock-names = "io", "core";
+                       interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               sdhci2: sdhci@ab1000 {
+                       compatible = "mrvl,pxav3-mmc";
+                       reg = <0xab1000 0x200>;
+                       interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_NFC_ECC>, <&chip CLKID_NFC>;
+                       clock-names = "io", "core";
+                       pinctrl-0 = <&emmc_pmux>;
+                       pinctrl-names = "default";
+                       status = "disabled";
+               };
+
                l2: l2-cache-controller@ac0000 {
                        compatible = "marvell,tauros3-cache", "arm,pl310-cache";
                        reg = <0xac0000 0x1000>;
                        clocks = <&chip CLKID_TWD>;
                };
 
+               eth1: ethernet@b90000 {
+                       compatible = "marvell,pxa168-eth";
+                       reg = <0xb90000 0x10000>;
+                       clocks = <&chip CLKID_GETH1>;
+                       interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+                       /* set by bootloader */
+                       local-mac-address = [00 00 00 00 00 00];
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       phy-connection-type = "mii";
+                       phy-handle = <&ethphy1>;
+                       status = "disabled";
+
+                       ethphy1: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+               };
+
                cpu-ctrl@dd0000 {
                        compatible = "marvell,berlin-cpu-ctrl";
                        reg = <0xdd0000 0x10000>;
                };
 
+               eth0: ethernet@e50000 {
+                       compatible = "marvell,pxa168-eth";
+                       reg = <0xe50000 0x10000>;
+                       clocks = <&chip CLKID_GETH0>;
+                       interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+                       /* set by bootloader */
+                       local-mac-address = [00 00 00 00 00 00];
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       phy-connection-type = "mii";
+                       phy-handle = <&ethphy0>;
+                       status = "disabled";
+
+                       ethphy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+               };
+
                apb@e80000 {
                        compatible = "simple-bus";
                        #address-cells = <1>;
                        };
                };
 
+               ahci: sata@e90000 {
+                       compatible = "marvell,berlin2-ahci", "generic-ahci";
+                       reg = <0xe90000 0x1000>;
+                       interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_SATA>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy 0>;
+                               status = "disabled";
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy 1>;
+                               status = "disabled";
+                       };
+               };
+
+               sata_phy: phy@e900a0 {
+                       compatible = "marvell,berlin2-sata-phy";
+                       reg = <0xe900a0 0x200>;
+                       clocks = <&chip CLKID_SATA>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       #phy-cells = <1>;
+                       status = "disabled";
+
+                       sata-phy@0 {
+                               reg = <0>;
+                       };
+
+                       sata-phy@1 {
+                               reg = <1>;
+                       };
+               };
+
                chip: chip-control@ea0000 {
                        compatible = "marvell,berlin2-chip-ctrl";
                        #clock-cells = <1>;
+                       #reset-cells = <2>;
                        reg = <0xea0000 0x400>;
                        clocks = <&refclk>;
                        clock-names = "refclk";
+
+                       emmc_pmux: emmc-pmux {
+                               groups = "G26";
+                               function = "emmc";
+                       };
                };
 
                apb@fc0000 {
index bcd81ffc495d7d58f4ba35c70f021946bedfac4b..30270be4d0c94704c7c78d64044ac8886af99b0f 100644 (file)
@@ -11,6 +11,7 @@
 /dts-v1/;
 
 #include "berlin2cd.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        model = "Google Chromecast";
                device_type = "memory";
                reg = <0x00000000 0x20000000>; /* 512 MB */
        };
+
+       leds {
+               compatible = "gpio-leds";
+
+               white {
+                       label = "white";
+                       gpios = <&portc 1 GPIO_ACTIVE_HIGH>;
+                       default-state = "keep";
+               };
+
+               red {
+                       label = "red";
+                       gpios = <&portc 2 GPIO_ACTIVE_HIGH>;
+                       default-state = "keep";
+               };
+       };
+};
+
+/*
+ * AzureWave AW-NH387 (Marvell 88W8787)
+ * 802.11b/g/n + Bluetooth 2.1
+ */
+&sdhci0 {
+       non-removable;
+       status = "okay";
 };
 
 &uart0 { status = "okay"; };
+
+&usb_phy1 { status = "okay"; };
+
+&usb1 { status = "okay"; };
index cc1df65da504327578637068732e441d3e06af77..230df3b1770e7d2f7476b9cc49d31a7071a784c7 100644 (file)
 
                ranges = <0 0xf7000000 0x1000000>;
 
+               sdhci0: sdhci@ab0000 {
+                       compatible = "mrvl,pxav3-mmc";
+                       reg = <0xab0000 0x200>;
+                       clocks = <&chip CLKID_SDIO0XIN>, <&chip CLKID_SDIO0>;
+                       clock-names = "io", "core";
+                       interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
                l2: l2-cache-controller@ac0000 {
                        compatible = "arm,pl310-cache";
                        reg = <0xac0000 0x1000>;
                        clocks = <&chip CLKID_TWD>;
                };
 
+               usb_phy0: usb-phy@b74000 {
+                       compatible = "marvell,berlin2cd-usb-phy";
+                       reg = <0xb74000 0x128>;
+                       #phy-cells = <0>;
+                       resets = <&chip 0x178 23>;
+                       status = "disabled";
+               };
+
+               usb_phy1: usb-phy@b78000 {
+                       compatible = "marvell,berlin2cd-usb-phy";
+                       reg = <0xb78000 0x128>;
+                       #phy-cells = <0>;
+                       resets = <&chip 0x178 24>;
+                       status = "disabled";
+               };
+
+               eth1: ethernet@b90000 {
+                       compatible = "marvell,pxa168-eth";
+                       reg = <0xb90000 0x10000>;
+                       clocks = <&chip CLKID_GETH1>;
+                       interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+                       /* set by bootloader */
+                       local-mac-address = [00 00 00 00 00 00];
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       phy-connection-type = "mii";
+                       phy-handle = <&ethphy1>;
+                       status = "disabled";
+
+                       ethphy1: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+               };
+
+               eth0: ethernet@e50000 {
+                       compatible = "marvell,pxa168-eth";
+                       reg = <0xe50000 0x10000>;
+                       clocks = <&chip CLKID_GETH0>;
+                       interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+                       /* set by bootloader */
+                       local-mac-address = [00 00 00 00 00 00];
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       phy-connection-type = "mii";
+                       phy-handle = <&ethphy0>;
+                       status = "disabled";
+
+                       ethphy0: ethernet-phy@0 {
+                               reg = <0>;
+                       };
+               };
+
                apb@e80000 {
                        compatible = "simple-bus";
                        #address-cells = <1>;
                chip: chip-control@ea0000 {
                        compatible = "marvell,berlin2cd-chip-ctrl";
                        #clock-cells = <1>;
+                       #reset-cells = <2>;
                        reg = <0xea0000 0x400>;
                        clocks = <&refclk>;
                        clock-names = "refclk";
                        };
                };
 
+               usb0: usb@ed0000 {
+                       compatible = "chipidea,usb2";
+                       reg = <0xed0000 0x200>;
+                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_USB0>;
+                       phys = <&usb_phy0>;
+                       phy-names = "usb-phy";
+                       status = "disabled";
+               };
+
+               usb1: usb@ee0000 {
+                       compatible = "chipidea,usb2";
+                       reg = <0xee0000 0x200>;
+                       interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_USB1>;
+                       phys = <&usb_phy1>;
+                       phy-names = "usb-phy";
+                       status = "disabled";
+               };
+
                apb@fc0000 {
                        compatible = "simple-bus";
                        #address-cells = <1>;
index ea1f99b8eed688988fa9b7924c60389d2162dbaa..28e7e2060c3399c204f547b37fc325fa1069e8d8 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 /dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
 #include "berlin2q.dtsi"
 
 / {
        choosen {
                bootargs = "console=ttyS0,115200 earlyprintk";
        };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_usb0_vbus: regulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb0_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&portb 8 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+
+               reg_usb1_vbus: regulator@1 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&portb 10 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+
+               reg_usb2_vbus: regulator@2 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb2_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&portb 12 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+       };
 };
 
 &sdhci1 {
        status = "okay";
 };
 
+&usb_phy0 {
+       status = "okay";
+};
+
+&usb_phy2 {
+       status = "okay";
+};
+
+&usb0 {
+       vbus-supply = <&reg_usb0_vbus>;
+       status = "okay";
+};
+
+&usb2 {
+       vbus-supply = <&reg_usb2_vbus>;
+       status = "okay";
+};
+
 &eth0 {
        status = "okay";
 };
+
+&sata0 {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+};
index 891d56b03922ad8237c306c80b56c5a936f8506d..35253c947a7cd0002211dac773d7f1f9723d6fce 100644 (file)
                        #interrupt-cells = <3>;
                };
 
+               usb_phy2: phy@a2f400 {
+                       compatible = "marvell,berlin2-usb-phy";
+                       reg = <0xa2f400 0x128>;
+                       #phy-cells = <0>;
+                       resets = <&chip 0x104 14>;
+                       status = "disabled";
+               };
+
+               usb2: usb@a30000 {
+                       compatible = "chipidea,usb2";
+                       reg = <0xa30000 0x10000>;
+                       interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_USB2>;
+                       phys = <&usb_phy2>;
+                       phy-names = "usb-phy";
+                       status = "disabled";
+               };
+
+               usb_phy0: phy@b74000 {
+                       compatible = "marvell,berlin2-usb-phy";
+                       reg = <0xb74000 0x128>;
+                       #phy-cells = <0>;
+                       resets = <&chip 0x104 12>;
+                       status = "disabled";
+               };
+
+               usb_phy1: phy@b78000 {
+                       compatible = "marvell,berlin2-usb-phy";
+                       reg = <0xb78000 0x128>;
+                       #phy-cells = <0>;
+                       resets = <&chip 0x104 13>;
+                       status = "disabled";
+               };
+
                eth0: ethernet@b90000 {
                        compatible = "marvell,pxa168-eth";
                        reg = <0xb90000 0x10000>;
                        local-mac-address = [00 00 00 00 00 00];
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       phy-connection-type = "mii";
                        phy-handle = <&ethphy0>;
                        status = "disabled";
 
                                reg = <0x2c14 0x14>;
                                clocks = <&chip CLKID_CFG>;
                                clock-names = "timer";
-                               status = "disabled";
                        };
 
                        timer2: timer@2c28 {
                chip: chip-control@ea0000 {
                        compatible = "marvell,berlin2q-chip-ctrl";
                        #clock-cells = <1>;
+                       #reset-cells = <2>;
                        reg = <0xea0000 0x400>, <0xdd0170 0x10>;
                        clocks = <&refclk>;
                        clock-names = "refclk";
                        };
                };
 
+               ahci: sata@e90000 {
+                       compatible = "marvell,berlin2q-ahci", "generic-ahci";
+                       reg = <0xe90000 0x1000>;
+                       interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_SATA>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       sata0: sata-port@0 {
+                               reg = <0>;
+                               phys = <&sata_phy 0>;
+                               status = "disabled";
+                       };
+
+                       sata1: sata-port@1 {
+                               reg = <1>;
+                               phys = <&sata_phy 1>;
+                               status = "disabled";
+                       };
+               };
+
+               sata_phy: phy@e900a0 {
+                       compatible = "marvell,berlin2q-sata-phy";
+                       reg = <0xe900a0 0x200>;
+                       clocks = <&chip CLKID_SATA>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       #phy-cells = <1>;
+                       status = "disabled";
+
+                       sata-phy@0 {
+                               reg = <0>;
+                       };
+
+                       sata-phy@1 {
+                               reg = <1>;
+                       };
+               };
+
+               usb0: usb@ed0000 {
+                       compatible = "chipidea,usb2";
+                       reg = <0xed0000 0x10000>;
+                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_USB0>;
+                       phys = <&usb_phy0>;
+                       phy-names = "usb-phy";
+                       status = "disabled";
+               };
+
+               usb1: usb@ee0000 {
+                       compatible = "chipidea,usb2";
+                       reg = <0xee0000 0x10000>;
+                       interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&chip CLKID_USB1>;
+                       phys = <&usb_phy1>;
+                       phy-names = "usb-phy";
+                       status = "disabled";
+               };
+
                apb@fc0000 {
                        compatible = "simple-bus";
                        #address-cells = <1>;
index c6ce6258434fa78ddbdc240de34dcb3cd3e0e1da..736092b1a535cdd566bd41856ad64a4583227b40 100644 (file)
                        0xd0    (PIN_OUTPUT | MUX_MODE0)        /* gpmc_be0n_cle */
                >;
        };
+
+       cpsw_default: cpsw_default {
+               pinctrl-single,pins = <
+                       /* Slave 1 */
+                       0x250 (PIN_OUTPUT | MUX_MODE0)  /* rgmii0_txc.rgmii0_txc */
+                       0x254 (PIN_OUTPUT | MUX_MODE0)  /* rgmii0_txctl.rgmii0_txctl */
+                       0x258 (PIN_OUTPUT | MUX_MODE0)  /* rgmii0_td3.rgmii0_txd3 */
+                       0x25c (PIN_OUTPUT | MUX_MODE0)  /* rgmii0_txd2.rgmii0_txd2 */
+                       0x260 (PIN_OUTPUT | MUX_MODE0)  /* rgmii0_txd1.rgmii0_txd1 */
+                       0x264 (PIN_OUTPUT | MUX_MODE0)  /* rgmii0_txd0.rgmii0_txd0 */
+                       0x268 (PIN_INPUT | MUX_MODE0)   /* rgmii0_rxc.rgmii0_rxc */
+                       0x26c (PIN_INPUT | MUX_MODE0)   /* rgmii0_rxctl.rgmii0_rxctl */
+                       0x270 (PIN_INPUT | MUX_MODE0)   /* rgmii0_rxd3.rgmii0_rxd3 */
+                       0x274 (PIN_INPUT | MUX_MODE0)   /* rgmii0_rxd2.rgmii0_rxd2 */
+                       0x278 (PIN_INPUT | MUX_MODE0)   /* rgmii0_rxd1.rgmii0_rxd1 */
+                       0x27c (PIN_INPUT | MUX_MODE0)   /* rgmii0_rxd0.rgmii0_rxd0 */
+
+                       /* Slave 2 */
+                       0x198 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d12.rgmii1_txc */
+                       0x19c (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d13.rgmii1_tctl */
+                       0x1a0 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d14.rgmii1_td3 */
+                       0x1a4 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d15.rgmii1_td2 */
+                       0x1a8 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d16.rgmii1_td1 */
+                       0x1ac (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d17.rgmii1_td0 */
+                       0x1b0 (PIN_INPUT | MUX_MODE3)   /* vin2a_d18.rgmii1_rclk */
+                       0x1b4 (PIN_INPUT | MUX_MODE3)   /* vin2a_d19.rgmii1_rctl */
+                       0x1b8 (PIN_INPUT | MUX_MODE3)   /* vin2a_d20.rgmii1_rd3 */
+                       0x1bc (PIN_INPUT | MUX_MODE3)   /* vin2a_d21.rgmii1_rd2 */
+                       0x1c0 (PIN_INPUT | MUX_MODE3)   /* vin2a_d22.rgmii1_rd1 */
+                       0x1c4 (PIN_INPUT | MUX_MODE3)   /* vin2a_d23.rgmii1_rd0 */
+               >;
+
+       };
+
+       cpsw_sleep: cpsw_sleep {
+               pinctrl-single,pins = <
+                       /* Slave 1 */
+                       0x250 (MUX_MODE15)
+                       0x254 (MUX_MODE15)
+                       0x258 (MUX_MODE15)
+                       0x25c (MUX_MODE15)
+                       0x260 (MUX_MODE15)
+                       0x264 (MUX_MODE15)
+                       0x268 (MUX_MODE15)
+                       0x26c (MUX_MODE15)
+                       0x270 (MUX_MODE15)
+                       0x274 (MUX_MODE15)
+                       0x278 (MUX_MODE15)
+                       0x27c (MUX_MODE15)
+
+                       /* Slave 2 */
+                       0x198 (MUX_MODE15)
+                       0x19c (MUX_MODE15)
+                       0x1a0 (MUX_MODE15)
+                       0x1a4 (MUX_MODE15)
+                       0x1a8 (MUX_MODE15)
+                       0x1ac (MUX_MODE15)
+                       0x1b0 (MUX_MODE15)
+                       0x1b4 (MUX_MODE15)
+                       0x1b8 (MUX_MODE15)
+                       0x1bc (MUX_MODE15)
+                       0x1c0 (MUX_MODE15)
+                       0x1c4 (MUX_MODE15)
+               >;
+       };
+
+       davinci_mdio_default: davinci_mdio_default {
+               pinctrl-single,pins = <
+                       0x23c (PIN_OUTPUT_PULLUP | MUX_MODE0)   /* mdio_d.mdio_d */
+                       0x240 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mdio_clk.mdio_clk */
+               >;
+       };
+
+       davinci_mdio_sleep: davinci_mdio_sleep {
+               pinctrl-single,pins = <
+                       0x23c (MUX_MODE15)
+                       0x240 (MUX_MODE15)
+               >;
+       };
+
+       dcan1_pins_default: dcan1_pins_default {
+               pinctrl-single,pins = <
+                       0x3d0   (PIN_OUTPUT | MUX_MODE0) /* dcan1_tx */
+                       0x3d4   (MUX_MODE15)            /* dcan1_rx.off */
+                       0x418   (PULL_DIS | MUX_MODE1) /* wakeup0.dcan1_rx */
+               >;
+       };
+
+       dcan1_pins_sleep: dcan1_pins_sleep {
+               pinctrl-single,pins = <
+                       0x3d0   (MUX_MODE15)    /* dcan1_tx.off */
+                       0x3d4   (MUX_MODE15)    /* dcan1_rx.off */
+                       0x418   (MUX_MODE15)    /* wakeup0.off */
+               >;
+       };
 };
 
 &i2c1 {
                                        regulator-name = "smps45";
                                        regulator-min-microvolt = < 850000>;
                                        regulator-max-microvolt = <1150000>;
+                                       regulator-always-on;
                                        regulator-boot-on;
                                };
 
                                        regulator-name = "smps6";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <12500000>;
+                                       regulator-always-on;
                                        regulator-boot-on;
                                };
 
                                        regulator-name = "smps8";
                                        regulator-min-microvolt = < 850000>;
                                        regulator-max-microvolt = <1250000>;
+                                       regulator-always-on;
                                        regulator-boot-on;
                                };
 
                                        regulator-name = "ldo2";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
                                        regulator-boot-on;
                                };
 
                                        regulator-name = "ldo9";
                                        regulator-min-microvolt = <1050000>;
                                        regulator-max-microvolt = <1050000>;
+                                       regulator-always-on;
                                        regulator-boot-on;
                                };
 
        ti,no-reset-on-init;
        ti,no-idle-on-init;
 };
+
+&mac {
+       status = "okay";
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cpsw_default>;
+       pinctrl-1 = <&cpsw_sleep>;
+       dual_emac;
+};
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <2>;
+       phy-mode = "rgmii";
+       dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <3>;
+       phy-mode = "rgmii";
+       dual_emac_res_vlan = <2>;
+};
+
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+};
+
+&dcan1 {
+       status = "ok";
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&dcan1_pins_default>;
+       pinctrl-1 = <&dcan1_pins_sleep>;
+};
index 9cc98436a98237336581d1a7447a231d7b7525bd..63bf99be17621330488f8c0e2bff00aa4373c692 100644 (file)
                serial3 = &uart4;
                serial4 = &uart5;
                serial5 = &uart6;
+               serial6 = &uart7;
+               serial7 = &uart8;
+               serial8 = &uart9;
+               serial9 = &uart10;
+               ethernet0 = &cpsw_emac0;
+               ethernet1 = &cpsw_emac1;
+               d_can0 = &dcan1;
+               d_can1 = &dcan2;
        };
 
        timer {
                        ti,hwmods = "counter_32k";
                };
 
+               dra7_ctrl_core: ctrl_core@4a002000 {
+                       compatible = "syscon";
+                       reg = <0x4a002000 0x6d0>;
+               };
+
                dra7_ctrl_general: tisyscon@4a002e00 {
                        compatible = "syscon";
                        reg = <0x4a002e00 0x7c>;
                        ti,hwmods = "uart1";
                        clock-frequency = <48000000>;
                        status = "disabled";
+                       dmas = <&sdma 49>, <&sdma 50>;
+                       dma-names = "tx", "rx";
                };
 
                uart2: serial@4806c000 {
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                        status = "disabled";
+                       dmas = <&sdma 51>, <&sdma 52>;
+                       dma-names = "tx", "rx";
                };
 
                uart3: serial@48020000 {
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                        status = "disabled";
+                       dmas = <&sdma 53>, <&sdma 54>;
+                       dma-names = "tx", "rx";
                };
 
                uart4: serial@4806e000 {
                        ti,hwmods = "uart4";
                        clock-frequency = <48000000>;
                         status = "disabled";
+                       dmas = <&sdma 55>, <&sdma 56>;
+                       dma-names = "tx", "rx";
                };
 
                uart5: serial@48066000 {
                        ti,hwmods = "uart5";
                        clock-frequency = <48000000>;
                        status = "disabled";
+                       dmas = <&sdma 63>, <&sdma 64>;
+                       dma-names = "tx", "rx";
                };
 
                uart6: serial@48068000 {
                        ti,hwmods = "uart6";
                        clock-frequency = <48000000>;
                        status = "disabled";
+                       dmas = <&sdma 79>, <&sdma 80>;
+                       dma-names = "tx", "rx";
                };
 
                uart7: serial@48420000 {
                mailbox1: mailbox@4a0f4000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x4a0f4000 0x200>;
+                       interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox1";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <3>;
                        ti,mbox-num-fifos = <8>;
                        status = "disabled";
                mailbox2: mailbox@4883a000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x4883a000 0x200>;
+                       interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox2";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox3: mailbox@4883c000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x4883c000 0x200>;
+                       interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox3";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox4: mailbox@4883e000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x4883e000 0x200>;
+                       interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox4";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox5: mailbox@48840000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48840000 0x200>;
+                       interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox5";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox6: mailbox@48842000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48842000 0x200>;
+                       interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox6";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox7: mailbox@48844000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48844000 0x200>;
+                       interrupts = <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox7";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox8: mailbox@48846000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48846000 0x200>;
+                       interrupts = <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox8";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox9: mailbox@4885e000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x4885e000 0x200>;
+                       interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox9";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox10: mailbox@48860000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48860000 0x200>;
+                       interrupts = <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox10";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox11: mailbox@48862000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48862000 0x200>;
+                       interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox11";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox12: mailbox@48864000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48864000 0x200>;
+                       interrupts = <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox12";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                mailbox13: mailbox@48802000 {
                        compatible = "ti,omap4-mailbox";
                        reg = <0x48802000 0x200>;
+                       interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 380 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox13";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        status = "disabled";
                        status = "disabled";
                };
 
+               rtc@48838000 {
+                       compatible = "ti,am3352-rtc";
+                       reg = <0x48838000 0x100>;
+                       interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
+                       ti,hwmods = "rtcss";
+                       clocks = <&sys_32k_ck>;
+               };
+
                omap_control_usb2phy1: control-phy@4a002300 {
                        compatible = "ti,control-phy-usb2";
                        reg = <0x4a002300 0x4>;
                        };
                };
 
-               omap_dwc3_1@48880000 {
+               omap_dwc3_1: omap_dwc3_1@48880000 {
                        compatible = "ti,dwc3";
                        ti,hwmods = "usb_otg_ss1";
                        reg = <0x48880000 0x10000>;
                        };
                };
 
-               omap_dwc3_2@488c0000 {
+               omap_dwc3_2: omap_dwc3_2@488c0000 {
                        compatible = "ti,dwc3";
                        ti,hwmods = "usb_otg_ss2";
                        reg = <0x488c0000 0x10000>;
                };
 
                /* IRQ for DWC3_3 and DWC3_4 need IRQ crossbar */
-               omap_dwc3_3@48900000 {
+               omap_dwc3_3: omap_dwc3_3@48900000 {
                        compatible = "ti,dwc3";
                        ti,hwmods = "usb_otg_ss3";
                        reg = <0x48900000 0x10000>;
                        };
                };
 
-               omap_dwc3_4@48940000 {
-                       compatible = "ti,dwc3";
-                       ti,hwmods = "usb_otg_ss4";
-                       reg = <0x48940000 0x10000>;
-                       interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       utmi-mode = <2>;
-                       ranges;
-                       status = "disabled";
-                       usb4: usb@48950000 {
-                               compatible = "snps,dwc3";
-                               reg = <0x48950000 0x17000>;
-                               interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>;
-                               tx-fifo-resize;
-                               maximum-speed = "high-speed";
-                               dr_mode = "otg";
-                       };
-               };
-
                elm: elm@48078000 {
                        compatible = "ti,am3352-elm";
                        reg = <0x48078000 0xfc0>;      /* device IO registers */
                        ti,irqs-skip = <10 133 139 140>;
                        ti,irqs-safe-map = <0>;
                };
+
+               mac: ethernet@4a100000 {
+                       compatible = "ti,cpsw";
+                       ti,hwmods = "gmac";
+                       clocks = <&dpll_gmac_ck>, <&gmac_gmii_ref_clk_div>;
+                       clock-names = "fck", "cpts";
+                       cpdma_channels = <8>;
+                       ale_entries = <1024>;
+                       bd_ram_size = <0x2000>;
+                       no_bd_ram = <0>;
+                       rx_descs = <64>;
+                       mac_control = <0x20>;
+                       slaves = <2>;
+                       active_slave = <0>;
+                       cpts_clock_mult = <0x80000000>;
+                       cpts_clock_shift = <29>;
+                       reg = <0x48484000 0x1000
+                              0x48485200 0x2E00>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       /*
+                        * rx_thresh_pend
+                        * rx_pend
+                        * tx_pend
+                        * misc_pend
+                        */
+                       interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>;
+                       ranges;
+                       status = "disabled";
+
+                       davinci_mdio: mdio@48485000 {
+                               compatible = "ti,davinci_mdio";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               ti,hwmods = "davinci_mdio";
+                               bus_freq = <1000000>;
+                               reg = <0x48485000 0x100>;
+                       };
+
+                       cpsw_emac0: slave@48480200 {
+                               /* Filled in by U-Boot */
+                               mac-address = [ 00 00 00 00 00 00 ];
+                       };
+
+                       cpsw_emac1: slave@48480300 {
+                               /* Filled in by U-Boot */
+                               mac-address = [ 00 00 00 00 00 00 ];
+                       };
+
+                       phy_sel: cpsw-phy-sel@4a002554 {
+                               compatible = "ti,dra7xx-cpsw-phy-sel";
+                               reg= <0x4a002554 0x4>;
+                               reg-names = "gmii-sel";
+                       };
+               };
+
+               dcan1: can@481cc000 {
+                       compatible = "ti,dra7-d_can";
+                       ti,hwmods = "dcan1";
+                       reg = <0x4ae3c000 0x2000>;
+                       syscon-raminit = <&dra7_ctrl_core 0x558 0>;
+                       interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&dcan1_sys_clk_mux>;
+                       status = "disabled";
+               };
+
+               dcan2: can@481d0000 {
+                       compatible = "ti,dra7-d_can";
+                       ti,hwmods = "dcan2";
+                       reg = <0x48480000 0x2000>;
+                       syscon-raminit = <&dra7_ctrl_core 0x558 1>;
+                       interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&sys_clkin1>;
+                       status = "disabled";
+               };
        };
 };
 
index 41074288adfa2003b07baa3d0b27f99255d0e0c4..afc74fd4bb5e829f1866cc450eaffa3ff618880f 100644 (file)
                device_type = "memory";
                reg = <0x80000000 0x40000000>; /* 1024 MB */
        };
+
+       evm_3v3: fixedregulator-evm_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "evm_3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
 };
 
 &dra7_pmx_core {
                        0x404 (PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */
                >;
        };
+
+       nand_default: nand_default {
+               pinctrl-single,pins = <
+                       0x0     (PIN_INPUT  | MUX_MODE0) /* gpmc_ad0 */
+                       0x4     (PIN_INPUT  | MUX_MODE0) /* gpmc_ad1 */
+                       0x8     (PIN_INPUT  | MUX_MODE0) /* gpmc_ad2 */
+                       0xc     (PIN_INPUT  | MUX_MODE0) /* gpmc_ad3 */
+                       0x10    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad4 */
+                       0x14    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad5 */
+                       0x18    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad6 */
+                       0x1c    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad7 */
+                       0x20    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad8 */
+                       0x24    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad9 */
+                       0x28    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad10 */
+                       0x2c    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad11 */
+                       0x30    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad12 */
+                       0x34    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad13 */
+                       0x38    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad14 */
+                       0x3c    (PIN_INPUT  | MUX_MODE0) /* gpmc_ad15 */
+                       0xb4    (PIN_OUTPUT | MUX_MODE0) /* gpmc_cs0 */
+                       0xc4    (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale */
+                       0xcc    (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen */
+                       0xc8    (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren */
+                       0xd0    (PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0 */
+                       0xd8    (PIN_INPUT  | MUX_MODE0) /* gpmc_wait0 */
+               >;
+       };
+
+       usb1_pins: pinmux_usb1_pins {
+               pinctrl-single,pins = <
+                       0x280 (PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
+               >;
+       };
+
+       usb2_pins: pinmux_usb2_pins {
+               pinctrl-single,pins = <
+                       0x284 (PIN_INPUT_SLEW | MUX_MODE0) /* usb2_drvvbus */
+               >;
+       };
+
+       tps65917_pins_default: tps65917_pins_default {
+               pinctrl-single,pins = <
+                       0x424 (PIN_INPUT_PULLUP | MUX_MODE1) /* wakeup3.sys_nirq1 */
+               >;
+       };
+
+       mmc1_pins_default: mmc1_pins_default {
+               pinctrl-single,pins = <
+                       0x36c (PIN_INPUT | MUX_MODE14)  /* mmc1sdcd.gpio219 */
+                       0x354 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
+                       0x358 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
+                       0x35c (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
+                       0x360 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
+                       0x364 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
+                       0x368 (PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
+               >;
+       };
+
+       mmc2_pins_default: mmc2_pins_default {
+               pinctrl-single,pins = <
+                       0x9c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
+                       0xb0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
+                       0xa0 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
+                       0xa4 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
+                       0xa8 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
+                       0xac (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
+                       0x8c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
+                       0x90 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
+                       0x94 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
+                       0x98 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
+               >;
+       };
+
+       dcan1_pins_default: dcan1_pins_default {
+               pinctrl-single,pins = <
+                       0x3d0   (PIN_OUTPUT | MUX_MODE0) /* dcan1_tx */
+                       0x3d4   (MUX_MODE15)            /* dcan1_rx.off */
+                       0x418   (PULL_DIS | MUX_MODE1) /* wakeup0.dcan1_rx */
+               >;
+       };
+
+       dcan1_pins_sleep: dcan1_pins_sleep {
+               pinctrl-single,pins = <
+                       0x3d0   (MUX_MODE15)    /* dcan1_tx.off */
+                       0x3d4   (MUX_MODE15)    /* dcan1_rx.off */
+                       0x418   (MUX_MODE15)    /* wakeup0.off */
+               >;
+       };
 };
 
 &i2c1 {
                compatible = "ti,tps65917";
                reg = <0x58>;
 
+               pinctrl-names = "default";
+               pinctrl-0 = <&tps65917_pins_default>;
+
                interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
                interrupt-parent = <&gic>;
                interrupt-controller;
                                };
                        };
                };
+
+               tps65917_power_button {
+                       compatible = "ti,palmas-pwrbutton";
+                       interrupt-parent = <&tps65917>;
+                       interrupts = <1 IRQ_TYPE_NONE>;
+                       wakeup-source;
+                       ti,palmas-long-press-seconds = <6>;
+               };
        };
 };
 
 &uart1 {
        status = "okay";
 };
+
+&elm {
+       status = "okay";
+};
+
+&gpmc {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&nand_default>;
+       ranges = <0 0 0 0x01000000>;    /* minimum GPMC partition = 16MB */
+       nand@0,0 {
+               /* To use NAND, DIP switch SW5 must be set like so:
+                * SW5.1 (NAND_SELn) = ON (LOW)
+                * SW5.9 (GPMC_WPN) = OFF (HIGH)
+                */
+               reg = <0 0 4>;          /* device IO registers */
+               ti,nand-ecc-opt = "bch8";
+               ti,elm-id = <&elm>;
+               nand-bus-width = <16>;
+               gpmc,device-width = <2>;
+               gpmc,sync-clk-ps = <0>;
+               gpmc,cs-on-ns = <0>;
+               gpmc,cs-rd-off-ns = <80>;
+               gpmc,cs-wr-off-ns = <80>;
+               gpmc,adv-on-ns = <0>;
+               gpmc,adv-rd-off-ns = <60>;
+               gpmc,adv-wr-off-ns = <60>;
+               gpmc,we-on-ns = <10>;
+               gpmc,we-off-ns = <50>;
+               gpmc,oe-on-ns = <4>;
+               gpmc,oe-off-ns = <40>;
+               gpmc,access-ns = <40>;
+               gpmc,wr-access-ns = <80>;
+               gpmc,rd-cycle-ns = <80>;
+               gpmc,wr-cycle-ns = <80>;
+               gpmc,bus-turnaround-ns = <0>;
+               gpmc,cycle2cycle-delay-ns = <0>;
+               gpmc,clk-activation-ns = <0>;
+               gpmc,wait-monitoring-ns = <0>;
+               gpmc,wr-data-mux-bus-ns = <0>;
+               /* MTD partition table */
+               /* All SPL-* partitions are sized to minimal length
+                * which can be independently programmable. For
+                * NAND flash this is equal to size of erase-block */
+               #address-cells = <1>;
+               #size-cells = <1>;
+               partition@0 {
+                       label = "NAND.SPL";
+                       reg = <0x00000000 0x000020000>;
+               };
+               partition@1 {
+                       label = "NAND.SPL.backup1";
+                       reg = <0x00020000 0x00020000>;
+               };
+               partition@2 {
+                       label = "NAND.SPL.backup2";
+                       reg = <0x00040000 0x00020000>;
+               };
+               partition@3 {
+                       label = "NAND.SPL.backup3";
+                       reg = <0x00060000 0x00020000>;
+               };
+               partition@4 {
+                       label = "NAND.u-boot-spl-os";
+                       reg = <0x00080000 0x00040000>;
+               };
+               partition@5 {
+                       label = "NAND.u-boot";
+                       reg = <0x000c0000 0x00100000>;
+               };
+               partition@6 {
+                       label = "NAND.u-boot-env";
+                       reg = <0x001c0000 0x00020000>;
+               };
+               partition@7 {
+                       label = "NAND.u-boot-env.backup1";
+                       reg = <0x001e0000 0x00020000>;
+               };
+               partition@8 {
+                       label = "NAND.kernel";
+                       reg = <0x00200000 0x00800000>;
+               };
+               partition@9 {
+                       label = "NAND.file-system";
+                       reg = <0x00a00000 0x0f600000>;
+               };
+       };
+};
+
+&usb2_phy1 {
+       phy-supply = <&ldo4_reg>;
+};
+
+&usb2_phy2 {
+       phy-supply = <&ldo4_reg>;
+};
+
+&usb1 {
+       dr_mode = "peripheral";
+       pinctrl-names = "default";
+       pinctrl-0 = <&usb1_pins>;
+};
+
+&usb2 {
+       dr_mode = "host";
+       pinctrl-names = "default";
+       pinctrl-0 = <&usb2_pins>;
+};
+
+&mmc1 {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins_default>;
+
+       vmmc-supply = <&ldo1_reg>;
+       bus-width = <4>;
+       /*
+        * SDCD signal is not being used here - using the fact that GPIO mode
+        * is a viable alternative
+        */
+       cd-gpios = <&gpio6 27 0>;
+};
+
+&mmc2 {
+       /* SW5-3 in ON position */
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins_default>;
+
+       vmmc-supply = <&evm_3v3>;
+       bus-width = <8>;
+       ti,non-removable;
+};
+
+&dra7_pmx_core {
+       cpsw_default: cpsw_default {
+               pinctrl-single,pins = <
+                       /* Slave 2 */
+                       0x198 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d12.rgmii1_txc */
+                       0x19c (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d13.rgmii1_tctl */
+                       0x1a0 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d14.rgmii1_td3 */
+                       0x1a4 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d15.rgmii1_td2 */
+                       0x1a8 (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d16.rgmii1_td1 */
+                       0x1ac (PIN_OUTPUT | MUX_MODE3)  /* vin2a_d17.rgmii1_td0 */
+                       0x1b0 (PIN_INPUT | MUX_MODE3)   /* vin2a_d18.rgmii1_rclk */
+                       0x1b4 (PIN_INPUT | MUX_MODE3)   /* vin2a_d19.rgmii1_rctl */
+                       0x1b8 (PIN_INPUT | MUX_MODE3)   /* vin2a_d20.rgmii1_rd3 */
+                       0x1bc (PIN_INPUT | MUX_MODE3)   /* vin2a_d21.rgmii1_rd2 */
+                       0x1c0 (PIN_INPUT | MUX_MODE3)   /* vin2a_d22.rgmii1_rd1 */
+                       0x1c4 (PIN_INPUT | MUX_MODE3)   /* vin2a_d23.rgmii1_rd0 */
+               >;
+
+       };
+
+       cpsw_sleep: cpsw_sleep {
+               pinctrl-single,pins = <
+                       /* Slave 2 */
+                       0x198 (MUX_MODE15)
+                       0x19c (MUX_MODE15)
+                       0x1a0 (MUX_MODE15)
+                       0x1a4 (MUX_MODE15)
+                       0x1a8 (MUX_MODE15)
+                       0x1ac (MUX_MODE15)
+                       0x1b0 (MUX_MODE15)
+                       0x1b4 (MUX_MODE15)
+                       0x1b8 (MUX_MODE15)
+                       0x1bc (MUX_MODE15)
+                       0x1c0 (MUX_MODE15)
+                       0x1c4 (MUX_MODE15)
+               >;
+       };
+
+       davinci_mdio_default: davinci_mdio_default {
+               pinctrl-single,pins = <
+                       /* MDIO */
+                       0x23c (PIN_OUTPUT_PULLUP | MUX_MODE0)   /* mdio_d.mdio_d */
+                       0x240 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mdio_clk.mdio_clk */
+               >;
+       };
+
+       davinci_mdio_sleep: davinci_mdio_sleep {
+               pinctrl-single,pins = <
+                       0x23c (MUX_MODE15)
+                       0x240 (MUX_MODE15)
+               >;
+       };
+};
+
+&mac {
+       status = "okay";
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cpsw_default>;
+       pinctrl-1 = <&cpsw_sleep>;
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <3>;
+       phy-mode = "rgmii";
+};
+
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+       active_slave = <1>;
+};
+
+&dcan1 {
+       status = "ok";
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&dcan1_pins_default>;
+       pinctrl-1 = <&dcan1_pins_sleep>;
+};
index 3be544c4891ff86a0541175254317e6484561a4e..10173fab1a15b72983d43fddf453ed5d4105f73a 100644 (file)
                interrupts = <GIC_SPI DIRECT_IRQ(131) IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI DIRECT_IRQ(132) IRQ_TYPE_LEVEL_HIGH>;
        };
+
+       ocp {
+               omap_dwc3_4: omap_dwc3_4@48940000 {
+                       compatible = "ti,dwc3";
+                       ti,hwmods = "usb_otg_ss4";
+                       reg = <0x48940000 0x10000>;
+                       interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       utmi-mode = <2>;
+                       ranges;
+                       status = "disabled";
+                       usb4: usb@48950000 {
+                               compatible = "snps,dwc3";
+                               reg = <0x48950000 0x17000>;
+                               interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>;
+                               tx-fifo-resize;
+                               maximum-speed = "high-speed";
+                               dr_mode = "otg";
+                       };
+               };
+       };
 };
index 50ccd151091e23d3acbec986bb3a321181b987b5..667d323e80a3e17616aec13cd0faab9f5a638a89 100644 (file)
 
        chosen {
                bootargs = "console=ttyS1,115200n81 ignore_loglevel root=/dev/nfs ip=dhcp";
-       };
-
-       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;
-       };
-
-       lan9220@20000000 {
-               compatible = "smsc,lan9220", "smsc,lan9115";
-               reg = <0x20000000 0x10000>;
-               phy-mode = "mii";
-               interrupt-parent = <&gpio0>;
-               interrupts = <1 IRQ_TYPE_EDGE_RISING>;
-               reg-io-width = <4>;
-               smsc,irq-active-high;
-               smsc,irq-push-pull;
-               vddvario-supply = <&reg_1p8v>;
-               vdd33a-supply = <&reg_3p3v>;
+               stdout-path = &uart1;
        };
 
        gpio_keys {
                        gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
                };
        };
+
+       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;
+       };
+
+       lan9220@20000000 {
+               compatible = "smsc,lan9220", "smsc,lan9115";
+               reg = <0x20000000 0x10000>;
+               phy-mode = "mii";
+               interrupt-parent = <&gpio0>;
+               interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+               reg-io-width = <4>;
+               smsc,irq-active-high;
+               smsc,irq-push-pull;
+               vddvario-supply = <&reg_1p8v>;
+               vdd33a-supply = <&reg_3p3v>;
+       };
 };
index 00eeed3721b63bfeb0bad99169557f660a03f1cc..cc7bfe0ba40af9a90ac8756c74e45865e0c68b0a 100644 (file)
@@ -55,7 +55,7 @@
                             <0 121 IRQ_TYPE_LEVEL_HIGH>;
        };
 
-       smu@e0110000 {
+       clocks@e0110000 {
                compatible = "renesas,emev2-smu";
                reg = <0xe0110000 0x10000>;
                #address-cells = <2>;
                };
        };
 
-       sti@e0180000 {
+       timer@e0180000 {
                compatible = "renesas,em-sti";
                reg = <0xe0180000 0x54>;
                interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
                clock-names = "sclk";
        };
 
-       uart@e1020000 {
+       uart0: serial@e1020000 {
                compatible = "renesas,em-uart";
                reg = <0xe1020000 0x38>;
                interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
                clock-names = "sclk";
        };
 
-       uart@e1030000 {
+       uart1: serial@e1030000 {
                compatible = "renesas,em-uart";
                reg = <0xe1030000 0x38>;
                interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
                clock-names = "sclk";
        };
 
-       uart@e1040000 {
+       uart2: serial@e1040000 {
                compatible = "renesas,em-uart";
                reg = <0xe1040000 0x38>;
                interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
                clock-names = "sclk";
        };
 
-       uart@e1050000 {
+       uart3: serial@e1050000 {
                compatible = "renesas,em-uart";
                reg = <0xe1050000 0x38>;
                interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/exynos3250-monk.dts
new file mode 100644 (file)
index 0000000..24822aa
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * Samsung's Exynos3250 based Monk board device tree source
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Device tree source file for Samsung's Monk board which is based on
+ * Samsung Exynos3250 SoC.
+ *
+ * This program is free software; you can 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 "exynos3250.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Samsung Monk board";
+       compatible = "samsung,monk", "samsung,exynos3250", "samsung,exynos3";
+
+       aliases {
+               i2c7 = &i2c_max77836;
+       };
+
+       memory {
+               reg =  <0x40000000 0x1ff00000>;
+       };
+
+       firmware@0205F000 {
+               compatible = "samsung,secure-firmware";
+               reg = <0x0205F000 0x1000>;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               power_key {
+                       interrupt-parent = <&gpx2>;
+                       interrupts = <7 0>;
+                       gpios = <&gpx2 7 1>;
+                       linux,code = <KEY_POWER>;
+                       label = "power key";
+                       debounce-interval = <10>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       vemmc_reg: voltage-regulator-0 {
+               compatible = "regulator-fixed";
+               regulator-name = "V_EMMC_2.8V-fixed";
+               regulator-min-microvolt = <2800000>;
+               regulator-max-microvolt = <2800000>;
+               gpio = <&gpk0 2 0>;
+               enable-active-high;
+       };
+
+       i2c_max77836: i2c-gpio-0 {
+               compatible = "i2c-gpio";
+               gpios = <&gpd0 2 0>, <&gpd0 3 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               max77836: subpmic@25 {
+                       compatible = "maxim,max77836";
+                       interrupt-parent = <&gpx1>;
+                       interrupts = <5 0>;
+                       reg = <0x25>;
+                       wakeup;
+
+                       muic: max77836-muic {
+                               compatible = "maxim,max77836-muic";
+                       };
+
+                       regulators {
+                               compatible = "maxim,max77836-regulator";
+                               safeout_reg: SAFEOUT {
+                                       regulator-name = "SAFEOUT";
+                               };
+
+                               charger_reg: CHARGER {
+                                       regulator-name = "CHARGER";
+                                       regulator-min-microamp = <45000>;
+                                       regulator-max-microamp = <475000>;
+                                       regulator-boot-on;
+                               };
+
+                               motor_reg: LDO1 {
+                                       regulator-name = "MOT_2.7V";
+                                       regulator-min-microvolt = <1100000>;
+                                       regulator-max-microvolt = <2700000>;
+                               };
+
+                               LDO2 {
+                                       regulator-name = "UNUSED_LDO2";
+                                       regulator-min-microvolt = <800000>;
+                                       regulator-max-microvolt = <3950000>;
+                               };
+                       };
+
+                       charger {
+                               compatible = "maxim,max77836-charger";
+
+                               maxim,constant-uvolt = <4350000>;
+                               maxim,fast-charge-uamp = <225000>;
+                               maxim,eoc-uamp = <7500>;
+                               maxim,ovp-uvolt = <6500000>;
+                       };
+               };
+       };
+};
+
+&adc {
+       vdd-supply = <&ldo3_reg>;
+       status = "okay";
+       assigned-clocks = <&cmu CLK_SCLK_TSADC>;
+       assigned-clock-rates = <6000000>;
+
+       thermistor-ap {
+               compatible = "ntc,ncp15wb473";
+               pullup-uv = <1800000>;
+               pullup-ohm = <100000>;
+               pulldown-ohm = <100000>;
+               io-channels = <&adc 0>;
+       };
+
+       thermistor-battery {
+               compatible = "ntc,ncp15wb473";
+               pullup-uv = <1800000>;
+               pullup-ohm = <100000>;
+               pulldown-ohm = <100000>;
+               io-channels = <&adc 1>;
+       };
+};
+
+&i2c_0 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-slave-addr = <0x10>;
+       samsung,i2c-max-bus-freq = <100000>;
+       status = "okay";
+
+       s2mps14_pmic@66 {
+               compatible = "samsung,s2mps14-pmic";
+               interrupt-parent = <&gpx0>;
+               interrupts = <7 0>;
+               reg = <0x66>;
+               wakeup;
+
+               s2mps14_osc: clocks {
+                       compatible = "samsung,s2mps14-clk";
+                       #clock-cells = <1>;
+                       clock-output-names = "s2mps14_ap", "unused",
+                               "s2mps14_bt";
+               };
+
+               regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "VAP_ALIVE_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: LDO2 {
+                               regulator-name = "VAP_M1_1.2V";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                       };
+
+                       ldo3_reg: LDO3 {
+                               regulator-name = "VCC_AP_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo4_reg: LDO4 {
+                               regulator-name = "VAP_AVDD_PLL1";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo5_reg: LDO5 {
+                               regulator-name = "VAP_PLL_ISO_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo6_reg: LDO6 {
+                               regulator-name = "VAP_MIPI_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo7_reg: LDO7 {
+                               regulator-name = "VAP_AVDD_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo8_reg: LDO8 {
+                               regulator-name = "VAP_USB_3.0V";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo9_reg: LDO9 {
+                               regulator-name = "V_LPDDR_1.2V";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "UNUSED_LDO10";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo11_reg: LDO11 {
+                               regulator-name = "V_EMMC_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               samsung,ext-control-gpios = <&gpk0 2 0>;
+                       };
+
+                       ldo12_reg: LDO12 {
+                               regulator-name = "V_EMMC_2.8V";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               samsung,ext-control-gpios = <&gpk0 2 0>;
+                       };
+
+                       ldo13_reg: LDO13 {
+                               regulator-name = "VSENSOR_2.85V";
+                               regulator-min-microvolt = <2850000>;
+                               regulator-max-microvolt = <2850000>;
+                               regulator-always-on;
+                       };
+
+                       ldo14_reg: LDO14 {
+                               regulator-name = "UNUSED_LDO14";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo15_reg: LDO15 {
+                               regulator-name = "TSP_AVDD_3.3V";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "LCD_VDD_3.3V";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       ldo17_reg: LDO17 {
+                               regulator-name = "UNUSED_LDO17";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo18_reg: LDO18 {
+                               regulator-name = "UNUSED_LDO18";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo19_reg: LDO19 {
+                               regulator-name = "TSP_VDD_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo20_reg: LDO20 {
+                               regulator-name = "LCD_VDD_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo21_reg: LDO21 {
+                               regulator-name = "UNUSED_LDO21";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo22_reg: LDO22 {
+                               regulator-name = "UNUSED_LDO22";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo23_reg: LDO23 {
+                               regulator-name = "UNUSED_LDO23";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       ldo24_reg: LDO24 {
+                               regulator-name = "UNUSED_LDO24";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       ldo25_reg: LDO25 {
+                               regulator-name = "UNUSED_LDO25";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "VAP_MIF_1.0V";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <900000>;
+                               regulator-always-on;
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "VAP_ARM_1.0V";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1150000>;
+                               regulator-always-on;
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "VAP_INT3D_1.0V";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "VCC_SUB_1.95V";
+                               regulator-min-microvolt = <1950000>;
+                               regulator-max-microvolt = <1950000>;
+                               regulator-always-on;
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "VCC_SUB_1.35V";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+&i2c_1 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-slave-addr = <0x10>;
+       samsung,i2c-max-bus-freq = <400000>;
+       status = "okay";
+
+       fuelgauge@36 {
+               compatible = "maxim,max77836-battery";
+               interrupt-parent = <&gpx1>;
+               interrupts = <2 8>;
+               reg = <0x36>;
+       };
+};
+
+&i2s2 {
+       status = "okay";
+};
+
+&mshc_0 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       num-slots = <1>;
+       broken-cd;
+       non-removable;
+       cap-mmc-highspeed;
+       desc-num = <4>;
+       mmc-hs200-1_8v;
+       card-detect-delay = <200>;
+       vmmc-supply = <&vemmc_reg>;
+       clock-frequency = <100000000>;
+       clock-freq-min-max = <400000 100000000>;
+       samsung,dw-mshc-ciu-div = <1>;
+       samsung,dw-mshc-sdr-timing = <0 1>;
+       samsung,dw-mshc-ddr-timing = <1 2>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8>;
+       bus-width = <8>;
+       status = "okay";
+};
+
+&serial_0 {
+       assigned-clocks = <&cmu CLK_SCLK_UART0>;
+       assigned-clock-rates = <100000000>;
+       status = "okay";
+};
+
+&serial_1 {
+       status = "okay";
+};
+
+&tmu {
+       vtmu-supply = <&ldo7_reg>;
+       status = "okay";
+};
+
+&rtc {
+       clocks = <&cmu CLK_RTC>, <&s2mps14_osc 0>;
+       clock-names = "rtc", "rtc_src";
+       status = "okay";
+};
+
+&xusbxti {
+       clock-frequency = <24000000>;
+};
+
+&pinctrl_0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep0>;
+
+       sleep0: sleep-state {
+               PIN_SLP(gpa0-0, INPUT, DOWN);
+               PIN_SLP(gpa0-1, INPUT, DOWN);
+               PIN_SLP(gpa0-2, INPUT, DOWN);
+               PIN_SLP(gpa0-3, INPUT, DOWN);
+               PIN_SLP(gpa0-4, INPUT, DOWN);
+               PIN_SLP(gpa0-5, INPUT, DOWN);
+               PIN_SLP(gpa0-6, INPUT, DOWN);
+               PIN_SLP(gpa0-7, INPUT, DOWN);
+
+               PIN_SLP(gpa1-0, INPUT, DOWN);
+               PIN_SLP(gpa1-1, INPUT, DOWN);
+               PIN_SLP(gpa1-2, INPUT, DOWN);
+               PIN_SLP(gpa1-3, INPUT, DOWN);
+               PIN_SLP(gpa1-4, INPUT, DOWN);
+               PIN_SLP(gpa1-5, INPUT, DOWN);
+
+               PIN_SLP(gpb-0, PREV, NONE);
+               PIN_SLP(gpb-1, PREV, NONE);
+               PIN_SLP(gpb-2, PREV, NONE);
+               PIN_SLP(gpb-3, PREV, NONE);
+               PIN_SLP(gpb-4, INPUT, DOWN);
+               PIN_SLP(gpb-5, INPUT, DOWN);
+               PIN_SLP(gpb-6, INPUT, DOWN);
+               PIN_SLP(gpb-7, INPUT, DOWN);
+
+               PIN_SLP(gpc0-0, INPUT, DOWN);
+               PIN_SLP(gpc0-1, INPUT, DOWN);
+               PIN_SLP(gpc0-2, INPUT, DOWN);
+               PIN_SLP(gpc0-3, INPUT, DOWN);
+               PIN_SLP(gpc0-4, INPUT, DOWN);
+
+               PIN_SLP(gpc1-0, INPUT, DOWN);
+               PIN_SLP(gpc1-1, INPUT, DOWN);
+               PIN_SLP(gpc1-2, INPUT, DOWN);
+               PIN_SLP(gpc1-3, INPUT, DOWN);
+               PIN_SLP(gpc1-4, INPUT, DOWN);
+
+               PIN_SLP(gpd0-0, INPUT, DOWN);
+               PIN_SLP(gpd0-1, INPUT, DOWN);
+               PIN_SLP(gpd0-2, INPUT, NONE);
+               PIN_SLP(gpd0-3, INPUT, NONE);
+
+               PIN_SLP(gpd1-0, INPUT, NONE);
+               PIN_SLP(gpd1-1, INPUT, NONE);
+               PIN_SLP(gpd1-2, INPUT, NONE);
+               PIN_SLP(gpd1-3, INPUT, NONE);
+       };
+};
+
+&pinctrl_1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep1>;
+
+       sleep1: sleep-state {
+               PIN_SLP(gpe0-0, PREV, NONE);
+               PIN_SLP(gpe0-1, PREV, NONE);
+               PIN_SLP(gpe0-2, INPUT, DOWN);
+               PIN_SLP(gpe0-3, INPUT, DOWN);
+               PIN_SLP(gpe0-4, PREV, NONE);
+               PIN_SLP(gpe0-5, INPUT, DOWN);
+               PIN_SLP(gpe0-6, INPUT, DOWN);
+               PIN_SLP(gpe0-7, INPUT, DOWN);
+
+               PIN_SLP(gpe1-0, INPUT, DOWN);
+               PIN_SLP(gpe1-1, PREV, NONE);
+               PIN_SLP(gpe1-2, INPUT, DOWN);
+               PIN_SLP(gpe1-3, INPUT, DOWN);
+               PIN_SLP(gpe1-4, INPUT, DOWN);
+               PIN_SLP(gpe1-5, INPUT, DOWN);
+               PIN_SLP(gpe1-6, INPUT, DOWN);
+               PIN_SLP(gpe1-7, INPUT, NONE);
+
+               PIN_SLP(gpe2-0, INPUT, NONE);
+               PIN_SLP(gpe2-1, INPUT, NONE);
+               PIN_SLP(gpe2-2, INPUT, NONE);
+
+               PIN_SLP(gpk0-0, INPUT, DOWN);
+               PIN_SLP(gpk0-1, INPUT, DOWN);
+               PIN_SLP(gpk0-2, OUT0, NONE);
+               PIN_SLP(gpk0-3, INPUT, DOWN);
+               PIN_SLP(gpk0-4, INPUT, DOWN);
+               PIN_SLP(gpk0-5, INPUT, DOWN);
+               PIN_SLP(gpk0-6, INPUT, DOWN);
+               PIN_SLP(gpk0-7, INPUT, DOWN);
+
+               PIN_SLP(gpk1-0, PREV, NONE);
+               PIN_SLP(gpk1-1, PREV, NONE);
+               PIN_SLP(gpk1-2, INPUT, DOWN);
+               PIN_SLP(gpk1-3, PREV, NONE);
+               PIN_SLP(gpk1-4, PREV, NONE);
+               PIN_SLP(gpk1-5, PREV, NONE);
+               PIN_SLP(gpk1-6, PREV, NONE);
+
+               PIN_SLP(gpk2-0, INPUT, DOWN);
+               PIN_SLP(gpk2-1, INPUT, DOWN);
+               PIN_SLP(gpk2-2, INPUT, DOWN);
+               PIN_SLP(gpk2-3, INPUT, DOWN);
+               PIN_SLP(gpk2-4, INPUT, DOWN);
+               PIN_SLP(gpk2-5, INPUT, DOWN);
+               PIN_SLP(gpk2-6, INPUT, DOWN);
+
+               PIN_SLP(gpl0-0, INPUT, DOWN);
+               PIN_SLP(gpl0-1, INPUT, DOWN);
+               PIN_SLP(gpl0-2, INPUT, DOWN);
+               PIN_SLP(gpl0-3, INPUT, DOWN);
+
+               PIN_SLP(gpm0-0, INPUT, DOWN);
+               PIN_SLP(gpm0-1, INPUT, DOWN);
+               PIN_SLP(gpm0-2, INPUT, DOWN);
+               PIN_SLP(gpm0-3, INPUT, DOWN);
+               PIN_SLP(gpm0-4, INPUT, DOWN);
+               PIN_SLP(gpm0-5, INPUT, DOWN);
+               PIN_SLP(gpm0-6, INPUT, DOWN);
+               PIN_SLP(gpm0-7, INPUT, DOWN);
+
+               PIN_SLP(gpm1-0, INPUT, DOWN);
+               PIN_SLP(gpm1-1, INPUT, DOWN);
+               PIN_SLP(gpm1-2, INPUT, DOWN);
+               PIN_SLP(gpm1-3, INPUT, DOWN);
+               PIN_SLP(gpm1-4, INPUT, DOWN);
+               PIN_SLP(gpm1-5, INPUT, DOWN);
+               PIN_SLP(gpm1-6, INPUT, DOWN);
+
+               PIN_SLP(gpm2-0, INPUT, DOWN);
+               PIN_SLP(gpm2-1, INPUT, DOWN);
+               PIN_SLP(gpm2-2, INPUT, DOWN);
+               PIN_SLP(gpm2-3, INPUT, DOWN);
+               PIN_SLP(gpm2-4, INPUT, DOWN);
+
+               PIN_SLP(gpm3-0, INPUT, DOWN);
+               PIN_SLP(gpm3-1, INPUT, DOWN);
+               PIN_SLP(gpm3-2, INPUT, DOWN);
+               PIN_SLP(gpm3-3, INPUT, DOWN);
+               PIN_SLP(gpm3-4, INPUT, DOWN);
+               PIN_SLP(gpm3-5, INPUT, DOWN);
+               PIN_SLP(gpm3-6, INPUT, DOWN);
+               PIN_SLP(gpm3-7, INPUT, DOWN);
+
+               PIN_SLP(gpm4-0, INPUT, DOWN);
+               PIN_SLP(gpm4-1, INPUT, DOWN);
+               PIN_SLP(gpm4-2, INPUT, DOWN);
+               PIN_SLP(gpm4-3, INPUT, DOWN);
+               PIN_SLP(gpm4-4, INPUT, DOWN);
+               PIN_SLP(gpm4-5, INPUT, DOWN);
+               PIN_SLP(gpm4-6, INPUT, DOWN);
+               PIN_SLP(gpm4-7, INPUT, DOWN);
+       };
+};
index 47b92c150f4e5cd6e3501ee9708df16d8e024df8..5ab81c39e2c9ca8bcd21e1cb14559e2e0166837a 100644 (file)
  * published by the Free Software Foundation.
 */
 
+#define PIN_PULL_NONE          0
+#define PIN_PULL_DOWN          1
+#define PIN_PULL_UP            3
+
+#define PIN_PDN_OUT0           0
+#define PIN_PDN_OUT1           1
+#define PIN_PDN_INPUT          2
+#define PIN_PDN_PREV           3
+
+#define PIN_SLP(_pin, _mode, _pull)                            \
+       _pin {                                                  \
+               samsung,pins = #_pin;                           \
+               samsung,pin-con-pdn = <PIN_PDN_ ##_mode>;       \
+               samsung,pin-pud-pdn = <PIN_PULL_ ##_pull>;      \
+       }
+
 &pinctrl_0 {
        gpa0: gpa0 {
                gpio-controller;
diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts
new file mode 100644 (file)
index 0000000..80aa8b4
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+ * Samsung's Exynos3250 based Rinato board device tree source
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Device tree source file for Samsung's Rinato board which is based on
+ * Samsung Exynos3250 SoC.
+ *
+ * This program is free software; you can 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 "exynos3250.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Samsung Rinato board";
+       compatible = "samsung,rinato", "samsung,exynos3250", "samsung,exynos3";
+
+       aliases {
+               i2c7 = &i2c_max77836;
+       };
+
+       memory {
+               reg =  <0x40000000 0x1ff00000>;
+       };
+
+       firmware@0205F000 {
+               compatible = "samsung,secure-firmware";
+               reg = <0x0205F000 0x1000>;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               power_key {
+                       interrupt-parent = <&gpx2>;
+                       interrupts = <7 0>;
+                       gpios = <&gpx2 7 1>;
+                       linux,code = <KEY_POWER>;
+                       label = "power key";
+                       debounce-interval = <10>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       i2c_max77836: i2c-gpio-0 {
+               compatible = "i2c-gpio";
+               gpios = <&gpd0 2 0>, <&gpd0 3 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               max77836: subpmic@25 {
+                       compatible = "maxim,max77836";
+                       interrupt-parent = <&gpx1>;
+                       interrupts = <5 0>;
+                       reg = <0x25>;
+                       wakeup;
+
+                       muic: max77836-muic {
+                               compatible = "maxim,max77836-muic";
+                       };
+
+                       regulators {
+                               compatible = "maxim,max77836-regulator";
+                               safeout_reg: SAFEOUT {
+                                       regulator-name = "SAFEOUT";
+                               };
+
+                               charger_reg: CHARGER {
+                                       regulator-name = "CHARGER";
+                                       regulator-min-microamp = <45000>;
+                                       regulator-max-microamp = <475000>;
+                                       regulator-boot-on;
+                               };
+
+                               motor_reg: LDO1 {
+                                       regulator-name = "MOT_2.7V";
+                                       regulator-min-microvolt = <1100000>;
+                                       regulator-max-microvolt = <2700000>;
+                               };
+
+                               LDO2 {
+                                       regulator-name = "UNUSED_LDO2";
+                                       regulator-min-microvolt = <800000>;
+                                       regulator-max-microvolt = <3950000>;
+                               };
+                       };
+
+                       charger {
+                               compatible = "maxim,max77836-charger";
+
+                               maxim,constant-uvolt = <4350000>;
+                               maxim,fast-charge-uamp = <225000>;
+                               maxim,eoc-uamp = <7500>;
+                               maxim,ovp-uvolt = <6500000>;
+                       };
+               };
+       };
+};
+
+&adc {
+       vdd-supply = <&ldo3_reg>;
+       status = "okay";
+       assigned-clocks = <&cmu CLK_SCLK_TSADC>;
+       assigned-clock-rates = <6000000>;
+
+       thermistor-ap {
+               compatible = "ntc,ncp15wb473";
+               pullup-uv = <1800000>;
+               pullup-ohm = <100000>;
+               pulldown-ohm = <100000>;
+               io-channels = <&adc 0>;
+       };
+
+       thermistor-battery {
+               compatible = "ntc,ncp15wb473";
+               pullup-uv = <1800000>;
+               pullup-ohm = <100000>;
+               pulldown-ohm = <100000>;
+               io-channels = <&adc 1>;
+       };
+};
+
+&i2c_0 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-slave-addr = <0x10>;
+       samsung,i2c-max-bus-freq = <100000>;
+       status = "okay";
+
+       s2mps14_pmic@66 {
+               compatible = "samsung,s2mps14-pmic";
+               interrupt-parent = <&gpx0>;
+               interrupts = <7 0>;
+               reg = <0x66>;
+               wakeup;
+
+               s2mps14_osc: clocks {
+                       compatible = "samsung,s2mps14-clk";
+                       #clock-cells = <1>;
+                       clock-output-names = "s2mps14_ap", "unused",
+                               "s2mps14_bt";
+               };
+
+               regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "VAP_ALIVE_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       ldo2_reg: LDO2 {
+                               regulator-name = "VAP_M1_1.2V";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo3_reg: LDO3 {
+                               regulator-name = "VCC_AP_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo4_reg: LDO4 {
+                               regulator-name = "VAP_AVDD_PLL1";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo5_reg: LDO5 {
+                               regulator-name = "VAP_PLL_ISO_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo6_reg: LDO6 {
+                               regulator-name = "VAP_VMIPI_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo7_reg: LDO7 {
+                               regulator-name = "VAP_AVDD_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo8_reg: LDO8 {
+                               regulator-name = "VAP_USB_3.0V";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo9_reg: LDO9 {
+                               regulator-name = "V_LPDDR_1.2V";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "UNUSED_LDO10";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo11_reg: LDO11 {
+                               regulator-name = "V_EMMC_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               samsung,ext-control-gpios = <&gpk0 2 0>;
+                       };
+
+                       ldo12_reg: LDO12 {
+                               regulator-name = "V_EMMC_2.8V";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               samsung,ext-control-gpios = <&gpk0 2 0>;
+                       };
+
+                       ldo13_reg: LDO13 {
+                               regulator-name = "CAM_AVDD_2.8V";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo14_reg: LDO14 {
+                               regulator-name = "UNUSED_LDO14";
+                               regulator-min-microvolt = <2700000>;
+                               regulator-max-microvolt = <2700000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo15_reg: LDO15 {
+                               regulator-name = "TSP_AVDD_3.3V";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "LCD_VDD_3.3V";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo17_reg: LDO17 {
+                               regulator-name = "V_IRLED_3.3V";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo18_reg: LDO18 {
+                               regulator-name = "CAM_AF_2.8V";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo19_reg: LDO19 {
+                               regulator-name = "TSP_VDD_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo20_reg: LDO20 {
+                               regulator-name = "LCD_VDD_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo21_reg: LDO21 {
+                               regulator-name = "CAM_IO_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo22_reg: LDO22 {
+                               regulator-name = "CAM_DVDD_1.2V";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo23_reg: LDO23 {
+                               regulator-name = "HRM_VCC_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       ldo24_reg: LDO24 {
+                               regulator-name = "HRM_VCC_3.3V";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo25_reg: LDO25 {
+                               regulator-name = "UNUSED_LDO25";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "VAP_MIF_1.0V";
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <900000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "VAP_ARM_1.0V";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1150000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "VAP_INT3D_1.0V";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "VCC_SUB_1.95V";
+                               regulator-min-microvolt = <1950000>;
+                               regulator-max-microvolt = <1950000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "VCC_SUB_1.35V";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+               };
+       };
+};
+
+&i2c_1 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-slave-addr = <0x10>;
+       samsung,i2c-max-bus-freq = <400000>;
+       status = "okay";
+
+       fuelgauge@36 {
+               compatible = "maxim,max77836-battery";
+               interrupt-parent = <&gpx1>;
+               interrupts = <2 8>;
+               reg = <0x36>;
+       };
+};
+
+&i2s2 {
+       status = "okay";
+};
+
+&mfc {
+       status = "okay";
+};
+
+&mshc_0 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       num-slots = <1>;
+       broken-cd;
+       non-removable;
+       cap-mmc-highspeed;
+       desc-num = <4>;
+       mmc-hs200-1_8v;
+       card-detect-delay = <200>;
+       vmmc-supply = <&ldo12_reg>;
+       clock-frequency = <100000000>;
+       clock-freq-min-max = <400000 100000000>;
+       samsung,dw-mshc-ciu-div = <1>;
+       samsung,dw-mshc-sdr-timing = <0 1>;
+       samsung,dw-mshc-ddr-timing = <1 2>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8>;
+       bus-width = <8>;
+       status = "okay";
+};
+
+&serial_0 {
+       assigned-clocks = <&cmu CLK_SCLK_UART0>;
+       assigned-clock-rates = <100000000>;
+       status = "okay";
+};
+
+&serial_1 {
+       status = "okay";
+};
+
+&tmu {
+       vtmu-supply = <&ldo7_reg>;
+       status = "okay";
+};
+
+&rtc {
+       clocks = <&cmu CLK_RTC>, <&s2mps14_osc 0>;
+       clock-names = "rtc", "rtc_src";
+       status = "okay";
+};
+
+&xusbxti {
+       clock-frequency = <24000000>;
+};
+
+&pinctrl_0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep0>;
+
+       sleep0: sleep-state {
+               PIN_SLP(gpa0-0, INPUT, DOWN);
+               PIN_SLP(gpa0-1, INPUT, DOWN);
+               PIN_SLP(gpa0-2, INPUT, DOWN);
+               PIN_SLP(gpa0-3, INPUT, DOWN);
+               PIN_SLP(gpa0-4, INPUT, DOWN);
+               PIN_SLP(gpa0-5, INPUT, DOWN);
+               PIN_SLP(gpa0-6, INPUT, DOWN);
+               PIN_SLP(gpa0-7, INPUT, DOWN);
+
+               PIN_SLP(gpa1-0, INPUT, DOWN);
+               PIN_SLP(gpa1-1, INPUT, DOWN);
+               PIN_SLP(gpa1-2, INPUT, DOWN);
+               PIN_SLP(gpa1-3, INPUT, DOWN);
+               PIN_SLP(gpa1-4, INPUT, DOWN);
+               PIN_SLP(gpa1-5, INPUT, DOWN);
+
+               PIN_SLP(gpb-0, PREV, NONE);
+               PIN_SLP(gpb-1, PREV, NONE);
+               PIN_SLP(gpb-2, PREV, NONE);
+               PIN_SLP(gpb-3, PREV, NONE);
+               PIN_SLP(gpb-4, INPUT, DOWN);
+               PIN_SLP(gpb-5, INPUT, DOWN);
+               PIN_SLP(gpb-6, INPUT, DOWN);
+               PIN_SLP(gpb-7, INPUT, DOWN);
+
+               PIN_SLP(gpc0-0, INPUT, DOWN);
+               PIN_SLP(gpc0-1, INPUT, DOWN);
+               PIN_SLP(gpc0-2, INPUT, DOWN);
+               PIN_SLP(gpc0-3, INPUT, DOWN);
+               PIN_SLP(gpc0-4, INPUT, DOWN);
+
+               PIN_SLP(gpc1-0, INPUT, DOWN);
+               PIN_SLP(gpc1-1, INPUT, DOWN);
+               PIN_SLP(gpc1-2, INPUT, DOWN);
+               PIN_SLP(gpc1-3, INPUT, DOWN);
+               PIN_SLP(gpc1-4, INPUT, DOWN);
+
+               PIN_SLP(gpd0-0, INPUT, DOWN);
+               PIN_SLP(gpd0-1, INPUT, DOWN);
+               PIN_SLP(gpd0-2, INPUT, NONE);
+               PIN_SLP(gpd0-3, INPUT, NONE);
+
+               PIN_SLP(gpd1-0, INPUT, NONE);
+               PIN_SLP(gpd1-1, INPUT, NONE);
+               PIN_SLP(gpd1-2, INPUT, NONE);
+               PIN_SLP(gpd1-3, INPUT, NONE);
+       };
+};
+
+&pinctrl_1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep1>;
+
+       sleep1: sleep-state {
+               PIN_SLP(gpe0-0, PREV, NONE);
+               PIN_SLP(gpe0-1, PREV, NONE);
+               PIN_SLP(gpe0-2, INPUT, DOWN);
+               PIN_SLP(gpe0-3, INPUT, UP);
+               PIN_SLP(gpe0-4, INPUT, DOWN);
+               PIN_SLP(gpe0-5, INPUT, DOWN);
+               PIN_SLP(gpe0-6, INPUT, DOWN);
+               PIN_SLP(gpe0-7, INPUT, DOWN);
+
+               PIN_SLP(gpe1-0, INPUT, DOWN);
+               PIN_SLP(gpe1-1, PREV, NONE);
+               PIN_SLP(gpe1-2, INPUT, DOWN);
+               PIN_SLP(gpe1-3, INPUT, DOWN);
+               PIN_SLP(gpe1-4, INPUT, DOWN);
+               PIN_SLP(gpe1-5, INPUT, DOWN);
+               PIN_SLP(gpe1-6, INPUT, DOWN);
+               PIN_SLP(gpe1-7, INPUT, NONE);
+
+               PIN_SLP(gpe2-0, INPUT, NONE);
+               PIN_SLP(gpe2-1, INPUT, NONE);
+               PIN_SLP(gpe2-2, INPUT, NONE);
+
+               PIN_SLP(gpk0-0, INPUT, DOWN);
+               PIN_SLP(gpk0-1, INPUT, DOWN);
+               PIN_SLP(gpk0-2, OUT0, NONE);
+               PIN_SLP(gpk0-3, INPUT, DOWN);
+               PIN_SLP(gpk0-4, INPUT, DOWN);
+               PIN_SLP(gpk0-5, INPUT, DOWN);
+               PIN_SLP(gpk0-6, INPUT, DOWN);
+               PIN_SLP(gpk0-7, INPUT, DOWN);
+
+               PIN_SLP(gpk1-0, INPUT, DOWN);
+               PIN_SLP(gpk1-1, INPUT, DOWN);
+               PIN_SLP(gpk1-2, INPUT, DOWN);
+               PIN_SLP(gpk1-3, INPUT, DOWN);
+               PIN_SLP(gpk1-4, INPUT, DOWN);
+               PIN_SLP(gpk1-5, INPUT, DOWN);
+               PIN_SLP(gpk1-6, INPUT, DOWN);
+
+               PIN_SLP(gpk2-0, INPUT, DOWN);
+               PIN_SLP(gpk2-1, INPUT, DOWN);
+               PIN_SLP(gpk2-2, INPUT, DOWN);
+               PIN_SLP(gpk2-3, INPUT, DOWN);
+               PIN_SLP(gpk2-4, INPUT, DOWN);
+               PIN_SLP(gpk2-5, INPUT, DOWN);
+               PIN_SLP(gpk2-6, INPUT, DOWN);
+
+               PIN_SLP(gpl0-0, INPUT, DOWN);
+               PIN_SLP(gpl0-1, INPUT, DOWN);
+               PIN_SLP(gpl0-2, INPUT, DOWN);
+               PIN_SLP(gpl0-3, INPUT, DOWN);
+
+               PIN_SLP(gpm0-0, INPUT, DOWN);
+               PIN_SLP(gpm0-1, INPUT, DOWN);
+               PIN_SLP(gpm0-2, INPUT, DOWN);
+               PIN_SLP(gpm0-3, INPUT, DOWN);
+               PIN_SLP(gpm0-4, INPUT, DOWN);
+               PIN_SLP(gpm0-5, INPUT, DOWN);
+               PIN_SLP(gpm0-6, INPUT, DOWN);
+               PIN_SLP(gpm0-7, INPUT, DOWN);
+
+               PIN_SLP(gpm1-0, INPUT, DOWN);
+               PIN_SLP(gpm1-1, INPUT, DOWN);
+               PIN_SLP(gpm1-2, INPUT, DOWN);
+               PIN_SLP(gpm1-3, INPUT, DOWN);
+               PIN_SLP(gpm1-4, INPUT, DOWN);
+               PIN_SLP(gpm1-5, INPUT, DOWN);
+               PIN_SLP(gpm1-6, INPUT, DOWN);
+
+               PIN_SLP(gpm2-0, INPUT, DOWN);
+               PIN_SLP(gpm2-1, INPUT, DOWN);
+               PIN_SLP(gpm2-2, INPUT, DOWN);
+               PIN_SLP(gpm2-3, INPUT, DOWN);
+               PIN_SLP(gpm2-4, INPUT, DOWN);
+
+               PIN_SLP(gpm3-0, INPUT, DOWN);
+               PIN_SLP(gpm3-1, INPUT, DOWN);
+               PIN_SLP(gpm3-2, INPUT, DOWN);
+               PIN_SLP(gpm3-3, INPUT, DOWN);
+               PIN_SLP(gpm3-4, INPUT, DOWN);
+               PIN_SLP(gpm3-5, INPUT, DOWN);
+               PIN_SLP(gpm3-6, INPUT, DOWN);
+               PIN_SLP(gpm3-7, INPUT, DOWN);
+
+               PIN_SLP(gpm4-0, INPUT, DOWN);
+               PIN_SLP(gpm4-1, INPUT, DOWN);
+               PIN_SLP(gpm4-2, INPUT, DOWN);
+               PIN_SLP(gpm4-3, INPUT, DOWN);
+               PIN_SLP(gpm4-4, INPUT, DOWN);
+               PIN_SLP(gpm4-5, INPUT, DOWN);
+               PIN_SLP(gpm4-6, INPUT, DOWN);
+               PIN_SLP(gpm4-7, INPUT, DOWN);
+       };
+};
index 693a3275606f2ab4c25e7647c5606ac42e88139d..242ddda0a8cdf161fca0813954bf24a7dbe2b12a 100644 (file)
                        status = "disabled";
                };
 
+               mfc: codec@13400000 {
+                       compatible = "samsung,mfc-v7";
+                       reg = <0x13400000 0x10000>;
+                       interrupts = <0 102 0>;
+                       clock-names = "mfc", "sclk_mfc";
+                       clocks = <&cmu CLK_MFC>, <&cmu CLK_SCLK_MFC>;
+                       samsung,power-domain = <&pd_mfc>;
+                       status = "disabled";
+               };
+
                serial_0: serial@13800000 {
                        compatible = "samsung,exynos4210-uart";
                        reg = <0x13800000 0x100>;
index e0278ecbc816a10291c65a1540e696aecbea9248..b8168f1f8139baf3a1420ba17061ad18dfa41151 100644 (file)
                reg = <0x13400000 0x10000>;
                interrupts = <0 94 0>;
                samsung,power-domain = <&pd_mfc>;
-               clocks = <&clock CLK_MFC>;
-               clock-names = "mfc";
+               clocks = <&clock CLK_MFC>, <&clock CLK_SCLK_MFC>;
+               clock-names = "mfc", "sclk_mfc";
                status = "disabled";
        };
 
index f516da9e8b3ae0b9de8a53857be04f89cbdfa4fa..720836205546f22dd078d590aef80664d2af7011 100644 (file)
 
                fimc_0: fimc@11800000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC0>,
+                                       <&clock CLK_SCLK_FIMC0>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
 
                fimc_1: fimc@11810000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC1>,
+                                       <&clock CLK_SCLK_FIMC1>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
 
                fimc_2: fimc@11820000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC2>,
+                                       <&clock CLK_SCLK_FIMC2>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
 
                fimc_3: fimc@11830000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC3>,
+                                       <&clock CLK_SCLK_FIMC3>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
        };
 };
index d50eb3aa708e9a5709f94c5c7491e8d85d1d2387..aaf0cae4f5e87bd976d34a591f52f11b5f4990c5 100644 (file)
 
                fimc_0: fimc@11800000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC0>,
+                                       <&clock CLK_SCLK_FIMC0>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
 
                fimc_1: fimc@11810000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC1>,
+                                       <&clock CLK_SCLK_FIMC1>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
 
                fimc_2: fimc@11820000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC2>,
+                                       <&clock CLK_SCLK_FIMC2>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
 
                fimc_3: fimc@11830000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC3>,
+                                       <&clock CLK_SCLK_FIMC3>;
+                       assigned-clock-parents = <&clock CLK_SCLK_MPLL>;
+                       assigned-clock-rates = <0>, <160000000>;
                };
        };
 };
index 807bb5bf91fc84db70430ba17b7f507b6ca11a76..bcc9e63c8070194f5c0ab4e88b729159911ae107 100644 (file)
                pinctrl2 = &pinctrl_2;
        };
 
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@900 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0x900>;
+               };
+
+               cpu@901 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0x901>;
+               };
+       };
+
        pmu_system_controller: system-controller@10020000 {
                clock-names = "clkout0", "clkout1", "clkout2", "clkout3",
                                "clkout4", "clkout8", "clkout9";
index 3c00e6ec93027f8ca410c1ee39b3b5d3200c3cd7..dd0a43ec56da905d64fc02f596b70d0ce92e67f3 100644 (file)
 / {
        compatible = "samsung,exynos4212", "samsung,exynos4";
 
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@A00 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xA00>;
+               };
+
+               cpu@A01 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xA01>;
+               };
+       };
+
        combiner: interrupt-controller@10440000 {
                samsung,combiner-nr = <18>;
        };
index c697ff01ae8dd4e214125b1e93ab223daccf1578..3fbf588682b94fcf8f6b340ad266794741825f34 100644 (file)
                compatible = "samsung,odroidx2-audio";
                samsung,i2s-controller = <&i2s0>;
                samsung,audio-codec = <&max98090>;
+               assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
+                               <&clock_audss EXYNOS_MOUT_I2S>,
+                               <&clock_audss EXYNOS_DOUT_SRP>,
+                               <&clock_audss EXYNOS_DOUT_AUD_BUS>;
+               assigned-clock-parents = <&clock CLK_FOUT_EPLL>,
+                               <&clock_audss EXYNOS_MOUT_AUDSS>;
+               assigned-clock-rates = <0>,
+                               <0>,
+                               <192000000>,
+                               <19200000>;
        };
 
        mmc@12550000 {
 
                fimc_0: fimc@11800000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC0>,
+                                       <&clock CLK_SCLK_FIMC0>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
 
                fimc_1: fimc@11810000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC1>,
+                                       <&clock CLK_SCLK_FIMC1>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
 
                fimc_2: fimc@11820000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC2>,
+                                       <&clock CLK_SCLK_FIMC2>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
 
                fimc_3: fimc@11830000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC3>,
+                                       <&clock CLK_SCLK_FIMC3>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
        };
 
index 5e066cd87f6653595142d2b34d533a973fc1b78c..29231b4526433ef0fbae30e81d81088671dc3ac1 100644 (file)
@@ -14,6 +14,7 @@
 
 /dts-v1/;
 #include "exynos4412.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        model = "Samsung Trats 2 based on Exynos4412";
@@ -22,6 +23,7 @@
        aliases {
                i2c9 = &i2c_ak8975;
                i2c10 = &i2c_cm36651;
+               i2c11 = &i2c_max77693;
        };
 
        memory {
                                        regulator-name = "VMEM_VDD_2.8V";
                                        regulator-min-microvolt = <2800000>;
                                        regulator-max-microvolt = <2800000>;
-                                       regulator-always-on;
-                                       regulator-mem-off;
                                };
 
                                ldo23_reg: ldo23 {
                                        regulator-name = "VMEM_VDDF_3.0V";
                                        regulator-min-microvolt = <2850000>;
                                        regulator-max-microvolt = <2850000>;
-                                       regulator-always-on;
-                                       regulator-mem-off;
                                };
 
                                buck9_reg: buck9 {
                };
        };
 
+       i2c_max77693: i2c-gpio-1 {
+               compatible = "i2c-gpio";
+               gpios = <&gpm2 0 GPIO_ACTIVE_HIGH>, <&gpm2 1 GPIO_ACTIVE_HIGH>;
+               i2c-gpio,delay-us = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "okay";
+
+               max77693@66 {
+                       compatible = "maxim,max77693";
+                       interrupt-parent = <&gpx1>;
+                       interrupts = <5 2>;
+                       reg = <0x66>;
+
+                       regulators {
+                               esafeout1_reg: ESAFEOUT1@1 {
+                                       regulator-name = "ESAFEOUT1";
+                               };
+                               esafeout2_reg: ESAFEOUT2@2 {
+                                       regulator-name = "ESAFEOUT2";
+                               };
+                               charger_reg: CHARGER@0 {
+                                       regulator-name = "CHARGER";
+                                       regulator-min-microamp = <60000>;
+                                       regulator-max-microamp = <2580000>;
+                               };
+                       };
+
+                       max77693_haptic {
+                               compatible = "maxim,max77693-haptic";
+                               haptic-supply = <&ldo26_reg>;
+                               pwms = <&pwm 0 38022 0>;
+                       };
+               };
+       };
+
        mmc@12550000 {
                num-slots = <1>;
                broken-cd;
                cap-mmc-highspeed;
        };
 
+       sdhci@12530000 {
+               bus-width = <4>;
+               cd-gpios = <&gpx3 4 0>;
+               cd-inverted;
+               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>;
+               pinctrl-names = "default";
+               vmmc-supply = <&ldo21_reg>;
+               status = "okay";
+       };
+
        serial@13800000 {
                status = "okay";
        };
                status = "okay";
        };
 
+       tmu@100C0000 {
+               vtmu-supply = <&ldo10_reg>;
+               status = "okay";
+       };
+
        i2c_ak8975: i2c-gpio-0 {
                compatible = "i2c-gpio";
                gpios = <&gpy2 4 0>, <&gpy2 5 0>;
                };
        };
 
+       pwm: pwm@139D0000 {
+               pinctrl-0 = <&pwm0_out>;
+               pinctrl-names = "default";
+               samsung,pwm-outputs = <0>;
+               status = "okay";
+       };
+
        dsi_0: dsi@11C80000 {
                vddcore-supply = <&ldo8_reg>;
                vddio-supply = <&ldo10_reg>;
                pinctrl-0 = <&cam_port_a_clk_active &cam_port_b_clk_active>;
                pinctrl-names = "default";
                status = "okay";
+               assigned-clocks = <&clock CLK_MOUT_CAM0>,
+                                 <&clock CLK_MOUT_CAM1>;
+               assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>,
+                                        <&clock CLK_MOUT_MPLL_USER_T>;
 
                fimc_0: fimc@11800000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC0>,
+                                       <&clock CLK_SCLK_FIMC0>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
 
                fimc_1: fimc@11810000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC1>,
+                                       <&clock CLK_SCLK_FIMC1>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
 
                fimc_2: fimc@11820000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC2>,
+                                       <&clock CLK_SCLK_FIMC2>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
 
                fimc_3: fimc@11830000 {
                        status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_FIMC3>,
+                                       <&clock CLK_SCLK_FIMC3>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
                };
 
                csis_0: csis@11880000 {
                        status = "okay";
                        vddcore-supply = <&ldo8_reg>;
                        vddio-supply = <&ldo10_reg>;
-                       clock-frequency = <176000000>;
+                       assigned-clocks = <&clock CLK_MOUT_CSIS0>,
+                                       <&clock CLK_SCLK_CSIS0>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
 
                        /* Camera C (3) MIPI CSI-2 (CSIS0) */
                        port@3 {
                };
 
                csis_1: csis@11890000 {
+                       status = "okay";
                        vddcore-supply = <&ldo8_reg>;
                        vddio-supply = <&ldo10_reg>;
-                       clock-frequency = <160000000>;
-                       status = "okay";
+                       assigned-clocks = <&clock CLK_MOUT_CSIS1>,
+                                       <&clock CLK_SCLK_CSIS1>;
+                       assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+                       assigned-clock-rates = <0>, <176000000>;
 
                        /* Camera D (4) MIPI CSI-2 (CSIS1) */
                        port@4 {
                io-channels = <&adc 2>;  /* Battery temperature */
        };
 };
+
+&pinctrl_0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep0>;
+
+       sleep0: sleep-states {
+               PIN_SLP(gpa0-0, INPUT, NONE);
+               PIN_SLP(gpa0-1, OUT0, NONE);
+               PIN_SLP(gpa0-2, INPUT, NONE);
+               PIN_SLP(gpa0-3, INPUT, UP);
+               PIN_SLP(gpa0-4, INPUT, NONE);
+               PIN_SLP(gpa0-5, INPUT, DOWN);
+               PIN_SLP(gpa0-6, INPUT, DOWN);
+               PIN_SLP(gpa0-7, INPUT, UP);
+
+               PIN_SLP(gpa1-0, INPUT, DOWN);
+               PIN_SLP(gpa1-1, INPUT, DOWN);
+               PIN_SLP(gpa1-2, INPUT, DOWN);
+               PIN_SLP(gpa1-3, INPUT, DOWN);
+               PIN_SLP(gpa1-4, INPUT, DOWN);
+               PIN_SLP(gpa1-5, INPUT, DOWN);
+
+               PIN_SLP(gpb-0, INPUT, NONE);
+               PIN_SLP(gpb-1, INPUT, NONE);
+               PIN_SLP(gpb-2, INPUT, NONE);
+               PIN_SLP(gpb-3, INPUT, NONE);
+               PIN_SLP(gpb-4, INPUT, DOWN);
+               PIN_SLP(gpb-5, INPUT, UP);
+               PIN_SLP(gpb-6, INPUT, DOWN);
+               PIN_SLP(gpb-7, INPUT, DOWN);
+
+               PIN_SLP(gpc0-0, INPUT, DOWN);
+               PIN_SLP(gpc0-1, INPUT, DOWN);
+               PIN_SLP(gpc0-2, INPUT, DOWN);
+               PIN_SLP(gpc0-3, INPUT, DOWN);
+               PIN_SLP(gpc0-4, INPUT, DOWN);
+
+               PIN_SLP(gpc1-0, INPUT, NONE);
+               PIN_SLP(gpc1-1, PREV, NONE);
+               PIN_SLP(gpc1-2, INPUT, NONE);
+               PIN_SLP(gpc1-3, INPUT, NONE);
+               PIN_SLP(gpc1-4, INPUT, NONE);
+
+               PIN_SLP(gpd0-0, INPUT, DOWN);
+               PIN_SLP(gpd0-1, INPUT, DOWN);
+               PIN_SLP(gpd0-2, INPUT, NONE);
+               PIN_SLP(gpd0-3, INPUT, NONE);
+
+               PIN_SLP(gpd1-0, INPUT, DOWN);
+               PIN_SLP(gpd1-1, INPUT, DOWN);
+               PIN_SLP(gpd1-2, INPUT, NONE);
+               PIN_SLP(gpd1-3, INPUT, NONE);
+
+               PIN_SLP(gpf0-0, INPUT, NONE);
+               PIN_SLP(gpf0-1, INPUT, NONE);
+               PIN_SLP(gpf0-2, INPUT, DOWN);
+               PIN_SLP(gpf0-3, INPUT, DOWN);
+               PIN_SLP(gpf0-4, INPUT, NONE);
+               PIN_SLP(gpf0-5, INPUT, DOWN);
+               PIN_SLP(gpf0-6, INPUT, NONE);
+               PIN_SLP(gpf0-7, INPUT, DOWN);
+
+               PIN_SLP(gpf1-0, INPUT, DOWN);
+               PIN_SLP(gpf1-1, INPUT, DOWN);
+               PIN_SLP(gpf1-2, INPUT, DOWN);
+               PIN_SLP(gpf1-3, INPUT, DOWN);
+               PIN_SLP(gpf1-4, INPUT, NONE);
+               PIN_SLP(gpf1-5, INPUT, NONE);
+               PIN_SLP(gpf1-6, INPUT, DOWN);
+               PIN_SLP(gpf1-7, PREV, NONE);
+
+               PIN_SLP(gpf2-0, PREV, NONE);
+               PIN_SLP(gpf2-1, INPUT, DOWN);
+               PIN_SLP(gpf2-2, INPUT, DOWN);
+               PIN_SLP(gpf2-3, INPUT, DOWN);
+               PIN_SLP(gpf2-4, INPUT, DOWN);
+               PIN_SLP(gpf2-5, INPUT, DOWN);
+               PIN_SLP(gpf2-6, INPUT, NONE);
+               PIN_SLP(gpf2-7, INPUT, NONE);
+
+               PIN_SLP(gpf3-0, INPUT, NONE);
+               PIN_SLP(gpf3-1, PREV, NONE);
+               PIN_SLP(gpf3-2, PREV, NONE);
+               PIN_SLP(gpf3-3, PREV, NONE);
+               PIN_SLP(gpf3-4, OUT1, NONE);
+               PIN_SLP(gpf3-5, INPUT, DOWN);
+
+               PIN_SLP(gpj0-0, PREV, NONE);
+               PIN_SLP(gpj0-1, PREV, NONE);
+               PIN_SLP(gpj0-2, PREV, NONE);
+               PIN_SLP(gpj0-3, INPUT, DOWN);
+               PIN_SLP(gpj0-4, PREV, NONE);
+               PIN_SLP(gpj0-5, PREV, NONE);
+               PIN_SLP(gpj0-6, INPUT, DOWN);
+               PIN_SLP(gpj0-7, INPUT, DOWN);
+
+               PIN_SLP(gpj1-0, INPUT, DOWN);
+               PIN_SLP(gpj1-1, PREV, NONE);
+               PIN_SLP(gpj1-2, PREV, NONE);
+               PIN_SLP(gpj1-3, INPUT, DOWN);
+               PIN_SLP(gpj1-4, INPUT, DOWN);
+       };
+};
+
+&pinctrl_1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep1>;
+
+       sleep1: sleep-states {
+               PIN_SLP(gpk0-0, PREV, NONE);
+               PIN_SLP(gpk0-1, PREV, NONE);
+               PIN_SLP(gpk0-2, OUT0, NONE);
+               PIN_SLP(gpk0-3, PREV, NONE);
+               PIN_SLP(gpk0-4, PREV, NONE);
+               PIN_SLP(gpk0-5, PREV, NONE);
+               PIN_SLP(gpk0-6, PREV, NONE);
+
+               PIN_SLP(gpk1-0, INPUT, DOWN);
+               PIN_SLP(gpk1-1, INPUT, DOWN);
+               PIN_SLP(gpk1-2, INPUT, DOWN);
+               PIN_SLP(gpk1-3, PREV, NONE);
+               PIN_SLP(gpk1-4, PREV, NONE);
+               PIN_SLP(gpk1-5, PREV, NONE);
+               PIN_SLP(gpk1-6, PREV, NONE);
+
+               PIN_SLP(gpk2-0, INPUT, DOWN);
+               PIN_SLP(gpk2-1, INPUT, DOWN);
+               PIN_SLP(gpk2-2, INPUT, DOWN);
+               PIN_SLP(gpk2-3, INPUT, DOWN);
+               PIN_SLP(gpk2-4, INPUT, DOWN);
+               PIN_SLP(gpk2-5, INPUT, DOWN);
+               PIN_SLP(gpk2-6, INPUT, DOWN);
+
+               PIN_SLP(gpk3-0, OUT0, NONE);
+               PIN_SLP(gpk3-1, INPUT, NONE);
+               PIN_SLP(gpk3-2, INPUT, DOWN);
+               PIN_SLP(gpk3-3, INPUT, NONE);
+               PIN_SLP(gpk3-4, INPUT, NONE);
+               PIN_SLP(gpk3-5, INPUT, NONE);
+               PIN_SLP(gpk3-6, INPUT, NONE);
+
+               PIN_SLP(gpl0-0, INPUT, DOWN);
+               PIN_SLP(gpl0-1, INPUT, DOWN);
+               PIN_SLP(gpl0-2, INPUT, DOWN);
+               PIN_SLP(gpl0-3, INPUT, DOWN);
+               PIN_SLP(gpl0-4, PREV, NONE);
+               PIN_SLP(gpl0-6, PREV, NONE);
+
+               PIN_SLP(gpl1-0, INPUT, DOWN);
+               PIN_SLP(gpl1-1, INPUT, DOWN);
+               PIN_SLP(gpl2-0, INPUT, DOWN);
+               PIN_SLP(gpl2-1, INPUT, DOWN);
+               PIN_SLP(gpl2-2, INPUT, DOWN);
+               PIN_SLP(gpl2-3, INPUT, DOWN);
+               PIN_SLP(gpl2-4, INPUT, DOWN);
+               PIN_SLP(gpl2-5, INPUT, DOWN);
+               PIN_SLP(gpl2-6, PREV, NONE);
+               PIN_SLP(gpl2-7, INPUT, DOWN);
+
+               PIN_SLP(gpm0-0, INPUT, DOWN);
+               PIN_SLP(gpm0-1, INPUT, DOWN);
+               PIN_SLP(gpm0-2, INPUT, DOWN);
+               PIN_SLP(gpm0-3, INPUT, DOWN);
+               PIN_SLP(gpm0-4, INPUT, DOWN);
+               PIN_SLP(gpm0-5, INPUT, DOWN);
+               PIN_SLP(gpm0-6, INPUT, DOWN);
+               PIN_SLP(gpm0-7, INPUT, DOWN);
+
+               PIN_SLP(gpm1-0, INPUT, DOWN);
+               PIN_SLP(gpm1-1, INPUT, DOWN);
+               PIN_SLP(gpm1-2, INPUT, NONE);
+               PIN_SLP(gpm1-3, INPUT, NONE);
+               PIN_SLP(gpm1-4, INPUT, NONE);
+               PIN_SLP(gpm1-5, INPUT, NONE);
+               PIN_SLP(gpm1-6, INPUT, DOWN);
+
+               PIN_SLP(gpm2-0, INPUT, NONE);
+               PIN_SLP(gpm2-1, INPUT, NONE);
+               PIN_SLP(gpm2-2, INPUT, DOWN);
+               PIN_SLP(gpm2-3, INPUT, DOWN);
+               PIN_SLP(gpm2-4, INPUT, DOWN);
+
+               PIN_SLP(gpm3-0, PREV, NONE);
+               PIN_SLP(gpm3-1, PREV, NONE);
+               PIN_SLP(gpm3-2, PREV, NONE);
+               PIN_SLP(gpm3-3, OUT1, NONE);
+               PIN_SLP(gpm3-4, INPUT, DOWN);
+               PIN_SLP(gpm3-5, INPUT, DOWN);
+               PIN_SLP(gpm3-6, INPUT, DOWN);
+               PIN_SLP(gpm3-7, INPUT, DOWN);
+
+               PIN_SLP(gpm4-0, INPUT, DOWN);
+               PIN_SLP(gpm4-1, INPUT, DOWN);
+               PIN_SLP(gpm4-2, INPUT, DOWN);
+               PIN_SLP(gpm4-3, INPUT, DOWN);
+               PIN_SLP(gpm4-4, INPUT, DOWN);
+               PIN_SLP(gpm4-5, INPUT, DOWN);
+               PIN_SLP(gpm4-6, INPUT, DOWN);
+               PIN_SLP(gpm4-7, INPUT, DOWN);
+
+               PIN_SLP(gpy0-0, INPUT, DOWN);
+               PIN_SLP(gpy0-1, INPUT, DOWN);
+               PIN_SLP(gpy0-2, INPUT, DOWN);
+               PIN_SLP(gpy0-3, INPUT, DOWN);
+               PIN_SLP(gpy0-4, INPUT, DOWN);
+               PIN_SLP(gpy0-5, INPUT, DOWN);
+
+               PIN_SLP(gpy1-0, INPUT, DOWN);
+               PIN_SLP(gpy1-1, INPUT, DOWN);
+               PIN_SLP(gpy1-2, INPUT, DOWN);
+               PIN_SLP(gpy1-3, INPUT, DOWN);
+
+               PIN_SLP(gpy2-0, PREV, NONE);
+               PIN_SLP(gpy2-1, INPUT, DOWN);
+               PIN_SLP(gpy2-2, INPUT, NONE);
+               PIN_SLP(gpy2-3, INPUT, NONE);
+               PIN_SLP(gpy2-4, INPUT, NONE);
+               PIN_SLP(gpy2-5, INPUT, NONE);
+
+               PIN_SLP(gpy3-0, INPUT, DOWN);
+               PIN_SLP(gpy3-1, INPUT, DOWN);
+               PIN_SLP(gpy3-2, INPUT, DOWN);
+               PIN_SLP(gpy3-3, INPUT, DOWN);
+               PIN_SLP(gpy3-4, INPUT, DOWN);
+               PIN_SLP(gpy3-5, INPUT, DOWN);
+               PIN_SLP(gpy3-6, INPUT, DOWN);
+               PIN_SLP(gpy3-7, INPUT, DOWN);
+
+               PIN_SLP(gpy4-0, INPUT, DOWN);
+               PIN_SLP(gpy4-1, INPUT, DOWN);
+               PIN_SLP(gpy4-2, INPUT, DOWN);
+               PIN_SLP(gpy4-3, INPUT, DOWN);
+               PIN_SLP(gpy4-4, INPUT, DOWN);
+               PIN_SLP(gpy4-5, INPUT, DOWN);
+               PIN_SLP(gpy4-6, INPUT, DOWN);
+               PIN_SLP(gpy4-7, INPUT, DOWN);
+
+               PIN_SLP(gpy5-0, INPUT, DOWN);
+               PIN_SLP(gpy5-1, INPUT, DOWN);
+               PIN_SLP(gpy5-2, INPUT, DOWN);
+               PIN_SLP(gpy5-3, INPUT, DOWN);
+               PIN_SLP(gpy5-4, INPUT, DOWN);
+               PIN_SLP(gpy5-5, INPUT, DOWN);
+               PIN_SLP(gpy5-6, INPUT, DOWN);
+               PIN_SLP(gpy5-7, INPUT, DOWN);
+
+               PIN_SLP(gpy6-0, INPUT, DOWN);
+               PIN_SLP(gpy6-1, INPUT, DOWN);
+               PIN_SLP(gpy6-2, INPUT, DOWN);
+               PIN_SLP(gpy6-3, INPUT, DOWN);
+               PIN_SLP(gpy6-4, INPUT, DOWN);
+               PIN_SLP(gpy6-5, INPUT, DOWN);
+               PIN_SLP(gpy6-6, INPUT, DOWN);
+               PIN_SLP(gpy6-7, INPUT, DOWN);
+       };
+};
+
+&pinctrl_2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep2>;
+
+       sleep2: sleep-states {
+               PIN_SLP(gpz-0, INPUT, DOWN);
+               PIN_SLP(gpz-1, INPUT, DOWN);
+               PIN_SLP(gpz-2, INPUT, DOWN);
+               PIN_SLP(gpz-3, INPUT, DOWN);
+               PIN_SLP(gpz-4, INPUT, DOWN);
+               PIN_SLP(gpz-5, INPUT, DOWN);
+               PIN_SLP(gpz-6, INPUT, DOWN);
+       };
+};
+
+&pinctrl_3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sleep3>;
+
+       sleep3: sleep-states {
+               PIN_SLP(gpv0-0, INPUT, DOWN);
+               PIN_SLP(gpv0-1, INPUT, DOWN);
+               PIN_SLP(gpv0-2, INPUT, DOWN);
+               PIN_SLP(gpv0-3, INPUT, DOWN);
+               PIN_SLP(gpv0-4, INPUT, DOWN);
+               PIN_SLP(gpv0-5, INPUT, DOWN);
+               PIN_SLP(gpv0-6, INPUT, DOWN);
+               PIN_SLP(gpv0-7, INPUT, DOWN);
+
+               PIN_SLP(gpv1-0, INPUT, DOWN);
+               PIN_SLP(gpv1-1, INPUT, DOWN);
+               PIN_SLP(gpv1-2, INPUT, DOWN);
+               PIN_SLP(gpv1-3, INPUT, DOWN);
+               PIN_SLP(gpv1-4, INPUT, DOWN);
+               PIN_SLP(gpv1-5, INPUT, DOWN);
+               PIN_SLP(gpv1-6, INPUT, DOWN);
+               PIN_SLP(gpv1-7, INPUT, DOWN);
+
+               PIN_SLP(gpv2-0, INPUT, DOWN);
+               PIN_SLP(gpv2-1, INPUT, DOWN);
+               PIN_SLP(gpv2-2, INPUT, DOWN);
+               PIN_SLP(gpv2-3, INPUT, DOWN);
+               PIN_SLP(gpv2-4, INPUT, DOWN);
+               PIN_SLP(gpv2-5, INPUT, DOWN);
+               PIN_SLP(gpv2-6, INPUT, DOWN);
+               PIN_SLP(gpv2-7, INPUT, DOWN);
+
+               PIN_SLP(gpv3-0, INPUT, DOWN);
+               PIN_SLP(gpv3-1, INPUT, DOWN);
+               PIN_SLP(gpv3-2, INPUT, DOWN);
+               PIN_SLP(gpv3-3, INPUT, DOWN);
+               PIN_SLP(gpv3-4, INPUT, DOWN);
+               PIN_SLP(gpv3-5, INPUT, DOWN);
+               PIN_SLP(gpv3-6, INPUT, DOWN);
+               PIN_SLP(gpv3-7, INPUT, DOWN);
+
+               PIN_SLP(gpv4-0, INPUT, DOWN);
+       };
+};
index d8bc059e172ff1562ea4525cedc2ad14948a4bad..0f6ec93bb1d8a243d511dac4e2e42f6a794e9015 100644 (file)
 / {
        compatible = "samsung,exynos4412", "samsung,exynos4";
 
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@A00 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xA00>;
+               };
+
+               cpu@A01 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xA01>;
+               };
+
+               cpu@A02 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xA02>;
+               };
+
+               cpu@A03 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xA03>;
+               };
+       };
+
        combiner: interrupt-controller@10440000 {
                samsung,combiner-nr = <20>;
        };
diff --git a/arch/arm/boot/dts/exynos4415-pinctrl.dtsi b/arch/arm/boot/dts/exynos4415-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..75af9c5
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * Samsung's Exynos4415 SoCs pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Samsung's Exynos4415 SoCs pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed in this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+&pinctrl_0 {
+       gpa0: gpa0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpa1: gpa1 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpb: gpb {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpc0: gpc0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpc1: gpc1 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpd0: gpd0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpd1: gpd1 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpf0: gpf0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpf1: gpf1 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpf2: gpf2 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       uart0_data: uart0-data {
+               samsung,pins = "gpa0-0", "gpa0-1";
+               samsung,pin-function = <0x2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       uart0_fctl: uart0-fctl {
+               samsung,pins = "gpa0-2", "gpa0-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       uart1_data: uart1-data {
+               samsung,pins = "gpa0-4", "gpa0-5";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       uart1_fctl: uart1-fctl {
+               samsung,pins = "gpa0-6", "gpa0-7";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       uart2_data: uart2-data {
+               samsung,pins = "gpa1-0", "gpa1-1";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       uart2_fctl: uart2-fctl {
+               samsung,pins = "gpa1-2", "gpa1-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       uart3_data: uart3-data {
+               samsung,pins = "gpa1-4", "gpa1-5";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c2_bus: i2c2-bus {
+               samsung,pins = "gpa0-6", "gpa0-7";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c3_bus: i2c3-bus {
+               samsung,pins = "gpa1-2", "gpa1-3";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       spi0_bus: spi0-bus {
+               samsung,pins = "gpb-0", "gpb-2", "gpb-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c4_bus: i2c4-bus {
+               samsung,pins = "gpb-0", "gpb-1";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       spi1_bus: spi1-bus {
+               samsung,pins = "gpb-4", "gpb-6", "gpb-7";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c5_bus: i2c5-bus {
+               samsung,pins = "gpb-2", "gpb-3";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2s1_bus: i2s1-bus {
+               samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+                               "gpc0-4";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2s2_bus: i2s2-bus {
+               samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+                               "gpc1-4";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       pcm2_bus: pcm2-bus {
+               samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+                               "gpc1-4";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c6_bus: i2c6-bus {
+               samsung,pins = "gpc1-3", "gpc1-4";
+               samsung,pin-function = <4>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       spi2_bus: spi2-bus {
+               samsung,pins = "gpc1-1", "gpc1-3", "gpc1-4";
+               samsung,pin-function = <5>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       pwm0_out: pwm0-out {
+               samsung,pins = "gpd0-0";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       pwm1_out: pwm1-out {
+               samsung,pins = "gpd0-1";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       pwm2_out: pwm2-out {
+               samsung,pins = "gpd0-2";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       pwm3_out: pwm3-out {
+               samsung,pins = "gpd0-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c7_bus: i2c7-bus {
+               samsung,pins = "gpd0-2", "gpd0-3";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c0_bus: i2c0-bus {
+               samsung,pins = "gpd1-0", "gpd1-1";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       i2c1_bus: i2c1-bus {
+               samsung,pins = "gpd1-2", "gpd1-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+};
+
+&pinctrl_1 {
+       gpk0: gpk0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpk1: gpk1 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpk2: gpk2 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpk3: gpk3 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpl0: gpl0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpm0: gpm0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpm1: gpm1 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpm2: gpm2 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpm3: gpm3 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpm4: gpm4 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpx0: gpx0 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               interrupt-parent = <&gic>;
+               interrupts = <0 32 0>, <0 33 0>, <0 34 0>, <0 35 0>,
+                               <0 36 0>, <0 37 0>, <0 38 0>, <0 39 0>;
+               #interrupt-cells = <2>;
+       };
+
+       gpx1: gpx1 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               interrupt-parent = <&gic>;
+               interrupts = <0 40 0>, <0 41 0>, <0 42 0>, <0 43 0>,
+                               <0 44 0>, <0 45 0>, <0 46 0>, <0 47 0>;
+               #interrupt-cells = <2>;
+       };
+
+       gpx2: gpx2 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       gpx3: gpx3 {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       sd0_clk: sd0-clk {
+               samsung,pins = "gpk0-0";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd0_cmd: sd0-cmd {
+               samsung,pins = "gpk0-1";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd0_cd: sd0-cd {
+               samsung,pins = "gpk0-2";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd0_rdqs: sd0-rdqs {
+               samsung,pins = "gpk0-7";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd0_bus1: sd0-bus-width1 {
+               samsung,pins = "gpk0-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd0_bus4: sd0-bus-width4 {
+               samsung,pins = "gpk0-4", "gpk0-5", "gpk0-6";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd0_bus8: sd0-bus-width8 {
+               samsung,pins = "gpl0-0", "gpl0-1", "gpl0-2", "gpl0-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd1_clk: sd1-clk {
+               samsung,pins = "gpk1-0";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd1_cmd: sd1-cmd {
+               samsung,pins = "gpk1-1";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd1_cd: sd1-cd {
+               samsung,pins = "gpk1-2";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd1_bus1: sd1-bus-width1 {
+               samsung,pins = "gpk1-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd1_bus4: sd1-bus-width4 {
+               samsung,pins = "gpk1-4", "gpk1-5", "gpk1-6";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd2_clk: sd2-clk {
+               samsung,pins = "gpk2-0";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <4>;
+       };
+
+       sd2_cmd: sd2-cmd {
+               samsung,pins = "gpk2-1";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <4>;
+       };
+
+       sd2_cd: sd2-cd {
+               samsung,pins = "gpk2-2";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <3>;
+       };
+
+       sd2_bus1: sd2-bus-width1 {
+               samsung,pins = "gpk2-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <4>;
+       };
+
+       sd2_bus4: sd2-bus-width4 {
+               samsung,pins = "gpk2-4", "gpk2-5", "gpk2-6";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <4>;
+       };
+
+       cam_port_b_io: cam-port-b-io {
+               samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3",
+                               "gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7",
+                               "gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       cam_port_b_clk_active: cam-port-b-clk-active {
+               samsung,pins = "gpm2-2";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <3>;
+       };
+
+       cam_port_b_clk_idle: cam-port-b-clk-idle {
+               samsung,pins = "gpm2-2";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       fimc_is_i2c0: fimc-is-i2c0 {
+               samsung,pins = "gpm4-0", "gpm4-1";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       fimc_is_i2c1: fimc-is-i2c1 {
+               samsung,pins = "gpm4-2", "gpm4-3";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       fimc_is_uart: fimc-is-uart {
+               samsung,pins = "gpm3-5", "gpm3-7";
+               samsung,pin-function = <3>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+};
+
+&pinctrl_2 {
+       gpz: gpz {
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       i2s0_bus: i2s0-bus {
+               samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+                               "gpz-4", "gpz-5", "gpz-6";
+               samsung,pin-function = <2>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+};
diff --git a/arch/arm/boot/dts/exynos4415.dtsi b/arch/arm/boot/dts/exynos4415.dtsi
new file mode 100644 (file)
index 0000000..c1c9b37
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+ * Samsung's Exynos4415 SoC device tree source
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Samsung's Exynos4415 SoC device nodes are listed in this file. Exynos4415
+ * based board files can include this file and provide values for board
+ * specific bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4415 SoC. As device tree coverage for Exynos4415 increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can 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 "skeleton.dtsi"
+#include <dt-bindings/clock/exynos4415.h>
+#include <dt-bindings/clock/exynos-audss-clk.h>
+
+/ {
+       compatible = "samsung,exynos4415";
+       interrupt-parent = <&gic>;
+
+       aliases {
+               pinctrl0 = &pinctrl_0;
+               pinctrl1 = &pinctrl_1;
+               pinctrl2 = &pinctrl_2;
+               mshc0 = &mshc_0;
+               mshc1 = &mshc_1;
+               mshc2 = &mshc_2;
+               spi0 = &spi_0;
+               spi1 = &spi_1;
+               spi2 = &spi_2;
+               i2c0 = &i2c_0;
+               i2c1 = &i2c_1;
+               i2c2 = &i2c_2;
+               i2c3 = &i2c_3;
+               i2c4 = &i2c_4;
+               i2c5 = &i2c_5;
+               i2c6 = &i2c_6;
+               i2c7 = &i2c_7;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@a00 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xa00>;
+                       clock-frequency = <1600000000>;
+               };
+
+               cpu1: cpu@a01 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xa01>;
+                       clock-frequency = <1600000000>;
+               };
+
+               cpu2: cpu@a02 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xa02>;
+                       clock-frequency = <1600000000>;
+               };
+
+               cpu3: cpu@a03 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0xa03>;
+                       clock-frequency = <1600000000>;
+               };
+       };
+
+       soc: soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               sysram@02020000 {
+                       compatible = "mmio-sram";
+                       reg = <0x02020000 0x50000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x02020000 0x50000>;
+
+                       smp-sysram@0 {
+                               compatible = "samsung,exynos4210-sysram";
+                               reg = <0x0 0x1000>;
+                       };
+
+                       smp-sysram@4f000 {
+                               compatible = "samsung,exynos4210-sysram-ns";
+                               reg = <0x4f000 0x1000>;
+                       };
+               };
+
+               pinctrl_2: pinctrl@03860000 {
+                       compatible = "samsung,exynos4415-pinctrl";
+                       reg = <0x03860000 0x1000>;
+                       interrupts = <0 242 0>;
+               };
+
+               chipid@10000000 {
+                       compatible = "samsung,exynos4210-chipid";
+                       reg = <0x10000000 0x100>;
+               };
+
+               sysreg_system_controller: syscon@10010000 {
+                       compatible = "samsung,exynos4-sysreg", "syscon";
+                       reg = <0x10010000 0x400>;
+               };
+
+               pmu_system_controller: system-controller@10020000 {
+                       compatible = "samsung,exynos4415-pmu", "syscon";
+                       reg = <0x10020000 0x4000>;
+               };
+
+               mipi_phy: video-phy@10020710 {
+                       compatible = "samsung,s5pv210-mipi-video-phy";
+                       reg = <0x10020710 8>;
+                       #phy-cells = <1>;
+               };
+
+               pd_cam: cam-power-domain@10024000 {
+                       compatible = "samsung,exynos4210-pd";
+                       reg = <0x10024000 0x20>;
+               };
+
+               pd_tv: tv-power-domain@10024020 {
+                       compatible = "samsung,exynos4210-pd";
+                       reg = <0x10024020 0x20>;
+               };
+
+               pd_mfc: mfc-power-domain@10024040 {
+                       compatible = "samsung,exynos4210-pd";
+                       reg = <0x10024040 0x20>;
+               };
+
+               pd_g3d: g3d-power-domain@10024060 {
+                       compatible = "samsung,exynos4210-pd";
+                       reg = <0x10024060 0x20>;
+               };
+
+               pd_lcd0: lcd0-power-domain@10024080 {
+                       compatible = "samsung,exynos4210-pd";
+                       reg = <0x10024080 0x20>;
+               };
+
+               pd_isp0: isp0-power-domain@100240A0 {
+                       compatible = "samsung,exynos4210-pd";
+                       reg = <0x100240A0 0x20>;
+               };
+
+               pd_isp1: isp1-power-domain@100240E0 {
+                       compatible = "samsung,exynos4210-pd";
+                       reg = <0x100240E0 0x20>;
+               };
+
+               cmu: clock-controller@10030000 {
+                       compatible = "samsung,exynos4415-cmu";
+                       reg = <0x10030000 0x18000>;
+                       #clock-cells = <1>;
+               };
+
+               rtc: rtc@10070000 {
+                       compatible = "samsung,exynos3250-rtc";
+                       reg = <0x10070000 0x100>;
+                       interrupts = <0 73 0>, <0 74 0>;
+                       status = "disabled";
+               };
+
+               mct@10050000 {
+                       compatible = "samsung,exynos4210-mct";
+                       reg = <0x10050000 0x800>;
+                       interrupts = <0 218 0>, <0 219 0>, <0 220 0>, <0 221 0>,
+                                    <0 223 0>, <0 226 0>, <0 227 0>, <0 228 0>;
+                       clocks = <&cmu CLK_FIN_PLL>, <&cmu CLK_MCT>;
+                       clock-names = "fin_pll", "mct";
+               };
+
+               gic: interrupt-controller@10481000 {
+                       compatible = "arm,cortex-a9-gic";
+                       #interrupt-cells = <3>;
+                       interrupt-controller;
+                       reg = <0x10481000 0x1000>,
+                             <0x10482000 0x1000>,
+                             <0x10484000 0x2000>,
+                             <0x10486000 0x2000>;
+                       interrupts = <1 9 0xf04>;
+               };
+
+               l2c: l2-cache-controller@10502000 {
+                       compatible = "arm,pl310-cache";
+                       reg = <0x10502000 0x1000>;
+                       cache-unified;
+                       cache-level = <2>;
+                       arm,tag-latency = <2 2 1>;
+                       arm,data-latency = <3 2 1>;
+                       arm,double-linefill = <1>;
+                       arm,double-linefill-incr = <0>;
+                       arm,double-linefill-wrap = <1>;
+                       arm,prefetch-drop = <1>;
+                       arm,prefetch-offset = <7>;
+               };
+
+               cmu_dmc: clock-controller@105C0000 {
+                       compatible = "samsung,exynos4415-cmu-dmc";
+                       reg = <0x105C0000 0x3000>;
+                       #clock-cells = <1>;
+               };
+
+               pinctrl_1: pinctrl@11000000 {
+                       compatible = "samsung,exynos4415-pinctrl";
+                       reg = <0x11000000 0x1000>;
+                       interrupts = <0 225 0>;
+
+                       wakeup-interrupt-controller {
+                               compatible = "samsung,exynos4210-wakeup-eint";
+                               interrupt-parent = <&gic>;
+                               interrupts = <0 48 0>;
+                       };
+               };
+
+               pinctrl_0: pinctrl@11400000 {
+                       compatible = "samsung,exynos4415-pinctrl";
+                       reg = <0x11400000 0x1000>;
+                       interrupts = <0 240 0>;
+               };
+
+               hsotg: hsotg@12480000 {
+                       compatible = "samsung,s3c6400-hsotg";
+                       reg = <0x12480000 0x20000>;
+                       interrupts = <0 141 0>;
+                       clocks = <&cmu CLK_USBDEVICE>;
+                       clock-names = "otg";
+                       phys = <&exynos_usbphy 0>;
+                       phy-names = "usb2-phy";
+                       status = "disabled";
+               };
+
+               mshc_0: mshc@12510000 {
+                       compatible = "samsung,exynos5250-dw-mshc";
+                       reg = <0x12510000 0x1000>;
+                       interrupts = <0 142 0>;
+                       clocks = <&cmu CLK_SDMMC0>, <&cmu CLK_SCLK_MMC0>;
+                       clock-names = "biu", "ciu";
+                       fifo-depth = <0x80>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               mshc_1: mshc@12520000 {
+                       compatible = "samsung,exynos5250-dw-mshc";
+                       reg = <0x12520000 0x1000>;
+                       interrupts = <0 143 0>;
+                       clocks = <&cmu CLK_SDMMC1>, <&cmu CLK_SCLK_MMC1>;
+                       clock-names = "biu", "ciu";
+                       fifo-depth = <0x80>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               mshc_2: mshc@12530000 {
+                       compatible = "samsung,exynos5250-dw-mshc";
+                       reg = <0x12530000 0x1000>;
+                       interrupts = <0 144 0>;
+                       clocks = <&cmu CLK_SDMMC2>, <&cmu CLK_SCLK_MMC2>;
+                       clock-names = "biu", "ciu";
+                       fifo-depth = <0x80>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               ehci: ehci@12580000 {
+                       compatible = "samsung,exynos4210-ehci";
+                       reg = <0x12580000 0x100>;
+                       interrupts = <0 140 0>;
+                       clocks = <&cmu CLK_USBHOST>;
+                       clock-names = "usbhost";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       port@0 {
+                               reg = <0>;
+                               phys = <&exynos_usbphy 1>;
+                               status = "disabled";
+                       };
+                       port@1 {
+                               reg = <1>;
+                               phys = <&exynos_usbphy 2>;
+                               status = "disabled";
+                       };
+                       port@2 {
+                               reg = <2>;
+                               phys = <&exynos_usbphy 3>;
+                               status = "disabled";
+                       };
+               };
+
+               ohci: ohci@12590000 {
+                       compatible = "samsung,exynos4210-ohci";
+                       reg = <0x12590000 0x100>;
+                       interrupts = <0 140 0>;
+                       clocks = <&cmu CLK_USBHOST>;
+                       clock-names = "usbhost";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       port@0 {
+                               reg = <0>;
+                               phys = <&exynos_usbphy 1>;
+                               status = "disabled";
+                       };
+               };
+
+               exynos_usbphy: exynos-usbphy@125B0000 {
+                       compatible = "samsung,exynos4x12-usb2-phy";
+                       reg = <0x125B0000 0x100>;
+                       samsung,pmureg-phandle = <&pmu_system_controller>;
+                       samsung,sysreg-phandle = <&sysreg_system_controller>;
+                       clocks = <&cmu CLK_USBDEVICE>, <&xusbxti>;
+                       clock-names = "phy", "ref";
+                       #phy-cells = <1>;
+                       status = "disabled";
+               };
+
+               amba {
+                       compatible = "arm,amba-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       interrupt-parent = <&gic>;
+                       ranges;
+
+                       pdma0: pdma@12680000 {
+                               compatible = "arm,pl330", "arm,primecell";
+                               reg = <0x12680000 0x1000>;
+                               interrupts = <0 138 0>;
+                               clocks = <&cmu CLK_PDMA0>;
+                               clock-names = "apb_pclk";
+                               #dma-cells = <1>;
+                               #dma-channels = <8>;
+                               #dma-requests = <32>;
+                       };
+
+                       pdma1: pdma@12690000 {
+                               compatible = "arm,pl330", "arm,primecell";
+                               reg = <0x12690000 0x1000>;
+                               interrupts = <0 139 0>;
+                               clocks = <&cmu CLK_PDMA1>;
+                               clock-names = "apb_pclk";
+                               #dma-cells = <1>;
+                               #dma-channels = <8>;
+                               #dma-requests = <32>;
+                       };
+               };
+
+               adc: adc@126C0000 {
+                       compatible = "samsung,exynos3250-adc",
+                                    "samsung,exynos-adc-v2";
+                       reg = <0x126C0000 0x100>, <0x10020718 0x4>;
+                       interrupts = <0 137 0>;
+                       clock-names = "adc", "sclk";
+                       clocks = <&cmu CLK_TSADC>, <&cmu CLK_SCLK_TSADC>;
+                       #io-channel-cells = <1>;
+                       io-channel-ranges;
+                       status = "disabled";
+               };
+
+               serial_0: serial@13800000 {
+                       compatible = "samsung,exynos4210-uart";
+                       reg = <0x13800000 0x100>;
+                       interrupts = <0 109 0>;
+                       clocks = <&cmu CLK_UART0>, <&cmu CLK_SCLK_UART0>;
+                       clock-names = "uart", "clk_uart_baud0";
+                       status = "disabled";
+               };
+
+               serial_1: serial@13810000 {
+                       compatible = "samsung,exynos4210-uart";
+                       reg = <0x13810000 0x100>;
+                       interrupts = <0 110 0>;
+                       clocks = <&cmu CLK_UART1>, <&cmu CLK_SCLK_UART1>;
+                       clock-names = "uart", "clk_uart_baud0";
+                       status = "disabled";
+               };
+
+               serial_2: serial@13820000 {
+                       compatible = "samsung,exynos4210-uart";
+                       reg = <0x13820000 0x100>;
+                       interrupts = <0 111 0>;
+                       clocks = <&cmu CLK_UART2>, <&cmu CLK_SCLK_UART2>;
+                       clock-names = "uart", "clk_uart_baud0";
+                       status = "disabled";
+               };
+
+               serial_3: serial@13830000 {
+                       compatible = "samsung,exynos4210-uart";
+                       reg = <0x13830000 0x100>;
+                       interrupts = <0 112 0>;
+                       clocks = <&cmu CLK_UART3>, <&cmu CLK_SCLK_UART3>;
+                       clock-names = "uart", "clk_uart_baud0";
+                       status = "disabled";
+               };
+
+               i2c_0: i2c@13860000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x13860000 0x100>;
+                       interrupts = <0 113 0>;
+                       clocks = <&cmu CLK_I2C0>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c0_bus>;
+                       status = "disabled";
+               };
+
+               i2c_1: i2c@13870000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x13870000 0x100>;
+                       interrupts = <0 114 0>;
+                       clocks = <&cmu CLK_I2C1>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c1_bus>;
+                       status = "disabled";
+               };
+
+               i2c_2: i2c@13880000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x13880000 0x100>;
+                       interrupts = <0 115 0>;
+                       clocks = <&cmu CLK_I2C2>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c2_bus>;
+                       status = "disabled";
+               };
+
+               i2c_3: i2c@13890000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x13890000 0x100>;
+                       interrupts = <0 116 0>;
+                       clocks = <&cmu CLK_I2C3>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c3_bus>;
+                       status = "disabled";
+               };
+
+               i2c_4: i2c@138A0000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x138A0000 0x100>;
+                       interrupts = <0 117 0>;
+                       clocks = <&cmu CLK_I2C4>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c4_bus>;
+                       status = "disabled";
+               };
+
+               i2c_5: i2c@138B0000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x138B0000 0x100>;
+                       interrupts = <0 118 0>;
+                       clocks = <&cmu CLK_I2C5>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c5_bus>;
+                       status = "disabled";
+               };
+
+               i2c_6: i2c@138C0000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x138C0000 0x100>;
+                       interrupts = <0 119 0>;
+                       clocks = <&cmu CLK_I2C6>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c6_bus>;
+                       status = "disabled";
+               };
+
+               i2c_7: i2c@138D0000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "samsung,s3c2440-i2c";
+                       reg = <0x138D0000 0x100>;
+                       interrupts = <0 120 0>;
+                       clocks = <&cmu CLK_I2C7>;
+                       clock-names = "i2c";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c7_bus>;
+                       status = "disabled";
+               };
+
+               spi_0: spi@13920000 {
+                       compatible = "samsung,exynos4210-spi";
+                       reg = <0x13920000 0x100>;
+                       interrupts = <0 121 0>;
+                       dmas = <&pdma0 7>, <&pdma0 6>;
+                       dma-names = "tx", "rx";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       clocks = <&cmu CLK_SPI0>, <&cmu CLK_SCLK_SPI0>;
+                       clock-names = "spi", "spi_busclk0";
+                       samsung,spi-src-clk = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&spi0_bus>;
+                       status = "disabled";
+               };
+
+               spi_1: spi@13930000 {
+                       compatible = "samsung,exynos4210-spi";
+                       reg = <0x13930000 0x100>;
+                       interrupts = <0 122 0>;
+                       dmas = <&pdma1 7>, <&pdma1 6>;
+                       dma-names = "tx", "rx";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       clocks = <&cmu CLK_SPI1>, <&cmu CLK_SCLK_SPI1>;
+                       clock-names = "spi", "spi_busclk0";
+                       samsung,spi-src-clk = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&spi1_bus>;
+                       status = "disabled";
+               };
+
+               spi_2: spi@13940000 {
+                       compatible = "samsung,exynos4210-spi";
+                       reg = <0x13940000 0x100>;
+                       interrupts = <0 123 0>;
+                       dmas = <&pdma0 9>, <&pdma0 8>;
+                       dma-names = "tx", "rx";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       clocks = <&cmu CLK_SPI2>, <&cmu CLK_SCLK_SPI2>;
+                       clock-names = "spi", "spi_busclk0";
+                       samsung,spi-src-clk = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&spi2_bus>;
+                       status = "disabled";
+               };
+
+               clock_audss: clock-controller@03810000 {
+                       compatible = "samsung,exynos4210-audss-clock";
+                       reg = <0x03810000 0x0C>;
+                       #clock-cells = <1>;
+               };
+
+               i2s0: i2s@3830000 {
+                       compatible = "samsung,s5pv210-i2s";
+                       reg = <0x03830000 0x100>;
+                       interrupts = <0 124 0>;
+                       clocks = <&clock_audss EXYNOS_I2S_BUS>,
+                               <&clock_audss EXYNOS_SCLK_I2S>;
+                       clock-names = "iis", "i2s_opclk0";
+                       dmas = <&pdma1 10>, <&pdma1 9>, <&pdma1 8>;
+                       dma-names = "tx", "rx", "tx-sec";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2s0_bus>;
+                       samsung,idma-addr = <0x03000000>;
+                       status = "disabled";
+               };
+
+               pwm: pwm@139D0000 {
+                       compatible = "samsung,exynos4210-pwm";
+                       reg = <0x139D0000 0x1000>;
+                       interrupts = <0 104 0>, <0 105 0>, <0 106 0>,
+                                    <0 107 0>, <0 108 0>;
+                       #pwm-cells = <3>;
+                       status = "disabled";
+               };
+
+               pmu {
+                       compatible = "arm,cortex-a9-pmu";
+                       interrupts = <0 18 0>, <0 19 0>, <0 20 0>, <0 21 0>;
+               };
+       };
+};
+
+#include "exynos4415-pinctrl.dtsi"
index 0865a2e33f970d32e740de3a80b7481cc8764c5d..c141931378e78aa17a3f45da0293d218713587a0 100644 (file)
  * published by the Free Software Foundation.
 */
 
+#define PIN_PULL_NONE          0
+#define PIN_PULL_DOWN          1
+#define PIN_PULL_UP            3
+
+#define PIN_PDN_OUT0           0
+#define PIN_PDN_OUT1           1
+#define PIN_PDN_INPUT          2
+#define PIN_PDN_PREV           3
+
+#define PIN_SLP(_pin, _mode, _pull)                            \
+       _pin {                                                  \
+               samsung,pins = #_pin;                           \
+               samsung,pin-con-pdn = <PIN_PDN_ ##_mode>;       \
+               samsung,pin-pud-pdn = <PIN_PULL_ ##_pull>;      \
+       }
+
 / {
        pinctrl@11400000 {
                gpa0: gpa0 {
index 861bb919f6d391ea44f097565eb0d36781d1a20a..2e9f1f7be77b10b43d5e88b656870c252209fb0b 100644 (file)
                compatible = "samsung,exynos4x12-usb2-phy";
                samsung,sysreg-phandle = <&sys_reg>;
        };
+
+       tmu@100C0000 {
+               compatible = "samsung,exynos4412-tmu";
+               interrupt-parent = <&combiner>;
+               interrupts = <2 4>;
+               reg = <0x100C0000 0x100>;
+               clocks = <&clock 383>;
+               clock-names = "tmu_apbif";
+               status = "disabled";
+       };
 };
index 3acd97eb6630f2b78fdfad4e4f4fb45e95f0fc0f..7e728a1b55590abe15e89d109ad0433a86785f17 100644 (file)
@@ -7,12 +7,13 @@
  * This program is free software; you can 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 "exynos5250.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/input/input.h>
+#include "exynos5250.dtsi"
 
 / {
        model = "Insignal Arndale evaluation board based on EXYNOS5250";
                bootargs = "console=ttySAC2,115200";
        };
 
-       rtc@101E0000 {
-               status = "okay";
-       };
-
-       codec@11000000 {
-               samsung,mfc-r = <0x43000000 0x800000>;
-               samsung,mfc-l = <0x51000000 0x800000>;
-       };
-
-       i2c@12C60000 {
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <20000>;
-               samsung,i2c-slave-addr = <0x66>;
-               status = "okay";
-
-               s5m8767_pmic@66 {
-                       compatible = "samsung,s5m8767-pmic";
-                       reg = <0x66>;
-                       interrupt-parent = <&gpx3>;
-                       interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
-
-                       vinb1-supply = <&main_dc_reg>;
-                       vinb2-supply = <&main_dc_reg>;
-                       vinb3-supply = <&main_dc_reg>;
-                       vinb4-supply = <&main_dc_reg>;
-                       vinb5-supply = <&main_dc_reg>;
-                       vinb6-supply = <&main_dc_reg>;
-                       vinb7-supply = <&main_dc_reg>;
-                       vinb8-supply = <&main_dc_reg>;
-                       vinb9-supply = <&main_dc_reg>;
-
-                       vinl1-supply = <&buck7_reg>;
-                       vinl2-supply = <&buck7_reg>;
-                       vinl3-supply = <&buck7_reg>;
-                       vinl4-supply = <&main_dc_reg>;
-                       vinl5-supply = <&main_dc_reg>;
-                       vinl6-supply = <&main_dc_reg>;
-                       vinl7-supply = <&main_dc_reg>;
-                       vinl8-supply = <&buck8_reg>;
-                       vinl9-supply = <&buck8_reg>;
-
-                       s5m8767,pmic-buck2-dvs-voltage = <1300000>;
-                       s5m8767,pmic-buck3-dvs-voltage = <1100000>;
-                       s5m8767,pmic-buck4-dvs-voltage = <1200000>;
-                       s5m8767,pmic-buck-dvs-gpios = <&gpd1 0 0>,
-                                                       <&gpd1 1 0>,
-                                                       <&gpd1 2 0>;
-                       s5m8767,pmic-buck-ds-gpios = <&gpx2 3 0>,
-                                                       <&gpx2 4 0>,
-                                                       <&gpx2 5 0>;
-                       regulators {
-                               ldo1_reg: LDO1 {
-                                       regulator-name = "VDD_ALIVE_1.0V";
-                                       regulator-min-microvolt = <1100000>;
-                                       regulator-max-microvolt = <1100000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo2_reg: LDO2 {
-                                       regulator-name = "VDD_28IO_DP_1.35V";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo3_reg: LDO3 {
-                                       regulator-name = "VDD_COMMON1_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo4_reg: LDO4 {
-                                       regulator-name = "VDD_IOPERI_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo5_reg: LDO5 {
-                                       regulator-name = "VDD_EXT_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo6_reg: LDO6 {
-                                       regulator-name = "VDD_MPLL_1.1V";
-                                       regulator-min-microvolt = <1100000>;
-                                       regulator-max-microvolt = <1100000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo7_reg: LDO7 {
-                                       regulator-name = "VDD_XPLL_1.1V";
-                                       regulator-min-microvolt = <1100000>;
-                                       regulator-max-microvolt = <1100000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo8_reg: LDO8 {
-                                       regulator-name = "VDD_COMMON2_1.0V";
-                                       regulator-min-microvolt = <1000000>;
-                                       regulator-max-microvolt = <1000000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo9_reg: LDO9 {
-                                       regulator-name = "VDD_33ON_3.0V";
-                                       regulator-min-microvolt = <3000000>;
-                                       regulator-max-microvolt = <3000000>;
-                                       op_mode = <1>;
-                               };
-
-                               ldo10_reg: LDO10 {
-                                       regulator-name = "VDD_COMMON3_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo11_reg: LDO11 {
-                                       regulator-name = "VDD_ABB2_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo12_reg: LDO12 {
-                                       regulator-name = "VDD_USB_3.0V";
-                                       regulator-min-microvolt = <3000000>;
-                                       regulator-max-microvolt = <3000000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo13_reg: LDO13 {
-                                       regulator-name = "VDDQ_C2C_W_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo14_reg: LDO14 {
-                                       regulator-name = "VDD18_ABB0_3_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo15_reg: LDO15 {
-                                       regulator-name = "VDD10_COMMON4_1.0V";
-                                       regulator-min-microvolt = <1000000>;
-                                       regulator-max-microvolt = <1000000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo16_reg: LDO16 {
-                                       regulator-name = "VDD18_HSIC_1.8V";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo17_reg: LDO17 {
-                                       regulator-name = "VDDQ_MMC2_3_2.8V";
-                                       regulator-min-microvolt = <2800000>;
-                                       regulator-max-microvolt = <2800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               ldo18_reg: LDO18 {
-                                       regulator-name = "VDD_33ON_2.8V";
-                                       regulator-min-microvolt = <2800000>;
-                                       regulator-max-microvolt = <2800000>;
-                                       op_mode = <1>;
-                               };
-
-                               ldo22_reg: LDO22 {
-                                       regulator-name = "EXT_33_OFF";
-                                       regulator-min-microvolt = <3300000>;
-                                       regulator-max-microvolt = <3300000>;
-                                       op_mode = <1>;
-                               };
-
-                               ldo23_reg: LDO23 {
-                                       regulator-name = "EXT_28_OFF";
-                                       regulator-min-microvolt = <2800000>;
-                                       regulator-max-microvolt = <2800000>;
-                                       op_mode = <1>;
-                               };
-
-                               ldo25_reg: LDO25 {
-                                       regulator-name = "PVDD_LDO25";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       op_mode = <1>;
-                               };
-
-                               ldo26_reg: LDO26 {
-                                       regulator-name = "EXT_18_OFF";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       op_mode = <1>;
-                               };
-
-                               buck1_reg: BUCK1 {
-                                       regulator-name = "vdd_mif";
-                                       regulator-min-microvolt = <950000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               buck2_reg: BUCK2 {
-                                       regulator-name = "vdd_arm";
-                                       regulator-min-microvolt = <912500>;
-                                       regulator-max-microvolt = <1300000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               buck3_reg: BUCK3 {
-                                       regulator-name = "vdd_int";
-                                       regulator-min-microvolt = <900000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               buck4_reg: BUCK4 {
-                                       regulator-name = "vdd_g3d";
-                                       regulator-min-microvolt = <1000000>;
-                                       regulator-max-microvolt = <1000000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               buck5_reg: BUCK5 {
-                                       regulator-name = "VDD_MEM_1.35V";
-                                       regulator-min-microvolt = <750000>;
-                                       regulator-max-microvolt = <1355000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       op_mode = <1>;
-                               };
-
-                               buck7_reg: BUCK7 {
-                                       regulator-name = "PVDD_BUCK7";
-                                       regulator-always-on;
-                                       op_mode = <1>;
-                               };
-
-                               buck8_reg: BUCK8 {
-                                       regulator-name = "PVDD_BUCK8";
-                                       regulator-always-on;
-                                       op_mode = <1>;
-                               };
-
-                               buck9_reg: BUCK9 {
-                                       regulator-name = "VDD_33_OFF_EXT1";
-                                       regulator-min-microvolt = <750000>;
-                                       regulator-max-microvolt = <3000000>;
-                                       op_mode = <1>;
-                               };
-                       };
-               };
-       };
-
-       i2c@12C80000 {
-               status = "okay";
-
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <66000>;
-               samsung,i2c-slave-addr = <0x50>;
-
-               hdmiddc@50 {
-                       compatible = "samsung,exynos4210-hdmiddc";
-                       reg = <0x50>;
-               };
-       };
-
-       i2c@12C90000 {
-               status = "okay";
-
-               wm1811a@1a {
-
-                       compatible = "wlf,wm1811";
-                       reg = <0x1a>;
-
-                       AVDD2-supply = <&main_dc_reg>;
-                       CPVDD-supply = <&main_dc_reg>;
-                       DBVDD1-supply = <&main_dc_reg>;
-                       DBVDD2-supply = <&main_dc_reg>;
-                       DBVDD3-supply = <&main_dc_reg>;
-                       LDO1VDD-supply = <&main_dc_reg>;
-                       SPKVDD1-supply = <&main_dc_reg>;
-                       SPKVDD2-supply = <&main_dc_reg>;
-
-                       wlf,ldo1ena = <&gpb0 0 0>;
-                       wlf,ldo2ena = <&gpb0 1 0>;
-               };
-       };
-
-       i2c@12CE0000 {
-               status = "okay";
-
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <66000>;
-               samsung,i2c-slave-addr = <0x38>;
-
-               hdmiphy@38 {
-                       compatible = "samsung,exynos4212-hdmiphy";
-                       reg = <0x38>;
-               };
-       };
-
-       i2c@121D0000 {
-               status = "okay";
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <40000>;
-               samsung,i2c-slave-addr = <0x38>;
-
-               sata_phy_i2c:sata-phy@38 {
-                       compatible = "samsung,exynos-sataphy-i2c";
-                       reg = <0x38>;
-               };
-       };
-
-       sata@122F0000 {
-               status = "okay";
-       };
-
-       sata-phy@12170000 {
-               status = "okay";
-               samsung,exynos-sataphy-i2c-phandle = <&sata_phy_i2c>;
-       };
-
-       mmc_0: mmc@12200000 {
-               status = "okay";
-               num-slots = <1>;
-               broken-cd;
-               card-detect-delay = <200>;
-               samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3>;
-               samsung,dw-mshc-ddr-timing = <1 2>;
-               vmmc-supply = <&mmc_reg>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
-               bus-width = <8>;
-               cap-mmc-highspeed;
-       };
-
-       mmc_2: mmc@12220000 {
-               status = "okay";
-               num-slots = <1>;
-               card-detect-delay = <200>;
-               samsung,dw-mshc-ciu-div = <3>;
-               samsung,dw-mshc-sdr-timing = <2 3>;
-               samsung,dw-mshc-ddr-timing = <1 2>;
-               vmmc-supply = <&mmc_reg>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
-               bus-width = <4>;
-               disable-wp;
-               cap-sd-highspeed;
-       };
-
-       i2s0: i2s@03830000 {
-               status = "okay";
-       };
-
        gpio_keys {
                compatible = "gpio-keys";
 
                menu {
                        label = "SW-TACT2";
-                       gpios = <&gpx1 4 1>;
+                       gpios = <&gpx1 4 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_MENU>;
                        gpio-key,wakeup;
                };
 
                home {
                        label = "SW-TACT3";
-                       gpios = <&gpx1 5 1>;
+                       gpios = <&gpx1 5 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_HOME>;
                        gpio-key,wakeup;
                };
 
                up {
                        label = "SW-TACT4";
-                       gpios = <&gpx1 6 1>;
+                       gpios = <&gpx1 6 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_UP>;
                        gpio-key,wakeup;
                };
 
                down {
                        label = "SW-TACT5";
-                       gpios = <&gpx1 7 1>;
+                       gpios = <&gpx1 7 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_DOWN>;
                        gpio-key,wakeup;
                };
 
                back {
                        label = "SW-TACT6";
-                       gpios = <&gpx2 0 1>;
+                       gpios = <&gpx2 0 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_BACK>;
                        gpio-key,wakeup;
                };
 
                wakeup {
                        label = "SW-TACT7";
-                       gpios = <&gpx2 1 1>;
+                       gpios = <&gpx2 1 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_WAKEUP>;
                        gpio-key,wakeup;
                };
        };
 
-       hdmi {
-               hpd-gpio = <&gpx3 7 2>;
-               vdd_osc-supply = <&ldo10_reg>;
-               vdd_pll-supply = <&ldo8_reg>;
-               vdd-supply = <&ldo8_reg>;
-       };
-
        regulators {
                compatible = "simple-bus";
                #address-cells = <1>;
                        regulator-name = "VDD_33ON_2.8V";
                        regulator-min-microvolt = <2800000>;
                        regulator-max-microvolt = <2800000>;
-                       gpio = <&gpx1 1 1>;
+                       gpio = <&gpx1 1 GPIO_ACTIVE_LOW>;
                        enable-active-high;
                };
 
                };
        };
 
-       dp-controller@145B0000 {
-               samsung,color-space = <0>;
-               samsung,dynamic-range = <0>;
-               samsung,ycbcr-coeff = <0>;
-               samsung,color-depth = <1>;
-               samsung,link-rate = <0x0a>;
-               samsung,lane-count = <4>;
-               status = "okay";
+       // SMSC USB3503 connected in hardware only mode as a PHY
+       usb_hub: usb-hub {
+               compatible = "smsc,usb3503a";
+
+               reset-gpios = <&gpx3 5 GPIO_ACTIVE_LOW>;
+               connect-gpios = <&gpd1 7 GPIO_ACTIVE_LOW>;
        };
+};
 
-       fimd: fimd@14400000 {
-               status = "okay";
-               display-timings {
-                       native-mode = <&timing0>;
-                       timing0: timing@0 {
-                               /* 2560x1600 DP panel */
-                               clock-frequency = <50000>;
-                               hactive = <2560>;
-                               vactive = <1600>;
-                               hfront-porch = <48>;
-                               hback-porch = <80>;
-                               hsync-len = <32>;
-                               vback-porch = <16>;
-                               vfront-porch = <8>;
-                               vsync-len = <6>;
-                       };
+&dp {
+       status = "okay";
+       samsung,color-space = <0>;
+       samsung,dynamic-range = <0>;
+       samsung,ycbcr-coeff = <0>;
+       samsung,color-depth = <1>;
+       samsung,link-rate = <0x0a>;
+       samsung,lane-count = <4>;
+};
+
+&fimd {
+       status = "okay";
+
+       display-timings {
+               native-mode = <&timing0>;
+
+               timing0: timing@0 {
+                       /* 2560x1600 DP panel */
+                       clock-frequency = <50000>;
+                       hactive = <2560>;
+                       vactive = <1600>;
+                       hfront-porch = <48>;
+                       hback-porch = <80>;
+                       hsync-len = <32>;
+                       vback-porch = <16>;
+                       vfront-porch = <8>;
+                       vsync-len = <6>;
                };
        };
+};
 
-       usb_hub_bus {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <0>;
+&hdmi {
+       hpd-gpio = <&gpx3 7 GPIO_ACTIVE_LOW>;
+       vdd_osc-supply = <&ldo10_reg>;
+       vdd_pll-supply = <&ldo8_reg>;
+       vdd-supply = <&ldo8_reg>;
+};
+
+&i2c_0 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <20000>;
+       samsung,i2c-slave-addr = <0x66>;
+
+       s5m8767_pmic@66 {
+               compatible = "samsung,s5m8767-pmic";
+               reg = <0x66>;
+               interrupt-parent = <&gpx3>;
+               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+               vinb1-supply = <&main_dc_reg>;
+               vinb2-supply = <&main_dc_reg>;
+               vinb3-supply = <&main_dc_reg>;
+               vinb4-supply = <&main_dc_reg>;
+               vinb5-supply = <&main_dc_reg>;
+               vinb6-supply = <&main_dc_reg>;
+               vinb7-supply = <&main_dc_reg>;
+               vinb8-supply = <&main_dc_reg>;
+               vinb9-supply = <&main_dc_reg>;
+
+               vinl1-supply = <&buck7_reg>;
+               vinl2-supply = <&buck7_reg>;
+               vinl3-supply = <&buck7_reg>;
+               vinl4-supply = <&main_dc_reg>;
+               vinl5-supply = <&main_dc_reg>;
+               vinl6-supply = <&main_dc_reg>;
+               vinl7-supply = <&main_dc_reg>;
+               vinl8-supply = <&buck8_reg>;
+               vinl9-supply = <&buck8_reg>;
+
+               s5m8767,pmic-buck2-dvs-voltage = <1300000>;
+               s5m8767,pmic-buck3-dvs-voltage = <1100000>;
+               s5m8767,pmic-buck4-dvs-voltage = <1200000>;
+               s5m8767,pmic-buck-dvs-gpios = <&gpd1 0 GPIO_ACTIVE_HIGH>,
+                                             <&gpd1 1 GPIO_ACTIVE_HIGH>,
+                                             <&gpd1 2 GPIO_ACTIVE_HIGH>;
+               s5m8767,pmic-buck-ds-gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>,
+                                            <&gpx2 4 GPIO_ACTIVE_HIGH>,
+                                            <&gpx2 5 GPIO_ACTIVE_HIGH>;
+
+               regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "VDD_ALIVE_1.0V";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
 
-               // SMSC USB3503 connected in hardware only mode as a PHY
-               usb_hub: usb_hub {
-                       compatible = "smsc,usb3503a";
+                       ldo2_reg: LDO2 {
+                               regulator-name = "VDD_28IO_DP_1.35V";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo3_reg: LDO3 {
+                               regulator-name = "VDD_COMMON1_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo4_reg: LDO4 {
+                               regulator-name = "VDD_IOPERI_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo5_reg: LDO5 {
+                               regulator-name = "VDD_EXT_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo6_reg: LDO6 {
+                               regulator-name = "VDD_MPLL_1.1V";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
 
-                       reset-gpios = <&gpx3 5 1>;
-                       connect-gpios = <&gpd1 7 1>;
+                       ldo7_reg: LDO7 {
+                               regulator-name = "VDD_XPLL_1.1V";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo8_reg: LDO8 {
+                               regulator-name = "VDD_COMMON2_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo9_reg: LDO9 {
+                               regulator-name = "VDD_33ON_3.0V";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               op_mode = <1>;
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "VDD_COMMON3_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo11_reg: LDO11 {
+                               regulator-name = "VDD_ABB2_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo12_reg: LDO12 {
+                               regulator-name = "VDD_USB_3.0V";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo13_reg: LDO13 {
+                               regulator-name = "VDDQ_C2C_W_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo14_reg: LDO14 {
+                               regulator-name = "VDD18_ABB0_3_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo15_reg: LDO15 {
+                               regulator-name = "VDD10_COMMON4_1.0V";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "VDD18_HSIC_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo17_reg: LDO17 {
+                               regulator-name = "VDDQ_MMC2_3_2.8V";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       ldo18_reg: LDO18 {
+                               regulator-name = "VDD_33ON_2.8V";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               op_mode = <1>;
+                       };
+
+                       ldo22_reg: LDO22 {
+                               regulator-name = "EXT_33_OFF";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               op_mode = <1>;
+                       };
+
+                       ldo23_reg: LDO23 {
+                               regulator-name = "EXT_28_OFF";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               op_mode = <1>;
+                       };
+
+                       ldo25_reg: LDO25 {
+                               regulator-name = "PVDD_LDO25";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               op_mode = <1>;
+                       };
+
+                       ldo26_reg: LDO26 {
+                               regulator-name = "EXT_18_OFF";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               op_mode = <1>;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "vdd_mif";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <912500>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "vdd_int";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "vdd_g3d";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "VDD_MEM_1.35V";
+                               regulator-min-microvolt = <750000>;
+                               regulator-max-microvolt = <1355000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       buck7_reg: BUCK7 {
+                               regulator-name = "PVDD_BUCK7";
+                               regulator-always-on;
+                               op_mode = <1>;
+                       };
+
+                       buck8_reg: BUCK8 {
+                               regulator-name = "PVDD_BUCK8";
+                               regulator-always-on;
+                               op_mode = <1>;
+                       };
+
+                       buck9_reg: BUCK9 {
+                               regulator-name = "VDD_33_OFF_EXT1";
+                               regulator-min-microvolt = <750000>;
+                               regulator-max-microvolt = <3000000>;
+                               op_mode = <1>;
+                       };
                };
        };
 };
+
+&i2c_2 {
+       status = "okay";
+
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+       samsung,i2c-slave-addr = <0x50>;
+
+       hdmiddc@50 {
+               compatible = "samsung,exynos4210-hdmiddc";
+               reg = <0x50>;
+       };
+};
+
+&i2c_3 {
+       status = "okay";
+
+       wm1811a@1a {
+               compatible = "wlf,wm1811";
+               reg = <0x1a>;
+
+               AVDD2-supply = <&main_dc_reg>;
+               CPVDD-supply = <&main_dc_reg>;
+               DBVDD1-supply = <&main_dc_reg>;
+               DBVDD2-supply = <&main_dc_reg>;
+               DBVDD3-supply = <&main_dc_reg>;
+               LDO1VDD-supply = <&main_dc_reg>;
+               SPKVDD1-supply = <&main_dc_reg>;
+               SPKVDD2-supply = <&main_dc_reg>;
+
+               wlf,ldo1ena = <&gpb0 0 GPIO_ACTIVE_HIGH>;
+               wlf,ldo2ena = <&gpb0 1 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+&i2c_8 {
+       status = "okay";
+
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+       samsung,i2c-slave-addr = <0x38>;
+
+       hdmiphy@38 {
+               compatible = "samsung,exynos4212-hdmiphy";
+               reg = <0x38>;
+       };
+};
+
+&i2c_9 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <40000>;
+       samsung,i2c-slave-addr = <0x38>;
+
+       sata_phy_i2c:sata-phy@38 {
+               compatible = "samsung,exynos-sataphy-i2c";
+               reg = <0x38>;
+       };
+};
+
+&i2s0 {
+       status = "okay";
+};
+
+&mfc {
+       samsung,mfc-r = <0x43000000 0x800000>;
+       samsung,mfc-l = <0x51000000 0x800000>;
+};
+
+&mmc_0 {
+       status = "okay";
+       num-slots = <1>;
+       broken-cd;
+       card-detect-delay = <200>;
+       samsung,dw-mshc-ciu-div = <3>;
+       samsung,dw-mshc-sdr-timing = <2 3>;
+       samsung,dw-mshc-ddr-timing = <1 2>;
+       vmmc-supply = <&mmc_reg>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+       bus-width = <8>;
+       cap-mmc-highspeed;
+};
+
+&mmc_2 {
+       status = "okay";
+       num-slots = <1>;
+       card-detect-delay = <200>;
+       samsung,dw-mshc-ciu-div = <3>;
+       samsung,dw-mshc-sdr-timing = <2 3>;
+       samsung,dw-mshc-ddr-timing = <1 2>;
+       vmmc-supply = <&mmc_reg>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+       bus-width = <4>;
+       disable-wp;
+       cap-sd-highspeed;
+};
+
+&rtc {
+       status = "okay";
+};
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+       samsung,exynos-sataphy-i2c-phandle = <&sata_phy_i2c>;
+};
index 6a0f4c0ff763f64c0846d539d74abd0d8fccd52e..bc27cc2558fe6518ad990b12a090fb8c7f008f5a 100644 (file)
@@ -7,9 +7,11 @@
  * This program is free software; you can 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/interrupt-controller/irq.h>
 #include "exynos5250.dtsi"
 
 / {
                bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
        };
 
-       rtc@101E0000 {
-               status = "okay";
-       };
-
-       i2c@12C60000 {
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <20000>;
-               status = "okay";
-
-               eeprom@50 {
-                       compatible = "samsung,s524ad0xd1";
-                       reg = <0x50>;
-               };
-
-               max77686@09 {
-                       compatible = "maxim,max77686";
-                       reg = <0x09>;
-                       interrupt-parent = <&gpx3>;
-                       interrupts = <2 0>;
-
-                       voltage-regulators {
-                               ldo1_reg: LDO1 {
-                                       regulator-name = "P1.0V_LDO_OUT1";
-                                       regulator-min-microvolt = <1000000>;
-                                       regulator-max-microvolt = <1000000>;
-                                       regulator-always-on;
-                               };
-
-                               ldo2_reg: LDO2 {
-                                       regulator-name = "P1.2V_LDO_OUT2";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       regulator-always-on;
-                               };
-
-                               ldo3_reg: LDO3 {
-                                       regulator-name = "P1.8V_LDO_OUT3";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                               };
-
-                               ldo4_reg: LDO4 {
-                                       regulator-name = "P2.8V_LDO_OUT4";
-                                       regulator-min-microvolt = <2800000>;
-                                       regulator-max-microvolt = <2800000>;
-                               };
-
-                               ldo5_reg: LDO5 {
-                                       regulator-name = "P1.8V_LDO_OUT5";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
-
-                               ldo6_reg: LDO6 {
-                                       regulator-name = "P1.1V_LDO_OUT6";
-                                       regulator-min-microvolt = <1100000>;
-                                       regulator-max-microvolt = <1100000>;
-                                       regulator-always-on;
-                               };
-
-                               ldo7_reg: LDO7 {
-                                       regulator-name = "P1.1V_LDO_OUT7";
-                                       regulator-min-microvolt = <1100000>;
-                                       regulator-max-microvolt = <1100000>;
-                                       regulator-always-on;
-                               };
-
-                               ldo8_reg: LDO8 {
-                                       regulator-name = "P1.0V_LDO_OUT8";
-                                       regulator-min-microvolt = <1000000>;
-                                       regulator-max-microvolt = <1000000>;
-                               };
-
-                               ldo10_reg: LDO10 {
-                                       regulator-name = "P1.8V_LDO_OUT10";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
-
-                               ldo11_reg: LDO11 {
-                                       regulator-name = "P1.8V_LDO_OUT11";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
-
-                               ldo12_reg: LDO12 {
-                                       regulator-name = "P3.0V_LDO_OUT12";
-                                       regulator-min-microvolt = <3000000>;
-                                       regulator-max-microvolt = <3000000>;
-                               };
-
-                               ldo13_reg: LDO13 {
-                                       regulator-name = "P1.8V_LDO_OUT13";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
-
-                               ldo14_reg: LDO14 {
-                                       regulator-name = "P1.8V_LDO_OUT14";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
-
-                               ldo15_reg: LDO15 {
-                                       regulator-name = "P1.0V_LDO_OUT15";
-                                       regulator-min-microvolt = <1000000>;
-                                       regulator-max-microvolt = <1000000>;
-                               };
-
-                               ldo16_reg: LDO16 {
-                                       regulator-name = "P1.8V_LDO_OUT16";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
-
-                               buck1_reg: BUCK1 {
-                                       regulator-name = "vdd_mif";
-                                       regulator-min-microvolt = <950000>;
-                                       regulator-max-microvolt = <1300000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                               };
-
-                               buck2_reg: BUCK2 {
-                                       regulator-name = "vdd_arm";
-                                       regulator-min-microvolt = <850000>;
-                                       regulator-max-microvolt = <1350000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                               };
-
-                               buck3_reg: BUCK3 {
-                                       regulator-name = "vdd_int";
-                                       regulator-min-microvolt = <900000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                               };
-
-                               buck4_reg: BUCK4 {
-                                       regulator-name = "vdd_g3d";
-                                       regulator-min-microvolt = <850000>;
-                                       regulator-max-microvolt = <1300000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                               };
-
-                               buck5_reg: BUCK5 {
-                                       regulator-name = "P1.8V_BUCK_OUT5";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                               };
-                       };
-               };
-       };
-
        vdd: fixed-regulator@0 {
                compatible = "regulator-fixed";
                regulator-name = "vdd-supply";
                regulator-always-on;
        };
 
-       i2c@12C70000 {
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <20000>;
-               status = "okay";
+       sound {
+               compatible = "samsung,smdk-wm8994";
 
-               eeprom@51 {
-                       compatible = "samsung,s524ad0xd1";
-                       reg = <0x51>;
+               samsung,i2s-controller = <&i2s0>;
+               samsung,audio-codec = <&wm8994>;
+       };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <24000000>;
                };
 
-               wm8994: wm8994@1a {
-                       compatible = "wlf,wm8994";
-                       reg = <0x1a>;
+               codec_mclk: codec-mclk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <16934000>;
+               };
+       };
+};
 
-                       gpio-controller;
-                       #gpio-cells = <2>;
+&dp {
+       samsung,color-space = <0>;
+       samsung,dynamic-range = <0>;
+       samsung,ycbcr-coeff = <0>;
+       samsung,color-depth = <1>;
+       samsung,link-rate = <0x0a>;
+       samsung,lane-count = <4>;
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&dp_hpd>;
+       status = "okay";
+};
 
-                       clocks = <&codec_mclk>;
-                       clock-names = "MCLK1";
+&ehci {
+       samsung,vbus-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
+};
 
-                       AVDD2-supply = <&vdd>;
-                       CPVDD-supply = <&vdd>;
-                       DBVDD-supply = <&dbvdd>;
-                       SPKVDD1-supply = <&spkvdd>;
-                       SPKVDD2-supply = <&spkvdd>;
+&fimd {
+       status = "okay";
+
+       display-timings {
+               native-mode = <&timing0>;
+
+               timing0: timing@0 {
+                       /* 1280x800 */
+                       clock-frequency = <50000>;
+                       hactive = <1280>;
+                       vactive = <800>;
+                       hfront-porch = <4>;
+                       hback-porch = <4>;
+                       hsync-len = <4>;
+                       vback-porch = <4>;
+                       vfront-porch = <4>;
+                       vsync-len = <4>;
                };
        };
+};
 
-       i2c@121D0000 {
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <40000>;
-               samsung,i2c-slave-addr = <0x38>;
-               status = "okay";
+&hdmi {
+       hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+};
 
-               sata_phy_i2c:sata-phy@38 {
-                       compatible = "samsung,exynos-sataphy-i2c";
-                       reg = <0x38>;
-               };
+&i2c_0 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <20000>;
+
+       eeprom@50 {
+               compatible = "samsung,s524ad0xd1";
+               reg = <0x50>;
        };
 
-       i2c@12C80000 {
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <66000>;
-               status = "okay";
+       max77686@09 {
+               compatible = "maxim,max77686";
+               reg = <0x09>;
+               interrupt-parent = <&gpx3>;
+               interrupts = <2 IRQ_TYPE_NONE>;
+
+               voltage-regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "P1.0V_LDO_OUT1";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
 
-               hdmiddc@50 {
-                       compatible = "samsung,exynos4210-hdmiddc";
-                       reg = <0x50>;
-               };
-       };
+                       ldo2_reg: LDO2 {
+                               regulator-name = "P1.2V_LDO_OUT2";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                       };
 
-       i2c@12CE0000 {
-               samsung,i2c-sda-delay = <100>;
-               samsung,i2c-max-bus-freq = <66000>;
-               status = "okay";
+                       ldo3_reg: LDO3 {
+                               regulator-name = "P1.8V_LDO_OUT3";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
 
-               hdmiphy@38 {
-                       compatible = "samsung,exynos4212-hdmiphy";
-                       reg = <0x38>;
-               };
-       };
+                       ldo4_reg: LDO4 {
+                               regulator-name = "P2.8V_LDO_OUT4";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                       };
 
-       sata@122F0000 {
-               status = "okay";
-       };
+                       ldo5_reg: LDO5 {
+                               regulator-name = "P1.8V_LDO_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
 
-       sata-phy@12170000 {
-               status = "okay";
-               samsung,exynos-sataphy-i2c-phandle = <&sata_phy_i2c>;
-       };
+                       ldo6_reg: LDO6 {
+                               regulator-name = "P1.1V_LDO_OUT6";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
 
-       mmc@12200000 {
-               status = "okay";
-               num-slots = <1>;
-               broken-cd;
-               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 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
-               bus-width = <8>;
-               cap-mmc-highspeed;
-       };
+                       ldo7_reg: LDO7 {
+                               regulator-name = "P1.1V_LDO_OUT7";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
 
-       mmc@12220000 {
-               status = "okay";
-               num-slots = <1>;
-               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 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
-               bus-width = <4>;
-               disable-wp;
-               cap-sd-highspeed;
-       };
+                       ldo8_reg: LDO8 {
+                               regulator-name = "P1.0V_LDO_OUT8";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "P1.8V_LDO_OUT10";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
 
-       spi_1: spi@12d30000 {
-               cs-gpios = <&gpa2 5 0>;
-               status = "okay";
+                       ldo11_reg: LDO11 {
+                               regulator-name = "P1.8V_LDO_OUT11";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
 
-               w25q80bw@0 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "w25x80";
-                       reg = <0>;
-                       spi-max-frequency = <1000000>;
+                       ldo12_reg: LDO12 {
+                               regulator-name = "P3.0V_LDO_OUT12";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
 
-                       controller-data {
-                               samsung,spi-feedback-delay = <0>;
+                       ldo13_reg: LDO13 {
+                               regulator-name = "P1.8V_LDO_OUT13";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
                        };
 
-                       partition@0 {
-                               label = "U-Boot";
-                               reg = <0x0 0x40000>;
-                               read-only;
+                       ldo14_reg: LDO14 {
+                               regulator-name = "P1.8V_LDO_OUT14";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
                        };
 
-                       partition@40000 {
-                               label = "Kernel";
-                               reg = <0x40000 0xc0000>;
+                       ldo15_reg: LDO15 {
+                               regulator-name = "P1.0V_LDO_OUT15";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "P1.8V_LDO_OUT16";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "vdd_mif";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "vdd_int";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "vdd_g3d";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "P1.8V_BUCK_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
                        };
                };
        };
+};
 
-       hdmi {
-               hpd-gpio = <&gpx3 7 0>;
-       };
+&i2c_1 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <20000>;
 
-       codec@11000000 {
-               samsung,mfc-r = <0x43000000 0x800000>;
-               samsung,mfc-l = <0x51000000 0x800000>;
+       eeprom@51 {
+               compatible = "samsung,s524ad0xd1";
+               reg = <0x51>;
        };
 
-       i2s0: i2s@03830000 {
-               status = "okay";
+       wm8994: wm8994@1a {
+               compatible = "wlf,wm8994";
+               reg = <0x1a>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               clocks = <&codec_mclk>;
+               clock-names = "MCLK1";
+
+               AVDD2-supply = <&vdd>;
+               CPVDD-supply = <&vdd>;
+               DBVDD-supply = <&dbvdd>;
+               SPKVDD1-supply = <&spkvdd>;
+               SPKVDD2-supply = <&spkvdd>;
        };
+};
 
-       sound {
-               compatible = "samsung,smdk-wm8994";
+&i2c_2 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
 
-               samsung,i2s-controller = <&i2s0>;
-               samsung,audio-codec = <&wm8994>;
+       hdmiddc@50 {
+               compatible = "samsung,exynos4210-hdmiddc";
+               reg = <0x50>;
        };
+};
+
+&i2c_8 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
 
-       usb@12110000 {
-               samsung,vbus-gpio = <&gpx2 6 0>;
+       hdmiphy@38 {
+               compatible = "samsung,exynos4212-hdmiphy";
+               reg = <0x38>;
        };
+};
+
+&i2c_9 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <40000>;
+       samsung,i2c-slave-addr = <0x38>;
 
-       dp-controller@145B0000 {
-               samsung,color-space = <0>;
-               samsung,dynamic-range = <0>;
-               samsung,ycbcr-coeff = <0>;
-               samsung,color-depth = <1>;
-               samsung,link-rate = <0x0a>;
-               samsung,lane-count = <4>;
-
-               pinctrl-names = "default";
-               pinctrl-0 = <&dp_hpd>;
-               status = "okay";
+       sata_phy_i2c: sata-phy@38 {
+               compatible = "samsung,exynos-sataphy-i2c";
+               reg = <0x38>;
        };
+};
 
-       fimd@14400000 {
-               status = "okay";
-               display-timings {
-                       native-mode = <&timing0>;
-                       timing0: timing@0 {
-                               /* 1280x800 */
-                               clock-frequency = <50000>;
-                               hactive = <1280>;
-                               vactive = <800>;
-                               hfront-porch = <4>;
-                               hback-porch = <4>;
-                               hsync-len = <4>;
-                               vback-porch = <4>;
-                               vfront-porch = <4>;
-                               vsync-len = <4>;
-                       };
+&i2s0 {
+       status = "okay";
+};
+
+&mfc {
+       samsung,mfc-r = <0x43000000 0x800000>;
+       samsung,mfc-l = <0x51000000 0x800000>;
+};
+
+&mmc_0 {
+       status = "okay";
+       num-slots = <1>;
+       broken-cd;
+       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 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+       bus-width = <8>;
+       cap-mmc-highspeed;
+};
+
+&mmc_2 {
+       status = "okay";
+       num-slots = <1>;
+       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 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+       bus-width = <4>;
+       disable-wp;
+       cap-sd-highspeed;
+};
+
+&rtc {
+       status = "okay";
+};
+
+&sata {
+       status = "okay";
+};
+
+&sata_phy {
+       status = "okay";
+       samsung,exynos-sataphy-i2c-phandle = <&sata_phy_i2c>;
+};
+
+&spi_1 {
+       status = "okay";
+       cs-gpios = <&gpa2 5 GPIO_ACTIVE_HIGH>;
+
+       w25q80bw@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "w25x80";
+               reg = <0>;
+               spi-max-frequency = <1000000>;
+
+               controller-data {
+                       samsung,spi-feedback-delay = <0>;
                };
-       };
 
-       fixed-rate-clocks {
-               xxti {
-                       compatible = "samsung,clock-xxti";
-                       clock-frequency = <24000000>;
+               partition@0 {
+                       label = "U-Boot";
+                       reg = <0x0 0x40000>;
+                       read-only;
                };
 
-               codec_mclk: codec-mclk {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <16934000>;
+               partition@40000 {
+                       label = "Kernel";
+                       reg = <0x40000 0xc0000>;
                };
        };
 };
index e51fcef884a43d629ab12132e549cc8a0b731405..effaf2af41bc007b4c284ddec8100ffe731a9ea7 100644 (file)
@@ -6,10 +6,13 @@
  * This program is free software; you can 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/clock/maxim,max77686.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/input/input.h>
 #include "exynos5250.dtsi"
 
 / {
        };
 
        chosen {
-       };
-
-       rtc@101E0000 {
-               status = "okay";
-       };
-
-       pinctrl@11400000 {
-               ec_irq: ec-irq {
-                       samsung,pins = "gpx1-6";
-                       samsung,pin-function = <0>;
-                       samsung,pin-pud = <0>;
-                       samsung,pin-drv = <0>;
-               };
-
-               sd3_clk: sd3-clk {
-                       samsung,pin-drv = <0>;
-               };
-
-               sd3_cmd: sd3-cmd {
-                       samsung,pin-pud = <3>;
-                       samsung,pin-drv = <0>;
-               };
-
-               sd3_bus4: sd3-bus-width4 {
-                       samsung,pin-drv = <0>;
-               };
-
-               max98095_en: max98095-en {
-                       samsung,pins = "gpx1-7";
-                       samsung,pin-function = <0>;
-                       samsung,pin-pud = <3>;
-                       samsung,pin-drv = <0>;
-               };
-
-               tps65090_irq: tps65090-irq {
-                       samsung,pins = "gpx2-6";
-                       samsung,pin-function = <0>;
-                       samsung,pin-pud = <0>;
-                       samsung,pin-drv = <0>;
-               };
-
-               usb3_vbus_en: usb3-vbus-en {
-                       samsung,pins = "gpx2-7";
-                       samsung,pin-function = <1>;
-                       samsung,pin-pud = <0>;
-                       samsung,pin-drv = <0>;
-               };
-
-               hdmi_hpd_irq: hdmi-hpd-irq {
-                       samsung,pins = "gpx3-7";
-                       samsung,pin-function = <0>;
-                       samsung,pin-pud = <1>;
-                       samsung,pin-drv = <0>;
-               };
-       };
-
-       pinctrl@13400000 {
-               arb_their_claim: arb-their-claim {
-                       samsung,pins = "gpe0-4";
-                       samsung,pin-function = <0>;
-                       samsung,pin-pud = <3>;
-                       samsung,pin-drv = <0>;
-               };
-
-               arb_our_claim: arb-our-claim {
-                       samsung,pins = "gpf0-3";
-                       samsung,pin-function = <1>;
-                       samsung,pin-pud = <0>;
-                       samsung,pin-drv = <0>;
-               };
+               bootargs = "console=tty1";
        };
 
        gpio-keys {
 
                power {
                        label = "Power";
-                       gpios = <&gpx1 3 1>;
-                       linux,code = <116>; /* KEY_POWER */
+                       gpios = <&gpx1 3 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
                        gpio-key,wakeup;
                };
 
                lid-switch {
                        label = "Lid";
-                       gpios = <&gpx3 5 1>;
+                       gpios = <&gpx3 5 GPIO_ACTIVE_LOW>;
                        linux,input-type = <5>; /* EV_SW */
                        linux,code = <0>; /* SW_LID */
                        debounce-interval = <1>;
 
                i2c-parent = <&{/i2c@12CA0000}>;
 
-               our-claim-gpio = <&gpf0 3 1>;
-               their-claim-gpios = <&gpe0 4 1>;
+               our-claim-gpio = <&gpf0 3 GPIO_ACTIVE_LOW>;
+               their-claim-gpios = <&gpe0 4 GPIO_ACTIVE_LOW>;
                slew-delay-us = <10>;
                wait-retry-us = <3000>;
                wait-free-us = <50000>;
                        cros_ec: embedded-controller {
                                compatible = "google,cros-ec-i2c";
                                reg = <0x1e>;
-                               interrupts = <6 0>;
+                               interrupts = <6 IRQ_TYPE_NONE>;
                                interrupt-parent = <&gpx1>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&ec_irq>;
        };
 
        i2c@12CD0000 {
-               max98095: codec@11 {
-                       compatible = "maxim,max98095";
-                       reg = <0x11>;
-                       pinctrl-0 = <&max98095_en>;
-                       pinctrl-names = "default";
-               };
-
                ptn3460: lvds-bridge@20 {
                        compatible = "nxp,ptn3460";
                        reg = <0x20>;
                };
        };
 
-       i2s0: i2s@03830000 {
-               status = "okay";
-       };
-
        sound {
                compatible = "google,snow-audio-max98095";
 
                regulator-name = "P5.0V_USB3CON";
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
-               gpio = <&gpx2 7 0>;
+               gpio = <&gpx2 7 GPIO_ACTIVE_HIGH>;
                pinctrl-names = "default";
                pinctrl-0 = <&usb3_vbus_en>;
                enable-active-high;
        };
 
-       phy@12100000 {
-               vbus-supply = <&usb3_vbus_reg>;
-       };
-
-       usb@12110000 {
-               samsung,vbus-gpio = <&gpx1 1 0>;
-       };
-
        fixed-rate-clocks {
                xxti {
                        compatible = "samsung,clock-xxti";
                };
        };
 
-       hdmi {
-               hpd-gpio = <&gpx3 7 0>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&hdmi_hpd_irq>;
-               phy = <&hdmiphy>;
-               ddc = <&i2c_2>;
-               hdmi-en-supply = <&tps65090_fet7>;
-               vdd-supply = <&ldo8_reg>;
-               vdd_osc-supply = <&ldo10_reg>;
-               vdd_pll-supply = <&ldo8_reg>;
-       };
-
        backlight: backlight {
                compatible = "pwm-backlight";
                pwms = <&pwm 0 1000000 0>;
                pinctrl-names = "default";
        };
 
-       fimd@14400000 {
-               status = "okay";
-               samsung,invert-vclk;
-       };
-
        panel: panel {
                compatible = "auo,b116xw03";
                power-supply = <&fet6>;
                backlight = <&backlight>;
        };
+};
 
-       dp-controller@145B0000 {
-               status = "okay";
-               pinctrl-names = "default";
-               pinctrl-0 = <&dp_hpd>;
-               samsung,color-space = <0>;
-               samsung,dynamic-range = <0>;
-               samsung,ycbcr-coeff = <0>;
-               samsung,color-depth = <1>;
-               samsung,link-rate = <0x0a>;
-               samsung,lane-count = <2>;
-               samsung,hpd-gpio = <&gpx0 7 0>;
-               bridge = <&ptn3460>;
-       };
+&dp {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&dp_hpd>;
+       samsung,color-space = <0>;
+       samsung,dynamic-range = <0>;
+       samsung,ycbcr-coeff = <0>;
+       samsung,color-depth = <1>;
+       samsung,link-rate = <0x0a>;
+       samsung,lane-count = <2>;
+       samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
+       bridge = <&ptn3460>;
+};
+
+&ehci {
+       samsung,vbus-gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>;
+};
+
+&fimd {
+       status = "okay";
+       samsung,invert-vclk;
+};
+
+&hdmi {
+       hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&hdmi_hpd_irq>;
+       phy = <&hdmiphy>;
+       ddc = <&i2c_2>;
+       hdmi-en-supply = <&tps65090_fet7>;
+       vdd-supply = <&ldo8_reg>;
+       vdd_osc-supply = <&ldo10_reg>;
+       vdd_pll-supply = <&ldo8_reg>;
 };
 
 &i2c_0 {
        samsung,i2c-sda-delay = <100>;
        samsung,i2c-max-bus-freq = <378000>;
 
-       max77686@09 {
+       max77686: max77686@09 {
                compatible = "maxim,max77686";
                interrupt-parent = <&gpx3>;
-               interrupts = <2 0>;
+               interrupts = <2 IRQ_TYPE_NONE>;
                pinctrl-names = "default";
                pinctrl-0 = <&max77686_irq>;
                wakeup-source;
        trackpad {
                reg = <0x67>;
                compatible = "cypress,cyapa";
-               interrupts = <2 0>;
+               interrupts = <2 IRQ_TYPE_NONE>;
                interrupt-parent = <&gpx1>;
                wakeup-source;
        };
        status = "okay";
        samsung,i2c-sda-delay = <100>;
        samsung,i2c-max-bus-freq = <66000>;
+
+       max98095: codec@11 {
+               compatible = "maxim,max98095";
+               reg = <0x11>;
+               pinctrl-0 = <&max98095_en>;
+               pinctrl-names = "default";
+       };
 };
 
 &i2c_8 {
        };
 };
 
+&i2s0 {
+       status = "okay";
+};
+
 &mmc_0 {
        status = "okay";
        num-slots = <1>;
        pinctrl-names = "default";
        pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
        bus-width = <4>;
-       wp-gpios = <&gpc2 1 0>;
+       wp-gpios = <&gpc2 1 GPIO_ACTIVE_HIGH>;
        cap-sd-highspeed;
 };
 
 };
 
 &pinctrl_0 {
+       ec_irq: ec-irq {
+               samsung,pins = "gpx1-6";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       max98095_en: max98095-en {
+               samsung,pins = "gpx1-7";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       tps65090_irq: tps65090-irq {
+               samsung,pins = "gpx2-6";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       usb3_vbus_en: usb3-vbus-en {
+               samsung,pins = "gpx2-7";
+               samsung,pin-function = <1>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
        max77686_irq: max77686-irq {
                samsung,pins = "gpx3-2";
                samsung,pin-function = <0>;
                samsung,pin-pud = <0>;
                samsung,pin-drv = <0>;
        };
+
+       hdmi_hpd_irq: hdmi-hpd-irq {
+               samsung,pins = "gpx3-7";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <1>;
+               samsung,pin-drv = <0>;
+       };
+};
+
+&pinctrl_1 {
+       arb_their_claim: arb-their-claim {
+               samsung,pins = "gpe0-4";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       arb_our_claim: arb-our-claim {
+               samsung,pins = "gpf0-3";
+               samsung,pin-function = <1>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+};
+
+&rtc {
+       status = "okay";
+       clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>;
+       clock-names = "rtc", "rtc_src";
+};
+
+&sd3_bus4 {
+       samsung,pin-drv = <0>;
+};
+
+&sd3_clk {
+       samsung,pin-drv = <0>;
+};
+
+&sd3_cmd {
+       samsung,pin-pud = <3>;
+       samsung,pin-drv = <0>;
 };
 
 &spi_1 {
        num-cs = <1>;
 };
 
+&usbdrd_dwc3 {
+       dr_mode = "host";
+};
+
+&usbdrd_phy {
+       vbus-supply = <&usb3_vbus_reg>;
+};
+
 #include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts
new file mode 100644 (file)
index 0000000..f027754
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * Google Spring board device tree source
+ *
+ * Copyright (c) 2013 Google, Inc
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can 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/interrupt-controller/irq.h>
+#include <dt-bindings/input/input.h>
+#include "exynos5250.dtsi"
+
+/ {
+       model = "Google Spring";
+       compatible = "google,spring", "samsung,exynos5250", "samsung,exynos5";
+
+       memory {
+               reg = <0x40000000 0x80000000>;
+       };
+
+       chosen {
+               bootargs = "console=tty1";
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&power_key_irq>, <&lid_irq>;
+
+               power {
+                       label = "Power";
+                       gpios = <&gpx1 3 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+                       gpio-key,wakeup;
+               };
+
+               lid-switch {
+                       label = "Lid";
+                       gpios = <&gpx3 5 GPIO_ACTIVE_LOW>;
+                       linux,input-type = <5>; /* EV_SW */
+                       linux,code = <0>; /* SW_LID */
+                       debounce-interval = <1>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       usb-hub {
+               compatible = "smsc,usb3503a";
+               reset-gpios = <&gpe1 0 GPIO_ACTIVE_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&hsic_reset>;
+       };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <24000000>;
+               };
+       };
+};
+
+&dp {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&dp_hpd_gpio>;
+       samsung,color-space = <0>;
+       samsung,dynamic-range = <0>;
+       samsung,ycbcr-coeff = <0>;
+       samsung,color-depth = <1>;
+       samsung,link-rate = <0x0a>;
+       samsung,lane-count = <1>;
+       samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
+};
+
+&ehci {
+       samsung,vbus-gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>;
+};
+
+&fimd {
+       status = "okay";
+       samsung,invert-vclk;
+};
+
+&hdmi {
+       hpd-gpio = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&hdmi_hpd_irq>;
+       phy = <&hdmiphy>;
+       ddc = <&i2c_2>;
+       hdmi-en-supply = <&ldo8_reg>;
+       vdd-supply = <&ldo8_reg>;
+       vdd_osc-supply = <&ldo10_reg>;
+       vdd_pll-supply = <&ldo8_reg>;
+};
+
+&i2c_0 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <378000>;
+
+       s5m8767-pmic@66 {
+               compatible = "samsung,s5m8767-pmic";
+               reg = <0x66>;
+               interrupt-parent = <&gpx3>;
+               interrupts = <2 IRQ_TYPE_NONE>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&s5m8767_irq &s5m8767_dvs &s5m8767_ds>;
+               wakeup-source;
+
+               s5m8767,pmic-buck-dvs-gpios = <&gpd1 0 GPIO_ACTIVE_LOW>, /* DVS1 */
+                                             <&gpd1 1 GPIO_ACTIVE_LOW>, /* DVS2 */
+                                             <&gpd1 2 GPIO_ACTIVE_LOW>; /* DVS3 */
+
+               s5m8767,pmic-buck-ds-gpios = <&gpx2 3 GPIO_ACTIVE_LOW>, /* SET1 */
+                                            <&gpx2 4 GPIO_ACTIVE_LOW>, /* SET2 */
+                                            <&gpx2 5 GPIO_ACTIVE_LOW>; /* SET3 */
+
+               /*
+                * The following arrays of DVS voltages are not used, since we are
+                * not using GPIOs to control PMIC bucks, but they must be defined
+                * to please the driver.
+                */
+               s5m8767,pmic-buck2-dvs-voltage = <1350000>, <1300000>,
+                                                <1250000>, <1200000>,
+                                                <1150000>, <1100000>,
+                                                <1000000>, <950000>;
+
+               s5m8767,pmic-buck3-dvs-voltage = <1100000>, <1100000>,
+                                                <1100000>, <1100000>,
+                                                <1000000>, <1000000>,
+                                                <1000000>, <1000000>;
+
+               s5m8767,pmic-buck4-dvs-voltage = <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>;
+
+               clocks {
+                       compatible = "samsung,s5m8767-clk";
+                       #clock-cells = <1>;
+                       clock-output-names = "en32khz_ap",
+                                            "en32khz_cp",
+                                            "en32khz_bt";
+               };
+
+               regulators {
+                       ldo4_reg: LDO4 {
+                               regulator-name = "P1.0V_LDO_OUT4";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo5_reg: LDO5 {
+                               regulator-name = "P1.0V_LDO_OUT5";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo6_reg: LDO6 {
+                               regulator-name = "vdd_mydp";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo7_reg: LDO7 {
+                               regulator-name = "P1.1V_LDO_OUT7";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo8_reg: LDO8 {
+                               regulator-name = "P1.0V_LDO_OUT8";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo10_reg: LDO10 {
+                               regulator-name = "P1.8V_LDO_OUT10";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo11_reg: LDO11 {
+                               regulator-name = "P1.8V_LDO_OUT11";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo12_reg: LDO12 {
+                               regulator-name = "P3.0V_LDO_OUT12";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo13_reg: LDO13 {
+                               regulator-name = "P1.8V_LDO_OUT13";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo14_reg: LDO14 {
+                               regulator-name = "P1.8V_LDO_OUT14";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo15_reg: LDO15 {
+                               regulator-name = "P1.0V_LDO_OUT15";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo16_reg: LDO16 {
+                               regulator-name = "P1.8V_LDO_OUT16";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               op_mode = <3>;
+                       };
+
+                       ldo17_reg: LDO17 {
+                               regulator-name = "P2.8V_LDO_OUT17";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-always-on;
+                               op_mode = <0>;
+                       };
+
+                       ldo25_reg: LDO25 {
+                               regulator-name = "vdd_bridge";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               op_mode = <1>;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "vdd_mif";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck2_reg: BUCK2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck3_reg: BUCK3 {
+                               regulator-name = "vdd_int";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck4_reg: BUCK4 {
+                               regulator-name = "vdd_g3d";
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+
+                       buck5_reg: BUCK5 {
+                               regulator-name = "P1.8V_BUCK_OUT5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <1>;
+                       };
+
+                       buck6_reg: BUCK6 {
+                               regulator-name = "P1.2V_BUCK_OUT6";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <0>;
+                       };
+
+                       buck9_reg: BUCK9 {
+                               regulator-name = "vdd_ummc";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               op_mode = <3>;
+                       };
+               };
+       };
+};
+
+&i2c_1 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <378000>;
+
+       trackpad@4b {
+               compatible = "atmel,maxtouch";
+               reg = <0x4b>;
+               interrupt-parent = <&gpx1>;
+               interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&trackpad_irq>;
+               linux,gpio-keymap = <KEY_RESERVED
+                                    KEY_RESERVED
+                                    KEY_RESERVED
+                                    KEY_RESERVED
+                                    KEY_RESERVED
+                                    BTN_LEFT>;
+               wakeup-source;
+       };
+};
+
+/*
+ * Disabled pullups since external part has its own pullups and
+ * double-pulling gets us out of spec in some cases.
+ */
+&i2c2_bus {
+       samsung,pin-pud = <0>;
+};
+
+&i2c_2 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+
+       hdmiddc@50 {
+               compatible = "samsung,exynos4210-hdmiddc";
+               reg = <0x50>;
+       };
+};
+
+&i2c_3 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+};
+
+&i2c_4 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+
+       cros_ec: embedded-controller {
+               compatible = "google,cros-ec-i2c";
+               reg = <0x1e>;
+               interrupts = <6 IRQ_TYPE_NONE>;
+               interrupt-parent = <&gpx1>;
+               wakeup-source;
+               pinctrl-names = "default";
+               pinctrl-0 = <&ec_irq>;
+       };
+};
+
+&i2c_5 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+};
+
+&i2c_7 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <66000>;
+
+       temperature-sensor@4c {
+               compatible = "gmt,g781";
+               reg = <0x4c>;
+       };
+};
+
+&i2c_8 {
+       status = "okay";
+       samsung,i2c-sda-delay = <100>;
+       samsung,i2c-max-bus-freq = <378000>;
+
+       hdmiphy: hdmiphy@38 {
+               compatible = "samsung,exynos4212-hdmiphy";
+               reg = <0x38>;
+       };
+};
+
+&i2s0 {
+       status = "okay";
+};
+
+&mfc {
+       samsung,mfc-r = <0x43000000 0x800000>;
+       samsung,mfc-l = <0x51000000 0x800000>;
+};
+
+&mmc_0 {
+       status = "okay";
+       num-slots = <1>;
+       supports-highspeed;
+       broken-cd;
+       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 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4 &sd0_bus8>;
+
+       slot@0 {
+               reg = <0>;
+               bus-width = <8>;
+       };
+};
+
+/*
+ * On Spring we've got SIP WiFi and so can keep drive strengths low to
+ * reduce EMI.
+ */
+&mmc_1 {
+       status = "okay";
+       num-slots = <1>;
+       supports-highspeed;
+       broken-cd;
+       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 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus4>;
+
+       slot@0 {
+               reg = <0>;
+               bus-width = <4>;
+       };
+};
+
+&pinctrl_0 {
+       s5m8767_dvs: s5m8767-dvs {
+               samsung,pins = "gpd1-0", "gpd1-1", "gpd1-2";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <1>;
+               samsung,pin-drv = <0>;
+       };
+
+       dp_hpd_gpio: dp-hpd-gpio {
+               samsung,pins = "gpc3-0";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <3>;
+               samsung,pin-drv = <0>;
+       };
+
+       trackpad_irq: trackpad-irq {
+               samsung,pins = "gpx1-2";
+               samsung,pin-function = <0xf>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       power_key_irq: power-key-irq {
+               samsung,pins = "gpx1-3";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       ec_irq: ec-irq {
+               samsung,pins = "gpx1-6";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       s5m8767_ds: s5m8767-ds {
+               samsung,pins = "gpx2-3", "gpx2-4", "gpx2-5";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <1>;
+               samsung,pin-drv = <0>;
+       };
+
+       s5m8767_irq: s5m8767-irq {
+               samsung,pins = "gpx3-2";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       lid_irq: lid-irq {
+               samsung,pins = "gpx3-5";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       hdmi_hpd_irq: hdmi-hpd-irq {
+               samsung,pins = "gpx3-7";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <1>;
+               samsung,pin-drv = <0>;
+       };
+};
+
+&pinctrl_1 {
+       hsic_reset: hsic-reset {
+               samsung,pins = "gpe1-0";
+               samsung,pin-function = <1>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+};
+
+&sd1_bus4 {
+       samsung,pin-drv = <0>;
+};
+
+&sd1_cd {
+       samsung,pin-drv = <0>;
+};
+
+&sd1_clk {
+       samsung,pin-drv = <0>;
+};
+
+&sd1_cmd {
+       samsung,pin-pud = <3>;
+       samsung,pin-drv = <0>;
+};
+
+&spi_1 {
+       status = "okay";
+       samsung,spi-src-clk = <0>;
+       num-cs = <1>;
+};
+
+#include "cros-ec-keyboard.dtsi"
index f21b9aa00fbb214f4dee8b0b1980884f5411c70f..d45a07ea3402c4ab658d33f8411fac08f5532ad7 100644 (file)
                clock-names = "fimg2d";
        };
 
-       codec@11000000 {
+       mfc: codec@11000000 {
                compatible = "samsung,mfc-v6";
                reg = <0x11000000 0x10000>;
                interrupts = <0 96 0>;
                clock-names = "mfc";
        };
 
-       rtc@101E0000 {
+       rtc: rtc@101E0000 {
                clocks = <&clock CLK_RTC>;
                clock-names = "rtc";
                status = "disabled";
                clock-names = "uart", "clk_uart_baud0";
        };
 
-       sata@122F0000 {
+       sata: sata@122F0000 {
                compatible = "snps,dwc-ahci";
                samsung,sata-freq = <66>;
                reg = <0x122F0000 0x1ff>;
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c0_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c1_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c2_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c3_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
                #size-cells = <1>;
                ranges;
 
-               dwc3 {
+               usbdrd_dwc3: dwc3 {
                        compatible = "synopsys,dwc3";
                        reg = <0x12000000 0x10000>;
                        interrupts = <0 72 0>;
                #phy-cells = <1>;
        };
 
-       usb@12110000 {
+       ehci: usb@12110000 {
                compatible = "samsung,exynos4210-ehci";
                reg = <0x12110000 0x100>;
                interrupts = <0 71 0>;
                };
        };
 
-       usb@12120000 {
+       ohci: usb@12120000 {
                compatible = "samsung,exynos4210-ohci";
                reg = <0x12120000 0x100>;
                interrupts = <0 71 0>;
                clock-names = "gscl";
        };
 
-       hdmi {
+       hdmi: hdmi {
                compatible = "samsung,exynos4212-hdmi";
                reg = <0x14530000 0x70000>;
                interrupts = <0 95 0>;
                #phy-cells = <0>;
        };
 
-       dp-controller@145B0000 {
+       dp: dp-controller@145B0000 {
                clocks = <&clock CLK_DP>;
                clock-names = "dp";
                phys = <&dp_phy>;
                phy-names = "dp";
        };
 
-       fimd@14400000 {
+       fimd: fimd@14400000 {
                clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
                clock-names = "sclk_fimd", "fimd";
        };
index 82cdb74484cc09c7d45a95b036d148c12f8144e7..9a050e19a4dcd5b9a0f4db2ba29e689ab3d9ed9c 100644 (file)
@@ -12,6 +12,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/maxim,max77802.h>
 #include "exynos5420.dtsi"
 
 / {
        status = "okay";
        clock-frequency = <400000>;
 
-       max77802-pmic@9 {
+       max77802: max77802-pmic@9 {
                compatible = "maxim,max77802";
                interrupt-parent = <&gpx3>;
                interrupts = <1 IRQ_TYPE_NONE>;
        status = "okay";
        num-slots = <1>;
        broken-cd;
-       caps2-mmc-hs200-1_8v;
+       mmc-hs200-1_8v;
        cap-mmc-highspeed;
        non-removable;
        card-detect-delay = <200>;
 
 &rtc {
        status = "okay";
+       clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
+       clock-names = "rtc", "rtc_src";
 };
 
 &spi_2 {
index 8617a031cbc06bf670e42f167056fe6c061b0d63..90bf4011e3195ae93a5a38bab7343e506ff45c0a 100644 (file)
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c0_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c1_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c2_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
                clock-names = "i2c";
                pinctrl-names = "default";
                pinctrl-0 = <&i2c3_bus>;
+               samsung,sysreg-phandle = <&sysreg_system_controller>;
                status = "disabled";
        };
 
index 7bb1c8dd42dd9a8c5d3c3196249787a39b0442b9..e8fdda827fc9d5561d6097ded1b177644442e31a 100644 (file)
@@ -12,6 +12,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/maxim,max77802.h>
 #include "exynos5800.dtsi"
 
 / {
        status = "okay";
        clock-frequency = <400000>;
 
-       max77802-pmic@9 {
+       max77802: max77802-pmic@9 {
                compatible = "maxim,max77802";
                interrupt-parent = <&gpx3>;
                interrupts = <1 IRQ_TYPE_NONE>;
        status = "okay";
        num-slots = <1>;
        broken-cd;
-       caps2-mmc-hs200-1_8v;
+       mmc-hs200-1_8v;
        cap-mmc-highspeed;
        non-removable;
        card-detect-delay = <200>;
 
 &rtc {
        status = "okay";
+       clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
+       clock-names = "rtc", "rtc_src";
 };
 
 &spi_2 {
index 05b44c272c9a7b11cd05f64ac1879dc128fe035d..721b09238f58846746053b64f113ea327723c60e 100644 (file)
 &uart0 {
        status = "okay";
 };
+
+&gmac0 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       phy-handle = <&phy2>;
+       phy-mode = "mii";
+       /* Placeholder, overwritten by bootloader */
+       mac-address = [00 00 00 00 00 00];
+       status = "okay";
+
+       phy2: ethernet-phy@2 {
+               reg = <2>;
+       };
+};
+
+&gmac1 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       phy-handle = <&phy1>;
+       phy-mode = "rgmii";
+       /* Placeholder, overwritten by bootloader */
+       mac-address = [00 00 00 00 00 00];
+       status = "okay";
+
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
+&ahci {
+       phys = <&sata_phy>;
+       phy-names = "sata-phy";
+};
index f85ba2924ff7ef01b08703a2ece00ffbe5382452..c52722b14e4a01577af7768a2b840f97836afbdd 100644 (file)
                                clock-names = "apb_pclk";
                                status = "disabled";
                        };
+
+                       gpio0: gpio@b20000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb20000 0x1000>;
+                               interrupts = <0 108 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio1: gpio@b21000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb21000 0x1000>;
+                               interrupts = <0 109 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio2: gpio@b22000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb22000 0x1000>;
+                               interrupts = <0 110 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio3: gpio@b23000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb23000 0x1000>;
+                               interrupts = <0 111 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio4: gpio@b24000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb24000 0x1000>;
+                               interrupts = <0 112 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio5: gpio@004000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0x004000 0x1000>;
+                               interrupts = <0 113 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio6: gpio@b26000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb26000 0x1000>;
+                               interrupts = <0 114 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio7: gpio@b27000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb27000 0x1000>;
+                               interrupts = <0 115 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio8: gpio@b28000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb28000 0x1000>;
+                               interrupts = <0 116 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio9: gpio@b29000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb29000 0x1000>;
+                               interrupts = <0 117 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio10: gpio@b2a000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb2a000 0x1000>;
+                               interrupts = <0 118 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio11: gpio@b2b000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb2b000 0x1000>;
+                               interrupts = <0 119 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio12: gpio@b2c000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb2c000 0x1000>;
+                               interrupts = <0 120 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio13: gpio@b2d000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb2d000 0x1000>;
+                               interrupts = <0 121 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio14: gpio@b2e000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb2e000 0x1000>;
+                               interrupts = <0 122 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio15: gpio@b2f000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb2f000 0x1000>;
+                               interrupts = <0 123 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio16: gpio@b30000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb30000 0x1000>;
+                               interrupts = <0 124 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       gpio17: gpio@b31000 {
+                               compatible = "arm,pl061", "arm,primecell";
+                               reg = <0xb31000 0x1000>;
+                               interrupts = <0 125 0x4>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               clocks = <&clock HIX5HD2_FIXED_100M>;
+                               clock-names = "apb_pclk";
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               status = "disabled";
+                       };
+
+                       wdt0: watchdog@a2c000 {
+                               compatible = "arm,sp805", "arm,primecell";
+                               arm,primecell-periphid = <0x00141805>;
+                               reg = <0xa2c000 0x1000>;
+                               interrupts = <0 29 4>;
+                               clocks = <&clock HIX5HD2_WDG0_RST>;
+                               clock-names = "apb_pclk";
+                       };
                };
 
                local_timer@00a00600 {
                };
 
                sysctrl: system-controller@00000000 {
-                       compatible = "hisilicon,sysctrl";
+                       compatible = "hisilicon,sysctrl", "syscon";
                        reg = <0x00000000 0x1000>;
-                       reboot-offset = <0x4>;
+               };
+
+               reboot {
+                       compatible = "syscon-reboot";
+                       regmap = <&sysctrl>;
+                       offset = <0x4>;
+                       mask = <0xdeadbeef>;
                };
 
                cpuctrl@00a22000 {
                                #clock-cells = <1>;
                        };
                };
+
+               /* unremovable emmc as mmcblk0 */
+               mmc: mmc@1830000 {
+                       compatible = "snps,dw-mshc";
+                       reg = <0x1830000 0x1000>;
+                       interrupts = <0 35 4>;
+                       clocks = <&clock HIX5HD2_MMC_CIU_RST>,
+                                <&clock HIX5HD2_MMC_BIU_CLK>;
+                       clock-names = "ciu", "biu";
+               };
+
+               sd: mmc@1820000 {
+                       compatible = "snps,dw-mshc";
+                       reg = <0x1820000 0x1000>;
+                       interrupts = <0 34 4>;
+                       clocks = <&clock HIX5HD2_SD_CIU_RST>,
+                                <&clock HIX5HD2_SD_BIU_CLK>;
+                       clock-names = "ciu","biu";
+               };
+
+               gmac0: ethernet@1840000 {
+                       compatible = "hisilicon,hix5hd2-gmac";
+                       reg = <0x1840000 0x1000>,<0x184300c 0x4>;
+                       interrupts = <0 71 4>;
+                       clocks = <&clock HIX5HD2_MAC0_CLK>;
+                       status = "disabled";
+               };
+
+               gmac1: ethernet@1841000 {
+                       compatible = "hisilicon,hix5hd2-gmac";
+                       reg = <0x1841000 0x1000>,<0x1843010 0x4>;
+                       interrupts = <0 72 4>;
+                       clocks = <&clock HIX5HD2_MAC1_CLK>;
+                       status = "disabled";
+               };
+
+               usb0: ehci@1890000 {
+                       compatible = "generic-ehci";
+                       reg = <0x1890000 0x1000>;
+                       interrupts = <0 66 4>;
+                       clocks = <&clock HIX5HD2_USB_CLK>;
+               };
+
+               usb1: ohci@1880000 {
+                       compatible = "generic-ohci";
+                       reg = <0x1880000 0x1000>;
+                       interrupts = <0 67 4>;
+                       clocks = <&clock HIX5HD2_USB_CLK>;
+               };
+
+               peripheral_ctrl: syscon@a20000 {
+                       compatible = "syscon";
+                       reg = <0xa20000 0x1000>;
+               };
+
+               sata_phy: phy@1900000 {
+                       compatible = "hisilicon,hix5hd2-sata-phy";
+                       reg = <0x1900000 0x10000>;
+                       #phy-cells = <0>;
+                       hisilicon,peripheral-syscon = <&peripheral_ctrl>;
+                       hisilicon,power-reg = <0x8 10>;
+               };
+
+               ahci: sata@1900000 {
+                       compatible = "hisilicon,hisi-ahci";
+                       reg = <0x1900000 0x10000>;
+                       interrupts = <0 70 4>;
+                       clocks = <&clock HIX5HD2_SATA_CLK>;
+               };
+
+               ir: ir@001000 {
+                       compatible = "hisilicon,hix5hd2-ir";
+                       reg = <0x001000 0x1000>;
+                       interrupts = <0 47 4>;
+                       clocks = <&clock HIX5HD2_FIXED_24M>;
+                       hisilicon,power-syscon = <&sysctrl>;
+               };
+
+               i2c0: i2c@b10000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0xb10000 0x1000>;
+                       interrupts = <0 38 4>;
+                       clocks = <&clock HIX5HD2_I2C0_RST>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@b11000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0xb11000 0x1000>;
+                       interrupts = <0 39 4>;
+                       clocks = <&clock HIX5HD2_I2C1_RST>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c2: i2c@b12000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0xb12000 0x1000>;
+                       interrupts = <0 40 4>;
+                       clocks = <&clock HIX5HD2_I2C2_RST>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c3: i2c@b13000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0xb13000 0x1000>;
+                       interrupts = <0 41 4>;
+                       clocks = <&clock HIX5HD2_I2C3_RST>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c4: i2c@b16000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0xb16000 0x1000>;
+                       interrupts = <0 43 4>;
+                       clocks = <&clock HIX5HD2_I2C4_RST>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c5: i2c@b17000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0xb17000 0x1000>;
+                       interrupts = <0 44 4>;
+                       clocks = <&clock HIX5HD2_I2C5_RST>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
        };
 };
index 09664fcf5afb047c0923fa5e5fe7c343e0f2171e..0e13b4b10a929cb7d22beee36a5775948849c5a3 100644 (file)
                        i2c0: i2c@80058000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&i2c0_pins_a>;
-                               clock-frequency = <400000>;
                                status = "okay";
 
                                sgtl5000: codec@0a {
index 92660e1fe1fc416669ac0ce7e821e0e849e4e80e..c0116cffc513436d54584ee9d1c9d8ad933ebb83 100644 (file)
                                        compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
                                        reg = <0x70014000 0x4000>;
                                        interrupts = <30>;
-                                       clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+                                       clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>,
+                                                <&clks IMX5_CLK_SSI2_ROOT_GATE>;
+                                       clock-names = "ipg", "baud";
                                        dmas = <&sdma 24 1 0>,
                                               <&sdma 25 1 0>;
                                        dma-names = "rx", "tx";
                                compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
                                reg = <0x83fcc000 0x4000>;
                                interrupts = <29>;
-                               clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+                               clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>,
+                                        <&clks IMX5_CLK_SSI1_ROOT_GATE>;
+                               clock-names = "ipg", "baud";
                                dmas = <&sdma 28 0 0>,
                                       <&sdma 29 0 0>;
                                dma-names = "rx", "tx";
                                compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
                                reg = <0x83fe8000 0x4000>;
                                interrupts = <96>;
-                               clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
+                               clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>,
+                                        <&clks IMX5_CLK_SSI3_ROOT_GATE>;
+                               clock-names = "ipg", "baud";
                                dmas = <&sdma 46 0 0>,
                                       <&sdma 47 0 0>;
                                dma-names = "rx", "tx";
index f91725b2e8ab4f76b3583ab786bca65a64c9e9c8..a30bddfdbdb6e587d455dc3d07beb0d6f4eb1aba 100644 (file)
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
-               cpu@0 {
+               cpu0: cpu@0 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a8";
                        reg = <0x0>;
+                       clocks = <&clks IMX5_CLK_ARM>;
+                       clock-latency = <61036>;
+                       voltage-tolerance = <5>;
+                       operating-points = <
+                               /* kHz */
+                                166666  850000
+                                400000  900000
+                                800000 1050000
+                               1000000 1200000
+                               1200000 1300000
+                       >;
                };
        };
 
                                                        "fsl,imx21-ssi";
                                        reg = <0x50014000 0x4000>;
                                        interrupts = <30>;
-                                       clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>;
+                                       clocks = <&clks IMX5_CLK_SSI2_IPG_GATE>,
+                                                <&clks IMX5_CLK_SSI2_ROOT_GATE>;
+                                       clock-names = "ipg", "baud";
                                        dmas = <&sdma 24 1 0>,
                                               <&sdma 25 1 0>;
                                        dma-names = "rx", "tx";
                                                "fsl,imx21-ssi";
                                reg = <0x63fcc000 0x4000>;
                                interrupts = <29>;
-                               clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>;
+                               clocks = <&clks IMX5_CLK_SSI1_IPG_GATE>,
+                                        <&clks IMX5_CLK_SSI1_ROOT_GATE>;
+                               clock-names = "ipg", "baud";
                                dmas = <&sdma 28 0 0>,
                                       <&sdma 29 0 0>;
                                dma-names = "rx", "tx";
                                                "fsl,imx21-ssi";
                                reg = <0x63fe8000 0x4000>;
                                interrupts = <96>;
-                               clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>;
+                               clocks = <&clks IMX5_CLK_SSI3_IPG_GATE>,
+                                        <&clks IMX5_CLK_SSI3_ROOT_GATE>;
+                               clock-names = "ipg", "baud";
                                dmas = <&sdma 46 0 0>,
                                       <&sdma 47 0 0>;
                                dma-names = "rx", "tx";
index b453e0e28aeec5d537e4b4da0f664f36d946bb70..1ac2fe7328679b128da6ef74669abad2d4bd08fd 100644 (file)
 #include "imx6qdl.dtsi"
 
 / {
+       aliases {
+               i2c3 = &i2c4;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                      "di0_sel", "di1_sel",
                      "di0", "di1";
 };
+
+&vpu {
+       compatible = "fsl,imx6dl-vpu", "cnm,coda960";
+};
diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts
new file mode 100644 (file)
index 0000000..a43abfa
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2014 Soeren Moch <smoch@web.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     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 "imx6q.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "TBS2910 Matrix ARM mini PC";
+       compatible = "tbs,imx6q-tbs2910", "fsl,imx6q";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       memory {
+               reg = <0x10000000 0x80000000>;
+       };
+
+       fan {
+               compatible = "gpio-fan";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_fan>;
+               gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>;
+               gpio-fan,speed-map = <0    0
+                                     3000 1>;
+       };
+
+       ir_recv {
+               compatible = "gpio-ir-receiver";
+               gpios = <&gpio3 18 GPIO_ACTIVE_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ir>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_leds>;
+
+               blue {
+                       label = "blue_status_led";
+                       gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+                       default-state = "keep";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_2p5v: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "2P5V";
+                       regulator-min-microvolt = <2500000>;
+                       regulator-max-microvolt = <2500000>;
+               };
+
+               reg_3p3v: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+               };
+
+               reg_5p0v: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "5P0V";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+               };
+       };
+
+       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 = <3>;
+               mux-int-port = <1>;
+               ssi-controller = <&ssi1>;
+       };
+
+       sound-spdif {
+               compatible = "fsl,imx-audio-spdif";
+               model = "On-board SPDIF";
+               spdif-controller = <&spdif>;
+               spdif-out;
+       };
+};
+
+&audmux {
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&hdmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hdmi>;
+       ddc-i2c-bus = <&i2c2>;
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       sgtl5000: sgtl5000@0a {
+               clocks = <&clks 201>;
+               compatible = "fsl,sgtl5000";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_sgtl5000>;
+               reg = <0x0a>;
+               VDDA-supply = <&reg_2p5v>;
+               VDDIO-supply = <&reg_3p3v>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       rtc: ds1307@68 {
+               compatible = "dallas,ds1307";
+               reg = <0x68>;
+       };
+};
+
+&pcie {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie>;
+       reset-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&sata {
+       status = "okay";
+};
+
+&snvs_poweroff {
+       status = "okay";
+};
+
+&spdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_spdif>;
+       status = "okay";
+};
+
+&ssi1 {
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_5p0v>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_5p0v>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usdhc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc2>;
+       bus-width = <4>;
+       cd-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       bus-width = <4>;
+       cd-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;
+       wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+       vmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
+
+&usdhc4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc4>;
+       bus-width = <8>;
+       non-removable;
+       no-1-8-v;
+       status = "okay";
+};
+
+&iomuxc {
+       imx6q-tbs2910 {
+               pinctrl_enet: enetgrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
+                               MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
+                               MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
+                               MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
+                               MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
+                               MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
+                               MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
+                               MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+                               MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
+                               MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
+                               MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
+                               MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
+                               MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
+                               MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
+                               MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+                               MX6QDL_PAD_GPIO_16__ENET_REF_CLK      0x4001b0a8
+                               MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25    0x1b059
+                       >;
+               };
+
+               pinctrl_hdmi: hdmigrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
+                       >;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_CSI0_DAT9__I2C1_SCL        0x4001b8b1
+                               MX6QDL_PAD_CSI0_DAT8__I2C1_SDA        0x4001b8b1
+                       >;
+               };
+
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_KEY_COL3__I2C2_SCL         0x4001b8b1
+                               MX6QDL_PAD_KEY_ROW3__I2C2_SDA         0x4001b8b1
+                       >;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_GPIO_3__I2C3_SCL           0x4001b8b1
+                               MX6QDL_PAD_GPIO_6__I2C3_SDA           0x4001b8b1
+                       >;
+               };
+
+               pinctrl_ir: irgrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_D18__GPIO3_IO18        0x17059
+                       >;
+               };
+
+               pinctrl_pcie: pciegrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_GPIO_17__GPIO7_IO12        0x17059
+                       >;
+               };
+
+               pinctrl_sgtl5000: sgtl5000grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_CSI0_DAT7__AUD3_RXD        0x130b0
+                               MX6QDL_PAD_CSI0_DAT4__AUD3_TXC        0x130b0
+                               MX6QDL_PAD_CSI0_DAT5__AUD3_TXD        0x110b0
+                               MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS       0x130b0
+                               MX6QDL_PAD_GPIO_0__CCM_CLKO1          0x130b0
+                       >;
+               };
+
+               pinctrl_spdif: spdifgrp {
+                       fsl,pins = <MX6QDL_PAD_GPIO_19__SPDIF_OUT     0x13091
+                       >;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA  0x1b0b1
+                               MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA  0x1b0b1
+                       >;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_D26__UART2_TX_DATA     0x1b0b1
+                               MX6QDL_PAD_EIM_D27__UART2_RX_DATA     0x1b0b1
+                       >;
+               };
+
+               pinctrl_usbotg: usbotggrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID     0x17059
+                       >;
+               };
+
+               pinctrl_usdhc2: usdhc2grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_SD2_CMD__SD2_CMD           0x17059
+                               MX6QDL_PAD_SD2_CLK__SD2_CLK           0x10059
+                               MX6QDL_PAD_SD2_DAT0__SD2_DATA0        0x17059
+                               MX6QDL_PAD_SD2_DAT1__SD2_DATA1        0x17059
+                               MX6QDL_PAD_SD2_DAT2__SD2_DATA2        0x17059
+                               MX6QDL_PAD_SD2_DAT3__SD2_DATA3        0x17059
+                               MX6QDL_PAD_NANDF_D2__GPIO2_IO02       0x17059
+                       >;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_SD3_CMD__SD3_CMD           0x17059
+                               MX6QDL_PAD_SD3_CLK__SD3_CLK           0x10059
+                               MX6QDL_PAD_SD3_DAT0__SD3_DATA0        0x17059
+                               MX6QDL_PAD_SD3_DAT1__SD3_DATA1        0x17059
+                               MX6QDL_PAD_SD3_DAT2__SD3_DATA2        0x17059
+                               MX6QDL_PAD_SD3_DAT3__SD3_DATA3        0x17059
+                               MX6QDL_PAD_NANDF_D0__GPIO2_IO00       0x17059
+                               MX6QDL_PAD_NANDF_D1__GPIO2_IO01       0x17059
+                       >;
+               };
+
+               pinctrl_usdhc4: usdhc4grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_SD4_CMD__SD4_CMD           0x17059
+                               MX6QDL_PAD_SD4_CLK__SD4_CLK           0x10059
+                               MX6QDL_PAD_SD4_DAT0__SD4_DATA0        0x17059
+                               MX6QDL_PAD_SD4_DAT1__SD4_DATA1        0x17059
+                               MX6QDL_PAD_SD4_DAT2__SD4_DATA2        0x17059
+                               MX6QDL_PAD_SD4_DAT3__SD4_DATA3        0x17059
+                               MX6QDL_PAD_SD4_DAT4__SD4_DATA4        0x17059
+                               MX6QDL_PAD_SD4_DAT5__SD4_DATA5        0x17059
+                               MX6QDL_PAD_SD4_DAT6__SD4_DATA6        0x17059
+                               MX6QDL_PAD_SD4_DAT7__SD4_DATA7        0x17059
+                       >;
+               };
+       };
+
+       gpio_fan {
+               pinctrl_gpio_fan: gpiofangrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_D28__GPIO3_IO28        0x130b1
+                       >;
+               };
+       };
+
+       gpio_leds {
+               pinctrl_gpio_leds: gpioledsgrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_GPIO_2__GPIO1_IO02         0x130b1
+                       >;
+               };
+       };
+};
index e9f3646d1760618cb04027329754c53194068a8c..85f72e6b5badebe9afb92a4ebda4414efb19aa83 100644 (file)
                };
        };
 };
+
+&vpu {
+       compatible = "fsl,imx6q-vpu", "cnm,coda960";
+};
index d3c0bf5c84e316bcab8c86d527dabd4598d9a63b..b5756c21ea1d55b791b10e6728b573a918ad78e7 100644 (file)
 };
 
 &ssi1 {
-       fsl,mode = "i2s-slave";
        status = "okay";
 };
 
index cade1bdc97e9b32b08c3971d55acfb8996439b86..86f03c1b147c630c43166aa9d4782da28f333519 100644 (file)
 };
 
 &ssi1 {
-       fsl,mode = "i2s-slave";
        status = "okay";
 };
 
index cf13239a16190e4d50fe9a7088810eb45258f0a5..4a8d97f477592316c3d9ff86cee4bc1b5c9e887f 100644 (file)
 };
 
 &ssi1 {
-       fsl,mode = "i2s-slave";
        status = "okay";
 };
 
 &ssi2 {
-       fsl,mode = "i2s-slave";
        status = "okay";
 };
 
index 584721264121b2192fbf425255c67c1bf7355f40..585b4f6986c1ccd7262cd9c4ce394039b376de22 100644 (file)
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
 / {
        chosen {
                linux,stdout-path = &uart4;
        };
+
+       regulators {
+               sound_1v8: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "i2s-audio-1v8";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+               };
+
+               sound_3v3: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "i2s-audio-3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+               };
+       };
+
+       tlv320_mclk: oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <19200000>;
+               clock-output-names = "tlv320-mclk";
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "OnboardTLV320AIC3007";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&dailink_master>;
+               simple-audio-card,frame-master = <&dailink_master>;
+               simple-audio-card,widgets =
+                       "Microphone", "Mic Jack",
+                       "Line", "Line In",
+                       "Line", "Line Out",
+                       "Speaker", "Speaker",
+                       "Headphone", "Headphone Jack";
+               simple-audio-card,routing =
+                       "Line Out", "LLOUT",
+                       "Line Out", "RLOUT",
+                       "Speaker", "SPOP",
+                       "Speaker", "SPOM",
+                       "Headphone Jack", "HPLOUT",
+                       "Headphone Jack", "HPROUT",
+                       "MIC3L", "Mic Jack",
+                       "MIC3R", "Mic Jack",
+                       "Mic Jack", "Mic Bias",
+                       "LINE1L", "Line In",
+                       "LINE1R", "Line In";
+
+               simple-audio-card,cpu {
+                       sound-dai = <&ssi2>;
+               };
+
+               dailink_master: simple-audio-card,codec {
+                       sound-dai = <&codec>;
+                       clocks = <&tlv320_mclk>;
+               };
+       };
+
 };
 
-&fec {
+&audmux {
        status = "okay";
+
+       ssi2 {
+               fsl,audmux-port = <1>;
+               fsl,port-config = <
+                       (IMX_AUDMUX_V2_PTCR_TFSDIR |
+                       IMX_AUDMUX_V2_PTCR_TFSEL(4) |
+                       IMX_AUDMUX_V2_PTCR_TCLKDIR |
+                       IMX_AUDMUX_V2_PTCR_TCSEL(4))
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(4)
+               >;
+       };
+
+       pins5 {
+               fsl,audmux-port = <4>;
+               fsl,port-config = <
+                       0x00000000
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(1)
+               >;
+       };
 };
 
-&gpmi {
+&can1 {
+       status = "okay";
+};
+
+&fec {
        status = "okay";
 };
 
 };
 
 &i2c2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c2>;
-       clock-frequency = <100000>;
        status = "okay";
 
-       tlv320@18 {
-               compatible = "ti,tlv320aic3x";
+       codec: tlv320@18 {
+               compatible = "ti,tlv320aic3007";
+               #sound-dai-cells = <0>;
                reg = <0x18>;
+               ai3x-micbias-vg = <2>;
+
+               AVDD-supply = <&sound_3v3>;
+               IOVDD-supply = <&sound_3v3>;
+               DRVDD-supply = <&sound_3v3>;
+               DVDD-supply = <&sound_1v8>;
        };
 
        stmpe@41 {
 };
 
 &i2c3 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_i2c3>;
-       clock-frequency = <100000>;
+       status = "okay";
+};
+
+&pcie {
+       status = "okay";
+};
+
+&ssi2 {
        status = "okay";
 };
 
 &usdhc3 {
        status = "okay";
 };
-
-&iomuxc {
-       pinctrl_i2c2: i2c2grp {
-               fsl,pins = <
-                       MX6QDL_PAD_EIM_EB2__I2C2_SCL            0x4001b8b1
-                       MX6QDL_PAD_EIM_D16__I2C2_SDA            0x4001b8b1
-               >;
-       };
-
-       pinctrl_i2c3: i2c3grp {
-               fsl,pins = <
-                       MX6QDL_PAD_EIM_D17__I2C3_SCL            0x4001b8b1
-                       MX6QDL_PAD_EIM_D18__I2C3_SDA            0x4001b8b1
-               >;
-       };
-};
index 0e50bb0a6b94c846f8dc0cf039893b1560fd4b97..19cc269a08d4d7acdc3572821b32399ee584f824 100644 (file)
        };
 };
 
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "disabled";
+};
+
+&can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       status = "disabled";
+};
+
 &ecspi3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ecspi3>;
        };
 };
 
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii";
+       phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+       phy-supply = <&vdd_eth_io_reg>;
+       status = "disabled";
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       nand-on-flash-bbt;
+       status = "okay";
+};
+
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c1>;
        pmic@58 {
                compatible = "dlg,da9063";
                reg = <0x58>;
-               interrupt-parent = <&gpio4>;
-               interrupts = <17 0x8>; /* active-low GPIO4_17 */
+               interrupt-parent = <&gpio2>;
+               interrupts = <9 0x8>; /* active-low GPIO2_9 */
 
                regulators {
                        vddcore_reg: bcore1 {
        };
 };
 
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       clock-frequency = <100000>;
+};
+
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       clock-frequency = <100000>;
+};
+
 &iomuxc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
                        fsl,pins = <
                                MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
                                MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
-                               MX6QDL_PAD_DI0_PIN15__GPIO4_IO17  0x80000000 /* PMIC interrupt */
+                               MX6QDL_PAD_SD4_DAT1__GPIO2_IO09  0x80000000 /* PMIC interrupt */
                                MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* Green LED */
                                MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000 /* Red LED */
                        >;
                        >;
                };
 
+               pinctrl_flexcan1: flexcan1grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX        0x1b0b0
+                               MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX        0x1b0b0
+                       >;
+               };
+
                pinctrl_gpmi_nand: gpminandgrp {
                        fsl,pins = <
                                MX6QDL_PAD_NANDF_CLE__NAND_CLE          0xb0b1
                        >;
                };
 
+               pinctrl_i2c2: i2c2grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_EB2__I2C2_SCL            0x4001b8b1
+                               MX6QDL_PAD_EIM_D16__I2C2_SDA            0x4001b8b1
+                       >;
+               };
+
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_D17__I2C3_SCL            0x4001b8b1
+                               MX6QDL_PAD_EIM_D18__I2C3_SDA            0x4001b8b1
+                       >;
+               };
+
+               pinctrl_pcie: pciegrp {
+                       fsl,pins = <MX6QDL_PAD_DI0_PIN15__GPIO4_IO17  0x80000000>;
+               };
+
                pinctrl_uart3: uart3grp {
                        fsl,pins = <
                                MX6QDL_PAD_EIM_D24__UART3_TX_DATA       0x1b0b1
                                MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
                        >;
                };
-       };
-};
 
-&fec {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
-       phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
-       phy-supply = <&vdd_eth_io_reg>;
-       status = "disabled";
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_DISP0_DAT16__AUD5_TXC        0x130b0
+                               MX6QDL_PAD_DISP0_DAT17__AUD5_TXD        0x110b0
+                               MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS       0x130b0
+                               MX6QDL_PAD_DISP0_DAT19__AUD5_RXD        0x130b0
+                       >;
+               };
+       };
 };
 
-&gpmi {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_gpmi_nand>;
-       nand-on-flash-bbt;
+&pcie {
+       pinctrl-name = "default";
+       pinctrl-0 = <&pinctrl_pcie>;
+       reset-gpio = <&gpio4 17 0>;
        status = "disabled";
 };
 
index df7bcf86c156958c99c844ed09212643a576305d..488a640796ac05fa50c4299185fbe71c64ef1a13 100644 (file)
 };
 
 &ssi1 {
-       fsl,mode = "i2s-slave";
        status = "okay";
 };
 
index baf2f00d519adf8e763129509b1dd912535d4f5f..f1cd2147421d2e0f82e2a921cc5c449d8ff6d1b4 100644 (file)
                        "Headphone Jack", "HPOUTR",
                        "Ext Spk", "SPKOUTL",
                        "Ext Spk", "SPKOUTR",
-                       "MICBIAS", "AMIC",
-                       "IN3R", "MICBIAS",
-                       "DMIC", "MICBIAS",
-                       "DMICDAT", "DMIC";
+                       "AMIC", "MICBIAS",
+                       "IN3R", "AMIC";
                mux-int-port = <2>;
                mux-ext-port = <3>;
        };
        codec: wm8962@1a {
                compatible = "wlf,wm8962";
                reg = <0x1a>;
-               clocks = <&clks 201>;
+               clocks = <&clks IMX6QDL_CLK_CKO>;
                DCVDD-supply = <&reg_audio>;
                DBVDD-supply = <&reg_audio>;
                AVDD-supply = <&reg_audio>;
        status = "okay";
 };
 
+&snvs_poweroff {
+       status = "okay";
+};
+
 &ssi2 {
        status = "okay";
 };
index 9596ed5867e6d9a6b838d5c6880ab0d86b26bb4b..4fc03b7f1ceec52fe5d327974cd2929127de21f9 100644 (file)
                        };
 
                        vpu: vpu@02040000 {
+                               compatible = "cnm,coda960";
                                reg = <0x02040000 0x3c000>;
                                interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>,
                                             <0 12 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "bit", "jpeg";
+                               clocks = <&clks IMX6QDL_CLK_VPU_AXI>,
+                                        <&clks IMX6QDL_CLK_MMDC_CH0_AXI>,
+                                        <&clks IMX6QDL_CLK_OCRAM>;
+                               clock-names = "per", "ahb", "ocram";
+                               resets = <&src 1>;
+                               iram = <&ocram>;
                        };
 
                        aipstz@0207c000 { /* AIPSTZ1 */
                                        interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
                                                     <0 20 IRQ_TYPE_LEVEL_HIGH>;
                                };
+
+                               snvs_poweroff: snvs-poweroff@38 {
+                                       compatible = "fsl,sec-v4.0-poweroff";
+                                       reg = <0x38 0x4>;
+                                       status = "disabled";
+                               };
                        };
 
                        epit1: epit@020d0000 { /* EPIT1 */
index 898d14fd765f75ef41196a216f143e39505afd2e..fda4932faefda2f0b847547f15954a94347d5c40 100644 (file)
        status = "okay";
 };
 
+&snvs_poweroff {
+       status = "okay";
+};
+
 &ssi2 {
        status = "okay";
 };
index dfd83e6d80879f9be696a3a065b8756d549d6f14..36ab8e054cee0a8ff5fcc1fb6938dc1d62a1e09f 100644 (file)
                                        interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
                                                     <0 20 IRQ_TYPE_LEVEL_HIGH>;
                                };
+
+                               snvs_poweroff: snvs-poweroff@38 {
+                                       compatible = "fsl,sec-v4.0-poweroff";
+                                       reg = <0x38 0x4>;
+                                       status = "disabled";
+                               };
                        };
 
                        epit1: epit@020d0000 {
index 82d6b34527b7a7ef7cddbb7d1beccefcc74153ac..1e6e5cc1c14cf283fb8b3bd9321f44218fbe4fb3 100644 (file)
                        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 {
 &fec1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet1>;
+       phy-supply = <&reg_enet_3v3>;
+       phy-mode = "rgmii";
+       status = "okay";
+};
+
+&fec2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet2>;
        phy-mode = "rgmii";
        status = "okay";
 };
        status = "okay";
 };
 
+&snvs_poweroff {
+       status = "okay";
+};
+
 &ssi2 {
        status = "okay";
 };
                                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_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
index f3e88c03b1e49d22d8cad7375e9f30daa617a4e0..7a24fee1e7aecf7bc16df8c241e42a5ba5e5e561 100644 (file)
                                        reg = <0x34 0x58>;
                                        interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
                                };
+
+                               snvs_poweroff: snvs-poweroff@38 {
+                                       compatible = "fsl,sec-v4.0-poweroff";
+                                       reg = <0x38 0x4>;
+                                       status = "disabled";
+                               };
                        };
 
                        epit1: epit@020d0000 {
                        };
 
                        fec2: ethernet@021b4000 {
-                               compatible = "fsl,imx6sx-fec";
+                               compatible = "fsl,imx6sx-fec", "fsl,imx6q-fec";
                                reg = <0x021b4000 0x4000>;
                                interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
index 88e3d477bf16394b0f789d855cabea0ae6217b9e..28e38f8c6b0fe46c743b75e5e207089e371bdc5e 100644 (file)
@@ -6,8 +6,18 @@
 
 / {
        core-module@10000000 {
-               compatible = "arm,core-module-integrator";
+               compatible = "arm,core-module-integrator", "syscon";
                reg = <0x10000000 0x200>;
+
+               /* Use core module LED to indicate CPU load */
+               led@0c.0 {
+                       compatible = "register-bit-led";
+                       offset = <0x0c>;
+                       mask = <0x01>;
+                       label = "integrator:core_module";
+                       linux,default-trigger = "cpu0";
+                       default-state = "on";
+               };
        };
 
        ebi@12000000 {
                        reg = <0x19000000 0x1000>;
                        interrupts = <4>;
                };
+
+               syscon {
+                       /* Debug registers mapped as syscon */
+                       compatible = "syscon";
+                       reg = <0x1a000000 0x10>;
+
+                       led@04.0 {
+                               compatible = "register-bit-led";
+                               offset = <0x04>;
+                               mask = <0x01>;
+                               label = "integrator:green0";
+                               linux,default-trigger = "heartbeat";
+                               default-state = "on";
+                       };
+                       led@04.1 {
+                               compatible = "register-bit-led";
+                               offset = <0x04>;
+                               mask = <0x02>;
+                               label = "integrator:yellow";
+                               default-state = "off";
+                       };
+                       led@04.2 {
+                               compatible = "register-bit-led";
+                               offset = <0x04>;
+                               mask = <0x04>;
+                               label = "integrator:red";
+                               default-state = "off";
+                       };
+                       led@04.3 {
+                               compatible = "register-bit-led";
+                               offset = <0x04>;
+                               mask = <0x08>;
+                               label = "integrator:green1";
+                               default-state = "off";
+                       };
+               };
        };
 };
index c568f067604d91c72a432de366b80b922570e7ba..560d62150ade0d1e29666ae086345054a42d554f 100644 (file)
                };
        };
 };
+
+&mdio {
+       ethphy0: ethernet-phy@0 {
+               compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+               reg = <0>;
+       };
+
+       ethphy1: ethernet-phy@1 {
+               compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+               reg = <1>;
+       };
+};
index c358b4b9a073738c5bf1830a9840c1f17a557c25..5fc14683d6df18ccb265538568343177b08fae0f 100644 (file)
                        #gpio-cells = <2>;
                        gpio,syscon-dev = <&devctrl 0x240>;
                };
+
+               pcie@21020000 {
+                       compatible = "ti,keystone-pcie","snps,dw-pcie";
+                       clocks = <&clkpcie1>;
+                       clock-names = "pcie";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       reg =  <0x21021000 0x2000>, <0x21020000 0x1000>, <0x02620128 4>;
+                       ranges = <0x81000000 0 0 0x23260000 0x4000 0x4000
+                               0x82000000 0 0x60000000 0x60000000 0 0x10000000>;
+
+                       device_type = "pci";
+                       num-lanes = <2>;
+
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0 0 0 1 &pcie_intc1 0>, /* INT A */
+                                       <0 0 0 2 &pcie_intc1 1>, /* INT B */
+                                       <0 0 0 3 &pcie_intc1 2>, /* INT C */
+                                       <0 0 0 4 &pcie_intc1 3>; /* INT D */
+
+                       pcie_msi_intc1: msi-interrupt-controller {
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                               interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 377 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 378 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 379 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 380 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 381 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 382 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 383 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 384 IRQ_TYPE_EDGE_RISING>;
+                       };
+
+                       pcie_intc1: legacy-interrupt-controller {
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                               interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 374 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 375 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 376 IRQ_TYPE_EDGE_RISING>;
+                       };
+               };
        };
 };
 
index fec43128a2e0f946dabf80e18e287269571c4854..85cc7f2872d71f04a350ea02cb9f1df398386270 100644 (file)
                };
        };
 };
+
+&mdio {
+       ethphy0: ethernet-phy@0 {
+               compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+               reg = <0>;
+       };
+
+       ethphy1: ethernet-phy@1 {
+               compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+               reg = <1>;
+       };
+};
index 5d3e83fa224258a093383a532b08640435be46ef..c06542b2c954452dcf891f579014478e573b8221 100644 (file)
                        #interrupt-cells = <1>;
                        ti,syscon-dev = <&devctrl 0x2a0>;
                };
+
+               pcie@21800000 {
+                       compatible = "ti,keystone-pcie", "snps,dw-pcie";
+                       clocks = <&clkpcie>;
+                       clock-names = "pcie";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       reg =  <0x21801000 0x2000>, <0x21800000 0x1000>, <0x02620128 4>;
+                       ranges = <0x81000000 0 0 0x23250000 0 0x4000
+                               0x82000000 0 0x50000000 0x50000000 0 0x10000000>;
+
+                       device_type = "pci";
+                       num-lanes = <2>;
+
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0 0 0 1 &pcie_intc0 0>, /* INT A */
+                                       <0 0 0 2 &pcie_intc0 1>, /* INT B */
+                                       <0 0 0 3 &pcie_intc0 2>, /* INT C */
+                                       <0 0 0 4 &pcie_intc0 3>; /* INT D */
+
+                       pcie_msi_intc0: msi-interrupt-controller {
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                               interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 30 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 31 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 33 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>;
+                       };
+
+                       pcie_intc0: legacy-interrupt-controller {
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                               interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 28 IRQ_TYPE_EDGE_RISING>,
+                                       <GIC_SPI 29 IRQ_TYPE_EDGE_RISING>;
+                       };
+               };
        };
 };
diff --git a/arch/arm/boot/dts/kirkwood-dir665.dts b/arch/arm/boot/dts/kirkwood-dir665.dts
new file mode 100644 (file)
index 0000000..786959e
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2014 Claudio Leite <leitec@staticky.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+
+/ {
+       model = "D-Link DIR-665";
+       compatible = "dlink,dir-665", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>; /* 128 MB */
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8 earlyprintk";
+               stdout-path = &uart0;
+       };
+
+       mbus {
+               pcie-controller {
+                       status = "okay";
+
+                       pcie@1,0 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       ocp@f1000000 {
+               pinctrl: pin-controller@10000 {
+                       pinctrl-0 =< &pmx_led_usb
+                                    &pmx_led_internet_blue
+                                    &pmx_led_internet_amber
+                                    &pmx_led_5g &pmx_led_status_blue
+                                    &pmx_led_wps &pmx_led_status_amber
+                                    &pmx_led_24g
+                                    &pmx_btn_restart &pmx_btn_wps>;
+                       pinctrl-names = "default";
+
+                       pmx_led_usb: pmx-led-usb {
+                               marvell,pins = "mpp12";
+                               marvell,function = "gpio";
+                       };
+                       pmx_led_internet_blue: pmx-led-internet-blue {
+                               marvell,pins = "mpp42";
+                               marvell,function = "gpio";
+                       };
+                       pmx_led_internet_amber: pmx-led-internet-amber {
+                               marvell,pins = "mpp43";
+                               marvell,function = "gpio";
+                       };
+                       pmx_led_5g: pmx-led-5g {
+                               marvell,pins = "mpp44";
+                               marvell,function = "gpio";
+                       };
+                       pmx_led_status_blue: pmx-led-status-blue {
+                               marvell,pins = "mpp45";
+                               marvell,function = "gpio";
+                       };
+                       pmx_led_wps: pmx-led-wps {
+                               marvell,pins = "mpp47";
+                               marvell,function = "gpio";
+                       };
+                       pmx_led_status_amber: pmx-led-status-amber {
+                               marvell,pins = "mpp48";
+                               marvell,function = "gpio";
+                       };
+                       pmx_led_24g: pmx-led-24g {
+                               marvell,pins = "mpp49";
+                               marvell,function = "gpio";
+                       };
+                       pmx_btn_restart: pmx-btn-restart {
+                               marvell,pins = "mpp28";
+                               marvell,function = "gpio";
+                       };
+                       pmx_btn_wps: pmx-btn-wps {
+                               marvell,pins = "mpp46";
+                               marvell,function = "gpio";
+                       };
+               };
+
+               spi@10600 {
+                       status = "okay";
+                       m25p80@0 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "mxicy,mx25l12805d";
+                               spi-max-frequency = <50000000>;
+                               reg = <0>;
+
+                               partition@0 {
+                                       label = "uboot";
+                                       reg = <0x0 0x30000>;
+                                       read-only;
+                               };
+
+                               partition@30000 {
+                                       label = "nvram";
+                                       reg = <0x30000 0x10000>;
+                                       read-only;
+                               };
+
+                               partition@40000 {
+                                       label = "kernel";
+                                       reg = <0x40000 0x180000>;
+                               };
+
+                               partition@1c0000 {
+                                       label = "rootfs";
+                                       reg = <0x1c0000 0xe00000>;
+                               };
+
+                               cal_data: partition@fc0000 {
+                                       label = "cal_data";
+                                       reg = <0xfc0000 0x10000>;
+                                       read-only;
+                               };
+
+                               partition@fd0000 {
+                                       label = "lang_pack";
+                                       reg = <0xfd0000 0x30000>;
+                                       read-only;
+                               };
+                       };
+               };
+
+               serial@12000 {
+                       status = "okay";
+               };
+
+               i2c@11000 {
+                       status = "okay";
+               };
+
+               ehci@50000 {
+                       status = "okay";
+               };
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               blue-usb {
+                       label = "dir665:blue:usb";
+                       gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+               };
+               blue-internet {
+                       /* Can only be turned on if the Internet
+                        * Ethernet port has Link
+                        */
+                       label = "dir665:blue:internet";
+                       gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+               };
+               amber-internet {
+                       label = "dir665:amber:internet";
+                       gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+               };
+               blue-wifi5g {
+                       label = "dir665:blue:5g";
+                       gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+               };
+               blue-status {
+                       label = "dir665:blue:status";
+                       gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+               };
+               blue-wps {
+                       label = "dir665:blue:wps";
+                       gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+               };
+               amber-status {
+                       label = "dir665:amber:status";
+                       gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
+               };
+               blue-24g {
+                       label = "dir665:blue:24g";
+                       gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reset {
+                       label = "reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
+               };
+               wps {
+                       label = "wps";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       dsa@0 {
+               compatible = "marvell,dsa";
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               dsa,ethernet = <&eth0port>;
+               dsa,mii-bus = <&mdio>;
+
+               switch@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0 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 = "wan";
+                       };
+
+                       port@6 {
+                              reg = <6>;
+                              label = "cpu";
+                       };
+               };
+       };
+};
+
+&mdio {
+       status = "okay";
+};
+
+/* eth0 is connected to a Marvell 88E6171 switch, without a PHY. So set
+ * fixed speed and duplex. */
+&eth0 {
+       status = "okay";
+
+       ethernet0-port@0 {
+               speed = <1000>;
+               duplex = <1>;
+       };
+};
+
+/* eth1 is connected to the switch as well. However DSA only supports a
+ * single CPU port. So leave this port disabled to avoid confusion. */
+
+&eth1 {
+       status = "disabled";
+};
+
+/* There is no battery on the boards, so the RTC does not keep time
+ * when there is no power, making it useless. */
+&rtc {
+       status = "disabled";
+};
index 811e0971fc588a2cc9f59ddbd8f64d51e38acb14..8be5b2e4626e58bb51c95c0b3f060ed2d56a0aca 100644 (file)
 
                        s35390a: s35390a@30 {
                                status = "disabled";
-                               compatible = "ssi,s35390a";
+                               compatible = "sii,s35390a";
                                reg = <0x30>;
                        };
                };
diff --git a/arch/arm/boot/dts/ls1021a-qds.dts b/arch/arm/boot/dts/ls1021a-qds.dts
new file mode 100644 (file)
index 0000000..9c5e16b
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License 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 "ls1021a.dtsi"
+
+/ {
+       model = "LS1021A QDS Board";
+
+       aliases {
+               enet0_rgmii_phy = &rgmii_phy1;
+               enet1_rgmii_phy = &rgmii_phy2;
+               enet2_rgmii_phy = &rgmii_phy3;
+               enet0_sgmii_phy = &sgmii_phy1c;
+               enet1_sgmii_phy = &sgmii_phy1d;
+       };
+};
+
+&dspi0 {
+       bus-num = <0>;
+       status = "okay";
+
+       dspiflash: at45db021d@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "atmel,at45db021d", "atmel,at45", "atmel,dataflash";
+               spi-max-frequency = <16000000>;
+               spi-cpol;
+               spi-cpha;
+               reg = <0>;
+       };
+};
+
+&i2c0 {
+       status = "okay";
+
+       pca9547: mux@77 {
+               reg = <0x77>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               i2c@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0>;
+
+                       ds3232: rtc@68 {
+                               compatible = "dallas,ds3232";
+                               reg = <0x68>;
+                               interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               i2c@2 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x2>;
+
+                       ina220@40 {
+                               compatible = "ti,ina220";
+                               reg = <0x40>;
+                               shunt-resistor = <1000>;
+                       };
+
+                       ina220@41 {
+                               compatible = "ti,ina220";
+                               reg = <0x41>;
+                               shunt-resistor = <1000>;
+                       };
+               };
+
+               i2c@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x3>;
+
+                       eeprom@56 {
+                               compatible = "atmel,24c512";
+                               reg = <0x56>;
+                       };
+
+                       eeprom@57 {
+                               compatible = "atmel,24c512";
+                               reg = <0x57>;
+                       };
+
+                       adt7461a@4c {
+                               compatible = "adi,adt7461a";
+                               reg = <0x4c>;
+                       };
+               };
+       };
+};
+
+&ifc {
+       #address-cells = <2>;
+       #size-cells = <1>;
+       /* NOR, NAND Flashes and FPGA on board */
+       ranges = <0x0 0x0 0x0 0x60000000 0x08000000
+                 0x2 0x0 0x0 0x7e800000 0x00010000
+                 0x3 0x0 0x0 0x7fb00000 0x00000100>;
+       status = "okay";
+
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x8000000>;
+               bank-width = <2>;
+               device-width = <1>;
+       };
+
+       fpga: board-control@3,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               reg = <0x3 0x0 0x0000100>;
+               bank-width = <1>;
+               device-width = <1>;
+               ranges = <0 3 0 0x100>;
+
+               mdio-mux-emi1 {
+                       compatible = "mdio-mux-mmioreg";
+                       mdio-parent-bus = <&mdio0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x54 1>; /* BRDCFG4 */
+                       mux-mask = <0xe0>; /* EMI1[2:0] */
+
+                       /* Onboard PHYs */
+                       ls1021amdio0: mdio@0 {
+                               reg = <0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               rgmii_phy1: ethernet-phy@1 {
+                                       reg = <0x1>;
+                               };
+                       };
+
+                       ls1021amdio1: mdio@20 {
+                               reg = <0x20>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               rgmii_phy2: ethernet-phy@2 {
+                                       reg = <0x2>;
+                               };
+                       };
+
+                       ls1021amdio2: mdio@40 {
+                               reg = <0x40>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               rgmii_phy3: ethernet-phy@3 {
+                                       reg = <0x3>;
+                               };
+                       };
+
+                       ls1021amdio3: mdio@60 {
+                               reg = <0x60>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               sgmii_phy1c: ethernet-phy@1c {
+                                       reg = <0x1c>;
+                               };
+                       };
+
+                       ls1021amdio4: mdio@80 {
+                               reg = <0x80>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               sgmii_phy1d: ethernet-phy@1d {
+                                       reg = <0x1d>;
+                               };
+                       };
+               };
+       };
+};
+
+&lpuart0 {
+       status = "okay";
+};
+
+&mdio0 {
+       tbi0: tbi-phy@8 {
+               reg = <0x8>;
+               device_type = "tbi-phy";
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
new file mode 100644 (file)
index 0000000..a2c591e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License 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 "ls1021a.dtsi"
+
+/ {
+       model = "LS1021A TWR Board";
+
+       aliases {
+               enet2_rgmii_phy = &rgmii_phy1;
+               enet0_sgmii_phy = &sgmii_phy2;
+               enet1_sgmii_phy = &sgmii_phy0;
+       };
+};
+
+&dspi1 {
+       bus-num = <0>;
+       status = "okay";
+
+       dspiflash: s25fl064k@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spansion,s25fl064k";
+               spi-max-frequency = <16000000>;
+               spi-cpol;
+               spi-cpha;
+               reg = <0>;
+       };
+};
+
+&i2c0 {
+       status = "okay";
+};
+
+&i2c1 {
+       status = "okay";
+};
+
+&ifc {
+       #address-cells = <2>;
+       #size-cells = <1>;
+       /* NOR Flash on board */
+       ranges = <0x0 0x0 0x0 0x60000000 0x08000000>;
+       status = "okay";
+
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x8000000>;
+               bank-width = <2>;
+               device-width = <1>;
+       };
+};
+
+&lpuart0 {
+       status = "okay";
+};
+
+&mdio0 {
+       sgmii_phy0: ethernet-phy@0 {
+               reg = <0x0>;
+       };
+       rgmii_phy1: ethernet-phy@1 {
+               reg = <0x1>;
+       };
+       sgmii_phy2: ethernet-phy@2 {
+               reg = <0x2>;
+       };
+       tbi1: tbi-phy@1f {
+               reg = <0x1f>;
+               device_type = "tbi-phy";
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
new file mode 100644 (file)
index 0000000..657da14
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License 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.
+ */
+
+#include "skeleton64.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       compatible = "fsl,ls1021a";
+       interrupt-parent = <&gic>;
+
+       aliases {
+               serial0 = &lpuart0;
+               serial1 = &lpuart1;
+               serial2 = &lpuart2;
+               serial3 = &lpuart3;
+               serial4 = &lpuart4;
+               serial5 = &lpuart5;
+               sysclk = &sysclk;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@f00 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0xf00>;
+                       clocks = <&cluster1_clk>;
+               };
+
+               cpu@f01 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0xf01>;
+                       clocks = <&cluster1_clk>;
+               };
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+
+       pmu {
+               compatible = "arm,cortex-a7-pmu";
+               interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               device_type = "soc";
+               interrupt-parent = <&gic>;
+               ranges;
+
+               gic: interrupt-controller@1400000 {
+                       compatible = "arm,cortex-a7-gic";
+                       #interrupt-cells = <3>;
+                       interrupt-controller;
+                       reg = <0x0 0x1401000 0x0 0x1000>,
+                             <0x0 0x1402000 0x0 0x1000>,
+                             <0x0 0x1404000 0x0 0x2000>,
+                             <0x0 0x1406000 0x0 0x2000>;
+                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+
+               };
+
+               ifc: ifc@1530000 {
+                       compatible = "fsl,ifc", "simple-bus";
+                       reg = <0x0 0x1530000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               dcfg: dcfg@1ee0000 {
+                       compatible = "fsl,ls1021a-dcfg", "syscon";
+                       reg = <0x0 0x1ee0000 0x0 0x10000>;
+                       big-endian;
+               };
+
+               esdhc: esdhc@1560000 {
+                       compatible = "fsl,esdhc";
+                       reg = <0x0 0x1560000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <0>;
+                       voltage-ranges = <1800 1800 3300 3300>;
+                       sdhci,auto-cmd12;
+                       big-endian;
+                       bus-width = <4>;
+                       status = "disabled";
+               };
+
+               scfg: scfg@1570000 {
+                       compatible = "fsl,ls1021a-scfg", "syscon";
+                       reg = <0x0 0x1570000 0x0 0x10000>;
+               };
+
+               clockgen: clocking@1ee1000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x0 0x1ee1000 0x10000>;
+
+                       sysclk: sysclk {
+                               compatible = "fixed-clock";
+                               #clock-cells = <0>;
+                               clock-output-names = "sysclk";
+                       };
+
+                       cga_pll1: pll@800 {
+                               compatible = "fsl,qoriq-core-pll-2.0";
+                               #clock-cells = <1>;
+                               reg = <0x800 0x10>;
+                               clocks = <&sysclk>;
+                               clock-output-names = "cga-pll1", "cga-pll1-div2",
+                                                    "cga-pll1-div4";
+                       };
+
+                       platform_clk: pll@c00 {
+                               compatible = "fsl,qoriq-core-pll-2.0";
+                               #clock-cells = <1>;
+                               reg = <0xc00 0x10>;
+                               clocks = <&sysclk>;
+                               clock-output-names = "platform-clk", "platform-clk-div2";
+                       };
+
+                       cluster1_clk: clk0c0@0 {
+                               compatible = "fsl,qoriq-core-mux-2.0";
+                               #clock-cells = <0>;
+                               reg = <0x0 0x10>;
+                               clock-names = "pll1cga", "pll1cga-div2", "pll1cga-div4";
+                               clocks = <&cga_pll1 0>, <&cga_pll1 1>, <&cga_pll1 2>;
+                               clock-output-names = "cluster1-clk";
+                       };
+               };
+
+               dspi0: dspi@2100000 {
+                       compatible = "fsl,vf610-dspi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2100000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-names = "dspi";
+                       clocks = <&platform_clk 1>;
+                       spi-num-chipselects = <5>;
+                       big-endian;
+                       status = "disabled";
+               };
+
+               dspi1: dspi@2110000 {
+                       compatible = "fsl,vf610-dspi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2110000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-names = "dspi";
+                       clocks = <&platform_clk 1>;
+                       spi-num-chipselects = <5>;
+                       big-endian;
+                       status = "disabled";
+               };
+
+               i2c0: i2c@2180000 {
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2180000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-names = "i2c";
+                       clocks = <&platform_clk 1>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@2190000 {
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2190000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-names = "i2c";
+                       clocks = <&platform_clk 1>;
+                       status = "disabled";
+               };
+
+               i2c2: i2c@21a0000 {
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x21a0000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-names = "i2c";
+                       clocks = <&platform_clk 1>;
+                       status = "disabled";
+               };
+
+               uart0: serial@21c0500 {
+                       compatible = "fsl,16550-FIFO64", "ns16550a";
+                       reg = <0x0 0x21c0500 0x0 0x100>;
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <0>;
+                       fifo-size = <15>;
+                       status = "disabled";
+               };
+
+               uart1: serial@21c0600 {
+                       compatible = "fsl,16550-FIFO64", "ns16550a";
+                       reg = <0x0 0x21c0600 0x0 0x100>;
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <0>;
+                       fifo-size = <15>;
+                       status = "disabled";
+               };
+
+               uart2: serial@21d0500 {
+                       compatible = "fsl,16550-FIFO64", "ns16550a";
+                       reg = <0x0 0x21d0500 0x0 0x100>;
+                       interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <0>;
+                       fifo-size = <15>;
+                       status = "disabled";
+               };
+
+               uart3: serial@21d0600 {
+                       compatible = "fsl,16550-FIFO64", "ns16550a";
+                       reg = <0x0 0x21d0600 0x0 0x100>;
+                       interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <0>;
+                       fifo-size = <15>;
+                       status = "disabled";
+               };
+
+               lpuart0: serial@2950000 {
+                       compatible = "fsl,ls1021a-lpuart";
+                       reg = <0x0 0x2950000 0x0 0x1000>;
+                       interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&sysclk>;
+                       clock-names = "ipg";
+                       status = "disabled";
+               };
+
+               lpuart1: serial@2960000 {
+                       compatible = "fsl,ls1021a-lpuart";
+                       reg = <0x0 0x2960000 0x0 0x1000>;
+                       interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "ipg";
+                       status = "disabled";
+               };
+
+               lpuart2: serial@2970000 {
+                       compatible = "fsl,ls1021a-lpuart";
+                       reg = <0x0 0x2970000 0x0 0x1000>;
+                       interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "ipg";
+                       status = "disabled";
+               };
+
+               lpuart3: serial@2980000 {
+                       compatible = "fsl,ls1021a-lpuart";
+                       reg = <0x0 0x2980000 0x0 0x1000>;
+                       interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "ipg";
+                       status = "disabled";
+               };
+
+               lpuart4: serial@2990000 {
+                       compatible = "fsl,ls1021a-lpuart";
+                       reg = <0x0 0x2990000 0x0 0x1000>;
+                       interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "ipg";
+                       status = "disabled";
+               };
+
+               lpuart5: serial@29a0000 {
+                       compatible = "fsl,ls1021a-lpuart";
+                       reg = <0x0 0x29a0000 0x0 0x1000>;
+                       interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "ipg";
+                       status = "disabled";
+               };
+
+               wdog0: watchdog@2ad0000 {
+                       compatible = "fsl,imx21-wdt";
+                       reg = <0x0 0x2ad0000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "wdog-en";
+                       big-endian;
+               };
+
+               sai1: sai@2b50000 {
+                       compatible = "fsl,vf610-sai";
+                       reg = <0x0 0x2b50000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "sai";
+                       dma-names = "tx", "rx";
+                       dmas = <&edma0 1 47>,
+                              <&edma0 1 46>;
+                       big-endian;
+                       status = "disabled";
+               };
+
+               sai2: sai@2b60000 {
+                       compatible = "fsl,vf610-sai";
+                       reg = <0x0 0x2b60000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&platform_clk 1>;
+                       clock-names = "sai";
+                       dma-names = "tx", "rx";
+                       dmas = <&edma0 1 45>,
+                              <&edma0 1 44>;
+                       big-endian;
+                       status = "disabled";
+               };
+
+               edma0: edma@2c00000 {
+                       #dma-cells = <2>;
+                       compatible = "fsl,vf610-edma";
+                       reg = <0x0 0x2c00000 0x0 0x10000>,
+                             <0x0 0x2c10000 0x0 0x10000>,
+                             <0x0 0x2c20000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "edma-tx", "edma-err";
+                       dma-channels = <32>;
+                       big-endian;
+                       clock-names = "dmamux0", "dmamux1";
+                       clocks = <&platform_clk 1>,
+                                <&platform_clk 1>;
+               };
+
+               mdio0: mdio@2d24000 {
+                       compatible = "gianfar";
+                       device_type = "mdio";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2d24000 0x0 0x4000>;
+               };
+
+               usb@8600000 {
+                       compatible = "fsl-usb2-dr-v2.5", "fsl-usb2-dr";
+                       reg = <0x0 0x8600000 0x0 0x1000>;
+                       interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+                       dr_mode = "host";
+                       phy_type = "ulpi";
+               };
+
+               usb3@3100000 {
+                       compatible = "snps,dwc3";
+                       reg = <0x0 0x3100000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+                       dr_mode = "host";
+               };
+       };
+};
index e6539ea5a711a788bedf28c128ada89b0185e1ed..03bcff87bd27194c43a8d375ae04ae03f69efb2b 100644 (file)
 / {
        interrupt-parent = <&gic>;
 
+       L2: l2-cache-controller@c4200000 {
+               compatible = "arm,pl310-cache";
+               reg = <0xc4200000 0x1000>;
+               cache-unified;
+               cache-level = <2>;
+       };
+
        gic: interrupt-controller@c4301000 {
                compatible = "arm,cortex-a9-gic";
                reg = <0xc4301000 0x1000>,
                        clocks = <&clk81>;
                        status = "disabled";
                };
+
+               i2c_AO: i2c@c8100500 {
+                       compatible = "amlogic,meson6-i2c";
+                       reg = <0xc8100500 0x20>;
+                       interrupts = <0 92 1>;
+                       clocks = <&clk81>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c_A: i2c@c1108500 {
+                       compatible = "amlogic,meson6-i2c";
+                       reg = <0xc1108500 0x20>;
+                       interrupts = <0 21 1>;
+                       clocks = <&clk81>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c_B: i2c@c11087c0 {
+                       compatible = "amlogic,meson6-i2c";
+                       reg = <0xc11087c0 0x20>;
+                       interrupts = <0 128 1>;
+                       clocks = <&clk81>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
        };
 }; /* end of / */
index dc2541faf1ecd218e33d34f9d2a1efa7e98a0778..d7d351a689447ea6449951200c632e19febf3b3b 100644 (file)
@@ -50,7 +50,7 @@
 
 / {
        model = "Geniatech ATV1200";
-       compatible = "geniatech,atv1200";
+       compatible = "geniatech,atv1200", "amlogic,meson6";
 
        aliases {
                serial0 = &uart_AO;
index 4ba49127779f04fe5147f0420560a74ebece70a2..8b33be15af943c81cad3dfd588077503da22c61f 100644 (file)
                cpu@200 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
                        reg = <0x200>;
                };
 
                cpu@201 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
                        reg = <0x201>;
                };
        };
diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi
new file mode 100644 (file)
index 0000000..1f442a7
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2014 Carlo Caione <carlo@caione.org>
+ *
+ * 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.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/include/ "meson.dtsi"
+
+/ {
+       model = "Amlogic Meson8 SoC";
+       compatible = "amlogic,meson8";
+
+       interrupt-parent = <&gic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@200 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
+                       reg = <0x200>;
+               };
+
+               cpu@201 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
+                       reg = <0x201>;
+               };
+
+               cpu@202 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
+                       reg = <0x202>;
+               };
+
+               cpu@203 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       next-level-cache = <&L2>;
+                       reg = <0x203>;
+               };
+       };
+
+       clk81: clk@0 {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <141666666>;
+       };
+}; /* end of / */
diff --git a/arch/arm/boot/dts/mt6592-evb.dts b/arch/arm/boot/dts/mt6592-evb.dts
new file mode 100644 (file)
index 0000000..b57237e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Howard Chen <ibanezchen@gmail.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.
+ */
+
+/dts-v1/;
+#include "mt6592.dtsi"
+
+/ {
+       model = "mt6592 evb";
+       compatible = "mediatek,mt6592-evb", "mediatek,mt6592";
+
+       memory {
+               reg = <0x80000000 0x40000000>;
+       };
+};
+
diff --git a/arch/arm/boot/dts/mt6592.dtsi b/arch/arm/boot/dts/mt6592.dtsi
new file mode 100644 (file)
index 0000000..31e5a09
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Howard Chen <ibanezchen@gmail.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 <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton.dtsi"
+
+/ {
+       compatible = "mediatek,mt6592";
+       interrupt-parent = <&gic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x0>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x1>;
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x2>;
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x3>;
+               };
+               cpu@4 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x4>;
+               };
+               cpu@5 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x5>;
+               };
+               cpu@6 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x6>;
+               };
+               cpu@7 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x7>;
+               };
+       };
+
+       system_clk: dummy13m {
+               compatible = "fixed-clock";
+               clock-frequency = <13000000>;
+               #clock-cells = <0>;
+       };
+
+       rtc_clk: dummy32k {
+               compatible = "fixed-clock";
+               clock-frequency = <32000>;
+               #clock-cells = <0>;
+       };
+
+       timer: timer@10008000 {
+               compatible = "mediatek,mt6577-timer";
+               reg = <0x10008000 0x80>;
+               interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&system_clk>, <&rtc_clk>;
+               clock-names = "system-clk", "rtc-clk";
+       };
+
+       gic: interrupt-controller@10211000 {
+               compatible = "arm,cortex-a7-gic";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x10211000 0x1000>,
+                     <0x10212000 0x1000>;
+       };
+
+};
+
diff --git a/arch/arm/boot/dts/mt8127-moose.dts b/arch/arm/boot/dts/mt8127-moose.dts
new file mode 100644 (file)
index 0000000..13cba0e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Joe.C <yingjoe.chen@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.
+ */
+
+/dts-v1/;
+#include "mt8127.dtsi"
+
+/ {
+       model = "MediaTek MT8127 Moose Board";
+       compatible = "mediatek,mt8127-moose", "mediatek,mt8127";
+
+       memory {
+               reg = <0 0x80000000 0 0x40000000>;
+       };
+};
diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi
new file mode 100644 (file)
index 0000000..b24c0a2
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Joe.C <yingjoe.chen@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.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton64.dtsi"
+
+/ {
+       compatible = "mediatek,mt8127";
+       interrupt-parent = <&gic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x0>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x1>;
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x2>;
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x3>;
+               };
+
+       };
+
+       clocks {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               compatible = "simple-bus";
+               ranges;
+
+               system_clk: dummy13m {
+                       compatible = "fixed-clock";
+                       clock-frequency = <13000000>;
+                       #clock-cells = <0>;
+               };
+
+               rtc_clk: dummy32k {
+                       compatible = "fixed-clock";
+                       clock-frequency = <32000>;
+                       #clock-cells = <0>;
+               };
+       };
+
+       soc {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               compatible = "simple-bus";
+               ranges;
+
+               timer: timer@10008000 {
+                       compatible = "mediatek,mt8127-timer",
+                                       "mediatek,mt6577-timer";
+                       reg = <0 0x10008000 0 0x80>;
+                       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&system_clk>, <&rtc_clk>;
+                       clock-names = "system-clk", "rtc-clk";
+               };
+
+               gic: interrupt-controller@10211000 {
+                       compatible = "arm,cortex-a7-gic";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       reg = <0 0x10211000 0 0x1000>,
+                             <0 0x10212000 0 0x1000>,
+                             <0 0x10214000 0 0x2000>,
+                             <0 0x10216000 0 0x2000>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts
new file mode 100644 (file)
index 0000000..a5adf97
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Joe.C <yingjoe.chen@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.
+ */
+
+/dts-v1/;
+#include "mt8135.dtsi"
+
+/ {
+       model = "MediaTek MT8135 evaluation board";
+       compatible = "mediatek,mt8135-evbp1", "mediatek,mt8135";
+
+       memory {
+               reg = <0 0x80000000 0 0x40000000>;
+       };
+};
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
new file mode 100644 (file)
index 0000000..7d56a98
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Joe.C <yingjoe.chen@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.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton64.dtsi"
+
+/ {
+       compatible = "mediatek,mt8135";
+       interrupt-parent = <&gic>;
+
+       cpu-map {
+               cluster0 {
+                       core0 {
+                               cpu = <&cpu0>;
+                       };
+                       core1 {
+                               cpu = <&cpu1>;
+                       };
+               };
+
+               cluster1 {
+                       core0 {
+                               cpu = <&cpu2>;
+                       };
+                       core1 {
+                               cpu = <&cpu3>;
+                       };
+               };
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x000>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x001>;
+               };
+
+               cpu2: cpu@100 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a15";
+                       reg = <0x100>;
+               };
+
+               cpu3: cpu@101 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a15";
+                       reg = <0x101>;
+               };
+       };
+
+       clocks {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               compatible = "simple-bus";
+               ranges;
+
+               system_clk: dummy13m {
+                       compatible = "fixed-clock";
+                       clock-frequency = <13000000>;
+                       #clock-cells = <0>;
+               };
+
+               rtc_clk: dummy32k {
+                       compatible = "fixed-clock";
+                       clock-frequency = <32000>;
+                       #clock-cells = <0>;
+               };
+       };
+
+       soc {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               compatible = "simple-bus";
+               ranges;
+
+               timer: timer@10008000 {
+                       compatible = "mediatek,mt8135-timer",
+                                       "mediatek,mt6577-timer";
+                       reg = <0 0x10008000 0 0x80>;
+                       interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&system_clk>, <&rtc_clk>;
+                       clock-names = "system-clk", "rtc-clk";
+               };
+
+               gic: interrupt-controller@10211000 {
+                       compatible = "arm,cortex-a15-gic";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       reg = <0 0x10211000 0 0x1000>,
+                             <0 0x10212000 0 0x1000>,
+                             <0 0x10214000 0 0x2000>,
+                             <0 0x10216000 0 0x2000>;
+               };
+       };
+};
index 521c587acaee9f679ab6f9200c5f8be8eee240e9..445fafc732543a15bc50b0a39a362b63ebc325ab 100644 (file)
        ethernet@gpmc {
                compatible = "smsc,lan9221", "smsc,lan9115";
                bank-width = <2>;
-               gpmc,mux-add-data;
-               gpmc,cs-on-ns = <1>;
-               gpmc,cs-rd-off-ns = <180>;
-               gpmc,cs-wr-off-ns = <180>;
-               gpmc,adv-rd-off-ns = <18>;
-               gpmc,adv-wr-off-ns = <48>;
-               gpmc,oe-on-ns = <54>;
-               gpmc,oe-off-ns = <168>;
-               gpmc,we-on-ns = <54>;
-               gpmc,we-off-ns = <168>;
-               gpmc,rd-cycle-ns = <186>;
-               gpmc,wr-cycle-ns = <186>;
-               gpmc,access-ns = <144>;
-               gpmc,page-burst-access-ns = <24>;
-               gpmc,bus-turnaround-ns = <90>;
-               gpmc,cycle2cycle-delay-ns = <90>;
-               gpmc,cycle2cycle-samecsen;
-               gpmc,cycle2cycle-diffcsen;
+               gpmc,device-width = <1>;
+               gpmc,cycle2cycle-samecsen = <1>;
+               gpmc,cycle2cycle-diffcsen = <1>;
+               gpmc,cs-on-ns = <5>;
+               gpmc,cs-rd-off-ns = <150>;
+               gpmc,cs-wr-off-ns = <150>;
+               gpmc,adv-on-ns = <0>;
+               gpmc,adv-rd-off-ns = <15>;
+               gpmc,adv-wr-off-ns = <40>;
+               gpmc,oe-on-ns = <45>;
+               gpmc,oe-off-ns = <140>;
+               gpmc,we-on-ns = <45>;
+               gpmc,we-off-ns = <140>;
+               gpmc,rd-cycle-ns = <155>;
+               gpmc,wr-cycle-ns = <155>;
+               gpmc,access-ns = <120>;
+               gpmc,page-burst-access-ns = <20>;
+               gpmc,bus-turnaround-ns = <75>;
+               gpmc,cycle2cycle-delay-ns = <75>;
+               gpmc,wait-monitoring-ns = <0>;
+               gpmc,clk-activation-ns = <0>;
+               gpmc,wr-data-mux-bus-ns = <0>;
+               gpmc,wr-access-ns = <0>;
                vddvario-supply = <&vddvario>;
                vdd33a-supply = <&vdd33a>;
                reg-io-width = <4>;
index 68221fab978d40a2e92c5b089e0e4fd1494e39e4..46ef3e443861982ee840bf1091079ae7bd227ccd 100644 (file)
@@ -5,7 +5,7 @@
 #include "omap-gpmc-smsc911x.dtsi"
 
 &gpmc {
-       ranges = <3 0 0x10000000 0x00000400>,
+       ranges = <3 0 0x10000000 0x1000000>,    /* CS3: 16MB for UART */
                 <7 0 0x2c000000 0x01000000>;
 
        /*
         */
        uart@3,0 {
                compatible = "ns16550a";
-               reg = <3 0 0x100>;
+               reg = <3 0 8>;  /* CS3, offset 0, IO size 8 */
+               bank-width = <2>;
+               reg-shift = <1>;
+               reg-io-width = <1>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <6 IRQ_TYPE_EDGE_RISING>;  /* gpio102 */
+               clock-frequency = <1843200>;
+               current-speed = <115200>;
+               gpmc,mux-add-data = <0>;
+               gpmc,device-width = <1>;
+               gpmc,wait-pin = <1>;
+               gpmc,cycle2cycle-samecsen = <1>;
+               gpmc,cycle2cycle-diffcsen = <1>;
+               gpmc,cs-on-ns = <5>;
+               gpmc,cs-rd-off-ns = <155>;
+               gpmc,cs-wr-off-ns = <155>;
+               gpmc,adv-on-ns = <15>;
+               gpmc,adv-rd-off-ns = <40>;
+               gpmc,adv-wr-off-ns = <40>;
+               gpmc,oe-on-ns = <45>;
+               gpmc,oe-off-ns = <145>;
+               gpmc,we-on-ns = <45>;
+               gpmc,we-off-ns = <145>;
+               gpmc,rd-cycle-ns = <155>;
+               gpmc,wr-cycle-ns = <155>;
+               gpmc,access-ns = <145>;
+               gpmc,page-burst-access-ns = <20>;
+               gpmc,bus-turnaround-ns = <20>;
+               gpmc,cycle2cycle-delay-ns = <20>;
+               gpmc,wait-monitoring-ns = <0>;
+               gpmc,clk-activation-ns = <0>;
+               gpmc,wr-data-mux-bus-ns = <45>;
+               gpmc,wr-access-ns = <145>;
+       };
+       uart@3,1 {
+               compatible = "ns16550a";
+               reg = <3 0x100 8>;      /* CS3, offset 0x100, IO size 8 */
+               bank-width = <2>;
+               reg-shift = <1>;
+               reg-io-width = <1>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <6 IRQ_TYPE_EDGE_RISING>;  /* gpio102 */
+               clock-frequency = <1843200>;
+               current-speed = <115200>;
+       };
+       uart@3,2 {
+               compatible = "ns16550a";
+               reg = <3 0x200 8>;      /* CS3, offset 0x200, IO size 8 */
+               bank-width = <2>;
+               reg-shift = <1>;
+               reg-io-width = <1>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <6 IRQ_TYPE_EDGE_RISING>;  /* gpio102 */
+               clock-frequency = <1843200>;
+               current-speed = <115200>;
+       };
+       uart@3,3 {
+               compatible = "ns16550a";
+               reg = <3 0x300 8>;      /* CS3, offset 0x300, IO size 8 */
                bank-width = <2>;
                reg-shift = <1>;
                reg-io-width = <1>;
index 24c50db2a478cf2a7e55865af10577db6fc5f14d..c9f1e93a95aec34e86f6ee5bfa1cd78ae04792d0 100644 (file)
 };
 
 &gpmc {
-       ranges = <0 0 0x04000000 0x10000000>;
+       ranges = <0 0 0x04000000 0x1000000>;    /* CS0: 16MB for OneNAND */
 
        /* gpio-irq for dma: 26 */
 
        onenand@0,0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               reg = <0 0 0x10000000>;
+               reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
 
                gpmc,sync-read;
                gpmc,burst-length = <16>;
index ae89aad01595890511f241c5dd932505e24fa78e..e2b2e93d7b6160f364bcb4832cc593c09f9627ac 100644 (file)
                        interrupts = <26>, <34>;
                        interrupt-names = "dsp", "iva";
                        ti,hwmods = "mailbox";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <6>;
                        mbox_dsp: dsp {
index 2c90d29b4cad7f166a7961bd882b59e19ff1cc64..05eca2e4430f1032b92caa0bd0651094e552a9f3 100644 (file)
                interrupts = <21 IRQ_TYPE_LEVEL_LOW>;   /* gpio149 */
                reg = <5 0x300 0xf>;
                bank-width = <2>;
-               gpmc,mux-add-data;
-        };
+               gpmc,sync-clk-ps = <0>;
+               gpmc,mux-add-data = <2>;
+               gpmc,device-width = <1>;
+               gpmc,cycle2cycle-samecsen = <1>;
+               gpmc,cycle2cycle-diffcsen = <1>;
+               gpmc,cs-on-ns = <7>;
+               gpmc,cs-rd-off-ns = <233>;
+               gpmc,cs-wr-off-ns = <233>;
+               gpmc,adv-on-ns = <22>;
+               gpmc,adv-rd-off-ns = <60>;
+               gpmc,adv-wr-off-ns = <60>;
+               gpmc,oe-on-ns = <67>;
+               gpmc,oe-off-ns = <210>;
+               gpmc,we-on-ns = <67>;
+               gpmc,we-off-ns = <210>;
+               gpmc,rd-cycle-ns = <233>;
+               gpmc,wr-cycle-ns = <233>;
+               gpmc,access-ns = <233>;
+               gpmc,page-burst-access-ns = <30>;
+               gpmc,bus-turnaround-ns = <30>;
+               gpmc,cycle2cycle-delay-ns = <30>;
+               gpmc,wait-monitoring-ns = <0>;
+               gpmc,clk-activation-ns = <0>;
+               gpmc,wr-data-mux-bus-ns = <0>;
+               gpmc,wr-access-ns = <0>;
+       };
 };
 
index b56d71611026571d5486badcadce45749b97a1a9..0dc8de2782b1871772150b3a62ab7a92685da56a 100644 (file)
                        reg = <0x48094000 0x200>;
                        interrupts = <26>;
                        ti,hwmods = "mailbox";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <6>;
                        mbox_dsp: dsp {
index d00502f4fd9b1562a88b5e7626fdebb10319bb0f..0ab748cf7749f18d90ad225a5d0aabac564fc53f 100644 (file)
        bus-width = <4>;
        cap-power-off-card;
 };
+
+&dss {
+       status = "ok";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &dss_dpi_pins_common
+               &dss_dpi_pins_cm_t35x
+       >;
+};
+
index d1458496520e7ec49ec278cde6d1ff32cbcc7008..8dd14fcf68258db40e852e089dfff47e7045e697 100644 (file)
        bus-width = <4>;
        cap-power-off-card;
 };
+
+&dss {
+       status = "ok";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &dss_dpi_pins_common
+               &dss_dpi_pins_cm_t35x
+       >;
+};
+
index b3f9a50b3bc8339d269307001f6cd7563205b79f..46eadb21b5ef5e97882e581f6e29f33bda2cd209 100644 (file)
        };
 };
 
+&omap3_pmx_wkup {
+       dss_dpi_pins_cm_t3730: pinmux_dss_dpi_pins_cm_t3730 {
+               pinctrl-single,pins = <
+                       OMAP3_WKUP_IOPAD(0x2a08, PIN_OUTPUT | MUX_MODE3)   /* sys_boot0.dss_data18 */
+                       OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE3)   /* sys_boot1.dss_data19 */
+                       OMAP3_WKUP_IOPAD(0x2a10, PIN_OUTPUT | MUX_MODE3)   /* sys_boot3.dss_data20 */
+                       OMAP3_WKUP_IOPAD(0x2a12, PIN_OUTPUT | MUX_MODE3)   /* sys_boot4.dss_data21 */
+                       OMAP3_WKUP_IOPAD(0x2a14, PIN_OUTPUT | MUX_MODE3)   /* sys_boot5.dss_data22 */
+                       OMAP3_WKUP_IOPAD(0x2a16, PIN_OUTPUT | MUX_MODE3)   /* sys_boot6.dss_data23 */
+               >;
+       };
+};
+
 &omap3_pmx_core {
 
        mmc2_pins: pinmux_mmc2_pins {
        bus-width = <4>;
        cap-power-off-card;
 };
+
+&dss {
+       status = "ok";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &dss_dpi_pins_common
+               &dss_dpi_pins_cm_t3730
+       >;
+};
+
index c671a2299ea8efa64b21a1f31bbdcf7903a642d0..6ea6d460db3090de2e891828bc8366933e003a56 100644 (file)
                compatible = "usb-nop-xceiv";
                vcc-supply = <&hsusb2_power>;
        };
+
+       ads7846reg: ads7846-reg {
+               compatible = "regulator-fixed";
+               regulator-name = "ads7846-reg";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       tv0: connector@1 {
+               compatible = "svideo-connector";
+               label = "tv";
+
+               port {
+                       tv_connector_in: endpoint {
+                               remote-endpoint = <&venc_out>;
+                       };
+               };
+       };
 };
 
 &omap3_pmx_core {
                        OMAP3_CORE1_IOPAD(0x21e2, PIN_OUTPUT | MUX_MODE4)       /* sys_clkout2.gpio_186 */
                >;
        };
+
+       dss_dpi_pins_common: pinmux_dss_dpi_pins_common {
+               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(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 */
+               >;
+       };
+
+       dss_dpi_pins_cm_t35x: pinmux_dss_dpi_pins_cm_t35x {
+               pinctrl-single,pins = <
+                       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 */
+               >;
+       };
+
+       ads7846_pins: pinmux_ads7846_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x20ba, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_ncs6.gpio_57 */
+               >;
+       };
+
+       mcspi1_pins: pinmux_mcspi1_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21c8, PIN_INPUT | MUX_MODE0)        /* mcspi1_clk */
+                       OMAP3_CORE1_IOPAD(0x21ca, PIN_INPUT | MUX_MODE0)        /* mcspi1_simo */
+                       OMAP3_CORE1_IOPAD(0x21cc, PIN_INPUT | MUX_MODE0)        /* mcspi1_somi */
+                       OMAP3_CORE1_IOPAD(0x21ce, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcspi1_cs0 */
+               >;
+       };
+
+       i2c1_pins: pinmux_i2c1_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_scl */
+                       OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c1_sda */
+               >;
+       };
+
+       mcbsp2_pins: pinmux_mcbsp2_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0)        /* mcbsp2_fsx */
+                       OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0)        /* mcbsp2_clkx */
+                       OMAP3_CORE1_IOPAD(0x2140, PIN_INPUT | MUX_MODE0)        /* mcbsp2_dr */
+                       OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0)       /* mcbsp2_dx */
+               >;
+       };
 };
 
 &uart3 {
 };
 
 &i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+
        clock-frequency = <400000>;
+
+       at24@50 {
+               compatible = "at24,24c02";
+               pagesize = <16>;
+               reg = <0x50>;
+       };
 };
 
 &i2c3 {
        clock-frequency = <400000>;
 };
+
 &usbhshost {
        port1-mode = "ehci-phy";
        port2-mode = "ehci-phy";
 &usbhsehci {
        phys = <&hsusb1_phy &hsusb2_phy>;
 };
+
+&mcspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcspi1_pins>;
+
+       /* touch controller */
+       ads7846@0 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&ads7846_pins>;
+
+               compatible = "ti,ads7846";
+               vcc-supply = <&ads7846reg>;
+
+               reg = <0>;                      /* CS0 */
+               spi-max-frequency = <1500000>;
+
+               interrupt-parent = <&gpio2>;
+               interrupts = <25 0>;            /* gpio_57 */
+               pendown-gpio = <&gpio2 25 0>;
+
+               ti,x-min = /bits/ 16 <0x0>;
+               ti,x-max = /bits/ 16 <0x0fff>;
+               ti,y-min = /bits/ 16 <0x0>;
+               ti,y-max = /bits/ 16 <0x0fff>;
+
+               ti,x-plate-ohms = /bits/ 16 <180>;
+               ti,pressure-max = /bits/ 16 <255>;
+
+               ti,debounce-max = /bits/ 16 <30>;
+               ti,debounce-tol = /bits/ 16 <10>;
+               ti,debounce-rep = /bits/ 16 <1>;
+
+               linux,wakeup;
+       };
+};
+
+&venc {
+       status = "ok";
+
+       port {
+               venc_out: endpoint {
+                       remote-endpoint = <&tv_connector_in>;
+                       ti,channels = <2>;
+               };
+       };
+};
+
+&mcbsp2 {
+       status = "ok";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcbsp2_pins>;
+};
index 25ba08331d8852e6701c96a4b9e8e54def19f0d8..9a4a3ab9af78707a03097832a34ff5722ab2c794 100644 (file)
                        cpu0-supply = <&vcc>;
                };
        };
+
+       sound {
+               compatible = "ti,omap-twl4030";
+               ti,model = "cm-t35";
+
+               ti,mcbsp = <&mcbsp2>;
+               ti,codec = <&twl_audio>;
+       };
 };
 
 &omap3_pmx_core {
                reg = <0x48>;
                interrupts = <7>; /* SYS_NIRQ cascaded to intc */
                interrupt-parent = <&intc>;
+
+               twl_audio: audio {
+                       compatible = "ti,twl4030-audio";
+                       codec {
+                       };
+               };
        };
 };
 
 #include "twl4030.dtsi"
 #include "twl4030_omap3.dtsi"
+#include <dt-bindings/input/input.h>
+
+&venc {
+       vdda-supply = <&vdac>;
+};
 
 &mmc1 {
        vmmc-supply = <&vmmc1>;
        ti,pullups = <0x000001>;
 };
 
+&twl_keypad {
+       linux,keymap = <
+                               MATRIX_KEY(0x00, 0x01, KEY_A)
+                               MATRIX_KEY(0x00, 0x02, KEY_B)
+                               MATRIX_KEY(0x00, 0x03, KEY_LEFT)
+
+                               MATRIX_KEY(0x01, 0x01, KEY_UP)
+                               MATRIX_KEY(0x01, 0x02, KEY_ENTER)
+                               MATRIX_KEY(0x01, 0x03, KEY_DOWN)
+
+                               MATRIX_KEY(0x02, 0x01, KEY_RIGHT)
+                               MATRIX_KEY(0x02, 0x02, KEY_C)
+                               MATRIX_KEY(0x02, 0x03, KEY_D)
+                       >;
+};
+
 &hsusb1_phy {
        reset-gpios = <&twl_gpio 6 GPIO_ACTIVE_LOW>;
 };
index da402f0fdab4861bf9b775b247cabaac192f8777..169037e5ff53cd83da50cfb16e70edfcc2c7d6ed 100644 (file)
 };
 
 &gpmc {
-       ranges = <0 0 0x30000000 0x04>;       /* CS0: NAND */
+       ranges = <0 0 0x30000000 0x1000000>;       /* CS0: 16MB for NAND */
 
        nand@0,0 {
-               reg = <0 0 0>; /* CS0, offset 0 */
+               reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
                nand-bus-width = <16>;
 
                gpmc,sync-clk-ps = <0>;
index a8bd4349c7d2b6a9445208ce403ff303b783d4a0..16e8ce350ddaae4f4bedc3d86f9d0418e4852f87 100644 (file)
 };
 
 &gpmc {
-       ranges = <0 0 0x00000000 0x20000000>,
+       ranges = <0 0 0x00000000 0x1000000>,    /* CS0: 16MB for NAND */
                 <5 0 0x2c000000 0x01000000>;
 
        nand@0,0 {
                linux,mtd-name= "hynix,h8kds0un0mer-4em";
-               reg = <0 0 0>;
+               reg = <0 0 4>;  /* CS0, offset 0, IO size 4 */
                nand-bus-width = <16>;
+               gpmc,device-width = <2>;
                ti,nand-ecc-opt = "bch8";
 
                gpmc,sync-clk-ps = <0>;
index c8747c7f1cc8fb66404639e1eb24a61d28e4e1de..127f3e7c10c4fcade6d95a201ffeccf4b66d9297 100644 (file)
@@ -2,6 +2,7 @@
  * Common support for omap3 EVM boards
  */
 
+#include <dt-bindings/input/input.h>
 #include "omap-gpmc-smsc911x.dtsi"
 
 / {
        ti,use-leds;
 };
 
+&twl_keypad {
+       linux,keymap = <
+                       MATRIX_KEY(2, 2, KEY_1)
+                       MATRIX_KEY(1, 1, KEY_2)
+                       MATRIX_KEY(0, 0, KEY_3)
+                       MATRIX_KEY(3, 2, KEY_4)
+                       MATRIX_KEY(2, 1, KEY_5)
+                       MATRIX_KEY(1, 0, KEY_6)
+                       MATRIX_KEY(1, 3, KEY_7)
+                       MATRIX_KEY(3, 1, KEY_8)
+                       MATRIX_KEY(2, 0, KEY_9)
+                       MATRIX_KEY(2, 3, KEY_KPASTERISK)
+                       MATRIX_KEY(0, 2, KEY_0)
+                       MATRIX_KEY(3, 0, KEY_KPDOT)
+                       /* s4 not wired */
+                       MATRIX_KEY(1, 2, KEY_BACKSPACE)
+                       MATRIX_KEY(0, 1, KEY_ENTER)
+                       >;
+};
+
 &usb_otg_hs {
        interface-type = <0>;
        usb-phy = <&usb2_phy>;
index fd34f913ace311edd8624692154366eb79504062..655d6e920a863a9436dd9814d88be0e37d9b3cfa 100644 (file)
 
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
-                       0x152 (PIN_INPUT | MUX_MODE0)           /* uart1_rx.uart1_rx */
-                       0x14c (PIN_OUTPUT |MUX_MODE0)           /* uart1_tx.uart1_tx */
+                       OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE0)                /* uart1_rx.uart1_rx */
+                       OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0)               /* uart1_tx.uart1_tx */
                >;
        };
 
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       0x14a (PIN_INPUT | MUX_MODE0)           /* uart2_rx.uart2_rx */
-                       0x148 (PIN_OUTPUT | MUX_MODE0)          /* uart2_tx.uart2_tx */
+                       OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)                /* uart2_rx.uart2_rx */
+                       OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)               /* uart2_tx.uart2_tx */
                >;
        };
 
        uart3_pins: pinmux_uart3_pins {
                pinctrl-single,pins = <
-                       0x16e (PIN_INPUT | MUX_MODE0)           /* uart3_rx.uart3_rx */
-                       0x170 (PIN_OUTPUT | MUX_MODE0)          /* uart3_tx.uart3_tx */
+                       OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0)                /* uart3_rx.uart3_rx */
+                       OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)               /* uart3_tx.uart3_tx */
                >;
        };
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       0x114 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_clk.sdmmc1_clk */
-                       0x116 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_cmd.sdmmc1_cmd */
-                       0x118 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat0.sdmmc1_dat0 */
-                       0x11a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat1.sdmmc1_dat1 */
-                       0x11c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat2.sdmmc1_dat2 */
-                       0x11e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_dat3.sdmmc1_dat3 */
+                       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 */
                >;
        };
 
        dss_dpi_pins: pinmux_dss_dpi_pins {
                pinctrl-single,pins = <
-                       0x0a4 (PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
-                       0x0a6 (PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
-                       0x0a8 (PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
-                       0x0aa (PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
-                       0x0ac (PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
-                       0x0ae (PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
-                       0x0b0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
-                       0x0b2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
-                       0x0b4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
-                       0x0b6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
-                       0x0b8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
-                       0x0ba (PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
-                       0x0bc (PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
-                       0x0be (PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
-                       0x0c0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
-                       0x0c2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
-                       0x0c4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
-                       0x0c6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
-                       0x0c8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
-                       0x0ca (PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
-                       0x0cc (PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
-                       0x0ce (PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
-                       0x0d0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
-                       0x0d2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
-                       0x0d4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
-                       0x0d6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
-                       0x0d8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
-                       0x0da (PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
-               >;
+                       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 */
+               >;
        };
 };
 
 };
 
 &gpmc {
-       ranges = <0 0 0x30000000 0x04>; /* CS0: NAND */
+       ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */
 
        nand@0,0 {
-               reg = <0 0 0>; /* CS0, offset 0 */
+               reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
                nand-bus-width = <16>;
                ti,nand-ecc-opt = "bch8";
 
index e2d163bf061975bff9ac5a6e83ecf6bf4ef98ed3..8a63ad2286aa26eaadf6162a12a98e24437acf28 100644 (file)
                regulator-always-on;
        };
 
-       lbee1usjyc_vmmc: lbee1usjyc_vmmc {
-               pinctrl-names = "default";
-               pinctrl-0 = <&lbee1usjyc_pins>;
-               compatible = "regulator-fixed";
-               regulator-name = "regulator-lbee1usjyc";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;    /* gpio_138 WIFI_PDN */
-               startup-delay-us = <10000>;
-               enable-active-high;
-               vin-supply = <&vdd33>;
-       };
 };
 
 &omap3_pmx_core {
                >;
        };
 
-       uart2_pins: pinmux_uart2_pins {
-               pinctrl-single,pins = <
-                       0x14a (PIN_INPUT | MUX_MODE0)           /* uart2_rx.uart2_rx */
-                       0x148 (PIN_OUTPUT | MUX_MODE0)          /* uart2_tx.uart2_tx */
-               >;
-       };
-
        uart3_pins: pinmux_uart3_pins {
                pinctrl-single,pins = <
                        0x16e (PIN_INPUT | MUX_MODE0)           /* uart3_rx.uart3_rx */
                >;
        };
 
-       /* WiFi/BT combo */
-       lbee1usjyc_pins: pinmux_lbee1usjyc_pins {
-               pinctrl-single,pins = <
-                       0x136 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat5.gpio_137 */
-                       0x138 (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat6.gpio_138 */
-                       0x13a (PIN_OUTPUT | MUX_MODE4)  /* sdmmc2_dat7.gpio_139 */
-               >;
-       };
-
        mcbsp2_pins: pinmux_mcbsp2_pins {
                pinctrl-single,pins = <
                        0x10c (PIN_INPUT | MUX_MODE0)           /* mcbsp2_fsx.mcbsp2_fsx */
                >;
        };
 
-       i2c2_pins: pinmux_i2c2_pins {
-               pinctrl-single,pins = <
-                       0x18e (PIN_INPUT | MUX_MODE0)   /* i2c2_scl.i2c2_scl */
-                       0x190 (PIN_INPUT | MUX_MODE0)   /* i2c2_sda.i2c2_sda */
-               >;
-       };
-
        i2c3_pins: pinmux_i2c3_pins {
                pinctrl-single,pins = <
                        0x192 (PIN_INPUT | MUX_MODE0)   /* i2c3_scl.i2c3_scl */
        };
 };
 
+&gpmc {
+       nand@0,0 {
+               linux,mtd-name= "micron,mt29c4g96maz";
+               reg = <0 0 4>;  /* CS0, offset 0, IO size 4 */
+               nand-bus-width = <16>;
+               gpmc,device-width = <2>;
+               ti,nand-ecc-opt = "bch8";
+
+               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>;
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               partition@0 {
+                       label = "SPL";
+                       reg = <0 0x100000>;
+               };
+               partition@80000 {
+                       label = "U-Boot";
+                       reg = <0x100000 0x180000>;
+               };
+               partition@1c0000 {
+                       label = "Environment";
+                       reg = <0x280000 0x100000>;
+               };
+               partition@280000 {
+                       label = "Kernel";
+                       reg = <0x380000 0x300000>;
+               };
+               partition@780000 {
+                       label = "Filesystem";
+                       reg = <0x680000 0x1f980000>;
+               };
+       };
+};
+
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c1_pins>;
 #include "twl4030.dtsi"
 #include "twl4030_omap3.dtsi"
 
-&i2c2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&i2c2_pins>;
-       clock-frequency = <400000>;
-};
-
 &i2c3 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c3_pins>;
       bus-width = <4>;
 };
 
-&mmc2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&mmc2_pins>;
-       vmmc-supply = <&lbee1usjyc_vmmc>;
-       bus-width = <4>;
-       non-removable;
-};
-
 &mmc3 {
        status = "disabled";
 };
        pinctrl-0 = <&uart1_pins>;
 };
 
-&uart2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart2_pins>;
-};
-
 &uart3 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart3_pins>;
diff --git a/arch/arm/boot/dts/omap3-igep0020-common.dtsi b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
new file mode 100644 (file)
index 0000000..e458c21
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Common Device Tree Source for IGEPv2
+ *
+ * Copyright (C) 2014 Javier Martinez Canillas <javier@collabora.co.uk>
+ * Copyright (C) 2014 Enric Balletbo i Serra <eballetbo@gmail.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 "omap3-igep.dtsi"
+#include "omap-gpmc-smsc9221.dtsi"
+
+/ {
+
+       leds {
+               pinctrl-names = "default";
+               pinctrl-0 = <&leds_pins>;
+               compatible = "gpio-leds";
+
+               boot {
+                        label = "omap3:green:boot";
+                        gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+                        default-state = "on";
+               };
+
+               user0 {
+                        label = "omap3:red:user0";
+                        gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+                        default-state = "off";
+               };
+
+               user1 {
+                        label = "omap3:red:user1";
+                        gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+                        default-state = "off";
+               };
+
+               user2 {
+                       label = "omap3:green:user1";
+                       gpios = <&twl_gpio 19 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       /* HS USB Port 1 Power */
+       hsusb1_power: hsusb1_power_reg {
+               compatible = "regulator-fixed";
+               regulator-name = "hsusb1_vbus";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&twl_gpio 18 GPIO_ACTIVE_LOW>;  /* GPIO LEDA */
+               startup-delay-us = <70000>;
+       };
+
+       /* HS USB Host PHY on PORT 1 */
+       hsusb1_phy: hsusb1_phy {
+               compatible = "usb-nop-xceiv";
+               reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; /* gpio_24 */
+               vcc-supply = <&hsusb1_power>;
+       };
+
+       tfp410: encoder@0 {
+               compatible = "ti,tfp410";
+               powerdown-gpios = <&gpio6 10 GPIO_ACTIVE_LOW>; /* gpio_170 */
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
+                               tfp410_in: endpoint@0 {
+                                       remote-endpoint = <&dpi_out>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+
+                               tfp410_out: endpoint@0 {
+                                       remote-endpoint = <&dvi_connector_in>;
+                               };
+                       };
+               };
+       };
+
+       dvi0: connector@0 {
+               compatible = "dvi-connector";
+               label = "dvi";
+
+               digital;
+
+               ddc-i2c-bus = <&i2c3>;
+
+               port {
+                       dvi_connector_in: endpoint {
+                               remote-endpoint = <&tfp410_out>;
+                       };
+               };
+       };
+};
+
+&omap3_pmx_core {
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &tfp410_pins
+               &dss_dpi_pins
+       >;
+
+       tfp410_pins: pinmux_tfp410_pins {
+               pinctrl-single,pins = <
+                       0x196 (PIN_OUTPUT | MUX_MODE4)   /* hdq_sio.gpio_170 */
+               >;
+       };
+
+       dss_dpi_pins: pinmux_dss_dpi_pins {
+               pinctrl-single,pins = <
+                       0x0a4 (PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
+                       0x0a6 (PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
+                       0x0a8 (PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
+                       0x0aa (PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
+                       0x0ac (PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
+                       0x0ae (PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
+                       0x0b0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
+                       0x0b2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
+                       0x0b4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
+                       0x0b6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
+                       0x0b8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
+                       0x0ba (PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
+                       0x0bc (PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
+                       0x0be (PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
+                       0x0c0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
+                       0x0c2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
+                       0x0c4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
+                       0x0c6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
+                       0x0c8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
+                       0x0ca (PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
+                       0x0cc (PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
+                       0x0ce (PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
+                       0x0d0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
+                       0x0d2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
+                       0x0d4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
+                       0x0d6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
+                       0x0d8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
+                       0x0da (PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
+               >;
+       };
+
+       uart2_pins: pinmux_uart2_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT | MUX_MODE0)        /* uart2_cts.uart2_cts */
+                       OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)       /* uart2_rts .uart2_rts*/
+                       OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)       /* uart2_tx.uart2_tx */
+                       OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)        /* uart2_rx.uart2_rx */
+               >;
+       };
+};
+
+&omap3_pmx_core2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &hsusbb1_pins
+       >;
+
+       hsusbb1_pins: pinmux_hsusbb1_pins {
+               pinctrl-single,pins = <
+                       OMAP3630_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3)            /* etk_ctl.hsusb1_clk */
+                       OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3)            /* etk_clk.hsusb1_stp */
+                       OMAP3630_CORE2_IOPAD(0x25ec, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d8.hsusb1_dir */
+                       OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d9.hsusb1_nxt */
+                       OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d0.hsusb1_data0 */
+                       OMAP3630_CORE2_IOPAD(0x25de, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d1.hsusb1_data1 */
+                       OMAP3630_CORE2_IOPAD(0x25e0, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d2.hsusb1_data2 */
+                       OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d3.hsusb1_data7 */
+                       OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d4.hsusb1_data4 */
+                       OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d5.hsusb1_data5 */
+                       OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d6.hsusb1_data6 */
+                       OMAP3630_CORE2_IOPAD(0x25ea, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d7.hsusb1_data3 */
+               >;
+       };
+
+       leds_pins: pinmux_leds_pins {
+               pinctrl-single,pins = <
+                       OMAP3630_CORE2_IOPAD(0x25f4, PIN_OUTPUT | MUX_MODE4) /* etk_d12.gpio_26 */
+                       OMAP3630_CORE2_IOPAD(0x25f6, PIN_OUTPUT | MUX_MODE4) /* etk_d13.gpio_27 */
+                       OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
+               >;
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+
+       /*
+        * Display monitor features are burnt in the EEPROM
+        * as EDID data.
+        */
+       eeprom@50 {
+               compatible = "ti,eeprom";
+               reg = <0x50>;
+       };
+};
+
+&gpmc {
+       ranges = <0 0 0x00000000 0x20000000>,
+                <5 0 0x2c000000 0x01000000>;
+
+       ethernet@gpmc {
+               pinctrl-names = "default";
+               pinctrl-0 = <&smsc9221_pins>;
+               reg = <5 0 0xff>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+};
+
+&usbhshost {
+       port1-mode = "ehci-phy";
+};
+
+&usbhsehci {
+       phys = <&hsusb1_phy>;
+};
+
+&vpll2 {
+       /* Needed for DSS */
+       regulator-name = "vdds_dsi";
+};
+
+&dss {
+       status = "ok";
+
+       port {
+               dpi_out: endpoint {
+                       remote-endpoint = <&tfp410_in>;
+                       data-lines = <24>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/omap3-igep0020-rev-f.dts b/arch/arm/boot/dts/omap3-igep0020-rev-f.dts
new file mode 100644 (file)
index 0000000..cc8bd0c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Device Tree Source for IGEPv2 Rev. F (TI OMAP AM/DM37x)
+ *
+ * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
+ * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.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 "omap3-igep0020-common.dtsi"
+
+/ {
+       model = "IGEPv2 Rev. F (TI OMAP AM/DM37x)";
+       compatible = "isee,omap3-igep0020-rev-f", "ti,omap36xx", "ti,omap3";
+
+       /* Regulator to trigger the WL_EN signal of the Wifi module */
+       lbep5clwmc_wlen: regulator-lbep5clwmc-wlen {
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbep5clwmc-wlen";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 11 GPIO_ACTIVE_HIGH>;            /* gpio_139 - WL_EN */
+               enable-active-high;
+       };
+};
+
+&omap3_pmx_core {
+       lbep5clwmc_pins: pinmux_lbep5clwmc_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT | MUX_MODE4)        /* mcspi1_cs3.gpio_177 - W_IRQ */
+                       OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat5.gpio_137 - BT_EN */
+                       OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat7.gpio_139 - WL_EN */
+               >;
+       };
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins &lbep5clwmc_pins>;
+       vmmc-supply = <&lbep5clwmc_wlen>;
+       bus-width = <4>;
+       non-removable;
+};
index b22caaaf774ba710461fcabf395c121c0ccc0482..fea7f7edb45dcb2fc4b8145ce9432b4c048f3c50 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEPv2 Rev. (TI OMAP AM/DM37x)
+ * Device Tree Source for IGEPv2 Rev. (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
  * published by the Free Software Foundation.
  */
 
-#include "omap3-igep.dtsi"
-#include "omap-gpmc-smsc9221.dtsi"
+#include "omap3-igep0020-common.dtsi"
 
 / {
-       model = "IGEPv2 (TI OMAP AM/DM37x)";
+       model = "IGEPv2 Rev. C (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0020", "ti,omap36xx", "ti,omap3";
 
-       leds {
-               pinctrl-names = "default";
-               pinctrl-0 = <&leds_pins>;
-               compatible = "gpio-leds";
-
-               boot {
-                        label = "omap3:green:boot";
-                        gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
-                        default-state = "on";
-               };
-
-               user0 {
-                        label = "omap3:red:user0";
-                        gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
-                        default-state = "off";
-               };
-
-               user1 {
-                        label = "omap3:red:user1";
-                        gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
-                        default-state = "off";
-               };
-
-               user2 {
-                       label = "omap3:green:user1";
-                       gpios = <&twl_gpio 19 GPIO_ACTIVE_LOW>;
-               };
+       /* Regulator to trigger the WIFI_PDN signal of the Wifi module */
+       lbee1usjyc_pdn: lbee1usjyc_pdn {
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbee1usjyc-pdn";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;    /* gpio_138 - WIFI_PDN */
+               startup-delay-us = <10000>;
+               enable-active-high;
        };
 
-       /* HS USB Port 1 Power */
-       hsusb1_power: hsusb1_power_reg {
-               compatible = "regulator-fixed";
-               regulator-name = "hsusb1_vbus";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               gpio = <&twl_gpio 18 GPIO_ACTIVE_LOW>;  /* GPIO LEDA */
-               startup-delay-us = <70000>;
-       };
-
-       /* HS USB Host PHY on PORT 1 */
-       hsusb1_phy: hsusb1_phy {
-               compatible = "usb-nop-xceiv";
-               reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; /* gpio_24 */
-               vcc-supply = <&hsusb1_power>;
-       };
-
-       tfp410: encoder@0 {
-               compatible = "ti,tfp410";
-               powerdown-gpios = <&gpio6 10 GPIO_ACTIVE_LOW>; /* gpio_170 */
-
-               ports {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       port@0 {
-                               reg = <0>;
-
-                               tfp410_in: endpoint@0 {
-                                       remote-endpoint = <&dpi_out>;
-                               };
-                       };
-
-                       port@1 {
-                               reg = <1>;
-
-                               tfp410_out: endpoint@0 {
-                                       remote-endpoint = <&dvi_connector_in>;
-                               };
-                       };
-               };
-       };
-
-       dvi0: connector@0 {
-               compatible = "dvi-connector";
-               label = "dvi";
-
-               digital;
-
-               ddc-i2c-bus = <&i2c3>;
-
-               port {
-                       dvi_connector_in: endpoint {
-                               remote-endpoint = <&tfp410_out>;
-                       };
-               };
+       /* Regulator to trigger the RESET_N_W signal of the Wifi module */
+       lbee1usjyc_reset_n_w: lbee1usjyc_reset_n_w {
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbee1usjyc-reset-n-w";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 11 GPIO_ACTIVE_HIGH>;    /* gpio_139 - RESET_N_W */
+               enable-active-high;
        };
 };
 
 &omap3_pmx_core {
-       pinctrl-names = "default";
-       pinctrl-0 = <
-               &tfp410_pins
-               &dss_dpi_pins
-       >;
-
-       tfp410_pins: pinmux_tfp410_pins {
+       lbee1usjyc_pins: pinmux_lbee1usjyc_pins {
                pinctrl-single,pins = <
-                       0x196 (PIN_OUTPUT | MUX_MODE4)   /* hdq_sio.gpio_170 */
+                       OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat5.gpio_137 - RESET_N_W */
+                       OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat6.gpio_138 - WIFI_PDN */
+                       OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat7.gpio_139 - RST_N_B */
                >;
        };
 
-       dss_dpi_pins: pinmux_dss_dpi_pins {
+       uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       0x0a4 (PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
-                       0x0a6 (PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
-                       0x0a8 (PIN_OUTPUT | MUX_MODE0)   /* dss_vsync.dss_vsync */
-                       0x0aa (PIN_OUTPUT | MUX_MODE0)   /* dss_acbias.dss_acbias */
-                       0x0ac (PIN_OUTPUT | MUX_MODE0)   /* dss_data0.dss_data0 */
-                       0x0ae (PIN_OUTPUT | MUX_MODE0)   /* dss_data1.dss_data1 */
-                       0x0b0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data2.dss_data2 */
-                       0x0b2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data3.dss_data3 */
-                       0x0b4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data4.dss_data4 */
-                       0x0b6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data5.dss_data5 */
-                       0x0b8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data6.dss_data6 */
-                       0x0ba (PIN_OUTPUT | MUX_MODE0)   /* dss_data7.dss_data7 */
-                       0x0bc (PIN_OUTPUT | MUX_MODE0)   /* dss_data8.dss_data8 */
-                       0x0be (PIN_OUTPUT | MUX_MODE0)   /* dss_data9.dss_data9 */
-                       0x0c0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data10.dss_data10 */
-                       0x0c2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data11.dss_data11 */
-                       0x0c4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data12.dss_data12 */
-                       0x0c6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data13.dss_data13 */
-                       0x0c8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data14.dss_data14 */
-                       0x0ca (PIN_OUTPUT | MUX_MODE0)   /* dss_data15.dss_data15 */
-                       0x0cc (PIN_OUTPUT | MUX_MODE0)   /* dss_data16.dss_data16 */
-                       0x0ce (PIN_OUTPUT | MUX_MODE0)   /* dss_data17.dss_data17 */
-                       0x0d0 (PIN_OUTPUT | MUX_MODE0)   /* dss_data18.dss_data18 */
-                       0x0d2 (PIN_OUTPUT | MUX_MODE0)   /* dss_data19.dss_data19 */
-                       0x0d4 (PIN_OUTPUT | MUX_MODE0)   /* dss_data20.dss_data20 */
-                       0x0d6 (PIN_OUTPUT | MUX_MODE0)   /* dss_data21.dss_data21 */
-                       0x0d8 (PIN_OUTPUT | MUX_MODE0)   /* dss_data22.dss_data22 */
-                       0x0da (PIN_OUTPUT | MUX_MODE0)   /* dss_data23.dss_data23 */
+                       OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT | MUX_MODE0)        /* uart2_cts.uart2_cts */
+                       OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)       /* uart2_rts .uart2_rts*/
+                       OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)       /* uart2_tx.uart2_tx */
+                       OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)        /* uart2_rx.uart2_rx */
                >;
        };
 };
 
-&omap3_pmx_core2 {
+/* On board Wifi module */
+&mmc2 {
        pinctrl-names = "default";
-       pinctrl-0 = <
-               &hsusbb1_pins
-       >;
-
-       hsusbb1_pins: pinmux_hsusbb1_pins {
-               pinctrl-single,pins = <
-                       OMAP3630_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3)            /* etk_ctl.hsusb1_clk */
-                       OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3)            /* etk_clk.hsusb1_stp */
-                       OMAP3630_CORE2_IOPAD(0x25ec, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d8.hsusb1_dir */
-                       OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d9.hsusb1_nxt */
-                       OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d0.hsusb1_data0 */
-                       OMAP3630_CORE2_IOPAD(0x25de, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d1.hsusb1_data1 */
-                       OMAP3630_CORE2_IOPAD(0x25e0, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d2.hsusb1_data2 */
-                       OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d3.hsusb1_data7 */
-                       OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d4.hsusb1_data4 */
-                       OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d5.hsusb1_data5 */
-                       OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d6.hsusb1_data6 */
-                       OMAP3630_CORE2_IOPAD(0x25ea, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d7.hsusb1_data3 */
-               >;
-       };
-
-       leds_pins: pinmux_leds_pins {
-               pinctrl-single,pins = <
-                       OMAP3630_CORE2_IOPAD(0x25f4, PIN_OUTPUT | MUX_MODE4) /* etk_d12.gpio_26 */
-                       OMAP3630_CORE2_IOPAD(0x25f6, PIN_OUTPUT | MUX_MODE4) /* etk_d13.gpio_27 */
-                       OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
-               >;
-       };
-};
-
-&i2c3 {
-       clock-frequency = <100000>;
-
-       /*
-        * Display monitor features are burnt in the EEPROM
-        * as EDID data.
-        */
-       eeprom@50 {
-               compatible = "ti,eeprom";
-               reg = <0x50>;
-       };
-};
-
-&gpmc {
-       ranges = <0 0 0x00000000 0x20000000>,
-                <5 0 0x2c000000 0x01000000>;
-
-       nand@0,0 {
-               linux,mtd-name= "micron,mt29c4g96maz";
-               reg = <0 0 0>;
-               nand-bus-width = <16>;
-               ti,nand-ecc-opt = "bch8";
-
-               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>;
-
-               #address-cells = <1>;
-               #size-cells = <1>;
-
-               partition@0 {
-                       label = "SPL";
-                       reg = <0 0x100000>;
-               };
-               partition@80000 {
-                       label = "U-Boot";
-                       reg = <0x100000 0x180000>;
-               };
-               partition@1c0000 {
-                       label = "Environment";
-                       reg = <0x280000 0x100000>;
-               };
-               partition@280000 {
-                       label = "Kernel";
-                       reg = <0x380000 0x300000>;
-               };
-               partition@780000 {
-                       label = "Filesystem";
-                       reg = <0x680000 0x1f980000>;
-               };
-       };
-
-       ethernet@gpmc {
-               pinctrl-names = "default";
-               pinctrl-0 = <&smsc9221_pins>;
-               reg = <5 0 0xff>;
-               interrupt-parent = <&gpio6>;
-               interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
-       };
-};
-
-&usbhshost {
-       port1-mode = "ehci-phy";
-};
-
-&usbhsehci {
-       phys = <&hsusb1_phy>;
-};
-
-&vpll2 {
-        /* Needed for DSS */
-        regulator-name = "vdds_dsi";
-};
-
-&dss {
-       status = "ok";
-
-       port {
-               dpi_out: endpoint {
-                       remote-endpoint = <&tfp410_in>;
-                       data-lines = <24>;
-               };
-       };
+       pinctrl-0 = <&mmc2_pins &lbee1usjyc_pins>;
+       vmmc-supply = <&lbee1usjyc_pdn>;
+       vmmc_aux-supply = <&lbee1usjyc_reset_n_w>;
+       bus-width = <4>;
+       non-removable;
 };
diff --git a/arch/arm/boot/dts/omap3-igep0030-common.dtsi b/arch/arm/boot/dts/omap3-igep0030-common.dtsi
new file mode 100644 (file)
index 0000000..0cb1527
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Common Device Tree Source for IGEP COM MODULE
+ *
+ * Copyright (C) 2014 Javier Martinez Canillas <javier@collabora.co.uk>
+ * Copyright (C) 2014 Enric Balletbo i Serra <eballetbo@gmail.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 "omap3-igep.dtsi"
+
+/ {
+       leds: gpio_leds {
+               compatible = "gpio-leds";
+
+               user0 {
+                        label = "omap3:red:user0";
+                        gpios = <&twl_gpio 18 GPIO_ACTIVE_LOW>;        /* LEDA */
+                        default-state = "off";
+               };
+
+               user1 {
+                        label = "omap3:green:user1";
+                        gpios = <&twl_gpio 19 GPIO_ACTIVE_LOW>;        /* LEDB */
+                        default-state = "off";
+               };
+
+               user2 {
+                        label = "omap3:red:user1";
+                        gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;           /* gpio_16 */
+                        default-state = "off";
+               };
+       };
+};
+
+&omap3_pmx_core {
+       uart2_pins: pinmux_uart2_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x216c, PIN_INPUT | MUX_MODE1)        /* mcbsp3_dx.uart2_cts */
+                       OMAP3_CORE1_IOPAD(0x216e, PIN_OUTPUT | MUX_MODE1)       /* mcbsp3_dr.uart2_rts */
+                       OMAP3_CORE1_IOPAD(0x2170, PIN_OUTPUT | MUX_MODE1)       /* mcbsp3_clk.uart2_tx */
+                       OMAP3_CORE1_IOPAD(0x2172, PIN_INPUT | MUX_MODE1)        /* mcbsp3_fsx.uart2_rx */
+               >;
+       };
+};
+
+&omap3_pmx_core2 {
+       leds_core2_pins: pinmux_leds_core2_pins {
+               pinctrl-single,pins = <
+                       OMAP3630_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4)    /* etk_d2.gpio_16 */
+               >;
+       };
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+};
diff --git a/arch/arm/boot/dts/omap3-igep0030-rev-g.dts b/arch/arm/boot/dts/omap3-igep0030-rev-g.dts
new file mode 100644 (file)
index 0000000..9326b28
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Device Tree Source for IGEP COM MODULE Rev. G (TI OMAP AM/DM37x)
+ *
+ * Copyright (C) 2014 Javier Martinez Canillas <javier@collabora.co.uk>
+ * Copyright (C) 2014 Enric Balletbo i Serra <eballetbo@gmail.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 "omap3-igep0030-common.dtsi"
+
+/ {
+       model = "IGEP COM MODULE Rev. G (TI OMAP AM/DM37x)";
+       compatible = "isee,omap3-igep0030-rev-g", "ti,omap36xx", "ti,omap3";
+
+       /* Regulator to trigger the WL_EN signal of the Wifi module */
+       lbep5clwmc_wlen: regulator-lbep5clwmc-wlen {
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbep5clwmc-wlen";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 11 GPIO_ACTIVE_HIGH>;            /* gpio_139 - WL_EN */
+               enable-active-high;
+       };
+};
+
+&omap3_pmx_core {
+       lbep5clwmc_pins: pinmux_lbep5clwmc_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2164, PIN_INPUT | MUX_MODE4)        /* sdmmc2_dat4.gpio_136 - W_IRQ */
+                       OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat5.gpio_137 - BT_EN */
+                       OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat7.gpio_139 - WL_EN */
+               >;
+       };
+
+       leds_pins: pinmux_leds_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21be, PIN_OUTPUT | MUX_MODE4)       /* i2c2_scl.gpio_168 */
+               >;
+       };
+
+};
+
+&i2c2 {
+       status = "disabled";
+};
+
+&leds {
+       pinctrl-names = "default";
+       pinctrl-0 = <&leds_pins &leds_core2_pins>;
+
+       boot {
+               label = "omap3:green:boot";
+               gpios = <&gpio6 8 GPIO_ACTIVE_HIGH>;
+               default-state = "on";
+       };
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins &lbep5clwmc_pins>;
+       vmmc-supply = <&lbep5clwmc_wlen>;
+       bus-width = <4>;
+       non-removable;
+};
index 2793749eb1ba460dcf8736fc964aef7b87b05d1a..8150f47ccdf5b6cbba75c79affcd9108b498e303 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for IGEP COM MODULE (TI OMAP AM/DM37x)
+ * Device Tree Source for IGEP COM MODULE Rev. E (TI OMAP AM/DM37x)
  *
  * Copyright (C) 2012 Javier Martinez Canillas <javier@collabora.co.uk>
  * Copyright (C) 2012 Enric Balletbo i Serra <eballetbo@gmail.com>
@@ -9,97 +9,62 @@
  * published by the Free Software Foundation.
  */
 
-#include "omap3-igep.dtsi"
+#include "omap3-igep0030-common.dtsi"
 
 / {
-       model = "IGEP COM MODULE (TI OMAP AM/DM37x)";
+       model = "IGEP COM MODULE Rev. E (TI OMAP AM/DM37x)";
        compatible = "isee,omap3-igep0030", "ti,omap36xx", "ti,omap3";
 
-       leds {
-               pinctrl-names = "default";
-               pinctrl-0 = <&leds_pins>;
-               compatible = "gpio-leds";
-
-               boot {
-                        label = "omap3:green:boot";
-                        gpios = <&twl_gpio 13 GPIO_ACTIVE_LOW>;
-                        default-state = "on";
-               };
-
-               user0 {
-                        label = "omap3:red:user0";
-                        gpios = <&twl_gpio 18 GPIO_ACTIVE_LOW>; /* LEDA */
-                        default-state = "off";
-               };
-
-               user1 {
-                        label = "omap3:green:user1";
-                        gpios = <&twl_gpio 19 GPIO_ACTIVE_LOW>; /* LEDB */
-                        default-state = "off";
-               };
+       /* Regulator to trigger the WIFI_PDN signal of the Wifi module */
+       lbee1usjyc_pdn: lbee1usjyc_pdn {
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbee1usjyc-pdn";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 10 GPIO_ACTIVE_HIGH>;    /* gpio_138 - WIFI_PDN */
+               startup-delay-us = <10000>;
+               enable-active-high;
+       };
 
-               user2 {
-                        label = "omap3:red:user1";
-                        gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
-                        default-state = "off";
-               };
+       /* Regulator to trigger the RESET_N_W signal of the Wifi module */
+       lbee1usjyc_reset_n_w: lbee1usjyc_reset_n_w {
+               compatible = "regulator-fixed";
+               regulator-name = "regulator-lbee1usjyc-reset-n-w";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 11 GPIO_ACTIVE_HIGH>;    /* gpio_139 - RESET_N_W */
+               enable-active-high;
        };
 };
 
-&omap3_pmx_core2 {
-       leds_pins: pinmux_leds_pins {
+&omap3_pmx_core {
+       lbee1usjyc_pins: pinmux_lbee1usjyc_pins {
                pinctrl-single,pins = <
-                       OMAP3630_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */
+                       OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat5.gpio_137 - RESET_N_W */
+                       OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat6.gpio_138 - WIFI_PDN */
+                       OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4)       /* sdmmc2_dat7.gpio_139 - RST_N_B */
                >;
        };
 };
 
-&gpmc {
-       ranges = <0 0 0x00000000 0x20000000>;
-
-       nand@0,0 {
-               linux,mtd-name= "micron,mt29c4g96maz";
-               reg = <0 0 0>;
-               nand-bus-width = <16>;
-               ti,nand-ecc-opt = "bch8";
+&leds {
+       pinctrl-names = "default";
+       pinctrl-0 = <&leds_core2_pins>;
 
-               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>;
-
-               #address-cells = <1>;
-               #size-cells = <1>;
-
-               partition@0 {
-                       label = "SPL";
-                       reg = <0 0x100000>;
-               };
-               partition@80000 {
-                       label = "U-Boot";
-                       reg = <0x100000 0x180000>;
-               };
-               partition@1c0000 {
-                       label = "Environment";
-                       reg = <0x280000 0x100000>;
-               };
-               partition@280000 {
-                       label = "Kernel";
-                       reg = <0x380000 0x300000>;
-               };
-               partition@780000 {
-                       label = "Filesystem";
-                       reg = <0x680000 0x1f980000>;
-               };
+       boot {
+               label = "omap3:green:boot";
+               gpios = <&twl_gpio 13 GPIO_ACTIVE_LOW>; /* LEDSYNC */
+               default-state = "on";
        };
 };
+
+/* On board Wifi module */
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins &lbee1usjyc_pins>;
+       vmmc-supply = <&lbee1usjyc_pdn>;
+       vmmc_aux-supply = <&lbee1usjyc_reset_n_w>;
+       bus-width = <4>;
+       non-removable;
+};
+
index 72dca0b7904d2c4078d1dfba477f190628f79cbc..b699bc48f242ef33cf7c390e3a4002a4a1ac3a31 100644 (file)
@@ -7,6 +7,7 @@
  */
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
 #include "omap34xx.dtsi"
 #include "omap-gpmc-smsc911x.dtsi"
 
 
        nand@0,0 {
                linux,mtd-name= "micron,nand";
-               reg = <0 0 0>;
+               reg = <0 0 4>;  /* CS0, offset 0, IO size 4 */
                nand-bus-width = <16>;
+               gpmc,device-width = <2>;
                ti,nand-ecc-opt = "bch8";
 
                gpmc,sync-clk-ps = <0>;
                };
                partition@2000000 {
                        label = "Filesystem";
-                       reg = <0x2000000 0xe000000>;
+                       reg = <0x2000000 0x6000000>;
                };
        };
 
        };
 };
 
+&twl_keypad {
+       linux,keymap = <MATRIX_KEY(0, 0, KEY_1)
+                       MATRIX_KEY(0, 1, KEY_2)
+                       MATRIX_KEY(0, 2, KEY_3)
+                       MATRIX_KEY(1, 0, KEY_4)
+                       MATRIX_KEY(1, 1, KEY_5)
+                       MATRIX_KEY(1, 2, KEY_6)
+                       MATRIX_KEY(1, 3, KEY_F5)
+                       MATRIX_KEY(2, 0, KEY_7)
+                       MATRIX_KEY(2, 1, KEY_8)
+                       MATRIX_KEY(2, 2, KEY_9)
+                       MATRIX_KEY(2, 3, KEY_F6)
+                       MATRIX_KEY(3, 0, KEY_F7)
+                       MATRIX_KEY(3, 1, KEY_0)
+                       MATRIX_KEY(3, 2, KEY_F8)
+                       MATRIX_KEY(5, 4, KEY_RESERVED)
+                       MATRIX_KEY(4, 4, KEY_VOLUMEUP)
+                       MATRIX_KEY(5, 5, KEY_VOLUMEDOWN)>;
+};
+
 &uart3 {
        interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
 };
index d97308896f0c621dfc0a29175ddfcf8e0c2082df..e81fb651d5d0f04a6a90a6abca434cd64dc5d21e 100644 (file)
                <7 0 0x15000000 0x01000000>;
 
        nand@0,0 {
-               reg = <0 0 0x1000000>;
+               reg = <0 0 4>;  /* CS0, offset 0, IO size 4 */
                nand-bus-width = <16>;
                ti,nand-ecc-opt = "bch8";
                /* no elm on omap3 */
index 739fcf29c6439af97b6a8bca100db0b3fd082e88..53f3ca064140470866dbfe12773af1ddb76d1632 100644 (file)
                eci-switch-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>; /* 182 */
                speaker-amplifier-gpios = <&twl_gpio 7 GPIO_ACTIVE_HIGH>;
        };
+
+       battery: n900-battery {
+               compatible = "nokia,n900-battery";
+               io-channels = <&twl_madc 0>, <&twl_madc 4>, <&twl_madc 12>;
+               io-channel-names = "temp", "bsi", "vbat";
+       };
 };
 
 &omap3_pmx_core {
                >;
        };
 
+       gpmc_pins: pinmux_gpmc_pins {
+               pinctrl-single,pins = <
+
+                       /* address lines */
+                        OMAP3_CORE1_IOPAD(0x207a, PIN_OUTPUT | MUX_MODE0)       /* gpmc_a1.gpmc_a1 */
+                        OMAP3_CORE1_IOPAD(0x207c, PIN_OUTPUT | MUX_MODE0)       /* gpmc_a2.gpmc_a2 */
+                        OMAP3_CORE1_IOPAD(0x207e, PIN_OUTPUT | MUX_MODE0)       /* gpmc_a3.gpmc_a3 */
+
+                       /* data lines, gpmc_d0..d7 not muxable according to TRM */
+                        OMAP3_CORE1_IOPAD(0x209e, PIN_INPUT | MUX_MODE0)        /* gpmc_d8.gpmc_d8 */
+                        OMAP3_CORE1_IOPAD(0x20a0, PIN_INPUT | MUX_MODE0)        /* gpmc_d9.gpmc_d9 */
+                        OMAP3_CORE1_IOPAD(0x20a2, PIN_INPUT | MUX_MODE0)        /* gpmc_d10.gpmc_d10 */
+                        OMAP3_CORE1_IOPAD(0x20a4, PIN_INPUT | MUX_MODE0)        /* gpmc_d11.gpmc_d11 */
+                        OMAP3_CORE1_IOPAD(0x20a6, PIN_INPUT | MUX_MODE0)        /* gpmc_d12.gpmc_d12 */
+                        OMAP3_CORE1_IOPAD(0x20a8, PIN_INPUT | MUX_MODE0)        /* gpmc_d13.gpmc_d13 */
+                        OMAP3_CORE1_IOPAD(0x20aa, PIN_INPUT | MUX_MODE0)        /* gpmc_d14.gpmc_d14 */
+                        OMAP3_CORE1_IOPAD(0x20ac, PIN_INPUT | MUX_MODE0)        /* gpmc_d15.gpmc_d15 */
+
+                       /*
+                        * gpmc_ncs0, gpmc_nadv_ale, gpmc_noe, gpmc_nwe, gpmc_wait0 not muxable
+                        * according to TRM. OneNAND seems to require PIN_INPUT on clock.
+                        */
+                        OMAP3_CORE1_IOPAD(0x20b0, PIN_OUTPUT | MUX_MODE0)       /* gpmc_ncs1.gpmc_ncs1 */
+                        OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0)        /* gpmc_clk.gpmc_clk */
+               >;
+       };
+
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
                        0x18a (PIN_INPUT | MUX_MODE0)           /* i2c1_scl */
                power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>; /* 98 */
        };
 
+       si4713: si4713@63 {
+               compatible = "silabs,si4713";
+                reg = <0x63>;
+
+                interrupts-extended = <&gpio2 21 IRQ_TYPE_EDGE_FALLING>; /* 53 */
+                reset-gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>; /* 163 */
+                vio-supply = <&vio>;
+                vdd-supply = <&vaux1>;
+       };
+
        bq24150a: bq24150a@6b {
                compatible = "ti,bq24150a";
                reg = <0x6b>;
 };
 
 &gpmc {
-       ranges = <0 0 0x04000000 0x10000000>; /* 256MB */
        ranges = <0 0 0x01000000 0x01000000>,   /* 16 MB for OneNAND */
                 <1 0 0x02000000 0x01000000>;   /* 16 MB for smc91c96 */
+       pinctrl-names = "default";
+       pinctrl-0 = <&gpmc_pins>;
 
-       /* gpio-irq for dma: 65 */
-
+       /* sys_ndmareq1 could be used by the driver, not as gpio65 though */
        onenand@0,0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               reg = <0 0 0x10000000>;
+               reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
 
                gpmc,sync-read;
                gpmc,sync-write;
                bank-width = <2>;
                pinctrl-names = "default";
                pinctrl-0 = <&ethernet_pins>;
+               power-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;     /* gpio86 */
+               reset-gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>;      /* gpio164 */
                gpmc,device-width = <2>;
                gpmc,sync-clk-ps = <0>;
                gpmc,cs-on-ns = <0>;
index 70addcba37c5d673410217f4731d540c35d817be..1e49dfe7e21294052b53cdabee085afd0dc31455 100644 (file)
 };
 
 &gpmc {
-       ranges = <0 0 0x04000000 0x20000000>;
+       ranges = <0 0 0x04000000 0x1000000>;    /* CS0: 16MB for OneNAND */
 
        onenand@0,0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               reg = <0 0 0x20000000>;
+               reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
 
                gpmc,sync-read;
                gpmc,sync-write;
index d59e3de1441e2f7dc5e0fb9b4bc29f49ee04cbc1..827f614261f6f0041096514be33f90540c61a608 100644 (file)
@@ -2,6 +2,59 @@
  * Common support for CompuLab SB-T35 used on SBC-T3530, SBC-T3517 and SBC-T3730
  */
 
+/ {
+       tfp410: encoder@0 {
+               compatible = "ti,tfp410";
+
+               powerdown-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;  /* gpio_54 */
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&tfp410_pins>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
+                               tfp410_in: endpoint@0 {
+                                       remote-endpoint = <&dpi_out>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+
+                               tfp410_out: endpoint@0 {
+                                       remote-endpoint = <&dvi_connector_in>;
+                               };
+                       };
+               };
+       };
+
+       dvi0: connector@0 {
+               compatible = "dvi-connector";
+               label = "dvi";
+
+               port {
+                       dvi_connector_in: endpoint {
+                               remote-endpoint = <&tfp410_out>;
+                       };
+               };
+       };
+
+       audio_amp: audio_amp {
+               compatible = "regulator-fixed";
+               regulator-name = "audio_amp";
+               pinctrl-names = "default";
+               pinctrl-0 = <&sb_t35_audio_amp>;
+               gpio = <&gpio2 29 GPIO_ACTIVE_LOW>;   /* gpio_61 */
+               enable-active-low;
+               regulator-always-on;
+       };
+};
+
 &omap3_pmx_core {
        smsc2_pins: pinmux_smsc2_pins {
                pinctrl-single,pins = <
@@ -9,6 +62,38 @@
                        OMAP3_CORE1_IOPAD(0x20d2, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_wait3.gpio_65 */
                >;
        };
+
+       tfp410_pins: pinmux_tfp410_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x20b4, PIN_OUTPUT | MUX_MODE4)       /* gpmc_ncs3.gpio_54 */
+               >;
+       };
+
+       i2c3_pins: pinmux_i2c3_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_scl */
+                       OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c3_sda */
+               >;
+       };
+
+       sb_t35_audio_amp: pinmux_sb_t35_audio_amp {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x20c8, PIN_OUTPUT | MUX_MODE4) /* gpmc_nbe1.gpio_61 */
+               >;
+       };
+};
+
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c3_pins>;
+
+       clock-frequency = <400000>;
+
+       at24@50 {
+               compatible = "at24,24c02";
+               pagesize = <16>;
+               reg = <0x50>;
+       };
 };
 
 &gpmc {
                interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
                reg = <4 0 0xff>;
                bank-width = <2>;
-               gpmc,mux-add-data;
-               gpmc,cs-on-ns = <1>;
-               gpmc,cs-rd-off-ns = <180>;
-               gpmc,cs-wr-off-ns = <180>;
-               gpmc,adv-rd-off-ns = <18>;
-               gpmc,adv-wr-off-ns = <48>;
-               gpmc,oe-on-ns = <54>;
-               gpmc,oe-off-ns = <168>;
-               gpmc,we-on-ns = <54>;
-               gpmc,we-off-ns = <168>;
-               gpmc,rd-cycle-ns = <186>;
-               gpmc,wr-cycle-ns = <186>;
-               gpmc,access-ns = <144>;
-               gpmc,page-burst-access-ns = <24>;
-               gpmc,bus-turnaround-ns = <90>;
-               gpmc,cycle2cycle-delay-ns = <90>;
-               gpmc,cycle2cycle-samecsen;
-               gpmc,cycle2cycle-diffcsen;
+               gpmc,device-width = <1>;
+               gpmc,cycle2cycle-samecsen = <1>;
+               gpmc,cycle2cycle-diffcsen = <1>;
+               gpmc,cs-on-ns = <5>;
+               gpmc,cs-rd-off-ns = <150>;
+               gpmc,cs-wr-off-ns = <150>;
+               gpmc,adv-on-ns = <0>;
+               gpmc,adv-rd-off-ns = <15>;
+               gpmc,adv-wr-off-ns = <40>;
+               gpmc,oe-on-ns = <45>;
+               gpmc,oe-off-ns = <140>;
+               gpmc,we-on-ns = <45>;
+               gpmc,we-off-ns = <140>;
+               gpmc,rd-cycle-ns = <155>;
+               gpmc,wr-cycle-ns = <155>;
+               gpmc,access-ns = <120>;
+               gpmc,page-burst-access-ns = <20>;
+               gpmc,bus-turnaround-ns = <75>;
+               gpmc,cycle2cycle-delay-ns = <75>;
+               gpmc,wait-monitoring-ns = <0>;
+               gpmc,clk-activation-ns = <0>;
+               gpmc,wr-data-mux-bus-ns = <0>;
+               gpmc,wr-access-ns = <0>;
                vddvario-supply = <&vddvario>;
                vdd33a-supply = <&vdd33a>;
                reg-io-width = <4>;
index 42189b65d393d29d2cf467ddbc5df4eb0661a471..17986536c61f93665201c5a488673f92e5ad0472 100644 (file)
@@ -9,6 +9,11 @@
        model = "CompuLab SBC-T3517 with CM-T3517";
        compatible = "compulab,omap3-sbc-t3517", "compulab,omap3-cm-t3517", "ti,am3517", "ti,omap3";
 
+       aliases {
+               display0 = &dvi0;
+               display1 = &tv0;
+       };
+
        /* Only one GPMC smsc9220 on SBC-T3517, CM-T3517 uses am35x Ethernet */
        vddvario: regulator-vddvario-sb-t35 {
                compatible = "regulator-fixed";
        wp-gpios =  <&gpio2 27 GPIO_ACTIVE_HIGH>; /* gpio_59  */
        cd-gpios =  <&gpio5 16 GPIO_ACTIVE_HIGH>; /* gpio_144 */
 };
+
+&dss {
+       port {
+               dpi_out: endpoint {
+                       remote-endpoint = <&tfp410_in>;
+                       data-lines = <24>;
+               };
+       };
+};
+
index bbbeea6b19881a975287135b6aafc4d5d8f08e2f..c994f0f7e38a120e6aa51eace3e384d91cc9a5e6 100644 (file)
@@ -8,6 +8,11 @@
 / {
        model = "CompuLab SBC-T3530 with CM-T3530";
        compatible = "compulab,omap3-sbc-t3530", "compulab,omap3-cm-t3530", "ti,omap34xx", "ti,omap3";
+
+       aliases {
+               display0 = &dvi0;
+               display1 = &tv0;
+       };
 };
 
 &omap3_pmx_core {
 &mmc1 {
        cd-gpios =  <&twl_gpio 0 GPIO_ACTIVE_HIGH>;
 };
+
+&dss {
+       port {
+               dpi_out: endpoint {
+                       remote-endpoint = <&tfp410_in>;
+                       data-lines = <24>;
+               };
+       };
+};
+
index 08e4a7086f2293c8b0343eeed752b48e477e37a9..5bdddf29341d936449cb6979a24ef0035800d962 100644 (file)
@@ -8,6 +8,11 @@
 / {
        model = "CompuLab SBC-T3730 with CM-T3730";
        compatible = "compulab,omap3-sbc-t3730", "compulab,omap3-cm-t3730", "ti,omap36xx", "ti,omap3";
+
+       aliases {
+               display0 = &dvi0;
+               display1 = &tv0;
+       };
 };
 
 &omap3_pmx_core {
        ranges = <5 0 0x2c000000 0x01000000>,
                 <4 0 0x2d000000 0x01000000>;
 };
+
+&dss {
+       port {
+               dpi_out: endpoint {
+                       remote-endpoint = <&tfp410_in>;
+                       data-lines = <24>;
+               };
+       };
+};
+
index b30f387d3a834ca7bcbe23e8a735ed9d1bf5cdce..e89820a6776ef2d5628e85e681e1b998aadbfdce 100644 (file)
        ranges = <0 0 0x00000000 0x01000000>;
 
        nand@0,0 {
-               reg = <0 0 0>; /* CS0, offset 0 */
+               reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
                nand-bus-width = <16>;
                gpmc,device-width = <2>;        /* GPMC_DEVWIDTH_16BIT */
                ti,nand-ecc-opt = "sw";
index d0e884d3a7372f003f1777aeba1f6ccc15c2e26c..01b71111bd558738595fde6deaa71b05c4c08e9a 100644 (file)
@@ -79,7 +79,7 @@
         * hierarchy.
         */
        ocp {
-               compatible = "simple-bus";
+               compatible = "ti,omap3-l3-smx", "simple-bus";
                reg = <0x68000000 0x10000>;
                interrupts = <9 10>;
                #address-cells = <1>;
                        ti,hwmods = "mailbox";
                        reg = <0x48094000 0x200>;
                        interrupts = <26>;
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <2>;
                        ti,mbox-num-fifos = <2>;
                        mbox_dsp: dsp {
index 9bad94efe1c81c65a56f9d8fbb6d8fcc53bcd2af..16b0cdfbee9cbb0368a2bdf8ddd59534ff16771e 100644 (file)
@@ -51,8 +51,8 @@
 
 &gpmc {
        ranges = <0 0 0x10000000 0x08000000>,
-                <1 0 0x28000000 0x08000000>,
-                <2 0 0x20000000 0x10000000>;
+                <1 0 0x28000000 0x1000000>,    /* CS1: 16MB for NAND */
+                <2 0 0x20000000 0x1000000>;    /* CS2: 16MB for OneNAND */
 
        nor@0,0 {
                compatible = "cfi-flash";
                linux,mtd-name= "micron,mt29f1g08abb";
                #address-cells = <1>;
                #size-cells = <1>;
-               reg = <1 0 0x08000000>;
+               reg = <1 0 4>;  /* CS1, offset 0, IO size 4 */
                ti,nand-ecc-opt = "sw";
                nand-bus-width = <8>;
                gpmc,cs-on-ns = <0>;
                linux,mtd-name= "samsung,kfm2g16q2m-deb8";
                #address-cells = <1>;
                #size-cells = <1>;
-               reg = <2 0 0x10000000>;
+               reg = <2 0 0x20000>;    /* CS2, offset 0, IO size 4 */
 
                gpmc,device-width = <2>;
                gpmc,mux-add-data = <2>;
index 6dc84d9f9b4c4a170f0b788f19ee9850333114d8..1a78f013f37ab8e2ee4de5361dc16bdeec2b2516 100644 (file)
 
 &hdmi {
        status = "ok";
+       vdda-supply = <&vdac>;
 
        pinctrl-names = "default";
        pinctrl-0 = <&dss_hdmi_pins>;
index 878c979203d09ea403577317e3211e85329303fe..074147cebae49f965b254915240b667bffcf9d21 100644 (file)
                        reg = <0x4a0f4000 0x200>;
                        interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <3>;
                        ti,mbox-num-fifos = <8>;
                        mbox_ipu: mbox_ipu {
                                reg = <0x58002000 0x1000>;
                                status = "disabled";
                                ti,hwmods = "dss_rfbi";
-                               clocks = <&dss_dss_clk>, <&dss_fck>;
+                               clocks = <&dss_dss_clk>, <&l3_div_ck>;
                                clock-names = "fck", "ick";
                        };
 
index c821ff5e9b8da038b731d992a5aeb961ed9efde2..f2c48f09824ea25a44a296f9318c38cabb4f4c43 100644 (file)
                reg = <0x1120>;
        };
 
-       dss_fck: dss_fck {
-               #clock-cells = <0>;
-               compatible = "ti,gate-clock";
-               clocks = <&l3_div_ck>;
-               ti,bit-shift = <1>;
-               reg = <0x1120>;
-       };
-
        fdif_fck: fdif_fck {
                #clock-cells = <0>;
                compatible = "ti,divider-clock";
index 256b7f69e45b4cba84b2bfa85543545374ce6f02..b321fdf42c9f3c51e3a59d4b51b27a08f4fcaba4 100644 (file)
                        reg = <0x4a0f4000 0x200>;
                        interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "mailbox";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <3>;
                        ti,mbox-num-fifos = <8>;
                        mbox_ipu: mbox_ipu {
index 963b7e54ab153ae1f276eb7eb3bf5a226eae5dab..1ca1a9aa953f7ee893fddf8b5a9217ddab7e2956 100644 (file)
                };
        };
 
+       arm-pmu {
+               compatible = "arm,cortex-a9-pmu";
+               interrupts = <29>;
+       };
+
        axi {
                compatible = "simple-bus";
                #address-cells = <1>;
                                reg = <0x90020000 0x10000>;
                                interrupts = <31>;
                                clocks = <&clks 35>;
+                               resets = <&rstc 6>;
                        };
                };
 
                                compatible = "sirf,prima2-dspif";
                                reg = <0xa8000000 0x10000>;
                                interrupts = <9>;
+                               resets = <&rstc 1>;
                        };
 
                        gps@a8010000 {
                                reg = <0xa8010000 0x10000>;
                                interrupts = <7>;
                                clocks = <&clks 9>;
+                               resets = <&rstc 2>;
                        };
 
                        dsp@a9000000 {
                                reg = <0xa9000000 0x1000000>;
                                interrupts = <8>;
                                clocks = <&clks 8>;
+                               resets = <&rstc 0>;
                        };
                };
 
                                                 sirf,function = "sdmmc5";
                                         };
                                 };
+                               i2s_mclk_pins_a: i2s_mclk@0 {
+                                        i2s_mclk {
+                                                sirf,pins = "i2smclkgrp";
+                                                sirf,function = "i2s_mclk";
+                                        };
+                                };
+                               i2s_ext_clk_input_pins_a: i2s_ext_clk_input@0 {
+                                        i2s_ext_clk_input {
+                                                sirf,pins = "i2s_ext_clk_inputgrp";
+                                                sirf,function = "i2s_ext_clk_input";
+                                        };
+                                };
                                 i2s_pins_a: i2s@0 {
                                         i2s {
                                                 sirf,pins = "i2sgrp";
                                                 sirf,function = "i2s";
                                         };
                                 };
+                               i2s_no_din_pins_a: i2s_no_din@0 {
+                                        i2s_no_din {
+                                                sirf,pins = "i2s_no_dingrp";
+                                                sirf,function = "i2s_no_din";
+                                        };
+                                };
+                               i2s_6chn_pins_a: i2s_6chn@0 {
+                                        i2s_6chn {
+                                                sirf,pins = "i2s_6chngrp";
+                                                sirf,function = "i2s_6chn";
+                                        };
+                                };
                                 ac97_pins_a: ac97@0 {
                                         ac97 {
                                                 sirf,pins = "ac97grp";
index a3ed23c0a8f58abd3e2d035042dceb658b528bee..1518c5bcca33d8d1052c7fe70f97b3f043c33da3 100644 (file)
@@ -21,7 +21,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySC2,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               stdout-path = &scif2;
        };
 
        memory {
index 801a556e264bcc950eb6eb3db55a61c9e92c1c0f..277e73c110e5d40c38953d3a3ea5079e6ec755f3 100644 (file)
                        clock-output-names = "usb_x1";
                };
 
-               /* Special CPG clocks */
-               cpg_clocks: cpg_clocks@fcfe0000 {
-                       #clock-cells = <1>;
-                       compatible = "renesas,r7s72100-cpg-clocks",
-                                    "renesas,rz-cpg-clocks";
-                       reg = <0xfcfe0000 0x18>;
-                       clocks = <&extal_clk>, <&usb_x1_clk>;
-                       clock-output-names = "pll", "i", "g";
-               };
-
                /* Fixed factor clocks */
                b_clk: b_clk {
                        #clock-cells = <0>;
                        clock-output-names = "p0";
                };
 
+               /* Special CPG clocks */
+               cpg_clocks: cpg_clocks@fcfe0000 {
+                       #clock-cells = <1>;
+                       compatible = "renesas,r7s72100-cpg-clocks",
+                                    "renesas,rz-cpg-clocks";
+                       reg = <0xfcfe0000 0x18>;
+                       clocks = <&extal_clk>, <&usb_x1_clk>;
+                       clock-output-names = "pll", "i", "g";
+               };
+
                /* MSTP clocks */
                mstp3_clks: mstp3_clks@fcfe0420 {
                        #clock-cells = <1>;
                };
        };
 
-       gic: interrupt-controller@e8201000 {
-               compatible = "arm,cortex-a9-gic";
-               #interrupt-cells = <3>;
-               #address-cells = <0>;
-               interrupt-controller;
-               reg = <0xe8201000 0x1000>,
-                       <0xe8202000 0x1000>;
-       };
-
-       i2c0: i2c@fcfee000 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
-               reg = <0xfcfee000 0x44>;
-               interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 158 IRQ_TYPE_EDGE_RISING>,
-                            <0 159 IRQ_TYPE_EDGE_RISING>,
-                            <0 160 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 161 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 162 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 163 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 164 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&mstp9_clks R7S72100_CLK_I2C0>;
-               clock-frequency = <100000>;
-               status = "disabled";
-       };
-
-       i2c1: i2c@fcfee400 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
-               reg = <0xfcfee400 0x44>;
-               interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 166 IRQ_TYPE_EDGE_RISING>,
-                            <0 167 IRQ_TYPE_EDGE_RISING>,
-                            <0 168 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 169 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 170 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 171 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 172 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&mstp9_clks R7S72100_CLK_I2C1>;
-               clock-frequency = <100000>;
-               status = "disabled";
-       };
-
-       i2c2: i2c@fcfee800 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
-               reg = <0xfcfee800 0x44>;
-               interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 174 IRQ_TYPE_EDGE_RISING>,
-                            <0 175 IRQ_TYPE_EDGE_RISING>,
-                            <0 176 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 177 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 178 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 179 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 180 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&mstp9_clks R7S72100_CLK_I2C2>;
-               clock-frequency = <100000>;
-               status = "disabled";
-       };
-
-       i2c3: i2c@fcfeec00 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
-               reg = <0xfcfeec00 0x44>;
-               interrupts = <0 181 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 182 IRQ_TYPE_EDGE_RISING>,
-                            <0 183 IRQ_TYPE_EDGE_RISING>,
-                            <0 184 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 185 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 186 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 187 IRQ_TYPE_LEVEL_HIGH>,
-                            <0 188 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&mstp9_clks R7S72100_CLK_I2C3>;
-               clock-frequency = <100000>;
-               status = "disabled";
-       };
-
-       mtu2: timer@fcff0000 {
-               compatible = "renesas,mtu2-r7s72100", "renesas,mtu2";
-               reg = <0xfcff0000 0x400>;
-               interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
-               interrupt-names = "tgi0a";
-               clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
-               clock-names = "fck";
-               status = "disabled";
-       };
-
        scif0: serial@e8007000 {
                compatible = "renesas,scif-r7s72100", "renesas,scif";
                reg = <0xe8007000 64>;
                #size-cells = <0>;
                status = "disabled";
        };
+
+       gic: interrupt-controller@e8201000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0xe8201000 0x1000>,
+                       <0xe8202000 0x1000>;
+       };
+
+       i2c0: i2c@fcfee000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+               reg = <0xfcfee000 0x44>;
+               interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 158 IRQ_TYPE_EDGE_RISING>,
+                            <0 159 IRQ_TYPE_EDGE_RISING>,
+                            <0 160 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 161 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 162 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 163 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 164 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R7S72100_CLK_I2C0>;
+               clock-frequency = <100000>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@fcfee400 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+               reg = <0xfcfee400 0x44>;
+               interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 166 IRQ_TYPE_EDGE_RISING>,
+                            <0 167 IRQ_TYPE_EDGE_RISING>,
+                            <0 168 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 169 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 170 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 171 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 172 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R7S72100_CLK_I2C1>;
+               clock-frequency = <100000>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@fcfee800 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+               reg = <0xfcfee800 0x44>;
+               interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 174 IRQ_TYPE_EDGE_RISING>,
+                            <0 175 IRQ_TYPE_EDGE_RISING>,
+                            <0 176 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 177 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 178 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 179 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 180 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R7S72100_CLK_I2C2>;
+               clock-frequency = <100000>;
+               status = "disabled";
+       };
+
+       i2c3: i2c@fcfeec00 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+               reg = <0xfcfeec00 0x44>;
+               interrupts = <0 181 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 182 IRQ_TYPE_EDGE_RISING>,
+                            <0 183 IRQ_TYPE_EDGE_RISING>,
+                            <0 184 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 185 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 186 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 187 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 188 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R7S72100_CLK_I2C3>;
+               clock-frequency = <100000>;
+               status = "disabled";
+       };
+
+       mtu2: timer@fcff0000 {
+               compatible = "renesas,mtu2-r7s72100", "renesas,mtu2";
+               reg = <0xfcff0000 0x400>;
+               interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "tgi0a";
+               clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
+               clock-names = "fck";
+               status = "disabled";
+       };
 };
index a860f32bca27fd8d089bb93f202b9b196dbcf6ac..84e05f713c5425a6007cdae230beee5972c21080 100644 (file)
@@ -21,7 +21,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySC0,115200 ignore_loglevel rw";
+               bootargs = "ignore_loglevel rw";
+               stdout-path = &scifa0;
        };
 
        memory@40000000 {
        voltage-tolerance = <1>; /* 1% */
 };
 
+&cmt1 {
+       status = "okay";
+};
+
 &pfc {
        scifa0_pins: serial0 {
                renesas,groups = "scifa0_data";
index ef152e384822c8f34633568a9002f2d1507fca21..5ac57babc3b95c9999370c86a1967441afdef7c1 100644 (file)
                };
        };
 
-       gic: interrupt-controller@f1001000 {
-               compatible = "arm,cortex-a15-gic";
-               #interrupt-cells = <3>;
-               #address-cells = <0>;
-               interrupt-controller;
-               reg = <0 0xf1001000 0 0x1000>,
-                       <0 0xf1002000 0 0x1000>,
-                       <0 0xf1004000 0 0x2000>,
-                       <0 0xf1006000 0 0x2000>;
-               interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
-       };
-
        timer {
                compatible = "arm,armv7-timer";
                interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                             <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
        };
 
+       dmac: dma-multiplexer {
+               compatible = "renesas,shdma-mux";
+               #dma-cells = <1>;
+               dma-channels = <20>;
+               dma-requests = <256>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               dma0: dma-controller@e6700020 {
+                       compatible = "renesas,shdma-r8a73a4";
+                       reg = <0 0xe6700020 0 0x89e0>;
+                       interrupts = <0 220 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
+                                       0 215 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>;
+                       interrupt-names = "error",
+                                       "ch0", "ch1", "ch2", "ch3",
+                                       "ch4", "ch5", "ch6", "ch7",
+                                       "ch8", "ch9", "ch10", "ch11",
+                                       "ch12", "ch13", "ch14", "ch15",
+                                       "ch16", "ch17", "ch18", "ch19";
+               };
+       };
+
+       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>;
+
+               status = "disabled";
+       };
+
+       cmt1: timer@e6130000 {
+               compatible = "renesas,cmt-48-r8a73a4", "renesas,cmt-48-gen2";
+               reg = <0 0xe6130000 0 0x1004>;
+               interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>;
+
+               renesas,channels-mask = <0xff>;
+
+               status = "disabled";
+       };
+
        irqc0: interrupt-controller@e61c0000 {
                compatible = "renesas,irqc-r8a73a4", "renesas,irqc";
                #interrupt-cells = <2>;
                             <0 57 IRQ_TYPE_LEVEL_HIGH>;
        };
 
-       dmac: dma-multiplexer@0 {
-               compatible = "renesas,shdma-mux";
-               #dma-cells = <1>;
-               dma-channels = <20>;
-               dma-requests = <256>;
-               #address-cells = <2>;
-               #size-cells = <2>;
-               ranges;
-
-               dma0: dma-controller@e6700020 {
-                       compatible = "renesas,shdma-r8a73a4";
-                       reg = <0 0xe6700020 0 0x89e0>;
-                       interrupts = <0 220 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
-                                       0 215 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>;
-                       interrupt-names = "error",
-                                       "ch0", "ch1", "ch2", "ch3",
-                                       "ch4", "ch5", "ch6", "ch7",
-                                       "ch8", "ch9", "ch10", "ch11",
-                                       "ch12", "ch13", "ch14", "ch15",
-                                       "ch16", "ch17", "ch18", "ch19";
-               };
-       };
-
        thermal@e61f0000 {
                compatible = "renesas,thermal-r8a73a4", "renesas,rcar-thermal";
                reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>,
        i2c0: i2c@e6500000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6500000 0 0x428>;
                interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        i2c1: i2c@e6510000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6510000 0 0x428>;
                interrupts = <0 175 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        i2c2: i2c@e6520000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6520000 0 0x428>;
                interrupts = <0 176 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        i2c3: i2c@e6530000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6530000 0 0x428>;
                interrupts = <0 177 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        i2c4: i2c@e6540000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6540000 0 0x428>;
                interrupts = <0 178 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
-       i2c5: i2c@e60b0000 {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
-               reg = <0 0xe60b0000 0 0x428>;
-               interrupts = <0 179 IRQ_TYPE_LEVEL_HIGH>;
-               status = "disabled";
-       };
-
        i2c6: i2c@e6550000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6550000 0 0x428>;
                interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        i2c7: i2c@e6560000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6560000 0 0x428>;
                interrupts = <0 185 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        i2c8: i2c@e6570000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6570000 0 0x428>;
                interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
+       scifb0: serial@e6c20000 {
+               compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+               reg = <0 0xe6c20000 0 0x100>;
+               interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       scifb1: serial@e6c30000 {
+               compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
+               reg = <0 0xe6c30000 0 0x100>;
+               interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
        scifa0: serial@e6c40000 {
                compatible = "renesas,scifa-r8a73a4", "renesas,scifa";
                reg = <0 0xe6c40000 0 0x100>;
                status = "disabled";
        };
 
-       scifb2: serial@e6c20000 {
-               compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
-               reg = <0 0xe6c20000 0 0x100>;
-               interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
-               status = "disabled";
-       };
-
-       scifb3: serial@e6c30000 {
-               compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
-               reg = <0 0xe6c30000 0 0x100>;
-               interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
-               status = "disabled";
-       };
-
-       scifb4: serial@e6ce0000 {
+       scifb2: serial@e6ce0000 {
                compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
                reg = <0 0xe6ce0000 0 0x100>;
                interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
-       scifb5: serial@e6cf0000 {
+       scifb3: serial@e6cf0000 {
                compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
                reg = <0 0xe6cf0000 0 0x100>;
                interrupts = <0 151 IRQ_TYPE_LEVEL_HIGH>;
                status = "disabled";
        };
 
-       mmcif0: mmc@ee200000 {
-               compatible = "renesas,sh-mmcif";
-               reg = <0 0xee200000 0 0x80>;
-               interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
-               reg-io-width = <4>;
-               status = "disabled";
-       };
-
-       mmcif1: mmc@ee220000 {
-               compatible = "renesas,sh-mmcif";
-               reg = <0 0xee220000 0 0x80>;
-               interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>;
-               reg-io-width = <4>;
-               status = "disabled";
-       };
-
-       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>;
-       };
-
        sdhi0: sd@ee100000 {
                compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee100000 0 0x100>;
                cap-sd-highspeed;
                status = "disabled";
        };
+
+       mmcif0: mmc@ee200000 {
+               compatible = "renesas,sh-mmcif";
+               reg = <0 0xee200000 0 0x80>;
+               interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
+               reg-io-width = <4>;
+               status = "disabled";
+       };
+
+       mmcif1: mmc@ee220000 {
+               compatible = "renesas,sh-mmcif";
+               reg = <0 0xee220000 0 0x80>;
+               interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>;
+               reg-io-width = <4>;
+               status = "disabled";
+       };
+
+       gic: interrupt-controller@f1001000 {
+               compatible = "arm,cortex-a15-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0 0xf1001000 0 0x1000>,
+                       <0 0xf1002000 0 0x1000>,
+                       <0 0xf1004000 0 0x2000>,
+                       <0 0xf1006000 0 0x2000>;
+               interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
 };
index effb7b46f13172d5cb30180caa283a05fd9a5a72..d4af4d86c6b03d01bbc5ba75b015f76d5e5e4cd6 100644 (file)
@@ -25,6 +25,7 @@
 
        chosen {
                bootargs = "console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
+               stdout-path = &scifa1;
        };
 
        memory {
@@ -77,7 +78,7 @@
                regulator-boot-on;
        };
 
-       gpio-keys {
+       keyboard {
                compatible = "gpio-keys";
 
                power-key {
 
        status = "okay";
 };
+
+&tmu0 {
+       status = "okay";
+};
index d46c213a17ad5de43972fd4f7b28beda61b53347..a8a674bafa677f097a882c5557fdcbedd0e90e57 100644 (file)
@@ -71,6 +71,7 @@
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A7740_CLK_INTCA>;
        };
 
        /* irqpin1: IRQ8 - IRQ15 */
@@ -91,6 +92,7 @@
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A7740_CLK_INTCA>;
        };
 
        /* irqpin2: IRQ16 - IRQ23 */
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A7740_CLK_INTCA>;
        };
 
        /* irqpin3: IRQ24 - IRQ31 */
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH
                              0 149 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A7740_CLK_INTCA>;
        };
 
        ether: ethernet@e9a00000 {
                compatible = "renesas,scifa-r8a7740", "renesas,scifa";
                reg = <0xe6c60000 0x100>;
                interrupts = <0 102 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&mstp2_clks R8A7740_CLK_SCIFA0>;
+               clocks = <&mstp2_clks R8A7740_CLK_SCIFA2>;
                clock-names = "sci_ick";
                status = "disabled";
        };
                status = "disabled";
        };
 
+       tmu0: timer@fff80000 {
+               compatible = "renesas,tmu-r8a7740", "renesas,tmu";
+               reg = <0xfff80000 0x2c>;
+               interrupts = <0 198 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 199 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 200 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7740_CLK_TMU0>;
+               clock-names = "fck";
+
+               #renesas,channels = <3>;
+
+               status = "disabled";
+       };
+
+       tmu1: timer@fff90000 {
+               compatible = "renesas,tmu-r8a7740", "renesas,tmu";
+               reg = <0xfff90000 0x2c>;
+               interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 171 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 172 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7740_CLK_TMU1>;
+               clock-names = "fck";
+
+               #renesas,channels = <3>;
+
+               status = "disabled";
+       };
+
        clocks {
                #address-cells = <1>;
                #size-cells = <1>;
                        clocks = <&cpg_clocks R8A7740_CLK_S>,
                                 <&cpg_clocks R8A7740_CLK_S>, <&sub_clk>,
                                 <&cpg_clocks R8A7740_CLK_B>,
-                                <&sub_clk>, <&sub_clk>,
+                                <&cpg_clocks R8A7740_CLK_HPP>, <&sub_clk>,
                                 <&cpg_clocks R8A7740_CLK_B>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
                mstp2_clks: mstp2_clks@e6150138 {
                        compatible = "renesas,r8a7740-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0xe6150138 4>, <0xe6150040 4>;
-                       clocks = <&sub_clk>, <&sub_clk>,
-                                <&cpg_clocks R8A7740_CLK_HP>,
+                       clocks = <&sub_clk>, <&cpg_clocks R8A7740_CLK_HP>,
+                                <&sub_clk>, <&cpg_clocks R8A7740_CLK_HP>,
                                 <&cpg_clocks R8A7740_CLK_HP>,
                                 <&cpg_clocks R8A7740_CLK_HP>,
                                 <&cpg_clocks R8A7740_CLK_HP>,
                                 <&sub_clk>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
-                               R8A7740_CLK_SCIFA6 R8A7740_CLK_SCIFA7
+                               R8A7740_CLK_SCIFA6 R8A7740_CLK_INTCA
+                               R8A7740_CLK_SCIFA7
                                R8A7740_CLK_DMAC1 R8A7740_CLK_DMAC2
                                R8A7740_CLK_DMAC3 R8A7740_CLK_USBDMAC
                                R8A7740_CLK_SCIFA5 R8A7740_CLK_SCIFB
                                R8A7740_CLK_SCIFA4
                        >;
                        clock-output-names =
-                               "scifa6", "scifa7", "dmac1", "dmac2", "dmac3",
+                               "scifa6", "intca",
+                               "scifa7", "dmac1", "dmac2", "dmac3",
                                "usbdmac", "scifa5", "scifb", "scifa0", "scifa1",
                                "scifa2", "scifa3", "scifa4";
                };
index 3342c74c5de890b1aa845a8a32835bd1dd9fd7a9..04c0c37bb7843997f127535e7f73e93cbf8bb8bb 100644 (file)
@@ -28,7 +28,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
+               bootargs = "ignore_loglevel root=/dev/nfs ip=dhcp rw";
+               stdout-path = &scif0;
        };
 
        memory {
        status = "okay";
 };
 
+&tmu0 {
+       status = "okay";
+};
+
 &pfc {
        scif0_pins: serial0 {
                renesas,groups = "scif0_data_a", "scif0_ctrl";
index 315ec62cb96b9ab5a9aed287ae2edd76a8c40608..ef8533910029620e5cb974bdafece1c2f90a3e1d 100644 (file)
                status = "disabled";
        };
 
+       tmu0: timer@ffd80000 {
+               compatible = "renesas,tmu-r8a7778", "renesas,tmu";
+               reg = <0xffd80000 0x30>;
+               interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 33 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 34 IRQ_TYPE_LEVEL_HIGH>;
+
+               #renesas,channels = <3>;
+
+               status = "disabled";
+       };
+
+       tmu1: timer@ffd81000 {
+               compatible = "renesas,tmu-r8a7778", "renesas,tmu";
+               reg = <0xffd81000 0x30>;
+               interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 37 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 38 IRQ_TYPE_LEVEL_HIGH>;
+
+               #renesas,channels = <3>;
+
+               status = "disabled";
+       };
+
+       tmu2: timer@ffd82000 {
+               compatible = "renesas,tmu-r8a7778", "renesas,tmu";
+               reg = <0xffd82000 0x30>;
+               interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 41 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 42 IRQ_TYPE_LEVEL_HIGH>;
+
+               #renesas,channels = <3>;
+
+               status = "disabled";
+       };
+
        scif0: serial@ffe40000 {
                compatible = "renesas,scif-r8a7778", "renesas,scif";
                reg = <0xffe40000 0x100>;
                compatible = "renesas,sdhi-r8a7778";
                reg = <0xffe4c000 0x100>;
                interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>;
-               cap-sd-highspeed;
-               cap-sdio-irq;
                status = "disabled";
        };
 
                compatible = "renesas,sdhi-r8a7778";
                reg = <0xffe4d000 0x100>;
                interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>;
-               cap-sd-highspeed;
-               cap-sdio-irq;
                status = "disabled";
        };
 
                compatible = "renesas,sdhi-r8a7778";
                reg = <0xffe4f000 0x100>;
                interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
-               cap-sd-highspeed;
-               cap-sdio-irq;
                status = "disabled";
        };
 
index c160404e4d405eb2acedc5affd96781ee8bca162..e83d40e24bcd48113d6bd1051f44413710af8b59 100644 (file)
@@ -25,6 +25,7 @@
 
        chosen {
                bootargs = "console=ttySC2,115200 ignore_loglevel root=/dev/nfs ip=on";
+               stdout-path = &scif2;
        };
 
        memory {
                        gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;
                };
        };
+
+       vga-encoder {
+               compatible = "adi,adv7123";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               vga_enc_in: endpoint {
+                                       remote-endpoint = <&du_out_rgb0>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               vga_enc_out: endpoint {
+                                       remote-endpoint = <&vga_in>;
+                               };
+                       };
+               };
+       };
+
+       vga {
+               compatible = "vga-connector";
+
+               port {
+                       vga_in: endpoint {
+                               remote-endpoint = <&vga_enc_out>;
+                       };
+               };
+       };
+
+       lvds-encoder {
+               compatible = "thine,thc63lvdm83d";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               lvds_enc_in: endpoint {
+                                       remote-endpoint = <&du_out_rgb1>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               lvds_connector: endpoint {
+                               };
+                       };
+               };
+       };
+};
+
+&du {
+       pinctrl-0 = <&du_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+
+       ports {
+               port@0 {
+                       endpoint {
+                               remote-endpoint = <&vga_enc_in>;
+                       };
+               };
+               port@1 {
+                       endpoint {
+                               remote-endpoint = <&lvds_enc_in>;
+                       };
+               };
+       };
 };
 
 &irqpin0 {
 };
 
 &pfc {
+       du_pins: du {
+               du0 {
+                       renesas,groups = "du0_rgb888", "du0_sync_1", "du0_clk_out_0";
+                       renesas,function = "du0";
+               };
+               du1 {
+                       renesas,groups = "du1_rgb666", "du1_sync_1", "du1_clk_out";
+                       renesas,function = "du1";
+               };
+       };
+
        lan0_pins: lan0 {
                intc {
                        renesas,groups = "intc_irq1_b";
index 7cfba9aa1b415cc180dae8f0a75901fb5921f488..ede9a29e4bc601ae15d3595014235da5b5436f3a 100644 (file)
        };
 
        sata: sata@fc600000 {
-               compatible = "renesas,rcar-sata";
+               compatible = "renesas,sata-r8a7779", "renesas,rcar-sata";
                reg = <0xfc600000 0x2000>;
                interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp1_clks R8A7779_CLK_SATA>;
                reg = <0xffe4c000 0x100>;
                interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7779_CLK_SDHI0>;
-               cap-sd-highspeed;
-               cap-sdio-irq;
                status = "disabled";
        };
 
                reg = <0xffe4d000 0x100>;
                interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7779_CLK_SDHI1>;
-               cap-sd-highspeed;
-               cap-sdio-irq;
                status = "disabled";
        };
 
                reg = <0xffe4e000 0x100>;
                interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7779_CLK_SDHI2>;
-               cap-sd-highspeed;
-               cap-sdio-irq;
                status = "disabled";
        };
 
                reg = <0xffe4f000 0x100>;
                interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7779_CLK_SDHI3>;
-               cap-sd-highspeed;
-               cap-sdio-irq;
                status = "disabled";
        };
 
                status = "disabled";
        };
 
+       du: display@fff80000 {
+               compatible = "renesas,du-r8a7779";
+               reg = <0 0xfff80000 0 0x40000>;
+               interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7779_CLK_DU>;
+               status = "disabled";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               du_out_rgb0: endpoint {
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               du_out_rgb1: endpoint {
+                               };
+                       };
+               };
+       };
+
        clocks {
                #address-cells = <1>;
                #size-cells = <1>;
index 69098b906b3919d2653dd244b6cc3220d6dfb741..636d53bb87a27062b79afae3f009629e52fd63d3 100644 (file)
@@ -9,6 +9,34 @@
  * kind, whether express or implied.
  */
 
+/*
+ * SSI-AK4643
+ *
+ * SW1: 1: AK4643
+ *      2: CN22
+ *      3: ADV7511
+ *
+ * This command is required when Playback/Capture
+ *
+ *     amixer set "LINEOUT Mixer DACL" on
+ *     amixer set "DVC Out" 100%
+ *     amixer set "DVC In" 100%
+ *
+ * You can use Mute
+ *
+ *     amixer set "DVC Out Mute" on
+ *     amixer set "DVC In Mute" on
+ *
+ * You can use Volume Ramp
+ *
+ *     amixer set "DVC Out Ramp Up Rate"   "0.125 dB/64 steps"
+ *     amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
+ *     amixer set "DVC Out Ramp" on
+ *     aplay xxx.wav &
+ *     amixer set "DVC Out"  80%  // Volume Down
+ *     amixer set "DVC Out" 100%  // Volume Up
+ */
+
 /dts-v1/;
 #include "r8a7790.dtsi"
 #include <dt-bindings/gpio/gpio.h>
        compatible = "renesas,lager", "renesas,r8a7790";
 
        aliases {
-               serial6 = &scif0;
-               serial7 = &scif1;
+               serial6 = &scifa0;
+               serial7 = &scifa1;
        };
 
        chosen {
                bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               stdout-path = &scifa0;
        };
 
        memory@40000000 {
@@ -42,7 +71,7 @@
                #size-cells = <1>;
        };
 
-       gpio_keys {
+       keyboard {
                compatible = "gpio-keys";
 
                button@1 {
                states = <3300000 1
                          1800000 0>;
        };
+
+       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>;
+               };
+       };
+
+       vga-encoder {
+               compatible = "adi,adv7123";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               adv7123_in: endpoint {
+                                       remote-endpoint = <&du_out_rgb>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               adv7123_out: endpoint {
+                                       remote-endpoint = <&vga_in>;
+                               };
+                       };
+               };
+       };
+
+       vga {
+               compatible = "vga-connector";
+
+               port {
+                       vga_in: endpoint {
+                               remote-endpoint = <&adv7123_out>;
+                       };
+               };
+       };
+};
+
+&du {
+       pinctrl-0 = <&du_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+
+       ports {
+               port@0 {
+                       endpoint {
+                               remote-endpoint = <&adv7123_in>;
+                       };
+               };
+               port@2 {
+                       lvds_connector: endpoint {
+                       };
+               };
+       };
 };
 
 &extal_clk {
 };
 
 &pfc {
-       pinctrl-0 = <&du_pins>;
-       pinctrl-names = "default";
-
        du_pins: du {
                renesas,groups = "du_rgb666", "du_sync_1", "du_clk_out_0";
                renesas,function = "du";
        };
 
-       scif0_pins: serial0 {
-               renesas,groups = "scif0_data";
-               renesas,function = "scif0";
+       scifa0_pins: serial0 {
+               renesas,groups = "scifa0_data";
+               renesas,function = "scifa0";
        };
 
        ether_pins: ether {
                renesas,function = "intc";
        };
 
-       scif1_pins: serial1 {
-               renesas,groups = "scif1_data";
-               renesas,function = "scif1";
+       scifa1_pins: serial1 {
+               renesas,groups = "scifa1_data";
+               renesas,function = "scifa1";
        };
 
        sdhi0_pins: sd0 {
                renesas,function = "iic3";
        };
 
+       hsusb_pins: hsusb {
+               renesas,groups = "usb0_ovc_vbus";
+               renesas,function = "usb0";
+       };
+
        usb0_pins: usb0 {
                renesas,groups = "usb0";
                renesas,function = "usb0";
                renesas,groups = "vin1_data8", "vin1_clk";
                renesas,function = "vin1";
        };
+
+       sound_pins: sound {
+               renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
+               renesas,function = "ssi";
+       };
+
+       sound_clk_pins: sound_clk {
+               renesas,groups = "audio_clk_a";
+               renesas,function = "audio_clk";
+       };
 };
 
 &ether {
        };
 };
 
-&scif0 {
-       pinctrl-0 = <&scif0_pins>;
+&scifa0 {
+       pinctrl-0 = <&scifa0_pins>;
        pinctrl-names = "default";
 
        status = "okay";
 };
 
-&scif1 {
-       pinctrl-0 = <&scif1_pins>;
+&scifa1 {
+       pinctrl-0 = <&scifa1_pins>;
        pinctrl-names = "default";
 
        status = "okay";
        pinctrl-0 = <&iic2_pins>;
        pinctrl-names = "default";
 
+       clock-frequency = <100000>;
+
+       ak4643: sound-codec@12 {
+               compatible = "asahi-kasei,ak4643";
+               #sound-dai-cells = <0>;
+               reg = <0x12>;
+       };
+
        composite-in@20 {
                compatible = "adi,adv7180";
                reg = <0x20>;
        pinctrl-names = "default";
 };
 
+&xhci {
+       status = "okay";
+       pinctrl-0 = <&usb2_pins>;
+       pinctrl-names = "default";
+};
+
 &pci2 {
        status = "okay";
        pinctrl-0 = <&usb2_pins>;
        pinctrl-names = "default";
 };
 
+&hsusb {
+       status = "okay";
+       pinctrl-0 = <&hsusb_pins>;
+       pinctrl-names = "default";
+       renesas,enable-gpio = <&gpio5 18 GPIO_ACTIVE_HIGH>;
+};
+
+&usbphy {
+       status = "okay";
+};
+
 /* composite video input */
 &vin1 {
        pinctrl-0 = <&vin1_pins>;
                };
        };
 };
+
+&rcar_sound {
+       pinctrl-0 = <&sound_pins &sound_clk_pins>;
+       pinctrl-names = "default";
+
+       #sound-dai-cells = <0>;
+
+       status = "okay";
+
+       rcar_sound,dai {
+               dai0 {
+                       playback = <&ssi0 &src2 &dvc0>;
+                       capture  = <&ssi1 &src3 &dvc1>;
+               };
+       };
+};
+
+&ssi1 {
+       shared-pin;
+};
index d0e17733dc1a340608b10b3f4f595e93ec53d45d..af7e255f629e32734c8307a5df23cee0c6ed73b7 100644 (file)
                #dma-cells = <1>;
                dma-channels = <15>;
        };
+
+       audma0: dma-controller@ec700000 {
+               compatible = "renesas,rcar-dmac";
+               reg = <0 0xec700000 0 0x10000>;
+               interrupts =    <0 346 IRQ_TYPE_LEVEL_HIGH
+                                0 320 IRQ_TYPE_LEVEL_HIGH
+                                0 321 IRQ_TYPE_LEVEL_HIGH
+                                0 322 IRQ_TYPE_LEVEL_HIGH
+                                0 323 IRQ_TYPE_LEVEL_HIGH
+                                0 324 IRQ_TYPE_LEVEL_HIGH
+                                0 325 IRQ_TYPE_LEVEL_HIGH
+                                0 326 IRQ_TYPE_LEVEL_HIGH
+                                0 327 IRQ_TYPE_LEVEL_HIGH
+                                0 328 IRQ_TYPE_LEVEL_HIGH
+                                0 329 IRQ_TYPE_LEVEL_HIGH
+                                0 330 IRQ_TYPE_LEVEL_HIGH
+                                0 331 IRQ_TYPE_LEVEL_HIGH
+                                0 332 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "error",
+                               "ch0", "ch1", "ch2", "ch3",
+                               "ch4", "ch5", "ch6", "ch7",
+                               "ch8", "ch9", "ch10", "ch11",
+                               "ch12";
+               clocks = <&mstp5_clks R8A7790_CLK_AUDIO_DMAC0>;
+               clock-names = "fck";
+               #dma-cells = <1>;
+               dma-channels = <13>;
+       };
+
+       audma1: dma-controller@ec720000 {
+               compatible = "renesas,rcar-dmac";
+               reg = <0 0xec720000 0 0x10000>;
+               interrupts =    <0 347 IRQ_TYPE_LEVEL_HIGH
+                                0 333 IRQ_TYPE_LEVEL_HIGH
+                                0 334 IRQ_TYPE_LEVEL_HIGH
+                                0 335 IRQ_TYPE_LEVEL_HIGH
+                                0 336 IRQ_TYPE_LEVEL_HIGH
+                                0 337 IRQ_TYPE_LEVEL_HIGH
+                                0 338 IRQ_TYPE_LEVEL_HIGH
+                                0 339 IRQ_TYPE_LEVEL_HIGH
+                                0 340 IRQ_TYPE_LEVEL_HIGH
+                                0 341 IRQ_TYPE_LEVEL_HIGH
+                                0 342 IRQ_TYPE_LEVEL_HIGH
+                                0 343 IRQ_TYPE_LEVEL_HIGH
+                                0 344 IRQ_TYPE_LEVEL_HIGH
+                                0 345 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "error",
+                               "ch0", "ch1", "ch2", "ch3",
+                               "ch4", "ch5", "ch6", "ch7",
+                               "ch8", "ch9", "ch10", "ch11",
+                               "ch12";
+               clocks = <&mstp5_clks R8A7790_CLK_AUDIO_DMAC1>;
+               clock-names = "fck";
+               #dma-cells = <1>;
+               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>;
                reg = <0 0xe6500000 0 0x425>;
                interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
+               dmas = <&dmac0 0x61>, <&dmac0 0x62>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xe6510000 0 0x425>;
                interrupts = <0 175 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_IIC1>;
+               dmas = <&dmac0 0x65>, <&dmac0 0x66>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xe6520000 0 0x425>;
                interrupts = <0 176 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_IIC2>;
+               dmas = <&dmac0 0x69>, <&dmac0 0x6a>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xe60b0000 0 0x425>;
                interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp9_clks R8A7790_CLK_IICDVFS>;
+               dmas = <&dmac0 0x77>, <&dmac0 0x78>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
-       mmcif0: mmcif@ee200000 {
+       mmcif0: mmc@ee200000 {
                compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
                reg = <0 0xee200000 0 0x80>;
                interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
+               dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
+               dma-names = "tx", "rx";
                reg-io-width = <4>;
                status = "disabled";
        };
                reg = <0 0xee220000 0 0x80>;
                interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_MMCIF1>;
+               dmas = <&dmac0 0xe1>, <&dmac0 0xe2>;
+               dma-names = "tx", "rx";
                reg-io-width = <4>;
                status = "disabled";
        };
                reg = <0 0xee100000 0 0x200>;
                interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI0>;
-               cap-sd-highspeed;
                status = "disabled";
        };
 
                reg = <0 0xee120000 0 0x200>;
                interrupts = <0 166 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI1>;
-               cap-sd-highspeed;
                status = "disabled";
        };
 
                reg = <0 0xee140000 0 0x100>;
                interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI2>;
-               cap-sd-highspeed;
                status = "disabled";
        };
 
                reg = <0 0xee160000 0 0x100>;
                interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI3>;
-               cap-sd-highspeed;
                status = "disabled";
        };
 
                status = "disabled";
        };
 
+       hsusb: usb@e6590000 {
+               compatible = "renesas,usbhs-r8a7790";
+               reg = <0 0xe6590000 0 0x100>;
+               interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp7_clks R8A7790_CLK_HSUSB>;
+               renesas,buswait = <4>;
+               phys = <&usb0 1>;
+               phy-names = "usb";
+               status = "disabled";
+       };
+
+       usbphy: usb-phy@e6590100 {
+               compatible = "renesas,usb-phy-r8a7790";
+               reg = <0 0xe6590100 0 0x100>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&mstp7_clks R8A7790_CLK_HSUSB>;
+               clock-names = "usbhs";
+               status = "disabled";
+
+               usb0: usb-channel@0 {
+                       reg = <0>;
+                       #phy-cells = <1>;
+               };
+               usb2: usb-channel@2 {
+                       reg = <2>;
+                       #phy-cells = <1>;
+               };
+       };
+
        vin0: video@e6ef0000 {
                compatible = "renesas,vin-r8a7790";
                clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
                status = "disabled";
        };
 
+       vsp1@fe920000 {
+               compatible = "renesas,vsp1";
+               reg = <0 0xfe920000 0 0x8000>;
+               interrupts = <0 266 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7790_CLK_VSP1_R>;
+
+               renesas,has-sru;
+               renesas,#rpf = <5>;
+               renesas,#uds = <1>;
+               renesas,#wpf = <4>;
+       };
+
+       vsp1@fe928000 {
+               compatible = "renesas,vsp1";
+               reg = <0 0xfe928000 0 0x8000>;
+               interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7790_CLK_VSP1_S>;
+
+               renesas,has-lut;
+               renesas,has-sru;
+               renesas,#rpf = <5>;
+               renesas,#uds = <3>;
+               renesas,#wpf = <4>;
+       };
+
+       vsp1@fe930000 {
+               compatible = "renesas,vsp1";
+               reg = <0 0xfe930000 0 0x8000>;
+               interrupts = <0 246 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7790_CLK_VSP1_DU0>;
+
+               renesas,has-lif;
+               renesas,has-lut;
+               renesas,#rpf = <4>;
+               renesas,#uds = <1>;
+               renesas,#wpf = <4>;
+       };
+
+       vsp1@fe938000 {
+               compatible = "renesas,vsp1";
+               reg = <0 0xfe938000 0 0x8000>;
+               interrupts = <0 247 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7790_CLK_VSP1_DU1>;
+
+               renesas,has-lif;
+               renesas,has-lut;
+               renesas,#rpf = <4>;
+               renesas,#uds = <1>;
+               renesas,#wpf = <4>;
+       };
+
+       du: display@feb00000 {
+               compatible = "renesas,du-r8a7790";
+               reg = <0 0xfeb00000 0 0x70000>,
+                     <0 0xfeb90000 0 0x1c>,
+                     <0 0xfeb94000 0 0x1c>;
+               reg-names = "du", "lvds.0", "lvds.1";
+               interrupts = <0 256 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 268 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 269 IRQ_TYPE_LEVEL_HIGH>;
+               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>;
+               clock-names = "du.0", "du.1", "du.2", "lvds.0", "lvds.1";
+               status = "disabled";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               du_out_rgb: endpoint {
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               du_out_lvds0: endpoint {
+                               };
+                       };
+                       port@2 {
+                               reg = <2>;
+                               du_out_lvds1: endpoint {
+                               };
+                       };
+               };
+       };
+
        clocks {
                #address-cells = <2>;
                #size-cells = <2>;
                        #clock-cells = <0>;
                        clock-output-names = "sd2";
                };
-               sd3_clk: sd3_clk@e615007c {
+               sd3_clk: sd3_clk@e615026c {
                        compatible = "renesas,r8a7790-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 = "sd3";
                mstp1_clks: mstp1_clks@e6150134 {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150134 0 4>, <0 0xe6150038 0 4>;
-                       clocks = <&m2_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>,
-                                <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>,
-                                <&zs_clk>;
+                       clocks = <&zs_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>, <&m2_clk>,
+                                <&zs_clk>, <&p_clk>, <&zg_clk>, <&zs_clk>, <&zs_clk>,
+                                <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>,
+                                <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
-                               R8A7790_CLK_JPU R8A7790_CLK_TMU1 R8A7790_CLK_TMU3 R8A7790_CLK_TMU2
-                               R8A7790_CLK_CMT0 R8A7790_CLK_TMU0 R8A7790_CLK_VSP1_DU1
-                               R8A7790_CLK_VSP1_DU0 R8A7790_CLK_VSP1_R R8A7790_CLK_VSP1_S
+                               R8A7790_CLK_VCP1 R8A7790_CLK_VCP0 R8A7790_CLK_VPC1
+                               R8A7790_CLK_VPC0 R8A7790_CLK_JPU R8A7790_CLK_SSP1
+                               R8A7790_CLK_TMU1 R8A7790_CLK_3DG R8A7790_CLK_2DDMAC
+                               R8A7790_CLK_FDP1_2 R8A7790_CLK_FDP1_1 R8A7790_CLK_FDP1_0
+                               R8A7790_CLK_TMU3 R8A7790_CLK_TMU2 R8A7790_CLK_CMT0
+                               R8A7790_CLK_TMU0 R8A7790_CLK_VSP1_DU1 R8A7790_CLK_VSP1_DU0
+                               R8A7790_CLK_VSP1_R R8A7790_CLK_VSP1_S
                        >;
                        clock-output-names =
-                               "jpu", "tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1",
-                               "vsp1-du0", "vsp1-rt", "vsp1-sy";
+                               "vcp1", "vcp0", "vpc1", "vpc0", "jpu", "ssp1",
+                               "tmu1", "3dg", "2ddmac", "fdp1-2", "fdp1-1",
+                               "fdp1-0", "tmu3", "tmu2", "cmt0", "tmu0",
+                               "vsp1-du1", "vsp1-du0", "vsp1-rt", "vsp1-sy";
                };
                mstp2_clks: mstp2_clks@e6150138 {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
                        clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&sd3_clk>,
                                 <&sd2_clk>, <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, <&mmc0_clk>,
-                                <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>;
+                                <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>,
+                                <&hp_clk>, <&hp_clk>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
                                R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
                                R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0
                                R8A7790_CLK_IIC0 R8A7790_CLK_PCIEC R8A7790_CLK_IIC1 R8A7790_CLK_SSUSB R8A7790_CLK_CMT1
+                               R8A7790_CLK_USBDMAC0 R8A7790_CLK_USBDMAC1
                        >;
                        clock-output-names =
                                "iic2", "tpu0", "mmcif1", "sdhi3",
                                "sdhi2", "sdhi1", "sdhi0", "mmcif0",
-                               "iic0", "pciec", "iic1", "ssusb", "cmt1";
+                               "iic0", "pciec", "iic1", "ssusb", "cmt1",
+                               "usbdmac0", "usbdmac1";
                };
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
-                       clocks = <&extal_clk>, <&p_clk>;
+                       clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>;
                        #clock-cells = <1>;
-                       renesas,clock-indices = <R8A7790_CLK_THERMAL R8A7790_CLK_PWM>;
-                       clock-output-names = "thermal", "pwm";
+                       renesas,clock-indices = <R8A7790_CLK_AUDIO_DMAC0 R8A7790_CLK_AUDIO_DMAC1
+                                                R8A7790_CLK_THERMAL R8A7790_CLK_PWM>;
+                       clock-output-names = "audmac0", "audmac1", "thermal", "pwm";
                };
                mstp7_clks: mstp7_clks@e615014c {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                status = "disabled";
        };
 
+       xhci: usb@ee000000 {
+               compatible = "renesas,xhci-r8a7790";
+               reg = <0 0xee000000 0 0xc00>;
+               interrupts = <0 101 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7790_CLK_SSUSB>;
+               phys = <&usb2 1>;
+               phy-names = "usb";
+               status = "disabled";
+       };
+
        pci0: pci@ee090000 {
                compatible = "renesas,pci-r8a7790";
                device_type = "pci";
                interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
                                 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
                                 0x1000 0 0 2 &gic 0 108 IRQ_TYPE_LEVEL_HIGH>;
+
+               usb@0,1 {
+                       reg = <0x800 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb0 0>;
+                       phy-names = "usb";
+               };
+
+               usb@0,2 {
+                       reg = <0x1000 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb0 0>;
+                       phy-names = "usb";
+               };
        };
 
        pci1: pci@ee0b0000 {
                interrupt-map = <0x0000 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
                                 0x0800 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
                                 0x1000 0 0 2 &gic 0 113 IRQ_TYPE_LEVEL_HIGH>;
+
+               usb@0,1 {
+                       reg = <0x800 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb2 0>;
+                       phy-names = "usb";
+               };
+
+               usb@0,2 {
+                       reg = <0x1000 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb2 0>;
+                       phy-names = "usb";
+               };
        };
 
        pciec: pcie@fe000000 {
                status = "disabled";
        };
 
-       rcar_sound: rcar_sound@0xec500000 {
+       rcar_sound: rcar_sound@ec500000 {
                #sound-dai-cells = <1>;
                compatible =  "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2", "renesas,rcar_sound";
                reg =   <0 0xec500000 0 0x1000>, /* SCU */
index f1b56de10205f14bdcd829900368c31dae067a39..740e38678032a7accf62dbaec94a4bd9a4c33dc7 100644 (file)
@@ -23,6 +23,7 @@
 
        chosen {
                bootargs = "console=ttySC0,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               stdout-path = &scif0;
        };
 
        memory@40000000 {
        pinctrl-names = "default";
 };
 
+&hsusb {
+       status = "okay";
+       pinctrl-0 = <&usb0_pins>;
+       pinctrl-names = "default";
+       renesas,enable-gpio = <&gpio5 31 GPIO_ACTIVE_HIGH>;
+};
+
+&usbphy {
+       status = "okay";
+};
+
 &pcie_bus_clk {
        status = "okay";
 };
index 07550e775e8047111e2f280ef8d94da993970ebb..990af167c551492cca23849514fb7e86a0f8e86c 100644 (file)
  * kind, whether express or implied.
  */
 
+/*
+ * SSI-AK4643
+ *
+ * SW1: 1: AK4643
+ *      2: CN22
+ *      3: ADV7511
+ *
+ * This command is required when Playback/Capture
+ *
+ *     amixer set "LINEOUT Mixer DACL" on
+ *     amixer set "DVC Out" 100%
+ *     amixer set "DVC In" 100%
+ *
+ * You can use Mute
+ *
+ *     amixer set "DVC Out Mute" on
+ *     amixer set "DVC In Mute" on
+ *
+ * You can use Volume Ramp
+ *
+ *     amixer set "DVC Out Ramp Up Rate"   "0.125 dB/64 steps"
+ *     amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
+ *     amixer set "DVC Out Ramp" on
+ *     aplay xxx.wav &
+ *     amixer set "DVC Out"  80%  // Volume Down
+ *     amixer set "DVC Out" 100%  // Volume Up
+ */
+
 /dts-v1/;
 #include "r8a7791.dtsi"
 #include <dt-bindings/gpio/gpio.h>
@@ -25,7 +53,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               stdout-path = &scif0;
        };
 
        memory@40000000 {
@@ -43,7 +72,7 @@
                #size-cells = <1>;
        };
 
-       gpio-keys {
+       keyboard {
                compatible = "gpio-keys";
 
                key-1 {
                compatible = "gpio-leds";
                led6 {
                        gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+                       label = "LED6";
                };
                led7 {
                        gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+                       label = "LED7";
                };
                led8 {
                        gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+                       label = "LED8";
                };
        };
 
                states = <3300000 1
                          1800000 0>;
        };
+
+       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>;
+               };
+       };
+};
+
+&du {
+       pinctrl-0 = <&du_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+
+       ports {
+               port@1 {
+                       lvds_connector: endpoint {
+                       };
+               };
+       };
 };
 
 &extal_clk {
 };
 
 &pfc {
-       pinctrl-0 = <&du_pins>;
-       pinctrl-names = "default";
-
        i2c2_pins: i2c2 {
                renesas,groups = "i2c2";
                renesas,function = "i2c2";
                renesas,groups = "vin1_data8", "vin1_clk";
                renesas,function = "vin1";
        };
+
+       sound_pins: sound {
+               renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
+               renesas,function = "ssi";
+       };
+
+       sound_clk_pins: sound_clk {
+               renesas,groups = "audio_clk_a";
+               renesas,function = "audio_clk";
+       };
 };
 
 &ether {
        pinctrl-names = "default";
 
        status = "okay";
-       clock-frequency = <400000>;
+       clock-frequency = <100000>;
+
+       ak4643: sound-codec@12 {
+               compatible = "asahi-kasei,ak4643";
+               #sound-dai-cells = <0>;
+               reg = <0x12>;
+       };
 
        composite-in@20 {
                compatible = "adi,adv7180";
        pinctrl-names = "default";
 };
 
+&hsusb {
+       status = "okay";
+       pinctrl-0 = <&usb0_pins>;
+       pinctrl-names = "default";
+       renesas,enable-gpio = <&gpio5 31 GPIO_ACTIVE_HIGH>;
+};
+
+&usbphy {
+       status = "okay";
+};
+
 &pcie_bus_clk {
        status = "okay";
 };
                };
        };
 };
+
+&rcar_sound {
+       pinctrl-0 = <&sound_pins &sound_clk_pins>;
+       pinctrl-names = "default";
+
+       #sound-dai-cells = <0>;
+
+       status = "okay";
+
+       rcar_sound,dai {
+               dai0 {
+                       playback = <&ssi0 &src2 &dvc0>;
+                       capture  = <&ssi1 &src3 &dvc1>;
+               };
+       };
+};
+
+&ssi1 {
+       shared-pin;
+};
index e06c11fa8698cfcc4cd5fc13ce1f905f554de01f..77c0beeb8d7c984c477acd634e28a70b79a4aad8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for the r8a7791 SoC
  *
- * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013-2014 Renesas Electronics Corporation
  * Copyright (C) 2013-2014 Renesas Solutions Corp.
  * Copyright (C) 2014 Cogent Embedded Inc.
  *
                dma-channels = <15>;
        };
 
+       audma0: dma-controller@ec700000 {
+               compatible = "renesas,rcar-dmac";
+               reg = <0 0xec700000 0 0x10000>;
+               interrupts =    <0 346 IRQ_TYPE_LEVEL_HIGH
+                                0 320 IRQ_TYPE_LEVEL_HIGH
+                                0 321 IRQ_TYPE_LEVEL_HIGH
+                                0 322 IRQ_TYPE_LEVEL_HIGH
+                                0 323 IRQ_TYPE_LEVEL_HIGH
+                                0 324 IRQ_TYPE_LEVEL_HIGH
+                                0 325 IRQ_TYPE_LEVEL_HIGH
+                                0 326 IRQ_TYPE_LEVEL_HIGH
+                                0 327 IRQ_TYPE_LEVEL_HIGH
+                                0 328 IRQ_TYPE_LEVEL_HIGH
+                                0 329 IRQ_TYPE_LEVEL_HIGH
+                                0 330 IRQ_TYPE_LEVEL_HIGH
+                                0 331 IRQ_TYPE_LEVEL_HIGH
+                                0 332 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "error",
+                               "ch0", "ch1", "ch2", "ch3",
+                               "ch4", "ch5", "ch6", "ch7",
+                               "ch8", "ch9", "ch10", "ch11",
+                               "ch12";
+               clocks = <&mstp5_clks R8A7791_CLK_AUDIO_DMAC0>;
+               clock-names = "fck";
+               #dma-cells = <1>;
+               dma-channels = <13>;
+       };
+
+       audma1: dma-controller@ec720000 {
+               compatible = "renesas,rcar-dmac";
+               reg = <0 0xec720000 0 0x10000>;
+               interrupts =    <0 347 IRQ_TYPE_LEVEL_HIGH
+                                0 333 IRQ_TYPE_LEVEL_HIGH
+                                0 334 IRQ_TYPE_LEVEL_HIGH
+                                0 335 IRQ_TYPE_LEVEL_HIGH
+                                0 336 IRQ_TYPE_LEVEL_HIGH
+                                0 337 IRQ_TYPE_LEVEL_HIGH
+                                0 338 IRQ_TYPE_LEVEL_HIGH
+                                0 339 IRQ_TYPE_LEVEL_HIGH
+                                0 340 IRQ_TYPE_LEVEL_HIGH
+                                0 341 IRQ_TYPE_LEVEL_HIGH
+                                0 342 IRQ_TYPE_LEVEL_HIGH
+                                0 343 IRQ_TYPE_LEVEL_HIGH
+                                0 344 IRQ_TYPE_LEVEL_HIGH
+                                0 345 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "error",
+                               "ch0", "ch1", "ch2", "ch3",
+                               "ch4", "ch5", "ch6", "ch7",
+                               "ch8", "ch9", "ch10", "ch11",
+                               "ch12";
+               clocks = <&mstp5_clks R8A7791_CLK_AUDIO_DMAC1>;
+               clock-names = "fck";
+               #dma-cells = <1>;
+               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>;
                reg = <0 0xe60b0000 0 0x425>;
                interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp9_clks R8A7791_CLK_IICDVFS>;
+               dmas = <&dmac0 0x77>, <&dmac0 0x78>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xe6500000 0 0x425>;
                interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7791_CLK_IIC0>;
+               dmas = <&dmac0 0x61>, <&dmac0 0x62>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xe6510000 0 0x425>;
                interrupts = <0 175 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7791_CLK_IIC1>;
+               dmas = <&dmac0 0x65>, <&dmac0 0x66>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                #gpio-range-cells = <3>;
        };
 
+       mmcif0: mmc@ee200000 {
+               compatible = "renesas,mmcif-r8a7791", "renesas,sh-mmcif";
+               reg = <0 0xee200000 0 0x80>;
+               interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7791_CLK_MMCIF0>;
+               dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
+               dma-names = "tx", "rx";
+               reg-io-width = <4>;
+               status = "disabled";
+       };
+
        sdhi0: sd@ee100000 {
                compatible = "renesas,sdhi-r8a7791";
                reg = <0 0xee100000 0 0x200>;
                status = "disabled";
        };
 
+       hsusb: usb@e6590000 {
+               compatible = "renesas,usbhs-r8a7791";
+               reg = <0 0xe6590000 0 0x100>;
+               interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp7_clks R8A7791_CLK_HSUSB>;
+               renesas,buswait = <4>;
+               phys = <&usb0 1>;
+               phy-names = "usb";
+               status = "disabled";
+       };
+
+       usbphy: usb-phy@e6590100 {
+               compatible = "renesas,usb-phy-r8a7791";
+               reg = <0 0xe6590100 0 0x100>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&mstp7_clks R8A7791_CLK_HSUSB>;
+               clock-names = "usbhs";
+               status = "disabled";
+
+               usb0: usb-channel@0 {
+                       reg = <0>;
+                       #phy-cells = <1>;
+               };
+               usb2: usb-channel@2 {
+                       reg = <2>;
+                       #phy-cells = <1>;
+               };
+       };
+
        vin0: video@e6ef0000 {
                compatible = "renesas,vin-r8a7791";
                clocks = <&mstp8_clks R8A7791_CLK_VIN0>;
                status = "disabled";
        };
 
+       vsp1@fe928000 {
+               compatible = "renesas,vsp1";
+               reg = <0 0xfe928000 0 0x8000>;
+               interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7791_CLK_VSP1_S>;
+
+               renesas,has-lut;
+               renesas,has-sru;
+               renesas,#rpf = <5>;
+               renesas,#uds = <3>;
+               renesas,#wpf = <4>;
+       };
+
+       vsp1@fe930000 {
+               compatible = "renesas,vsp1";
+               reg = <0 0xfe930000 0 0x8000>;
+               interrupts = <0 246 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7791_CLK_VSP1_DU0>;
+
+               renesas,has-lif;
+               renesas,has-lut;
+               renesas,#rpf = <4>;
+               renesas,#uds = <1>;
+               renesas,#wpf = <4>;
+       };
+
+       vsp1@fe938000 {
+               compatible = "renesas,vsp1";
+               reg = <0 0xfe938000 0 0x8000>;
+               interrupts = <0 247 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7791_CLK_VSP1_DU1>;
+
+               renesas,has-lif;
+               renesas,has-lut;
+               renesas,#rpf = <4>;
+               renesas,#uds = <1>;
+               renesas,#wpf = <4>;
+       };
+
+       du: display@feb00000 {
+               compatible = "renesas,du-r8a7791";
+               reg = <0 0xfeb00000 0 0x40000>,
+                     <0 0xfeb90000 0 0x1c>;
+               reg-names = "du", "lvds.0";
+               interrupts = <0 256 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 268 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp7_clks R8A7791_CLK_DU0>,
+                        <&mstp7_clks R8A7791_CLK_DU1>,
+                        <&mstp7_clks R8A7791_CLK_LVDS0>;
+               clock-names = "du.0", "du.1", "lvds.0";
+               status = "disabled";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               du_out_rgb: endpoint {
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               du_out_lvds0: endpoint {
+                               };
+                       };
+               };
+       };
+
        clocks {
                #address-cells = <2>;
                #size-cells = <2>;
                mstp1_clks: mstp1_clks@e6150134 {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150134 0 4>, <0 0xe6150038 0 4>;
-                       clocks = <&m2_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>,
-                                <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>;
+                       clocks = <&zs_clk>, <&zs_clk>, <&m2_clk>, <&zs_clk>, <&p_clk>,
+                                <&zg_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>,
+                                <&p_clk>, <&rclk_clk>, <&cp_clk>, <&zs_clk>, <&zs_clk>,
+                                <&zs_clk>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
-                               R8A7791_CLK_JPU R8A7791_CLK_TMU1 R8A7791_CLK_TMU3 R8A7791_CLK_TMU2
-                               R8A7791_CLK_CMT0 R8A7791_CLK_TMU0 R8A7791_CLK_VSP1_DU1
-                               R8A7791_CLK_VSP1_DU0 R8A7791_CLK_VSP1_S
+                               R8A7791_CLK_VCP0 R8A7791_CLK_VPC0 R8A7791_CLK_JPU
+                               R8A7791_CLK_SSP1 R8A7791_CLK_TMU1 R8A7791_CLK_3DG
+                               R8A7791_CLK_2DDMAC R8A7791_CLK_FDP1_1 R8A7791_CLK_FDP1_0
+                               R8A7791_CLK_TMU3 R8A7791_CLK_TMU2 R8A7791_CLK_CMT0
+                               R8A7791_CLK_TMU0 R8A7791_CLK_VSP1_DU1 R8A7791_CLK_VSP1_DU0
+                               R8A7791_CLK_VSP1_S
                        >;
                        clock-output-names =
-                               "jpu", "tmu1", "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du1",
-                               "vsp1-du0", "vsp1-sy";
+                               "vcp0", "vpc0", "jpu", "ssp1", "tmu1", "3dg",
+                               "2ddmac", "fdp1-1", "fdp1-0", "tmu3", "tmu2", "cmt0",
+                               "tmu0", "vsp1-du1", "vsp1-du0", "vsp1-sy";
                };
                mstp2_clks: mstp2_clks@e6150138 {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        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>,
-                                <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>;
+                                <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>,
+                                <&hp_clk>, <&hp_clk>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
                                R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1 R8A7791_CLK_SDHI0
                                R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_PCIEC R8A7791_CLK_IIC1
                                R8A7791_CLK_SSUSB R8A7791_CLK_CMT1
+                               R8A7791_CLK_USBDMAC0 R8A7791_CLK_USBDMAC1
                        >;
                        clock-output-names =
                                "tpu0", "sdhi2", "sdhi1", "sdhi0",
-                               "mmcif0", "i2c7", "pciec", "i2c8", "ssusb", "cmt1";
+                               "mmcif0", "i2c7", "pciec", "i2c8", "ssusb", "cmt1",
+                               "usbdmac0", "usbdmac1";
                };
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
-                       clocks = <&extal_clk>, <&p_clk>;
+                       clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>;
                        #clock-cells = <1>;
-                       renesas,clock-indices = <R8A7791_CLK_THERMAL R8A7791_CLK_PWM>;
-                       clock-output-names = "thermal", "pwm";
+                       renesas,clock-indices = <R8A7791_CLK_AUDIO_DMAC0 R8A7791_CLK_AUDIO_DMAC1
+                                                R8A7791_CLK_THERMAL R8A7791_CLK_PWM>;
+                       clock-output-names = "audmac0", "audmac1", "thermal", "pwm";
                };
                mstp7_clks: mstp7_clks@e615014c {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                status = "disabled";
        };
 
+       xhci: usb@ee000000 {
+               compatible = "renesas,xhci-r8a7791";
+               reg = <0 0xee000000 0 0xc00>;
+               interrupts = <0 101 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7791_CLK_SSUSB>;
+               phys = <&usb2 1>;
+               phy-names = "usb";
+               status = "disabled";
+       };
+
        pci0: pci@ee090000 {
                compatible = "renesas,pci-r8a7791";
                device_type = "pci";
                interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
                                 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH
                                 0x1000 0 0 2 &gic 0 108 IRQ_TYPE_LEVEL_HIGH>;
+
+               usb@0,1 {
+                       reg = <0x800 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb0 0>;
+                       phy-names = "usb";
+               };
+
+               usb@0,2 {
+                       reg = <0x1000 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb0 0>;
+                       phy-names = "usb";
+               };
        };
 
        pci1: pci@ee0d0000 {
                interrupt-map = <0x0000 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
                                 0x0800 0 0 1 &gic 0 113 IRQ_TYPE_LEVEL_HIGH
                                 0x1000 0 0 2 &gic 0 113 IRQ_TYPE_LEVEL_HIGH>;
+
+               usb@0,1 {
+                       reg = <0x800 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb2 0>;
+                       phy-names = "usb";
+               };
+
+               usb@0,2 {
+                       reg = <0x1000 0 0 0 0>;
+                       device_type = "pci";
+                       phys = <&usb2 0>;
+                       phy-names = "usb";
+               };
        };
 
        pciec: pcie@fe000000 {
                status = "disabled";
        };
 
-       rcar_sound: rcar_sound@0xec500000 {
+       rcar_sound: rcar_sound@ec500000 {
                #sound-dai-cells = <1>;
                compatible =  "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2", "renesas,rcar_sound";
                reg =   <0 0xec500000 0 0x1000>, /* SCU */
index 79d06ef017a05b770ac095825075ab09845e44aa..f2cf7576bf3f5a0be9f3373b033558b8345bf138 100644 (file)
@@ -20,7 +20,8 @@
        };
 
        chosen {
-               bootargs = "console=ttySC0,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
+               stdout-path = &scif2;
        };
 
        memory@40000000 {
index d4e8bce1e0b7f7ee2a0f9fbd0cbd528921f2ba0c..19c9de3f2a5ade334488161a027133538bdacc7f 100644 (file)
                status = "disabled";
        };
 
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+
        irqc0: interrupt-controller@e61c0000 {
                compatible = "renesas,irqc-r8a7794", "renesas,irqc";
                #interrupt-cells = <2>;
                mstp1_clks: mstp1_clks@e6150134 {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150134 0 4>, <0 0xe6150038 0 4>;
-                       clocks = <&p_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>,
-                                <&cp_clk>,
-                                <&zs_clk>, <&zs_clk>, <&zs_clk>;
+                       clocks = <&zs_clk>, <&zs_clk>, <&p_clk>, <&zg_clk>, <&zs_clk>,
+                                <&zs_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>, <&cp_clk>,
+                                <&zs_clk>, <&zs_clk>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
-                               R8A7794_CLK_TMU1 R8A7794_CLK_TMU3 R8A7794_CLK_TMU2
-                               R8A7794_CLK_CMT0 R8A7794_CLK_TMU0
+                               R8A7794_CLK_VCP0 R8A7794_CLK_VPC0 R8A7794_CLK_TMU1
+                               R8A7794_CLK_3DG R8A7794_CLK_2DDMAC R8A7794_CLK_FDP1_0
+                               R8A7794_CLK_TMU3 R8A7794_CLK_TMU2 R8A7794_CLK_CMT0
+                               R8A7794_CLK_TMU0 R8A7794_CLK_VSP1_DU0 R8A7794_CLK_VSP1_S
                        >;
                        clock-output-names =
-                               "tmu1", "tmu3", "tmu2", "cmt0", "tmu0";
+                               "vcp0", "vpc0", "tmu1", "3dg", "2ddmac", "fdp1-0",
+                               "tmu3", "tmu2", "cmt0", "tmu0", "vsp1-du0", "vsps";
                };
                mstp2_clks: mstp2_clks@e6150138 {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
                mstp8_clks: mstp8_clks@e6150990 {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>;
-                       clocks = <&p_clk>;
+                       clocks = <&zg_clk>, <&zg_clk>, <&p_clk>;
                        #clock-cells = <1>;
                        renesas,clock-indices = <
-                               R8A7794_CLK_ETHER
+                               R8A7794_CLK_VIN1 R8A7794_CLK_VIN0 R8A7794_CLK_ETHER
                        >;
                        clock-output-names =
-                               "ether";
+                               "vin1", "vin0", "ether";
                };
                mstp11_clks: mstp11_clks@e615099c {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
diff --git a/arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi b/arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi
new file mode 100644 (file)
index 0000000..65cb50f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Common file for the AA104XD12 panel connected to Renesas R-Car boards
+ *
+ * Copyright (C) 2014 Renesas Electronics Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/ {
+       panel {
+               compatible = "mitsubishi,aa104xd12", "panel-dpi";
+
+               width-mm = <210>;
+               height-mm = <158>;
+
+               panel-timing {
+                       /* 1024x768 @65Hz */
+                       clock-frequency = <65000000>;
+                       hactive = <1024>;
+                       vactive = <768>;
+                       hsync-len = <136>;
+                       hfront-porch = <20>;
+                       hback-porch = <160>;
+                       vfront-porch = <3>;
+                       vback-porch = <29>;
+                       vsync-len = <6>;
+               };
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&lvds_connector>;
+                       };
+               };
+       };
+};
+
+&lvds_connector {
+       remote-endpoint = <&panel_in>;
+};
index d5344510c6763f3dbd2b74c0c71593db213fdbdd..baf21ac6ce7f5a2116e65bc9439a87326597a284 100644 (file)
        };
 };
 
+&cpu0 {
+       cpu0-supply = <&vdd_arm>;
+};
+
 &i2c1 {
        status = "okay";
        clock-frequency = <400000>;
diff --git a/arch/arm/boot/dts/rk3066a-marsboard.dts b/arch/arm/boot/dts/rk3066a-marsboard.dts
new file mode 100644 (file)
index 0000000..0a7304b
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2014 Romain Perier <romain.perier@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "rk3066a.dtsi"
+
+/ {
+       model = "MarsBoard RK3066";
+       compatible = "haoyu,marsboard-rk3066", "rockchip,rk3066a";
+
+       memory {
+               reg = <0x60000000 0x40000000>;
+       };
+
+       vcc_sd0: sdmmc-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "sdmmc-supply";
+               regulator-min-microvolt = <3000000>;
+               regulator-max-microvolt = <3000000>;
+               gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
+               startup-delay-us = <100000>;
+               vin-supply = <&vcc_io>;
+       };
+
+       vsys: vsys-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vsys";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+       };
+};
+
+&i2c1 {
+       status = "okay";
+       clock-frequency = <400000>;
+
+       tps: tps@2d {
+               reg = <0x2d>;
+
+               interrupt-parent = <&gpio6>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+
+               vcc1-supply = <&vsys>;
+               vcc2-supply = <&vsys>;
+               vcc3-supply = <&vsys>;
+               vcc4-supply = <&vsys>;
+               vcc5-supply = <&vcc_io>;
+               vcc6-supply = <&vcc_io>;
+               vcc7-supply = <&vsys>;
+               vccio-supply = <&vsys>;
+
+               regulators {
+                       vcc_rtc: regulator@0 {
+                               regulator-name = "vcc_rtc";
+                               regulator-always-on;
+                       };
+
+                       vcc_io: regulator@1 {
+                               regulator-name = "vcc_io";
+                               regulator-always-on;
+                       };
+
+                       vdd_arm: regulator@2 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = <600000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vcc_ddr: regulator@3 {
+                               regulator-name = "vcc_ddr";
+                               regulator-min-microvolt = <600000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vcc18_cif: regulator@5 {
+                               regulator-name = "vcc18_cif";
+                               regulator-always-on;
+                       };
+
+                       vdd_11: regulator@6 {
+                               regulator-name = "vdd_11";
+                               regulator-always-on;
+                       };
+
+                       vcc_25: regulator@7 {
+                               regulator-name = "vcc_25";
+                               regulator-always-on;
+                       };
+
+                       vcc_18: regulator@8 {
+                               regulator-name = "vcc_18";
+                               regulator-always-on;
+                       };
+
+                       vcc25_hdmi: regulator@9 {
+                               regulator-name = "vcc25_hdmi";
+                               regulator-always-on;
+                       };
+
+                       vcca_33: regulator@10 {
+                               regulator-name = "vcca_33";
+                               regulator-always-on;
+                       };
+
+                       vcc_rmii: regulator@11 {
+                               regulator-name = "vcc_rmii";
+                       };
+
+                       vcc28_cif: regulator@12 {
+                               regulator-name = "vcc28_cif";
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+/* must be included after &tps gets defined */
+#include "tps65910.dtsi"
+
+&emac {
+       status = "okay";
+
+       phy = <&phy0>;
+       phy-supply = <&vcc_rmii>;
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&emac_xfer>, <&emac_mdio>, <&phy_int>;
+
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
+
+&pinctrl {
+       lan8720a {
+               phy_int: phy-int {
+                       rockchip,pins = <RK_GPIO1 26 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
+
+&wdt {
+       status = "okay";
+};
index ad9c2db59670659a9142edfbe486459f0eb84f35..41ffd4951ef3541786a26821ec82fba1e537f69e 100644 (file)
                #size-cells = <0>;
                enable-method = "rockchip,rk3066-smp";
 
-               cpu@0 {
+               cpu0: cpu@0 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
                        next-level-cache = <&L2>;
                        reg = <0x0>;
+                       operating-points = <
+                               /* kHz    uV */
+                               1008000 1075000
+                                816000 1025000
+                                600000 1025000
+                                504000 1000000
+                                312000  975000
+                       >;
+                       clock-latency = <40000>;
+                       clocks = <&cru ARMCLK>;
                };
                cpu@1 {
                        device_type = "cpu";
                };
        };
 
+       i2s0: i2s@10118000 {
+               compatible = "rockchip,rk3066-i2s";
+               reg = <0x10118000 0x2000>;
+               interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s0_bus>;
+               dmas = <&dmac1_s 4>, <&dmac1_s 5>;
+               dma-names = "tx", "rx";
+               clock-names = "i2s_hclk", "i2s_clk";
+               clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+               status = "disabled";
+       };
+
+       i2s1: i2s@1011a000 {
+               compatible = "rockchip,rk3066-i2s";
+               reg = <0x1011a000 0x2000>;
+               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s1_bus>;
+               dmas = <&dmac1_s 6>, <&dmac1_s 7>;
+               dma-names = "tx", "rx";
+               clock-names = "i2s_hclk", "i2s_clk";
+               clocks = <&cru HCLK_I2S1>, <&cru SCLK_I2S1>;
+               status = "disabled";
+       };
+
+       i2s2: i2s@1011c000 {
+               compatible = "rockchip,rk3066-i2s";
+               reg = <0x1011c000 0x2000>;
+               interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s2_bus>;
+               dmas = <&dmac1_s 9>, <&dmac1_s 10>;
+               dma-names = "tx", "rx";
+               clock-names = "i2s_hclk", "i2s_clk";
+               clocks = <&cru HCLK_I2S2>, <&cru SCLK_I2S2>;
+               status = "disabled";
+       };
+
        cru: clock-controller@20000000 {
                compatible = "rockchip,rk3066a-cru";
                reg = <0x20000000 0x1000>;
                        bias-disable;
                };
 
+               emac {
+                       emac_xfer: emac-xfer {
+                               rockchip,pins = <RK_GPIO1 16 RK_FUNC_2 &pcfg_pull_none>, /* mac_clk */
+                                               <RK_GPIO1 17 RK_FUNC_2 &pcfg_pull_none>, /* tx_en */
+                                               <RK_GPIO1 18 RK_FUNC_2 &pcfg_pull_none>, /* txd1 */
+                                               <RK_GPIO1 19 RK_FUNC_2 &pcfg_pull_none>, /* txd0 */
+                                               <RK_GPIO1 20 RK_FUNC_2 &pcfg_pull_none>, /* rx_err */
+                                               <RK_GPIO1 21 RK_FUNC_2 &pcfg_pull_none>, /* crs_dvalid */
+                                               <RK_GPIO1 22 RK_FUNC_2 &pcfg_pull_none>, /* rxd1 */
+                                               <RK_GPIO1 23 RK_FUNC_2 &pcfg_pull_none>; /* rxd0 */
+                       };
+
+                       emac_mdio: emac-mdio {
+                               rockchip,pins = <RK_GPIO1 24 RK_FUNC_2 &pcfg_pull_none>, /* mac_md */
+                                               <RK_GPIO1 25 RK_FUNC_2 &pcfg_pull_none>; /* mac_mdclk */
+                       };
+               };
+
                emmc {
                        emmc_clk: emmc-clk {
                                rockchip,pins = <RK_GPIO3 31 RK_FUNC_2 &pcfg_pull_default>;
                                                <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
                        };
                };
+
+               i2s0 {
+                       i2s0_bus: i2s0-bus {
+                               rockchip,pins = <RK_GPIO0 7 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 8 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 9 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 10 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 11 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 12 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 13 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 14 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 15 RK_FUNC_1 &pcfg_pull_default>;
+                       };
+               };
+
+               i2s1 {
+                       i2s1_bus: i2s1-bus {
+                               rockchip,pins = <RK_GPIO0 16 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 17 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 18 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 19 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 20 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 21 RK_FUNC_1 &pcfg_pull_default>;
+                       };
+               };
+
+               i2s2 {
+                       i2s2_bus: i2s2-bus {
+                               rockchip,pins = <RK_GPIO0 24 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 25 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 26 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 27 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 28 RK_FUNC_1 &pcfg_pull_default>,
+                                               <RK_GPIO0 29 RK_FUNC_1 &pcfg_pull_default>;
+                       };
+               };
        };
 };
 
 &wdt {
        compatible = "rockchip,rk3066-wdt", "snps,dw-wdt";
 };
+
+&emac {
+       compatible = "rockchip,rk3066-emac";
+};
index 15910c9ddbc7c6cb33c30904a4107b387693e132..9a09579b8309c39fbb767c7798adee8f56062cea 100644 (file)
                compatible = "gpio-leds";
 
                green {
+                       label = "rock:green:user1";
                        gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
-               yellow {
+               blue {
+                       label = "rock:blue:user2";
                        gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
                sleep {
+                       label = "rock:red:power";
                        gpios = <&gpio0 15 0>;
                        default-state = "off";
                };
        };
 };
 
+&cpu0 {
+       cpu0-supply = <&vdd_arm>;
+};
+
 &i2c1 {
        status = "okay";
        clock-frequency = <400000>;
                        vdd_arm: REG3 {
                                regulator-name = "VDD_ARM";
                                regulator-min-microvolt = <875000>;
-                               regulator-max-microvolt = <1300000>;
+                               regulator-max-microvolt = <1350000>;
                                regulator-always-on;
                        };
 
        disable-wp;
 };
 
+&pwm1 {
+       status = "okay";
+};
+
+&pwm2 {
+       status = "okay";
+};
+
+&pwm3 {
+       status = "okay";
+};
+
 &pinctrl {
        pcfg_output_low: pcfg-output-low {
                output-low;
index ddaada788b4584429840953311cd806a7c2cff19..1d4d79c6688df78bdb622e1f0e36e740eeb602d3 100644 (file)
                #size-cells = <0>;
                enable-method = "rockchip,rk3066-smp";
 
-               cpu@0 {
+               cpu0: cpu@0 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
                        next-level-cache = <&L2>;
                        reg = <0x0>;
+                       operating-points = <
+                               /* kHz    uV */
+                               1608000 1350000
+                               1416000 1250000
+                               1200000 1150000
+                               1008000 1075000
+                                816000  975000
+                                600000  950000
+                                504000  925000
+                                312000  875000
+                       >;
+                       clock-latency = <40000>;
+                       clocks = <&cru ARMCLK>;
                };
                cpu@1 {
                        device_type = "cpu";
                };
        };
 
+       i2s0: i2s@1011a000 {
+               compatible = "rockchip,rk3188-i2s", "rockchip,rk3066-i2s";
+               reg = <0x1011a000 0x2000>;
+               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s0_bus>;
+               dmas = <&dmac1_s 6>, <&dmac1_s 7>;
+               dma-names = "tx", "rx";
+               clock-names = "i2s_hclk", "i2s_clk";
+               clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+               status = "disabled";
+       };
+
        cru: clock-controller@20000000 {
                compatible = "rockchip,rk3188-cru";
                reg = <0x20000000 0x1000>;
                #size-cells = <1>;
                ranges;
 
-               gpio0: gpio0@0x2000a000 {
+               gpio0: gpio0@2000a000 {
                        compatible = "rockchip,rk3188-gpio-bank0";
                        reg = <0x2000a000 0x100>;
                        interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
                        #interrupt-cells = <2>;
                };
 
-               gpio1: gpio1@0x2003c000 {
+               gpio1: gpio1@2003c000 {
                        compatible = "rockchip,gpio-bank";
                        reg = <0x2003c000 0x100>;
                        interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
                                                <RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
                        };
                };
+
+               i2s0 {
+                       i2s0_bus: i2s0-bus {
+                               rockchip,pins = <RK_GPIO1 16 RK_FUNC_1 &pcfg_pull_none>,
+                                               <RK_GPIO1 17 RK_FUNC_1 &pcfg_pull_none>,
+                                               <RK_GPIO1 18 RK_FUNC_1 &pcfg_pull_none>,
+                                               <RK_GPIO1 19 RK_FUNC_1 &pcfg_pull_none>,
+                                               <RK_GPIO1 20 RK_FUNC_1 &pcfg_pull_none>,
+                                               <RK_GPIO1 21 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
        };
 };
 
index ff522f8e3df4ea393a00a83b509f4452b1ef1bff..d8c775e6d5fe7d7ca73a3142b5c8b5707797b7cb 100644 (file)
        compatible = "rockchip,rk3288-evb-rk808", "rockchip,rk3288";
 };
 
+&cpu0 {
+       cpu0-supply = <&vdd_cpu>;
+};
+
 &i2c0 {
        clock-frequency = <400000>;
        status = "okay";
@@ -44,7 +48,7 @@
                                regulator-always-on;
                                regulator-boot-on;
                                regulator-min-microvolt = <750000>;
-                               regulator-max-microvolt = <1300000>;
+                               regulator-max-microvolt = <1350000>;
                                regulator-name = "vdd_arm";
                        };
 
index cb83cea52fa141db24a4882469ef7dad904d892a..3e067dd65d0c87d7845809bd121859f86de1a879 100644 (file)
        status = "okay";
 };
 
+&tsadc {
+       rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
+       rockchip,hw-tshut-polarity = <0>; /* tshut polarity 0:LOW 1:HIGH */
+       status = "okay";
+};
+
 &pinctrl {
        backlight {
                bl_en: bl-en {
diff --git a/arch/arm/boot/dts/rk3288-thermal.dtsi b/arch/arm/boot/dts/rk3288-thermal.dtsi
new file mode 100644 (file)
index 0000000..2695200
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Device Tree Source for RK3288 SoC thermal
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+reserve_thermal: reserve_thermal {
+       polling-delay-passive = <1000>; /* milliseconds */
+       polling-delay = <5000>; /* milliseconds */
+
+       thermal-sensors = <&tsadc 0>;
+};
+
+cpu_thermal: cpu_thermal {
+       polling-delay-passive = <1000>; /* milliseconds */
+       polling-delay = <5000>; /* milliseconds */
+
+       thermal-sensors = <&tsadc 1>;
+
+       trips {
+               cpu_alert0: cpu_alert0 {
+                       temperature = <70000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu_crit: cpu_crit {
+                       temperature = <90000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               map0 {
+                       trip = <&cpu_alert0>;
+                       cooling-device =
+                               <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+               };
+       };
+};
+
+gpu_thermal: gpu_thermal {
+       polling-delay-passive = <1000>; /* milliseconds */
+       polling-delay = <5000>; /* milliseconds */
+
+       thermal-sensors = <&tsadc 2>;
+
+       trips {
+               gpu_alert0: gpu_alert0 {
+                       temperature = <70000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "passive";
+               };
+               gpu_crit: gpu_crit {
+                       temperature = <90000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               map0 {
+                       trip = <&gpu_alert0>;
+                       cooling-device =
+                               <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+               };
+       };
+};
index 874e66dbb93be117c5ff7afda004d8151b3603fd..fd19f00784bdc2e1dae5b0d27a5f503b3184cb93 100644 (file)
@@ -15,6 +15,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 #include <dt-bindings/clock/rk3288-cru.h>
+#include <dt-bindings/thermal/thermal.h>
 #include "skeleton.dtsi"
 
 / {
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
+               enable-method = "rockchip,rk3066-smp";
+               rockchip,pmu = <&pmu>;
 
-               cpu@500 {
+               cpu0: cpu@500 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a12";
                        reg = <0x500>;
+                       resets = <&cru SRST_CORE0>;
+                       operating-points = <
+                               /* KHz    uV */
+                               1608000 1350000
+                               1512000 1300000
+                               1416000 1200000
+                               1200000 1100000
+                               1008000 1050000
+                                816000 1000000
+                                696000  950000
+                                600000  900000
+                                408000  900000
+                                312000  900000
+                                216000  900000
+                                126000  900000
+                       >;
+                       #cooling-cells = <2>; /* min followed by max */
+                       clock-latency = <40000>;
+                       clocks = <&cru ARMCLK>;
                };
                cpu@501 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a12";
                        reg = <0x501>;
+                       resets = <&cru SRST_CORE1>;
                };
                cpu@502 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a12";
                        reg = <0x502>;
+                       resets = <&cru SRST_CORE2>;
                };
                cpu@503 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a12";
                        reg = <0x503>;
+                       resets = <&cru SRST_CORE3>;
                };
        };
 
 
        timer {
                compatible = "arm,armv7-timer";
+               arm,cpu-registers-not-fw-configured;
                interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
                             <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
                             <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
                compatible = "rockchip,rk3288-spi", "rockchip,rk3066-spi";
                clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
                clock-names = "spiclk", "apb_pclk";
+               dmas = <&dmac_peri 11>, <&dmac_peri 12>;
+               dma-names = "tx", "rx";
                interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
                pinctrl-names = "default";
                pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
                compatible = "rockchip,rk3288-spi", "rockchip,rk3066-spi";
                clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
                clock-names = "spiclk", "apb_pclk";
+               dmas = <&dmac_peri 13>, <&dmac_peri 14>;
+               dma-names = "tx", "rx";
                interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
                pinctrl-names = "default";
                pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
                compatible = "rockchip,rk3288-spi", "rockchip,rk3066-spi";
                clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
                clock-names = "spiclk", "apb_pclk";
+               dmas = <&dmac_peri 15>, <&dmac_peri 16>;
+               dma-names = "tx", "rx";
                interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
                pinctrl-names = "default";
                pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
                status = "disabled";
        };
 
+       thermal-zones {
+               #include "rk3288-thermal.dtsi"
+       };
+
+       tsadc: tsadc@ff280000 {
+               compatible = "rockchip,rk3288-tsadc";
+               reg = <0xff280000 0x100>;
+               interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+               clock-names = "tsadc", "apb_pclk";
+               resets = <&cru SRST_TSADC>;
+               reset-names = "tsadc-apb";
+               pinctrl-names = "default";
+               pinctrl-0 = <&otp_out>;
+               #thermal-sensor-cells = <1>;
+               rockchip,hw-tshut-temp = <95000>;
+               status = "disabled";
+       };
+
        usb_host0_ehci: usb@ff500000 {
                compatible = "generic-ehci";
                reg = <0xff500000 0x100>;
                status = "disabled";
        };
 
+       bus_intmem@ff700000 {
+               compatible = "mmio-sram";
+               reg = <0xff700000 0x18000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0xff700000 0x18000>;
+               smp-sram@0 {
+                       compatible = "rockchip,rk3066-smp-sram";
+                       reg = <0x00 0x10>;
+               };
+       };
+
        pmu: power-management@ff730000 {
                compatible = "rockchip,rk3288-pmu", "syscon";
                reg = <0xff730000 0x100>;
                rockchip,grf = <&grf>;
                #clock-cells = <1>;
                #reset-cells = <1>;
+               assigned-clocks = <&cru PLL_GPLL>, <&cru PLL_CPLL>,
+                                 <&cru PLL_NPLL>, <&cru ACLK_CPU>,
+                                 <&cru HCLK_CPU>, <&cru PCLK_CPU>,
+                                 <&cru ACLK_PERI>, <&cru HCLK_PERI>,
+                                 <&cru PCLK_PERI>;
+               assigned-clock-rates = <594000000>, <400000000>,
+                                      <500000000>, <300000000>,
+                                      <150000000>, <75000000>,
+                                      <300000000>, <150000000>,
+                                      <75000000>;
        };
 
        grf: syscon@ff770000 {
                status = "disabled";
        };
 
+       vopb_mmu: iommu@ff930300 {
+               compatible = "rockchip,iommu";
+               reg = <0xff930300 0x100>;
+               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vopb_mmu";
+               #iommu-cells = <0>;
+               status = "disabled";
+       };
+
+       vopl_mmu: iommu@ff940300 {
+               compatible = "rockchip,iommu";
+               reg = <0xff940300 0x100>;
+               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vopl_mmu";
+               #iommu-cells = <0>;
+               status = "disabled";
+       };
+
        gic: interrupt-controller@ffc01000 {
                compatible = "arm,gic-400";
                interrupt-controller;
                        };
                };
 
+               tsadc {
+                       otp_out: otp-out {
+                               rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
                pwm0 {
                        pwm0_pin: pwm0-pin {
                                rockchip,pins = <7 0 RK_FUNC_1 &pcfg_pull_none>;
index 499468d42adac51007f6c663c6b2e0e64cd67ef6..c54a9715dcfa376e155ad991f75f32e4b849aad8 100644 (file)
                mshc0 = &emmc;
                mshc1 = &mmc0;
                mshc2 = &mmc1;
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
                spi0 = &spi0;
                spi1 = &spi1;
        };
                compatible = "rockchip,rk2928-dw-mshc";
                reg = <0x10214000 0x1000>;
                interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-
                clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
                clock-names = "biu", "ciu";
-
+               fifo-depth = <256>;
                status = "disabled";
        };
 
                compatible = "rockchip,rk2928-dw-mshc";
                reg = <0x10218000 0x1000>;
                interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-
                clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>;
                clock-names = "biu", "ciu";
-
+               fifo-depth = <256>;
                status = "disabled";
        };
 
                compatible = "rockchip,rk2928-dw-mshc";
                reg = <0x1021c000 0x1000>;
                interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
-
                clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>;
                clock-names = "biu", "ciu";
-
+               fifo-depth = <256>;
                status = "disabled";
        };
 
                reg = <0x20070000 0x1000>;
                #address-cells = <1>;
                #size-cells = <0>;
+               dmas = <&dmac2 10>, <&dmac2 11>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0x20074000 0x1000>;
                #address-cells = <1>;
                #size-cells = <0>;
+               dmas = <&dmac2 12>, <&dmac2 13>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 };
index 57e00f9bce999574d4eafc767d03344b83124e82..a25debb50401b01f5db79fc85007733bb4d8785d 100644 (file)
        status = "okay";
 };
 
-&pwm {
-       status = "okay";
-};
-
 &pinctrl0 {
        gpio_leds: gpio-leds {
                samsung,pins = "gpk-4", "gpk-5", "gpk-6", "gpk-7";
index ff5bdaac987af393e6640fd830c6a6a1806ef5b7..0ccb414cd2687c9567e492972528db4101d26199 100644 (file)
                        clocks = <&clocks PCLK_PWM>;
                        samsung,pwm-outputs = <0>, <1>;
                        #pwm-cells = <3>;
-                       status = "disabled";
                };
 
                pinctrl0: pinctrl@7f008000 {
index 7997dc9863ed2cb7dd1cfc49c6f5bfcc70304d45..883878b32971a915d6d841ecc404cba1d9dd6056 100644 (file)
@@ -12,5 +12,5 @@
 #include "sama5d3_uart.dtsi"
 
 / {
-       compatible = "atmel,samad31", "atmel,sama5d3", "atmel,sama5";
+       compatible = "atmel,sama5d31", "atmel,sama5d3", "atmel,sama5";
 };
index 39f832253cafb7613ed46bed3d2cb3d19f0a1b1f..4b4434aca351208553a857d0b9a662c4a977b2e3 100644 (file)
@@ -10,5 +10,5 @@
 #include "sama5d3_gmac.dtsi"
 
 / {
-       compatible = "atmel,samad33", "atmel,sama5d3", "atmel,sama5";
+       compatible = "atmel,sama5d33", "atmel,sama5d3", "atmel,sama5";
 };
index 89cda2c0da39268f548533538fb76a9d08652a6e..aa01573fdee9366dbb23086092e8dde3d7970d45 100644 (file)
@@ -12,5 +12,5 @@
 #include "sama5d3_mci2.dtsi"
 
 / {
-       compatible = "atmel,samad34", "atmel,sama5d3", "atmel,sama5";
+       compatible = "atmel,sama5d34", "atmel,sama5d3", "atmel,sama5";
 };
index d20cd71b5f0e7f142c9b83ce81b5f9d5a7e73e6a..16c39f4c96a40841d07bac8ffce1d768d1c69cc4 100644 (file)
@@ -14,5 +14,5 @@
 #include "sama5d3_tcb1.dtsi"
 
 / {
-       compatible = "atmel,samad35", "atmel,sama5d3", "atmel,sama5";
+       compatible = "atmel,sama5d35", "atmel,sama5d3", "atmel,sama5";
 };
index db58cad6acd32633b88bf88a0589885bfa58ed9b..e85139ef40aff61a1da90f76d963ed015e9d3fc9 100644 (file)
@@ -16,5 +16,5 @@
 #include "sama5d3_uart.dtsi"
 
 / {
-       compatible = "atmel,samad36", "atmel,sama5d3", "atmel,sama5";
+       compatible = "atmel,sama5d36", "atmel,sama5d3", "atmel,sama5";
 };
index 962dc28dc37b9bbc4a3427c4e127d26fc689bf63..cfcd200b0c177967f91d9c26e4372d4f1f514b27 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 / {
-       compatible = "atmel,samad3xcm", "atmel,sama5d3", "atmel,sama5";
+       compatible = "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
 
        chosen {
                bootargs = "console=ttyS0,115200 rootfstype=ubifs ubi.mtd=5 root=ubi0:rootfs";
index 30ef97e99dc53ea77cefcf55f370c8511ec468c8..939be1299ca6ca348b216e2aae325bb9af7675ee 100644 (file)
@@ -40,6 +40,7 @@
 
        chosen {
                bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel rw";
+               stdout-path = &scifa4;
        };
 
        memory {
                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";
                };
        };
 
-       gpio-keys {
+       keyboard {
                compatible = "gpio-keys";
 
                back-key {
                };
        };
 
-       ak4648: ak4648@0x12 {
+       ak4648: ak4648@12 {
                #sound-dai-cells = <0>;
                compatible = "asahi-kasei,ak4648";
                reg = <0x12>;
index 030a5920312fa19b631246cd82e7a65924c95a46..d8def5a529da288251796155426cf08c110e12a1 100644 (file)
        i2c0: i2c@e6820000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-sh73a0", "renesas,rmobile-iic";
                reg = <0xe6820000 0x425>;
                interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH
                              0 168 IRQ_TYPE_LEVEL_HIGH
        i2c1: i2c@e6822000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-sh73a0", "renesas,rmobile-iic";
                reg = <0xe6822000 0x425>;
                interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH
                              0 52 IRQ_TYPE_LEVEL_HIGH
        i2c2: i2c@e6824000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-sh73a0", "renesas,rmobile-iic";
                reg = <0xe6824000 0x425>;
                interrupts = <0 171 IRQ_TYPE_LEVEL_HIGH
                              0 172 IRQ_TYPE_LEVEL_HIGH
        i2c3: i2c@e6826000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-sh73a0", "renesas,rmobile-iic";
                reg = <0xe6826000 0x425>;
                interrupts = <0 183 IRQ_TYPE_LEVEL_HIGH
                              0 184 IRQ_TYPE_LEVEL_HIGH
        i2c4: i2c@e6828000 {
                #address-cells = <1>;
                #size-cells = <0>;
-               compatible = "renesas,rmobile-iic";
+               compatible = "renesas,iic-sh73a0", "renesas,rmobile-iic";
                reg = <0xe6828000 0x425>;
                interrupts = <0 187 IRQ_TYPE_LEVEL_HIGH
                              0 188 IRQ_TYPE_LEVEL_HIGH
index 45fce2cf6fede0a11ce2aca2d1de31aa70147ecf..252c3d1bda501f0814b73f6fa5e267c177cbff75 100644 (file)
                        status = "disabled";
                };
 
-               gpio@ff708000 {
+               gpio0: gpio@ff708000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "snps,dw-apb-gpio";
                        clocks = <&per_base_clk>;
                        status = "disabled";
 
-                       gpio0: gpio-controller@0 {
+                       porta: gpio-controller@0 {
                                compatible = "snps,dw-apb-gpio-port";
                                gpio-controller;
                                #gpio-cells = <2>;
                        };
                };
 
-               gpio@ff709000 {
+               gpio1: gpio@ff709000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "snps,dw-apb-gpio";
                        clocks = <&per_base_clk>;
                        status = "disabled";
 
-                       gpio1: gpio-controller@0 {
+                       portb: gpio-controller@0 {
                                compatible = "snps,dw-apb-gpio-port";
                                gpio-controller;
                                #gpio-cells = <2>;
                        };
                };
 
-               gpio@ff70a000 {
+               gpio2: gpio@ff70a000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "snps,dw-apb-gpio";
                        clocks = <&per_base_clk>;
                        status = "disabled";
 
-                       gpio2: gpio-controller@0 {
+                       portc: gpio-controller@0 {
                                compatible = "snps,dw-apb-gpio-port";
                                gpio-controller;
                                #gpio-cells = <2>;
                        clock-names = "biu", "ciu";
                };
 
+               ocram: sram@ffff0000 {
+                       compatible = "mmio-sram";
+                       reg = <0xffff0000 0x10000>;
+               };
+
+               spi0: spi@fff00000 {
+                       compatible = "snps,dw-apb-ssi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xfff00000 0x1000>;
+                       interrupts = <0 154 4>;
+                       num-cs = <4>;
+                       clocks = <&spi_m_clk>;
+                       status = "disabled";
+               };
+
+               spi1: spi@fff01000 {
+                       compatible = "snps,dw-apb-ssi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xfff01000 0x1000>;
+                       interrupts = <0 156 4>;
+                       num-cs = <4>;
+                       clocks = <&spi_m_clk>;
+                       status = "disabled";
+               };
+
                /* Local timer */
                timer@fffec600 {
                        compatible = "arm,cortex-a9-twd-timer";
diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi
new file mode 100644 (file)
index 0000000..8a05c47
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Copyright Altera Corporation (C) 2014. 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/>.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet0 = &gmac0;
+               ethernet1 = &gmac1;
+               ethernet2 = &gmac2;
+               serial0 = &uart0;
+               serial1 = &uart1;
+               timer0 = &timer0;
+               timer1 = &timer1;
+               timer2 = &timer2;
+               timer3 = &timer3;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       compatible = "arm,cortex-a9";
+                       device_type = "cpu";
+                       reg = <0>;
+                       next-level-cache = <&L2>;
+               };
+               cpu@1 {
+                       compatible = "arm,cortex-a9";
+                       device_type = "cpu";
+                       reg = <1>;
+                       next-level-cache = <&L2>;
+               };
+       };
+
+       intc: intc@ffffd000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0xffffd000 0x1000>,
+                     <0xffffc100 0x100>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               device_type = "soc";
+               interrupt-parent = <&intc>;
+               ranges;
+
+               amba {
+                       compatible = "arm,amba-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       pdma: pdma@ffda1000 {
+                               compatible = "arm,pl330", "arm,primecell";
+                               reg = <0xffda1000 0x1000>;
+                               interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 84 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 85 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 86 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 87 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 88 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 89 IRQ_TYPE_LEVEL_HIGH>,
+                                            <0 90 IRQ_TYPE_LEVEL_HIGH>;
+                               #dma-cells = <1>;
+                               #dma-channels = <8>;
+                               #dma-requests = <32>;
+                       };
+               };
+
+               clkmgr@ffd04000 {
+                               compatible = "altr,clk-mgr";
+                               reg = <0xffd04000 0x1000>;
+
+                               clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       osc1: osc1 {
+                                               #clock-cells = <0>;
+                                               compatible = "fixed-clock";
+                                       };
+
+                                       main_pll: main_pll {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #clock-cells = <0>;
+                                               compatible = "altr,socfpga-pll-clock";
+                                               clocks = <&osc1>;
+                                       };
+
+                                       periph_pll: periph_pll {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #clock-cells = <0>;
+                                               compatible = "altr,socfpga-pll-clock";
+                                               clocks = <&osc1>;
+                                       };
+                               };
+               };
+
+               gmac0: ethernet@ff800000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.72a", "snps,dwmac";
+                       reg = <0xff800000 0x2000>;
+                       interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "macirq";
+                       /* Filled in by bootloader */
+                       mac-address = [00 00 00 00 00 00];
+                       status = "disabled";
+               };
+
+               gmac1: ethernet@ff802000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.72a", "snps,dwmac";
+                       reg = <0xff802000 0x2000>;
+                       interrupts = <0 93 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "macirq";
+                       /* Filled in by bootloader */
+                       mac-address = [00 00 00 00 00 00];
+                       status = "disabled";
+               };
+
+               gmac2: ethernet@ff804000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.72a", "snps,dwmac";
+                       reg = <0xff804000 0x2000>;
+                       interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "macirq";
+                       /* Filled in by bootloader */
+                       mac-address = [00 00 00 00 00 00];
+                       status = "disabled";
+               };
+
+               gpio0: gpio@ffc02900 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0xffc02900 0x100>;
+                       status = "disabled";
+
+                       porta: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <29>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <0 112 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               gpio1: gpio@ffc02a00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0xffc02a00 0x100>;
+                       status = "disabled";
+
+                       portb: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <29>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <0 113 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               gpio2: gpio@ffc02b00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0xffc02b00 0x100>;
+                       status = "disabled";
+
+                       portc: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <27>;
+                               reg = <0>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <0 114 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               i2c0: i2c@ffc02200 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02200 0x100>;
+                       interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@ffc02300 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02300 0x100>;
+                       interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               i2c2: i2c@ffc02400 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02400 0x100>;
+                       interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               i2c3: i2c@ffc02500 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02500 0x100>;
+                       interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               i2c4: i2c@ffc02600 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "snps,designware-i2c";
+                       reg = <0xffc02600 0x100>;
+                       interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               L2: l2-cache@fffff000 {
+                       compatible = "arm,pl310-cache";
+                       reg = <0xfffff000 0x1000>;
+                       interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
+                       cache-unified;
+                       cache-level = <2>;
+               };
+
+               mmc: dwmmc0@ff808000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "altr,socfpga-dw-mshc";
+                       reg = <0xff808000 0x1000>;
+                       interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
+                       fifo-depth = <0x400>;
+               };
+
+               ocram: sram@ffe00000 {
+                       compatible = "mmio-sram";
+                       reg = <0xffe00000 0x40000>;
+               };
+
+               rst: rstmgr@ffd05000 {
+                       #reset-cells = <1>;
+                       compatible = "altr,rst-mgr";
+                       reg = <0xffd05000 0x100>;
+               };
+
+               sysmgr: sysmgr@ffd06000 {
+                       compatible = "altr,sys-mgr", "syscon";
+                       reg = <0xffd06000 0x300>;
+               };
+
+               /* Local timer */
+               timer@ffffc600 {
+                       compatible = "arm,cortex-a9-twd-timer";
+                       reg = <0xffffc600 0x100>;
+                       interrupts = <1 13 0xf04>;
+               };
+
+               timer0: timer0@ffc02700 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 115 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0xffc02700 0x100>;
+               };
+
+               timer1: timer1@ffc02800 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 116 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0xffc02800 0x100>;
+               };
+
+               timer2: timer2@ffd00000 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 117 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0xffd00000 0x100>;
+               };
+
+               timer3: timer3@ffd00100 {
+                       compatible = "snps,dw-apb-timer";
+                       interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0xffd01000 0x100>;
+               };
+
+               uart0: serial0@ffc02000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc02000 0x100>;
+                       interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               uart1: serial1@ffc02100 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc02100 0x100>;
+                       interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               usbphy0: usbphy@0 {
+                       #phy-cells = <0>;
+                       compatible = "usb-nop-xceiv";
+                       status = "okay";
+               };
+
+               usb0: usb@ffb00000 {
+                       compatible = "snps,dwc2";
+                       reg = <0xffb00000 0xffff>;
+                       interrupts = <0 95 IRQ_TYPE_LEVEL_HIGH>;
+                       phys = <&usbphy0>;
+                       phy-names = "usb2-phy";
+                       status = "disabled";
+               };
+
+               usb1: usb@ffb40000 {
+                       compatible = "snps,dwc2";
+                       reg = <0xffb40000 0xffff>;
+                       interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
+                       phys = <&usbphy0>;
+                       phy-names = "usb2-phy";
+                       status = "disabled";
+               };
+
+               watchdog0: watchdog@ffd00200 {
+                       compatible = "snps,dw-wdt";
+                       reg = <0xffd00200 0x100>;
+                       interrupts = <0 119 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               watchdog1: watchdog@ffd00300 {
+                       compatible = "snps,dw-wdt";
+                       reg = <0xffd00300 0x100>;
+                       interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk.dts b/arch/arm/boot/dts/socfpga_arria10_socdk.dts
new file mode 100755 (executable)
index 0000000..3015ce8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 Altera Corporation <www.altera.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/>.
+ */
+
+/dts-v1/;
+#include "socfpga_arria10.dtsi"
+
+/ {
+       model = "Altera SOCFPGA Arria 10";
+       compatible = "altr,socfpga-arria10", "altr,socfpga";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 rootwait";
+       };
+
+       memory {
+               name = "memory";
+               device_type = "memory";
+               reg = <0x0 0x40000000>; /* 1GB */
+       };
+
+       soc {
+               clkmgr@ffd04000 {
+                       clocks {
+                               osc1 {
+                                       clock-frequency = <25000000>;
+                               };
+                       };
+               };
+
+               serial0@ffc02000 {
+                       status = "okay";
+               };
+       };
+};
index 03e8268ae2196e697cededfe5db00eec393fac9d..1907cc60045218663fad56e7def2a8825311f9f1 100644 (file)
@@ -29,7 +29,7 @@
                        };
                };
 
-               dwmmc0@ff704000 {
+               mmc0: dwmmc0@ff704000 {
                        num-slots = <1>;
                        broken-cd;
                        bus-width = <4>;
index 27d551c384d06b884f4eee5d19f7c75e783938e3..ccaf41742fc3d05921ee80d67ba00304010a666b 100644 (file)
                */
                ethernet0 = &gmac1;
        };
+
+       regulator_3_3v: 3-3-v-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
 };
 
 &gmac1 {
        };
 };
 
+&mmc0 {
+       vmmc-supply = <&regulator_3_3v>;
+       vqmmc-supply = <&regulator_3_3v>;
+};
+
 &usb1 {
        status = "okay";
 };
index 28c05e7a31c9ec172ef03b1fc95bdcb7044446cc..06db951e06f8865b72cbce65739ce88c112f0dd8 100644 (file)
@@ -49,3 +49,7 @@
                };
        };
 };
+
+&watchdog0 {
+       status = "okay";
+};
index d7296a5f750cd5edef23d62078b47361027de785..258865da8f6a6fe45a0fc9ae6c0281ef2f0c4824 100644 (file)
                 */
                ethernet0 = &gmac1;
        };
+
+       regulator_3_3v: 3-3-v-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
 };
 
 &gmac1 {
        rxc-skew-ps = <2000>;
 };
 
+&gpio1 {
+       status = "okay";
+};
+
 &i2c0 {
        status = "okay";
 
@@ -69,7 +80,9 @@
 };
 
 &mmc0 {
-       cd-gpios = <&gpio1 18 0>;
+       cd-gpios = <&portb 18 0>;
+       vmmc-supply = <&regulator_3_3v>;
+       vqmmc-supply = <&regulator_3_3v>;
 };
 
 &usb1 {
index d26f155f5fd9f64fcdbd1bcf12626c6008683b9b..16ea6f5f2ab81092d76697d020ef575610dc8045 100644 (file)
                 */
                ethernet0 = &gmac1;
        };
+
+       regulator_3_3v: vcc3p3-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC3P3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
 };
 
 &gmac1 {
        rxc-skew-ps = <2000>;
 };
 
+&mmc0 {
+       vmmc-supply = <&regulator_3_3v>;
+       vqmmc-supply = <&regulator_3_3v>;
+};
+
 &usb1 {
        status = "okay";
 };
index 9d2323020d340b4138dc5b5895d95ace4e8a7211..bfd3f1c734b8d84dec4a622032e1b29efa07b83d 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/mfd/dbx500-prcmu.h>
+#include <dt-bindings/arm/ux500_pm_domains.h>
 #include "skeleton.dtsi"
 
 / {
                        interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
                };
 
+               pm_domains: pm_domains0 {
+                       compatible = "stericsson,ux500-pm-domains";
+                       #power-domain-cells = <1>;
+               };
 
                clocks {
                        compatible = "stericsson,u8500-clks";
                        clock-frequency = <400000>;
                        clocks = <&prcc_kclk 3 3>, <&prcc_pclk 3 3>;
                        clock-names = "i2cclk", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                i2c@80122000 {
 
                        clocks = <&prcc_kclk 1 2>, <&prcc_pclk 1 2>;
                        clock-names = "i2cclk", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                i2c@80128000 {
 
                        clocks = <&prcc_kclk 1 6>, <&prcc_pclk 1 6>;
                        clock-names = "i2cclk", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                i2c@80110000 {
 
                        clocks = <&prcc_kclk 2 0>, <&prcc_pclk 2 0>;
                        clock-names = "i2cclk", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                i2c@8012a000 {
 
                        clocks = <&prcc_kclk 1 9>, <&prcc_pclk 1 10>;
                        clock-names = "i2cclk", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                ssp@80002000 {
                        dmas = <&dma 8 0 0x2>, /* Logical - DevToMem */
                               <&dma 8 0 0x0>; /* Logical - MemToDev */
                        dma-names = "rx", "tx";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                ssp@80003000 {
                        dmas = <&dma 9 0 0x2>, /* Logical - DevToMem */
                               <&dma 9 0 0x0>; /* Logical - MemToDev */
                        dma-names = "rx", "tx";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                spi@8011a000 {
                        dmas = <&dma 0 0 0x2>, /* Logical - DevToMem */
                               <&dma 0 0 0x0>; /* Logical - MemToDev */
                        dma-names = "rx", "tx";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                spi@80112000 {
                        dmas = <&dma 35 0 0x2>, /* Logical - DevToMem */
                               <&dma 35 0 0x0>; /* Logical - MemToDev */
                        dma-names = "rx", "tx";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                spi@80111000 {
                        dmas = <&dma 33 0 0x2>, /* Logical - DevToMem */
                               <&dma 33 0 0x0>; /* Logical - MemToDev */
                        dma-names = "rx", "tx";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                spi@80129000 {
                        dmas = <&dma 40 0 0x2>, /* Logical - DevToMem */
                               <&dma 40 0 0x0>; /* Logical - MemToDev */
                        dma-names = "rx", "tx";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
                };
 
                uart@80120000 {
 
                        clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>;
                        clock-names = "sdi", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
 
                        status = "disabled";
                };
 
                        clocks = <&prcc_kclk 2 4>, <&prcc_pclk 2 6>;
                        clock-names = "sdi", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
 
                        status = "disabled";
                };
 
                        clocks = <&prcc_kclk 3 4>, <&prcc_pclk 3 4>;
                        clock-names = "sdi", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
 
                        status = "disabled";
                };
 
                        clocks = <&prcc_kclk 2 5>, <&prcc_pclk 2 7>;
                        clock-names = "sdi", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
 
                        status = "disabled";
                };
 
                        clocks = <&prcc_kclk 2 2>, <&prcc_pclk 2 4>;
                        clock-names = "sdi", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
 
                        status = "disabled";
                };
 
                        clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>;
                        clock-names = "sdi", "apb_pclk";
+                       power-domains = <&pm_domains DOMAIN_VAPE>;
 
                        status = "disabled";
                };
diff --git a/arch/arm/boot/dts/ste-nomadik-nhk15.dts b/arch/arm/boot/dts/ste-nomadik-nhk15.dts
new file mode 100644 (file)
index 0000000..a8c00ee
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Device Tree for the ST-Ericsson Nomadik S8815 board
+ * Produced by Calao Systems
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "ste-nomadik-stn8815.dtsi"
+
+/ {
+       model = "Nomadik STN8815NHK";
+       compatible = "st,nomadik-nhk-15";
+
+       chosen {
+               bootargs = "root=/dev/ram0 console=ttyAMA1,115200n8 earlyprintk";
+       };
+
+       aliases {
+               stmpe-i2c0 = &stmpe0;
+               stmpe-i2c1 = &stmpe1;
+       };
+
+       pinctrl {
+               stmpe2401_1 {
+                       stmpe2401_1_nhk_mode: stmpe2401_1_nhk {
+                               nhk_cfg1 {
+                                       ste,pins = "GPIO76_B20"; // IRQ line
+                                       ste,input = <0>;
+                               };
+                               nhk_cfg2 {
+                                       ste,pins = "GPIO77_B8"; // reset line
+                                       ste,output = <1>;
+                               };
+                       };
+               };
+               stmpe2401_2 {
+                       stmpe2401_2_nhk_mode: stmpe2401_2_nhk {
+                               nhk_cfg1 {
+                                       ste,pins = "GPIO78_A8"; // IRQ line
+                                       ste,input = <0>;
+                               };
+                               nhk_cfg2 {
+                                       ste,pins = "GPIO79_C9"; // reset line
+                                       ste,output = <1>;
+                               };
+                       };
+               };
+       };
+
+       src@101e0000 {
+               /* These chrystal outputs are not used on this board */
+               disable-sxtalo;
+               disable-mxtalo;
+       };
+
+       /* This is where the interrupt is routed on the NHK-15 debug board */
+       external-bus@34000000 {
+               compatible = "simple-bus";
+               reg = <0x34000000 0x1000000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x34000000 0x1000000>;
+               ethernet@300 {
+                       compatible = "smsc,lan91c111";
+                       reg = <0x300 0x0fd00>;
+                       reg-io-width = <2>;
+                       reset-gpios = <&stmpe_gpio44 10 GPIO_ACTIVE_HIGH>;
+                       interrupt-parent = <&stmpe_gpio44>;
+                       interrupts = <11 IRQ_TYPE_EDGE_RISING>;
+               };
+       };
+
+       i2c0 {
+               stmpe0: stmpe2401@43 {
+                       compatible = "st,stmpe2401";
+                       reg = <0x43>;
+                       reset-gpios = <&gpio2 13 GPIO_ACTIVE_LOW>; // GPIO77
+                       interrupts = <12 IRQ_TYPE_EDGE_FALLING>; // GPIO76
+                       interrupt-parent = <&gpio2>;
+                       interrupt-controller;
+                       wakeup-source;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&stmpe2401_1_nhk_mode>;
+                       stmpe_gpio43: stmpe_gpio {
+                               compatible = "st,stmpe-gpio";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               /* Some pins in alternate functions */
+                               st,norequest-mask = <0xf0f002>;
+                       };
+                       stmpe_keypad {
+                               compatible = "st,stmpe-keypad";
+                               debounce-interval = <64>;
+                               st,scan-count = <8>;
+                               st,no-autorepeat;
+                               keypad,num-rows = <8>;
+                               keypad,num-columns = <8>;
+                               linux,keymap = <0x00020072 // Vol down
+                                               0x00030073 // Vol up
+                                               0x0100009e // Back
+                                               0x010100e3 // TV out
+                                               0x01020098 // Lock
+                                               0x0103013b // Start
+                                               0x020000a3 // Next
+                                               0x020100a4 // Play
+                                               0x020200a5 // Prev
+                                               0x02030160 // OK
+                                               0x03000069 // Left
+                                               0x0301006a // Right
+                                               0x03020067 // Up
+                                               0x0303006c>; // Down
+                       };
+               };
+               stmpe1: stmpe2401@44 {
+                       compatible = "st,stmpe2401";
+                       reg = <0x44>;
+                       reset-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>; // GPIO79
+                       interrupts = <14 IRQ_TYPE_EDGE_FALLING>; // GPIO78
+                       interrupt-parent = <&gpio2>;
+                       interrupt-controller;
+                       wakeup-source;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&stmpe2401_2_nhk_mode>;
+                       stmpe_gpio44: stmpe_gpio {
+                               compatible = "st,stmpe-gpio";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+       };
+
+       amba {
+               mmcsd: sdi@101f6000 {
+                       cd-gpios = <&stmpe_gpio44 7 GPIO_ACTIVE_LOW>;
+                       wp-gpios = <&stmpe_gpio44 18 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
+       /* Custom board node with GPIO pins to active etc */
+       usb-s8815 {
+               /* This will turn off SATA so that MMC/SD can thrive */
+               mmcsd-gpio {
+                       gpios = <&stmpe_gpio44 2 0x1>;
+               };
+       };
+};
index 90d8b6c7a20506ee81e9e5258e0d4522d8cfeba8..e411ff7769fee3fb2481bd89a0d7585d4eb1703e 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "ste-nomadik-stn8815.dtsi"
 
 / {
                bootargs = "root=/dev/ram0 console=ttyAMA1,115200n8 earlyprintk";
        };
 
-       /* This is where the interrupt is routed on the S8815 board */
-       external-bus@34000000 {
-               ethernet@300 {
-                       interrupt-parent = <&gpio3>;
-                       interrupts = <8 0x1>;
-               };
-       };
-
        src@101e0000 {
                /* These chrystal drivers are not used on this board */
                disable-sxtalo;
                                };
                        };
                };
+               gpioi2c {
+                       gpioi2c_default_mode: gpioi2c_default {
+                               gpioi2c_default_cfg {
+                                       ste,pins = "GPIO73_C21", "GPIO74_C20";
+                                       ste,input = <0>;
+                               };
+                       };
+               };
                user-led {
                        user_led_default_mode: user_led_default {
                                user_led_default_cfg {
                };
        };
 
+       /* Ethernet */
+       external-bus@34000000 {
+               compatible = "simple-bus";
+               reg = <0x34000000 0x1000000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x34000000 0x1000000>;
+               ethernet@300 {
+                       compatible = "smsc,lan91c111";
+                       reg = <0x300 0x0fd00>;
+                       interrupt-parent = <&gpio3>;
+                       interrupts = <8 IRQ_TYPE_EDGE_RISING>;
+               };
+       };
+
+       /* GPIO I2C connected to the USB portions of the STw4811 only */
+       gpio-i2c {
+               compatible = "i2c-gpio";
+               gpios = <&gpio2 10 0>, /* sda */
+                       <&gpio2 9 0>; /* scl */
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&gpioi2c_default_mode>;
+
+               stw4811@2d {
+                          compatible = "st,stw4811-usb";
+                          reg = <0x2d>;
+               };
+       };
+
+
+       /* Configure card detect for the uSD slot */
+       amba {
+               mmcsd: sdi@101f6000 {
+                       cd-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
+               };
+       };
+
        /* Custom board node with GPIO pins to active etc */
        usb-s8815 {
                /* This will bias the MMC/SD card detect line */
index dbcf521b017f207fff1286d3c02e3e6586cc761e..f435ff20aefef7d1b7edbd7391217ac140a585de 100644 (file)
                        mmcsd_default_mux: mmcsd_mux {
                                mmcsd_default_mux {
                                        ste,function = "mmcsd";
-                                       ste,pins = "mmcsd_a_1";
+                                       ste,pins = "mmcsd_a_1", "mmcsd_b_1";
                                };
                        };
                        mmcsd_default_mode: mmcsd_default {
                                        ste,output = <0>;
                                };
                                mmcsd_default_cfg2 {
-                                       /* MCCMDDIR, MCDAT0DIR, MCDAT31DIR */
+                                       /* MCCMDDIR, MCDAT0DIR, MCDAT31DIR, MCDATDIR2 */
                                        ste,pins = "GPIO10_C11", "GPIO15_A12",
-                                       "GPIO16_C13";
+                                       "GPIO16_C13", "GPIO23_D15";
                                        ste,output = <1>;
                                };
                                mmcsd_default_cfg3 {
                                };
                        };
                };
-               i2c2 {
-                       i2c2_default_mode: i2c2_default {
-                               i2c2_default_cfg {
-                                       ste,pins = "GPIO73_C21", "GPIO74_C20";
-                                       ste,input = <0>;
-                               };
-                       };
-               };
        };
 
        src: src@101e0000 {
                compatible = "stericsson,nomadik-src";
                reg = <0x101e0000 0x1000>;
-               disable-sxtalo;
-               disable-mxtalo;
 
                /*
                 * MXTAL "Main Chrystal" is a chrystal oscillator @19.2 MHz
                };
        };
 
-       external-bus@34000000 {
-               compatible = "simple-bus";
-               reg = <0x34000000 0x1000000>;
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges = <0 0x34000000 0x1000000>;
-               ethernet@300 {
-                       compatible = "smsc,lan91c111";
-                       reg = <0x300 0x0fd00>;
-               };
-       };
-
        /* I2C0 connected to the STw4811 power management chip */
        i2c0 {
                compatible = "st,nomadik-i2c", "arm,primecell";
                };
        };
 
-       /* I2C2 connected to the USB portions of the STw4811 only */
-       i2c2 {
-               compatible = "i2c-gpio";
-               gpios = <&gpio2 10 0>, /* sda */
-                       <&gpio2 9 0>; /* scl */
-               #address-cells = <1>;
-               #size-cells = <0>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&i2c2_default_mode>;
-
-               stw4811@2d {
-                          compatible = "st,stw4811-usb";
-                          reg = <0x2d>;
-               };
-       };
-
        amba {
                compatible = "arm,amba-bus";
                #address-cells = <1>;
                        bus-width = <4>;
                        cap-mmc-highspeed;
                        cap-sd-highspeed;
-                       cd-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>;
                        vmmc-supply = <&vmmc_regulator>;
index fe69f92e5f827c02c0c4566ffac0ed938ceaf410..261d5e2c48d24de2262d2947387e39441c6a434d 100644 (file)
@@ -7,13 +7,15 @@
  * published by the Free Software Foundation.
  */
 /dts-v1/;
-#include "stih407.dtsi"
+#include "stih407-clock.dtsi"
+#include "stih407-family.dtsi"
+#include "stihxxx-b2120.dtsi"
 / {
        model = "STiH407 B2120";
        compatible = "st,stih407-b2120", "st,stih407";
 
        chosen {
-               bootargs = "console=ttyAS0,115200";
+               bootargs = "console=ttyAS0,115200 clk_ignore_unused";
                linux,stdout-path = &sbc_serial0;
        };
 
                ttyAS0 = &sbc_serial0;
        };
 
-       soc {
-               sbc_serial0: serial@9530000 {
-                       status = "okay";
-               };
-
-               leds {
-                       compatible = "gpio-leds";
-                       red {
-                               #gpio-cells = <2>;
-                               label = "Front Panel LED";
-                               gpios = <&pio4 1 0>;
-                               linux,default-trigger = "heartbeat";
-                       };
-                       green {
-                               #gpio-cells = <2>;
-                               gpios = <&pio1 3 0>;
-                               default-state = "off";
-                       };
-               };
-
-               i2c@9842000 {
-                       status = "okay";
-               };
-
-               i2c@9843000 {
-                       status = "okay";
-               };
-
-               i2c@9844000 {
-                       status = "okay";
-               };
-
-               i2c@9845000 {
-                       status = "okay";
-               };
-
-               i2c@9540000 {
-                       status = "okay";
-               };
-
-               /* SSC11 to HDMI */
-               i2c@9541000 {
-                       status = "okay";
-                       /* HDMI V1.3a supports Standard mode only */
-                       clock-frequency = <100000>;
-                       st,i2c-min-scl-pulse-width-us = <0>;
-                       st,i2c-min-sda-pulse-width-us = <5>;
-               };
-       };
 };
index 800f46f009f3838c98beaa83d05dd442acb68690..e65744fc12ab0e293ae8d43ce1d05311f7216f10 100644 (file)
@@ -5,8 +5,13 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <dt-bindings/clock/stih407-clks.h>
 / {
        clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
                /*
                 * Fixed 30MHz oscillator inputs to SoC
                 */
                /*
                 * ARM Peripheral clock for timers
                 */
-               arm_periph_clk: arm-periph-clk {
+               arm_periph_clk: clk-m-a9-periphs {
                        #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <600000000>;
+                       compatible = "fixed-factor-clock";
+
+                       clocks = <&clk_m_a9>;
+                       clock-div = <2>;
+                       clock-mult = <1>;
+               };
+
+               /*
+                * A9 PLL.
+                */
+               clockgen-a9@92b0000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x92b0000 0xffff>;
+
+                       clockgen_a9_pll: clockgen-a9-pll {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-a9", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clockgen-a9-pll-odf";
+                       };
+               };
+
+               /*
+                * ARM CPU related clocks.
+                */
+               clk_m_a9: clk-m-a9@92b0000 {
+                       #clock-cells = <0>;
+                       compatible = "st,stih407-clkgen-a9-mux", "st,clkgen-mux";
+                       reg = <0x92b0000 0x10000>;
+
+                       clocks = <&clockgen_a9_pll 0>,
+                                <&clockgen_a9_pll 0>,
+                                <&clk_s_c0_flexgen 13>,
+                                <&clk_m_a9_ext2f_div2>;
+               };
+
+               /*
+                * ARM Peripheral clock for timers
+                */
+               clk_m_a9_ext2f_div2: clk-m-a9-ext2f-div2s {
+                       #clock-cells = <0>;
+                       compatible = "fixed-factor-clock";
+
+                       clocks = <&clk_s_c0_flexgen 13>;
+
+                       clock-output-names = "clk-m-a9-ext2f-div2";
+
+                       clock-div = <2>;
+                       clock-mult = <1>;
                };
 
                /*
                        clock-frequency = <200000000>;
                        clock-output-names = "clk-s-icn-reg-0";
                };
+
+               clockgen-a@090ff000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x90ff000 0x1000>;
+
+                       clk_s_a0_pll: clk-s-a0-pll {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-a0", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clk-s-a0-pll-ofd-0";
+                       };
+
+                       clk_s_a0_flexgen: clk-s-a0-flexgen {
+                               compatible = "st,flexgen";
+
+                               #clock-cells = <1>;
+
+                               clocks = <&clk_s_a0_pll 0>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-ic-lmi0";
+                       };
+               };
+
+               clk_s_c0_quadfs: clk-s-c0-quadfs@9103000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-C", "st,quadfs";
+                       reg = <0x9103000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-c0-fs0-ch0",
+                                            "clk-s-c0-fs0-ch1",
+                                            "clk-s-c0-fs0-ch2",
+                                            "clk-s-c0-fs0-ch3";
+               };
+
+               clk_s_c0: clockgen-c@09103000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9103000 0x1000>;
+
+                       clk_s_c0_pll0: clk-s-c0-pll0 {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-c0_0", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clk-s-c0-pll0-odf-0";
+                       };
+
+                       clk_s_c0_pll1: clk-s-c0-pll1 {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-c0_1", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clk-s-c0-pll1-odf-0";
+                       };
+
+                       clk_s_c0_flexgen: clk-s-c0-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_c0_pll0 0>,
+                                        <&clk_s_c0_pll1 0>,
+                                        <&clk_s_c0_quadfs 0>,
+                                        <&clk_s_c0_quadfs 1>,
+                                        <&clk_s_c0_quadfs 2>,
+                                        <&clk_s_c0_quadfs 3>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-icn-gpu",
+                                                    "clk-fdma",
+                                                    "clk-nand",
+                                                    "clk-hva",
+                                                    "clk-proc-stfe",
+                                                    "clk-proc-tp",
+                                                    "clk-rx-icn-dmu",
+                                                    "clk-rx-icn-hva",
+                                                    "clk-icn-cpu",
+                                                    "clk-tx-icn-dmu",
+                                                    "clk-mmc-0",
+                                                    "clk-mmc-1",
+                                                    "clk-jpegdec",
+                                                    "clk-ext2fa9",
+                                                    "clk-ic-bdisp-0",
+                                                    "clk-ic-bdisp-1",
+                                                    "clk-pp-dmu",
+                                                    "clk-vid-dmu",
+                                                    "clk-dss-lpc",
+                                                    "clk-st231-aud-0",
+                                                    "clk-st231-gp-1",
+                                                    "clk-st231-dmu",
+                                                    "clk-icn-lmi",
+                                                    "clk-tx-icn-disp-1",
+                                                    "clk-icn-sbc",
+                                                    "clk-stfe-frc2",
+                                                    "clk-eth-phy",
+                                                    "clk-eth-ref-phyclk",
+                                                    "clk-flash-promip",
+                                                    "clk-main-disp",
+                                                    "clk-aux-disp",
+                                                    "clk-compo-dvp";
+                       };
+               };
+
+               clk_s_d0_quadfs: clk-s-d0-quadfs@9104000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-D", "st,quadfs";
+                       reg = <0x9104000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-d0-fs0-ch0",
+                                            "clk-s-d0-fs0-ch1",
+                                            "clk-s-d0-fs0-ch2",
+                                            "clk-s-d0-fs0-ch3";
+               };
+
+               clockgen-d0@09104000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9104000 0x1000>;
+
+                       clk_s_d0_flexgen: clk-s-d0-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_d0_quadfs 0>,
+                                        <&clk_s_d0_quadfs 1>,
+                                        <&clk_s_d0_quadfs 2>,
+                                        <&clk_s_d0_quadfs 3>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-pcm-0",
+                                                    "clk-pcm-1",
+                                                    "clk-pcm-2",
+                                                    "clk-spdiff";
+                       };
+               };
+
+               clk_s_d2_quadfs: clk-s-d2-quadfs@9106000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-D", "st,quadfs";
+                       reg = <0x9106000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-d2-fs0-ch0",
+                                            "clk-s-d2-fs0-ch1",
+                                            "clk-s-d2-fs0-ch2",
+                                            "clk-s-d2-fs0-ch3";
+               };
+
+               clk_tmdsout_hdmi: clk-tmdsout-hdmi {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <0>;
+               };
+
+               clockgen-d2@x9106000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9106000 0x1000>;
+
+                       clk_s_d2_flexgen: clk-s-d2-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_d2_quadfs 0>,
+                                        <&clk_s_d2_quadfs 1>,
+                                        <&clk_s_d2_quadfs 2>,
+                                        <&clk_s_d2_quadfs 3>,
+                                        <&clk_sysin>,
+                                        <&clk_sysin>,
+                                        <&clk_tmdsout_hdmi>;
+
+                               clock-output-names = "clk-pix-main-disp",
+                                                    "clk-pix-pip",
+                                                    "clk-pix-gdp1",
+                                                    "clk-pix-gdp2",
+                                                    "clk-pix-gdp3",
+                                                    "clk-pix-gdp4",
+                                                    "clk-pix-aux-disp",
+                                                    "clk-denc",
+                                                    "clk-pix-hddac",
+                                                    "clk-hddac",
+                                                    "clk-sddac",
+                                                    "clk-pix-dvo",
+                                                    "clk-dvo",
+                                                    "clk-pix-hdmi",
+                                                    "clk-tmds-hdmi",
+                                                    "clk-ref-hdmiphy";
+                                                    };
+               };
+
+               clk_s_d3_quadfs: clk-s-d3-quadfs@9107000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-D", "st,quadfs";
+                       reg = <0x9107000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-d3-fs0-ch0",
+                                            "clk-s-d3-fs0-ch1",
+                                            "clk-s-d3-fs0-ch2",
+                                            "clk-s-d3-fs0-ch3";
+               };
+
+               clockgen-d3@9107000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9107000 0x1000>;
+
+                       clk_s_d3_flexgen: clk-s-d3-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_d3_quadfs 0>,
+                                        <&clk_s_d3_quadfs 1>,
+                                        <&clk_s_d3_quadfs 2>,
+                                        <&clk_s_d3_quadfs 3>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-stfe-frc1",
+                                                    "clk-tsout-0",
+                                                    "clk-tsout-1",
+                                                    "clk-mchi",
+                                                    "clk-vsens-compo",
+                                                    "clk-frc1-remote",
+                                                    "clk-lpc-0",
+                                                    "clk-lpc-1";
+                       };
+               };
        };
 };
diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
new file mode 100644 (file)
index 0000000..3e31d32
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics Limited.
+ * Author: Giuseppe Cavallaro <peppe.cavallaro@st.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
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih407-pinctrl.dtsi"
+#include <dt-bindings/reset-controller/stih407-resets.h>
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <1>;
+               };
+       };
+
+       intc: interrupt-controller@08761000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x08761000 0x1000>, <0x08760100 0x100>;
+       };
+
+       scu@08760000 {
+               compatible = "arm,cortex-a9-scu";
+               reg = <0x08760000 0x1000>;
+       };
+
+       timer@08760200 {
+               interrupt-parent = <&intc>;
+               compatible = "arm,cortex-a9-global-timer";
+               reg = <0x08760200 0x100>;
+               interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&arm_periph_clk>;
+       };
+
+       l2: cache-controller {
+               compatible = "arm,pl310-cache";
+               reg = <0x08762000 0x1000>;
+               arm,data-latency = <3 3 3>;
+               arm,tag-latency = <2 2 2>;
+               cache-unified;
+               cache-level = <2>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               interrupt-parent = <&intc>;
+               ranges;
+               compatible = "simple-bus";
+
+               powerdown: powerdown-controller {
+                       compatible = "st,stih407-powerdown";
+                       #reset-cells = <1>;
+               };
+
+               softreset: softreset-controller {
+                       compatible = "st,stih407-softreset";
+                       #reset-cells = <1>;
+               };
+
+               picophyreset: picophyreset-controller {
+                       compatible = "st,stih407-picophyreset";
+                       #reset-cells = <1>;
+               };
+
+               syscfg_sbc: sbc-syscfg@9620000 {
+                       compatible = "st,stih407-sbc-syscfg", "syscon";
+                       reg = <0x9620000 0x1000>;
+               };
+
+               syscfg_front: front-syscfg@9280000 {
+                       compatible = "st,stih407-front-syscfg", "syscon";
+                       reg = <0x9280000 0x1000>;
+               };
+
+               syscfg_rear: rear-syscfg@9290000 {
+                       compatible = "st,stih407-rear-syscfg", "syscon";
+                       reg = <0x9290000 0x1000>;
+               };
+
+               syscfg_flash: flash-syscfg@92a0000 {
+                       compatible = "st,stih407-flash-syscfg", "syscon";
+                       reg = <0x92a0000 0x1000>;
+               };
+
+               syscfg_sbc_reg: fvdp-lite-syscfg@9600000 {
+                       compatible = "st,stih407-sbc-reg-syscfg", "syscon";
+                       reg = <0x9600000 0x1000>;
+               };
+
+               syscfg_core: core-syscfg@92b0000 {
+                       compatible = "st,stih407-core-syscfg", "syscon";
+                       reg = <0x92b0000 0x1000>;
+               };
+
+               syscfg_lpm: lpm-syscfg@94b5100 {
+                       compatible = "st,stih407-lpm-syscfg", "syscon";
+                       reg = <0x94b5100 0x1000>;
+               };
+
+               serial@9830000 {
+                       compatible = "st,asc";
+                       reg = <0x9830000 0x2c>;
+                       interrupts = <GIC_SPI 122 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_serial0>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+
+                       status = "disabled";
+               };
+
+               serial@9831000 {
+                       compatible = "st,asc";
+                       reg = <0x9831000 0x2c>;
+                       interrupts = <GIC_SPI 123 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_serial1>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+
+                       status = "disabled";
+               };
+
+               serial@9832000 {
+                       compatible = "st,asc";
+                       reg = <0x9832000 0x2c>;
+                       interrupts = <GIC_SPI 124 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_serial2>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+
+                       status = "disabled";
+               };
+
+               /* SBC_ASC0 - UART10 */
+               sbc_serial0: serial@9530000 {
+                       compatible = "st,asc";
+                       reg = <0x9530000 0x2c>;
+                       interrupts = <GIC_SPI 138 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_sbc_serial0>;
+                       clocks = <&clk_sysin>;
+
+                       status = "disabled";
+               };
+
+               serial@9531000 {
+                       compatible = "st,asc";
+                       reg = <0x9531000 0x2c>;
+                       interrupts = <GIC_SPI 139 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_sbc_serial1>;
+                       clocks = <&clk_sysin>;
+
+                       status = "disabled";
+               };
+
+               i2c@9840000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0x9840000 0x110>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c0_default>;
+
+                       status = "disabled";
+               };
+
+               i2c@9841000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       reg = <0x9841000 0x110>;
+                       interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c1_default>;
+
+                       status = "disabled";
+               };
+
+               i2c@9842000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       reg = <0x9842000 0x110>;
+                       interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c2_default>;
+
+                       status = "disabled";
+               };
+
+               i2c@9843000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       reg = <0x9843000 0x110>;
+                       interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c3_default>;
+
+                       status = "disabled";
+               };
+
+               i2c@9844000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       reg = <0x9844000 0x110>;
+                       interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c4_default>;
+
+                       status = "disabled";
+               };
+
+               i2c@9845000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       reg = <0x9845000 0x110>;
+                       interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c5_default>;
+
+                       status = "disabled";
+               };
+
+
+               /* SSCs on SBC */
+               i2c@9540000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       reg = <0x9540000 0x110>;
+                       interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_sysin>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c10_default>;
+
+                       status = "disabled";
+               };
+
+               i2c@9541000 {
+                       compatible = "st,comms-ssc4-i2c";
+                       reg = <0x9541000 0x110>;
+                       interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_sysin>;
+                       clock-names = "ssc";
+                       clock-frequency = <400000>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_i2c11_default>;
+
+                       status = "disabled";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/stih407.dtsi b/arch/arm/boot/dts/stih407.dtsi
deleted file mode 100644 (file)
index 4f9024f..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics Limited.
- * Author: Giuseppe Cavallaro <peppe.cavallaro@st.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
- * publishhed by the Free Software Foundation.
- */
-#include "stih407-clock.dtsi"
-#include "stih407-pinctrl.dtsi"
-/ {
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               cpu@0 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a9";
-                       reg = <0>;
-               };
-               cpu@1 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a9";
-                       reg = <1>;
-               };
-       };
-
-       intc: interrupt-controller@08761000 {
-               compatible = "arm,cortex-a9-gic";
-               #interrupt-cells = <3>;
-               interrupt-controller;
-               reg = <0x08761000 0x1000>, <0x08760100 0x100>;
-       };
-
-       scu@08760000 {
-               compatible = "arm,cortex-a9-scu";
-               reg = <0x08760000 0x1000>;
-       };
-
-       timer@08760200 {
-               interrupt-parent = <&intc>;
-               compatible = "arm,cortex-a9-global-timer";
-               reg = <0x08760200 0x100>;
-               interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&arm_periph_clk>;
-       };
-
-       l2: cache-controller {
-               compatible = "arm,pl310-cache";
-               reg = <0x08762000 0x1000>;
-               arm,data-latency = <3 3 3>;
-               arm,tag-latency = <2 2 2>;
-               cache-unified;
-               cache-level = <2>;
-       };
-
-       soc {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               interrupt-parent = <&intc>;
-               ranges;
-               compatible = "simple-bus";
-
-               syscfg_sbc: sbc-syscfg@9620000 {
-                       compatible = "st,stih407-sbc-syscfg", "syscon";
-                       reg = <0x9620000 0x1000>;
-               };
-
-               syscfg_front: front-syscfg@9280000 {
-                       compatible = "st,stih407-front-syscfg", "syscon";
-                       reg = <0x9280000 0x1000>;
-               };
-
-               syscfg_rear: rear-syscfg@9290000 {
-                       compatible = "st,stih407-rear-syscfg", "syscon";
-                       reg = <0x9290000 0x1000>;
-               };
-
-               syscfg_flash: flash-syscfg@92a0000 {
-                       compatible = "st,stih407-flash-syscfg", "syscon";
-                       reg = <0x92a0000 0x1000>;
-               };
-
-               syscfg_sbc_reg: fvdp-lite-syscfg@9600000 {
-                       compatible = "st,stih407-sbc-reg-syscfg", "syscon";
-                       reg = <0x9600000 0x1000>;
-               };
-
-               syscfg_core: core-syscfg@92b0000 {
-                       compatible = "st,stih407-core-syscfg", "syscon";
-                       reg = <0x92b0000 0x1000>;
-               };
-
-               syscfg_lpm: lpm-syscfg@94b5100 {
-                       compatible = "st,stih407-lpm-syscfg", "syscon";
-                       reg = <0x94b5100 0x1000>;
-               };
-
-               serial@9830000 {
-                       compatible = "st,asc";
-                       reg = <0x9830000 0x2c>;
-                       interrupts = <GIC_SPI 122 IRQ_TYPE_NONE>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_serial0>;
-                       clocks = <&clk_ext2f_a9>;
-
-                       status = "disabled";
-               };
-
-               serial@9831000 {
-                       compatible = "st,asc";
-                       reg = <0x9831000 0x2c>;
-                       interrupts = <GIC_SPI 123 IRQ_TYPE_NONE>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_serial1>;
-                       clocks = <&clk_ext2f_a9>;
-
-                       status = "disabled";
-               };
-
-               serial@9832000 {
-                       compatible = "st,asc";
-                       reg = <0x9832000 0x2c>;
-                       interrupts = <GIC_SPI 124 IRQ_TYPE_NONE>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_serial2>;
-                       clocks = <&clk_ext2f_a9>;
-
-                       status = "disabled";
-               };
-
-               /* SBC_ASC0 - UART10 */
-               sbc_serial0: serial@9530000 {
-                       compatible = "st,asc";
-                       reg = <0x9530000 0x2c>;
-                       interrupts = <GIC_SPI 138 IRQ_TYPE_NONE>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_sbc_serial0>;
-                       clocks = <&clk_sysin>;
-
-                       status = "disabled";
-               };
-
-               serial@9531000 {
-                       compatible = "st,asc";
-                       reg = <0x9531000 0x2c>;
-                       interrupts = <GIC_SPI 139 IRQ_TYPE_NONE>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_sbc_serial1>;
-                       clocks = <&clk_sysin>;
-
-                       status = "disabled";
-               };
-
-               i2c@9840000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-                       reg = <0x9840000 0x110>;
-                       clocks = <&clk_ext2f_a9>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c0_default>;
-
-                       status = "disabled";
-               };
-
-               i2c@9841000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       reg = <0x9841000 0x110>;
-                       interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&clk_ext2f_a9>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c1_default>;
-
-                       status = "disabled";
-               };
-
-               i2c@9842000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       reg = <0x9842000 0x110>;
-                       interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&clk_ext2f_a9>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c2_default>;
-
-                       status = "disabled";
-               };
-
-               i2c@9843000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       reg = <0x9843000 0x110>;
-                       interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&clk_ext2f_a9>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c3_default>;
-
-                       status = "disabled";
-               };
-
-               i2c@9844000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       reg = <0x9844000 0x110>;
-                       interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&clk_ext2f_a9>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c4_default>;
-
-                       status = "disabled";
-               };
-
-               i2c@9845000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       reg = <0x9845000 0x110>;
-                       interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&clk_ext2f_a9>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c5_default>;
-
-                       status = "disabled";
-               };
-
-
-               /* SSCs on SBC */
-               i2c@9540000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       reg = <0x9540000 0x110>;
-                       interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&clk_sysin>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c10_default>;
-
-                       status = "disabled";
-               };
-
-               i2c@9541000 {
-                       compatible = "st,comms-ssc4-i2c";
-                       reg = <0x9541000 0x110>;
-                       interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&clk_sysin>;
-                       clock-names = "ssc";
-                       clock-frequency = <400000>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_i2c11_default>;
-
-                       status = "disabled";
-               };
-       };
-};
diff --git a/arch/arm/boot/dts/stih410-b2120.dts b/arch/arm/boot/dts/stih410-b2120.dts
new file mode 100644 (file)
index 0000000..2f61a99
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited.
+ * Author: Peter Griffin <peter.griffin@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.
+ */
+/dts-v1/;
+#include "stih410.dtsi"
+#include "stihxxx-b2120.dtsi"
+/ {
+       model = "STiH410 B2120";
+       compatible = "st,stih410-b2120", "st,stih410";
+
+       chosen {
+               bootargs = "console=ttyAS0,115200 clk_ignore_unused";
+               linux,stdout-path = &sbc_serial0;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x40000000 0x80000000>;
+       };
+
+       aliases {
+               ttyAS0 = &sbc_serial0;
+       };
+};
diff --git a/arch/arm/boot/dts/stih410-clock.dtsi b/arch/arm/boot/dts/stih410-clock.dtsi
new file mode 100644 (file)
index 0000000..6b5803a
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics R&D Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <dt-bindings/clock/stih410-clks.h>
+/ {
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               compatible = "st,stih410-clk", "simple-bus";
+
+               /*
+                * Fixed 30MHz oscillator inputs to SoC
+                */
+               clk_sysin: clk-sysin {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <30000000>;
+                       clock-output-names = "CLK_SYSIN";
+               };
+
+               /*
+                * ARM Peripheral clock for timers
+                */
+               arm_periph_clk: clk-m-a9-periphs {
+                       #clock-cells = <0>;
+                       compatible = "fixed-factor-clock";
+                       clocks = <&clk_m_a9>;
+                       clock-div = <2>;
+                       clock-mult = <1>;
+               };
+
+               /*
+                * A9 PLL.
+                */
+               clockgen-a9@92b0000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x92b0000 0xffff>;
+
+                       clockgen_a9_pll: clockgen-a9-pll {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-a9", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clockgen-a9-pll-odf";
+                       };
+               };
+
+               /*
+                * ARM CPU related clocks.
+                */
+               clk_m_a9: clk-m-a9@92b0000 {
+                       #clock-cells = <0>;
+                       compatible = "st,stih407-clkgen-a9-mux", "st,clkgen-mux";
+                       reg = <0x92b0000 0x10000>;
+
+                       clocks = <&clockgen_a9_pll 0>,
+                                <&clockgen_a9_pll 0>,
+                                <&clk_s_c0_flexgen 13>,
+                                <&clk_m_a9_ext2f_div2>;
+               };
+
+               /*
+                * ARM Peripheral clock for timers
+                */
+               clk_m_a9_ext2f_div2: clk-m-a9-ext2f-div2s {
+                       #clock-cells = <0>;
+                       compatible = "fixed-factor-clock";
+
+                       clocks = <&clk_s_c0_flexgen 13>;
+
+                       clock-output-names = "clk-m-a9-ext2f-div2";
+
+                       clock-div = <2>;
+                       clock-mult = <1>;
+               };
+
+               /*
+                * Bootloader initialized system infrastructure clock for
+                * serial devices.
+                */
+               clk_ext2f_a9: clockgen-c0@13 {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <200000000>;
+                       clock-output-names = "clk-s-icn-reg-0";
+               };
+
+               clockgen-a@090ff000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x90ff000 0x1000>;
+
+                       clk_s_a0_pll: clk-s-a0-pll {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-a0", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clk-s-a0-pll-ofd-0";
+                       };
+
+                       clk_s_a0_flexgen: clk-s-a0-flexgen {
+                               compatible = "st,flexgen";
+
+                               #clock-cells = <1>;
+
+                               clocks = <&clk_s_a0_pll 0>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-ic-lmi0",
+                                                    "clk-ic-lmi1";
+                       };
+               };
+
+               clk_s_c0_quadfs: clk-s-c0-quadfs@9103000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-C", "st,quadfs";
+                       reg = <0x9103000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-c0-fs0-ch0",
+                                            "clk-s-c0-fs0-ch1",
+                                            "clk-s-c0-fs0-ch2",
+                                            "clk-s-c0-fs0-ch3";
+               };
+
+               clk_s_c0: clockgen-c@09103000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9103000 0x1000>;
+
+                       clk_s_c0_pll0: clk-s-c0-pll0 {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-c0_0", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clk-s-c0-pll0-odf-0";
+                       };
+
+                       clk_s_c0_pll1: clk-s-c0-pll1 {
+                               #clock-cells = <1>;
+                               compatible = "st,stih407-plls-c32-c0_1", "st,clkgen-plls-c32";
+
+                               clocks = <&clk_sysin>;
+
+                               clock-output-names = "clk-s-c0-pll1-odf-0";
+                       };
+
+                       clk_s_c0_flexgen: clk-s-c0-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_c0_pll0 0>,
+                                        <&clk_s_c0_pll1 0>,
+                                        <&clk_s_c0_quadfs 0>,
+                                        <&clk_s_c0_quadfs 1>,
+                                        <&clk_s_c0_quadfs 2>,
+                                        <&clk_s_c0_quadfs 3>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-icn-gpu",
+                                                    "clk-fdma",
+                                                    "clk-nand",
+                                                    "clk-hva",
+                                                    "clk-proc-stfe",
+                                                    "clk-proc-tp",
+                                                    "clk-rx-icn-dmu",
+                                                    "clk-rx-icn-hva",
+                                                    "clk-icn-cpu",
+                                                    "clk-tx-icn-dmu",
+                                                    "clk-mmc-0",
+                                                    "clk-mmc-1",
+                                                    "clk-jpegdec",
+                                                    "clk-ext2fa9",
+                                                    "clk-ic-bdisp-0",
+                                                    "clk-ic-bdisp-1",
+                                                    "clk-pp-dmu",
+                                                    "clk-vid-dmu",
+                                                    "clk-dss-lpc",
+                                                    "clk-st231-aud-0",
+                                                    "clk-st231-gp-1",
+                                                    "clk-st231-dmu",
+                                                    "clk-icn-lmi",
+                                                    "clk-tx-icn-disp-1",
+                                                    "clk-icn-sbc",
+                                                    "clk-stfe-frc2",
+                                                    "clk-eth-phy",
+                                                    "clk-eth-ref-phyclk",
+                                                    "clk-flash-promip",
+                                                    "clk-main-disp",
+                                                    "clk-aux-disp",
+                                                    "clk-compo-dvp",
+                                                    "clk-tx-icn-hades",
+                                                    "clk-rx-icn-hades",
+                                                    "clk-icn-reg-16",
+                                                    "clk-pp-hades",
+                                                    "clk-clust-hades",
+                                                    "clk-hwpe-hades",
+                                                    "clk-fc-hades";
+                       };
+               };
+
+               clk_s_d0_quadfs: clk-s-d0-quadfs@9104000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-D", "st,quadfs";
+                       reg = <0x9104000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-d0-fs0-ch0",
+                                            "clk-s-d0-fs0-ch1",
+                                            "clk-s-d0-fs0-ch2",
+                                            "clk-s-d0-fs0-ch3";
+               };
+
+               clockgen-d0@09104000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9104000 0x1000>;
+
+                       clk_s_d0_flexgen: clk-s-d0-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_d0_quadfs 0>,
+                                        <&clk_s_d0_quadfs 1>,
+                                        <&clk_s_d0_quadfs 2>,
+                                        <&clk_s_d0_quadfs 3>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-pcm-0",
+                                                    "clk-pcm-1",
+                                                    "clk-pcm-2",
+                                                    "clk-spdiff",
+                                                    "clk-pcmr10-master",
+                                                    "clk-usb2-phy";
+                       };
+               };
+
+               clk_s_d2_quadfs: clk-s-d2-quadfs@9106000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-D", "st,quadfs";
+                       reg = <0x9106000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-d2-fs0-ch0",
+                                            "clk-s-d2-fs0-ch1",
+                                            "clk-s-d2-fs0-ch2",
+                                            "clk-s-d2-fs0-ch3";
+               };
+
+               clk_tmdsout_hdmi: clk-tmdsout-hdmi {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <0>;
+               };
+
+               clockgen-d2@x9106000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9106000 0x1000>;
+
+                       clk_s_d2_flexgen: clk-s-d2-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_d2_quadfs 0>,
+                                        <&clk_s_d2_quadfs 1>,
+                                        <&clk_s_d2_quadfs 2>,
+                                        <&clk_s_d2_quadfs 3>,
+                                        <&clk_sysin>,
+                                        <&clk_sysin>,
+                                        <&clk_tmdsout_hdmi>;
+
+                               clock-output-names = "clk-pix-main-disp",
+                                                    "clk-pix-pip",
+                                                    "clk-pix-gdp1",
+                                                    "clk-pix-gdp2",
+                                                    "clk-pix-gdp3",
+                                                    "clk-pix-gdp4",
+                                                    "clk-pix-aux-disp",
+                                                    "clk-denc",
+                                                    "clk-pix-hddac",
+                                                    "clk-hddac",
+                                                    "clk-sddac",
+                                                    "clk-pix-dvo",
+                                                    "clk-dvo",
+                                                    "clk-pix-hdmi",
+                                                    "clk-tmds-hdmi",
+                                                    "clk-ref-hdmiphy";
+                                                    };
+               };
+
+               clk_s_d3_quadfs: clk-s-d3-quadfs@9107000 {
+                       #clock-cells = <1>;
+                       compatible = "st,stih407-quadfs660-D", "st,quadfs";
+                       reg = <0x9107000 0x1000>;
+
+                       clocks = <&clk_sysin>;
+
+                       clock-output-names = "clk-s-d3-fs0-ch0",
+                                            "clk-s-d3-fs0-ch1",
+                                            "clk-s-d3-fs0-ch2",
+                                            "clk-s-d3-fs0-ch3";
+               };
+
+               clockgen-d3@9107000 {
+                       compatible = "st,clkgen-c32";
+                       reg = <0x9107000 0x1000>;
+
+                       clk_s_d3_flexgen: clk-s-d3-flexgen {
+                               #clock-cells = <1>;
+                               compatible = "st,flexgen";
+
+                               clocks = <&clk_s_d3_quadfs 0>,
+                                        <&clk_s_d3_quadfs 1>,
+                                        <&clk_s_d3_quadfs 2>,
+                                        <&clk_s_d3_quadfs 3>,
+                                        <&clk_sysin>;
+
+                               clock-output-names = "clk-stfe-frc1",
+                                                    "clk-tsout-0",
+                                                    "clk-tsout-1",
+                                                    "clk-mchi",
+                                                    "clk-vsens-compo",
+                                                    "clk-frc1-remote",
+                                                    "clk-lpc-0",
+                                                    "clk-lpc-1";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/stih410-pinctrl.dtsi b/arch/arm/boot/dts/stih410-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..b3e9dfc
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics Limited.
+ * Author: Peter Griffin <peter.griffin@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
+ * publishhed by the Free Software Foundation.
+ */
+#include "st-pincfg.h"
+/ {
+
+       soc {
+               pin-controller-rear {
+
+                       usb0 {
+                               pinctrl_usb0: usb2-0 {
+                                       st,pins {
+                                               usb-oc-detect = <&pio35 0 ALT1 IN>;
+                                               usb-pwr-enable = <&pio35 1 ALT1 OUT>;
+                                       };
+                               };
+                       };
+
+                       usb1 {
+                               pinctrl_usb1: usb2-1 {
+                                       st,pins {
+                                               usb-oc-detect = <&pio35 2 ALT1 IN>;
+                                               usb-pwr-enable = <&pio35 3 ALT1 OUT>;
+                                       };
+                               };
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi
new file mode 100644 (file)
index 0000000..c05627e
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics Limited.
+ * Author: Peter Griffin <peter.griffin@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
+ * publishhed by the Free Software Foundation.
+ */
+#include "stih410-clock.dtsi"
+#include "stih407-family.dtsi"
+#include "stih410-pinctrl.dtsi"
+/ {
+
+};
index 8509a037ae2193d8da6ab290b7bf256313328dab..3791ad95dbaff9a35321dfa326c7af17e20d370b 100644 (file)
 / {
 
        aliases {
-               gpio0   = &PIO0;
-               gpio1   = &PIO1;
-               gpio2   = &PIO2;
-               gpio3   = &PIO3;
-               gpio4   = &PIO4;
-               gpio5   = &PIO5;
-               gpio6   = &PIO6;
-               gpio7   = &PIO7;
-               gpio8   = &PIO8;
-               gpio9   = &PIO9;
-               gpio10  = &PIO10;
-               gpio11  = &PIO11;
-               gpio12  = &PIO12;
-               gpio13  = &PIO13;
-               gpio14  = &PIO14;
-               gpio15  = &PIO15;
-               gpio16  = &PIO16;
-               gpio17  = &PIO17;
-               gpio18  = &PIO18;
-               gpio19  = &PIO100;
-               gpio20  = &PIO101;
-               gpio21  = &PIO102;
-               gpio22  = &PIO103;
-               gpio23  = &PIO104;
-               gpio24  = &PIO105;
-               gpio25  = &PIO106;
-               gpio26  = &PIO107;
+               gpio0   = &pio0;
+               gpio1   = &pio1;
+               gpio2   = &pio2;
+               gpio3   = &pio3;
+               gpio4   = &pio4;
+               gpio5   = &pio5;
+               gpio6   = &pio6;
+               gpio7   = &pio7;
+               gpio8   = &pio8;
+               gpio9   = &pio9;
+               gpio10  = &pio10;
+               gpio11  = &pio11;
+               gpio12  = &pio12;
+               gpio13  = &pio13;
+               gpio14  = &pio14;
+               gpio15  = &pio15;
+               gpio16  = &pio16;
+               gpio17  = &pio17;
+               gpio18  = &pio18;
+               gpio19  = &pio100;
+               gpio20  = &pio101;
+               gpio21  = &pio102;
+               gpio22  = &pio103;
+               gpio23  = &pio104;
+               gpio24  = &pio105;
+               gpio25  = &pio106;
+               gpio26  = &pio107;
        };
 
        soc {
@@ -52,7 +52,7 @@
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfe610000 0x5000>;
 
-                       PIO0: gpio@fe610000 {
+                       pio0: gpio@fe610000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -60,7 +60,7 @@
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO0";
                        };
-                       PIO1: gpio@fe611000 {
+                       pio1: gpio@fe611000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -68,7 +68,7 @@
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO1";
                        };
-                       PIO2: gpio@fe612000 {
+                       pio2: gpio@fe612000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -76,7 +76,7 @@
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO2";
                        };
-                       PIO3: gpio@fe613000 {
+                       pio3: gpio@fe613000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -84,7 +84,7 @@
                                reg             = <0x3000 0x100>;
                                st,bank-name    = "PIO3";
                        };
-                       PIO4: gpio@fe614000 {
+                       pio4: gpio@fe614000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -96,8 +96,8 @@
                        sbc_serial1 {
                                pinctrl_sbc_serial1:sbc_serial1 {
                                        st,pins {
-                                               tx      = <&PIO2 6 ALT3 OUT>;
-                                               rx      = <&PIO2 7 ALT3 IN>;
+                                               tx      = <&pio2 6 ALT3 OUT>;
+                                               rx      = <&pio2 7 ALT3 IN>;
                                        };
                                };
                        };
                        keyscan {
                                pinctrl_keyscan: keyscan {
                                        st,pins {
-                                               keyin0 = <&PIO0 2 ALT2 IN>;
-                                               keyin1 = <&PIO0 3 ALT2 IN>;
-                                               keyin2 = <&PIO0 4 ALT2 IN>;
-                                               keyin3 = <&PIO2 6 ALT2 IN>;
-
-                                               keyout0 = <&PIO1 6 ALT2 OUT>;
-                                               keyout1 = <&PIO1 7 ALT2 OUT>;
-                                               keyout2 = <&PIO0 6 ALT2 OUT>;
-                                               keyout3 = <&PIO2 7 ALT2 OUT>;
+                                               keyin0 = <&pio0 2 ALT2 IN>;
+                                               keyin1 = <&pio0 3 ALT2 IN>;
+                                               keyin2 = <&pio0 4 ALT2 IN>;
+                                               keyin3 = <&pio2 6 ALT2 IN>;
+
+                                               keyout0 = <&pio1 6 ALT2 OUT>;
+                                               keyout1 = <&pio1 7 ALT2 OUT>;
+                                               keyout2 = <&pio0 6 ALT2 OUT>;
+                                               keyout3 = <&pio2 7 ALT2 OUT>;
                                        };
                                };
                        };
                        sbc_i2c0 {
                                pinctrl_sbc_i2c0_default: sbc_i2c0-default {
                                        st,pins {
-                                               sda = <&PIO4 6 ALT1 BIDIR>;
-                                               scl = <&PIO4 5 ALT1 BIDIR>;
+                                               sda = <&pio4 6 ALT1 BIDIR>;
+                                               scl = <&pio4 5 ALT1 BIDIR>;
                                        };
                                };
                        };
                        sbc_i2c1 {
                                pinctrl_sbc_i2c1_default: sbc_i2c1-default {
                                        st,pins {
-                                               sda = <&PIO3 2 ALT2 BIDIR>;
-                                               scl = <&PIO3 1 ALT2 BIDIR>;
+                                               sda = <&pio3 2 ALT2 BIDIR>;
+                                               scl = <&pio3 1 ALT2 BIDIR>;
                                        };
                                };
                        };
                        rc{
                                pinctrl_ir: ir0 {
                                        st,pins {
-                                               ir = <&PIO4 0 ALT2 IN>;
+                                               ir = <&pio4 0 ALT2 IN>;
                                        };
                                };
                        };
                        gmac1 {
                                pinctrl_mii1: mii1 {
                                                st,pins {
-                                                txd0   = <&PIO0 0 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
-                                                txd1   = <&PIO0 1 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
-                                                txd2   = <&PIO0 2 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
-                                                txd3   = <&PIO0 3 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
-                                                txer   = <&PIO0 4 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
-                                                txen   = <&PIO0 5 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
-                                                txclk  = <&PIO0 6 ALT1 IN   NICLK      0       CLK_A>;
-                                                col    = <&PIO0 7 ALT1 IN   BYPASS     1000>;
-                                                mdio   = <&PIO1 0 ALT1 OUT  BYPASS     0>;
-                                                mdc    = <&PIO1 1 ALT1 OUT  NICLK      0       CLK_A>;
-                                                crs    = <&PIO1 2 ALT1 IN   BYPASS     1000>;
-                                                mdint  = <&PIO1 3 ALT1 IN   BYPASS     0>;
-                                                rxd0   = <&PIO1 4 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
-                                                rxd1   = <&PIO1 5 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
-                                                rxd2   = <&PIO1 6 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
-                                                rxd3   = <&PIO1 7 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
-                                                rxdv   = <&PIO2 0 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
-                                                rx_er  = <&PIO2 1 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
-                                                rxclk  = <&PIO2 2 ALT1 IN   NICLK      0       CLK_A>;
-                                                phyclk = <&PIO2 3 ALT1 IN   NICLK      1000    CLK_A>;
+                                                txd0   = <&pio0 0 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
+                                                txd1   = <&pio0 1 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
+                                                txd2   = <&pio0 2 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
+                                                txd3   = <&pio0 3 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
+                                                txer   = <&pio0 4 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
+                                                txen   = <&pio0 5 ALT1 OUT  SE_NICLK_IO        0       CLK_A>;
+                                                txclk  = <&pio0 6 ALT1 IN   NICLK      0       CLK_A>;
+                                                col    = <&pio0 7 ALT1 IN   BYPASS     1000>;
+                                                mdio   = <&pio1 0 ALT1 OUT  BYPASS     0>;
+                                                mdc    = <&pio1 1 ALT1 OUT  NICLK      0       CLK_A>;
+                                                crs    = <&pio1 2 ALT1 IN   BYPASS     1000>;
+                                                mdint  = <&pio1 3 ALT1 IN   BYPASS     0>;
+                                                rxd0   = <&pio1 4 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
+                                                rxd1   = <&pio1 5 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
+                                                rxd2   = <&pio1 6 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
+                                                rxd3   = <&pio1 7 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
+                                                rxdv   = <&pio2 0 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
+                                                rx_er  = <&pio2 1 ALT1 IN   SE_NICLK_IO        0       CLK_A>;
+                                                rxclk  = <&pio2 2 ALT1 IN   NICLK      0       CLK_A>;
+                                                phyclk = <&pio2 3 ALT1 IN   NICLK      1000    CLK_A>;
                                        };
                                };
 
                                pinctrl_rgmii1: rgmii1-0 {
                                        st,pins {
-                                                txd0 =  <&PIO0 0 ALT1 OUT DE_IO        1000    CLK_A>;
-                                                txd1 =  <&PIO0 1 ALT1 OUT DE_IO        1000    CLK_A>;
-                                                txd2 =  <&PIO0 2 ALT1 OUT DE_IO        1000    CLK_A>;
-                                                txd3 =  <&PIO0 3 ALT1 OUT DE_IO        1000    CLK_A>;
-                                                txen =  <&PIO0 5 ALT1 OUT DE_IO        0       CLK_A>;
-                                                txclk = <&PIO0 6 ALT1 IN       NICLK   0       CLK_A>;
-                                                mdio =  <&PIO1 0 ALT1 OUT      BYPASS  0>;
-                                                mdc =   <&PIO1 1 ALT1 OUT      NICLK   0       CLK_A>;
-                                                rxd0 =  <&PIO1 4 ALT1 IN DE_IO 0       CLK_A>;
-                                                rxd1 =  <&PIO1 5 ALT1 IN DE_IO 0       CLK_A>;
-                                                rxd2 =  <&PIO1 6 ALT1 IN DE_IO 0       CLK_A>;
-                                                rxd3 =  <&PIO1 7 ALT1 IN DE_IO 0       CLK_A>;
-
-                                                rxdv =   <&PIO2 0 ALT1 IN DE_IO        500     CLK_A>;
-                                                rxclk =  <&PIO2 2 ALT1 IN      NICLK   0       CLK_A>;
-                                                phyclk = <&PIO2 3 ALT4 OUT     NICLK   0       CLK_B>;
-
-                                                clk125= <&PIO3 7 ALT4 IN       NICLK   0       CLK_A>;
+                                                txd0 =  <&pio0 0 ALT1 OUT DE_IO        1000    CLK_A>;
+                                                txd1 =  <&pio0 1 ALT1 OUT DE_IO        1000    CLK_A>;
+                                                txd2 =  <&pio0 2 ALT1 OUT DE_IO        1000    CLK_A>;
+                                                txd3 =  <&pio0 3 ALT1 OUT DE_IO        1000    CLK_A>;
+                                                txen =  <&pio0 5 ALT1 OUT DE_IO        0       CLK_A>;
+                                                txclk = <&pio0 6 ALT1 IN       NICLK   0       CLK_A>;
+                                                mdio =  <&pio1 0 ALT1 OUT      BYPASS  0>;
+                                                mdc =   <&pio1 1 ALT1 OUT      NICLK   0       CLK_A>;
+                                                rxd0 =  <&pio1 4 ALT1 IN DE_IO 0       CLK_A>;
+                                                rxd1 =  <&pio1 5 ALT1 IN DE_IO 0       CLK_A>;
+                                                rxd2 =  <&pio1 6 ALT1 IN DE_IO 0       CLK_A>;
+                                                rxd3 =  <&pio1 7 ALT1 IN DE_IO 0       CLK_A>;
+
+                                                rxdv =   <&pio2 0 ALT1 IN DE_IO        500     CLK_A>;
+                                                rxclk =  <&pio2 2 ALT1 IN      NICLK   0       CLK_A>;
+                                                phyclk = <&pio2 3 ALT4 OUT     NICLK   0       CLK_B>;
+
+                                                clk125= <&pio3 7 ALT4 IN       NICLK   0       CLK_A>;
                                        };
                                };
                        };
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfee00000 0x8000>;
 
-                       PIO5: gpio@fee00000 {
+                       pio5: gpio@fee00000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO5";
                        };
-                       PIO6: gpio@fee01000 {
+                       pio6: gpio@fee01000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO6";
                        };
-                       PIO7: gpio@fee02000 {
+                       pio7: gpio@fee02000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO7";
                        };
-                       PIO8: gpio@fee03000 {
+                       pio8: gpio@fee03000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x3000 0x100>;
                                st,bank-name    = "PIO8";
                        };
-                       PIO9: gpio@fee04000 {
+                       pio9: gpio@fee04000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x4000 0x100>;
                                st,bank-name    = "PIO9";
                        };
-                       PIO10: gpio@fee05000 {
+                       pio10: gpio@fee05000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x5000 0x100>;
                                st,bank-name    = "PIO10";
                        };
-                       PIO11: gpio@fee06000 {
+                       pio11: gpio@fee06000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x6000 0x100>;
                                st,bank-name    = "PIO11";
                        };
-                       PIO12: gpio@fee07000 {
+                       pio12: gpio@fee07000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                        i2c0 {
                                pinctrl_i2c0_default: i2c0-default {
                                        st,pins {
-                                               sda = <&PIO9 3 ALT1 BIDIR>;
-                                               scl = <&PIO9 2 ALT1 BIDIR>;
+                                               sda = <&pio9 3 ALT1 BIDIR>;
+                                               scl = <&pio9 2 ALT1 BIDIR>;
                                        };
                                };
                        };
                        i2c1 {
                                pinctrl_i2c1_default: i2c1-default {
                                        st,pins {
-                                               sda = <&PIO12 1 ALT1 BIDIR>;
-                                               scl = <&PIO12 0 ALT1 BIDIR>;
+                                               sda = <&pio12 1 ALT1 BIDIR>;
+                                               scl = <&pio12 0 ALT1 BIDIR>;
                                        };
                                };
                        };
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfe820000 0x8000>;
 
-                       PIO13: gpio@fe820000 {
+                       pio13: gpio@fe820000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO13";
                        };
-                       PIO14: gpio@fe821000 {
+                       pio14: gpio@fe821000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO14";
                        };
-                       PIO15: gpio@fe822000 {
+                       pio15: gpio@fe822000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO15";
                        };
-                       PIO16: gpio@fe823000 {
+                       pio16: gpio@fe823000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x3000 0x100>;
                                st,bank-name    = "PIO16";
                        };
-                       PIO17: gpio@fe824000 {
+                       pio17: gpio@fe824000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x4000 0x100>;
                                st,bank-name    = "PIO17";
                        };
-                       PIO18: gpio@fe825000 {
+                       pio18: gpio@fe825000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                        serial2 {
                                pinctrl_serial2: serial2-0 {
                                        st,pins {
-                                               tx      = <&PIO17 4 ALT2 OUT>;
-                                               rx      = <&PIO17 5 ALT2 IN>;
+                                               tx      = <&pio17 4 ALT2 OUT>;
+                                               rx      = <&pio17 5 ALT2 IN>;
                                        };
                                };
                        };
                        gmac0{
                                pinctrl_mii0: mii0 {
                                        st,pins {
-                                        mdint =        <&PIO13 6 ALT2  IN      BYPASS          0>;
-                                        txen =         <&PIO13 7 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
-
-                                        txd0 =         <&PIO14 0 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
-                                        txd1 =         <&PIO14 1 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
-                                        txd2 =         <&PIO14 2 ALT2  OUT     SE_NICLK_IO     0       CLK_B>;
-                                        txd3 =         <&PIO14 3 ALT2  OUT     SE_NICLK_IO     0       CLK_B>;
-
-                                        txclk =        <&PIO15 0 ALT2  IN      NICLK           0       CLK_A>;
-                                        txer =         <&PIO15 1 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
-                                        crs =          <&PIO15 2 ALT2  IN      BYPASS          1000>;
-                                        col =          <&PIO15 3 ALT2  IN      BYPASS          1000>;
-                                        mdio  =        <&PIO15 4 ALT2  OUT     BYPASS  3000>;
-                                        mdc   =        <&PIO15 5 ALT2  OUT     NICLK   0       CLK_B>;
-
-                                        rxd0 =         <&PIO16 0 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
-                                        rxd1 =         <&PIO16 1 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
-                                        rxd2 =         <&PIO16 2 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
-                                        rxd3 =         <&PIO16 3 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
-                                        rxdv =         <&PIO15 6 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
-                                        rx_er =        <&PIO15 7 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
-                                        rxclk =        <&PIO17 0 ALT2  IN      NICLK           0       CLK_A>;
-                                        phyclk =       <&PIO13 5 ALT2  OUT     NICLK   1000    CLK_A>;
+                                        mdint =        <&pio13 6 ALT2  IN      BYPASS          0>;
+                                        txen =         <&pio13 7 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
+
+                                        txd0 =         <&pio14 0 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
+                                        txd1 =         <&pio14 1 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
+                                        txd2 =         <&pio14 2 ALT2  OUT     SE_NICLK_IO     0       CLK_B>;
+                                        txd3 =         <&pio14 3 ALT2  OUT     SE_NICLK_IO     0       CLK_B>;
+
+                                        txclk =        <&pio15 0 ALT2  IN      NICLK           0       CLK_A>;
+                                        txer =         <&pio15 1 ALT2  OUT     SE_NICLK_IO     0       CLK_A>;
+                                        crs =          <&pio15 2 ALT2  IN      BYPASS          1000>;
+                                        col =          <&pio15 3 ALT2  IN      BYPASS          1000>;
+                                        mdio  =        <&pio15 4 ALT2  OUT     BYPASS  3000>;
+                                        mdc   =        <&pio15 5 ALT2  OUT     NICLK   0       CLK_B>;
+
+                                        rxd0 =         <&pio16 0 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
+                                        rxd1 =         <&pio16 1 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
+                                        rxd2 =         <&pio16 2 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
+                                        rxd3 =         <&pio16 3 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
+                                        rxdv =         <&pio15 6 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
+                                        rx_er =        <&pio15 7 ALT2  IN      SE_NICLK_IO     0       CLK_A>;
+                                        rxclk =        <&pio17 0 ALT2  IN      NICLK           0       CLK_A>;
+                                        phyclk =       <&pio13 5 ALT2  OUT     NICLK   1000    CLK_A>;
 
                                        };
                                };
 
                        pinctrl_gmii0: gmii0 {
                                st,pins {
-                                        mdint =        <&PIO13 6       ALT2 IN         BYPASS  0>;
-                                        mdio  =        <&PIO15 4       ALT2 OUT        BYPASS  3000>;
-                                        mdc   =        <&PIO15 5       ALT2 OUT        NICLK   0       CLK_B>;
-                                        txen =         <&PIO13 7       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
-
-                                        txd0 =         <&PIO14 0       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
-                                        txd1 =         <&PIO14 1       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
-                                        txd2 =         <&PIO14 2       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
-                                        txd3 =         <&PIO14 3       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
-                                        txd4 =         <&PIO14 4       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
-                                        txd5 =         <&PIO14 5       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
-                                        txd6 =         <&PIO14 6       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
-                                        txd7 =         <&PIO14 7       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
-
-                                        txclk =        <&PIO15 0       ALT2 IN         NICLK   0       CLK_A>;
-                                        txer =         <&PIO15 1       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
-                                        crs =          <&PIO15 2       ALT2 IN         BYPASS  1000>;
-                                        col =          <&PIO15 3       ALT2 IN         BYPASS  1000>;
-                                        rxdv =         <&PIO15 6       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rx_er =        <&PIO15 7       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-
-                                        rxd0 =         <&PIO16 0       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rxd1 =         <&PIO16 1       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rxd2 =         <&PIO16 2       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rxd3 =         <&PIO16 3       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rxd4 =         <&PIO16 4       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rxd5 =         <&PIO16 5       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rxd6 =         <&PIO16 6       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-                                        rxd7 =         <&PIO16 7       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
-
-                                        rxclk =        <&PIO17 0       ALT2 IN NICLK   0       CLK_A>;
-                                        clk125 =       <&PIO17 6       ALT1 IN NICLK   0       CLK_A>;
-                                         phyclk =       <&PIO13 5       ALT4 OUT NICLK   0       CLK_B>;
+                                        mdint =        <&pio13 6       ALT2 IN         BYPASS  0>;
+                                        mdio  =        <&pio15 4       ALT2 OUT        BYPASS  3000>;
+                                        mdc   =        <&pio15 5       ALT2 OUT        NICLK   0       CLK_B>;
+                                        txen =         <&pio13 7       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
+
+                                        txd0 =         <&pio14 0       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
+                                        txd1 =         <&pio14 1       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
+                                        txd2 =         <&pio14 2       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
+                                        txd3 =         <&pio14 3       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
+                                        txd4 =         <&pio14 4       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
+                                        txd5 =         <&pio14 5       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
+                                        txd6 =         <&pio14 6       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
+                                        txd7 =         <&pio14 7       ALT2 OUT        SE_NICLK_IO     3000    CLK_B>;
+
+                                        txclk =        <&pio15 0       ALT2 IN         NICLK   0       CLK_A>;
+                                        txer =         <&pio15 1       ALT2 OUT        SE_NICLK_IO     3000    CLK_A>;
+                                        crs =          <&pio15 2       ALT2 IN         BYPASS  1000>;
+                                        col =          <&pio15 3       ALT2 IN         BYPASS  1000>;
+                                        rxdv =         <&pio15 6       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rx_er =        <&pio15 7       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+
+                                        rxd0 =         <&pio16 0       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rxd1 =         <&pio16 1       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rxd2 =         <&pio16 2       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rxd3 =         <&pio16 3       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rxd4 =         <&pio16 4       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rxd5 =         <&pio16 5       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rxd6 =         <&pio16 6       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+                                        rxd7 =         <&pio16 7       ALT2 IN         SE_NICLK_IO     1500    CLK_A>;
+
+                                        rxclk =        <&pio17 0       ALT2 IN NICLK   0       CLK_A>;
+                                        clk125 =       <&pio17 6       ALT1 IN NICLK   0       CLK_A>;
+                                         phyclk =       <&pio13 5       ALT4 OUT NICLK   0       CLK_B>;
 
 
                                        };
                                };
                        };
+
+                       mmc0 {
+                               pinctrl_mmc0: mmc0 {
+                                       st,pins {
+                                               mmcclk = <&pio13 4 ALT4 BIDIR_PU NICLK 0 CLK_B>;
+                                               data0  = <&pio14 4 ALT4 BIDIR_PU BYPASS 0>;
+                                               data1  = <&pio14 5 ALT4 BIDIR_PU BYPASS 0>;
+                                               data2  = <&pio14 6 ALT4 BIDIR_PU BYPASS 0>;
+                                               data3  = <&pio14 7 ALT4 BIDIR_PU BYPASS 0>;
+                                               cmd    = <&pio15 1 ALT4 BIDIR_PU BYPASS 0>;
+                                               wp     = <&pio15 3 ALT4 IN>;
+                                               data4  = <&pio16 4 ALT4 BIDIR_PU BYPASS 0>;
+                                               data5  = <&pio16 5 ALT4 BIDIR_PU BYPASS 0>;
+                                               data6  = <&pio16 6 ALT4 BIDIR_PU BYPASS 0>;
+                                               data7  = <&pio16 7 ALT4 BIDIR_PU BYPASS 0>;
+                                               pwr    = <&pio17 1 ALT4 OUT>;
+                                               cd     = <&pio17 2 ALT4 IN>;
+                                               led    = <&pio17 3 ALT4 OUT>;
+                                       };
+                               };
+                       };
                };
 
                pin-controller-left {
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfd6b0000 0x3000>;
 
-                       PIO100: gpio@fd6b0000 {
+                       pio100: gpio@fd6b0000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO100";
                        };
-                       PIO101: gpio@fd6b1000 {
+                       pio101: gpio@fd6b1000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO101";
                        };
-                       PIO102: gpio@fd6b2000 {
+                       pio102: gpio@fd6b2000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfd330000 0x5000>;
 
-                       PIO103: gpio@fd330000 {
+                       pio103: gpio@fd330000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO103";
                        };
-                       PIO104: gpio@fd331000 {
+                       pio104: gpio@fd331000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO104";
                        };
-                       PIO105: gpio@fd332000 {
+                       pio105: gpio@fd332000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO105";
                        };
-                       PIO106: gpio@fd333000 {
+                       pio106: gpio@fd333000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x3000 0x100>;
                                st,bank-name    = "PIO106";
                        };
-                       PIO107: gpio@fd334000 {
+                       pio107: gpio@fd334000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
index a0f6f75fe3b558d6cb32dbfb1c03f2fb121c45ac..9198c12765ea0eb49de1a0b53545b6819b4b48bc 100644 (file)
                        resets  = <&powerdown STIH415_KEYSCAN_POWERDOWN>,
                                  <&softreset STIH415_KEYSCAN_SOFTRESET>;
                };
+
+               mmc0: sdhci@fe81e000 {
+                       compatible      = "st,sdhci";
+                       status          = "disabled";
+                       reg             = <0xfe81e000 0x1000>;
+                       interrupts      = <GIC_SPI 145 IRQ_TYPE_NONE>;
+                       interrupt-names = "mmcirq";
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_mmc0>;
+                       clock-names     = "mmc";
+                       clocks          = <&clk_s_a1_ls 1>;
+               };
        };
 };
index 4e2df66b99eaf2443e03a8062eebd1b2ea6f7686..200a81844765d203c421df8e081a56f1801fb7a2 100644 (file)
 / {
        model = "STiH416 B2020";
        compatible = "st,stih416-b2020", "st,stih416";
+
+       soc {
+               mmc1: sdhci@fe81f000 {
+                       status       = "okay";
+                       bus-width    = <8>;
+                       non-removable;
+               };
+
+               miphy365x_phy: phy@fe382000 {
+                       phy_port0: port@fe382000 {
+                               st,sata-gen = <3>;
+                       };
+
+                       phy_port1: port@fe38a000 {
+                               st,pcie-tx-pol-inv;
+                       };
+               };
+
+               sata0: sata@fe380000{
+                       status = "okay";
+               };
+       };
 };
index ba0fa2caaf1851be88c5c62f18d47f60bb652bc3..961799e1dc519e68ddd600645236010032c28420 100644 (file)
                        red {
                                #gpio-cells             = <1>;
                                label                   = "Front Panel LED";
-                               gpios                   = <&PIO4 1>;
+                               gpios                   = <&pio4 1>;
                                linux,default-trigger   = "heartbeat";
                        };
                        green {
-                               gpios                   = <&PIO1 3>;
+                               gpios                   = <&pio1 3>;
                                default-state           = "off";
                        };
                };
 
                ethernet1: dwmac@fef08000 {
-                       snps,reset-gpio = <&PIO0 7>;
+                       snps,reset-gpio = <&pio0 7>;
+               };
+
+               mmc1: sdhci@fe81f000 {
+                       status       = "okay";
+                       bus-width    = <8>;
+                       non-removable;
+               };
+
+               miphy365x_phy: phy@fe382000 {
+                       phy_port0: port@fe382000 {
+                               st,sata-gen = <3>;
+                       };
+
+                       phy_port1: port@fe38a000 {
+                               st,pcie-tx-pol-inv;
+                       };
+               };
+
+               sata0: sata@fe380000{
+                       status = "okay";
                };
        };
 };
index ee6c119e261e89e8a887b18a78fdfdff284c0975..9cccf2d6aa26f5c17e0bd83684e17bb4335acabf 100644 (file)
 / {
 
        aliases {
-               gpio0   = &PIO0;
-               gpio1   = &PIO1;
-               gpio2   = &PIO2;
-               gpio3   = &PIO3;
-               gpio4   = &PIO4;
-               gpio5   = &PIO40;
-               gpio6   = &PIO5;
-               gpio7   = &PIO6;
-               gpio8   = &PIO7;
-               gpio9   = &PIO8;
-               gpio10  = &PIO9;
-               gpio11  = &PIO10;
-               gpio12  = &PIO11;
-               gpio13  = &PIO12;
-               gpio14  = &PIO30;
-               gpio15  = &PIO31;
-               gpio16  = &PIO13;
-               gpio17  = &PIO14;
-               gpio18  = &PIO15;
-               gpio19  = &PIO16;
-               gpio20  = &PIO17;
-               gpio21  = &PIO18;
-               gpio22  = &PIO100;
-               gpio23  = &PIO101;
-               gpio24  = &PIO102;
-               gpio25  = &PIO103;
-               gpio26  = &PIO104;
-               gpio27  = &PIO105;
-               gpio28  = &PIO106;
-               gpio29  = &PIO107;
+               gpio0   = &pio0;
+               gpio1   = &pio1;
+               gpio2   = &pio2;
+               gpio3   = &pio3;
+               gpio4   = &pio4;
+               gpio5   = &pio40;
+               gpio6   = &pio5;
+               gpio7   = &pio6;
+               gpio8   = &pio7;
+               gpio9   = &pio8;
+               gpio10  = &pio9;
+               gpio11  = &pio10;
+               gpio12  = &pio11;
+               gpio13  = &pio12;
+               gpio14  = &pio30;
+               gpio15  = &pio31;
+               gpio16  = &pio13;
+               gpio17  = &pio14;
+               gpio18  = &pio15;
+               gpio19  = &pio16;
+               gpio20  = &pio17;
+               gpio21  = &pio18;
+               gpio22  = &pio100;
+               gpio23  = &pio101;
+               gpio24  = &pio102;
+               gpio25  = &pio103;
+               gpio26  = &pio104;
+               gpio27  = &pio105;
+               gpio28  = &pio106;
+               gpio29  = &pio107;
        };
 
        soc {
@@ -56,7 +56,7 @@
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfe610000 0x6000>;
 
-                       PIO0: gpio@fe610000 {
+                       pio0: gpio@fe610000 {
                                gpio-controller;
                                #gpio-cells = <1>;
                                interrupt-controller;
@@ -64,7 +64,7 @@
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO0";
                        };
-                       PIO1: gpio@fe611000 {
+                       pio1: gpio@fe611000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -72,7 +72,7 @@
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO1";
                        };
-                       PIO2: gpio@fe612000 {
+                       pio2: gpio@fe612000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -80,7 +80,7 @@
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO2";
                        };
-                       PIO3: gpio@fe613000 {
+                       pio3: gpio@fe613000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -88,7 +88,7 @@
                                reg             = <0x3000 0x100>;
                                st,bank-name    = "PIO3";
                        };
-                       PIO4: gpio@fe614000 {
+                       pio4: gpio@fe614000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
@@ -96,7 +96,7 @@
                                reg             = <0x4000 0x100>;
                                st,bank-name    = "PIO4";
                        };
-                       PIO40: gpio@fe615000 {
+                       pio40: gpio@fe615000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                        rc{
                                pinctrl_ir: ir0 {
                                        st,pins {
-                                               ir = <&PIO4 0 ALT2 IN>;
+                                               ir = <&pio4 0 ALT2 IN>;
                                        };
                                };
                        };
                        sbc_serial1 {
                                pinctrl_sbc_serial1: sbc_serial1 {
                                        st,pins {
-                                               tx      = <&PIO2 6 ALT3 OUT>;
-                                               rx      = <&PIO2 7 ALT3 IN>;
+                                               tx      = <&pio2 6 ALT3 OUT>;
+                                               rx      = <&pio2 7 ALT3 IN>;
                                        };
                                };
                        };
                        keyscan {
                                pinctrl_keyscan: keyscan {
                                        st,pins {
-                                               keyin0 = <&PIO0 2 ALT2 IN>;
-                                               keyin1 = <&PIO0 3 ALT2 IN>;
-                                               keyin2 = <&PIO0 4 ALT2 IN>;
-                                               keyin3 = <&PIO2 6 ALT2 IN>;
-
-                                               keyout0 = <&PIO1 6 ALT2 OUT>;
-                                               keyout1 = <&PIO1 7 ALT2 OUT>;
-                                               keyout2 = <&PIO0 6 ALT2 OUT>;
-                                               keyout3 = <&PIO2 7 ALT2 OUT>;
+                                               keyin0 = <&pio0 2 ALT2 IN>;
+                                               keyin1 = <&pio0 3 ALT2 IN>;
+                                               keyin2 = <&pio0 4 ALT2 IN>;
+                                               keyin3 = <&pio2 6 ALT2 IN>;
+
+                                               keyout0 = <&pio1 6 ALT2 OUT>;
+                                               keyout1 = <&pio1 7 ALT2 OUT>;
+                                               keyout2 = <&pio0 6 ALT2 OUT>;
+                                               keyout3 = <&pio2 7 ALT2 OUT>;
                                        };
                                };
                        };
                        sbc_i2c0 {
                                pinctrl_sbc_i2c0_default: sbc_i2c0-default {
                                        st,pins {
-                                               sda = <&PIO4 6 ALT1 BIDIR>;
-                                               scl = <&PIO4 5 ALT1 BIDIR>;
+                                               sda = <&pio4 6 ALT1 BIDIR>;
+                                               scl = <&pio4 5 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
+
+                       usb {
+                               pinctrl_usb3: usb3 {
+                                       st,pins {
+                                               oc-detect = <&pio40 0 ALT1 IN>;
+                                               pwr-enable = <&pio40 1 ALT1 OUT>;
                                        };
                                };
                        };
                        sbc_i2c1 {
                                pinctrl_sbc_i2c1_default: sbc_i2c1-default {
                                        st,pins {
-                                               sda = <&PIO3 2 ALT2 BIDIR>;
-                                               scl = <&PIO3 1 ALT2 BIDIR>;
+                                               sda = <&pio3 2 ALT2 BIDIR>;
+                                               scl = <&pio3 1 ALT2 BIDIR>;
                                        };
                                };
                        };
                        gmac1 {
                                pinctrl_mii1: mii1 {
                                        st,pins {
-                                               txd0 = <&PIO0 0 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txd1 = <&PIO0 1 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txd2 = <&PIO0 2 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txd3 = <&PIO0 3 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txer = <&PIO0 4 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txen = <&PIO0 5 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txclk = <&PIO0 6 ALT1 IN NICLK 0 CLK_A>;
-                                               col =   <&PIO0 7 ALT1 IN BYPASS 1000>;
-
-                                               mdio =  <&PIO1 0 ALT1 OUT BYPASS 1500>;
-                                               mdc =   <&PIO1 1 ALT1 OUT NICLK 0 CLK_A>;
-                                               crs =   <&PIO1 2 ALT1 IN BYPASS 1000>;
-                                               mdint = <&PIO1 3 ALT1 IN BYPASS 0>;
-                                               rxd0 =  <&PIO1 4 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxd1 =  <&PIO1 5 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxd2 =  <&PIO1 6 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxd3 =  <&PIO1 7 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-
-                                               rxdv =  <&PIO2 0 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-                                               rx_er = <&PIO2 1 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxclk = <&PIO2 2 ALT1 IN NICLK 0 CLK_A>;
-                                               phyclk = <&PIO2 3 ALT1 OUT NICLK 0 CLK_A>;
+                                               txd0 = <&pio0 0 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txd1 = <&pio0 1 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txd2 = <&pio0 2 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txd3 = <&pio0 3 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txer = <&pio0 4 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txen = <&pio0 5 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txclk = <&pio0 6 ALT1 IN NICLK 0 CLK_A>;
+                                               col =   <&pio0 7 ALT1 IN BYPASS 1000>;
+
+                                               mdio =  <&pio1 0 ALT1 OUT BYPASS 1500>;
+                                               mdc =   <&pio1 1 ALT1 OUT NICLK 0 CLK_A>;
+                                               crs =   <&pio1 2 ALT1 IN BYPASS 1000>;
+                                               mdint = <&pio1 3 ALT1 IN BYPASS 0>;
+                                               rxd0 =  <&pio1 4 ALT1 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxd1 =  <&pio1 5 ALT1 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxd2 =  <&pio1 6 ALT1 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxd3 =  <&pio1 7 ALT1 IN SE_NICLK_IO 0 CLK_A>;
+
+                                               rxdv =  <&pio2 0 ALT1 IN SE_NICLK_IO 0 CLK_A>;
+                                               rx_er = <&pio2 1 ALT1 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxclk = <&pio2 2 ALT1 IN NICLK 0 CLK_A>;
+                                               phyclk = <&pio2 3 ALT1 OUT NICLK 0 CLK_A>;
                                        };
                                };
                                pinctrl_rgmii1: rgmii1-0 {
                                        st,pins {
-                                               txd0 =  <&PIO0 0 ALT1 OUT DE_IO 500 CLK_A>;
-                                               txd1 =  <&PIO0 1 ALT1 OUT DE_IO 500 CLK_A>;
-                                               txd2 =  <&PIO0 2 ALT1 OUT DE_IO 500 CLK_A>;
-                                               txd3 =  <&PIO0 3 ALT1 OUT DE_IO 500 CLK_A>;
-                                               txen =  <&PIO0 5 ALT1 OUT DE_IO 0   CLK_A>;
-                                               txclk = <&PIO0 6 ALT1 IN  NICLK 0   CLK_A>;
-
-                                               mdio = <&PIO1 0 ALT1 OUT BYPASS 0>;
-                                               mdc  = <&PIO1 1 ALT1 OUT NICLK  0 CLK_A>;
-                                               rxd0 = <&PIO1 4 ALT1 IN DE_IO 500 CLK_A>;
-                                               rxd1 = <&PIO1 5 ALT1 IN DE_IO 500 CLK_A>;
-                                               rxd2 = <&PIO1 6 ALT1 IN DE_IO 500 CLK_A>;
-                                               rxd3 = <&PIO1 7 ALT1 IN DE_IO 500 CLK_A>;
-
-                                               rxdv   = <&PIO2 0 ALT1 IN  DE_IO 500 CLK_A>;
-                                               rxclk  = <&PIO2 2 ALT1 IN  NICLK 0   CLK_A>;
-                                               phyclk = <&PIO2 3 ALT4 OUT NICLK 0   CLK_B>;
-
-                                               clk125= <&PIO3 7 ALT4 IN NICLK 0 CLK_A>;
+                                               txd0 =  <&pio0 0 ALT1 OUT DE_IO 500 CLK_A>;
+                                               txd1 =  <&pio0 1 ALT1 OUT DE_IO 500 CLK_A>;
+                                               txd2 =  <&pio0 2 ALT1 OUT DE_IO 500 CLK_A>;
+                                               txd3 =  <&pio0 3 ALT1 OUT DE_IO 500 CLK_A>;
+                                               txen =  <&pio0 5 ALT1 OUT DE_IO 0   CLK_A>;
+                                               txclk = <&pio0 6 ALT1 IN  NICLK 0   CLK_A>;
+
+                                               mdio = <&pio1 0 ALT1 OUT BYPASS 0>;
+                                               mdc  = <&pio1 1 ALT1 OUT NICLK  0 CLK_A>;
+                                               rxd0 = <&pio1 4 ALT1 IN DE_IO 500 CLK_A>;
+                                               rxd1 = <&pio1 5 ALT1 IN DE_IO 500 CLK_A>;
+                                               rxd2 = <&pio1 6 ALT1 IN DE_IO 500 CLK_A>;
+                                               rxd3 = <&pio1 7 ALT1 IN DE_IO 500 CLK_A>;
+
+                                               rxdv   = <&pio2 0 ALT1 IN  DE_IO 500 CLK_A>;
+                                               rxclk  = <&pio2 2 ALT1 IN  NICLK 0   CLK_A>;
+                                               phyclk = <&pio2 3 ALT4 OUT NICLK 0   CLK_B>;
+
+                                               clk125= <&pio3 7 ALT4 IN NICLK 0 CLK_A>;
                                        };
                                };
                        };
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfee00000 0x10000>;
 
-                       PIO5: gpio@fee00000 {
+                       pio5: gpio@fee00000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO5";
                        };
-                       PIO6: gpio@fee01000 {
+                       pio6: gpio@fee01000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO6";
                        };
-                       PIO7: gpio@fee02000 {
+                       pio7: gpio@fee02000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO7";
                        };
-                       PIO8: gpio@fee03000 {
+                       pio8: gpio@fee03000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x3000 0x100>;
                                st,bank-name    = "PIO8";
                        };
-                       PIO9: gpio@fee04000 {
+                       pio9: gpio@fee04000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x4000 0x100>;
                                st,bank-name    = "PIO9";
                        };
-                       PIO10: gpio@fee05000 {
+                       pio10: gpio@fee05000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x5000 0x100>;
                                st,bank-name    = "PIO10";
                        };
-                       PIO11: gpio@fee06000 {
+                       pio11: gpio@fee06000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x6000 0x100>;
                                st,bank-name    = "PIO11";
                        };
-                       PIO12: gpio@fee07000 {
+                       pio12: gpio@fee07000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x7000 0x100>;
                                st,bank-name    = "PIO12";
                        };
-                       PIO30: gpio@fee08000 {
+                       pio30: gpio@fee08000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x8000 0x100>;
                                st,bank-name    = "PIO30";
                        };
-                       PIO31: gpio@fee09000 {
+                       pio31: gpio@fee09000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                        serial2-oe {
                                pinctrl_serial2_oe: serial2-1 {
                                        st,pins {
-                                               output-enable   = <&PIO11 3 ALT2 OUT>;
+                                               output-enable   = <&pio11 3 ALT2 OUT>;
                                        };
                                };
                        };
                        i2c0 {
                                pinctrl_i2c0_default: i2c0-default {
                                        st,pins {
-                                               sda = <&PIO9 3 ALT1 BIDIR>;
-                                               scl = <&PIO9 2 ALT1 BIDIR>;
+                                               sda = <&pio9 3 ALT1 BIDIR>;
+                                               scl = <&pio9 2 ALT1 BIDIR>;
+                                       };
+                               };
+                       };
+
+                       usb {
+                               pinctrl_usb0: usb0 {
+                                       st,pins {
+                                               oc-detect = <&pio9 4 ALT1 IN>;
+                                               pwr-enable = <&pio9 5 ALT1 OUT>;
                                        };
                                };
                        };
 
+
                        i2c1 {
                                pinctrl_i2c1_default: i2c1-default {
                                        st,pins {
-                                               sda = <&PIO12 1 ALT1 BIDIR>;
-                                               scl = <&PIO12 0 ALT1 BIDIR>;
+                                               sda = <&pio12 1 ALT1 BIDIR>;
+                                               scl = <&pio12 0 ALT1 BIDIR>;
                                        };
                                };
                        };
                        fsm {
                                pinctrl_fsm: fsm {
                                        st,pins {
-                                               spi-fsm-clk  = <&PIO12 2 ALT1 OUT>;
-                                               spi-fsm-cs   = <&PIO12 3 ALT1 OUT>;
-                                               spi-fsm-mosi = <&PIO12 4 ALT1 OUT>;
-                                               spi-fsm-miso = <&PIO12 5 ALT1 IN>;
-                                               spi-fsm-hol  = <&PIO12 6 ALT1 OUT>;
-                                               spi-fsm-wp   = <&PIO12 7 ALT1 OUT>;
+                                               spi-fsm-clk  = <&pio12 2 ALT1 OUT>;
+                                               spi-fsm-cs   = <&pio12 3 ALT1 OUT>;
+                                               spi-fsm-mosi = <&pio12 4 ALT1 OUT>;
+                                               spi-fsm-miso = <&pio12 5 ALT1 IN>;
+                                               spi-fsm-hol  = <&pio12 6 ALT1 OUT>;
+                                               spi-fsm-wp   = <&pio12 7 ALT1 OUT>;
                                        };
                                };
                        };
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfe820000 0x6000>;
 
-                       PIO13: gpio@fe820000 {
+                       pio13: gpio@fe820000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO13";
                        };
-                       PIO14: gpio@fe821000 {
+                       pio14: gpio@fe821000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO14";
                        };
-                       PIO15: gpio@fe822000 {
+                       pio15: gpio@fe822000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO15";
                        };
-                       PIO16: gpio@fe823000 {
+                       pio16: gpio@fe823000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x3000 0x100>;
                                st,bank-name    = "PIO16";
                        };
-                       PIO17: gpio@fe824000 {
+                       pio17: gpio@fe824000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x4000 0x100>;
                                st,bank-name    = "PIO17";
                        };
-                       PIO18: gpio@fe825000 {
+                       pio18: gpio@fe825000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                        serial2 {
                                pinctrl_serial2: serial2-0 {
                                        st,pins {
-                                               tx      = <&PIO17 4 ALT2 OUT>;
-                                               rx      = <&PIO17 5 ALT2 IN>;
+                                               tx      = <&pio17 4 ALT2 OUT>;
+                                               rx      = <&pio17 5 ALT2 IN>;
                                        };
                                };
                        };
                        gmac0 {
                                pinctrl_mii0: mii0 {
                                        st,pins {
-                                               mdint = <&PIO13 6 ALT2 IN  BYPASS      0>;
-                                               txen =  <&PIO13 7 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txd0 =  <&PIO14 0 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txd1 =  <&PIO14 1 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-                                               txd2 =  <&PIO14 2 ALT2 OUT SE_NICLK_IO 0 CLK_B>;
-                                               txd3 =  <&PIO14 3 ALT2 OUT SE_NICLK_IO 0 CLK_B>;
-
-                                               txclk = <&PIO15 0 ALT2 IN  NICLK       0 CLK_A>;
-                                               txer =  <&PIO15 1 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-                                               crs = <&PIO15 2 ALT2 IN  BYPASS 1000>;
-                                               col = <&PIO15 3 ALT2 IN  BYPASS 1000>;
-                                               mdio= <&PIO15 4 ALT2 OUT BYPASS 1500>;
-                                               mdc = <&PIO15 5 ALT2 OUT NICLK  0    CLK_B>;
-
-                                               rxd0 =  <&PIO16 0 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxd1 =  <&PIO16 1 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxd2 =  <&PIO16 2 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxd3 =  <&PIO16 3 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxdv =  <&PIO15 6 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-                                               rx_er = <&PIO15 7 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-                                               rxclk = <&PIO17 0 ALT2 IN NICLK 0 CLK_A>;
-                                               phyclk = <&PIO13 5 ALT2 OUT NICLK 0 CLK_B>;
+                                               mdint = <&pio13 6 ALT2 IN  BYPASS      0>;
+                                               txen =  <&pio13 7 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txd0 =  <&pio14 0 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txd1 =  <&pio14 1 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
+                                               txd2 =  <&pio14 2 ALT2 OUT SE_NICLK_IO 0 CLK_B>;
+                                               txd3 =  <&pio14 3 ALT2 OUT SE_NICLK_IO 0 CLK_B>;
+
+                                               txclk = <&pio15 0 ALT2 IN  NICLK       0 CLK_A>;
+                                               txer =  <&pio15 1 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
+                                               crs = <&pio15 2 ALT2 IN  BYPASS 1000>;
+                                               col = <&pio15 3 ALT2 IN  BYPASS 1000>;
+                                               mdio= <&pio15 4 ALT2 OUT BYPASS 1500>;
+                                               mdc = <&pio15 5 ALT2 OUT NICLK  0    CLK_B>;
+
+                                               rxd0 =  <&pio16 0 ALT2 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxd1 =  <&pio16 1 ALT2 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxd2 =  <&pio16 2 ALT2 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxd3 =  <&pio16 3 ALT2 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxdv =  <&pio15 6 ALT2 IN SE_NICLK_IO 0 CLK_A>;
+                                               rx_er = <&pio15 7 ALT2 IN SE_NICLK_IO 0 CLK_A>;
+                                               rxclk = <&pio17 0 ALT2 IN NICLK 0 CLK_A>;
+                                               phyclk = <&pio13 5 ALT2 OUT NICLK 0 CLK_B>;
                                        };
                                };
 
                                };
                                pinctrl_rgmii0: rgmii0 {
                                        st,pins {
-                                                phyclk = <&PIO13  5 ALT4 OUT NICLK 0 CLK_B>;
-                                                txen = <&PIO13 7 ALT2 OUT DE_IO 0 CLK_A>;
-                                                txd0  = <&PIO14 0 ALT2 OUT DE_IO 500 CLK_A>;
-                                                txd1  = <&PIO14 1 ALT2 OUT DE_IO 500 CLK_A>;
-                                                txd2  = <&PIO14 2 ALT2 OUT DE_IO 500 CLK_B>;
-                                                txd3  = <&PIO14 3 ALT2 OUT DE_IO 500 CLK_B>;
-                                                txclk = <&PIO15 0 ALT2 IN NICLK 0 CLK_A>;
-
-                                                mdio = <&PIO15 4 ALT2 OUT BYPASS 0>;
-                                                mdc = <&PIO15 5 ALT2 OUT NICLK 0 CLK_B>;
-
-                                                rxdv = <&PIO15 6 ALT2 IN DE_IO 500 CLK_A>;
-                                                rxd0 =<&PIO16 0 ALT2 IN DE_IO  500 CLK_A>;
-                                                rxd1 =<&PIO16 1 ALT2 IN DE_IO  500 CLK_A>;
-                                                rxd2 =<&PIO16 2 ALT2 IN DE_IO  500 CLK_A>;
-                                                rxd3  =<&PIO16 3 ALT2 IN DE_IO 500 CLK_A>;
-                                                rxclk =<&PIO17 0 ALT2 IN NICLK 0 CLK_A>;
-
-                                                clk125=<&PIO17 6 ALT1 IN NICLK 0 CLK_A>;
+                                                phyclk = <&pio13  5 ALT4 OUT NICLK 0 CLK_B>;
+                                                txen = <&pio13 7 ALT2 OUT DE_IO 0 CLK_A>;
+                                                txd0  = <&pio14 0 ALT2 OUT DE_IO 500 CLK_A>;
+                                                txd1  = <&pio14 1 ALT2 OUT DE_IO 500 CLK_A>;
+                                                txd2  = <&pio14 2 ALT2 OUT DE_IO 500 CLK_B>;
+                                                txd3  = <&pio14 3 ALT2 OUT DE_IO 500 CLK_B>;
+                                                txclk = <&pio15 0 ALT2 IN NICLK 0 CLK_A>;
+
+                                                mdio = <&pio15 4 ALT2 OUT BYPASS 0>;
+                                                mdc = <&pio15 5 ALT2 OUT NICLK 0 CLK_B>;
+
+                                                rxdv = <&pio15 6 ALT2 IN DE_IO 500 CLK_A>;
+                                                rxd0 =<&pio16 0 ALT2 IN DE_IO  500 CLK_A>;
+                                                rxd1 =<&pio16 1 ALT2 IN DE_IO  500 CLK_A>;
+                                                rxd2 =<&pio16 2 ALT2 IN DE_IO  500 CLK_A>;
+                                                rxd3  =<&pio16 3 ALT2 IN DE_IO 500 CLK_A>;
+                                                rxclk =<&pio17 0 ALT2 IN NICLK 0 CLK_A>;
+
+                                                clk125=<&pio17 6 ALT1 IN NICLK 0 CLK_A>;
+                                       };
+                               };
+                       };
+
+                       mmc0 {
+                               pinctrl_mmc0: mmc0 {
+                                       st,pins {
+                                               mmcclk  = <&pio13 4 ALT4 BIDIR_PU NICLK 0 CLK_B>;
+                                               data0   = <&pio14 4 ALT4 BIDIR_PU BYPASS 0>;
+                                               data1   = <&pio14 5 ALT4 BIDIR_PU BYPASS 0>;
+                                               data2   = <&pio14 6 ALT4 BIDIR_PU BYPASS 0>;
+                                               data3   = <&pio14 7 ALT4 BIDIR_PU BYPASS 0>;
+                                               cmd     = <&pio15 1 ALT4 BIDIR_PU BYPASS 0>;
+                                               wp      = <&pio15 3 ALT4 IN>;
+                                               data4   = <&pio16 4 ALT4 BIDIR_PU BYPASS 0>;
+                                               data5   = <&pio16 5 ALT4 BIDIR_PU BYPASS 0>;
+                                               data6   = <&pio16 6 ALT4 BIDIR_PU BYPASS 0>;
+                                               data7   = <&pio16 7 ALT4 BIDIR_PU BYPASS 0>;
+                                               pwr     = <&pio17 1 ALT4 OUT>;
+                                               cd      = <&pio17 2 ALT4 IN>;
+                                               led     = <&pio17 3 ALT4 OUT>;
+                                       };
+                               };
+                       };
+                       mmc1 {
+                               pinctrl_mmc1: mmc1 {
+                                       st,pins {
+                                               mmcclk  = <&pio15 0 ALT3 BIDIR_PU NICLK 0 CLK_B>;
+                                               data0   = <&pio13 7 ALT3 BIDIR_PU BYPASS 0>;
+                                               data1   = <&pio14 1 ALT3 BIDIR_PU BYPASS 0>;
+                                               data2   = <&pio14 2 ALT3 BIDIR_PU BYPASS 0>;
+                                               data3   = <&pio14 3 ALT3 BIDIR_PU BYPASS 0>;
+                                               cmd     = <&pio15 4 ALT3 BIDIR_PU BYPASS 0>;
+                                               data4   = <&pio15 6 ALT3 BIDIR_PU BYPASS 0>;
+                                               data5   = <&pio15 7 ALT3 BIDIR_PU BYPASS 0>;
+                                               data6   = <&pio16 0 ALT3 BIDIR_PU BYPASS 0>;
+                                               data7   = <&pio16 1 ALT3 BIDIR_PU BYPASS 0>;
+                                               pwr     = <&pio16 2 ALT3 OUT>;
+                                               nreset  = <&pio13 6 ALT3 OUT>;
+                                       };
+                               };
+                       };
+
+                       usb {
+                               pinctrl_usb1: usb1 {
+                                       st,pins {
+                                               oc-detect = <&pio18 0 ALT1 IN>;
+                                               pwr-enable = <&pio18 1 ALT1 OUT>;
+                                       };
+                               };
+                               pinctrl_usb2: usb2 {
+                                       st,pins {
+                                               oc-detect = <&pio18 2 ALT1 IN>;
+                                               pwr-enable = <&pio18 3 ALT1 OUT>;
                                        };
                                };
                        };
                        interrupt-names = "irqmux";
                        ranges          = <0 0xfd6b0000 0x3000>;
 
-                       PIO100: gpio@fd6b0000 {
+                       pio100: gpio@fd6b0000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO100";
                        };
-                       PIO101: gpio@fd6b1000 {
+                       pio101: gpio@fd6b1000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO101";
                        };
-                       PIO102: gpio@fd6b2000 {
+                       pio102: gpio@fd6b2000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                        interrupt-names = "irqmux";
                        ranges                  = <0 0xfd330000 0x5000>;
 
-                       PIO103: gpio@fd330000 {
+                       pio103: gpio@fd330000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0 0x100>;
                                st,bank-name    = "PIO103";
                        };
-                       PIO104: gpio@fd331000 {
+                       pio104: gpio@fd331000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x1000 0x100>;
                                st,bank-name    = "PIO104";
                        };
-                       PIO105: gpio@fd332000 {
+                       pio105: gpio@fd332000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                reg             = <0x2000 0x100>;
                                st,bank-name    = "PIO105";
                        };
-                       PIO106: gpio@fd333000 {
+                       pio106: gpio@fd333000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
                                st,bank-name    = "PIO106";
                        };
 
-                       PIO107: gpio@fd334000 {
+                       pio107: gpio@fd334000 {
                                gpio-controller;
                                #gpio-cells     = <1>;
                                interrupt-controller;
index 84758d76d064f5bc790cc0b08629e48bd8fec7ea..fad9073ddeed1a3e4193f30140bb8c30773fd955 100644 (file)
@@ -9,6 +9,8 @@
 #include "stih41x.dtsi"
 #include "stih416-clock.dtsi"
 #include "stih416-pinctrl.dtsi"
+
+#include <dt-bindings/phy/phy-miphy365x.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset-controller/stih416-resets.h>
 / {
                        resets  = <&powerdown STIH416_KEYSCAN_POWERDOWN>,
                                  <&softreset STIH416_KEYSCAN_SOFTRESET>;
                };
+
+               temp0 {
+                       compatible = "st,stih416-sas-thermal";
+                       clock-names = "thermal";
+                       clocks = <&clockgen_c_vcc 14>;
+
+                       status = "okay";
+               };
+
+               temp1@fdfe8000 {
+                       compatible = "st,stih416-mpe-thermal";
+                       reg = <0xfdfe8000 0x10>;
+                       clocks = <&clockgen_e 3>;
+                       clock-names = "thermal";
+                       interrupts = <GIC_SPI 23 IRQ_TYPE_EDGE_RISING>;
+
+                       status = "okay";
+               };
+
+               mmc0: sdhci@fe81e000 {
+                       compatible      = "st,sdhci";
+                       status          = "disabled";
+                       reg             = <0xfe81e000 0x1000>;
+                       interrupts      = <GIC_SPI 127 IRQ_TYPE_NONE>;
+                       interrupt-names = "mmcirq";
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_mmc0>;
+                       clock-names     = "mmc";
+                       clocks          = <&clk_s_a1_ls 1>;
+               };
+
+               mmc1: sdhci@fe81f000 {
+                       compatible      = "st,sdhci";
+                       status          = "disabled";
+                       reg             = <0xfe81f000 0x1000>;
+                       interrupts      = <GIC_SPI 128 IRQ_TYPE_NONE>;
+                       interrupt-names = "mmcirq";
+                       pinctrl-names   = "default";
+                       pinctrl-0       = <&pinctrl_mmc1>;
+                       clock-names     = "mmc";
+                       clocks          = <&clk_s_a1_ls 8>;
+               };
+
+               miphy365x_phy: phy@fe382000 {
+                       compatible      = "st,miphy365x-phy";
+                       st,syscfg       = <&syscfg_rear>;
+                       #address-cells  = <1>;
+                       #size-cells     = <1>;
+                       ranges;
+
+                       phy_port0: port@fe382000 {
+                               #phy-cells = <1>;
+                               reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>;
+                               reg-names = "sata", "pcie", "syscfg";
+                       };
+
+                       phy_port1: port@fe38a000 {
+                               #phy-cells = <1>;
+                               reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>;
+                               reg-names = "sata", "pcie", "syscfg";
+                       };
+               };
+
+               sata0: sata@fe380000 {
+                       compatible      = "st,sti-ahci";
+                       reg             = <0xfe380000 0x1000>;
+                       interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
+                       interrupt-names = "hostc";
+                       phys            = <&phy_port0 MIPHY_TYPE_SATA>;
+                       phy-names       = "sata-phy";
+                       resets          = <&powerdown STIH416_SATA0_POWERDOWN>,
+                                         <&softreset STIH416_SATA0_SOFTRESET>;
+                       reset-names     = "pwr-dwn", "sw-rst";
+                       clock-names     = "ahci_clk";
+                       clocks          = <&clk_s_a0_ls CLK_ICN_REG>;
+
+                       status          = "disabled";
+               };
+
+               usb2_phy: phy@0 {
+                       compatible = "st,stih416-usb-phy";
+                       #phy-cells = <0>;
+                       st,syscfg = <&syscfg_rear>;
+                       clocks = <&clk_sysin>;
+                       clock-names = "osc_phy";
+               };
+
+               ehci0: usb@fe1ffe00 {
+                       compatible = "st,st-ehci-300x";
+                       reg = <0xfe1ffe00 0x100>;
+                       interrupts = <GIC_SPI 148 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb0>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       resets = <&powerdown STIH416_USB0_POWERDOWN>,
+                                <&softreset STIH416_USB0_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
+
+               ohci0: usb@fe1ffc00 {
+                       compatible = "st,st-ohci-300x";
+                       reg = <0xfe1ffc00 0x100>;
+                       interrupts = <GIC_SPI 149 IRQ_TYPE_NONE>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       status = "okay";
+                       resets = <&powerdown STIH416_USB0_POWERDOWN>,
+                                <&softreset STIH416_USB0_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
+
+               ehci1: usb@fe203e00 {
+                       compatible = "st,st-ehci-300x";
+                       reg = <0xfe203e00 0x100>;
+                       interrupts = <GIC_SPI 150 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb1>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       resets = <&powerdown STIH416_USB1_POWERDOWN>,
+                                <&softreset STIH416_USB1_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
+
+               ohci1: usb@fe203c00 {
+                       compatible = "st,st-ohci-300x";
+                       reg = <0xfe203c00 0x100>;
+                       interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       resets = <&powerdown STIH416_USB1_POWERDOWN>,
+                                <&softreset STIH416_USB1_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
+
+               ehci2: usb@fe303e00 {
+                       compatible = "st,st-ehci-300x";
+                       reg = <0xfe303e00 0x100>;
+                       interrupts = <GIC_SPI 152 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       resets = <&powerdown STIH416_USB2_POWERDOWN>,
+                                <&softreset STIH416_USB2_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
+
+               ohci2: usb@fe303c00 {
+                       compatible = "st,st-ohci-300x";
+                       reg = <0xfe303c00 0x100>;
+                       interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       resets = <&powerdown STIH416_USB2_POWERDOWN>,
+                                <&softreset STIH416_USB2_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
+
+               ehci3: usb@fe343e00 {
+                       compatible = "st,st-ehci-300x";
+                       reg = <0xfe343e00 0x100>;
+                       interrupts = <GIC_SPI 154 IRQ_TYPE_NONE>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb3>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       resets = <&powerdown STIH416_USB3_POWERDOWN>,
+                                <&softreset STIH416_USB3_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
+
+               ohci3: usb@fe343c00 {
+                       compatible = "st,st-ohci-300x";
+                       reg = <0xfe343c00 0x100>;
+                       interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>;
+                       clocks = <&clk_s_a1_ls 0>,
+                                <&clockgen_b0 0>;
+                       clock-names = "ic", "clk48";
+                       phys = <&usb2_phy>;
+                       phy-names = "usb";
+                       resets = <&powerdown STIH416_USB3_POWERDOWN>,
+                                <&softreset STIH416_USB3_SOFTRESET>;
+                       reset-names = "power", "softreset";
+               };
        };
 };
index b3dd6ca5c2ae0bff23f33fd3fbc0e3d8c11c6c28..5f91f455f05b7084927f0c05da530e1271de59c7 100644 (file)
@@ -35,7 +35,7 @@
                        fp_led {
                                #gpio-cells = <1>;
                                label   = "Front Panel LED";
-                               gpios   = <&PIO105 7>;
+                               gpios   = <&pio105 7>;
                                linux,default-trigger   = "heartbeat";
                        };
                };
@@ -55,7 +55,7 @@
                        phy-mode                = "mii";
                        pinctrl-0               = <&pinctrl_mii0>;
 
-                       snps,reset-gpio         = <&PIO106 2>;
+                       snps,reset-gpio         = <&pio106 2>;
                        snps,reset-active-low;
                        snps,reset-delays-us    = <0 10000 10000>;
                };
@@ -65,7 +65,7 @@
                        phy-mode                = "mii";
                        st,tx-retime-src        = "txclk";
 
-                       snps,reset-gpio         = <&PIO4 7>;
+                       snps,reset-gpio         = <&pio4 7>;
                        snps,reset-active-low;
                        snps,reset-delays-us    = <0 10000 10000>;
                };
index d8a84295c328bf778d35ad064c55a63f21ed96c4..487d7d87dbefb1127a1de540c5a839145e0325ad 100644 (file)
                        red {
                                #gpio-cells = <1>;
                                label   = "Front Panel LED";
-                               gpios   = <&PIO4 1>;
+                               gpios   = <&pio4 1>;
                                linux,default-trigger   = "heartbeat";
                        };
                        green {
-                               gpios   = <&PIO4 7>;
+                               gpios   = <&pio4 7>;
                                default-state = "off";
                        };
                };
                        phy-mode                = "rgmii-id";
                        max-speed               = <1000>;
                        st,tx-retime-src        = "clk_125";
-                       snps,reset-gpio         = <&PIO3 0>;
+                       snps,reset-gpio         = <&pio3 0>;
                        snps,reset-active-low;
                        snps,reset-delays-us    = <0 10000 10000>;
 
                        pinctrl-0       = <&pinctrl_rgmii1>;
                };
+
+               mmc0: sdhci@fe81e000 {
+                       bus-width = <8>;
+               };
        };
 };
index df01c1211b329fc0d271de5498316b74f56f9bce..f797a0607382f35ce1b0cb9b60debeb6ee586446 100644 (file)
@@ -8,6 +8,10 @@
  */
 / {
        soc {
+               mmc0: sdhci@fe81e000 {
+                       status = "okay";
+               };
+
                spifsm: spifsm@fe902000 {
                        #address-cells = <1>;
                        #size-cells    = <1>;
diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi
new file mode 100644 (file)
index 0000000..0074bd4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited.
+ * Author: Giuseppe Cavallaro <peppe.cavallaro@st.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.
+ */
+/ {
+       soc {
+               sbc_serial0: serial@9530000 {
+                       status = "okay";
+               };
+
+               leds {
+                       compatible = "gpio-leds";
+                       red {
+                               #gpio-cells = <2>;
+                               label = "Front Panel LED";
+                               gpios = <&pio4 1 0>;
+                               linux,default-trigger = "heartbeat";
+                       };
+                       green {
+                               #gpio-cells = <2>;
+                               gpios = <&pio1 3 0>;
+                               default-state = "off";
+                       };
+               };
+
+               i2c@9842000 {
+                       status = "okay";
+               };
+
+               i2c@9843000 {
+                       status = "okay";
+               };
+
+               i2c@9844000 {
+                       status = "okay";
+               };
+
+               i2c@9845000 {
+                       status = "okay";
+               };
+
+               i2c@9540000 {
+                       status = "okay";
+               };
+
+               /* SSC11 to HDMI */
+               i2c@9541000 {
+                       status = "okay";
+                       /* HDMI V1.3a supports Standard mode only */
+                       clock-frequency = <100000>;
+                       st,i2c-min-scl-pulse-width-us = <0>;
+                       st,i2c-min-sda-pulse-width-us = <5>;
+               };
+       };
+};
index 9e99ade35e37b3e2117bd1b3fd9ef304875cdfc2..3bcfd81837f048c2d329cee59d08733998f99f8b 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Emilio López <emilio@elopez.com.ar>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 1763cc7ec02385297e6d93f93f2f5f448da25ed1..f3f2974658e4f12689b6515e20419af502075e78 100644 (file)
@@ -1,12 +1,48 @@
 /*
  * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 3ce56bfbc0b5f6ee46b685112648b5c9af7c8fbf..6a310da53f185bb961b30b4977d7cf17d1f9f634 100644 (file)
@@ -2,12 +2,48 @@
  * Copyright 2012 Stefan Roese
  * Stefan Roese <sr@denx.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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 891ea446abae9480f189b2d95fb31608ca5aa3f9..efc116287e0fd69154626b846b533373ffd4c08f 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 6b0c37812ade80ef457fe38b56d114be02659c28..3e25ee4d324863824eea0a192834c1e65a424ebb 100644 (file)
@@ -3,12 +3,48 @@
  *
  * David Lanzendörfer <david.lanzendoerfer@o2s.ch>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index b9ecce60f2e7e68d77621ec9a99a4b2ddbedd07a..8b3f974702492ce40c6a1ee8b16db8b8b243dafe 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index d046d568f5a1f1f55b93a387e205838e9499aee2..88cf1a531155b6354103ee0b6b1cc58775e8b5cf 100644 (file)
@@ -1,12 +1,48 @@
 /*
  * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 6675bcd7860e8eea367ca0fd9975e3ff2aea95b9..ce5994597407aaff1a5329658fa525f38698dac3 100644 (file)
@@ -2,12 +2,48 @@
  * Copyright 2014 Zoltan HERPAI
  * Zoltan HERPAI <wigyori@uid0.hu>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 380f914b226d527e0052df449a7f2fc33cb0c16c..e3ab942fd1488c974824dc05445ad970158dbc5b 100644 (file)
                serial7 = &uart7;
        };
 
+       chosen {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               framebuffer@0 {
+                       compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
+                       allwinner,pipeline = "de_be0-lcd0-hdmi";
+                       clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
+                                <&ahb_gates 44>;
+                       status = "disabled";
+               };
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
index ea9519da57643ffbbc2539fe5396c1f24dceace9..fe3c559ca6a8e6d24412abe6d2a81c2a6b97bdda 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 43a93762d4f290075d3f506e4822adb1b79e13cc..1fa2916eafc2752c69436e69eb2c965662719379 100644 (file)
@@ -1,12 +1,48 @@
 /*
  * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 531272c0e526aec013c22ec6a7d6a3a044f88467..81ad4b94e812c7f16e1e885cfff7181249d5f61a 100644 (file)
                serial3 = &uart3;
        };
 
+       chosen {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               framebuffer@0 {
+                       compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
+                       allwinner,pipeline = "de_be0-lcd0-hdmi";
+                       clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
+                                <&ahb_gates 44>;
+                       status = "disabled";
+               };
+       };
+
        cpus {
                cpu@0 {
                        compatible = "arm,cortex-a8";
index 8b3cd0907b3249775977dc5b760beb5c93227551..eeed1f236ee8c400465cbe87824516462dc6ec63 100644 (file)
@@ -6,18 +6,18 @@
  * 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
+ *  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 library is distributed in the hope that it will be useful,
+ *     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 library; if not, write to the Free
+ *     License along with this file; if not, write to the Free
  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  *     MA 02110-1301 USA
  *
index fa44b026483b34c59197bb8d1d2594c068b81448..916ee8bb826f7186380ecaf967d55488f84db6aa 100644 (file)
@@ -1,15 +1,49 @@
 /*
- * Copyright 2012 Maxime Ripard
+ * Copyright 2012 Maxime Ripard <maxime.ripard@free-electrons.com>
  * Copyright 2013 Hans de Goede <hdegoede@redhat.com>
  *
- * Maxime Ripard <maxime.ripard@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.
  *
- * 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:
+ *  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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *     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/;
index 429994e1943e83eda0ce8a0fa9ef29d39f435628..e31d291d14cbcd22add60622a9a2e83b8206ea11 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 2bbf8867362b59b7c083381b87675ac8b6a71666..c74a63a395312da47dd24dca1e2c271376a3789d 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Boris Brezillon <boris.brezillon@free-electrons.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 546cf6eff5c796fcaa65da5f2bd58331ef0a59c1..c36b4dc89c1300f596601cc761dbefdb13bbdc97 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index f142065b3c1fb4c807cf5c25ee8e039179dbd94c..6e924d9d2912ba5cb53eabfb9164601ce7565fc4 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Maxime Ripard <maxime.ripard@free-electrons.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index bc6115da5ae14055dd07f36de51cc0204dffdd9b..3ab544f3af4a5dc93ff7c6bac66583ff82a5f981 100644 (file)
@@ -1,12 +1,48 @@
 /*
  * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
                        status = "okay";
                };
 
+               usbphy: phy@01c19400 {
+                       usb1_vbus-supply = <&reg_usb1_vbus>;
+                       status = "okay";
+               };
+
+               ehci0: usb@01c1a000 {
+                       status = "okay";
+               };
+
+               ehci1: usb@01c1b000 {
+                       status = "okay";
+               };
+
                pio: pinctrl@01c20800 {
+                       led_pins_m9: led_pins@0 {
+                               allwinner,pins = "PH13";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
                        mmc0_cd_pin_m9: mmc0_cd_pin@0 {
                                allwinner,pins = "PH22";
                                allwinner,function = "gpio_in";
                                allwinner,drive = <0>;
                                allwinner,pull = <1>;
                        };
+
+                       usb1_vbus_pin_m9: usb1_vbus_pin@0 {
+                               allwinner,pins = "PC27";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
                };
 
                uart0: serial@01c28000 {
                        pinctrl-0 = <&uart0_pins_a>;
                        status = "okay";
                };
+
+               gmac: ethernet@01c30000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&gmac_pins_mii_a>;
+                       phy = <&phy1>;
+                       phy-mode = "mii";
+                       status = "okay";
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins_m9>;
+
+               blue {
+                       label = "m9:blue:usr";
+                       gpios = <&pio 7 13 0>;
+               };
+       };
+
+       reg_usb1_vbus: usb1-vbus {
+               pinctrl-names = "default";
+               pinctrl-0 = <&usb1_vbus_pin_m9>;
+               gpio = <&pio 2 27 0>;
+               status = "okay";
        };
 };
index 543f895d18d3c870446f52085095221566ef83a3..a400172a8a52255c6ed7bd4226e3f9ee016d2dfc 100644 (file)
@@ -8,18 +8,18 @@
  * 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
+ *  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 library is distributed in the hope that it will be useful,
+ *     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 library; if not, write to the Free
+ *     License along with this file; if not, write to the Free
  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  *     MA 02110-1301 USA
  *
                ethernet0 = &gmac;
        };
 
+       chosen {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               framebuffer@0 {
+                       compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
+                       allwinner,pipeline = "de_be0-lcd0-hdmi";
+                       clocks = <&pll6 0>;
+                       status = "disabled";
+               };
+       };
 
        cpus {
                enable-method = "allwinner,sun6i-a31";
                };
 
                pll6: clk@01c20028 {
-                       #clock-cells = <0>;
+                       #clock-cells = <1>;
                        compatible = "allwinner,sun6i-a31-pll6-clk";
                        reg = <0x01c20028 0x4>;
                        clocks = <&osc24M>;
-                       clock-output-names = "pll6";
+                       clock-output-names = "pll6", "pll6x2";
                };
 
                cpu: cpu@01c20050 {
                        #clock-cells = <0>;
                        compatible = "allwinner,sun6i-a31-ahb1-mux-clk";
                        reg = <0x01c20054 0x4>;
-                       clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>;
+                       clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
                        clock-output-names = "ahb1_mux";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-apb1-mux-clk";
                        reg = <0x01c20058 0x4>;
-                       clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
+                       clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
                        clock-output-names = "apb2_mux";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c20088 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "mmc0";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c2008c 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "mmc1";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c20090 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "mmc2";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c20094 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "mmc3";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c200a0 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "spi0";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c200a4 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "spi1";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c200a8 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "spi2";
                };
 
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-mod0-clk";
                        reg = <0x01c200ac 0x4>;
-                       clocks = <&osc24M>, <&pll6>;
+                       clocks = <&osc24M>, <&pll6 0>;
                        clock-output-names = "spi3";
                };
 
                        clocks = <&ahb1_gates 6>;
                        resets = <&ahb1_rst 6>;
                        #dma-cells = <1>;
+
+                       /* DMA controller requires AHB1 clocked from PLL6 */
+                       assigned-clocks = <&ahb1_mux>;
+                       assigned-clock-parents = <&pll6 0>;
                };
 
                mmc0: mmc@01c0f000 {
                        ar100: ar100_clk {
                                compatible = "allwinner,sun6i-a31-ar100-clk";
                                #clock-cells = <0>;
-                               clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
+                               clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
                                clock-output-names = "ar100";
                        };
 
diff --git a/arch/arm/boot/dts/sun7i-a20-bananapi.dts b/arch/arm/boot/dts/sun7i-a20-bananapi.dts
new file mode 100644 (file)
index 0000000..1cf1214
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Hans de Goede <hdegoede@redhat.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.
+ *
+ *     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/ "sun7i-a20.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+       model = "LeMaker Banana Pi";
+       compatible = "lemaker,bananapi", "allwinner,sun7i-a20";
+
+       soc@01c00000 {
+               spi0: spi@01c05000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&spi0_pins_a>;
+                       status = "okay";
+               };
+
+               mmc0: mmc@01c0f000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_bananapi>;
+                       vmmc-supply = <&reg_vcc3v3>;
+                       bus-width = <4>;
+                       cd-gpios = <&pio 7 10 0>; /* PH10 */
+                       cd-inverted;
+                       status = "okay";
+               };
+
+               usbphy: phy@01c13400 {
+                       usb1_vbus-supply = <&reg_usb1_vbus>;
+                       usb2_vbus-supply = <&reg_usb2_vbus>;
+                       status = "okay";
+               };
+
+               ehci0: usb@01c14000 {
+                       status = "okay";
+               };
+
+               ohci0: usb@01c14400 {
+                       status = "okay";
+               };
+
+               ahci: sata@01c18000 {
+                       status = "okay";
+               };
+
+               ehci1: usb@01c1c000 {
+                       status = "okay";
+               };
+
+               ohci1: usb@01c1c400 {
+                       status = "okay";
+               };
+
+               pinctrl@01c20800 {
+                       mmc0_cd_pin_bananapi: mmc0_cd_pin@0 {
+                               allwinner,pins = "PH10";
+                               allwinner,function = "gpio_in";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <1>;
+                       };
+
+                       gmac_power_pin_bananapi: gmac_power_pin@0 {
+                               allwinner,pins = "PH23";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
+                       led_pins_bananapi: led_pins@0 {
+                               allwinner,pins = "PH24";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+               };
+
+               ir0: ir@01c21800 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&ir0_pins_a>;
+                       status = "okay";
+               };
+
+               uart0: serial@01c28000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart0_pins_a>;
+                       status = "okay";
+               };
+
+               uart3: serial@01c28c00 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart3_pins_b>;
+                       status = "okay";
+               };
+
+               uart7: serial@01c29c00 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart7_pins_a>;
+                       status = "okay";
+               };
+
+               i2c0: i2c@01c2ac00 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c0_pins_a>;
+                       status = "okay";
+
+                       axp209: pmic@34 {
+                               compatible = "x-powers,axp209";
+                               reg = <0x34>;
+                               interrupt-parent = <&nmi_intc>;
+                               interrupts = <0 8>;
+
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                       };
+               };
+
+               i2c2: i2c@01c2b400 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c2_pins_a>;
+                       status = "okay";
+               };
+
+               gmac: ethernet@01c50000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&gmac_pins_rgmii_a>;
+                       phy = <&phy1>;
+                       phy-mode = "rgmii";
+                       phy-supply = <&reg_gmac_3v3>;
+                       status = "okay";
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins_bananapi>;
+
+               green {
+                       label = "bananapi:green:usr";
+                       gpios = <&pio 7 24 0>;
+               };
+       };
+
+       reg_usb1_vbus: usb1-vbus {
+               status = "okay";
+       };
+
+       reg_usb2_vbus: usb2-vbus {
+               status = "okay";
+       };
+
+       reg_gmac_3v3: gmac-3v3 {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&gmac_power_pin_bananapi>;
+               regulator-name = "gmac-3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               startup-delay-us = <100000>;
+               enable-active-high;
+               gpio = <&pio 7 23 0>;
+       };
+};
index a6c1a3c717bcaf94d2115f9e147059da01c7a984..a281d259b9b8ce0218d690ef0ddd9c05bfe0f844 100644 (file)
@@ -40,6 +40,7 @@
                };
 
                usbphy: phy@01c13400 {
+                       usb0_vbus-supply = <&reg_usb0_vbus>;
                        usb1_vbus-supply = <&reg_usb1_vbus>;
                        usb2_vbus-supply = <&reg_usb2_vbus>;
                        status = "okay";
                                allwinner,drive = <0>;
                                allwinner,pull = <0>;
                        };
+
+                       usb0_vbus_pin_a: usb0_vbus_pin@0 {
+                               allwinner,pins = "PH17";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
                };
 
                pwm: pwm@01c20e00 {
                status = "okay";
        };
 
+       reg_usb0_vbus: usb0-vbus {
+               pinctrl-0 = <&usb0_vbus_pin_a>;
+               gpio = <&pio 7 17 0>;
+               status = "okay";
+       };
+
        reg_usb1_vbus: usb1-vbus {
                status = "okay";
        };
index 6a67712d417acdb8dcea56c545875c3dccb54776..f38bb1a6656ca1e600f0a2391c822a094ced6030 100644 (file)
@@ -1,12 +1,48 @@
 /*
  * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
diff --git a/arch/arm/boot/dts/sun7i-a20-m3.dts b/arch/arm/boot/dts/sun7i-a20-m3.dts
new file mode 100644 (file)
index 0000000..b8e568c
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Hans de Goede <hdegoede@redhat.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.
+ *
+ *     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/ "sun7i-a20.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+       model = "Mele M3";
+       compatible = "mele,m3", "allwinner,sun7i-a20";
+
+       soc@01c00000 {
+               mmc0: mmc@01c0f000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
+                       vmmc-supply = <&reg_vcc3v3>;
+                       bus-width = <4>;
+                       cd-gpios = <&pio 7 1 0>; /* PH1 */
+                       cd-inverted;
+                       status = "okay";
+               };
+
+               mmc2: mmc@01c11000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc2_pins_a>;
+                       vmmc-supply = <&reg_vcc3v3>;
+                       bus-width = <4>;
+                       non-removable;
+                       status = "okay";
+               };
+
+               usbphy: phy@01c13400 {
+                       usb1_vbus-supply = <&reg_usb1_vbus>;
+                       usb2_vbus-supply = <&reg_usb2_vbus>;
+                       status = "okay";
+               };
+
+               ehci0: usb@01c14000 {
+                       status = "okay";
+               };
+
+               ohci0: usb@01c14400 {
+                       status = "okay";
+               };
+
+               ehci1: usb@01c1c000 {
+                       status = "okay";
+               };
+
+               ohci1: usb@01c1c400 {
+                       status = "okay";
+               };
+
+               pinctrl@01c20800 {
+                       led_pins_m3: led_pins@0 {
+                               allwinner,pins = "PH20";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+               };
+
+               ir0: ir@01c21800 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&ir0_pins_a>;
+                       status = "okay";
+               };
+
+               uart0: serial@01c28000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart0_pins_a>;
+                       status = "okay";
+               };
+
+               i2c0: i2c@01c2ac00 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c0_pins_a>;
+                       status = "okay";
+
+                       axp209: pmic@34 {
+                               compatible = "x-powers,axp209";
+                               reg = <0x34>;
+                               interrupt-parent = <&nmi_intc>;
+                               interrupts = <0 8>;
+
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+                       };
+               };
+
+               gmac: ethernet@01c50000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&gmac_pins_mii_a>;
+                       phy = <&phy1>;
+                       phy-mode = "mii";
+                       status = "okay";
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins_m3>;
+
+               blue {
+                       label = "m3:blue:usr";
+                       gpios = <&pio 7 20 0>;
+               };
+       };
+
+       reg_usb1_vbus: usb1-vbus {
+               status = "okay";
+       };
+
+       reg_usb2_vbus: usb2-vbus {
+               status = "okay";
+       };
+};
index 1eb8175959a60b9e07434e8de8830aa7b35f644b..3f3ff9693992b0effcf0bdf6d60939c2476db2f7 100644 (file)
@@ -4,12 +4,48 @@
  * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
  * Copyright (c) 2014 FUKAUMI Naoki <naobsd@gmail.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
new file mode 100644 (file)
index 0000000..ed364d5
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2014 - Iain Paton <ipaton0@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     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/ "sun7i-a20.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+       model = "Olimex A20-OLinuXino-LIME2";
+       compatible = "olimex,a20-olinuxino-lime2", "allwinner,sun7i-a20";
+
+       soc@01c00000 {
+               mmc0: mmc@01c0f000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
+                       vmmc-supply = <&reg_vcc3v3>;
+                       bus-width = <4>;
+                       cd-gpios = <&pio 7 1 0>; /* PH1 */
+                       cd-inverted;
+                       status = "okay";
+               };
+
+               usbphy: phy@01c13400 {
+                       usb1_vbus-supply = <&reg_usb1_vbus>;
+                       usb2_vbus-supply = <&reg_usb2_vbus>;
+                       status = "okay";
+               };
+
+               ehci0: usb@01c14000 {
+                       status = "okay";
+               };
+
+               ohci0: usb@01c14400 {
+                       status = "okay";
+               };
+
+               ahci: sata@01c18000 {
+                       target-supply = <&reg_ahci_5v>;
+                       status = "okay";
+               };
+
+               ehci1: usb@01c1c000 {
+                       status = "okay";
+               };
+
+               ohci1: usb@01c1c400 {
+                       status = "okay";
+               };
+
+               pinctrl@01c20800 {
+                       ahci_pwr_pin_olinuxinolime: ahci_pwr_pin@1 {
+                               allwinner,pins = "PC3";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
+                       led_pins_olinuxinolime: led_pins@0 {
+                               allwinner,pins = "PH2";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <1>;
+                               allwinner,pull = <0>;
+                       };
+               };
+
+               uart0: serial@01c28000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart0_pins_a>;
+                       status = "okay";
+               };
+
+               i2c0: i2c@01c2ac00 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c0_pins_a>;
+                       status = "okay";
+
+                       axp209: pmic@34 {
+                               compatible = "x-powers,axp209";
+                               reg = <0x34>;
+                               interrupt-parent = <&nmi_intc>;
+                               interrupts = <0 8>;
+
+                               interrupt-controller;
+                               #interrupt-cells = <1>;
+
+                               acin-supply = <&reg_axp_ipsout>;
+                               vin2-supply = <&reg_axp_ipsout>;
+                               vin3-supply = <&reg_axp_ipsout>;
+                               ldo24in-supply = <&reg_axp_ipsout>;
+                               ldo3in-supply = <&reg_axp_ipsout>;
+
+                               regulators {
+                                       vdd_rtc: ldo1 {
+                                               regulator-min-microvolt = <1300000>;
+                                               regulator-max-microvolt = <1300000>;
+                                               regulator-always-on;
+                                       };
+
+                                       avcc: ldo2 {
+                                               regulator-min-microvolt = <1800000>;
+                                               regulator-max-microvolt = <3300000>;
+                                               regulator-always-on;
+                                       };
+
+                                       vcc_csi0: ldo3 {
+                                               regulator-min-microvolt = <700000>;
+                                               regulator-max-microvolt = <3500000>;
+                                               regulator-always-on;
+                                       };
+
+                                       vcc_csi1: ldo4 {
+                                               regulator-min-microvolt = <1250000>;
+                                               regulator-max-microvolt = <3300000>;
+                                               regulator-always-on;
+                                       };
+
+                                       vdd_cpu: dcdc2 {
+                                               regulator-min-microvolt = <700000>;
+                                               regulator-max-microvolt = <2275000>;
+                                               regulator-always-on;
+                                       };
+
+                                       vdd_int: dcdc3 {
+                                               regulator-min-microvolt = <700000>;
+                                               regulator-max-microvolt = <3500000>;
+                                               regulator-always-on;
+                                       };
+                               };
+                       };
+               };
+
+               i2c1: i2c@01c2b000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c1_pins_a>;
+                       status = "okay";
+               };
+
+               gmac: ethernet@01c50000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&gmac_pins_rgmii_a>;
+                       phy = <&phy1>;
+                       phy-mode = "rgmii";
+                       status = "okay";
+
+                       phy1: ethernet-phy@1 {
+                               reg = <1>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins_olinuxinolime>;
+
+               green {
+                       label = "a20-olinuxino-lime2:green:usr";
+                       gpios = <&pio 7 2 0>;
+                       default-state = "on";
+               };
+       };
+
+       reg_ahci_5v: ahci-5v {
+               pinctrl-0 = <&ahci_pwr_pin_olinuxinolime>;
+               gpio = <&pio 2 3 0>;
+               status = "okay";
+       };
+
+       reg_usb1_vbus: usb1-vbus {
+               status = "okay";
+       };
+
+       reg_usb2_vbus: usb2-vbus {
+               status = "okay";
+       };
+
+       reg_axp_ipsout: axp_ipsout {
+               compatible = "regulator-fixed";
+               regulator-name = "axp-ipsout";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+};
index 046dfc0d45d8ebb21d8a7dd050fdb500dbbf6d35..8dca49b2477bc7737735a33c206605ee1f1d2e36 100644 (file)
@@ -2,12 +2,48 @@
  * Copyright 2014 Zoltan HERPAI
  * Zoltan HERPAI <wigyori@uid0.hu>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 82097c905c48cb5e99387db684c113fb6d37cb94..82a524ce28ad1502c5aee93accdb649aeede8821 100644 (file)
@@ -8,18 +8,18 @@
  * 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
+ *  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 library is distributed in the hope that it will be useful,
+ *     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 library; if not, write to the Free
+ *     License along with this file; if not, write to the Free
  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  *     MA 02110-1301 USA
  *
                serial7 = &uart7;
        };
 
+       chosen {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               framebuffer@0 {
+                       compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
+                       allwinner,pipeline = "de_be0-lcd0-hdmi";
+                       clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
+                                <&ahb_gates 44>;
+                       status = "disabled";
+               };
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                        reg-names = "phy_ctrl", "pmu1", "pmu2";
                        clocks = <&usb_clk 8>;
                        clock-names = "usb_phy";
-                       resets = <&usb_clk 1>, <&usb_clk 2>;
-                       reset-names = "usb1_reset", "usb2_reset";
+                       resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>;
+                       reset-names = "usb0_reset", "usb1_reset", "usb2_reset";
                        status = "disabled";
                };
 
                                allwinner,pull = <0>;
                        };
 
+                       uart3_pins_b: uart3@1 {
+                               allwinner,pins = "PH0", "PH1";
+                               allwinner,function = "uart3";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
                        uart4_pins_a: uart4@0 {
                                allwinner,pins = "PG10", "PG11";
                                allwinner,function = "uart4";
                                allwinner,pull = <0>;
                        };
 
+                       spi0_pins_a: spi0@0 {
+                               allwinner,pins = "PI10", "PI11", "PI12", "PI13", "PI14";
+                               allwinner,function = "spi0";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
                        spi1_pins_a: spi1@0 {
                                allwinner,pins = "PI16", "PI17", "PI18", "PI19";
                                allwinner,function = "spi1";
                                allwinner,pull = <1>;
                        };
 
+                       mmc2_pins_a: mmc2@0 {
+                               allwinner,pins = "PC6","PC7","PC8","PC9","PC10","PC11";
+                               allwinner,function = "mmc2";
+                               allwinner,drive = <2>;
+                               allwinner,pull = <1>;
+                       };
+
                        mmc3_pins_a: mmc3@0 {
                                allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
                                allwinner,function = "mmc3";
index e9b8cca8dcc1cc7a9c61c9fe6a3450c72241849b..7f2117ce6985b1de46cfd2fbfbc42fb76e19a1d7 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Chen-Yu Tsai <wens@csie.org>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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/;
index 6146ef15efbe31849eedd9ca1efa9de1d99935e1..6086adbf9d749adf1fb2040fb76675e84292bab9 100644 (file)
@@ -8,18 +8,18 @@
  * 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
+ *  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 library is distributed in the hope that it will be useful,
+ *     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 library; if not, write to the Free
+ *     License along with this file; if not, write to the Free
  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  *     MA 02110-1301 USA
  *
diff --git a/arch/arm/boot/dts/sun9i-a80-optimus.dts b/arch/arm/boot/dts/sun9i-a80-optimus.dts
new file mode 100644 (file)
index 0000000..506948f
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * 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/ "sun9i-a80.dtsi"
+
+/ {
+       model = "Merrii A80 Optimus Board";
+       compatible = "merrii,a80-optimus", "allwinner,sun9i-a80";
+
+       chosen {
+               bootargs = "earlyprintk console=ttyS0,115200";
+       };
+
+       soc {
+               pio: pinctrl@06000800 {
+                       i2c3_pins_a: i2c3@0 {
+                               /* Enable internal pull-up */
+                               allwinner,pull = <1>;
+                       };
+
+                       led_pins_optimus: led-pins@0 {
+                               allwinner,pins = "PH0", "PH1";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
+                       uart4_pins_a: uart4@0 {
+                               /* Enable internal pull-up */
+                               allwinner,pull = <1>;
+                       };
+               };
+
+               uart0: serial@07000000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart0_pins_a>;
+                       status = "okay";
+               };
+
+               uart4: serial@07001000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart4_pins_a>;
+                       status = "okay";
+               };
+
+               i2c3: i2c@07003400 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c3_pins_a>;
+                       status = "okay";
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins_optimus>;
+
+               /* The LED names match those found on the board */
+
+               led2 {
+                       label = "optimus:led2:usr";
+                       gpios = <&pio 7 1 0>;
+               };
+
+               /* led3 is on PM15, in R_PIO */
+
+               led4 {
+                       label = "optimus:led4:usr";
+                       gpios = <&pio 7 0 0>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi
new file mode 100644 (file)
index 0000000..494714f
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2014 Chen-Yu Tsai
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * 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.
+ */
+
+/include/ "skeleton64.dtsi"
+
+/ {
+       interrupt-parent = <&gic>;
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
+               serial4 = &uart4;
+               serial5 = &uart5;
+               serial6 = &r_uart;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0x0>;
+               };
+
+               cpu1: cpu@1 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0x1>;
+               };
+
+               cpu2: cpu@2 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0x2>;
+               };
+
+               cpu3: cpu@3 {
+                       compatible = "arm,cortex-a7";
+                       device_type = "cpu";
+                       reg = <0x3>;
+               };
+
+               cpu4: cpu@100 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <0x100>;
+               };
+
+               cpu5: cpu@101 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <0x101>;
+               };
+
+               cpu6: cpu@102 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <0x102>;
+               };
+
+               cpu7: cpu@103 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <0x103>;
+               };
+       };
+
+       memory {
+               /* 8GB max. with LPAE */
+               reg = <0 0x20000000 0x02 0>;
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               /*
+                * map 64 bit address range down to 32 bits,
+                * as the peripherals are all under 512MB.
+                */
+               ranges = <0 0 0 0x20000000>;
+
+               osc24M: osc24M_clk {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <24000000>;
+                       clock-output-names = "osc24M";
+               };
+
+               osc32k: osc32k_clk {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <32768>;
+                       clock-output-names = "osc32k";
+               };
+
+               pll4: clk@0600000c {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-pll4-clk";
+                       reg = <0x0600000c 0x4>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll4";
+               };
+
+               pll12: clk@0600002c {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-pll4-clk";
+                       reg = <0x0600002c 0x4>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll12";
+               };
+
+               gt_clk: clk@0600005c {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-gt-clk";
+                       reg = <0x0600005c 0x4>;
+                       clocks = <&osc24M>, <&pll4>, <&pll12>, <&pll12>;
+                       clock-output-names = "gt";
+               };
+
+               ahb0: clk@06000060 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-ahb-clk";
+                       reg = <0x06000060 0x4>;
+                       clocks = <&gt_clk>, <&pll4>, <&pll12>, <&pll12>;
+                       clock-output-names = "ahb0";
+               };
+
+               ahb1: clk@06000064 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-ahb-clk";
+                       reg = <0x06000064 0x4>;
+                       clocks = <&gt_clk>, <&pll4>, <&pll12>, <&pll12>;
+                       clock-output-names = "ahb1";
+               };
+
+               ahb2: clk@06000068 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-ahb-clk";
+                       reg = <0x06000068 0x4>;
+                       clocks = <&gt_clk>, <&pll4>, <&pll12>, <&pll12>;
+                       clock-output-names = "ahb2";
+               };
+
+               apb0: clk@06000070 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-apb0-clk";
+                       reg = <0x06000070 0x4>;
+                       clocks = <&osc24M>, <&pll4>;
+                       clock-output-names = "apb0";
+               };
+
+               apb1: clk@06000074 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-apb1-clk";
+                       reg = <0x06000074 0x4>;
+                       clocks = <&osc24M>, <&pll4>;
+                       clock-output-names = "apb1";
+               };
+
+               cci400_clk: clk@06000078 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun9i-a80-gt-clk";
+                       reg = <0x06000078 0x4>;
+                       clocks = <&osc24M>, <&pll4>, <&pll12>, <&pll12>;
+                       clock-output-names = "cci400";
+               };
+
+               ahb0_gates: clk@06000580 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun9i-a80-ahb0-gates-clk";
+                       reg = <0x06000580 0x4>;
+                       clocks = <&ahb0>;
+                       clock-output-names = "ahb0_fd", "ahb0_ve", "ahb0_gpu",
+                                       "ahb0_ss", "ahb0_sd", "ahb0_nand1",
+                                       "ahb0_nand0", "ahb0_sdram",
+                                       "ahb0_mipi_hsi", "ahb0_sata", "ahb0_ts",
+                                       "ahb0_spi0","ahb0_spi1", "ahb0_spi2",
+                                       "ahb0_spi3";
+               };
+
+               ahb1_gates: clk@06000584 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun9i-a80-ahb1-gates-clk";
+                       reg = <0x06000584 0x4>;
+                       clocks = <&ahb1>;
+                       clock-output-names = "ahb1_usbotg", "ahb1_usbhci",
+                                       "ahb1_gmac", "ahb1_msgbox",
+                                       "ahb1_spinlock", "ahb1_hstimer",
+                                       "ahb1_dma";
+               };
+
+               ahb2_gates: clk@06000588 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun9i-a80-ahb2-gates-clk";
+                       reg = <0x06000588 0x4>;
+                       clocks = <&ahb2>;
+                       clock-output-names = "ahb2_lcd0", "ahb2_lcd1",
+                                       "ahb2_edp", "ahb2_csi", "ahb2_hdmi",
+                                       "ahb2_de", "ahb2_mp", "ahb2_mipi_dsi";
+               };
+
+               apb0_gates: clk@06000590 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun9i-a80-apb0-gates-clk";
+                       reg = <0x06000590 0x4>;
+                       clocks = <&apb0>;
+                       clock-output-names = "apb0_spdif", "apb0_pio",
+                                       "apb0_ac97", "apb0_i2s0", "apb0_i2s1",
+                                       "apb0_lradc", "apb0_gpadc", "apb0_twd",
+                                       "apb0_cirtx";
+               };
+
+               apb1_gates: clk@06000594 {
+                       #clock-cells = <1>;
+                       compatible = "allwinner,sun9i-a80-apb1-gates-clk";
+                       reg = <0x06000594 0x4>;
+                       clocks = <&apb1>;
+                       clock-output-names = "apb1_i2c0", "apb1_i2c1",
+                                       "apb1_i2c2", "apb1_i2c3", "apb1_i2c4",
+                                       "apb1_uart0", "apb1_uart1",
+                                       "apb1_uart2", "apb1_uart3",
+                                       "apb1_uart4", "apb1_uart5";
+               };
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               /*
+                * map 64 bit address range down to 32 bits,
+                * as the peripherals are all under 512MB.
+                */
+               ranges = <0 0 0 0x20000000>;
+
+               gic: interrupt-controller@01c41000 {
+                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+                       reg = <0x01c41000 0x1000>,
+                             <0x01c42000 0x1000>,
+                             <0x01c44000 0x2000>,
+                             <0x01c46000 0x2000>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       interrupts = <1 9 0xf04>;
+               };
+
+               ahb0_resets: reset@060005a0 {
+                       #reset-cells = <1>;
+                       compatible = "allwinner,sun6i-a31-clock-reset";
+                       reg = <0x060005a0 0x4>;
+               };
+
+               ahb1_resets: reset@060005a4 {
+                       #reset-cells = <1>;
+                       compatible = "allwinner,sun6i-a31-clock-reset";
+                       reg = <0x060005a4 0x4>;
+               };
+
+               ahb2_resets: reset@060005a8 {
+                       #reset-cells = <1>;
+                       compatible = "allwinner,sun6i-a31-clock-reset";
+                       reg = <0x060005a8 0x4>;
+               };
+
+               apb0_resets: reset@060005b0 {
+                       #reset-cells = <1>;
+                       compatible = "allwinner,sun6i-a31-clock-reset";
+                       reg = <0x060005b0 0x4>;
+               };
+
+               apb1_resets: reset@060005b4 {
+                       #reset-cells = <1>;
+                       compatible = "allwinner,sun6i-a31-clock-reset";
+                       reg = <0x060005b4 0x4>;
+               };
+
+               timer@06000c00 {
+                       compatible = "allwinner,sun4i-a10-timer";
+                       reg = <0x06000c00 0xa0>;
+                       interrupts = <0 18 4>,
+                                    <0 19 4>,
+                                    <0 20 4>,
+                                    <0 21 4>,
+                                    <0 22 4>,
+                                    <0 23 4>;
+
+                       clocks = <&osc24M>;
+               };
+
+               pio: pinctrl@06000800 {
+                       compatible = "allwinner,sun9i-a80-pinctrl";
+                       reg = <0x06000800 0x400>;
+                       interrupts = <0 11 4>,
+                                    <0 15 4>,
+                                    <0 16 4>,
+                                    <0 17 4>,
+                                    <0 120 4>;
+                       clocks = <&apb0_gates 5>;
+                       gpio-controller;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       #size-cells = <0>;
+                       #gpio-cells = <3>;
+
+                       i2c3_pins_a: i2c3@0 {
+                               allwinner,pins = "PG10", "PG11";
+                               allwinner,function = "i2c3";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
+                       uart0_pins_a: uart0@0 {
+                               allwinner,pins = "PH12", "PH13";
+                               allwinner,function = "uart0";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
+                       uart4_pins_a: uart4@0 {
+                               allwinner,pins = "PG12", "PG13", "PG14", "PG15";
+                               allwinner,function = "uart4";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+               };
+
+               uart0: serial@07000000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x07000000 0x400>;
+                       interrupts = <0 0 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 16>;
+                       resets = <&apb1_resets 16>;
+                       status = "disabled";
+               };
+
+               uart1: serial@07000400 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x07000400 0x400>;
+                       interrupts = <0 1 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 17>;
+                       resets = <&apb1_resets 17>;
+                       status = "disabled";
+               };
+
+               uart2: serial@07000800 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x07000800 0x400>;
+                       interrupts = <0 2 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 18>;
+                       resets = <&apb1_resets 18>;
+                       status = "disabled";
+               };
+
+               uart3: serial@07000c00 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x07000c00 0x400>;
+                       interrupts = <0 3 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 19>;
+                       resets = <&apb1_resets 19>;
+                       status = "disabled";
+               };
+
+               uart4: serial@07001000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x07001000 0x400>;
+                       interrupts = <0 4 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 20>;
+                       resets = <&apb1_resets 20>;
+                       status = "disabled";
+               };
+
+               uart5: serial@07001400 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x07001400 0x400>;
+                       interrupts = <0 5 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&apb1_gates 21>;
+                       resets = <&apb1_resets 21>;
+                       status = "disabled";
+               };
+
+               i2c0: i2c@07002800 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x07002800 0x400>;
+                       interrupts = <0 6 4>;
+                       clocks = <&apb1_gates 0>;
+                       resets = <&apb1_resets 0>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c1: i2c@07002c00 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x07002c00 0x400>;
+                       interrupts = <0 7 4>;
+                       clocks = <&apb1_gates 1>;
+                       resets = <&apb1_resets 1>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c2: i2c@07003000 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x07003000 0x400>;
+                       interrupts = <0 8 4>;
+                       clocks = <&apb1_gates 2>;
+                       resets = <&apb1_resets 2>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c3: i2c@07003400 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x07003400 0x400>;
+                       interrupts = <0 9 4>;
+                       clocks = <&apb1_gates 3>;
+                       resets = <&apb1_resets 3>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c4: i2c@07003800 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x07003800 0x400>;
+                       interrupts = <0 10 4>;
+                       clocks = <&apb1_gates 4>;
+                       resets = <&apb1_resets 4>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               r_wdt: watchdog@08001000 {
+                       compatible = "allwinner,sun6i-a31-wdt";
+                       reg = <0x08001000 0x20>;
+                       interrupts = <0 36 4>;
+               };
+
+               r_uart: serial@08002800 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x08002800 0x400>;
+                       interrupts = <0 38 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&osc24M>;
+                       status = "disabled";
+               };
+       };
+};
index c9c5b10e03eb11dbff0c8b40bb308e8764572777..d8876634f965e47e99e6554d0fccca2c88f4afc4 100644 (file)
@@ -3,12 +3,48 @@
  *
  * Copyright 2014 - Hans de Goede <hdegoede@redhat.com>
  *
- * 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:
+ * 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.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  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.
  */
 
 / {
                                allwinner,pull = <0>;
                        };
 
+                       usb0_vbus_pin_a: usb0_vbus_pin@0 {
+                               allwinner,pins = "PB9";
+                               allwinner,function = "gpio_out";
+                               allwinner,drive = <0>;
+                               allwinner,pull = <0>;
+                       };
+
                        usb1_vbus_pin_a: usb1_vbus_pin@0 {
                                allwinner,pins = "PH6";
                                allwinner,function = "gpio_out";
                regulator-name = "ahci-5v";
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
                enable-active-high;
                gpio = <&pio 1 8 0>;
                status = "disabled";
        };
 
+       reg_usb0_vbus: usb0-vbus {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&usb0_vbus_pin_a>;
+               regulator-name = "usb0-vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               enable-active-high;
+               gpio = <&pio 1 9 0>;
+               status = "disabled";
+       };
+
        reg_usb1_vbus: usb1-vbus {
                compatible = "regulator-fixed";
                pinctrl-names = "default";
index 5c21d216515a3d5a06b76a4b449cc72ef208b6af..8b7aa0dcdc6ee4d4a04100650c1ac33cebcd6762 100644 (file)
@@ -15,6 +15,7 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps65913@58";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uartd;
        };
 
        memory {
index c7c6825f11fbb1b902b6f230eb62d8d8f88077a6..38acf78d7815fab2ab14842503a4bf79c040f9ed 100644 (file)
                linux,initrd-end = <0x82800000>;
        };
 
+       aliases {
+               serial0 = &uartd;
+       };
+
        firmware {
                trusted-foundations {
                        compatible = "tlm,trusted-foundations";
                                                regulator-name = "vddio-sdmmc3";
                                                regulator-min-microvolt = <1800000>;
                                                regulator-max-microvolt = <3300000>;
-                                               regulator-always-on;
-                                               regulator-boot-on;
                                        };
 
                                        ldousb {
        sdhci@78000400 {
                status = "okay";
                bus-width = <4>;
-               vmmc-supply = <&vddio_sdmmc3>;
+               vqmmc-supply = <&vddio_sdmmc3>;
                cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
                power-gpios = <&gpio TEGRA_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
        };
        sdhci@78000600 {
                status = "okay";
                bus-width = <8>;
-               vmmc-supply = <&vdd_1v8>;
                non-removable;
        };
 
index 96366214563542479db657f80b12a28918e30824..f91c2c9b2f9431aef1e1611ba2eaf064a40aed7d 100644 (file)
                linux,initrd-end = <0x82800000>;
        };
 
+       aliases {
+               serial0 = &uartd;
+       };
+
        firmware {
                trusted-foundations {
                        compatible = "tlm,trusted-foundations";
        sdhci@78000600 {
                status = "okay";
                bus-width = <8>;
-               vmmc-supply = <&vdd_1v8>;
                non-removable;
        };
 
index 2ca9c1807f72374bb176aada1203f6d9bc88e220..222f3b3f4dd5c4f852259349228db76e89c7ac27 100644 (file)
@@ -9,13 +9,6 @@
        compatible = "nvidia,tegra114";
        interrupt-parent = <&gic>;
 
-       aliases {
-               serial0 = &uarta;
-               serial1 = &uartb;
-               serial2 = &uartc;
-               serial3 = &uartd;
-       };
-
        host1x@50000000 {
                compatible = "nvidia,tegra114-host1x", "simple-bus";
                reg = <0x50000000 0x00028000>;
index 029c9a0215413355d3ce7c081a3ac5bd00fcd3d7..51b373ff106555edf302c9066809ea4abbd25c5c 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@0,7000d000/pmic@40";
                rtc1 = "/rtc@0,7000e000";
+               serial0 = &uartd;
        };
 
        memory {
index 7d0784ce4c748183083fa4ab5947b9adfb083d72..53181d31024713796897f5980cf9994339eb691f 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@0,7000d000/pmic@40";
                rtc1 = "/rtc@0,7000e000";
+               serial0 = &uarta;
        };
 
        memory {
index 13008858e96754dda8de3f838add6e0b6d4fb911..5c3f7813360d2a59bffcc463f059b2047440fabf 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@0,7000d000/pmic@40";
                rtc1 = "/rtc@0,7000e000";
+               serial0 = &uarta;
        };
 
        memory {
index 478c555ebd96bd0897bae7d3d0e7fa368573cba5..df2b06b299851a85533243a96126e49e43813066 100644 (file)
         * the APB DMA based serial driver, the comptible is
         * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart".
         */
-       serial@0,70006000 {
+       uarta: serial@0,70006000 {
                compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
                reg = <0x0 0x70006000 0x0 0x40>;
                reg-shift = <2>;
                status = "disabled";
        };
 
-       serial@0,70006040 {
+       uartb: serial@0,70006040 {
                compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
                reg = <0x0 0x70006040 0x0 0x40>;
                reg-shift = <2>;
                status = "disabled";
        };
 
-       serial@0,70006200 {
+       uartc: serial@0,70006200 {
                compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
                reg = <0x0 0x70006200 0x0 0x40>;
                reg-shift = <2>;
                status = "disabled";
        };
 
-       serial@0,70006300 {
+       uartd: serial@0,70006300 {
                compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
                reg = <0x0 0x70006300 0x0 0x40>;
                reg-shift = <2>;
index a37279af687c6a436ba5308c6139a5c3c8be9014..b926a07b944303fb24468d6899bc9324c7c956bb 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps6586x@34";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uartd;
        };
 
        memory {
index 8cfb83f42e1fd87ff608b171a2c404942975b0ff..1dd7d7bfdfcc25e3d3fcb35e6f17c4ccb95b2b5f 100644 (file)
@@ -6,6 +6,11 @@
        model = "Toradex Colibri T20 512MB on Iris";
        compatible = "toradex,iris", "toradex,colibri_t20-512", "nvidia,tegra20";
 
+       aliases {
+               serial0 = &uarta;
+               serial1 = &uartd;
+       };
+
        host1x@50000000 {
                hdmi@54280000 {
                        status = "okay";
index 1b7c56b33acae6f2c6c4b1da3154d6c92aebb96a..9b87526ab0b70fad25125a4f5764d418243aa50c 100644 (file)
@@ -6,6 +6,10 @@
        model = "Avionic Design Medcom-Wide board";
        compatible = "ad,medcom-wide", "ad,tamonten", "nvidia,tegra20";
 
+       aliases {
+               serial0 = &uartd;
+       };
+
        pwm@7000a000 {
                status = "okay";
        };
index d4438e30de456c70047457f6ee974ac31a6f686f..ed7e1009326cd748628c5422849bfffad2a3b21e 100644 (file)
@@ -10,6 +10,8 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps6586x@34";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uarta;
+               serial1 = &uartc;
        };
 
        memory {
index a1d4bf9895d74c8b0efb7d2fe948a9fcd602b25e..ea282c7c0ca5645394a28e313fbad1deac339882 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps6586x@34";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uartd;
        };
 
        memory {
index 80e7d386ce3452e3776e70771233eea336a81e98..13d4e6185275f43c3f74fbeb0397d97b0348f9fb 100644 (file)
@@ -7,6 +7,7 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps6586x@34";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uartd;
        };
 
        memory {
index 5ad87979ab13ff68527f3b6c8a1ba9bb51e2bda5..d99af4ef9c6444f73e7044c7447557fbca4b4ee1 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@7000c500/rtc@56";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uarta;
        };
 
        memory {
index ca8484cccddccc32313649e1abfd644b527f50a3..04c58e9ca490bb8bf205b4608d371bbecf5f3f61 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps6586x@34";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uartd;
        };
 
        memory {
index 1843725785c90f1f2518bade455af7dead4c6ec8..340d81108df1a232fcefe64c81bdb9372a4c814c 100644 (file)
@@ -10,6 +10,7 @@
        aliases {
                rtc0 = "/i2c@7000d000/max8907@3c";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uarta;
        };
 
        memory {
index 3b374c49d04d962478aebc62799bcce5b31aa6dd..8acf5d85c99da5b0077f6ce1b80c2ba08d45865c 100644 (file)
@@ -9,14 +9,6 @@
        compatible = "nvidia,tegra20";
        interrupt-parent = <&intc>;
 
-       aliases {
-               serial0 = &uarta;
-               serial1 = &uartb;
-               serial2 = &uartc;
-               serial3 = &uartd;
-               serial4 = &uarte;
-       };
-
        host1x@50000000 {
                compatible = "nvidia,tegra20-host1x", "simple-bus";
                reg = <0x50000000 0x00024000>;
index 45d40f024585d95a53928e36d351db05aa514592..6236bdecb48ba08891896f6967199aba6e2a6680 100644 (file)
                rtc0 = "/i2c@7000c000/rtc@68";
                rtc1 = "/i2c@7000d000/tps65911@2d";
                rtc2 = "/rtc@7000e000";
+               serial0 = &uarta;
+               serial1 = &uartb;
+               serial2 = &uartc;
+               serial3 = &uartd;
        };
 
        pcie-controller@00003000 {
index cee8f2246fdb2467fbde27bae612a0752d7f6da2..6b157eeabcc5c9b07009c4d91a291122b3732887 100644 (file)
@@ -9,6 +9,7 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps65911@2d";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uarta;
        };
 
        memory {
index 20637954624425795453cc78699e674276de5430..cbf5a1ae0ca7261abb3642648a31802ac95230ed 100644 (file)
@@ -30,6 +30,8 @@
        aliases {
                rtc0 = "/i2c@7000d000/tps65911@2d";
                rtc1 = "/rtc@7000e000";
+               serial0 = &uarta;
+               serial1 = &uartc;
        };
 
        memory {
 
                /* ALS and Proximity sensor */
                isl29028@44 {
-                       compatible = "isil,isl29028";
+                       compatible = "isl,isl29028";
                        reg = <0x44>;
                        interrupt-parent = <&gpio>;
                        interrupts = <TEGRA_GPIO(L, 0) IRQ_TYPE_LEVEL_HIGH>;
index 7793abd5bef132388100e8a0c1aa4ca79e7ed803..4d3ddc58564126433410c17b5c3ef569532a9aa1 100644 (file)
@@ -10,6 +10,9 @@
                rtc0 = "/i2c@7000c000/rtc@68";
                rtc1 = "/i2c@7000d000/tps65911@2d";
                rtc2 = "/rtc@7000e000";
+               serial0 = &uarta;
+               serial1 = &uartb;
+               serial2 = &uartd;
        };
 
        host1x@50000000 {
index aa6ccea13d308036e853b58bafe840d7c3450e87..b270b9e3d4554407157be95cadd71c9b5e902eeb 100644 (file)
@@ -9,14 +9,6 @@
        compatible = "nvidia,tegra30";
        interrupt-parent = <&intc>;
 
-       aliases {
-               serial0 = &uarta;
-               serial1 = &uartb;
-               serial2 = &uartc;
-               serial3 = &uartd;
-               serial4 = &uarte;
-       };
-
        pcie-controller@00003000 {
                compatible = "nvidia,tegra30-pcie";
                device_type = "pci";
diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
new file mode 100644 (file)
index 0000000..56a452b
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/ {
+       chosen {
+               bootargs = "console=ttyLP0,115200";
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               sys_5v0_reg: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "5v0";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+               };
+
+               /* USBH_PEN */
+               usbh_vbus_reg: regulator@1 {
+                       compatible = "regulator-fixed";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usbh1_reg>;
+                       reg = <1>;
+                       regulator-name = "usbh_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 19 GPIO_ACTIVE_LOW>;
+                       vin-supply = <&sys_5v0_reg>;
+               };
+       };
+};
+
+&bl {
+       brightness-levels = <0 4 8 16 32 64 128 255>;
+       default-brightness-level = <6>;
+       status  = "okay";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&fec1 {
+       phy-mode = "rmii";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
+       status = "okay";
+};
+
+&i2c0 {
+       status = "okay";
+
+       /* M41T0M6 real time clock on carrier board */
+       rtc: m41t0m6@68 {
+               compatible = "st,m41t00";
+               reg = <0x68>;
+       };
+};
+
+&pwm0 {
+       status = "okay";
+};
+
+&pwm1 {
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&usbh_vbus_reg>;
+};
diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi
new file mode 100644 (file)
index 0000000..82f5728
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/ {
+       bl: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm0 0 5000000 0>;
+               status = "disabled";
+       };
+};
+
+&adc0 {
+       status = "okay";
+};
+
+&adc1 {
+       status = "okay";
+};
+
+&edma0 {
+       status = "okay";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <4>;
+       cd-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+};
+
+&fec1 {
+       phy-mode = "rmii";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec1>;
+};
+
+&i2c0 {
+       clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c0>;
+};
+
+&pwm0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm0>;
+};
+
+&pwm1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm1>;
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart0>;
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+};
+
+&usbdev0 {
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       disable-over-current;
+       status = "okay";
+};
+
+&usbmisc0 {
+       status = "okay";
+};
+
+&usbmisc1 {
+       status = "okay";
+};
+
+&usbphy0 {
+       status = "okay";
+};
+
+&usbphy1 {
+       status = "okay";
+};
+
+&iomuxc {
+       vf610-colibri {
+               pinctrl_gpio_ext: gpio_ext {
+                       fsl,pins = <
+                               VF610_PAD_PTD10__GPIO_89        0x22ed /* EXT_IO_0 */
+                               VF610_PAD_PTD9__GPIO_88         0x22ed /* EXT_IO_1 */
+                               VF610_PAD_PTD26__GPIO_68        0x22ed /* EXT_IO_2 */
+                       >;
+               };
+
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <
+                               VF610_PAD_PTA24__ESDHC1_CLK     0x31ef
+                               VF610_PAD_PTA25__ESDHC1_CMD     0x31ef
+                               VF610_PAD_PTA26__ESDHC1_DAT0    0x31ef
+                               VF610_PAD_PTA27__ESDHC1_DAT1    0x31ef
+                               VF610_PAD_PTA28__ESDHC1_DATA2   0x31ef
+                               VF610_PAD_PTA29__ESDHC1_DAT3    0x31ef
+                               VF610_PAD_PTB20__GPIO_42        0x219d
+                       >;
+               };
+
+               pinctrl_fec1: fec1grp {
+                       fsl,pins = <
+                               VF610_PAD_PTC9__ENET_RMII1_MDC          0x30d2
+                               VF610_PAD_PTC10__ENET_RMII1_MDIO        0x30d3
+                               VF610_PAD_PTC11__ENET_RMII1_CRS         0x30d1
+                               VF610_PAD_PTC12__ENET_RMII_RXD1         0x30d1
+                               VF610_PAD_PTC13__ENET_RMII1_RXD0        0x30d1
+                               VF610_PAD_PTC14__ENET_RMII1_RXER        0x30d1
+                               VF610_PAD_PTC15__ENET_RMII1_TXD1        0x30d2
+                               VF610_PAD_PTC16__ENET_RMII1_TXD0        0x30d2
+                               VF610_PAD_PTC17__ENET_RMII1_TXEN        0x30d2
+                       >;
+               };
+
+               pinctrl_i2c0: i2c0grp {
+                       fsl,pins = <
+                               VF610_PAD_PTB14__I2C0_SCL               0x37ff
+                               VF610_PAD_PTB15__I2C0_SDA               0x37ff
+                       >;
+               };
+
+               pinctrl_pwm0: pwm0grp {
+                       fsl,pins = <
+                               VF610_PAD_PTB0__FTM0_CH0                0x1182
+                               VF610_PAD_PTB1__FTM0_CH1                0x1182
+                       >;
+               };
+
+               pinctrl_pwm1: pwm1grp {
+                       fsl,pins = <
+                               VF610_PAD_PTB8__FTM1_CH0                0x1182
+                               VF610_PAD_PTB9__FTM1_CH1                0x1182
+                       >;
+               };
+
+               pinctrl_uart0: uart0grp {
+                       fsl,pins = <
+                               VF610_PAD_PTB10__UART0_TX               0x21a2
+                               VF610_PAD_PTB11__UART0_RX               0x21a1
+                       >;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <
+                               VF610_PAD_PTB4__UART1_TX                0x21a2
+                               VF610_PAD_PTB5__UART1_RX                0x21a1
+                       >;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <
+                               VF610_PAD_PTD0__UART2_TX                0x21a2
+                               VF610_PAD_PTD1__UART2_RX                0x21a1
+                               VF610_PAD_PTD2__UART2_RTS               0x21a2
+                               VF610_PAD_PTD3__UART2_CTS               0x21a1
+                       >;
+               };
+
+               pinctrl_usbh1_reg: gpio_usb_vbus {
+                       fsl,pins = <
+                               VF610_PAD_PTD4__GPIO_83                 0x22ed
+                       >;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/vf500-colibri-eval-v3.dts b/arch/arm/boot/dts/vf500-colibri-eval-v3.dts
new file mode 100644 (file)
index 0000000..7fc782c
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "vf500-colibri.dtsi"
+#include "vf-colibri-eval-v3.dtsi"
+
+/ {
+       model = "Toradex Colibri VF50 on Colibri Evaluation Board";
+       compatible = "toradex,vf500-colibri_vf50-on-eval", "toradex,vf500-colibri_vf50", "fsl,vf500";
+};
diff --git a/arch/arm/boot/dts/vf500-colibri.dtsi b/arch/arm/boot/dts/vf500-colibri.dtsi
new file mode 100644 (file)
index 0000000..cee34a3
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Toradex AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "vf500.dtsi"
+#include "vf-colibri.dtsi"
+
+/ {
+       model = "Toradex Colibri VF50 COM";
+       compatible = "toradex,vf610-colibri_vf50", "fsl,vf500";
+
+       memory {
+               reg = <0x80000000 0x8000000>;
+       };
+};
diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi
new file mode 100644 (file)
index 0000000..de67005
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "skeleton.dtsi"
+#include "vfxxx.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               a5_cpu: cpu@0 {
+                       compatible = "arm,cortex-a5";
+                       device_type = "cpu";
+                       reg = <0x0>;
+               };
+       };
+
+       soc {
+               interrupt-parent = <&intc>;
+
+               aips-bus@40000000 {
+
+                       intc: interrupt-controller@40002000 {
+                               compatible = "arm,cortex-a9-gic";
+                               #interrupt-cells = <3>;
+                               interrupt-controller;
+                               reg = <0x40003000 0x1000>,
+                                     <0x40002100 0x100>;
+                       };
+
+                       global_timer: timer@40002200 {
+                               compatible = "arm,cortex-a9-global-timer";
+                               reg = <0x40002200 0x20>;
+                               interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                               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>;
+};
+
+&gpio1 {
+       interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio2 {
+       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio3 {
+       interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio4 {
+       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio5 {
+       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>;
+};
+
+&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>;
+};
index 7fb306679341a5d94a8c3fed2f8a3434d940709d..10ebe99e2751ee404ff7c4aed3a48b30e66c6c2b 100644 (file)
@@ -9,38 +9,9 @@
 
 /dts-v1/;
 #include "vf610-colibri.dtsi"
+#include "vf-colibri-eval-v3.dtsi"
 
 / {
        model = "Toradex Colibri VF61 on Colibri Evaluation Board";
        compatible = "toradex,vf610-colibri_vf61-on-eval", "toradex,vf610-colibri_vf61", "fsl,vf610";
-
-       chosen {
-               bootargs = "console=ttyLP0,115200";
-       };
-};
-
-&esdhc1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1>;
-       bus-width = <4>;
-       status = "okay";
-};
-
-&fec1 {
-       phy-mode = "rmii";
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec1>;
-       status = "okay";
-};
-
-&uart0 {
-       status = "okay";
-};
-
-&uart1 {
-       status = "okay";
-};
-
-&uart2 {
-       status = "okay";
-};
+};
\ No newline at end of file
index 0cd83434b073695e7ae99849443a33e6d19b55b3..19fe045b83342a6ee0f55a02b1490c291b9537dd 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "vf610.dtsi"
+#include "vf-colibri.dtsi"
 
 / {
        model = "Toradex Colibri VF61 COM";
        memory {
                reg = <0x80000000 0x10000000>;
        };
-
-       clocks {
-               enet_ext {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <50000000>;
-               };
-       };
-
-};
-
-&esdhc1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_esdhc1>;
-       bus-width = <4>;
-};
-
-&fec1 {
-       phy-mode = "rmii";
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_fec1>;
 };
 
 &L2 {
        arm,data-latency = <2 1 2>;
        arm,tag-latency = <3 2 3>;
 };
-
-&uart0 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart0>;
-};
-
-&uart1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1>;
-};
-
-&uart2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart2>;
-};
-
-&usbdev0 {
-       disable-over-current;
-       status = "okay";
-};
-
-&usbh1 {
-       disable-over-current;
-       status = "okay";
-};
-
-&iomuxc {
-       vf610-colibri {
-               pinctrl_esdhc1: esdhc1grp {
-                       fsl,pins = <
-                               VF610_PAD_PTA24__ESDHC1_CLK     0x31ef
-                               VF610_PAD_PTA25__ESDHC1_CMD     0x31ef
-                               VF610_PAD_PTA26__ESDHC1_DAT0    0x31ef
-                               VF610_PAD_PTA27__ESDHC1_DAT1    0x31ef
-                               VF610_PAD_PTA28__ESDHC1_DATA2   0x31ef
-                               VF610_PAD_PTA29__ESDHC1_DAT3    0x31ef
-                               VF610_PAD_PTB20__GPIO_42        0x219d
-                       >;
-               };
-
-               pinctrl_fec1: fec1grp {
-                       fsl,pins = <
-                               VF610_PAD_PTC9__ENET_RMII1_MDC          0x30d2
-                               VF610_PAD_PTC10__ENET_RMII1_MDIO        0x30d3
-                               VF610_PAD_PTC11__ENET_RMII1_CRS         0x30d1
-                               VF610_PAD_PTC12__ENET_RMII_RXD1         0x30d1
-                               VF610_PAD_PTC13__ENET_RMII1_RXD0        0x30d1
-                               VF610_PAD_PTC14__ENET_RMII1_RXER        0x30d1
-                               VF610_PAD_PTC15__ENET_RMII1_TXD1        0x30d2
-                               VF610_PAD_PTC16__ENET_RMII1_TXD0        0x30d2
-                               VF610_PAD_PTC17__ENET_RMII1_TXEN        0x30d2
-                       >;
-               };
-
-               pinctrl_uart0: uart0grp {
-                       fsl,pins = <
-                               VF610_PAD_PTB10__UART0_TX               0x21a2
-                               VF610_PAD_PTB11__UART0_RX               0x21a1
-                       >;
-               };
-
-               pinctrl_uart1: uart1grp {
-                       fsl,pins = <
-                               VF610_PAD_PTB4__UART1_TX                0x21a2
-                               VF610_PAD_PTB5__UART1_RX                0x21a1
-                       >;
-               };
-
-               pinctrl_uart2: uart2grp {
-                       fsl,pins = <
-                               VF610_PAD_PTD0__UART2_TX                0x21a2
-                               VF610_PAD_PTD1__UART2_RX                0x21a1
-                               VF610_PAD_PTD2__UART2_RTS               0x21a2
-                               VF610_PAD_PTD3__UART2_CTS               0x21a1
-                       >;
-               };
-       };
-};
index 3fd1b74e1216e1b028751ef64e4f84e7af65bcf3..fd8758b639f5a0c01e252a56772402472e67b04b 100644 (file)
                reg = <0x80000000 0x10000000>;
        };
 
-       clocks {
-               enet_ext {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <50000000>;
-               };
+       enet_ext: enet_ext {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <50000000>;
        };
+};
 
+&clks {
+       clocks = <&sxosc>, <&fxosc>, <&enet_ext>;
+       clock-names = "sxosc", "fxosc", "enet_ext";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <4>;
+       status = "okay";
 };
 
 &fec1 {
 
 &iomuxc {
        vf610-cosmic {
+               pinctrl_esdhc1: esdhc1grp {
+                       fsl,pins = <
+                               VF610_PAD_PTA24__ESDHC1_CLK     0x31ef
+                               VF610_PAD_PTA25__ESDHC1_CMD     0x31ef
+                               VF610_PAD_PTA26__ESDHC1_DAT0    0x31ef
+                               VF610_PAD_PTA27__ESDHC1_DAT1    0x31ef
+                               VF610_PAD_PTA28__ESDHC1_DATA2   0x31ef
+                               VF610_PAD_PTA29__ESDHC1_DAT3    0x31ef
+                               VF610_PAD_PTB28__GPIO_98        0x219d
+                       >;
+               };
+
                pinctrl_fec1: fec1grp {
                        fsl,pins = <
                                VF610_PAD_PTC9__ENET_RMII1_MDC          0x30d2
index 189b6975fe7d99eaca1941bf1e5725a353fbd52c..a0f762159cb26501b517a1af0d529da8abc42283 100644 (file)
                reg = <0x80000000 0x8000000>;
        };
 
-       clocks {
-               audio_ext {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <24576000>;
-               };
+       audio_ext: mclk_osc {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24576000>;
+       };
 
-               enet_ext {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <50000000>;
-               };
+       enet_ext: eth_osc {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <50000000>;
        };
 
        regulators {
        status = "okay";
 };
 
+&clks {
+       clocks = <&sxosc>, <&fxosc>, <&enet_ext>, <&audio_ext>;
+       clock-names = "sxosc", "fxosc", "enet_ext", "audio_ext";
+};
+
 &dspi0 {
        bus-num = <0>;
        pinctrl-names = "default";
        };
 };
 
+&edma0 {
+       status = "okay";
+};
+
 &esdhc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_esdhc1>;
        bus-width = <4>;
+       cd-gpios = <&gpio5 6 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
 
        disable-over-current;
        status = "okay";
 };
+
+&usbmisc0 {
+       status = "okay";
+};
+
+&usbmisc1 {
+       status = "okay";
+};
+
+&usbphy0 {
+       status = "okay";
+};
+
+&usbphy1 {
+       status = "okay";
+};
index 4d2ec32de96f408f5e7b9b6c383cbde06fe566a5..5f8eb1bd782bf01a6454aa7cb63682835c179650 100644 (file)
  * (at your option) any later version.
  */
 
-#include "skeleton.dtsi"
-#include "vf610-pinfunc.h"
-#include <dt-bindings/clock/vf610-clock.h>
-#include <dt-bindings/interrupt-controller/irq.h>
+#include "vf500.dtsi"
 
-/ {
-       aliases {
-               can0 = &can0;
-               can1 = &can1;
-               serial0 = &uart0;
-               serial1 = &uart1;
-               serial2 = &uart2;
-               serial3 = &uart3;
-               serial4 = &uart4;
-               serial5 = &uart5;
-               gpio0 = &gpio1;
-               gpio1 = &gpio2;
-               gpio2 = &gpio3;
-               gpio3 = &gpio4;
-               gpio4 = &gpio5;
-               usbphy0 = &usbphy0;
-               usbphy1 = &usbphy1;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               cpu@0 {
-                       compatible = "arm,cortex-a5";
-                       device_type = "cpu";
-                       reg = <0x0>;
-                       next-level-cache = <&L2>;
-               };
-       };
-
-       clocks {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               sxosc {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <32768>;
-               };
-
-               fxosc {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <24000000>;
-               };
-       };
-
-       soc {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "simple-bus";
-               interrupt-parent = <&intc>;
-               ranges;
-
-               aips0: aips-bus@40000000 {
-                       compatible = "fsl,aips-bus", "simple-bus";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       interrupt-parent = <&intc>;
-                       reg = <0x40000000 0x70000>;
-                       ranges;
-
-                       intc: interrupt-controller@40002000 {
-                               compatible = "arm,cortex-a9-gic";
-                               #interrupt-cells = <3>;
-                               interrupt-controller;
-                               reg = <0x40003000 0x1000>,
-                                     <0x40002100 0x100>;
-                       };
-
-                       L2: l2-cache@40006000 {
-                               compatible = "arm,pl310-cache";
-                               reg = <0x40006000 0x1000>;
-                               cache-unified;
-                               cache-level = <2>;
-                               arm,data-latency = <1 1 1>;
-                               arm,tag-latency = <2 2 2>;
-                       };
-
-                       edma0: dma-controller@40018000 {
-                               #dma-cells = <2>;
-                               compatible = "fsl,vf610-edma";
-                               reg = <0x40018000 0x2000>,
-                                       <0x40024000 0x1000>,
-                                       <0x40025000 0x1000>;
-                               interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
-                                               <0 9 IRQ_TYPE_LEVEL_HIGH>;
-                               interrupt-names = "edma-tx", "edma-err";
-                               dma-channels = <32>;
-                               clock-names = "dmamux0", "dmamux1";
-                               clocks = <&clks VF610_CLK_DMAMUX0>,
-                                       <&clks VF610_CLK_DMAMUX1>;
-                       };
-
-                       can0: flexcan@40020000 {
-                               compatible = "fsl,vf610-flexcan";
-                               reg = <0x40020000 0x4000>;
-                               interrupts = <0 58 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_FLEXCAN0>,
-                                        <&clks VF610_CLK_FLEXCAN0>;
-                               clock-names = "ipg", "per";
-                               status = "disabled";
-                       };
-
-                       uart0: serial@40027000 {
-                               compatible = "fsl,vf610-lpuart";
-                               reg = <0x40027000 0x1000>;
-                               interrupts = <0 61 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_UART0>;
-                               clock-names = "ipg";
-                               dmas = <&edma0 0 2>,
-                                       <&edma0 0 3>;
-                               dma-names = "rx","tx";
-                               status = "disabled";
-                       };
-
-                       uart1: serial@40028000 {
-                               compatible = "fsl,vf610-lpuart";
-                               reg = <0x40028000 0x1000>;
-                               interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_UART1>;
-                               clock-names = "ipg";
-                               dmas = <&edma0 0 4>,
-                                       <&edma0 0 5>;
-                               dma-names = "rx","tx";
-                               status = "disabled";
-                       };
-
-                       uart2: serial@40029000 {
-                               compatible = "fsl,vf610-lpuart";
-                               reg = <0x40029000 0x1000>;
-                               interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_UART2>;
-                               clock-names = "ipg";
-                               dmas = <&edma0 0 6>,
-                                       <&edma0 0 7>;
-                               dma-names = "rx","tx";
-                               status = "disabled";
-                       };
-
-                       uart3: serial@4002a000 {
-                               compatible = "fsl,vf610-lpuart";
-                               reg = <0x4002a000 0x1000>;
-                               interrupts = <0 64 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_UART3>;
-                               clock-names = "ipg";
-                               dmas = <&edma0 0 8>,
-                                       <&edma0 0 9>;
-                               dma-names = "rx","tx";
-                               status = "disabled";
-                       };
-
-                       dspi0: dspi0@4002c000 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,vf610-dspi";
-                               reg = <0x4002c000 0x1000>;
-                               interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_DSPI0>;
-                               clock-names = "dspi";
-                               spi-num-chipselects = <5>;
-                               status = "disabled";
-                       };
-
-                       sai2: sai@40031000 {
-                               compatible = "fsl,vf610-sai";
-                               reg = <0x40031000 0x1000>;
-                               interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_SAI2>;
-                               clock-names = "sai";
-                               dma-names = "tx", "rx";
-                               dmas = <&edma0 0 21>,
-                                       <&edma0 0 20>;
-                               status = "disabled";
-                       };
-
-                       pit: pit@40037000 {
-                               compatible = "fsl,vf610-pit";
-                               reg = <0x40037000 0x1000>;
-                               interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_PIT>;
-                               clock-names = "pit";
-                       };
-
-                       pwm0: pwm@40038000 {
-                               compatible = "fsl,vf610-ftm-pwm";
-                               #pwm-cells = <3>;
-                               reg = <0x40038000 0x1000>;
-                               clock-names = "ftm_sys", "ftm_ext",
-                                             "ftm_fix", "ftm_cnt_clk_en";
-                               clocks = <&clks VF610_CLK_FTM0>,
-                                       <&clks VF610_CLK_FTM0_EXT_SEL>,
-                                       <&clks VF610_CLK_FTM0_FIX_SEL>,
-                                       <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
-                               status = "disabled";
-                       };
-
-                       adc0: adc@4003b000 {
-                               compatible = "fsl,vf610-adc";
-                               reg = <0x4003b000 0x1000>;
-                               interrupts = <0 53 0x04>;
-                               clocks = <&clks VF610_CLK_ADC0>;
-                               clock-names = "adc";
-                               status = "disabled";
-                       };
-
-                       wdog@4003e000 {
-                               compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
-                               reg = <0x4003e000 0x1000>;
-                               clocks = <&clks VF610_CLK_WDT>;
-                               clock-names = "wdog";
-                       };
-
-                       qspi0: quadspi@40044000 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,vf610-qspi";
-                               reg = <0x40044000 0x1000>;
-                               interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_QSPI0_EN>,
-                                       <&clks VF610_CLK_QSPI0>;
-                               clock-names = "qspi_en", "qspi";
-                               status = "disabled";
-                       };
-
-                       iomuxc: iomuxc@40048000 {
-                               compatible = "fsl,vf610-iomuxc";
-                               reg = <0x40048000 0x1000>;
-                               #gpio-range-cells = <3>;
-                       };
-
-                       gpio1: gpio@40049000 {
-                               compatible = "fsl,vf610-gpio";
-                               reg = <0x40049000 0x1000 0x400ff000 0x40>;
-                               interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               gpio-ranges = <&iomuxc 0 0 32>;
-                       };
-
-                       gpio2: gpio@4004a000 {
-                               compatible = "fsl,vf610-gpio";
-                               reg = <0x4004a000 0x1000 0x400ff040 0x40>;
-                               interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               gpio-ranges = <&iomuxc 0 32 32>;
-                       };
-
-                       gpio3: gpio@4004b000 {
-                               compatible = "fsl,vf610-gpio";
-                               reg = <0x4004b000 0x1000 0x400ff080 0x40>;
-                               interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               gpio-ranges = <&iomuxc 0 64 32>;
-                       };
-
-                       gpio4: gpio@4004c000 {
-                               compatible = "fsl,vf610-gpio";
-                               reg = <0x4004c000 0x1000 0x400ff0c0 0x40>;
-                               interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               gpio-ranges = <&iomuxc 0 96 32>;
-                       };
-
-                       gpio5: gpio@4004d000 {
-                               compatible = "fsl,vf610-gpio";
-                               reg = <0x4004d000 0x1000 0x400ff100 0x40>;
-                               interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               gpio-ranges = <&iomuxc 0 128 7>;
-                       };
-
-                       anatop: anatop@40050000 {
-                               compatible = "fsl,vf610-anatop", "syscon";
-                               reg = <0x40050000 0x400>;
-                       };
-
-                       usbphy0: usbphy@40050800 {
-                               compatible = "fsl,vf610-usbphy";
-                               reg = <0x40050800 0x400>;
-                               interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_USBPHY0>;
-                               fsl,anatop = <&anatop>;
-                       };
-
-                       usbphy1: usbphy@40050c00 {
-                               compatible = "fsl,vf610-usbphy";
-                               reg = <0x40050c00 0x400>;
-                               interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_USBPHY1>;
-                               fsl,anatop = <&anatop>;
-                       };
-
-                       i2c0: i2c@40066000 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,vf610-i2c";
-                               reg = <0x40066000 0x1000>;
-                               interrupts =<0 71 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_I2C0>;
-                               clock-names = "ipg";
-                               dmas = <&edma0 0 50>,
-                                       <&edma0 0 51>;
-                               dma-names = "rx","tx";
-                               status = "disabled";
-                       };
-
-                       clks: ccm@4006b000 {
-                               compatible = "fsl,vf610-ccm";
-                               reg = <0x4006b000 0x1000>;
-                               #clock-cells = <1>;
-                       };
-
-                       usbdev0: usb@40034000 {
-                               compatible = "fsl,vf610-usb", "fsl,imx27-usb";
-                               reg = <0x40034000 0x800>;
-                               interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_USBC0>;
-                               fsl,usbphy = <&usbphy0>;
-                               fsl,usbmisc = <&usbmisc0 0>;
-                               dr_mode = "peripheral";
-                               status = "disabled";
-                       };
-
-                       usbmisc0: usb@40034800 {
-                               #index-cells = <1>;
-                               compatible = "fsl,vf610-usbmisc";
-                               reg = <0x40034800 0x200>;
-                               clocks = <&clks VF610_CLK_USBC0>;
-                       };
-               };
-
-               aips1: aips-bus@40080000 {
-                       compatible = "fsl,aips-bus", "simple-bus";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       reg = <0x40080000 0x80000>;
-                       ranges;
-
-                       edma1: dma-controller@40098000 {
-                               #dma-cells = <2>;
-                               compatible = "fsl,vf610-edma";
-                               reg = <0x40098000 0x2000>,
-                                       <0x400a1000 0x1000>,
-                                       <0x400a2000 0x1000>;
-                               interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>,
-                                               <0 11 IRQ_TYPE_LEVEL_HIGH>;
-                               interrupt-names = "edma-tx", "edma-err";
-                               dma-channels = <32>;
-                               clock-names = "dmamux0", "dmamux1";
-                               clocks = <&clks VF610_CLK_DMAMUX2>,
-                                       <&clks VF610_CLK_DMAMUX3>;
-                       };
-
-                       uart4: serial@400a9000 {
-                               compatible = "fsl,vf610-lpuart";
-                               reg = <0x400a9000 0x1000>;
-                               interrupts = <0 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 = <0 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 = <0 54 0x04>;
-                               clocks = <&clks VF610_CLK_ADC1>;
-                               clock-names = "adc";
-                               status = "disabled";
-                       };
-
-                       esdhc1: esdhc@400b2000 {
-                               compatible = "fsl,imx53-esdhc";
-                               reg = <0x400b2000 0x1000>;
-                               interrupts = <0 28 0x04>;
-                               clocks = <&clks VF610_CLK_IPG_BUS>,
-                                       <&clks VF610_CLK_PLATFORM_BUS>,
-                                       <&clks VF610_CLK_ESDHC1>;
-                               clock-names = "ipg", "ahb", "per";
-                               status = "disabled";
-                       };
-
-                       usbh1: usb@400b4000 {
-                               compatible = "fsl,vf610-usb", "fsl,imx27-usb";
-                               reg = <0x400b4000 0x800>;
-                               interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_USBC1>;
-                               fsl,usbphy = <&usbphy1>;
-                               fsl,usbmisc = <&usbmisc1 0>;
-                               dr_mode = "host";
-                               status = "disabled";
-                       };
-
-                       usbmisc1: usb@400b4800 {
-                               #index-cells = <1>;
-                               compatible = "fsl,vf610-usbmisc";
-                               reg = <0x400b4800 0x200>;
-                               clocks = <&clks VF610_CLK_USBC1>;
-                       };
-
-                       ftm: ftm@400b8000 {
-                               compatible = "fsl,ftm-timer";
-                               reg = <0x400b8000 0x1000 0x400b9000 0x1000>;
-                               interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>;
-                               clock-names = "ftm-evt", "ftm-src",
-                                       "ftm-evt-counter-en", "ftm-src-counter-en";
-                               clocks = <&clks VF610_CLK_FTM2>,
-                                       <&clks VF610_CLK_FTM3>,
-                                       <&clks VF610_CLK_FTM2_EXT_FIX_EN>,
-                                       <&clks VF610_CLK_FTM3_EXT_FIX_EN>;
-                               status = "disabled";
-                       };
-
-                       fec0: ethernet@400d0000 {
-                               compatible = "fsl,mvf600-fec";
-                               reg = <0x400d0000 0x1000>;
-                               interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_ENET0>,
-                                       <&clks VF610_CLK_ENET0>,
-                                       <&clks VF610_CLK_ENET>;
-                               clock-names = "ipg", "ahb", "ptp";
-                               status = "disabled";
-                       };
-
-                       fec1: ethernet@400d1000 {
-                               compatible = "fsl,mvf600-fec";
-                               reg = <0x400d1000 0x1000>;
-                               interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_ENET1>,
-                                       <&clks VF610_CLK_ENET1>,
-                                       <&clks VF610_CLK_ENET>;
-                               clock-names = "ipg", "ahb", "ptp";
-                               status = "disabled";
-                       };
-
-                       can1: flexcan@400d4000 {
-                               compatible = "fsl,vf610-flexcan";
-                               reg = <0x400d4000 0x4000>;
-                               interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_FLEXCAN1>,
-                                        <&clks VF610_CLK_FLEXCAN1>;
-                               clock-names = "ipg", "per";
-                               status = "disabled";
-                       };
+&a5_cpu {
+       next-level-cache = <&L2>;
+};
 
-               };
+&aips0 {
+       L2: l2-cache@40006000 {
+               compatible = "arm,pl310-cache";
+               reg = <0x40006000 0x1000>;
+               cache-unified;
+               cache-level = <2>;
+               arm,data-latency = <1 1 1>;
+               arm,tag-latency = <2 2 2>;
        };
 };
diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
new file mode 100644 (file)
index 0000000..505969a
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "vf610-pinfunc.h"
+#include <dt-bindings/clock/vf610-clock.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       aliases {
+               can0 = &can0;
+               can1 = &can1;
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
+               serial4 = &uart4;
+               serial5 = &uart5;
+               gpio0 = &gpio1;
+               gpio1 = &gpio2;
+               gpio2 = &gpio3;
+               gpio3 = &gpio4;
+               gpio4 = &gpio5;
+               usbphy0 = &usbphy0;
+               usbphy1 = &usbphy1;
+       };
+
+       fxosc: fxosc {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24000000>;
+       };
+
+       sxosc: sxosc {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               ranges;
+
+               aips0: aips-bus@40000000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       edma0: dma-controller@40018000 {
+                               #dma-cells = <2>;
+                               compatible = "fsl,vf610-edma";
+                               reg = <0x40018000 0x2000>,
+                                       <0x40024000 0x1000>,
+                                       <0x40025000 0x1000>;
+                               dma-channels = <32>;
+                               clock-names = "dmamux0", "dmamux1";
+                               clocks = <&clks VF610_CLK_DMAMUX0>,
+                                       <&clks VF610_CLK_DMAMUX1>;
+                               status = "disabled";
+                       };
+
+                       can0: flexcan@40020000 {
+                               compatible = "fsl,vf610-flexcan";
+                               reg = <0x40020000 0x4000>;
+                               clocks = <&clks VF610_CLK_FLEXCAN0>,
+                                        <&clks VF610_CLK_FLEXCAN0>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+                       uart0: serial@40027000 {
+                               compatible = "fsl,vf610-lpuart";
+                               reg = <0x40027000 0x1000>;
+                               clocks = <&clks VF610_CLK_UART0>;
+                               clock-names = "ipg";
+                               dmas = <&edma0 0 2>,
+                                       <&edma0 0 3>;
+                               dma-names = "rx","tx";
+                               status = "disabled";
+                       };
+
+                       uart1: serial@40028000 {
+                               compatible = "fsl,vf610-lpuart";
+                               reg = <0x40028000 0x1000>;
+                               clocks = <&clks VF610_CLK_UART1>;
+                               clock-names = "ipg";
+                               dmas = <&edma0 0 4>,
+                                       <&edma0 0 5>;
+                               dma-names = "rx","tx";
+                               status = "disabled";
+                       };
+
+                       uart2: serial@40029000 {
+                               compatible = "fsl,vf610-lpuart";
+                               reg = <0x40029000 0x1000>;
+                               clocks = <&clks VF610_CLK_UART2>;
+                               clock-names = "ipg";
+                               dmas = <&edma0 0 6>,
+                                       <&edma0 0 7>;
+                               dma-names = "rx","tx";
+                               status = "disabled";
+                       };
+
+                       uart3: serial@4002a000 {
+                               compatible = "fsl,vf610-lpuart";
+                               reg = <0x4002a000 0x1000>;
+                               clocks = <&clks VF610_CLK_UART3>;
+                               clock-names = "ipg";
+                               dmas = <&edma0 0 8>,
+                                       <&edma0 0 9>;
+                               dma-names = "rx","tx";
+                               status = "disabled";
+                       };
+
+                       dspi0: dspi0@4002c000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,vf610-dspi";
+                               reg = <0x4002c000 0x1000>;
+                               clocks = <&clks VF610_CLK_DSPI0>;
+                               clock-names = "dspi";
+                               spi-num-chipselects = <5>;
+                               status = "disabled";
+                       };
+
+                       sai2: sai@40031000 {
+                               compatible = "fsl,vf610-sai";
+                               reg = <0x40031000 0x1000>;
+                               clocks = <&clks VF610_CLK_SAI2>;
+                               clock-names = "sai";
+                               dma-names = "tx", "rx";
+                               dmas = <&edma0 0 21>,
+                                       <&edma0 0 20>;
+                               status = "disabled";
+                       };
+
+                       pit: pit@40037000 {
+                               compatible = "fsl,vf610-pit";
+                               reg = <0x40037000 0x1000>;
+                               clocks = <&clks VF610_CLK_PIT>;
+                               clock-names = "pit";
+                       };
+
+                       pwm0: pwm@40038000 {
+                               compatible = "fsl,vf610-ftm-pwm";
+                               #pwm-cells = <3>;
+                               reg = <0x40038000 0x1000>;
+                               clock-names = "ftm_sys", "ftm_ext",
+                                             "ftm_fix", "ftm_cnt_clk_en";
+                               clocks = <&clks VF610_CLK_FTM0>,
+                                       <&clks VF610_CLK_FTM0_EXT_SEL>,
+                                       <&clks VF610_CLK_FTM0_FIX_SEL>,
+                                       <&clks VF610_CLK_FTM0_EXT_FIX_EN>;
+                               status = "disabled";
+                       };
+
+                       pwm1: pwm@40039000 {
+                               compatible = "fsl,vf610-ftm-pwm";
+                               #pwm-cells = <3>;
+                               reg = <0x40039000 0x1000>;
+                               clock-names = "ftm_sys", "ftm_ext",
+                                             "ftm_fix", "ftm_cnt_clk_en";
+                               clocks = <&clks VF610_CLK_FTM1>,
+                                       <&clks VF610_CLK_FTM1_EXT_SEL>,
+                                       <&clks VF610_CLK_FTM1_FIX_SEL>,
+                                       <&clks VF610_CLK_FTM1_EXT_FIX_EN>;
+                               status = "disabled";
+                       };
+
+                       adc0: adc@4003b000 {
+                               compatible = "fsl,vf610-adc";
+                               reg = <0x4003b000 0x1000>;
+                               clocks = <&clks VF610_CLK_ADC0>;
+                               clock-names = "adc";
+                               status = "disabled";
+                       };
+
+                       wdog@4003e000 {
+                               compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
+                               reg = <0x4003e000 0x1000>;
+                               clocks = <&clks VF610_CLK_WDT>;
+                               clock-names = "wdog";
+                               status = "disabled";
+                       };
+
+                       qspi0: quadspi@40044000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,vf610-qspi";
+                               reg = <0x40044000 0x1000>;
+                               clocks = <&clks VF610_CLK_QSPI0_EN>,
+                                       <&clks VF610_CLK_QSPI0>;
+                               clock-names = "qspi_en", "qspi";
+                               status = "disabled";
+                       };
+
+                       iomuxc: iomuxc@40048000 {
+                               compatible = "fsl,vf610-iomuxc";
+                               reg = <0x40048000 0x1000>;
+                               #gpio-range-cells = <3>;
+                       };
+
+                       gpio1: gpio@40049000 {
+                               compatible = "fsl,vf610-gpio";
+                               reg = <0x40049000 0x1000 0x400ff000 0x40>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 0 32>;
+                       };
+
+                       gpio2: gpio@4004a000 {
+                               compatible = "fsl,vf610-gpio";
+                               reg = <0x4004a000 0x1000 0x400ff040 0x40>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 32 32>;
+                       };
+
+                       gpio3: gpio@4004b000 {
+                               compatible = "fsl,vf610-gpio";
+                               reg = <0x4004b000 0x1000 0x400ff080 0x40>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 64 32>;
+                       };
+
+                       gpio4: gpio@4004c000 {
+                               compatible = "fsl,vf610-gpio";
+                               reg = <0x4004c000 0x1000 0x400ff0c0 0x40>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 96 32>;
+                       };
+
+                       gpio5: gpio@4004d000 {
+                               compatible = "fsl,vf610-gpio";
+                               reg = <0x4004d000 0x1000 0x400ff100 0x40>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               gpio-ranges = <&iomuxc 0 128 7>;
+                       };
+
+                       anatop: anatop@40050000 {
+                               compatible = "fsl,vf610-anatop", "syscon";
+                               reg = <0x40050000 0x400>;
+                       };
+
+                       usbphy0: usbphy@40050800 {
+                               compatible = "fsl,vf610-usbphy";
+                               reg = <0x40050800 0x400>;
+                               clocks = <&clks VF610_CLK_USBPHY0>;
+                               fsl,anatop = <&anatop>;
+                               status = "disabled";
+                       };
+
+                       usbphy1: usbphy@40050c00 {
+                               compatible = "fsl,vf610-usbphy";
+                               reg = <0x40050c00 0x400>;
+                               clocks = <&clks VF610_CLK_USBPHY1>;
+                               fsl,anatop = <&anatop>;
+                               status = "disabled";
+                       };
+
+                       i2c0: i2c@40066000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,vf610-i2c";
+                               reg = <0x40066000 0x1000>;
+                               clocks = <&clks VF610_CLK_I2C0>;
+                               clock-names = "ipg";
+                               dmas = <&edma0 0 50>,
+                                       <&edma0 0 51>;
+                               dma-names = "rx","tx";
+                               status = "disabled";
+                       };
+
+                       clks: ccm@4006b000 {
+                               compatible = "fsl,vf610-ccm";
+                               reg = <0x4006b000 0x1000>;
+                               clocks = <&sxosc>, <&fxosc>;
+                               clock-names = "sxosc", "fxosc";
+                               #clock-cells = <1>;
+                       };
+
+                       usbdev0: usb@40034000 {
+                               compatible = "fsl,vf610-usb", "fsl,imx27-usb";
+                               reg = <0x40034000 0x800>;
+                               clocks = <&clks VF610_CLK_USBC0>;
+                               fsl,usbphy = <&usbphy0>;
+                               fsl,usbmisc = <&usbmisc0 0>;
+                               dr_mode = "peripheral";
+                               status = "disabled";
+                       };
+
+                       usbmisc0: usb@40034800 {
+                               #index-cells = <1>;
+                               compatible = "fsl,vf610-usbmisc";
+                               reg = <0x40034800 0x200>;
+                               clocks = <&clks VF610_CLK_USBC0>;
+                               status = "disabled";
+                       };
+               };
+
+               aips1: aips-bus@40080000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       edma1: dma-controller@40098000 {
+                               #dma-cells = <2>;
+                               compatible = "fsl,vf610-edma";
+                               reg = <0x40098000 0x2000>,
+                                       <0x400a1000 0x1000>,
+                                       <0x400a2000 0x1000>;
+                               dma-channels = <32>;
+                               clock-names = "dmamux0", "dmamux1";
+                               clocks = <&clks VF610_CLK_DMAMUX2>,
+                                       <&clks VF610_CLK_DMAMUX3>;
+                               status = "disabled";
+                       };
+
+                       uart4: serial@400a9000 {
+                               compatible = "fsl,vf610-lpuart";
+                               reg = <0x400a9000 0x1000>;
+                               clocks = <&clks VF610_CLK_UART4>;
+                               clock-names = "ipg";
+                               status = "disabled";
+                       };
+
+                       uart5: serial@400aa000 {
+                               compatible = "fsl,vf610-lpuart";
+                               reg = <0x400aa000 0x1000>;
+                               clocks = <&clks VF610_CLK_UART5>;
+                               clock-names = "ipg";
+                               status = "disabled";
+                       };
+
+                       adc1: adc@400bb000 {
+                               compatible = "fsl,vf610-adc";
+                               reg = <0x400bb000 0x1000>;
+                               clocks = <&clks VF610_CLK_ADC1>;
+                               clock-names = "adc";
+                               status = "disabled";
+                       };
+
+                       esdhc1: esdhc@400b2000 {
+                               compatible = "fsl,imx53-esdhc";
+                               reg = <0x400b2000 0x1000>;
+                               clocks = <&clks VF610_CLK_IPG_BUS>,
+                                       <&clks VF610_CLK_PLATFORM_BUS>,
+                                       <&clks VF610_CLK_ESDHC1>;
+                               clock-names = "ipg", "ahb", "per";
+                               status = "disabled";
+                       };
+
+                       usbh1: usb@400b4000 {
+                               compatible = "fsl,vf610-usb", "fsl,imx27-usb";
+                               reg = <0x400b4000 0x800>;
+                               clocks = <&clks VF610_CLK_USBC1>;
+                               fsl,usbphy = <&usbphy1>;
+                               fsl,usbmisc = <&usbmisc1 0>;
+                               dr_mode = "host";
+                               status = "disabled";
+                       };
+
+                       usbmisc1: usb@400b4800 {
+                               #index-cells = <1>;
+                               compatible = "fsl,vf610-usbmisc";
+                               reg = <0x400b4800 0x200>;
+                               clocks = <&clks VF610_CLK_USBC1>;
+                               status = "disabled";
+                       };
+
+                       ftm: ftm@400b8000 {
+                               compatible = "fsl,ftm-timer";
+                               reg = <0x400b8000 0x1000 0x400b9000 0x1000>;
+                               clock-names = "ftm-evt", "ftm-src",
+                                       "ftm-evt-counter-en", "ftm-src-counter-en";
+                               clocks = <&clks VF610_CLK_FTM2>,
+                                       <&clks VF610_CLK_FTM3>,
+                                       <&clks VF610_CLK_FTM2_EXT_FIX_EN>,
+                                       <&clks VF610_CLK_FTM3_EXT_FIX_EN>;
+                               status = "disabled";
+                       };
+
+                       fec0: ethernet@400d0000 {
+                               compatible = "fsl,mvf600-fec";
+                               reg = <0x400d0000 0x1000>;
+                               clocks = <&clks VF610_CLK_ENET0>,
+                                       <&clks VF610_CLK_ENET0>,
+                                       <&clks VF610_CLK_ENET>;
+                               clock-names = "ipg", "ahb", "ptp";
+                               status = "disabled";
+                       };
+
+                       fec1: ethernet@400d1000 {
+                               compatible = "fsl,mvf600-fec";
+                               reg = <0x400d1000 0x1000>;
+                               clocks = <&clks VF610_CLK_ENET1>,
+                                       <&clks VF610_CLK_ENET1>,
+                                       <&clks VF610_CLK_ENET>;
+                               clock-names = "ipg", "ahb", "ptp";
+                               status = "disabled";
+                       };
+
+                       can1: flexcan@400d4000 {
+                               compatible = "fsl,vf610-flexcan";
+                               reg = <0x400d4000 0x4000>;
+                               clocks = <&clks VF610_CLK_FLEXCAN1>,
+                                        <&clks VF610_CLK_FLEXCAN1>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+
+               };
+       };
+};
index 24036c440440c0f13cbcbc54ac0c034dcc5653cc..ee3e5d675b053fca340ec8a3ca98c0cc012f044c 100644 (file)
@@ -30,7 +30,6 @@
                                /* kHz    uV */
                                666667  1000000
                                333334  1000000
-                               222223  1000000
                        >;
                };
 
@@ -65,7 +64,7 @@
                interrupt-parent = <&intc>;
                ranges;
 
-               adc@f8007100 {
+               adc: adc@f8007100 {
                        compatible = "xlnx,zynq-xadc-1.00.a";
                        reg = <0xf8007100 0x20>;
                        interrupts = <0 7 4>;
                              <0xF8F00100 0x100>;
                };
 
-               L2: cache-controller {
+               L2: cache-controller@f8f02000 {
                        compatible = "arm,pl310-cache";
                        reg = <0xF8F02000 0x1000>;
                        arm,data-latency = <3 2 2>;
                        cache-level = <2>;
                };
 
-               memory-controller@f8006000 {
+               mc: memory-controller@f8006000 {
                        compatible = "xlnx,zynq-ddrc-a05";
                        reg = <0xf8006000 0x1000>;
-               } ;
+               };
 
                uart0: serial@e0000000 {
                        compatible = "xlnx,xuartps", "cdns,uart-r1p8";
 
                gem0: ethernet@e000b000 {
                        compatible = "cdns,gem";
-                       reg = <0xe000b000 0x4000>;
+                       reg = <0xe000b000 0x1000>;
                        status = "disabled";
                        interrupts = <0 22 4>;
                        clocks = <&clkc 30>, <&clkc 30>, <&clkc 13>;
 
                gem1: ethernet@e000c000 {
                        compatible = "cdns,gem";
-                       reg = <0xe000c000 0x4000>;
+                       reg = <0xe000c000 0x1000>;
                        status = "disabled";
                        interrupts = <0 45 4>;
                        clocks = <&clkc 31>, <&clkc 31>, <&clkc 14>;
                        clkc: clkc@100 {
                                #clock-cells = <1>;
                                compatible = "xlnx,ps7-clkc";
-                               ps-clk-frequency = <33333333>;
                                fclk-enable = <0>;
                                clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
                                                "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
                        reg = <0xf8f00600 0x20>;
                        clocks = <&clkc 4>;
                };
+
+               watchdog0: watchdog@f8005000 {
+                       clocks = <&clkc 45>;
+                       compatible = "xlnx,zynq-wdt-r1p2";
+                       device_type = "watchdog";
+                       interrupt-parent = <&intc>;
+                       interrupts = <0 9 1>;
+                       reg = <0xf8005000 0x1000>;
+                       reset = <0>;
+                       timeout-sec = <10>;
+               };
        };
 };
index e1f51ca127fe835664f0609b19a1ef428de62ca8..ab1dc0a56cddc0209518842436d37403cb927278 100644 (file)
        };
 };
 
+&clkc {
+       fclk-enable = <0xf>;
+       ps-clk-frequency = <33333333>;
+};
+
 &gem0 {
        status = "okay";
        phy-mode = "rgmii-id";
index 94e2cda6f9b6f8bbf5188e38b9878ad1d22da85c..280f02dd4ddcb99e530bcd9c957ac2d2ad29456d 100644 (file)
        status = "okay";
 };
 
+&clkc {
+       ps-clk-frequency = <33333333>;
+};
+
 &gem0 {
        status = "okay";
        phy-mode = "rgmii-id";
index a8bbdfbc7093caad3cdf0ace86052d29a38a0150..34f7812d2ee86f993c6163f3719d8979b0d6ea7d 100644 (file)
 
 };
 
+&clkc {
+       ps-clk-frequency = <33333333>;
+};
+
 &gem0 {
        status = "okay";
        phy-mode = "rgmii-id";
index 697779a353edcda3852fbd381ab2efdb6b40779b..1c7cc990b47a6229c87759f24d6148b68f531154 100644 (file)
 
 };
 
+&clkc {
+       ps-clk-frequency = <33333333>;
+};
+
 &gem0 {
        status = "okay";
        phy-mode = "rgmii-id";
diff --git a/arch/arm/boot/dts/zynq-zybo.dts b/arch/arm/boot/dts/zynq-zybo.dts
new file mode 100644 (file)
index 0000000..a9a12ce
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (C) 2011 - 2014 Xilinx
+ *  Copyright (C) 2012 National Instruments Corp.
+ *
+ * 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.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+       model = "Zynq ZYBO Development Board";
+       compatible = "digilent,zynq-zybo", "xlnx,zynq-7000";
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x20000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyPS0,115200 earlyprintk";
+       };
+
+};
+
+&clkc {
+       ps-clk-frequency = <50000000>;
+};
+
+&gem0 {
+       status = "okay";
+       phy-mode = "rgmii-id";
+       phy-handle = <&ethernet_phy>;
+
+       ethernet_phy: ethernet-phy@0 {
+               reg = <0>;
+       };
+};
+
+&sdhci0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
index d86771abbf57a3760e65c4718a4fbfc6bad8359b..5662a872689b39c04e09eef6ac80b9f81d168107 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/edma.h>
+#include <linux/dma-mapping.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_dma.h>
@@ -244,6 +245,8 @@ struct edma {
        /* list of channels with no even trigger; terminated by "-1" */
        const s8        *noevent;
 
+       struct edma_soc_info *info;
+
        /* The edma_inuse bit for each PaRAM slot is clear unless the
         * channel is in use ... by ARM or DSP, for QDMA, or whatever.
         */
@@ -295,7 +298,7 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
                        ~(0x7 << bit), queue_no << bit);
 }
 
-static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
+static void assign_priority_to_queue(unsigned ctlr, int queue_no,
                int priority)
 {
        int bit = queue_no * 4;
@@ -314,7 +317,7 @@ static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
  * included in that particular EDMA variant (Eg : dm646x)
  *
  */
-static void __init map_dmach_param(unsigned ctlr)
+static void map_dmach_param(unsigned ctlr)
 {
        int i;
        for (i = 0; i < EDMA_MAX_DMACH; i++)
@@ -1623,6 +1626,11 @@ static int edma_probe(struct platform_device *pdev)
        struct device_node      *node = pdev->dev.of_node;
        struct device           *dev = &pdev->dev;
        int                     ret;
+       struct platform_device_info edma_dev_info = {
+               .name = "edma-dma-engine",
+               .dma_mask = DMA_BIT_MASK(32),
+               .parent = &pdev->dev,
+       };
 
        if (node) {
                /* Check if this is a second instance registered */
@@ -1792,15 +1800,66 @@ static int edma_probe(struct platform_device *pdev)
                        edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
                        edma_write_array(j, EDMA_QRAE, i, 0x0);
                }
+               edma_cc[j]->info = info[j];
                arch_num_cc++;
+
+               edma_dev_info.id = j;
+               platform_device_register_full(&edma_dev_info);
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int edma_pm_resume(struct device *dev)
+{
+       int i, j;
+
+       for (j = 0; j < arch_num_cc; j++) {
+               struct edma *cc = edma_cc[j];
+
+               s8 (*queue_priority_mapping)[2];
+
+               queue_priority_mapping = cc->info->queue_priority_mapping;
+
+               /* Event queue priority mapping */
+               for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+                       assign_priority_to_queue(j,
+                                                queue_priority_mapping[i][0],
+                                                queue_priority_mapping[i][1]);
+
+               /*
+                * Map the channel to param entry if channel mapping logic
+                * exist
+                */
+               if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
+                       map_dmach_param(j);
+
+               for (i = 0; i < cc->num_channels; i++) {
+                       if (test_bit(i, cc->edma_inuse)) {
+                               /* ensure access through shadow region 0 */
+                               edma_or_array2(j, EDMA_DRAE, 0, i >> 5,
+                                              BIT(i & 0x1f));
+
+                               setup_dma_interrupt(i,
+                                                   cc->intr_data[i].callback,
+                                                   cc->intr_data[i].data);
+                       }
+               }
        }
 
        return 0;
 }
+#endif
+
+static const struct dev_pm_ops edma_pm_ops = {
+       SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, edma_pm_resume)
+};
 
 static struct platform_driver edma_driver = {
        .driver = {
                .name   = "edma",
+               .pm     = &edma_pm_ops,
                .of_match_table = edma_of_ids,
        },
        .probe = edma_probe,
index b54b28fc5a70579e62aa6e3d66c44562bcffbde2..db81d8ce4c03bb1bc175a4c9e3e2fbd0d5013566 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_ARM_APPENDED_DTB=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_BINFMT_MISC=y
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
index 3b515c17948771b17a11b7d9158de203f9f91723..a67375f24b2184d9b159fa6d8b11f5ebf1e57679 100644 (file)
@@ -80,6 +80,7 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 CONFIG_MACB=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_DM9000=y
 # CONFIG_NET_VENDOR_FARADAY is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -113,6 +114,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=272
 CONFIG_INPUT_JOYDEV=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT1070=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
@@ -186,6 +188,7 @@ CONFIG_IIO=y
 CONFIG_AT91_ADC=y
 CONFIG_PWM=y
 CONFIG_PWM_ATMEL=y
+CONFIG_PWM_ATMEL_TCB=y
 CONFIG_EXT4_FS=y
 CONFIG_FANOTIFY=y
 CONFIG_VFAT_FS=y
diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig
deleted file mode 100644 (file)
index bf05771..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_USER_NS=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_FORCE_LOAD=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91RM9200=y
-CONFIG_MACH_ONEARM=y
-CONFIG_MACH_AT91RM9200EK=y
-CONFIG_MACH_CSB337=y
-CONFIG_MACH_CSB637=y
-CONFIG_MACH_CARMEVA=y
-CONFIG_MACH_ATEB9200=y
-CONFIG_MACH_KB9200=y
-CONFIG_MACH_PICOTUX2XX=y
-CONFIG_MACH_KAFA=y
-CONFIG_MACH_ECBAT91=y
-CONFIG_MACH_YL9200=y
-CONFIG_MACH_CPUAT91=y
-CONFIG_MACH_ECO920=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
-CONFIG_AT91_TIMER_HZ=100
-# CONFIG_ARM_THUMB is not set
-CONFIG_PCCARD=y
-CONFIG_AT91_CF=y
-CONFIG_AEABI=y
-# CONFIG_COMPACTION is not set
-CONFIG_ZBOOT_ROM_TEXT=0x10000000
-CONFIG_ZBOOT_ROM_BSS=0x20040000
-CONFIG_KEXEC=y
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_MISC=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_IP_PNP_BOOTP=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_DIAG is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD 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_JEDECPROBE=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_COMPLEX_MAPPINGS=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PLATRAM=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_NAND_PLATFORM=y
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_GLUEBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_NETDEVICES=y
-CONFIG_MII=y
-CONFIG_ARM_AT91_ETHER=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_MICREL_PHY=y
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91RM9200_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_FB_S1D13XXX=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_LOGO=y
-CONFIG_USB=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_AT91=y
-CONFIG_USB_G_SERIAL=y
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_UBIFS_FS=y
-CONFIG_UBIFS_FS_ADVANCED_COMPR=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_XZ_DEC_ARMTHUMB=y
diff --git a/arch/arm/configs/at91sam9260_9g20_defconfig b/arch/arm/configs/at91sam9260_9g20_defconfig
deleted file mode 100644 (file)
index 3ada05d..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-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_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_AT91SAM9260EK=y
-CONFIG_MACH_CAM60=y
-CONFIG_MACH_SAM9_L9260=y
-CONFIG_MACH_AFEB9260=y
-CONFIG_MACH_CPU9260=y
-CONFIG_MACH_FLEXIBITY=y
-CONFIG_MACH_AT91SAM9G20EK=y
-CONFIG_MACH_AT91SAM9G20EK_2MMC=y
-CONFIG_MACH_CPU9G20=y
-CONFIG_MACH_ACMENETUSFOXG20=y
-CONFIG_MACH_PORTUXG20=y
-CONFIG_MACH_STAMP9G20=y
-CONFIG_MACH_PCONTROL_G20=y
-CONFIG_MACH_GSIA18S=y
-CONFIG_MACH_SNAPPER_9260=y
-CONFIG_MACH_AT91SAM9_DT=y
-CONFIG_AT91_SLOW_CLOCK=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_ARM_ATAG_DTB_COMPAT=y
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_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_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_UBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_EEPROM_AT25=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_MACB=y
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_MICROCHIP is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SMSC is not set
-# CONFIG_NET_VENDOR_STMICRO is not set
-CONFIG_SMSC_PHY=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_SPI_SPIDEV=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_POWER_RESET=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PROCFS is not set
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_AT91=y
-CONFIG_USB_G_SERIAL=y
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=y
-CONFIG_MMC_SPI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_RV3029C2=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_IIO=y
-CONFIG_AT91_ADC=y
-CONFIG_EXT4_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_UBIFS_FS=y
-CONFIG_UBIFS_FS_ADVANCED_COMPR=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
diff --git a/arch/arm/configs/at91sam9261_9g10_defconfig b/arch/arm/configs/at91sam9261_9g10_defconfig
deleted file mode 100644 (file)
index 0c505d8..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_KERNEL_LZMA=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_NAMESPACES=y
-CONFIG_EMBEDDED=y
-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_AT91=y
-CONFIG_ARCH_AT91SAM9261=y
-CONFIG_MACH_AT91SAM9261EK=y
-CONFIG_MACH_AT91SAM9G10EK=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-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_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_CFG80211=y
-CONFIG_MAC80211=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_GLUEBI=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_NETDEVICES=y
-CONFIG_DM9000=y
-CONFIG_USB_ZD1201=m
-CONFIG_RTL8187=m
-CONFIG_LIBERTAS=m
-CONFIG_LIBERTAS_USB=m
-CONFIG_LIBERTAS_SDIO=m
-CONFIG_LIBERTAS_SPI=m
-CONFIG_RT2X00=m
-CONFIG_RT2500USB=m
-CONFIG_RT73USB=m
-CONFIG_ZD1211RW=m
-CONFIG_INPUT_POLLDEV=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_POWER_RESET=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-# CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_ATMEL_LCDC=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_LOGO=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-# 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_AT73C213=y
-CONFIG_SND_USB_AUDIO=m
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_AT91=y
-CONFIG_USB_G_SERIAL=y
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_UBIFS_FS=y
-CONFIG_UBIFS_FS_ADVANCED_COMPR=y
-CONFIG_SQUASHFS=y
-CONFIG_SQUASHFS_LZO=y
-CONFIG_SQUASHFS_XZ=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_CRC_CCITT=m
diff --git a/arch/arm/configs/at91sam9263_defconfig b/arch/arm/configs/at91sam9263_defconfig
deleted file mode 100644 (file)
index 8b671c9..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_NAMESPACES=y
-CONFIG_EMBEDDED=y
-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_AT91=y
-CONFIG_ARCH_AT91SAM9263=y
-CONFIG_MACH_AT91SAM9263EK=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_NET_IPIP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=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_INET_DIAG is not set
-CONFIG_IPV6=y
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_NFTL=y
-CONFIG_NFTL_RW=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_BLOCK2MTD=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_GLUEBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_NETDEVICES=y
-CONFIG_MACB=y
-CONFIG_SMSC_PHY=y
-# CONFIG_WLAN is not set
-CONFIG_INPUT_POLLDEV=m
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_POWER_RESET=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_LOGO=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-# 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_ATMEL_AC97C=y
-# CONFIG_SND_SPI is not set
-CONFIG_SND_USB_AUDIO=m
-CONFIG_USB=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ATMEL_USBA=y
-CONFIG_USB_G_SERIAL=y
-CONFIG_MMC=y
-CONFIG_SDIO_UART=m
-CONFIG_MMC_ATMELMCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_PWM=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_PWM=y
-CONFIG_PWM_ATMEL=y
-CONFIG_EXT4_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_UBIFS_FS=y
-CONFIG_UBIFS_FS_ADVANCED_COMPR=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_USER=y
-CONFIG_XZ_DEC=y
-CONFIG_FONTS=y
diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig
deleted file mode 100644 (file)
index f66d1a1..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9G45=y
-CONFIG_MACH_AT91SAM9M10G45EK=y
-CONFIG_MACH_AT91SAM9_DT=y
-CONFIG_AT91_SLOW_CLOCK=y
-CONFIG_AEABI=y
-CONFIG_UACCESS_WITH_MEMCPY=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x71100000,25165824 root=/dev/ram0 rw"
-CONFIG_AUTO_ZRELADDR=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-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_IP_PNP_BOOTP=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_DIAG is not set
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-CONFIG_IPV6_SIT_6RD=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_GLUEBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=4
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_MACB=y
-CONFIG_DAVICOM_PHY=y
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_JOYDEV=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_QT1070=y
-CONFIG_KEYBOARD_QT2160=y
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ATMEL_MXT=m
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_POWER_RESET=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_ATMEL_LCDC=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-CONFIG_BACKLIGHT_PWM=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-CONFIG_LOGO=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-# 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_ATMEL_AC97C=y
-# CONFIG_SND_SPI is not set
-# CONFIG_SND_USB is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_ACM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ATMEL_USBA=y
-CONFIG_USB_G_MULTI=y
-CONFIG_USB_G_MULTI_CDC=y
-CONFIG_MMC=y
-# CONFIG_MMC_BLOCK_BOUNCE is not set
-CONFIG_MMC_ATMELMCI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_PWM=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91RM9200=y
-CONFIG_DMADEVICES=y
-CONFIG_AT_HDMAC=y
-CONFIG_DMATEST=m
-# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_IIO=y
-CONFIG_AT91_ADC=y
-CONFIG_PWM=y
-CONFIG_PWM_ATMEL=y
-CONFIG_EXT4_FS=y
-CONFIG_FANOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_UBIFS_FS=y
-CONFIG_UBIFS_FS_ADVANCED_COMPR=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_STRIP_ASM_SYMS=y
-CONFIG_DEBUG_MEMORY_INIT=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_FTRACE is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_CRYPTO_ECB=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_USER_API_HASH=m
-CONFIG_CRYPTO_USER_API_SKCIPHER=m
-# CONFIG_CRYPTO_HW is not set
-CONFIG_FONTS=y
diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig
deleted file mode 100644 (file)
index 4c26d34..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-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_AT91=y
-CONFIG_ARCH_AT91SAM9RL=y
-CONFIG_MACH_AT91SAM9RLEK=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_UBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=4
-CONFIG_BLK_DEV_RAM_SIZE=24576
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_POWER_RESET=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ATMEL_USBA=y
-CONFIG_MMC=y
-CONFIG_MMC_ATMELMCI=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_PWM=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_IIO=y
-CONFIG_AT91_ADC=y
-CONFIG_PWM=y
-CONFIG_PWM_ATMEL=y
-CONFIG_EXT4_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_UBIFS_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91x40_defconfig b/arch/arm/configs/at91x40_defconfig
deleted file mode 100644 (file)
index c55e921..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_ELF_CORE is not set
-# CONFIG_FUTEX is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-# CONFIG_MMU is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91X40=y
-CONFIG_MACH_AT91EB01=y
-CONFIG_AT91_EARLY_USART0=y
-CONFIG_CPU_ARM7TDMI=y
-CONFIG_SET_MEM_PARAM=y
-CONFIG_DRAM_BASE=0x01000000
-CONFIG_DRAM_SIZE=0x00400000
-CONFIG_FLASH_MEM_BASE=0x01400000
-CONFIG_PROCESSOR_ID=0x14000040
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_BINFMT_FLAT=y
-# CONFIG_SUSPEND is not set
-# CONFIG_FW_LOADER is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_ROM=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_DNOTIFY is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_ENABLE_MUST_CHECK is not set
index bc614f44b33d73cc6bf20a6b12890d0f112ce0c9..83a87e48901c105232b25cd89ff774bc72f7458c 100644 (file)
@@ -25,7 +25,8 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_BCM=y
-CONFIG_ARCH_BCM_MOBILE=y
+CONFIG_ARCH_BCM_21664=y
+CONFIG_ARCH_BCM_281XX=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
index 72058b8a6f4d4ccce4a8e5a740f82ba0321ef561..c4199072902402f542487b584289eb6245b76a4f 100644 (file)
@@ -134,6 +134,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_HSIC_USB3503=y
 CONFIG_MMC=y
+CONFIG_MMC_BLOCK_MINORS=16
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_S3C=y
 CONFIG_MMC_SDHCI_S3C_DMA=y
@@ -142,11 +143,13 @@ CONFIG_MMC_DW_IDMAC=y
 CONFIG_MMC_DW_EXYNOS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_MAX77686=y
+CONFIG_RTC_DRV_MAX77802=y
 CONFIG_RTC_DRV_S5M=y
 CONFIG_RTC_DRV_S3C=y
 CONFIG_DMADEVICES=y
 CONFIG_PL330_DMA=y
 CONFIG_COMMON_CLK_MAX77686=y
+CONFIG_COMMON_CLK_MAX77802=y
 CONFIG_COMMON_CLK_S2MPS11=y
 CONFIG_EXYNOS_IOMMU=y
 CONFIG_IIO=y
index 1772505caeba52b0a6efb5eb739e8538a69acf5f..1fe3621faf65694fb0b8f3533b88754e29812c74 100644 (file)
@@ -5,6 +5,8 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
 CONFIG_ARCH_HISI=y
 CONFIG_ARCH_HI3xxx=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_CMDLINE_PARTITION=y
 CONFIG_ARCH_HIX5HD2=y
 CONFIG_ARCH_HIP04=y
 CONFIG_SMP=y
@@ -14,8 +16,11 @@ CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_NEON=y
 CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
+CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
 CONFIG_IP_PNP=y
@@ -26,6 +31,7 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_NETDEVICES=y
+CONFIG_HIX5HD2_GMAC=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -39,8 +45,13 @@ CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_PINCTRL_SINGLE=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIOLIB=y
 CONFIG_GPIO_GENERIC_PLATFORM=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_MFD_SYSCON=y
+CONFIG_POWER_RESET_SYSCON=y
 CONFIG_DRM=y
 CONFIG_FB_SIMPLE=y
 CONFIG_USB=y
@@ -48,15 +59,21 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_MMC=y
 CONFIG_RTC_CLASS=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_DW_PLTFM=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_DMADEVICES=y
 CONFIG_DW_DMAC=y
 CONFIG_PL330_DMA=y
 CONFIG_PWM=y
+CONFIG_PHY_HIX5HD2_SATA=y
 CONFIG_EXT4_FS=y
 CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
@@ -65,6 +82,8 @@ CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOCKUP_DETECTOR=y
 CONFIG_VFP=y
index e688741c89aae2d24ec42b6e95120bf78e32b317..e6b0007355f883eaca70e4ce4df5b6fcc9818ae4 100644 (file)
@@ -97,6 +97,7 @@ CONFIG_SERIAL_IMX_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_IMX=y
+CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
index 8fca6e276b6949e73e036aac03a1d84f9a2b2760..f707cd2691cf3986249f6ba08e0c5aab8a8c71e9 100644 (file)
@@ -158,11 +158,18 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_ALGOPCF=m
 CONFIG_I2C_ALGOPCA=m
 CONFIG_I2C_IMX=y
+CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_MC9S08DZ60=y
 CONFIG_GPIO_STMPE=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_IMX=y
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
 CONFIG_MFD_DA9052_I2C=y
@@ -210,6 +217,7 @@ CONFIG_SND_SOC_IMX_WM8962=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
 CONFIG_SND_SOC_IMX_SPDIF=y
 CONFIG_SND_SOC_IMX_MC13783=y
+CONFIG_SND_SOC_TLV320AIC3X=y
 CONFIG_SND_SIMPLE_CARD=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
@@ -238,6 +246,7 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=y
 CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_ISL1208=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_MC13XXX=y
index c1f5adc5493e84b2bbeed7e07318138678f63114..71f14675d009413ee7bc26751eb4a7ae7d446a32 100644 (file)
@@ -8,6 +8,9 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_MULTI_V4T=y
+CONFIG_ARCH_MULTI_V5=y
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_INTEGRATOR=y
 CONFIG_ARCH_INTEGRATOR_AP=y
 CONFIG_ARCH_INTEGRATOR_CP=y
index 932ae40fb12857de015cb96876851b339c3a1b87..20a3ff99fae28f3af1107514e42bf80eceef8457 100644 (file)
@@ -20,6 +20,9 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_ARCH_KEYSTONE=y
 CONFIG_ARM_LPAE=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_KEYSTONE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
@@ -194,3 +197,7 @@ CONFIG_LEDS_TRIGGER_ONESHOT=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
 CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_KEYSTONE_IRQ=y
+CONFIG_GPIO_SYSCON=y
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_MARVELL_PHY=y
diff --git a/arch/arm/configs/koelsch_defconfig b/arch/arm/configs/koelsch_defconfig
deleted file mode 100644 (file)
index b33d19b..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_EMBEDDED=y
-CONFIG_PERF_EVENTS=y
-CONFIG_SLAB=y
-CONFIG_ARCH_SHMOBILE_LEGACY=y
-CONFIG_ARCH_R8A7791=y
-CONFIG_MACH_KOELSCH=y
-# CONFIG_SWP_EMULATE is not set
-CONFIG_CPU_BPREDICT_DISABLE=y
-CONFIG_PL310_ERRATA_588369=y
-CONFIG_ARM_ERRATA_754322=y
-CONFIG_PCI=y
-CONFIG_PCI_RCAR_GEN2=y
-CONFIG_PCI_RCAR_GEN2_PCIE=y
-CONFIG_SMP=y
-CONFIG_SCHED_MC=y
-CONFIG_NR_CPUS=8
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_KEXEC=y
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_SD=y
-CONFIG_ATA=y
-CONFIG_SATA_RCAR=y
-CONFIG_MTD=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_SPI_NOR=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-CONFIG_SH_ETH=y
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SMSC is not set
-# CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=20
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_I2C_MUX=y
-CONFIG_I2C_SH_MOBILE=y
-CONFIG_I2C_RCAR=y
-CONFIG_SPI=y
-CONFIG_SPI_RSPI=y
-CONFIG_SPI_SH_MSIOF=y
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_RCAR=y
-# CONFIG_HWMON is not set
-CONFIG_THERMAL=y
-CONFIG_RCAR_THERMAL=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_REGULATOR_DA9210=y
-CONFIG_REGULATOR_GPIO=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_MEDIA_CAMERA_SUPPORT=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_SOC_CAMERA=y
-CONFIG_SOC_CAMERA_PLATFORM=y
-CONFIG_VIDEO_RCAR_VIN=y
-# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
-CONFIG_VIDEO_ADV7180=y
-# CONFIG_HID is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_SDHI=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-# CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_ARM_UNWIND is not set
index 018bef9fa7e8f26fc4cb241c954cd91b3e203a2a..9d56781a8f80171e65922a44786d8bb10cbd3d4a 100644 (file)
@@ -67,9 +67,11 @@ CONFIG_SATA_AHCI=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_DSA_MV88E6123_61_65=y
+CONFIG_NET_DSA_MV88E6171=y
 CONFIG_MV643XX_ETH=y
 CONFIG_R8169=y
 CONFIG_MARVELL_PHY=y
+CONFIG_MWL8K=m
 CONFIG_LIBERTAS=y
 CONFIG_LIBERTAS_SDIO=y
 CONFIG_INPUT_EVDEV=y
index 491b7d5523bf8f2d2f741f078739b168443dfa8d..d7896580f3bb3f646bd80467b2b3831a79a76c14 100644 (file)
@@ -3,12 +3,14 @@ CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
+CONFIG_CMDLINE_PARTITION=y
 CONFIG_ARCH_VIRT=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
@@ -17,7 +19,9 @@ CONFIG_MACH_ARMADA_38X=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_MACH_DOVE=y
 CONFIG_ARCH_BCM=y
-CONFIG_ARCH_BCM_MOBILE=y
+CONFIG_ARCH_BCM_CYGNUS=y
+CONFIG_ARCH_BCM_21664=y
+CONFIG_ARCH_BCM_281XX=y
 CONFIG_ARCH_BCM_5301X=y
 CONFIG_ARCH_BRCMSTB=y
 CONFIG_ARCH_BERLIN=y
@@ -124,8 +128,12 @@ CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_OMAP_OCP2SCP=y
 CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
 CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
 CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_AD525X_DPOT=y
 CONFIG_AD525X_DPOT_I2C=y
@@ -146,6 +154,7 @@ CONFIG_AHCI_TEGRA=y
 CONFIG_SATA_HIGHBANK=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
+CONFIG_HIX5HD2_GMAC=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_MACB=y
 CONFIG_NET_CALXEDA_XGMAC=y
@@ -160,6 +169,7 @@ CONFIG_TI_CPSW=y
 CONFIG_XILINX_EMACLITE=y
 CONFIG_AT803X_PHY=y
 CONFIG_MARVELL_PHY=y
+CONFIG_BROADCOM_PHY=y
 CONFIG_ICPLUS_PHY=y
 CONFIG_USB_PEGASUS=y
 CONFIG_USB_USBNET=y
@@ -217,6 +227,7 @@ CONFIG_I2C_CADENCE=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_I2C_EXYNOS5=y
 CONFIG_I2C_MV64XXX=y
+CONFIG_I2C_S3C2410=y
 CONFIG_I2C_SIRF=y
 CONFIG_I2C_TEGRA=y
 CONFIG_I2C_ST=y
@@ -233,8 +244,10 @@ CONFIG_SPI_TEGRA114=y
 CONFIG_SPI_TEGRA20_SFLASH=y
 CONFIG_SPI_TEGRA20_SLINK=y
 CONFIG_SPI_XILINX=y
+CONFIG_SPI_SPIDEV=y
 CONFIG_PINCTRL_AS3722=y
 CONFIG_PINCTRL_PALMAS=y
+CONFIG_PINCTRL_APQ8084=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_GENERIC_PLATFORM=y
 CONFIG_GPIO_DWAPB=y
@@ -259,12 +272,15 @@ CONFIG_ST_THERMAL_SYSCFG=y
 CONFIG_ST_THERMAL_MEMMAP=y
 CONFIG_WATCHDOG=y
 CONFIG_XILINX_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
 CONFIG_ORION_WATCHDOG=y
 CONFIG_SUNXI_WATCHDOG=y
+CONFIG_MESON_WATCHDOG=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_BCM590XX=y
 CONFIG_MFD_CROS_EC=y
 CONFIG_MFD_CROS_EC_SPI=y
+CONFIG_MFD_MAX77686=y
 CONFIG_MFD_MAX8907=y
 CONFIG_MFD_SEC_CORE=y
 CONFIG_MFD_STMPE=y
@@ -276,7 +292,10 @@ CONFIG_REGULATOR_AB8500=y
 CONFIG_REGULATOR_AS3722=y
 CONFIG_REGULATOR_BCM590XX=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_MFD_SYSCON=y
+CONFIG_POWER_RESET_SYSCON=y
 CONFIG_REGULATOR_MAX8907=y
+CONFIG_REGULATOR_MAX77686=y
 CONFIG_REGULATOR_PALMAS=y
 CONFIG_REGULATOR_S2MPS11=y
 CONFIG_REGULATOR_S5M8767=y
@@ -305,6 +324,8 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_SOUND=y
 CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_TEGRA=y
 CONFIG_SND_SOC_TEGRA_RT5640=y
@@ -318,9 +339,11 @@ CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_MVEBU=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_EHCI_HCD_STI=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_ISP1760_HCD=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_STI=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
@@ -352,7 +375,10 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_MMC_MVSDIO=y
 CONFIG_MMC_SUNXI=y
 CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_DW_PLTFM=y
 CONFIG_MMC_DW_EXYNOS=y
+CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
@@ -375,6 +401,7 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AS3722=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_MAX8907=y
+CONFIG_RTC_DRV_MAX77686=y
 CONFIG_RTC_DRV_PALMAS=y
 CONFIG_RTC_DRV_TWL4030=y
 CONFIG_RTC_DRV_TPS6586X=y
@@ -409,6 +436,8 @@ CONFIG_NVEC_POWER=y
 CONFIG_NVEC_PAZ00=y
 CONFIG_QCOM_GSBI=y
 CONFIG_COMMON_CLK_QCOM=y
+CONFIG_COMMON_CLK_MAX77686=y
+CONFIG_APQ_MMCC_8084=y
 CONFIG_MSM_GCC_8660=y
 CONFIG_MSM_MMCC_8960=y
 CONFIG_MSM_MMCC_8974=y
@@ -421,12 +450,19 @@ CONFIG_AK8975=y
 CONFIG_PWM=y
 CONFIG_PWM_TEGRA=y
 CONFIG_PWM_VT8500=y
+CONFIG_PHY_HIX5HD2_SATA=y
 CONFIG_OMAP_USB2=y
 CONFIG_TI_PIPE3=y
 CONFIG_PHY_MIPHY365X=y
+CONFIG_PHY_STIH41X_USB=y
 CONFIG_PHY_SUN4I_USB=y
 CONFIG_EXT4_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
 CONFIG_TMPFS=y
 CONFIG_SQUASHFS=y
 CONFIG_SQUASHFS_LZO=y
@@ -435,6 +471,9 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
index 22058e18dfaab66d28beb5593494451a628be5a7..824de499237b46dd2ed2988367e65d6212d73da7 100644 (file)
@@ -67,9 +67,11 @@ CONFIG_SATA_AHCI=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_DSA_MV88E6123_61_65=y
+CONFIG_NET_DSA_MV88E6171=y
 CONFIG_MV643XX_ETH=y
 CONFIG_R8169=y
 CONFIG_MARVELL_PHY=y
+CONFIG_MWL8K=m
 CONFIG_LIBERTAS=y
 CONFIG_LIBERTAS_SDIO=y
 CONFIG_INPUT_EVDEV=y
index ed0a0d1be0f31686a924dbd8b4e0f1a9d281bab6..627accea72fbec2759eebfed8099a60d53e2a78d 100644 (file)
@@ -45,6 +45,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
@@ -59,10 +60,12 @@ CONFIG_ATA=y
 CONFIG_AHCI_MVEBU=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
+CONFIG_NET_DSA_MV88E6171=y
 CONFIG_MV643XX_ETH=y
 CONFIG_MVNETA=y
 CONFIG_MVPP2=y
 CONFIG_MARVELL_PHY=y
+CONFIG_FIXED_PHY=y
 CONFIG_MWIFIEX=y
 CONFIG_MWIFIEX_SDIO=y
 CONFIG_INPUT_EVDEV=y
@@ -72,6 +75,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MV64XXX=y
 CONFIG_SPI=y
 CONFIG_SPI_ORION=y
@@ -85,7 +89,9 @@ CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_KIRKWOOD_SOC=y
-CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB=y
+CONFIG_SND_SOC_CS42L51_I2C=y
+CONFIG_SND_SOC_SPDIF=y
+CONFIG_SND_SIMPLE_CARD=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_MVEBU=y
@@ -96,6 +102,7 @@ CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_DOVE=y
+CONFIG_MMC_SDHCI_PXAV3=y
 CONFIG_MMC_MVSDIO=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_CLASS=y
index 263ae3869e32c5f9ecf8bc2f2fd63b8ce8291eda..7d2ad30d9e705c4e9c18865285292aa119fe7ccf 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -57,14 +56,12 @@ CONFIG_MTD_NAND_FSMC=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_GENERIC=y
-CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
@@ -83,21 +80,21 @@ CONFIG_PPP_SYNC_TTY=m
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_STMPE=y
 # CONFIG_MOUSE_PS2 is not set
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_NOMADIK=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_GPIO=y
-CONFIG_I2C_NOMADIK=y
 CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_STMPE=y
 # CONFIG_HWMON is not set
+CONFIG_MFD_STMPE=y
 CONFIG_REGULATOR=y
 CONFIG_MMC=y
-CONFIG_MMC_UNSAFE_RESUME=y
 # CONFIG_MMC_BLOCK_BOUNCE is not set
 CONFIG_MMC_ARMMMCI=y
 CONFIG_NEW_LEDS=y
@@ -125,12 +122,12 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=y
+CONFIG_DEBUG_INFO=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_DES=y
index 16e719c268dd77407f8ffb00fc687036d319a2b1..3e09286f7ff188a20380ea9be7e315f010feff5c 100644 (file)
@@ -86,7 +86,6 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
 CONFIG_NETFILTER=y
 CONFIG_CAN=m
 CONFIG_CAN_C_CAN=m
@@ -112,6 +111,7 @@ CONFIG_MTD_OOPS=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC_BCH=y
 CONFIG_MTD_NAND_OMAP2=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
@@ -129,11 +129,27 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MD=y
 CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_KS8851=y
 CONFIG_KS8851_MLL=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_TI_CPSW=y
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_AT803X_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_USB_USBNET=y
@@ -161,6 +177,7 @@ CONFIG_KEYBOARD_MATRIX=m
 CONFIG_KEYBOARD_TWL4030=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
 CONFIG_TOUCHSCREEN_TSC2005=m
 CONFIG_TOUCHSCREEN_TSC2007=m
 CONFIG_INPUT_MISC=y
@@ -264,6 +281,8 @@ CONFIG_SND_VERBOSE_PRINTK=y
 CONFIG_SND_DEBUG=y
 CONFIG_SND_USB_AUDIO=m
 CONFIG_SND_SOC=m
+CONFIG_SND_EDMA_SOC=m
+CONFIG_SND_AM33XX_SOC_EVM=m
 CONFIG_SND_OMAP_SOC=m
 CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
 CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
@@ -271,6 +290,7 @@ CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=m
 CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=m
@@ -306,6 +326,8 @@ CONFIG_DMA_OMAP=y
 CONFIG_EXTCON=y
 CONFIG_EXTCON_PALMAS=y
 CONFIG_PWM=y
+CONFIG_PWM_TIECAP=y
+CONFIG_PWM_TIEHRPWM=y
 CONFIG_PWM_TWL=y
 CONFIG_PWM_TWL_LED=y
 CONFIG_OMAP_USB2=y
@@ -317,7 +339,7 @@ CONFIG_EXT4_FS=y
 CONFIG_FANOTIFY=y
 CONFIG_QUOTA=y
 CONFIG_QFMT_V2=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS4_FS=m
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index c9089c927daf0e4f5a84dba71f5cae85ea2e13c6..b58fb32770a0e6f5468da385babb2dd5629e5647 100644 (file)
@@ -12,7 +12,7 @@ CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_LBDAF is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
@@ -20,7 +20,6 @@ CONFIG_ARCH_AT91=y
 CONFIG_SOC_SAM_V7=y
 CONFIG_SOC_SAMA5D3=y
 CONFIG_SOC_SAMA5D4=y
-CONFIG_MACH_SAMA5_DT=y
 CONFIG_AEABI=y
 CONFIG_UACCESS_WITH_MEMCPY=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -30,6 +29,8 @@ CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 r
 CONFIG_KEXEC=y
 CONFIG_AUTO_ZRELADDR=y
 CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_PM_DEBUG=y
@@ -176,11 +177,13 @@ CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT91RM9200=y
 CONFIG_DMADEVICES=y
+CONFIG_AT_XDMAC=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_AT91_ADC=y
 CONFIG_PWM=y
 CONFIG_PWM_ATMEL=y
+CONFIG_PWM_ATMEL_TCB=y
 CONFIG_EXT4_FS=y
 CONFIG_FANOTIFY=y
 CONFIG_VFAT_FS=y
index d7346ad51043efd6c6b1b1bcb48e2d2e1360b531..63fb5316ff02a1a8fea511e662f931b4fea3be5a 100644 (file)
@@ -17,7 +17,6 @@ CONFIG_ARCH_R8A7779=y
 CONFIG_ARCH_R8A7790=y
 CONFIG_ARCH_R8A7791=y
 CONFIG_ARCH_R8A7794=y
-CONFIG_MACH_KOELSCH=y
 CONFIG_MACH_LAGER=y
 CONFIG_MACH_MARZEN=y
 # CONFIG_SWP_EMULATE is not set
@@ -126,6 +125,7 @@ CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_SH4_FSI=y
 CONFIG_SND_SOC_RCAR=y
+CONFIG_SND_SOC_AK4642=y
 CONFIG_SND_SOC_WM8978=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
@@ -146,6 +146,8 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_S35390A=y
 CONFIG_DMADEVICES=y
 CONFIG_SH_DMAE=y
+CONFIG_RCAR_AUDMAC_PP=y
+CONFIG_RCAR_DMAC=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PWM=y
 CONFIG_PWM_RENESAS_TPU=y
index d7a5855a5db89a550f967125f5e300c8a1152f54..a2956c3112f14abd66c5ed586d621d8e7dd548b8 100644 (file)
@@ -1,5 +1,6 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -11,23 +12,17 @@ CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_HOTPLUG=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_SOCFPGA=y
-CONFIG_MACH_SOCFPGA_CYCLONE5=y
 CONFIG_ARM_THUMBEE=y
-# CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set
-# CONFIG_CACHE_L2X0 is not set
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE=""
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_NET=y
@@ -41,38 +36,30 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
+CONFIG_IPV6=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VLAN_8021Q_GVRP=y
 CONFIG_CAN=y
-CONFIG_CAN_RAW=y
-CONFIG_CAN_BCM=y
-CONFIG_CAN_GW=y
-CONFIG_CAN_DEV=y
-CONFIG_CAN_CALC_BITTIMING=y
 CONFIG_CAN_C_CAN=y
 CONFIG_CAN_C_CAN_PLATFORM=y
 CONFIG_CAN_DEBUG_DEVICES=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
-CONFIG_PROC_DEVICETREE=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=2
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SRAM=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_STMMAC_ETH=y
+CONFIG_DWMAC_SOCFPGA=y
 CONFIG_MICREL_PHY=y
-# CONFIG_STMMAC_PHY_ID_ZERO_WORKAROUND is not set
 CONFIG_INPUT_EVDEV=y
-CONFIG_DWMAC_SOCFPGA=y
-CONFIG_PPS=y
-CONFIG_NETWORK_PHY_TIMESTAMPING=y
-CONFIG_PTP_1588_CLOCK=y
-CONFIG_VLAN_8021Q=y
-CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_GARP=y
-CONFIG_IPV6=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
@@ -81,45 +68,43 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 CONFIG_SERIAL_8250_DW=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_DWAPB=y
-# CONFIG_RTC_HCTOSYS is not set
+CONFIG_PMBUS=y
+CONFIG_SENSORS_LTC2978=y
+CONFIG_SENSORS_LTC2978_REGULATOR=y
 CONFIG_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT3_FS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
-CONFIG_FHANDLE=y
+CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_NTFS_RW=y
 CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_SCHED_DEBUG is not set
-CONFIG_DEBUG_INFO=y
 CONFIG_ENABLE_DEFAULT_TRACERS=y
 CONFIG_DEBUG_USER=y
 CONFIG_XZ_DEC=y
-CONFIG_I2C=y
-CONFIG_I2C_DESIGNWARE_CORE=y
-CONFIG_I2C_DESIGNWARE_PLATFORM=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_MMC=y
-CONFIG_MMC_DW=y
-CONFIG_PM=y
-CONFIG_SUSPEND=y
-CONFIG_MMC_UNSAFE_RESUME=y
-CONFIG_USB=y
-CONFIG_USB_DWC2=y
-CONFIG_USB_DWC2_HOST=y
-CONFIG_USB_DWC2_PLATFORM=y
index 847045313101300f9d48d5b05e587c6456d16f30..f7ac0379850fc8d9ff9328dbd85b705bcb893b7f 100644 (file)
@@ -76,6 +76,7 @@ CONFIG_WATCHDOG=y
 CONFIG_SUNXI_WATCHDOG=y
 CONFIG_MFD_AXP20X=y
 CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
index 888fc15213224861ca9fce74ab0d488f8eb66143..40750f93aa83afc44fd1b27caccf5861498488db 100644 (file)
@@ -97,10 +97,8 @@ CONFIG_ICS932S401=y
 CONFIG_APDS9802ALS=y
 CONFIG_ISL29003=y
 CONFIG_EEPROM_AT24=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
index 92793ba69c4020bc3ae1aac0560f96b7be0347a5..d4ebf5679f1fd90c9422589381423a2bcd70e5bc 100644 (file)
@@ -78,6 +78,15 @@ static inline u32 arch_timer_get_cntfrq(void)
        return val;
 }
 
+static inline u64 arch_counter_get_cntpct(void)
+{
+       u64 cval;
+
+       isb();
+       asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
+       return cval;
+}
+
 static inline u64 arch_counter_get_cntvct(void)
 {
        u64 cval;
index 2c9f10df7568d5c77010f0cf8e4e08b1bc820082..89aefe10d66b78102919d05860eb89715d01f85d 100644 (file)
@@ -28,7 +28,7 @@ struct firmware_ops {
        /*
         * Enters CPU idle mode
         */
-       int (*do_idle)(void);
+       int (*do_idle)(unsigned long mode);
        /*
         * Sets boot address of specified physical CPU
         */
@@ -41,6 +41,14 @@ struct firmware_ops {
         * Initializes L2 cache
         */
        int (*l2x0_init)(void);
+       /*
+        * Enter system-wide suspend.
+        */
+       int (*suspend)(void);
+       /*
+        * Restore state of privileged hardware after system-wide suspend.
+        */
+       int (*resume)(void);
 };
 
 /* Global pointer for current firmware_ops structure, can't be NULL. */
index 180567408ee8a0310eed2185fbafa2d06ae991d5..db58deb00aa74c8176380075d06b60e6b0858009 100644 (file)
@@ -47,13 +47,13 @@ extern void atomic_io_modify_relaxed(void __iomem *reg, u32 mask, u32 set);
  * Generic IO read/write.  These perform native-endian accesses.  Note
  * that some architectures will want to re-define __raw_{read,write}w.
  */
-extern void __raw_writesb(void __iomem *addr, const void *data, int bytelen);
-extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
-extern void __raw_writesl(void __iomem *addr, const void *data, int longlen);
+void __raw_writesb(volatile void __iomem *addr, const void *data, int bytelen);
+void __raw_writesw(volatile void __iomem *addr, const void *data, int wordlen);
+void __raw_writesl(volatile void __iomem *addr, const void *data, int longlen);
 
-extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen);
-extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
-extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
+void __raw_readsb(const volatile void __iomem *addr, void *data, int bytelen);
+void __raw_readsw(const volatile void __iomem *addr, void *data, int wordlen);
+void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen);
 
 #if __LINUX_ARM_ARCH__ < 6
 /*
@@ -69,6 +69,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
  * writeback addressing modes as these incur a significant performance
  * overhead (the address generation must be emulated in software).
  */
+#define __raw_writew __raw_writew
 static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 {
        asm volatile("strh %1, %0"
@@ -76,6 +77,7 @@ static inline void __raw_writew(u16 val, volatile void __iomem *addr)
                     : "r" (val));
 }
 
+#define __raw_readw __raw_readw
 static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
        u16 val;
@@ -86,6 +88,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 }
 #endif
 
+#define __raw_writeb __raw_writeb
 static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
 {
        asm volatile("strb %1, %0"
@@ -93,6 +96,7 @@ static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
                     : "r" (val));
 }
 
+#define __raw_writel __raw_writel
 static inline void __raw_writel(u32 val, volatile void __iomem *addr)
 {
        asm volatile("str %1, %0"
@@ -100,6 +104,7 @@ static inline void __raw_writel(u32 val, volatile void __iomem *addr)
                     : "r" (val));
 }
 
+#define __raw_readb __raw_readb
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
        u8 val;
@@ -109,6 +114,7 @@ static inline u8 __raw_readb(const volatile void __iomem *addr)
        return val;
 }
 
+#define __raw_readl __raw_readl
 static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
        u32 val;
@@ -267,20 +273,6 @@ extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
 #define insl(p,d,l)            __raw_readsl(__io(p),d,l)
 #endif
 
-#define outb_p(val,port)       outb((val),(port))
-#define outw_p(val,port)       outw((val),(port))
-#define outl_p(val,port)       outl((val),(port))
-#define inb_p(port)            inb((port))
-#define inw_p(port)            inw((port))
-#define inl_p(port)            inl((port))
-
-#define outsb_p(port,from,len) outsb(port,from,len)
-#define outsw_p(port,from,len) outsw(port,from,len)
-#define outsl_p(port,from,len) outsl(port,from,len)
-#define insb_p(port,to,len)    insb(port,to,len)
-#define insw_p(port,to,len)    insw(port,to,len)
-#define insl_p(port,to,len)    insl(port,to,len)
-
 /*
  * String version of IO memory access ops:
  */
@@ -347,39 +339,41 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
 #define iounmap                                __arm_iounmap
 
 /*
- * io{read,write}{8,16,32} macros
+ * io{read,write}{16,32}be() macros
  */
-#ifndef ioread8
-#define ioread8(p)     ({ unsigned int __v = __raw_readb(p); __iormb(); __v; })
-#define ioread16(p)    ({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; })
-#define ioread32(p)    ({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; })
-
-#define ioread16be(p)  ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
-#define ioread32be(p)  ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
-
-#define iowrite8(v,p)  ({ __iowmb(); __raw_writeb(v, p); })
-#define iowrite16(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_le16(v), p); })
-#define iowrite32(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_le32(v), p); })
+#define ioread16be(p)          ({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32be(p)          ({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
 
-#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
-#define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
-
-#define ioread8_rep(p,d,c)     __raw_readsb(p,d,c)
-#define ioread16_rep(p,d,c)    __raw_readsw(p,d,c)
-#define ioread32_rep(p,d,c)    __raw_readsl(p,d,c)
-
-#define iowrite8_rep(p,s,c)    __raw_writesb(p,s,c)
-#define iowrite16_rep(p,s,c)   __raw_writesw(p,s,c)
-#define iowrite32_rep(p,s,c)   __raw_writesl(p,s,c)
+#define iowrite16be(v,p)       ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p)       ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
 
+#ifndef ioport_map
+#define ioport_map ioport_map
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+#endif
+#ifndef ioport_unmap
+#define ioport_unmap ioport_unmap
 extern void ioport_unmap(void __iomem *addr);
 #endif
 
 struct pci_dev;
 
+#define pci_iounmap pci_iounmap
 extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
 
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p)   __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p)  p
+
+#include <asm-generic/io.h>
+
 /*
  * can the hardware map this into one segment or not, given no other
  * constraints.
@@ -401,17 +395,6 @@ extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
 extern int devmem_is_allowed(unsigned long pfn);
 #endif
 
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)   __va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p)  p
-
 /*
  * Register ISA memory and port locations for glibc iopl/inb/outb
  * emulation.
index e731018869a7570cfb7836424304db6284993d90..184def0e1652ea0bffeedecf5fa82b5ce256acf7 100644 (file)
@@ -274,11 +274,13 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
  * translation for translating DMA addresses.  Use the driver
  * DMA support - see dma-mapping.h.
  */
+#define virt_to_phys virt_to_phys
 static inline phys_addr_t virt_to_phys(const volatile void *x)
 {
        return __virt_to_phys((unsigned long)(x));
 }
 
+#define phys_to_virt phys_to_virt
 static inline void *phys_to_virt(phys_addr_t x)
 {
        return (void *)__phys_to_virt(x);
@@ -322,11 +324,13 @@ static inline phys_addr_t __virt_to_idmap(unsigned long x)
 #endif
 
 #ifdef CONFIG_VIRT_TO_BUS
+#define virt_to_bus virt_to_bus
 static inline __deprecated unsigned long virt_to_bus(void *x)
 {
        return __virt_to_bus((unsigned long)x);
 }
 
+#define bus_to_virt bus_to_virt
 static inline __deprecated void *bus_to_virt(unsigned long x)
 {
        return (void *)__bus_to_virt(x);
index c3a83691af8eda239f00df0a46b8839044c9e65d..d9cf138fd7d455624e0e823d9ed136fd329716a2 100644 (file)
@@ -12,7 +12,7 @@
 #ifndef __ARM_PERF_EVENT_H__
 #define __ARM_PERF_EVENT_H__
 
-#ifdef CONFIG_HW_PERF_EVENTS
+#ifdef CONFIG_PERF_EVENTS
 struct pt_regs;
 extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
 extern unsigned long perf_misc_flags(struct pt_regs *regs);
index 0b648c541293b9ac7387e14fbbe61f6ad87ff789..b1596bd59129049ab3dfd46a95aff4e75531fe90 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/interrupt.h>
 #include <linux/perf_event.h>
 
+#include <asm/cputype.h>
+
 /*
  * struct arm_pmu_platdata - ARM PMU platform data
  *
@@ -66,19 +68,25 @@ struct pmu_hw_events {
        /*
         * The events that are active on the PMU for the given index.
         */
-       struct perf_event       **events;
+       struct perf_event       *events[ARMPMU_MAX_HWEVENTS];
 
        /*
         * A 1 bit for an index indicates that the counter is being used for
         * an event. A 0 means that the counter can be used.
         */
-       unsigned long           *used_mask;
+       DECLARE_BITMAP(used_mask, ARMPMU_MAX_HWEVENTS);
 
        /*
         * Hardware lock to serialize accesses to PMU registers. Needed for the
         * read/modify/write sequences.
         */
        raw_spinlock_t          pmu_lock;
+
+       /*
+        * When using percpu IRQs, we need a percpu dev_id. Place it here as we
+        * already have to allocate this struct per cpu.
+        */
+       struct arm_pmu          *percpu_pmu;
 };
 
 struct arm_pmu {
@@ -107,7 +115,8 @@ struct arm_pmu {
        struct mutex    reserve_mutex;
        u64             max_period;
        struct platform_device  *plat_device;
-       struct pmu_hw_events    *(*get_hw_events)(void);
+       struct pmu_hw_events    __percpu *hw_events;
+       struct notifier_block   hotplug_nb;
 };
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
@@ -127,6 +136,27 @@ int armpmu_map_event(struct perf_event *event,
                                                [PERF_COUNT_HW_CACHE_RESULT_MAX],
                     u32 raw_event_mask);
 
+struct pmu_probe_info {
+       unsigned int cpuid;
+       unsigned int mask;
+       int (*init)(struct arm_pmu *);
+};
+
+#define PMU_PROBE(_cpuid, _mask, _fn)  \
+{                                      \
+       .cpuid = (_cpuid),              \
+       .mask = (_mask),                \
+       .init = (_fn),                  \
+}
+
+#define ARM_PMU_PROBE(_cpuid, _fn) \
+       PMU_PROBE(_cpuid, ARM_CPU_PART_MASK, _fn)
+
+#define ARM_PMU_XSCALE_MASK    ((0xff << 24) | ARM_CPU_XSCALE_ARCH_MASK)
+
+#define XSCALE_PMU_PROBE(_version, _fn) \
+       PMU_PROBE(ARM_CPU_IMP_INTEL << 24 | _version, ARM_PMU_XSCALE_MASK, _fn)
+
 #endif /* CONFIG_HW_PERF_EVENTS */
 
 #endif /* __ARM_PMU_H__ */
index fc44d3761f9e7d36eb8ff4911ff0120a63e7584f..ce73ab6354149f8c490319bdeb6acdbc92cd784c 100644 (file)
@@ -44,16 +44,6 @@ struct cpu_context_save {
        __u32   extra[2];               /* Xscale 'acc' register, etc */
 };
 
-struct arm_restart_block {
-       union {
-               /* For user cache flushing */
-               struct {
-                       unsigned long start;
-                       unsigned long end;
-               } cache;
-       };
-};
-
 /*
  * low level task data that entry.S needs immediate access to.
  * __switch_to() assumes cpu_context follows immediately after cpu_domain.
@@ -79,7 +69,6 @@ struct thread_info {
        unsigned long           thumbee_state;  /* ThumbEE Handler Base register */
 #endif
        struct restart_block    restart_block;
-       struct arm_restart_block        arm_restart_block;
 };
 
 #define INIT_THREAD_INFO(tsk)                                          \
diff --git a/arch/arm/include/debug/asm9260.S b/arch/arm/include/debug/asm9260.S
new file mode 100644 (file)
index 0000000..292f85b
--- /dev/null
@@ -0,0 +1,29 @@
+/* Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *  Modified for ASM9260 by Oleksij Remepl <linux@rempel-privat.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.
+ *
+ */
+
+               .macro  addruart, rp, rv, tmp
+               ldr     \rp, = CONFIG_DEBUG_UART_PHYS
+               ldr     \rv, = CONFIG_DEBUG_UART_VIRT
+               .endm
+
+               .macro  waituart,rd,rx
+               .endm
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #0x50]       @ TXDATA
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #0x60]       @ STAT
+               tst     \rd, #1 << 27           @ TXEMPTY
+               beq     1002b                   @ wait until transmit done
+               .endm
diff --git a/arch/arm/include/debug/renesas-scif.S b/arch/arm/include/debug/renesas-scif.S
new file mode 100644 (file)
index 0000000..97820a8
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Renesas SCIF(A) debugging macro include header
+ *
+ * Based on r8a7790.S
+ *
+ * Copyright (C) 2012-2013 Renesas Electronics Corporation
+ * Copyright (C) 1994-1999 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define SCIF_PHYS      CONFIG_DEBUG_UART_PHYS
+#define SCIF_VIRT      ((SCIF_PHYS & 0x00ffffff) | 0xfd000000)
+
+#if CONFIG_DEBUG_UART_PHYS < 0xe6e00000
+/* SCIFA */
+#define FTDR           0x20
+#define FSR            0x14
+#else
+/* SCIF */
+#define FTDR           0x0c
+#define FSR            0x10
+#endif
+
+#define TDFE   (1 << 5)
+#define TEND   (1 << 6)
+
+       .macro  addruart, rp, rv, tmp
+       ldr     \rp, =SCIF_PHYS
+       ldr     \rv, =SCIF_VIRT
+       .endm
+
+       .macro  waituart, rd, rx
+1001:  ldrh    \rd, [\rx, #FSR]
+       tst     \rd, #TDFE
+       beq     1001b
+       .endm
+
+       .macro  senduart, rd, rx
+       strb    \rd, [\rx, #FTDR]
+       ldrh    \rd, [\rx, #FSR]
+       bic     \rd, \rd, #TEND
+       strh    \rd, [\rx, #FSR]
+       .endm
+
+       .macro  busyuart, rd, rx
+1001:  ldrh    \rd, [\rx, #FSR]
+       tst     \rd, #TEND
+       beq     1001b
+       .endm
diff --git a/arch/arm/include/debug/sa1100.S b/arch/arm/include/debug/sa1100.S
new file mode 100644 (file)
index 0000000..a0ae4f4
--- /dev/null
@@ -0,0 +1,68 @@
+/* arch/arm/include/debug/sa1100.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can 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 UTCR3          0x0c
+#define UTDR           0x14
+#define UTSR1          0x20
+#define UTCR3_TXE      0x00000002      /* Transmit Enable                 */
+#define UTSR1_TBY      0x00000001      /* Transmitter BusY (read)         */
+#define UTSR1_TNF      0x00000004      /* Transmit FIFO Not Full (read)   */
+
+               .macro  addruart, rp, rv, tmp
+               mrc     p15, 0, \rp, c1, c0
+               tst     \rp, #1                 @ MMU enabled?
+               moveq   \rp, #0x80000000        @ physical base address
+               movne   \rp, #0xf8000000        @ virtual address
+
+               @ We probe for the active serial port here, coherently with
+               @ the comment in arch/arm/mach-sa1100/include/mach/uncompress.h.
+               @ We assume r1 can be clobbered.
+
+               @ see if Ser3 is active
+               add     \rp, \rp, #0x00050000
+               ldr     \rv, [\rp, #UTCR3]
+               tst     \rv, #UTCR3_TXE
+
+               @ if Ser3 is inactive, then try Ser1
+               addeq   \rp, \rp, #(0x00010000 - 0x00050000)
+               ldreq   \rv, [\rp, #UTCR3]
+               tsteq   \rv, #UTCR3_TXE
+
+               @ if Ser1 is inactive, then try Ser2
+               addeq   \rp, \rp, #(0x00030000 - 0x00010000)
+               ldreq   \rv, [\rp, #UTCR3]
+               tsteq   \rv, #UTCR3_TXE
+
+               @ clear top bits, and generate both phys and virt addresses
+               lsl     \rp, \rp, #8
+               lsr     \rp, \rp, #8
+               orr     \rv, \rp, #0xf8000000   @ virtual
+               orr     \rp, \rp, #0x80000000   @ physical
+
+               .endm
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #UTDR]
+               .endm
+
+               .macro  waituart,rd,rx
+1001:          ldr     \rd, [\rx, #UTSR1]
+               tst     \rd, #UTSR1_TNF
+               beq     1001b
+               .endm
+
+               .macro  busyuart,rd,rx
+1001:          ldr     \rd, [\rx, #UTSR1]
+               tst     \rd, #UTSR1_TBY
+               bne     1001b
+               .endm
index 3aaa75cae90c912737efbe9ed834d437d0fcaf01..705bb7620673a10222e3258d94158ab8ec1555c9 100644 (file)
 #define __NR_seccomp                   (__NR_SYSCALL_BASE+383)
 #define __NR_getrandom                 (__NR_SYSCALL_BASE+384)
 #define __NR_memfd_create              (__NR_SYSCALL_BASE+385)
+#define __NR_bpf                       (__NR_SYSCALL_BASE+386)
 
 /*
  * The following SWIs are ARM private.
index 38ddd9f83d0e586289c56bdbf1e38a6a977ff1a7..8dcbed5016ac2c3d18f3b3bbc2c30030c5c0a87e 100644 (file)
@@ -82,7 +82,7 @@ obj-$(CONFIG_CPU_MOHAWK)      += xscale-cp0.o
 obj-$(CONFIG_CPU_PJ4)          += pj4-cp0.o
 obj-$(CONFIG_CPU_PJ4B)         += pj4-cp0.o
 obj-$(CONFIG_IWMMXT)           += iwmmxt.o
-obj-$(CONFIG_PERF_EVENTS)      += perf_regs.o
+obj-$(CONFIG_PERF_EVENTS)      += perf_regs.o perf_callchain.o
 obj-$(CONFIG_HW_PERF_EVENTS)   += perf_event.o perf_event_cpu.o
 AFLAGS_iwmmxt.o                        := -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
index 713e807621d2cf6a785660d40fec9367866eedcd..2d2d6087b9b105d5dadcd66f9821deefe50d1e66 100644 (file)
@@ -10,6 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/compiler.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
  * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
  *            (http://gcc.gnu.org/PR8896) and incorrect structure
  *           initialisation in fs/jffs2/erase.c
+ * GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854
+ *           miscompiles find_get_entry(), and can result in EXT3 and EXT4
+ *           filesystem corruption (possibly other FS too).
  */
+#ifdef __GNUC__
 #if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
 #error Your compiler is too buggy; it is known to miscompile kernels.
-#error    Known good compilers: 3.3
+#error    Known good compilers: 3.3, 4.x
+#endif
+#if GCC_VERSION >= 40800 && GCC_VERSION < 40803
+#error Your compiler is too buggy; it is known to miscompile kernels
+#error and result in filesystem corruption and oopses.
+#endif
 #endif
 
 int main(void)
index 9f899d8fdccabb4751bddf48da8f522a17905c75..e51833f8cc387118ae3826a0a78a533f4ff90a5f 100644 (file)
                CALL(sys_seccomp)
                CALL(sys_getrandom)
 /* 385 */      CALL(sys_memfd_create)
+               CALL(sys_bpf)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c
new file mode 100644 (file)
index 0000000..4e02ae5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * ARM callchain support
+ *
+ * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
+ * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
+ *
+ * This code is based on the ARM OProfile backtrace code.
+ */
+#include <linux/perf_event.h>
+#include <linux/uaccess.h>
+
+#include <asm/stacktrace.h>
+
+/*
+ * The registers we're interested in are at the end of the variable
+ * length saved register structure. The fp points at the end of this
+ * structure so the address of this struct is:
+ * (struct frame_tail *)(xxx->fp)-1
+ *
+ * This code has been adapted from the ARM OProfile support.
+ */
+struct frame_tail {
+       struct frame_tail __user *fp;
+       unsigned long sp;
+       unsigned long lr;
+} __attribute__((packed));
+
+/*
+ * Get the return address for a single stackframe and return a pointer to the
+ * next frame tail.
+ */
+static struct frame_tail __user *
+user_backtrace(struct frame_tail __user *tail,
+              struct perf_callchain_entry *entry)
+{
+       struct frame_tail buftail;
+       unsigned long err;
+
+       if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
+               return NULL;
+
+       pagefault_disable();
+       err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
+       pagefault_enable();
+
+       if (err)
+               return NULL;
+
+       perf_callchain_store(entry, buftail.lr);
+
+       /*
+        * Frame pointers should strictly progress back up the stack
+        * (towards higher addresses).
+        */
+       if (tail + 1 >= buftail.fp)
+               return NULL;
+
+       return buftail.fp - 1;
+}
+
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+{
+       struct frame_tail __user *tail;
+
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* We don't support guest os callchain now */
+               return;
+       }
+
+       perf_callchain_store(entry, regs->ARM_pc);
+
+       if (!current->mm)
+               return;
+
+       tail = (struct frame_tail __user *)regs->ARM_fp - 1;
+
+       while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+              tail && !((unsigned long)tail & 0x3))
+               tail = user_backtrace(tail, entry);
+}
+
+/*
+ * Gets called by walk_stackframe() for every stackframe. This will be called
+ * whist unwinding the stackframe and is like a subroutine return so we use
+ * the PC.
+ */
+static int
+callchain_trace(struct stackframe *fr,
+               void *data)
+{
+       struct perf_callchain_entry *entry = data;
+       perf_callchain_store(entry, fr->pc);
+       return 0;
+}
+
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+{
+       struct stackframe fr;
+
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* We don't support guest os callchain now */
+               return;
+       }
+
+       arm_get_current_stackframe(regs, &fr);
+       walk_stackframe(&fr, callchain_trace, entry);
+}
+
+unsigned long perf_instruction_pointer(struct pt_regs *regs)
+{
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
+               return perf_guest_cbs->get_guest_ip();
+
+       return instruction_pointer(regs);
+}
+
+unsigned long perf_misc_flags(struct pt_regs *regs)
+{
+       int misc = 0;
+
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               if (perf_guest_cbs->is_user_mode())
+                       misc |= PERF_RECORD_MISC_GUEST_USER;
+               else
+                       misc |= PERF_RECORD_MISC_GUEST_KERNEL;
+       } else {
+               if (user_mode(regs))
+                       misc |= PERF_RECORD_MISC_USER;
+               else
+                       misc |= PERF_RECORD_MISC_KERNEL;
+       }
+
+       return misc;
+}
index 266cba46db3efe4f92c554320ac9668d098cdf7f..e34934f63a492d23249d91e88831566cf9c8f76c 100644 (file)
@@ -7,21 +7,18 @@
  * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
  *
  * This code is based on the sparc64 perf event code, which is in turn based
- * on the x86 code. Callchain code is based on the ARM OProfile backtrace
- * code.
+ * on the x86 code.
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-#include <linux/uaccess.h>
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 
 #include <asm/irq_regs.h>
 #include <asm/pmu.h>
-#include <asm/stacktrace.h>
 
 static int
 armpmu_map_cache_event(const unsigned (*cache_map)
@@ -80,8 +77,12 @@ armpmu_map_event(struct perf_event *event,
                 u32 raw_event_mask)
 {
        u64 config = event->attr.config;
+       int type = event->attr.type;
 
-       switch (event->attr.type) {
+       if (type == event->pmu->type)
+               return armpmu_map_raw_event(raw_event_mask, config);
+
+       switch (type) {
        case PERF_TYPE_HARDWARE:
                return armpmu_map_hw_event(event_map, config);
        case PERF_TYPE_HW_CACHE:
@@ -200,7 +201,7 @@ static void
 armpmu_del(struct perf_event *event, int flags)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
-       struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+       struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
 
@@ -217,7 +218,7 @@ static int
 armpmu_add(struct perf_event *event, int flags)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
-       struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+       struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
        struct hw_perf_event *hwc = &event->hw;
        int idx;
        int err = 0;
@@ -274,14 +275,12 @@ validate_group(struct perf_event *event)
 {
        struct perf_event *sibling, *leader = event->group_leader;
        struct pmu_hw_events fake_pmu;
-       DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS);
 
        /*
         * Initialise the fake PMU. We only need to populate the
         * used_mask for the purposes of validation.
         */
-       memset(fake_used_mask, 0, sizeof(fake_used_mask));
-       fake_pmu.used_mask = fake_used_mask;
+       memset(&fake_pmu.used_mask, 0, sizeof(fake_pmu.used_mask));
 
        if (!validate_event(&fake_pmu, leader))
                return -EINVAL;
@@ -305,17 +304,21 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
        int ret;
        u64 start_clock, finish_clock;
 
-       if (irq_is_percpu(irq))
-               dev = *(void **)dev;
-       armpmu = dev;
+       /*
+        * we request the IRQ with a (possibly percpu) struct arm_pmu**, but
+        * the handlers expect a struct arm_pmu*. The percpu_irq framework will
+        * do any necessary shifting, we just need to perform the first
+        * dereference.
+        */
+       armpmu = *(void **)dev;
        plat_device = armpmu->plat_device;
        plat = dev_get_platdata(&plat_device->dev);
 
        start_clock = sched_clock();
        if (plat && plat->handle_irq)
-               ret = plat->handle_irq(irq, dev, armpmu->handle_irq);
+               ret = plat->handle_irq(irq, armpmu, armpmu->handle_irq);
        else
-               ret = armpmu->handle_irq(irq, dev);
+               ret = armpmu->handle_irq(irq, armpmu);
        finish_clock = sched_clock();
 
        perf_sample_event_took(finish_clock - start_clock);
@@ -468,7 +471,7 @@ static int armpmu_event_init(struct perf_event *event)
 static void armpmu_enable(struct pmu *pmu)
 {
        struct arm_pmu *armpmu = to_arm_pmu(pmu);
-       struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+       struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
        int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
 
        if (enabled)
@@ -533,130 +536,3 @@ int armpmu_register(struct arm_pmu *armpmu, int type)
        return perf_pmu_register(&armpmu->pmu, armpmu->name, type);
 }
 
-/*
- * Callchain handling code.
- */
-
-/*
- * The registers we're interested in are at the end of the variable
- * length saved register structure. The fp points at the end of this
- * structure so the address of this struct is:
- * (struct frame_tail *)(xxx->fp)-1
- *
- * This code has been adapted from the ARM OProfile support.
- */
-struct frame_tail {
-       struct frame_tail __user *fp;
-       unsigned long sp;
-       unsigned long lr;
-} __attribute__((packed));
-
-/*
- * Get the return address for a single stackframe and return a pointer to the
- * next frame tail.
- */
-static struct frame_tail __user *
-user_backtrace(struct frame_tail __user *tail,
-              struct perf_callchain_entry *entry)
-{
-       struct frame_tail buftail;
-       unsigned long err;
-
-       if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
-               return NULL;
-
-       pagefault_disable();
-       err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
-       pagefault_enable();
-
-       if (err)
-               return NULL;
-
-       perf_callchain_store(entry, buftail.lr);
-
-       /*
-        * Frame pointers should strictly progress back up the stack
-        * (towards higher addresses).
-        */
-       if (tail + 1 >= buftail.fp)
-               return NULL;
-
-       return buftail.fp - 1;
-}
-
-void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
-{
-       struct frame_tail __user *tail;
-
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-               /* We don't support guest os callchain now */
-               return;
-       }
-
-       perf_callchain_store(entry, regs->ARM_pc);
-
-       if (!current->mm)
-               return;
-
-       tail = (struct frame_tail __user *)regs->ARM_fp - 1;
-
-       while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
-              tail && !((unsigned long)tail & 0x3))
-               tail = user_backtrace(tail, entry);
-}
-
-/*
- * Gets called by walk_stackframe() for every stackframe. This will be called
- * whist unwinding the stackframe and is like a subroutine return so we use
- * the PC.
- */
-static int
-callchain_trace(struct stackframe *fr,
-               void *data)
-{
-       struct perf_callchain_entry *entry = data;
-       perf_callchain_store(entry, fr->pc);
-       return 0;
-}
-
-void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
-{
-       struct stackframe fr;
-
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-               /* We don't support guest os callchain now */
-               return;
-       }
-
-       arm_get_current_stackframe(regs, &fr);
-       walk_stackframe(&fr, callchain_trace, entry);
-}
-
-unsigned long perf_instruction_pointer(struct pt_regs *regs)
-{
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
-               return perf_guest_cbs->get_guest_ip();
-
-       return instruction_pointer(regs);
-}
-
-unsigned long perf_misc_flags(struct pt_regs *regs)
-{
-       int misc = 0;
-
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-               if (perf_guest_cbs->is_user_mode())
-                       misc |= PERF_RECORD_MISC_GUEST_USER;
-               else
-                       misc |= PERF_RECORD_MISC_GUEST_KERNEL;
-       } else {
-               if (user_mode(regs))
-                       misc |= PERF_RECORD_MISC_USER;
-               else
-                       misc |= PERF_RECORD_MISC_KERNEL;
-       }
-
-       return misc;
-}
index eb2c4d55666b49776d45281de430c8af8b0790cc..dd9acc95ebc0ef3df443ac9e48b3aa4b06d7b73b 100644 (file)
 /* Set at runtime when we know what CPU type we are. */
 static struct arm_pmu *cpu_pmu;
 
-static DEFINE_PER_CPU(struct arm_pmu *, percpu_pmu);
-static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
-static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
-static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
-
 /*
  * Despite the names, these two functions are CPU-specific and are used
  * by the OProfile/perf code.
@@ -69,11 +64,6 @@ EXPORT_SYMBOL_GPL(perf_num_counters);
 #include "perf_event_v6.c"
 #include "perf_event_v7.c"
 
-static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
-{
-       return this_cpu_ptr(&cpu_hw_events);
-}
-
 static void cpu_pmu_enable_percpu_irq(void *data)
 {
        int irq = *(int *)data;
@@ -92,20 +82,21 @@ static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
 {
        int i, irq, irqs;
        struct platform_device *pmu_device = cpu_pmu->plat_device;
+       struct pmu_hw_events __percpu *hw_events = cpu_pmu->hw_events;
 
        irqs = min(pmu_device->num_resources, num_possible_cpus());
 
        irq = platform_get_irq(pmu_device, 0);
        if (irq >= 0 && irq_is_percpu(irq)) {
                on_each_cpu(cpu_pmu_disable_percpu_irq, &irq, 1);
-               free_percpu_irq(irq, &percpu_pmu);
+               free_percpu_irq(irq, &hw_events->percpu_pmu);
        } else {
                for (i = 0; i < irqs; ++i) {
                        if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
                                continue;
                        irq = platform_get_irq(pmu_device, i);
                        if (irq >= 0)
-                               free_irq(irq, cpu_pmu);
+                               free_irq(irq, per_cpu_ptr(&hw_events->percpu_pmu, i));
                }
        }
 }
@@ -114,19 +105,21 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 {
        int i, err, irq, irqs;
        struct platform_device *pmu_device = cpu_pmu->plat_device;
+       struct pmu_hw_events __percpu *hw_events = cpu_pmu->hw_events;
 
        if (!pmu_device)
                return -ENODEV;
 
        irqs = min(pmu_device->num_resources, num_possible_cpus());
        if (irqs < 1) {
-               printk_once("perf/ARM: No irqs for PMU defined, sampling events not supported\n");
+               pr_warn_once("perf/ARM: No irqs for PMU defined, sampling events not supported\n");
                return 0;
        }
 
        irq = platform_get_irq(pmu_device, 0);
        if (irq >= 0 && irq_is_percpu(irq)) {
-               err = request_percpu_irq(irq, handler, "arm-pmu", &percpu_pmu);
+               err = request_percpu_irq(irq, handler, "arm-pmu",
+                                        &hw_events->percpu_pmu);
                if (err) {
                        pr_err("unable to request IRQ%d for ARM PMU counters\n",
                                irq);
@@ -153,7 +146,7 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 
                        err = request_irq(irq, handler,
                                          IRQF_NOBALANCING | IRQF_NO_THREAD, "arm-pmu",
-                                         cpu_pmu);
+                                         per_cpu_ptr(&hw_events->percpu_pmu, i));
                        if (err) {
                                pr_err("unable to request IRQ%d for ARM PMU counters\n",
                                        irq);
@@ -167,18 +160,50 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
        return 0;
 }
 
-static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
+/*
+ * PMU hardware loses all context when a CPU goes offline.
+ * When a CPU is hotplugged back in, since some hardware registers are
+ * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
+ * junk values out of them.
+ */
+static int cpu_pmu_notify(struct notifier_block *b, unsigned long action,
+                         void *hcpu)
+{
+       struct arm_pmu *pmu = container_of(b, struct arm_pmu, hotplug_nb);
+
+       if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
+               return NOTIFY_DONE;
+
+       if (pmu->reset)
+               pmu->reset(pmu);
+       else
+               return NOTIFY_DONE;
+
+       return NOTIFY_OK;
+}
+
+static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
 {
+       int err;
        int cpu;
+       struct pmu_hw_events __percpu *cpu_hw_events;
+
+       cpu_hw_events = alloc_percpu(struct pmu_hw_events);
+       if (!cpu_hw_events)
+               return -ENOMEM;
+
+       cpu_pmu->hotplug_nb.notifier_call = cpu_pmu_notify;
+       err = register_cpu_notifier(&cpu_pmu->hotplug_nb);
+       if (err)
+               goto out_hw_events;
+
        for_each_possible_cpu(cpu) {
-               struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
-               events->events = per_cpu(hw_events, cpu);
-               events->used_mask = per_cpu(used_mask, cpu);
+               struct pmu_hw_events *events = per_cpu_ptr(cpu_hw_events, cpu);
                raw_spin_lock_init(&events->pmu_lock);
-               per_cpu(percpu_pmu, cpu) = cpu_pmu;
+               events->percpu_pmu = cpu_pmu;
        }
 
-       cpu_pmu->get_hw_events  = cpu_pmu_get_cpu_events;
+       cpu_pmu->hw_events      = cpu_hw_events;
        cpu_pmu->request_irq    = cpu_pmu_request_irq;
        cpu_pmu->free_irq       = cpu_pmu_free_irq;
 
@@ -189,31 +214,19 @@ static void cpu_pmu_init(struct arm_pmu *cpu_pmu)
        /* If no interrupts available, set the corresponding capability flag */
        if (!platform_get_irq(cpu_pmu->plat_device, 0))
                cpu_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
-}
-
-/*
- * PMU hardware loses all context when a CPU goes offline.
- * When a CPU is hotplugged back in, since some hardware registers are
- * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
- * junk values out of them.
- */
-static int cpu_pmu_notify(struct notifier_block *b, unsigned long action,
-                         void *hcpu)
-{
-       if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
-               return NOTIFY_DONE;
 
-       if (cpu_pmu && cpu_pmu->reset)
-               cpu_pmu->reset(cpu_pmu);
-       else
-               return NOTIFY_DONE;
+       return 0;
 
-       return NOTIFY_OK;
+out_hw_events:
+       free_percpu(cpu_hw_events);
+       return err;
 }
 
-static struct notifier_block cpu_pmu_hotplug_notifier = {
-       .notifier_call = cpu_pmu_notify,
-};
+static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu)
+{
+       unregister_cpu_notifier(&cpu_pmu->hotplug_nb);
+       free_percpu(cpu_pmu->hw_events);
+}
 
 /*
  * PMU platform driver and devicetree bindings.
@@ -241,48 +254,34 @@ static struct platform_device_id cpu_pmu_plat_device_ids[] = {
        {},
 };
 
+static const struct pmu_probe_info pmu_probe_table[] = {
+       ARM_PMU_PROBE(ARM_CPU_PART_ARM1136, armv6_1136_pmu_init),
+       ARM_PMU_PROBE(ARM_CPU_PART_ARM1156, armv6_1156_pmu_init),
+       ARM_PMU_PROBE(ARM_CPU_PART_ARM1176, armv6_1176_pmu_init),
+       ARM_PMU_PROBE(ARM_CPU_PART_ARM11MPCORE, armv6mpcore_pmu_init),
+       ARM_PMU_PROBE(ARM_CPU_PART_CORTEX_A8, armv7_a8_pmu_init),
+       ARM_PMU_PROBE(ARM_CPU_PART_CORTEX_A9, armv7_a9_pmu_init),
+       XSCALE_PMU_PROBE(ARM_CPU_XSCALE_ARCH_V1, xscale1pmu_init),
+       XSCALE_PMU_PROBE(ARM_CPU_XSCALE_ARCH_V2, xscale2pmu_init),
+       { /* sentinel value */ }
+};
+
 /*
  * CPU PMU identification and probing.
  */
 static int probe_current_pmu(struct arm_pmu *pmu)
 {
        int cpu = get_cpu();
+       unsigned int cpuid = read_cpuid_id();
        int ret = -ENODEV;
+       const struct pmu_probe_info *info;
 
        pr_info("probing PMU on CPU %d\n", cpu);
 
-       switch (read_cpuid_part()) {
-       /* ARM Ltd CPUs. */
-       case ARM_CPU_PART_ARM1136:
-               ret = armv6_1136_pmu_init(pmu);
-               break;
-       case ARM_CPU_PART_ARM1156:
-               ret = armv6_1156_pmu_init(pmu);
-               break;
-       case ARM_CPU_PART_ARM1176:
-               ret = armv6_1176_pmu_init(pmu);
-               break;
-       case ARM_CPU_PART_ARM11MPCORE:
-               ret = armv6mpcore_pmu_init(pmu);
-               break;
-       case ARM_CPU_PART_CORTEX_A8:
-               ret = armv7_a8_pmu_init(pmu);
-               break;
-       case ARM_CPU_PART_CORTEX_A9:
-               ret = armv7_a9_pmu_init(pmu);
-               break;
-
-       default:
-               if (read_cpuid_implementor() == ARM_CPU_IMP_INTEL) {
-                       switch (xscale_cpu_arch_version()) {
-                       case ARM_CPU_XSCALE_ARCH_V1:
-                               ret = xscale1pmu_init(pmu);
-                               break;
-                       case ARM_CPU_XSCALE_ARCH_V2:
-                               ret = xscale2pmu_init(pmu);
-                               break;
-                       }
-               }
+       for (info = pmu_probe_table; info->init != NULL; info++) {
+               if ((cpuid & info->mask) != info->cpuid)
+                       continue;
+               ret = info->init(pmu);
                break;
        }
 
@@ -299,13 +298,13 @@ static int cpu_pmu_device_probe(struct platform_device *pdev)
        int ret = -ENODEV;
 
        if (cpu_pmu) {
-               pr_info("attempt to register multiple PMU devices!");
+               pr_info("attempt to register multiple PMU devices!\n");
                return -ENOSPC;
        }
 
        pmu = kzalloc(sizeof(struct arm_pmu), GFP_KERNEL);
        if (!pmu) {
-               pr_info("failed to allocate PMU device!");
+               pr_info("failed to allocate PMU device!\n");
                return -ENOMEM;
        }
 
@@ -320,18 +319,24 @@ static int cpu_pmu_device_probe(struct platform_device *pdev)
        }
 
        if (ret) {
-               pr_info("failed to probe PMU!");
+               pr_info("failed to probe PMU!\n");
                goto out_free;
        }
 
-       cpu_pmu_init(cpu_pmu);
-       ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW);
+       ret = cpu_pmu_init(cpu_pmu);
+       if (ret)
+               goto out_free;
 
-       if (!ret)
-               return 0;
+       ret = armpmu_register(cpu_pmu, -1);
+       if (ret)
+               goto out_destroy;
 
+       return 0;
+
+out_destroy:
+       cpu_pmu_destroy(cpu_pmu);
 out_free:
-       pr_info("failed to register PMU devices!");
+       pr_info("failed to register PMU devices!\n");
        kfree(pmu);
        return ret;
 }
@@ -348,16 +353,6 @@ static struct platform_driver cpu_pmu_driver = {
 
 static int __init register_pmu_driver(void)
 {
-       int err;
-
-       err = register_cpu_notifier(&cpu_pmu_hotplug_notifier);
-       if (err)
-               return err;
-
-       err = platform_driver_register(&cpu_pmu_driver);
-       if (err)
-               unregister_cpu_notifier(&cpu_pmu_hotplug_notifier);
-
-       return err;
+       return platform_driver_register(&cpu_pmu_driver);
 }
 device_initcall(register_pmu_driver);
index abfeb04f3213e1fbd6fb93e07114d7475e249922..f2ffd5c542ed99779f8a65aa22477d1cd78f74d6 100644 (file)
@@ -262,7 +262,7 @@ static void armv6pmu_enable_event(struct perf_event *event)
        unsigned long val, mask, evt, flags;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        if (ARMV6_CYCLE_COUNTER == idx) {
@@ -300,7 +300,7 @@ armv6pmu_handle_irq(int irq_num,
        unsigned long pmcr = armv6_pmcr_read();
        struct perf_sample_data data;
        struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
-       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
        struct pt_regs *regs;
        int idx;
 
@@ -356,7 +356,7 @@ armv6pmu_handle_irq(int irq_num,
 static void armv6pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = armv6_pmcr_read();
@@ -368,7 +368,7 @@ static void armv6pmu_start(struct arm_pmu *cpu_pmu)
 static void armv6pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = armv6_pmcr_read();
@@ -409,7 +409,7 @@ static void armv6pmu_disable_event(struct perf_event *event)
        unsigned long val, mask, evt, flags;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        if (ARMV6_CYCLE_COUNTER == idx) {
@@ -444,7 +444,7 @@ static void armv6mpcore_pmu_disable_event(struct perf_event *event)
        unsigned long val, mask, flags, evt = 0;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        if (ARMV6_CYCLE_COUNTER == idx) {
index 116758b77f930bace4b6c59b4ee0dcc71963690b..8993770c47de7ebdb59e5151bf2c4bc7948e19fd 100644 (file)
@@ -564,13 +564,11 @@ static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx)
        return pmnc & BIT(ARMV7_IDX_TO_COUNTER(idx));
 }
 
-static inline int armv7_pmnc_select_counter(int idx)
+static inline void armv7_pmnc_select_counter(int idx)
 {
        u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter));
        isb();
-
-       return idx;
 }
 
 static inline u32 armv7pmu_read_counter(struct perf_event *event)
@@ -580,13 +578,15 @@ static inline u32 armv7pmu_read_counter(struct perf_event *event)
        int idx = hwc->idx;
        u32 value = 0;
 
-       if (!armv7_pmnc_counter_valid(cpu_pmu, idx))
+       if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
                pr_err("CPU%u reading wrong counter %d\n",
                        smp_processor_id(), idx);
-       else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+       } else if (idx == ARMV7_IDX_CYCLE_COUNTER) {
                asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
-       else if (armv7_pmnc_select_counter(idx) == idx)
+       } else {
+               armv7_pmnc_select_counter(idx);
                asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value));
+       }
 
        return value;
 }
@@ -597,45 +597,43 @@ static inline void armv7pmu_write_counter(struct perf_event *event, u32 value)
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
 
-       if (!armv7_pmnc_counter_valid(cpu_pmu, idx))
+       if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
                pr_err("CPU%u writing wrong counter %d\n",
                        smp_processor_id(), idx);
-       else if (idx == ARMV7_IDX_CYCLE_COUNTER)
+       } else if (idx == ARMV7_IDX_CYCLE_COUNTER) {
                asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
-       else if (armv7_pmnc_select_counter(idx) == idx)
+       } else {
+               armv7_pmnc_select_counter(idx);
                asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
+       }
 }
 
 static inline void armv7_pmnc_write_evtsel(int idx, u32 val)
 {
-       if (armv7_pmnc_select_counter(idx) == idx) {
-               val &= ARMV7_EVTYPE_MASK;
-               asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
-       }
+       armv7_pmnc_select_counter(idx);
+       val &= ARMV7_EVTYPE_MASK;
+       asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
 }
 
-static inline int armv7_pmnc_enable_counter(int idx)
+static inline void armv7_pmnc_enable_counter(int idx)
 {
        u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter)));
-       return idx;
 }
 
-static inline int armv7_pmnc_disable_counter(int idx)
+static inline void armv7_pmnc_disable_counter(int idx)
 {
        u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter)));
-       return idx;
 }
 
-static inline int armv7_pmnc_enable_intens(int idx)
+static inline void armv7_pmnc_enable_intens(int idx)
 {
        u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter)));
-       return idx;
 }
 
-static inline int armv7_pmnc_disable_intens(int idx)
+static inline void armv7_pmnc_disable_intens(int idx)
 {
        u32 counter = ARMV7_IDX_TO_COUNTER(idx);
        asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter)));
@@ -643,8 +641,6 @@ static inline int armv7_pmnc_disable_intens(int idx)
        /* Clear the overflow flag in case an interrupt is pending. */
        asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (BIT(counter)));
        isb();
-
-       return idx;
 }
 
 static inline u32 armv7_pmnc_getreset_flags(void)
@@ -667,34 +663,34 @@ static void armv7_pmnc_dump_regs(struct arm_pmu *cpu_pmu)
        u32 val;
        unsigned int cnt;
 
-       printk(KERN_INFO "PMNC registers dump:\n");
+       pr_info("PMNC registers dump:\n");
 
        asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
-       printk(KERN_INFO "PMNC  =0x%08x\n", val);
+       pr_info("PMNC  =0x%08x\n", val);
 
        asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
-       printk(KERN_INFO "CNTENS=0x%08x\n", val);
+       pr_info("CNTENS=0x%08x\n", val);
 
        asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
-       printk(KERN_INFO "INTENS=0x%08x\n", val);
+       pr_info("INTENS=0x%08x\n", val);
 
        asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
-       printk(KERN_INFO "FLAGS =0x%08x\n", val);
+       pr_info("FLAGS =0x%08x\n", val);
 
        asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
-       printk(KERN_INFO "SELECT=0x%08x\n", val);
+       pr_info("SELECT=0x%08x\n", val);
 
        asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
-       printk(KERN_INFO "CCNT  =0x%08x\n", val);
+       pr_info("CCNT  =0x%08x\n", val);
 
        for (cnt = ARMV7_IDX_COUNTER0;
                        cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) {
                armv7_pmnc_select_counter(cnt);
                asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
-               printk(KERN_INFO "CNT[%d] count =0x%08x\n",
+               pr_info("CNT[%d] count =0x%08x\n",
                        ARMV7_IDX_TO_COUNTER(cnt), val);
                asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
-               printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
+               pr_info("CNT[%d] evtsel=0x%08x\n",
                        ARMV7_IDX_TO_COUNTER(cnt), val);
        }
 }
@@ -705,7 +701,7 @@ static void armv7pmu_enable_event(struct perf_event *event)
        unsigned long flags;
        struct hw_perf_event *hwc = &event->hw;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
@@ -751,7 +747,7 @@ static void armv7pmu_disable_event(struct perf_event *event)
        unsigned long flags;
        struct hw_perf_event *hwc = &event->hw;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        if (!armv7_pmnc_counter_valid(cpu_pmu, idx)) {
@@ -783,7 +779,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
        u32 pmnc;
        struct perf_sample_data data;
        struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
-       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
        struct pt_regs *regs;
        int idx;
 
@@ -843,7 +839,7 @@ static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
 static void armv7pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        /* Enable all counters */
@@ -854,7 +850,7 @@ static void armv7pmu_start(struct arm_pmu *cpu_pmu)
 static void armv7pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        /* Disable all counters */
@@ -1287,7 +1283,7 @@ static void krait_pmu_disable_event(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        /* Disable counter and interrupt */
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
@@ -1313,7 +1309,7 @@ static void krait_pmu_enable_event(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        /*
         * Enable counter and interrupt, and set the counter to count
index 08da0af550b7912e184080680347f7d9dccba7cf..8af9f1f82c68a0f61b219bb2c23e29856e660632 100644 (file)
@@ -138,7 +138,7 @@ xscale1pmu_handle_irq(int irq_num, void *dev)
        unsigned long pmnc;
        struct perf_sample_data data;
        struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
-       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
        struct pt_regs *regs;
        int idx;
 
@@ -198,7 +198,7 @@ static void xscale1pmu_enable_event(struct perf_event *event)
        unsigned long val, mask, evt, flags;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        switch (idx) {
@@ -234,7 +234,7 @@ static void xscale1pmu_disable_event(struct perf_event *event)
        unsigned long val, mask, evt, flags;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        switch (idx) {
@@ -287,7 +287,7 @@ xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
 static void xscale1pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale1pmu_read_pmnc();
@@ -299,7 +299,7 @@ static void xscale1pmu_start(struct arm_pmu *cpu_pmu)
 static void xscale1pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale1pmu_read_pmnc();
@@ -485,7 +485,7 @@ xscale2pmu_handle_irq(int irq_num, void *dev)
        unsigned long pmnc, of_flags;
        struct perf_sample_data data;
        struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev;
-       struct pmu_hw_events *cpuc = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
        struct pt_regs *regs;
        int idx;
 
@@ -539,7 +539,7 @@ static void xscale2pmu_enable_event(struct perf_event *event)
        unsigned long flags, ien, evtsel;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        ien = xscale2pmu_read_int_enable();
@@ -585,7 +585,7 @@ static void xscale2pmu_disable_event(struct perf_event *event)
        unsigned long flags, ien, evtsel, of_flags;
        struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
        struct hw_perf_event *hwc = &event->hw;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
        int idx = hwc->idx;
 
        ien = xscale2pmu_read_int_enable();
@@ -651,7 +651,7 @@ out:
 static void xscale2pmu_start(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
@@ -663,7 +663,7 @@ static void xscale2pmu_start(struct arm_pmu *cpu_pmu)
 static void xscale2pmu_stop(struct arm_pmu *cpu_pmu)
 {
        unsigned long flags, val;
-       struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+       struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
        val = xscale2pmu_read_pmnc();
index 0c8b10801d36ad6a25806892ea283c7b93d28f61..9f5d81881eb6da9bdd599a7321cf83fbdcb0a0e2 100644 (file)
@@ -533,8 +533,6 @@ static int bad_syscall(int n, struct pt_regs *regs)
        return regs->ARM_r0;
 }
 
-static long do_cache_op_restart(struct restart_block *);
-
 static inline int
 __do_cache_op(unsigned long start, unsigned long end)
 {
@@ -543,24 +541,8 @@ __do_cache_op(unsigned long start, unsigned long end)
        do {
                unsigned long chunk = min(PAGE_SIZE, end - start);
 
-               if (signal_pending(current)) {
-                       struct thread_info *ti = current_thread_info();
-
-                       ti->restart_block = (struct restart_block) {
-                               .fn     = do_cache_op_restart,
-                       };
-
-                       ti->arm_restart_block = (struct arm_restart_block) {
-                               {
-                                       .cache = {
-                                               .start  = start,
-                                               .end    = end,
-                                       },
-                               },
-                       };
-
-                       return -ERESTART_RESTARTBLOCK;
-               }
+               if (fatal_signal_pending(current))
+                       return 0;
 
                ret = flush_cache_user_range(start, start + chunk);
                if (ret)
@@ -573,15 +555,6 @@ __do_cache_op(unsigned long start, unsigned long end)
        return 0;
 }
 
-static long do_cache_op_restart(struct restart_block *unused)
-{
-       struct arm_restart_block *restart_block;
-
-       restart_block = &current_thread_info()->arm_restart_block;
-       return __do_cache_op(restart_block->cache.start,
-                            restart_block->cache.end);
-}
-
 static inline int
 do_cache_op(unsigned long start, unsigned long end, int flags)
 {
index 57a403a5c22bf9e174ec88a0377b4ab07c3b0a29..8664ff17cbbeaf531b03174e1524cc00a6e86849 100644 (file)
@@ -197,7 +197,8 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
        pgd = pgdp + pgd_index(addr);
        do {
                next = kvm_pgd_addr_end(addr, end);
-               unmap_puds(kvm, pgd, addr, next);
+               if (!pgd_none(*pgd))
+                       unmap_puds(kvm, pgd, addr, next);
        } while (pgd++, addr = next, addr != end);
 }
 
@@ -834,6 +835,11 @@ static bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
        return kvm_vcpu_dabt_iswrite(vcpu);
 }
 
+static bool kvm_is_device_pfn(unsigned long pfn)
+{
+       return !pfn_valid(pfn);
+}
+
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                          struct kvm_memory_slot *memslot, unsigned long hva,
                          unsigned long fault_status)
@@ -904,7 +910,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
        if (is_error_pfn(pfn))
                return -EFAULT;
 
-       if (kvm_is_mmio_pfn(pfn))
+       if (kvm_is_device_pfn(pfn))
                mem_type = PAGE_S2_DEVICE;
 
        spin_lock(&kvm->mmu_lock);
diff --git a/arch/arm/mach-asm9260/Kconfig b/arch/arm/mach-asm9260/Kconfig
new file mode 100644 (file)
index 0000000..8423be7
--- /dev/null
@@ -0,0 +1,6 @@
+config MACH_ASM9260
+       bool "Alphascale ASM9260"
+       depends on ARCH_MULTI_V5
+       select CPU_ARM926T
+       help
+         Support for Alphascale ASM9260 based platform.
index 0e6d548b70d9720d78c55c8a3341402486bc6dc9..2395c68b3e327094fa7048228bc1067173ac4c99 100644 (file)
@@ -15,27 +15,10 @@ config HAVE_AT91_DBGU1
 config HAVE_AT91_DBGU2
        bool
 
-config AT91_USE_OLD_CLK
-       bool
-
-config AT91_PMC_UNIT
-       bool
-       default !ARCH_AT91X40
-
 config COMMON_CLK_AT91
        bool
-       default AT91_PMC_UNIT && USE_OF && !AT91_USE_OLD_CLK
        select COMMON_CLK
 
-config OLD_CLK_AT91
-       bool
-       default AT91_PMC_UNIT && AT91_USE_OLD_CLK
-
-config OLD_IRQ_AT91
-       bool
-       select MULTI_IRQ_HANDLER
-       select SPARSE_IRQ
-
 config HAVE_AT91_SMD
        bool
 
@@ -44,20 +27,22 @@ config HAVE_AT91_H32MX
 
 config SOC_AT91SAM9
        bool
-       select ATMEL_AIC_IRQ if !OLD_IRQ_AT91
+       select ATMEL_AIC_IRQ
+       select COMMON_CLK_AT91
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
-       select MEMORY if USE_OF
-       select ATMEL_SDRAMC if USE_OF
+       select MEMORY
+       select ATMEL_SDRAMC
 
 config SOC_SAMA5
        bool
        select ATMEL_AIC5_IRQ
+       select COMMON_CLK_AT91
        select CPU_V7
        select GENERIC_CLOCKEVENTS
-       select USE_OF
        select MEMORY
        select ATMEL_SDRAMC
+       select PHYLIB if NETDEVICES
 
 menu "Atmel AT91 System-on-Chip"
 
@@ -65,16 +50,6 @@ choice
 
        prompt "Core type"
 
-config ARCH_AT91X40
-       bool "ARM7 AT91X40"
-       depends on !MMU
-       select CPU_ARM7TDMI
-       select ARCH_USES_GETTIMEOFFSET
-       select OLD_IRQ_AT91
-
-       help
-         Select this if you are using one of Atmel's AT91X40 SoC.
-
 config SOC_SAM_V4_V5
        bool "ARM9 AT91SAM9/AT91RM9200"
        help
@@ -122,7 +97,8 @@ endif
 if SOC_SAM_V4_V5
 config SOC_AT91RM9200
        bool "AT91RM9200"
-       select ATMEL_AIC_IRQ if !OLD_IRQ_AT91
+       select ATMEL_AIC_IRQ
+       select COMMON_CLK_AT91
        select CPU_ARM920T
        select GENERIC_CLOCKEVENTS
        select HAVE_AT91_DBGU0
@@ -198,37 +174,11 @@ config SOC_AT91SAM9N12
 # ----------------------------------------------------------
 endif # SOC_SAM_V4_V5
 
-
-if SOC_SAM_V4_V5 || ARCH_AT91X40
-source arch/arm/mach-at91/Kconfig.non_dt
-endif
-
-comment "Generic Board Type"
-
 config MACH_AT91RM9200_DT
-       bool "Atmel AT91RM9200 Evaluation Kits with device-tree support"
-       depends on SOC_AT91RM9200
-       select USE_OF
-       help
-         Select this if you want to experiment device-tree with
-         an Atmel RM9200 Evaluation Kit.
+       def_bool SOC_AT91RM9200
 
 config MACH_AT91SAM9_DT
-       bool "Atmel AT91SAM Evaluation Kits with device-tree support"
-       depends on SOC_AT91SAM9
-       select USE_OF
-       help
-         Select this if you want to experiment device-tree with
-         an Atmel Evaluation Kit.
-
-config MACH_SAMA5_DT
-       bool "Atmel SAMA5 Evaluation Kits with device-tree support"
-       depends on SOC_SAMA5
-       select USE_OF
-       select PHYLIB if NETDEVICES
-       help
-         Select this if you want to experiment device-tree with
-         an Atmel Evaluation Kit.
+       def_bool SOC_AT91SAM9
 
 # ----------------------------------------------------------
 
@@ -251,7 +201,7 @@ config AT91_TIMER_HZ
        int "Kernel HZ (jiffies per second)"
        range 32 1024
        depends on ARCH_AT91
-       default "128" if ARCH_AT91RM9200
+       default "128" if SOC_AT91RM9200
        default "100"
        help
          On AT91rm9200 chips where you're using a system clock derived
diff --git a/arch/arm/mach-at91/Kconfig.non_dt b/arch/arm/mach-at91/Kconfig.non_dt
deleted file mode 100644 (file)
index d8e8821..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-menu "Atmel Non-DT world"
-
-config HAVE_AT91_DATAFLASH_CARD
-       bool
-
-choice
-       prompt "Atmel AT91 Processor Devices for non DT boards"
-       depends on !ARCH_AT91X40
-
-config ARCH_AT91_NONE
-       bool "None"
-
-config ARCH_AT91RM9200
-       bool "AT91RM9200"
-       select SOC_AT91RM9200
-       select AT91_USE_OLD_CLK
-       select OLD_IRQ_AT91
-
-config ARCH_AT91SAM9260
-       bool "AT91SAM9260 or AT91SAM9XE or AT91SAM9G20"
-       select SOC_AT91SAM9260
-       select AT91_USE_OLD_CLK
-       select OLD_IRQ_AT91
-
-config ARCH_AT91SAM9261
-       bool "AT91SAM9261 or AT91SAM9G10"
-       select SOC_AT91SAM9261
-       select AT91_USE_OLD_CLK
-       select OLD_IRQ_AT91
-
-config ARCH_AT91SAM9263
-       bool "AT91SAM9263"
-       select SOC_AT91SAM9263
-       select AT91_USE_OLD_CLK
-       select OLD_IRQ_AT91
-
-config ARCH_AT91SAM9RL
-       bool "AT91SAM9RL"
-       select SOC_AT91SAM9RL
-       select AT91_USE_OLD_CLK
-       select OLD_IRQ_AT91
-
-config ARCH_AT91SAM9G45
-       bool "AT91SAM9G45"
-       select SOC_AT91SAM9G45
-       select AT91_USE_OLD_CLK
-       select OLD_IRQ_AT91
-
-endchoice
-
-config ARCH_AT91SAM9G20
-       bool
-       select ARCH_AT91SAM9260
-
-config ARCH_AT91SAM9G10
-       bool
-       select ARCH_AT91SAM9261
-
-# ----------------------------------------------------------
-
-if ARCH_AT91RM9200
-
-comment "AT91RM9200 Board Type"
-
-config MACH_ONEARM
-       bool "Ajeco 1ARM Single Board Computer"
-       help
-         Select this if you are using Ajeco's 1ARM Single Board Computer.
-         <http://www.ajeco.fi/>
-
-config MACH_AT91RM9200EK
-       bool "Atmel AT91RM9200-EK Evaluation Kit"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit.
-         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3507>
-
-config MACH_CSB337
-       bool "Cogent CSB337"
-       help
-         Select this if you are using Cogent's CSB337 board.
-         <http://www.cogcomp.com/csb_csb337.htm>
-
-config MACH_CSB637
-       bool "Cogent CSB637"
-       help
-         Select this if you are using Cogent's CSB637 board.
-         <http://www.cogcomp.com/csb_csb637.htm>
-
-config MACH_CARMEVA
-       bool "Conitec ARM&EVA"
-       help
-         Select this if you are using Conitec's AT91RM9200-MCU-Module.
-         <http://www.conitec.net/english/linuxboard.php>
-
-config MACH_ATEB9200
-       bool "Embest ATEB9200"
-       help
-         Select this if you are using Embest's ATEB9200 board.
-         <http://www.embedinfo.com/english/product/ATEB9200.asp>
-
-config MACH_KB9200
-       bool "KwikByte KB920x"
-       help
-         Select this if you are using KwikByte's KB920x board.
-         <http://www.kwikbyte.com/KB9202.html>
-
-config MACH_PICOTUX2XX
-       bool "picotux 200"
-       help
-         Select this if you are using a picotux 200.
-         <http://www.picotux.com/>
-
-config MACH_KAFA
-       bool "Sperry-Sun KAFA board"
-       help
-         Select this if you are using Sperry-Sun's KAFA board.
-
-config MACH_ECBAT91
-       bool "emQbit ECB_AT91 SBC"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using emQbit's ECB_AT91 board.
-         <http://wiki.emqbit.com/free-ecb-at91>
-
-config MACH_YL9200
-       bool "ucDragon YL-9200"
-       help
-         Select this if you are using the ucDragon YL-9200 board.
-
-config MACH_CPUAT91
-       bool "Eukrea CPUAT91"
-       help
-         Select this if you are using the Eukrea Electromatique's
-         CPUAT91 board <http://www.eukrea.com/>.
-
-config MACH_ECO920
-       bool "eco920"
-       help
-         Select this if you are using the eco920 board
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9260
-
-comment "AT91SAM9260 Variants"
-
-comment "AT91SAM9260 / AT91SAM9XE Board Type"
-
-config MACH_AT91SAM9260EK
-       bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
-         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
-
-config MACH_CAM60
-       bool "KwikByte KB9260 (CAM60) board"
-       help
-         Select this if you are using KwikByte's KB9260 (CAM60) board based on the Atmel AT91SAM9260.
-         <http://www.kwikbyte.com/KB9260.html>
-
-config MACH_SAM9_L9260
-       bool "Olimex SAM9-L9260 board"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using Olimex's SAM9-L9260 board based on the Atmel AT91SAM9260.
-         <http://www.olimex.com/dev/sam9-L9260.html>
-
-config MACH_AFEB9260
-       bool "Custom afeb9260 board v1"
-       help
-         Select this if you are using custom afeb9260 board based on
-         open hardware design. Select this for revision 1 of the board.
-         <svn://194.85.238.22/home/users/george/svn/arm9eb>
-         <http://groups.google.com/group/arm9fpga-evolution-board>
-
-config MACH_CPU9260
-       bool "Eukrea CPU9260 board"
-       help
-         Select this if you are using a Eukrea Electromatique's
-         CPU9260 Board <http://www.eukrea.com/>
-
-config MACH_FLEXIBITY
-       bool "Flexibity Connect board"
-       help
-         Select this if you are using Flexibity Connect board
-         <http://www.flexibity.com>
-
-comment "AT91SAM9G20 Board Type"
-
-config MACH_AT91SAM9G20EK
-       bool "Atmel AT91SAM9G20-EK Evaluation Kit"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using Atmel's AT91SAM9G20-EK Evaluation Kit
-         that embeds only one SD/MMC slot.
-
-config MACH_AT91SAM9G20EK_2MMC
-       depends on MACH_AT91SAM9G20EK
-       bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
-       help
-         Select this if you are using an Atmel AT91SAM9G20-EK Evaluation Kit
-         with 2 SD/MMC Slots. This is the case for AT91SAM9G20-EK rev. C and
-         onwards.
-         <http://www.atmel.com/tools/SAM9G20-EK.aspx>
-
-config MACH_CPU9G20
-       bool "Eukrea CPU9G20 board"
-       help
-         Select this if you are using a Eukrea Electromatique's
-         CPU9G20 Board <http://www.eukrea.com/>
-
-config MACH_PORTUXG20
-       bool "taskit PortuxG20"
-       help
-         Select this if you are using taskit's PortuxG20.
-         <http://www.taskit.de/en/>
-
-config MACH_STAMP9G20
-       bool "taskit Stamp9G20 CPU module"
-       help
-         Select this if you are using taskit's Stamp9G20 CPU module on its
-         evaluation board.
-         <http://www.taskit.de/en/>
-
-config MACH_PCONTROL_G20
-       bool "PControl G20 CPU module"
-       help
-         Select this if you are using taskit's Stamp9G20 CPU module on this
-         carrier board, being the decentralized unit of a building automation
-         system; featuring nvram, eth-switch, iso-rs485, display, io
-
-config MACH_GSIA18S
-       bool "GS_IA18_S board"
-       help
-         This enables support for the GS_IA18_S board
-         produced by GeoSIG Ltd company. This is an internet accelerograph.
-         <http://www.geosig.com>
-
-config MACH_SNAPPER_9260
-       bool "Bluewater Systems Snapper 9260/9G20 module"
-       help
-         Select this if you are using the Bluewater Systems Snapper 9260 or
-         Snapper 9G20 modules.
-         <http://www.bluewatersys.com/>
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9261
-
-comment "AT91SAM9261 Board Type"
-
-config MACH_AT91SAM9261EK
-       bool "Atmel AT91SAM9261-EK Evaluation Kit"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit.
-         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820>
-
-comment "AT91SAM9G10 Board Type"
-
-config MACH_AT91SAM9G10EK
-       bool "Atmel AT91SAM9G10-EK Evaluation Kit"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using Atmel's AT91SAM9G10-EK Evaluation Kit.
-         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4588>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9263
-
-comment "AT91SAM9263 Board Type"
-
-config MACH_AT91SAM9263EK
-       bool "Atmel AT91SAM9263-EK Evaluation Kit"
-       select HAVE_AT91_DATAFLASH_CARD
-       help
-         Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
-         <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9RL
-
-comment "AT91SAM9RL Board Type"
-
-config MACH_AT91SAM9RLEK
-       bool "Atmel AT91SAM9RL-EK Evaluation Kit"
-       help
-         Select this if you are using Atmel's AT91SAM9RL-EK Evaluation Kit.
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91SAM9G45
-
-comment "AT91SAM9G45 Board Type"
-
-config MACH_AT91SAM9M10G45EK
-       bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
-       help
-         Select this if you are using Atmel's AT91SAM9M10G45-EK Evaluation Kit.
-         Those boards can be populated with any SoC of AT91SAM9G45 or AT91SAM9M10
-         families: AT91SAM9G45, AT91SAM9G46, AT91SAM9M10 and AT91SAM9M11.
-         <http://www.atmel.com/tools/SAM9M10-G45-EK.aspx>
-
-endif
-
-# ----------------------------------------------------------
-
-if ARCH_AT91X40
-
-comment "AT91X40 Board Type"
-
-config MACH_AT91EB01
-       bool "Atmel AT91EB01 Evaluation Kit"
-       help
-         Select this if you are using Atmel's AT91EB01 Evaluation Kit.
-         It is also a popular target for simulators such as GDB's
-         ARM simulator (commonly known as the ARMulator) and the
-         Skyeye simulator.
-
-endif
-
-# ----------------------------------------------------------
-
-comment "AT91 Board Options"
-
-config MTD_AT91_DATAFLASH_CARD
-       bool "Enable DataFlash Card support"
-       depends on HAVE_AT91_DATAFLASH_CARD
-       help
-         Enable support for the DataFlash card.
-
-endmenu
index 1b9ae0257a6eac6321c94bea9ccde88a286731fd..7b6424d40764560310bbea92cbbdbde06c88c881 100644 (file)
@@ -2,10 +2,8 @@
 # Makefile for the linux kernel.
 #
 
-obj-y          := gpio.o setup.o sysirq_mask.o
+obj-y          := setup.o sysirq_mask.o
 
-obj-$(CONFIG_OLD_IRQ_AT91)     += irq.o
-obj-$(CONFIG_OLD_CLK_AT91)     += clock.o
 obj-$(CONFIG_SOC_AT91SAM9)     += sam9_smc.o
 
 # CPU-specific support
@@ -20,73 +18,12 @@ obj-$(CONFIG_SOC_AT91SAM9RL)        += at91sam9rl.o
 obj-$(CONFIG_SOC_SAMA5D3)      += sama5d3.o
 obj-$(CONFIG_SOC_SAMA5D4)      += sama5d4.o
 
-obj-$(CONFIG_ARCH_AT91RM9200)  += at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9RL)  += at91sam9rl_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45_devices.o
-obj-$(CONFIG_ARCH_AT91X40)     += at91x40.o at91x40_time.o
-
-# AT91RM9200 board-specific support
-obj-$(CONFIG_MACH_ONEARM)      += board-1arm.o
-obj-$(CONFIG_MACH_AT91RM9200EK)        += board-rm9200ek.o
-obj-$(CONFIG_MACH_CSB337)      += board-csb337.o
-obj-$(CONFIG_MACH_CSB637)      += board-csb637.o
-obj-$(CONFIG_MACH_CARMEVA)     += board-carmeva.o
-obj-$(CONFIG_MACH_KB9200)      += board-kb9202.o
-obj-$(CONFIG_MACH_ATEB9200)    += board-eb9200.o
-obj-$(CONFIG_MACH_KAFA)                += board-kafa.o
-obj-$(CONFIG_MACH_PICOTUX2XX)  += board-picotux200.o
-obj-$(CONFIG_MACH_ECBAT91)     += board-ecbat91.o
-obj-$(CONFIG_MACH_YL9200)      += board-yl-9200.o
-obj-$(CONFIG_MACH_CPUAT91)     += board-cpuat91.o
-obj-$(CONFIG_MACH_ECO920)      += board-eco920.o
-
-# AT91SAM9260 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
-obj-$(CONFIG_MACH_CAM60)       += board-cam60.o
-obj-$(CONFIG_MACH_SAM9_L9260)  += board-sam9-l9260.o
-obj-$(CONFIG_MACH_AFEB9260)    += board-afeb-9260v1.o
-obj-$(CONFIG_MACH_CPU9260)     += board-cpu9krea.o
-obj-$(CONFIG_MACH_FLEXIBITY)   += board-flexibity.o
-
-# AT91SAM9261 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
-obj-$(CONFIG_MACH_AT91SAM9G10EK) += board-sam9261ek.o
-
-# AT91SAM9263 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
-
-# AT91SAM9RL board-specific support
-obj-$(CONFIG_MACH_AT91SAM9RLEK)        += board-sam9rlek.o
-
-# AT91SAM9G20 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
-obj-$(CONFIG_MACH_CPU9G20)     += board-cpu9krea.o
-obj-$(CONFIG_MACH_STAMP9G20)   += board-stamp9g20.o
-obj-$(CONFIG_MACH_PORTUXG20)   += board-stamp9g20.o
-obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o board-stamp9g20.o
-obj-$(CONFIG_MACH_GSIA18S)     += board-gsia18s.o board-stamp9g20.o
-
-# AT91SAM9260/AT91SAM9G20 board-specific support
-obj-$(CONFIG_MACH_SNAPPER_9260)        += board-snapper9260.o
-
-# AT91SAM9G45 board-specific support
-obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
-
 # AT91SAM board with device-tree
 obj-$(CONFIG_MACH_AT91RM9200_DT) += board-dt-rm9200.o
 obj-$(CONFIG_MACH_AT91SAM9_DT) += board-dt-sam9.o
 
 # SAMA5 board with device-tree
-obj-$(CONFIG_MACH_SAMA5_DT) += board-dt-sama5.o
-
-# AT91X40 board-specific support
-obj-$(CONFIG_MACH_AT91EB01)    += board-eb01.o
-
-# Drivers
-obj-y                          += leds.o
+obj-$(CONFIG_SOC_SAMA5)                += board-dt-sama5.o
 
 # Power Management
 obj-$(CONFIG_PM)               += pm.o
index 5309f9b6aabceedca1fe5da89d94b00226013ac8..29ed0fa374ca6703c15b71d1ccd45a821200e45a 100644 (file)
@@ -3,12 +3,6 @@
 #   PARAMS_PHYS must be within 4MB of ZRELADDR
 #   INITRD_PHYS must be in RAM
 
-ifeq ($(CONFIG_ARCH_AT91SAM9G45),y)
-   zreladdr-y  += 0x70008000
-params_phys-y  := 0x70000100
-initrd_phys-y  := 0x70410000
-else
    zreladdr-y  += 0x20008000
 params_phys-y  := 0x20000100
 initrd_phys-y  := 0x20410000
-endif
diff --git a/arch/arm/mach-at91/at91_aic.h b/arch/arm/mach-at91/at91_aic.h
deleted file mode 100644 (file)
index eaea661..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_aic.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Advanced Interrupt Controller (AIC) - 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_AIC_H
-#define AT91_AIC_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_aic_base;
-
-#define at91_aic_read(field) \
-       __raw_readl(at91_aic_base + field)
-
-#define at91_aic_write(field, value) \
-       __raw_writel(value, at91_aic_base + field)
-#else
-.extern at91_aic_base
-#endif
-
-/* Number of irq lines managed by AIC */
-#define NR_AIC_IRQS    32
-#define NR_AIC5_IRQS   128
-
-#define AT91_AIC5_SSR          0x0                     /* Source Select Register [AIC5] */
-#define        AT91_AIC5_INTSEL_MSK    (0x7f << 0)             /* Interrupt Line Selection Mask */
-
-#define AT91_AIC_IRQ_MIN_PRIORITY      0
-#define AT91_AIC_IRQ_MAX_PRIORITY      7
-
-#define AT91_AIC_SMR(n)                ((n) * 4)               /* Source Mode Registers 0-31 */
-#define AT91_AIC5_SMR          0x4                     /* Source Mode Register [AIC5] */
-#define                AT91_AIC_PRIOR          (7 << 0)                /* Priority Level */
-#define                AT91_AIC_SRCTYPE        (3 << 5)                /* Interrupt Source Type */
-#define                        AT91_AIC_SRCTYPE_LOW            (0 << 5)
-#define                        AT91_AIC_SRCTYPE_FALLING        (1 << 5)
-#define                        AT91_AIC_SRCTYPE_HIGH           (2 << 5)
-#define                        AT91_AIC_SRCTYPE_RISING         (3 << 5)
-
-#define AT91_AIC_SVR(n)                (0x80 + ((n) * 4))      /* Source Vector Registers 0-31 */
-#define AT91_AIC5_SVR          0x8                     /* Source Vector Register [AIC5] */
-#define AT91_AIC_IVR           0x100                   /* Interrupt Vector Register */
-#define AT91_AIC5_IVR          0x10                    /* Interrupt Vector Register [AIC5] */
-#define AT91_AIC_FVR           0x104                   /* Fast Interrupt Vector Register */
-#define AT91_AIC5_FVR          0x14                    /* Fast Interrupt Vector Register [AIC5] */
-#define AT91_AIC_ISR           0x108                   /* Interrupt Status Register */
-#define AT91_AIC5_ISR          0x18                    /* Interrupt Status Register [AIC5] */
-#define                AT91_AIC_IRQID          (0x1f << 0)             /* Current Interrupt Identifier */
-
-#define AT91_AIC_IPR           0x10c                   /* Interrupt Pending Register */
-#define AT91_AIC5_IPR0         0x20                    /* Interrupt Pending Register 0 [AIC5] */
-#define AT91_AIC5_IPR1         0x24                    /* Interrupt Pending Register 1 [AIC5] */
-#define AT91_AIC5_IPR2         0x28                    /* Interrupt Pending Register 2 [AIC5] */
-#define AT91_AIC5_IPR3         0x2c                    /* Interrupt Pending Register 3 [AIC5] */
-#define AT91_AIC_IMR           0x110                   /* Interrupt Mask Register */
-#define AT91_AIC5_IMR          0x30                    /* Interrupt Mask Register [AIC5] */
-#define AT91_AIC_CISR          0x114                   /* Core Interrupt Status Register */
-#define AT91_AIC5_CISR         0x34                    /* Core Interrupt Status Register [AIC5] */
-#define                AT91_AIC_NFIQ           (1 << 0)                /* nFIQ Status */
-#define                AT91_AIC_NIRQ           (1 << 1)                /* nIRQ Status */
-
-#define AT91_AIC_IECR          0x120                   /* Interrupt Enable Command Register */
-#define AT91_AIC5_IECR         0x40                    /* Interrupt Enable Command Register [AIC5] */
-#define AT91_AIC_IDCR          0x124                   /* Interrupt Disable Command Register */
-#define AT91_AIC5_IDCR         0x44                    /* Interrupt Disable Command Register [AIC5] */
-#define AT91_AIC_ICCR          0x128                   /* Interrupt Clear Command Register */
-#define AT91_AIC5_ICCR         0x48                    /* Interrupt Clear Command Register [AIC5] */
-#define AT91_AIC_ISCR          0x12c                   /* Interrupt Set Command Register */
-#define AT91_AIC5_ISCR         0x4c                    /* Interrupt Set Command Register [AIC5] */
-#define AT91_AIC_EOICR         0x130                   /* End of Interrupt Command Register */
-#define AT91_AIC5_EOICR                0x38                    /* End of Interrupt Command Register [AIC5] */
-#define AT91_AIC_SPU           0x134                   /* Spurious Interrupt Vector Register */
-#define AT91_AIC5_SPU          0x3c                    /* Spurious Interrupt Vector Register [AIC5] */
-#define AT91_AIC_DCR           0x138                   /* Debug Control Register */
-#define AT91_AIC5_DCR          0x6c                    /* Debug Control Register [AIC5] */
-#define                AT91_AIC_DCR_PROT       (1 << 0)                /* Protection Mode */
-#define                AT91_AIC_DCR_GMSK       (1 << 1)                /* General Mask */
-
-#define AT91_AIC_FFER          0x140                   /* Fast Forcing Enable Register [SAM9 only] */
-#define AT91_AIC5_FFER         0x50                    /* Fast Forcing Enable Register [AIC5] */
-#define AT91_AIC_FFDR          0x144                   /* Fast Forcing Disable Register [SAM9 only] */
-#define AT91_AIC5_FFDR         0x54                    /* Fast Forcing Disable Register [AIC5] */
-#define AT91_AIC_FFSR          0x148                   /* Fast Forcing Status Register [SAM9 only] */
-#define AT91_AIC5_FFSR         0x58                    /* Fast Forcing Status Register [AIC5] */
-
-void at91_aic_handle_irq(struct pt_regs *regs);
-void at91_aic5_handle_irq(struct pt_regs *regs);
-
-#endif
diff --git a/arch/arm/mach-at91/at91_tc.h b/arch/arm/mach-at91/at91_tc.h
deleted file mode 100644 (file)
index 46a317f..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_tc.h
- *
- * Copyright (C) SAN People
- *
- * Timer/Counter Unit (TC) 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_TC_H
-#define AT91_TC_H
-
-#define AT91_TC_BCR            0xc0            /* TC Block Control Register */
-#define                AT91_TC_SYNC            (1 << 0)        /* Synchro Command */
-
-#define AT91_TC_BMR            0xc4            /* TC Block Mode Register */
-#define                AT91_TC_TC0XC0S         (3 << 0)        /* External Clock Signal 0 Selection */
-#define                        AT91_TC_TC0XC0S_TCLK0           (0 << 0)
-#define                        AT91_TC_TC0XC0S_NONE            (1 << 0)
-#define                        AT91_TC_TC0XC0S_TIOA1           (2 << 0)
-#define                        AT91_TC_TC0XC0S_TIOA2           (3 << 0)
-#define                AT91_TC_TC1XC1S         (3 << 2)        /* External Clock Signal 1 Selection */
-#define                        AT91_TC_TC1XC1S_TCLK1           (0 << 2)
-#define                        AT91_TC_TC1XC1S_NONE            (1 << 2)
-#define                        AT91_TC_TC1XC1S_TIOA0           (2 << 2)
-#define                        AT91_TC_TC1XC1S_TIOA2           (3 << 2)
-#define                AT91_TC_TC2XC2S         (3 << 4)        /* External Clock Signal 2 Selection */
-#define                        AT91_TC_TC2XC2S_TCLK2           (0 << 4)
-#define                        AT91_TC_TC2XC2S_NONE            (1 << 4)
-#define                        AT91_TC_TC2XC2S_TIOA0           (2 << 4)
-#define                        AT91_TC_TC2XC2S_TIOA1           (3 << 4)
-
-
-#define AT91_TC_CCR            0x00            /* Channel Control Register */
-#define                AT91_TC_CLKEN           (1 << 0)        /* Counter Clock Enable Command */
-#define                AT91_TC_CLKDIS          (1 << 1)        /* Counter CLock Disable Command */
-#define                AT91_TC_SWTRG           (1 << 2)        /* Software Trigger Command */
-
-#define AT91_TC_CMR            0x04            /* Channel Mode Register */
-#define                AT91_TC_TCCLKS          (7 << 0)        /* Capture/Waveform Mode: Clock Selection */
-#define                        AT91_TC_TIMER_CLOCK1            (0 << 0)
-#define                        AT91_TC_TIMER_CLOCK2            (1 << 0)
-#define                        AT91_TC_TIMER_CLOCK3            (2 << 0)
-#define                        AT91_TC_TIMER_CLOCK4            (3 << 0)
-#define                        AT91_TC_TIMER_CLOCK5            (4 << 0)
-#define                        AT91_TC_XC0                     (5 << 0)
-#define                        AT91_TC_XC1                     (6 << 0)
-#define                        AT91_TC_XC2                     (7 << 0)
-#define                AT91_TC_CLKI            (1 << 3)        /* Capture/Waveform Mode: Clock Invert */
-#define                AT91_TC_BURST           (3 << 4)        /* Capture/Waveform Mode: Burst Signal Selection */
-#define                AT91_TC_LDBSTOP         (1 << 6)        /* Capture Mode: Counter Clock Stopped with TB Loading */
-#define                AT91_TC_LDBDIS          (1 << 7)        /* Capture Mode: Counter Clock Disable with RB Loading */
-#define                AT91_TC_ETRGEDG         (3 << 8)        /* Capture Mode: External Trigger Edge Selection */
-#define                AT91_TC_ABETRG          (1 << 10)       /* Capture Mode: TIOA or TIOB External Trigger Selection */
-#define                AT91_TC_CPCTRG          (1 << 14)       /* Capture Mode: RC Compare Trigger Enable */
-#define                AT91_TC_WAVE            (1 << 15)       /* Capture/Waveform mode */
-#define                AT91_TC_LDRA            (3 << 16)       /* Capture Mode: RA Loading Selection */
-#define                AT91_TC_LDRB            (3 << 18)       /* Capture Mode: RB Loading Selection */
-
-#define                AT91_TC_CPCSTOP         (1 <<  6)       /* Waveform Mode: Counter Clock Stopped with RC Compare */
-#define                AT91_TC_CPCDIS          (1 <<  7)       /* Waveform Mode: Counter Clock Disable with RC Compare */
-#define                AT91_TC_EEVTEDG         (3 <<  8)       /* Waveform Mode: External Event Edge Selection */
-#define                        AT91_TC_EEVTEDG_NONE            (0 << 8)
-#define                        AT91_TC_EEVTEDG_RISING          (1 << 8)
-#define                        AT91_TC_EEVTEDG_FALLING         (2 << 8)
-#define                        AT91_TC_EEVTEDG_BOTH            (3 << 8)
-#define                AT91_TC_EEVT            (3 << 10)       /* Waveform Mode: External Event Selection */
-#define                        AT91_TC_EEVT_TIOB               (0 << 10)
-#define                        AT91_TC_EEVT_XC0                (1 << 10)
-#define                        AT91_TC_EEVT_XC1                (2 << 10)
-#define                        AT91_TC_EEVT_XC2                (3 << 10)
-#define                AT91_TC_ENETRG          (1 << 12)       /* Waveform Mode: External Event Trigger Enable */
-#define                AT91_TC_WAVESEL         (3 << 13)       /* Waveform Mode: Waveform Selection */
-#define                        AT91_TC_WAVESEL_UP              (0 << 13)
-#define                        AT91_TC_WAVESEL_UP_AUTO         (2 << 13)
-#define                        AT91_TC_WAVESEL_UPDOWN          (1 << 13)
-#define                        AT91_TC_WAVESEL_UPDOWN_AUTO     (3 << 13)
-#define                AT91_TC_ACPA            (3 << 16)       /* Waveform Mode: RA Compare Effect on TIOA */
-#define                        AT91_TC_ACPA_NONE               (0 << 16)
-#define                        AT91_TC_ACPA_SET                (1 << 16)
-#define                        AT91_TC_ACPA_CLEAR              (2 << 16)
-#define                        AT91_TC_ACPA_TOGGLE             (3 << 16)
-#define                AT91_TC_ACPC            (3 << 18)       /* Waveform Mode: RC Compre Effect on TIOA */
-#define                        AT91_TC_ACPC_NONE               (0 << 18)
-#define                        AT91_TC_ACPC_SET                (1 << 18)
-#define                        AT91_TC_ACPC_CLEAR              (2 << 18)
-#define                        AT91_TC_ACPC_TOGGLE             (3 << 18)
-#define                AT91_TC_AEEVT           (3 << 20)       /* Waveform Mode: External Event Effect on TIOA */
-#define                        AT91_TC_AEEVT_NONE              (0 << 20)
-#define                        AT91_TC_AEEVT_SET               (1 << 20)
-#define                        AT91_TC_AEEVT_CLEAR             (2 << 20)
-#define                        AT91_TC_AEEVT_TOGGLE            (3 << 20)
-#define                AT91_TC_ASWTRG          (3 << 22)       /* Waveform Mode: Software Trigger Effect on TIOA */
-#define                        AT91_TC_ASWTRG_NONE             (0 << 22)
-#define                        AT91_TC_ASWTRG_SET              (1 << 22)
-#define                        AT91_TC_ASWTRG_CLEAR            (2 << 22)
-#define                        AT91_TC_ASWTRG_TOGGLE           (3 << 22)
-#define                AT91_TC_BCPB            (3 << 24)       /* Waveform Mode: RB Compare Effect on TIOB */
-#define                        AT91_TC_BCPB_NONE               (0 << 24)
-#define                        AT91_TC_BCPB_SET                (1 << 24)
-#define                        AT91_TC_BCPB_CLEAR              (2 << 24)
-#define                        AT91_TC_BCPB_TOGGLE             (3 << 24)
-#define                AT91_TC_BCPC            (3 << 26)       /* Waveform Mode: RC Compare Effect on TIOB */
-#define                        AT91_TC_BCPC_NONE               (0 << 26)
-#define                        AT91_TC_BCPC_SET                (1 << 26)
-#define                        AT91_TC_BCPC_CLEAR              (2 << 26)
-#define                        AT91_TC_BCPC_TOGGLE             (3 << 26)
-#define                AT91_TC_BEEVT           (3 << 28)       /* Waveform Mode: External Event Effect on TIOB */
-#define                        AT91_TC_BEEVT_NONE              (0 << 28)
-#define                        AT91_TC_BEEVT_SET               (1 << 28)
-#define                        AT91_TC_BEEVT_CLEAR             (2 << 28)
-#define                        AT91_TC_BEEVT_TOGGLE            (3 << 28)
-#define                AT91_TC_BSWTRG          (3 << 30)       /* Waveform Mode: Software Trigger Effect on TIOB */
-#define                        AT91_TC_BSWTRG_NONE             (0 << 30)
-#define                        AT91_TC_BSWTRG_SET              (1 << 30)
-#define                        AT91_TC_BSWTRG_CLEAR            (2 << 30)
-#define                        AT91_TC_BSWTRG_TOGGLE           (3 << 30)
-
-#define AT91_TC_CV             0x10            /* Counter Value */
-#define AT91_TC_RA             0x14            /* Register A */
-#define AT91_TC_RB             0x18            /* Register B */
-#define AT91_TC_RC             0x1c            /* Register C */
-
-#define AT91_TC_SR             0x20            /* Status Register */
-#define                AT91_TC_COVFS           (1 <<  0)       /* Counter Overflow Status */
-#define                AT91_TC_LOVRS           (1 <<  1)       /* Load Overrun Status */
-#define                AT91_TC_CPAS            (1 <<  2)       /* RA Compare Status */
-#define                AT91_TC_CPBS            (1 <<  3)       /* RB Compare Status */
-#define                AT91_TC_CPCS            (1 <<  4)       /* RC Compare Status */
-#define                AT91_TC_LDRAS           (1 <<  5)       /* RA Loading Status */
-#define                AT91_TC_LDRBS           (1 <<  6)       /* RB Loading Status */
-#define                AT91_TC_ETRGS           (1 <<  7)       /* External Trigger Status */
-#define                AT91_TC_CLKSTA          (1 << 16)       /* Clock Enabling Status */
-#define                AT91_TC_MTIOA           (1 << 17)       /* TIOA Mirror */
-#define                AT91_TC_MTIOB           (1 << 18)       /* TIOB Mirror */
-
-#define AT91_TC_IER            0x24            /* Interrupt Enable Register */
-#define AT91_TC_IDR            0x28            /* Interrupt Disable Register */
-#define AT91_TC_IMR            0x2c            /* Interrupt Mask Register */
-
-#endif
index 038702ee8bc6f370a1aabc27cf1590fd34d19fae..b5291694753513cd02e64cabe1f566eab04d9201 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/reboot.h>
 #include <linux/clk/at91_pmc.h>
 
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
-#include <mach/at91rm9200.h>
 #include <mach/at91_st.h>
-#include <mach/cpu.h>
 #include <mach/hardware.h>
 
-#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-#include "pm.h"
-
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk udc_clk = {
-       .name           = "udc_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_UDP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ohci_clk = {
-       .name           = "ohci_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_UHP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ether_clk = {
-       .name           = "ether_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_EMAC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-       .name           = "mci_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_MCI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi_clk = {
-       .name           = "twi_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_TWI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_US0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_US1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_US2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_US3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi_clk = {
-       .name           = "spi_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_SPI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_PIOA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_PIOB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-       .name           = "pioC_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_PIOC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioD_clk = {
-       .name           = "pioD_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_PIOD,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc0_clk = {
-       .name           = "ssc0_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_SSC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc1_clk = {
-       .name           = "ssc1_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_SSC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc2_clk = {
-       .name           = "ssc2_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_SSC2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc0_clk = {
-       .name           = "tc0_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_TC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc1_clk = {
-       .name           = "tc1_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_TC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc2_clk = {
-       .name           = "tc2_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_TC2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc3_clk = {
-       .name           = "tc3_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_TC3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc4_clk = {
-       .name           = "tc4_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_TC4,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc5_clk = {
-       .name           = "tc5_clk",
-       .pmc_mask       = 1 << AT91RM9200_ID_TC5,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioA_clk,
-       &pioB_clk,
-       &pioC_clk,
-       &pioD_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &usart3_clk,
-       &mmc_clk,
-       &udc_clk,
-       &twi_clk,
-       &spi_clk,
-       &ssc0_clk,
-       &ssc1_clk,
-       &ssc2_clk,
-       &tc0_clk,
-       &tc1_clk,
-       &tc2_clk,
-       &tc3_clk,
-       &tc4_clk,
-       &tc5_clk,
-       &ohci_clk,
-       &ether_clk,
-       // irq0 .. irq6
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffd0000.ssc", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffd4000.ssc", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffd8000.ssc", &ssc2_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
-       /* fake hclk clock */
-       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
-       CLKDEV_CON_ID("pioA", &pioA_clk),
-       CLKDEV_CON_ID("pioB", &pioB_clk),
-       CLKDEV_CON_ID("pioC", &pioC_clk),
-       CLKDEV_CON_ID("pioD", &pioD_clk),
-       /* usart lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "fffc0000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffc4000.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffc8000.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffcc000.serial", &usart3_clk),
-       /* tc lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "fffa4000.timer", &tc3_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "fffa4000.timer", &tc4_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "fffa4000.timer", &tc5_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fffb4000.mmc", &mmc_clk),
-       CLKDEV_CON_DEV_ID("emac_clk", "fffbc000.ethernet", &ether_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffb8000.i2c", &twi_clk),
-       CLKDEV_CON_DEV_ID("hclk", "300000.ohci", &ohci_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioD_clk),
-};
-
-static struct clk_lookup usart_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.4", &usart3_clk),
-};
-
-/*
- * The four programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-static struct clk pck2 = {
-       .name           = "pck2",
-       .pmc_mask       = AT91_PMC_PCK2,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 2,
-};
-static struct clk pck3 = {
-       .name           = "pck3",
-       .pmc_mask       = AT91_PMC_PCK3,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 3,
-};
-
-static void __init at91rm9200_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-       clkdev_add_table(usart_clocks_lookups,
-                        ARRAY_SIZE(usart_clocks_lookups));
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-       clk_register(&pck2);
-       clk_register(&pck3);
-}
-#else
-#define at91rm9200_register_clocks NULL
-#endif
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91rm9200_gpio[] __initdata = {
-       {
-               .id             = AT91RM9200_ID_PIOA,
-               .regbase        = AT91RM9200_BASE_PIOA,
-       }, {
-               .id             = AT91RM9200_ID_PIOB,
-               .regbase        = AT91RM9200_BASE_PIOB,
-       }, {
-               .id             = AT91RM9200_ID_PIOC,
-               .regbase        = AT91RM9200_BASE_PIOC,
-       }, {
-               .id             = AT91RM9200_ID_PIOD,
-               .regbase        = AT91RM9200_BASE_PIOD,
-       }
-};
 
 static void at91rm9200_idle(void)
 {
@@ -329,74 +48,14 @@ static void __init at91rm9200_map_io(void)
        at91_init_sram(0, AT91RM9200_SRAM_BASE, AT91RM9200_SRAM_SIZE);
 }
 
-static void __init at91rm9200_ioremap_registers(void)
-{
-       at91rm9200_ioremap_st(AT91RM9200_BASE_ST);
-       at91_ioremap_ramc(0, AT91RM9200_BASE_MC, 256);
-       at91_pm_set_standby(at91rm9200_standby);
-}
-
 static void __init at91rm9200_initialize(void)
 {
        arm_pm_idle = at91rm9200_idle;
        arm_pm_restart = at91rm9200_restart;
-
-       /* Initialize GPIO subsystem */
-       at91_gpio_init(at91rm9200_gpio,
-               cpu_is_at91rm9200_bga() ? AT91RM9200_BGA : AT91RM9200_PQFP);
 }
 
 
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller (FIQ) */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A */
-       1,      /* Parallel IO Controller B */
-       1,      /* Parallel IO Controller C */
-       1,      /* Parallel IO Controller D */
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       5,      /* USART 3 */
-       0,      /* Multimedia Card Interface */
-       2,      /* USB Device Port */
-       6,      /* Two-Wire Interface */
-       5,      /* Serial Peripheral Interface */
-       4,      /* Serial Synchronous Controller 0 */
-       4,      /* Serial Synchronous Controller 1 */
-       4,      /* Serial Synchronous Controller 2 */
-       0,      /* Timer Counter 0 */
-       0,      /* Timer Counter 1 */
-       0,      /* Timer Counter 2 */
-       0,      /* Timer Counter 3 */
-       0,      /* Timer Counter 4 */
-       0,      /* Timer Counter 5 */
-       2,      /* USB Host port */
-       3,      /* Ethernet MAC */
-       0,      /* Advanced Interrupt Controller (IRQ0) */
-       0,      /* Advanced Interrupt Controller (IRQ1) */
-       0,      /* Advanced Interrupt Controller (IRQ2) */
-       0,      /* Advanced Interrupt Controller (IRQ3) */
-       0,      /* Advanced Interrupt Controller (IRQ4) */
-       0,      /* Advanced Interrupt Controller (IRQ5) */
-       0       /* Advanced Interrupt Controller (IRQ6) */
-};
-
 AT91_SOC_START(at91rm9200)
        .map_io = at91rm9200_map_io,
-       .default_irq_priority = at91rm9200_default_irq_priority,
-       .extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
-                   | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
-                   | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5)
-                   | (1 << AT91RM9200_ID_IRQ6),
-       .ioremap_registers = at91rm9200_ioremap_registers,
-       .register_clocks = at91rm9200_register_clocks,
        .init = at91rm9200_initialize,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
deleted file mode 100644 (file)
index 74f1eaf..0000000
+++ /dev/null
@@ -1,1212 +0,0 @@
-/*
- * arch/arm/mach-at91/at91rm9200_devices.c
- *
- *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
- *  Copyright (C) 2005 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/gpio/machine.h>
-#include <linux/platform_device.h>
-#include <linux/i2c-gpio.h>
-
-#include <mach/at91rm9200.h>
-#include <mach/at91rm9200_mc.h>
-#include <mach/at91_ramc.h>
-#include <mach/hardware.h>
-
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-/* --------------------------------------------------------------------
- *  USB Host
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_UHP_BASE,
-               .end    = AT91RM9200_UHP_BASE + SZ_1M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_usbh_device = {
-       .name           = "at91_ohci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &ohci_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &usbh_data,
-       },
-       .resource       = usbh_resources,
-       .num_resources  = ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-       int i;
-
-       if (!data)
-               return;
-
-       /* Enable overcurrent notification */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->overcurrent_pin[i]))
-                       at91_set_gpio_input(data->overcurrent_pin[i], 1);
-       }
-
-       usbh_data = *data;
-       platform_device_register(&at91rm9200_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_UDP,
-               .end    = AT91RM9200_BASE_UDP + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_udc_device = {
-       .name           = "at91_udc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data          = &udc_data,
-       },
-       .resource       = udc_resources,
-       .num_resources  = ARRAY_SIZE(udc_resources),
-};
-
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->vbus_pin)) {
-               at91_set_gpio_input(data->vbus_pin, 0);
-               at91_set_deglitch(data->vbus_pin, 1);
-       }
-       if (gpio_is_valid(data->pullup_pin))
-               at91_set_gpio_output(data->pullup_pin, 0);
-
-       udc_data = *data;
-       platform_device_register(&at91rm9200_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Ethernet
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct macb_platform_data eth_data;
-
-static struct resource eth_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_EMAC,
-               .end    = AT91RM9200_BASE_EMAC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_eth_device = {
-       .name           = "at91_ether",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &eth_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &eth_data,
-       },
-       .resource       = eth_resources,
-       .num_resources  = ARRAY_SIZE(eth_resources),
-};
-
-void __init at91_add_device_eth(struct macb_platform_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->phy_irq_pin)) {
-               at91_set_gpio_input(data->phy_irq_pin, 0);
-               at91_set_deglitch(data->phy_irq_pin, 1);
-       }
-
-       /* Pins used for MII and RMII */
-       at91_set_A_periph(AT91_PIN_PA16, 0);    /* EMDIO */
-       at91_set_A_periph(AT91_PIN_PA15, 0);    /* EMDC */
-       at91_set_A_periph(AT91_PIN_PA14, 0);    /* ERXER */
-       at91_set_A_periph(AT91_PIN_PA13, 0);    /* ERX1 */
-       at91_set_A_periph(AT91_PIN_PA12, 0);    /* ERX0 */
-       at91_set_A_periph(AT91_PIN_PA11, 0);    /* ECRS_ECRSDV */
-       at91_set_A_periph(AT91_PIN_PA10, 0);    /* ETX1 */
-       at91_set_A_periph(AT91_PIN_PA9, 0);     /* ETX0 */
-       at91_set_A_periph(AT91_PIN_PA8, 0);     /* ETXEN */
-       at91_set_A_periph(AT91_PIN_PA7, 0);     /* ETXCK_EREFCK */
-
-       if (!data->is_rmii) {
-               at91_set_B_periph(AT91_PIN_PB19, 0);    /* ERXCK */
-               at91_set_B_periph(AT91_PIN_PB18, 0);    /* ECOL */
-               at91_set_B_periph(AT91_PIN_PB17, 0);    /* ERXDV */
-               at91_set_B_periph(AT91_PIN_PB16, 0);    /* ERX3 */
-               at91_set_B_periph(AT91_PIN_PB15, 0);    /* ERX2 */
-               at91_set_B_periph(AT91_PIN_PB14, 0);    /* ETXER */
-               at91_set_B_periph(AT91_PIN_PB13, 0);    /* ETX3 */
-               at91_set_B_periph(AT91_PIN_PB12, 0);    /* ETX2 */
-       }
-
-       eth_data = *data;
-       platform_device_register(&at91rm9200_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct macb_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Compact Flash / PCMCIA
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
-static struct at91_cf_data cf_data;
-
-#define CF_BASE                AT91_CHIPSELECT_4
-
-static struct resource cf_resources[] = {
-       [0] = {
-               .start  = CF_BASE,
-               /* ties up CS4, CS5 and CS6 */
-               .end    = CF_BASE + (0x30000000 - 1),
-               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
-       },
-};
-
-static struct platform_device at91rm9200_cf_device = {
-       .name           = "at91_cf",
-       .id             = -1,
-       .dev            = {
-                               .platform_data          = &cf_data,
-       },
-       .resource       = cf_resources,
-       .num_resources  = ARRAY_SIZE(cf_resources),
-};
-
-void __init at91_add_device_cf(struct at91_cf_data *data)
-{
-       unsigned int csa;
-
-       if (!data)
-               return;
-
-       data->chipselect = 4;           /* can only use EBI ChipSelect 4 */
-
-       /* CF takes over CS4, CS5, CS6 */
-       csa = at91_ramc_read(0, AT91_EBI_CSA);
-       at91_ramc_write(0, AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
-
-       /*
-        * Static memory controller timing adjustments.
-        * REVISIT:  these timings are in terms of MCK cycles, so
-        * when MCK changes (cpufreq etc) so must these values...
-        */
-       at91_ramc_write(0, AT91_SMC_CSR(4),
-                                 AT91_SMC_ACSS_STD
-                               | AT91_SMC_DBW_16
-                               | AT91_SMC_BAT
-                               | AT91_SMC_WSEN
-                               | AT91_SMC_NWS_(32)     /* wait states */
-                               | AT91_SMC_RWSETUP_(6)  /* setup time */
-                               | AT91_SMC_RWHOLD_(4)   /* hold time */
-       );
-
-       /* input/irq */
-       if (gpio_is_valid(data->irq_pin)) {
-               at91_set_gpio_input(data->irq_pin, 1);
-               at91_set_deglitch(data->irq_pin, 1);
-       }
-       at91_set_gpio_input(data->det_pin, 1);
-       at91_set_deglitch(data->det_pin, 1);
-
-       /* outputs, initially off */
-       if (gpio_is_valid(data->vcc_pin))
-               at91_set_gpio_output(data->vcc_pin, 0);
-       at91_set_gpio_output(data->rst_pin, 0);
-
-       /* force poweron defaults for these pins ... */
-       at91_set_A_periph(AT91_PIN_PC9, 0);     /* A25/CFRNW */
-       at91_set_A_periph(AT91_PIN_PC10, 0);    /* NCS4/CFCS */
-       at91_set_A_periph(AT91_PIN_PC11, 0);    /* NCS5/CFCE1 */
-       at91_set_A_periph(AT91_PIN_PC12, 0);    /* NCS6/CFCE2 */
-
-       /* nWAIT is _not_ a default setting */
-       at91_set_A_periph(AT91_PIN_PC6, 1);     /* nWAIT */
-
-       cf_data = *data;
-       platform_device_register(&at91rm9200_cf_device);
-}
-#else
-void __init at91_add_device_cf(struct at91_cf_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc_data;
-
-static struct resource mmc_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_MCI,
-               .end    = AT91RM9200_BASE_MCI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_mmc_device = {
-       .name           = "atmel_mci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc_data,
-       },
-       .resource       = mmc_resources,
-       .num_resources  = ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-       unsigned int i;
-       unsigned int slot_count = 0;
-
-       if (!data)
-               return;
-
-       for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
-
-               if (!data->slot[i].bus_width)
-                       continue;
-
-               /* input/irq */
-               if (gpio_is_valid(data->slot[i].detect_pin)) {
-                       at91_set_gpio_input(data->slot[i].detect_pin, 1);
-                       at91_set_deglitch(data->slot[i].detect_pin, 1);
-               }
-               if (gpio_is_valid(data->slot[i].wp_pin))
-                       at91_set_gpio_input(data->slot[i].wp_pin, 1);
-
-               switch (i) {
-               case 0:                                 /* slot A */
-                       /* CMD */
-                       at91_set_A_periph(AT91_PIN_PA28, 1);
-                       /* DAT0, maybe DAT1..DAT3 */
-                       at91_set_A_periph(AT91_PIN_PA29, 1);
-                       if (data->slot[i].bus_width == 4) {
-                               at91_set_B_periph(AT91_PIN_PB3, 1);
-                               at91_set_B_periph(AT91_PIN_PB4, 1);
-                               at91_set_B_periph(AT91_PIN_PB5, 1);
-                       }
-                       slot_count++;
-                       break;
-               case 1:                                 /* slot B */
-                       /* CMD */
-                       at91_set_B_periph(AT91_PIN_PA8, 1);
-                       /* DAT0, maybe DAT1..DAT3 */
-                       at91_set_B_periph(AT91_PIN_PA9, 1);
-                       if (data->slot[i].bus_width == 4) {
-                               at91_set_B_periph(AT91_PIN_PA10, 1);
-                               at91_set_B_periph(AT91_PIN_PA11, 1);
-                               at91_set_B_periph(AT91_PIN_PA12, 1);
-                       }
-                       slot_count++;
-                       break;
-               default:
-                       printk(KERN_ERR
-                              "AT91: SD/MMC slot %d not available\n", i);
-                       break;
-               }
-               if (slot_count) {
-                       /* CLK */
-                       at91_set_A_periph(AT91_PIN_PA27, 0);
-
-                       mmc_data = *data;
-                       platform_device_register(&at91rm9200_mmc_device);
-               }
-       }
-
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  NAND / SmartMedia
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE      AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-       {
-               .start  = NAND_BASE,
-               .end    = NAND_BASE + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91rm9200_nand_device = {
-       .name           = "atmel_nand",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &nand_data,
-       },
-       .resource       = nand_resources,
-       .num_resources  = ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-       unsigned int csa;
-
-       if (!data)
-               return;
-
-       /* enable the address range of CS3 */
-       csa = at91_ramc_read(0, AT91_EBI_CSA);
-       at91_ramc_write(0, AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA);
-
-       /* set the bus interface characteristics */
-       at91_ramc_write(0, AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN
-               | AT91_SMC_NWS_(5)
-               | AT91_SMC_TDF_(1)
-               | AT91_SMC_RWSETUP_(0)  /* tDS Data Set up Time 30 - ns */
-               | AT91_SMC_RWHOLD_(1)   /* tDH Data Hold Time 20 - ns */
-       );
-
-       /* enable pin */
-       if (gpio_is_valid(data->enable_pin))
-               at91_set_gpio_output(data->enable_pin, 1);
-
-       /* ready/busy pin */
-       if (gpio_is_valid(data->rdy_pin))
-               at91_set_gpio_input(data->rdy_pin, 1);
-
-       /* card detect pin */
-       if (gpio_is_valid(data->det_pin))
-               at91_set_gpio_input(data->det_pin, 1);
-
-       at91_set_A_periph(AT91_PIN_PC1, 0);             /* SMOE */
-       at91_set_A_periph(AT91_PIN_PC3, 0);             /* SMWE */
-
-       nand_data = *data;
-       platform_device_register(&at91rm9200_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  TWI (i2c)
- * -------------------------------------------------------------------- */
-
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-       .sda_pin                = AT91_PIN_PA25,
-       .sda_is_open_drain      = 1,
-       .scl_pin                = AT91_PIN_PA26,
-       .scl_is_open_drain      = 1,
-       .udelay                 = 2,            /* ~100 kHz */
-};
-
-static struct platform_device at91rm9200_twi_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 0,
-       .dev.platform_data      = &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       at91_set_GPIO_periph(AT91_PIN_PA25, 1);         /* TWD (SDA) */
-       at91_set_multi_drive(AT91_PIN_PA25, 1);
-
-       at91_set_GPIO_periph(AT91_PIN_PA26, 1);         /* TWCK (SCL) */
-       at91_set_multi_drive(AT91_PIN_PA26, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91rm9200_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_TWI,
-               .end    = AT91RM9200_BASE_TWI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_twi_device = {
-       .name           = "i2c-at91rm9200",
-       .id             = 0,
-       .resource       = twi_resources,
-       .num_resources  = ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       /* pins used for TWI interface */
-       at91_set_A_periph(AT91_PIN_PA25, 0);            /* TWD */
-       at91_set_multi_drive(AT91_PIN_PA25, 1);
-
-       at91_set_A_periph(AT91_PIN_PA26, 0);            /* TWCK */
-       at91_set_multi_drive(AT91_PIN_PA26, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91rm9200_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_SPI,
-               .end    = AT91RM9200_BASE_SPI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_spi_device = {
-       .name           = "atmel_spi",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi_resources,
-       .num_resources  = ARRAY_SIZE(spi_resources),
-};
-
-static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-       int i;
-       unsigned long cs_pin;
-
-       at91_set_A_periph(AT91_PIN_PA0, 0);     /* MISO */
-       at91_set_A_periph(AT91_PIN_PA1, 0);     /* MOSI */
-       at91_set_A_periph(AT91_PIN_PA2, 0);     /* SPCK */
-
-       /* Enable SPI chip-selects */
-       for (i = 0; i < nr_devices; i++) {
-               if (devices[i].controller_data)
-                       cs_pin = (unsigned long) devices[i].controller_data;
-               else
-                       cs_pin = spi_standard_cs[devices[i].chip_select];
-
-               if (devices[i].chip_select == 0)        /* for CS0 errata */
-                       at91_set_A_periph(cs_pin, 0);
-               else
-                       at91_set_gpio_output(cs_pin, 1);
-
-
-               /* pass chip-select pin to driver */
-               devices[i].controller_data = (void *) cs_pin;
-       }
-
-       spi_register_board_info(devices, nr_devices);
-       platform_device_register(&at91rm9200_spi_device);
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Timer/Counter blocks
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb0_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_TCB0,
-               .end    = AT91RM9200_BASE_TCB0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_tcb0_device = {
-       .name           = "atmel_tcb",
-       .id             = 0,
-       .resource       = tcb0_resources,
-       .num_resources  = ARRAY_SIZE(tcb0_resources),
-};
-
-static struct resource tcb1_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_TCB1,
-               .end    = AT91RM9200_BASE_TCB1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_tcb1_device = {
-       .name           = "atmel_tcb",
-       .id             = 1,
-       .resource       = tcb1_resources,
-       .num_resources  = ARRAY_SIZE(tcb1_resources),
-};
-
-static void __init at91_add_device_tc(void)
-{
-       platform_device_register(&at91rm9200_tcb0_device);
-       platform_device_register(&at91rm9200_tcb1_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
-/* --------------------------------------------------------------------
- *  RTC
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
-static struct resource rtc_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_RTC,
-               .end    = AT91RM9200_BASE_RTC + SZ_256 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_rtc_device = {
-       .name           = "at91_rtc",
-       .id             = -1,
-       .resource       = rtc_resources,
-       .num_resources  = ARRAY_SIZE(rtc_resources),
-};
-
-static void __init at91_add_device_rtc(void)
-{
-       platform_device_register(&at91rm9200_rtc_device);
-}
-#else
-static void __init at91_add_device_rtc(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE)
-static struct platform_device at91rm9200_wdt_device = {
-       .name           = "at91_wdt",
-       .id             = -1,
-       .num_resources  = 0,
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-       platform_device_register(&at91rm9200_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SSC -- Synchronous Serial Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_SSC0,
-               .end    = AT91RM9200_BASE_SSC0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_ssc0_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 0,
-       .dev    = {
-               .dma_mask               = &ssc0_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc0_resources,
-       .num_resources  = ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PB0, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PB1, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PB2, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PB3, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PB4, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PB5, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_SSC1,
-               .end    = AT91RM9200_BASE_SSC1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_ssc1_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 1,
-       .dev    = {
-               .dma_mask               = &ssc1_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc1_resources,
-       .num_resources  = ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PB6, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PB7, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PB8, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PB9, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PB10, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PB11, 1);
-}
-
-static u64 ssc2_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc2_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_SSC2,
-               .end    = AT91RM9200_BASE_SSC2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91rm9200_ssc2_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 2,
-       .dev    = {
-               .dma_mask               = &ssc2_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc2_resources,
-       .num_resources  = ARRAY_SIZE(ssc2_resources),
-};
-
-static inline void configure_ssc2_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PB12, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PB13, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PB14, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PB15, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PB16, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PB17, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-       struct platform_device *pdev;
-
-       /*
-        * NOTE: caller is responsible for passing information matching
-        * "pins" to whatever will be using each particular controller.
-        */
-       switch (id) {
-       case AT91RM9200_ID_SSC0:
-               pdev = &at91rm9200_ssc0_device;
-               configure_ssc0_pins(pins);
-               break;
-       case AT91RM9200_ID_SSC1:
-               pdev = &at91rm9200_ssc1_device;
-               configure_ssc1_pins(pins);
-               break;
-       case AT91RM9200_ID_SSC2:
-               pdev = &at91rm9200_ssc2_device;
-               configure_ssc2_pins(pins);
-               break;
-       default:
-               return;
-       }
-
-       platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_DBGU,
-               .end    = AT91RM9200_BASE_DBGU + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data dbgu_data = {
-       .use_dma_tx     = 0,
-       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_dbgu_device = {
-       .name           = "atmel_usart",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &dbgu_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &dbgu_data,
-       },
-       .resource       = dbgu_resources,
-       .num_resources  = ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-       at91_set_A_periph(AT91_PIN_PA30, 0);            /* DRXD */
-       at91_set_A_periph(AT91_PIN_PA31, 1);            /* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_US0,
-               .end    = AT91RM9200_BASE_US0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart0_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static struct gpiod_lookup_table uart0_gpios_table = {
-       .dev_id = "atmel_usart",
-       .table = {
-               GPIO_LOOKUP("pioA", 21, "rts", GPIO_ACTIVE_LOW),
-               { },
-       },
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart0_device = {
-       .name           = "atmel_usart",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &uart0_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart0_data,
-       },
-       .resource       = uart0_resources,
-       .num_resources  = ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PA17, 1);            /* TXD0 */
-       at91_set_A_periph(AT91_PIN_PA18, 0);            /* RXD0 */
-
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PA20, 0);    /* CTS0 */
-
-       if (pins & ATMEL_UART_RTS) {
-               /*
-                * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
-                * We need to drive the pin manually. The serial driver will driver
-                * this to high when initializing.
-                */
-               gpiod_add_lookup_table(&uart0_gpios_table);
-       }
-}
-
-static struct resource uart1_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_US1,
-               .end    = AT91RM9200_BASE_US1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart1_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart1_device = {
-       .name           = "atmel_usart",
-       .id             = 2,
-       .dev            = {
-                               .dma_mask               = &uart1_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart1_data,
-       },
-       .resource       = uart1_resources,
-       .num_resources  = ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB20, 1);            /* TXD1 */
-       at91_set_A_periph(AT91_PIN_PB21, 0);            /* RXD1 */
-
-       if (pins & ATMEL_UART_RI)
-               at91_set_A_periph(AT91_PIN_PB18, 0);    /* RI1 */
-       if (pins & ATMEL_UART_DTR)
-               at91_set_A_periph(AT91_PIN_PB19, 0);    /* DTR1 */
-       if (pins & ATMEL_UART_DCD)
-               at91_set_A_periph(AT91_PIN_PB23, 0);    /* DCD1 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PB24, 0);    /* CTS1 */
-       if (pins & ATMEL_UART_DSR)
-               at91_set_A_periph(AT91_PIN_PB25, 0);    /* DSR1 */
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PB26, 0);    /* RTS1 */
-}
-
-static struct resource uart2_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_US2,
-               .end    = AT91RM9200_BASE_US2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart2_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart2_device = {
-       .name           = "atmel_usart",
-       .id             = 3,
-       .dev            = {
-                               .dma_mask               = &uart2_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart2_data,
-       },
-       .resource       = uart2_resources,
-       .num_resources  = ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PA22, 0);            /* RXD2 */
-       at91_set_A_periph(AT91_PIN_PA23, 1);            /* TXD2 */
-
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PA30, 0);    /* CTS2 */
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PA31, 0);    /* RTS2 */
-}
-
-static struct resource uart3_resources[] = {
-       [0] = {
-               .start  = AT91RM9200_BASE_US3,
-               .end    = AT91RM9200_BASE_US3 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
-               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart3_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91rm9200_uart3_device = {
-       .name           = "atmel_usart",
-       .id             = 4,
-       .dev            = {
-                               .dma_mask               = &uart3_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart3_data,
-       },
-       .resource       = uart3_resources,
-       .num_resources  = ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(unsigned pins)
-{
-       at91_set_B_periph(AT91_PIN_PA5, 1);             /* TXD3 */
-       at91_set_B_periph(AT91_PIN_PA6, 0);             /* RXD3 */
-
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PB1, 0);     /* CTS3 */
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PB0, 0);     /* RTS3 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];  /* the UARTs to use */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-       struct platform_device *pdev;
-       struct atmel_uart_data *pdata;
-
-       switch (id) {
-               case 0:         /* DBGU */
-                       pdev = &at91rm9200_dbgu_device;
-                       configure_dbgu_pins();
-                       break;
-               case AT91RM9200_ID_US0:
-                       pdev = &at91rm9200_uart0_device;
-                       configure_usart0_pins(pins);
-                       break;
-               case AT91RM9200_ID_US1:
-                       pdev = &at91rm9200_uart1_device;
-                       configure_usart1_pins(pins);
-                       break;
-               case AT91RM9200_ID_US2:
-                       pdev = &at91rm9200_uart2_device;
-                       configure_usart2_pins(pins);
-                       break;
-               case AT91RM9200_ID_US3:
-                       pdev = &at91rm9200_uart3_device;
-                       configure_usart3_pins(pins);
-                       break;
-               default:
-                       return;
-       }
-       pdata = pdev->dev.platform_data;
-       pdata->num = portnr;            /* update to mapped ID */
-
-       if (portnr < ATMEL_MAX_UART)
-               at91_uarts[portnr] = pdev;
-}
-
-void __init at91_add_device_serial(void)
-{
-       int i;
-
-       for (i = 0; i < ATMEL_MAX_UART; i++) {
-               if (at91_uarts[i])
-                       platform_device_register(at91_uarts[i]);
-       }
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-       at91_add_device_rtc();
-       at91_add_device_watchdog();
-       at91_add_device_tc();
-       return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
index 7fd13aef982725ea0e869d5b76ddd4fe2530eb67..51761f8927b7a4959468ad0df8c4ddf86565303a 100644 (file)
@@ -183,7 +183,6 @@ static struct clock_event_device clkevt = {
 void __iomem *at91_st_base;
 EXPORT_SYMBOL_GPL(at91_st_base);
 
-#ifdef CONFIG_OF
 static struct of_device_id at91rm9200_st_timer_ids[] = {
        { .compatible = "atmel,at91rm9200-st" },
        { /* sentinel */ }
@@ -219,28 +218,6 @@ node_err:
 err:
        return -EINVAL;
 }
-#else
-static int __init of_at91rm9200_st_init(void)
-{
-       return -EINVAL;
-}
-#endif
-
-void __init at91rm9200_ioremap_st(u32 addr)
-{
-#ifdef CONFIG_OF
-       struct device_node *np;
-
-       np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
-       if (np) {
-               of_node_put(np);
-               return;
-       }
-#endif
-       at91_st_base = ioremap(addr, 256);
-       if (!at91_st_base)
-               panic("Impossible to ioremap ST\n");
-}
 
 /*
  * ST (system timer) module supports both clockevents and clocksource.
index aab1f969a7c3f6bba1b2d51824c34e3e28a2f13d..78137c24d90b9dddfd0d5a1be75a267a5402768d 100644 (file)
  *
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk/at91_pmc.h>
-
-#include <asm/proc-fns.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
-#include <mach/at91sam9260.h>
 #include <mach/hardware.h>
 
-#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-#include "pm.h"
-
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_PIOA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_PIOB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-       .name           = "pioC_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_PIOC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk adc_clk = {
-       .name           = "adc_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_ADC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk adc_op_clk = {
-       .name           = "adc_op_clk",
-       .type           = CLK_TYPE_PERIPHERAL,
-       .rate_hz        = 5000000,
-};
-
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_US0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_US1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_US2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-       .name           = "mci_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_MCI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udc_clk = {
-       .name           = "udc_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_UDP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi_clk = {
-       .name           = "twi_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_TWI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-       .name           = "spi0_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_SPI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-       .name           = "spi1_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_SPI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc_clk = {
-       .name           = "ssc_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_SSC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc0_clk = {
-       .name           = "tc0_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_TC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc1_clk = {
-       .name           = "tc1_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_TC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc2_clk = {
-       .name           = "tc2_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_TC2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ohci_clk = {
-       .name           = "ohci_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_UHP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk macb_clk = {
-       .name           = "pclk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_EMAC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk isi_clk = {
-       .name           = "isi_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_ISI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_US3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart4_clk = {
-       .name           = "usart4_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_US4,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart5_clk = {
-       .name           = "usart5_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_US5,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc3_clk = {
-       .name           = "tc3_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_TC3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc4_clk = {
-       .name           = "tc4_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_TC4,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc5_clk = {
-       .name           = "tc5_clk",
-       .pmc_mask       = 1 << AT91SAM9260_ID_TC5,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioA_clk,
-       &pioB_clk,
-       &pioC_clk,
-       &adc_clk,
-       &adc_op_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &mmc_clk,
-       &udc_clk,
-       &twi_clk,
-       &spi0_clk,
-       &spi1_clk,
-       &ssc_clk,
-       &tc0_clk,
-       &tc1_clk,
-       &tc2_clk,
-       &ohci_clk,
-       &macb_clk,
-       &isi_clk,
-       &usart3_clk,
-       &usart4_clk,
-       &usart5_clk,
-       &tc3_clk,
-       &tc4_clk,
-       &tc5_clk,
-       // irq0 .. irq2
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       /* One additional fake clock for macb_hclk */
-       CLKDEV_CON_ID("hclk", &macb_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
-       /* more usart lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffb4000.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffb8000.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
-       CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffac000.i2c", &twi_clk),
-       /* more tc lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "fffdc000.timer", &tc3_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
-       CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffc8000.spi", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffcc000.spi", &spi1_clk),
-       /* fake hclk clock */
-       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
-       CLKDEV_CON_ID("pioA", &pioA_clk),
-       CLKDEV_CON_ID("pioB", &pioB_clk),
-       CLKDEV_CON_ID("pioC", &pioC_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
-};
-
-static struct clk_lookup usart_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.4", &usart3_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.5", &usart4_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.6", &usart5_clk),
-};
-
-/*
- * The two programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-
-static void __init at91sam9260_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-       clkdev_add_table(usart_clocks_lookups,
-                        ARRAY_SIZE(usart_clocks_lookups));
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-}
-#else
-#define at91sam9260_register_clocks NULL
-#endif
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91sam9260_gpio[] __initdata = {
-       {
-               .id             = AT91SAM9260_ID_PIOA,
-               .regbase        = AT91SAM9260_BASE_PIOA,
-       }, {
-               .id             = AT91SAM9260_ID_PIOB,
-               .regbase        = AT91SAM9260_BASE_PIOB,
-       }, {
-               .id             = AT91SAM9260_ID_PIOC,
-               .regbase        = AT91SAM9260_BASE_PIOC,
-       }
-};
 
 /* --------------------------------------------------------------------
  *  AT91SAM9260 processor initialization
@@ -340,119 +48,14 @@ static void __init at91sam9260_map_io(void)
                at91_init_sram(0, AT91SAM9260_SRAM_BASE, AT91SAM9260_SRAM_SIZE);
 }
 
-static void __init at91sam9260_ioremap_registers(void)
-{
-       at91_ioremap_ramc(0, AT91SAM9260_BASE_SDRAMC, 512);
-       at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
-       at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
-       at91_ioremap_matrix(AT91SAM9260_BASE_MATRIX);
-       at91_pm_set_standby(at91sam9_sdram_standby);
-}
-
 static void __init at91sam9260_initialize(void)
 {
        arm_pm_idle = at91sam9_idle;
 
        at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT);
-
-       /* Register GPIO subsystem */
-       at91_gpio_init(at91sam9260_gpio, 3);
-}
-
-static struct resource rstc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_RSTC,
-               .end    = AT91SAM9260_BASE_RSTC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9260_BASE_SDRAMC,
-               .end    = AT91SAM9260_BASE_SDRAMC + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device rstc_device = {
-       .name           = "at91-sam9260-reset",
-       .resource       = rstc_resources,
-       .num_resources  = ARRAY_SIZE(rstc_resources),
-};
-
-static struct resource shdwc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_SHDWC,
-               .end    = AT91SAM9260_BASE_SHDWC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device shdwc_device = {
-       .name           = "at91-poweroff",
-       .resource       = shdwc_resources,
-       .num_resources  = ARRAY_SIZE(shdwc_resources),
-};
-
-static void __init at91sam9260_register_devices(void)
-{
-       platform_device_register(&rstc_device);
-       platform_device_register(&shdwc_device);
-}
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A */
-       1,      /* Parallel IO Controller B */
-       1,      /* Parallel IO Controller C */
-       0,      /* Analog-to-Digital Converter */
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       0,      /* Multimedia Card Interface */
-       2,      /* USB Device Port */
-       6,      /* Two-Wire Interface */
-       5,      /* Serial Peripheral Interface 0 */
-       5,      /* Serial Peripheral Interface 1 */
-       5,      /* Serial Synchronous Controller */
-       0,
-       0,
-       0,      /* Timer Counter 0 */
-       0,      /* Timer Counter 1 */
-       0,      /* Timer Counter 2 */
-       2,      /* USB Host port */
-       3,      /* Ethernet */
-       0,      /* Image Sensor Interface */
-       5,      /* USART 3 */
-       5,      /* USART 4 */
-       5,      /* USART 5 */
-       0,      /* Timer Counter 3 */
-       0,      /* Timer Counter 4 */
-       0,      /* Timer Counter 5 */
-       0,      /* Advanced Interrupt Controller */
-       0,      /* Advanced Interrupt Controller */
-       0,      /* Advanced Interrupt Controller */
-};
-
-static void __init at91sam9260_init_time(void)
-{
-       at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
 }
 
 AT91_SOC_START(at91sam9260)
        .map_io = at91sam9260_map_io,
-       .default_irq_priority = at91sam9260_default_irq_priority,
-       .extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
-                   | (1 << AT91SAM9260_ID_IRQ2),
-       .ioremap_registers = at91sam9260_ioremap_registers,
-       .register_clocks = at91sam9260_register_clocks,
-       .register_devices = at91sam9260_register_devices,
        .init = at91sam9260_initialize,
-       .init_time = at91sam9260_init_time,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
deleted file mode 100644 (file)
index ef88e0f..0000000
+++ /dev/null
@@ -1,1364 +0,0 @@
-/*
- * arch/arm/mach-at91/at91sam9260_devices.c
- *
- *  Copyright (C) 2006 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.
- *
- */
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/i2c-gpio.h>
-
-#include <linux/platform_data/at91_adc.h>
-
-#include <mach/cpu.h>
-#include <mach/at91sam9260.h>
-#include <mach/at91sam9260_matrix.h>
-#include <mach/at91_matrix.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/hardware.h>
-
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-/* --------------------------------------------------------------------
- *  USB Host
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_UHP_BASE,
-               .end    = AT91SAM9260_UHP_BASE + SZ_1M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_usbh_device = {
-       .name           = "at91_ohci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &ohci_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &usbh_data,
-       },
-       .resource       = usbh_resources,
-       .num_resources  = ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-       int i;
-
-       if (!data)
-               return;
-
-       /* Enable overcurrent notification */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->overcurrent_pin[i]))
-                       at91_set_gpio_input(data->overcurrent_pin[i], 1);
-       }
-
-       usbh_data = *data;
-       platform_device_register(&at91_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_UDP,
-               .end    = AT91SAM9260_BASE_UDP + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_udc_device = {
-       .name           = "at91_udc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data          = &udc_data,
-       },
-       .resource       = udc_resources,
-       .num_resources  = ARRAY_SIZE(udc_resources),
-};
-
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->vbus_pin)) {
-               at91_set_gpio_input(data->vbus_pin, 0);
-               at91_set_deglitch(data->vbus_pin, 1);
-       }
-
-       /* Pullup pin is handled internally by USB device peripheral */
-
-       udc_data = *data;
-       platform_device_register(&at91_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Ethernet
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct macb_platform_data eth_data;
-
-static struct resource eth_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_EMAC,
-               .end    = AT91SAM9260_BASE_EMAC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_eth_device = {
-       .name           = "macb",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &eth_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &eth_data,
-       },
-       .resource       = eth_resources,
-       .num_resources  = ARRAY_SIZE(eth_resources),
-};
-
-void __init at91_add_device_eth(struct macb_platform_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->phy_irq_pin)) {
-               at91_set_gpio_input(data->phy_irq_pin, 0);
-               at91_set_deglitch(data->phy_irq_pin, 1);
-       }
-
-       /* Pins used for MII and RMII */
-       at91_set_A_periph(AT91_PIN_PA19, 0);    /* ETXCK_EREFCK */
-       at91_set_A_periph(AT91_PIN_PA17, 0);    /* ERXDV */
-       at91_set_A_periph(AT91_PIN_PA14, 0);    /* ERX0 */
-       at91_set_A_periph(AT91_PIN_PA15, 0);    /* ERX1 */
-       at91_set_A_periph(AT91_PIN_PA18, 0);    /* ERXER */
-       at91_set_A_periph(AT91_PIN_PA16, 0);    /* ETXEN */
-       at91_set_A_periph(AT91_PIN_PA12, 0);    /* ETX0 */
-       at91_set_A_periph(AT91_PIN_PA13, 0);    /* ETX1 */
-       at91_set_A_periph(AT91_PIN_PA21, 0);    /* EMDIO */
-       at91_set_A_periph(AT91_PIN_PA20, 0);    /* EMDC */
-
-       if (!data->is_rmii) {
-               at91_set_B_periph(AT91_PIN_PA28, 0);    /* ECRS */
-               at91_set_B_periph(AT91_PIN_PA29, 0);    /* ECOL */
-               at91_set_B_periph(AT91_PIN_PA25, 0);    /* ERX2 */
-               at91_set_B_periph(AT91_PIN_PA26, 0);    /* ERX3 */
-               at91_set_B_periph(AT91_PIN_PA27, 0);    /* ERXCK */
-               at91_set_B_periph(AT91_PIN_PA23, 0);    /* ETX2 */
-               at91_set_B_periph(AT91_PIN_PA24, 0);    /* ETX3 */
-               at91_set_B_periph(AT91_PIN_PA22, 0);    /* ETXER */
-       }
-
-       eth_data = *data;
-       platform_device_register(&at91sam9260_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct macb_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  MMC / SD Slot for Atmel MCI Driver
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc_data;
-
-static struct resource mmc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_MCI,
-               .end    = AT91SAM9260_BASE_MCI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_mmc_device = {
-       .name           = "atmel_mci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc_data,
-       },
-       .resource       = mmc_resources,
-       .num_resources  = ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-       unsigned int i;
-       unsigned int slot_count = 0;
-
-       if (!data)
-               return;
-
-       for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
-               if (data->slot[i].bus_width) {
-                       /* input/irq */
-                       if (gpio_is_valid(data->slot[i].detect_pin)) {
-                               at91_set_gpio_input(data->slot[i].detect_pin, 1);
-                               at91_set_deglitch(data->slot[i].detect_pin, 1);
-                       }
-                       if (gpio_is_valid(data->slot[i].wp_pin))
-                               at91_set_gpio_input(data->slot[i].wp_pin, 1);
-
-                       switch (i) {
-                       case 0:
-                               /* CMD */
-                               at91_set_A_periph(AT91_PIN_PA7, 1);
-                               /* DAT0, maybe DAT1..DAT3 */
-                               at91_set_A_periph(AT91_PIN_PA6, 1);
-                               if (data->slot[i].bus_width == 4) {
-                                       at91_set_A_periph(AT91_PIN_PA9, 1);
-                                       at91_set_A_periph(AT91_PIN_PA10, 1);
-                                       at91_set_A_periph(AT91_PIN_PA11, 1);
-                               }
-                               slot_count++;
-                               break;
-                       case 1:
-                               /* CMD */
-                               at91_set_B_periph(AT91_PIN_PA1, 1);
-                               /* DAT0, maybe DAT1..DAT3 */
-                               at91_set_B_periph(AT91_PIN_PA0, 1);
-                               if (data->slot[i].bus_width == 4) {
-                                       at91_set_B_periph(AT91_PIN_PA5, 1);
-                                       at91_set_B_periph(AT91_PIN_PA4, 1);
-                                       at91_set_B_periph(AT91_PIN_PA3, 1);
-                               }
-                               slot_count++;
-                               break;
-                       default:
-                               printk(KERN_ERR
-                                       "AT91: SD/MMC slot %d not available\n", i);
-                               break;
-                       }
-               }
-       }
-
-       if (slot_count) {
-               /* CLK */
-               at91_set_A_periph(AT91_PIN_PA8, 0);
-
-               mmc_data = *data;
-               platform_device_register(&at91sam9260_mmc_device);
-       }
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  NAND / SmartMedia
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE      AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-       [0] = {
-               .start  = NAND_BASE,
-               .end    = NAND_BASE + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9260_BASE_ECC,
-               .end    = AT91SAM9260_BASE_ECC + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9260_nand_device = {
-       .name           = "atmel_nand",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &nand_data,
-       },
-       .resource       = nand_resources,
-       .num_resources  = ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-       unsigned long csa;
-
-       if (!data)
-               return;
-
-       csa = at91_matrix_read(AT91_MATRIX_EBICSA);
-       at91_matrix_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
-
-       /* enable pin */
-       if (gpio_is_valid(data->enable_pin))
-               at91_set_gpio_output(data->enable_pin, 1);
-
-       /* ready/busy pin */
-       if (gpio_is_valid(data->rdy_pin))
-               at91_set_gpio_input(data->rdy_pin, 1);
-
-       /* card detect pin */
-       if (gpio_is_valid(data->det_pin))
-               at91_set_gpio_input(data->det_pin, 1);
-
-       nand_data = *data;
-       platform_device_register(&at91sam9260_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  TWI (i2c)
- * -------------------------------------------------------------------- */
-
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-       .sda_pin                = AT91_PIN_PA23,
-       .sda_is_open_drain      = 1,
-       .scl_pin                = AT91_PIN_PA24,
-       .scl_is_open_drain      = 1,
-       .udelay                 = 2,            /* ~100 kHz */
-};
-
-static struct platform_device at91sam9260_twi_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 0,
-       .dev.platform_data      = &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       at91_set_GPIO_periph(AT91_PIN_PA23, 1);         /* TWD (SDA) */
-       at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-       at91_set_GPIO_periph(AT91_PIN_PA24, 1);         /* TWCK (SCL) */
-       at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9260_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_TWI,
-               .end    = AT91SAM9260_BASE_TWI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_twi_device = {
-       .id             = 0,
-       .resource       = twi_resources,
-       .num_resources  = ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       /* IP version is not the same on 9260 and g20 */
-       if (cpu_is_at91sam9g20()) {
-               at91sam9260_twi_device.name = "i2c-at91sam9g20";
-       } else {
-               at91sam9260_twi_device.name = "i2c-at91sam9260";
-       }
-
-       /* pins used for TWI interface */
-       at91_set_A_periph(AT91_PIN_PA23, 0);            /* TWD */
-       at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-       at91_set_A_periph(AT91_PIN_PA24, 0);            /* TWCK */
-       at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9260_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_SPI0,
-               .end    = AT91SAM9260_BASE_SPI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_spi0_device = {
-       .name           = "atmel_spi",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi0_resources,
-       .num_resources  = ARRAY_SIZE(spi0_resources),
-};
-
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 };
-
-static struct resource spi1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_SPI1,
-               .end    = AT91SAM9260_BASE_SPI1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_spi1_device = {
-       .name           = "atmel_spi",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi1_resources,
-       .num_resources  = ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-       int i;
-       unsigned long cs_pin;
-       short enable_spi0 = 0;
-       short enable_spi1 = 0;
-
-       /* Choose SPI chip-selects */
-       for (i = 0; i < nr_devices; i++) {
-               if (devices[i].controller_data)
-                       cs_pin = (unsigned long) devices[i].controller_data;
-               else if (devices[i].bus_num == 0)
-                       cs_pin = spi0_standard_cs[devices[i].chip_select];
-               else
-                       cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-               if (!gpio_is_valid(cs_pin))
-                       continue;
-
-               if (devices[i].bus_num == 0)
-                       enable_spi0 = 1;
-               else
-                       enable_spi1 = 1;
-
-               /* enable chip-select pin */
-               at91_set_gpio_output(cs_pin, 1);
-
-               /* pass chip-select pin to driver */
-               devices[i].controller_data = (void *) cs_pin;
-       }
-
-       spi_register_board_info(devices, nr_devices);
-
-       /* Configure SPI bus(es) */
-       if (enable_spi0) {
-               at91_set_A_periph(AT91_PIN_PA0, 0);     /* SPI0_MISO */
-               at91_set_A_periph(AT91_PIN_PA1, 0);     /* SPI0_MOSI */
-               at91_set_A_periph(AT91_PIN_PA2, 0);     /* SPI1_SPCK */
-
-               platform_device_register(&at91sam9260_spi0_device);
-       }
-       if (enable_spi1) {
-               at91_set_A_periph(AT91_PIN_PB0, 0);     /* SPI1_MISO */
-               at91_set_A_periph(AT91_PIN_PB1, 0);     /* SPI1_MOSI */
-               at91_set_A_periph(AT91_PIN_PB2, 0);     /* SPI1_SPCK */
-
-               platform_device_register(&at91sam9260_spi1_device);
-       }
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Timer/Counter blocks
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_TCB0,
-               .end    = AT91SAM9260_BASE_TCB0 + SZ_256 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_tcb0_device = {
-       .name           = "atmel_tcb",
-       .id             = 0,
-       .resource       = tcb0_resources,
-       .num_resources  = ARRAY_SIZE(tcb0_resources),
-};
-
-static struct resource tcb1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_TCB1,
-               .end    = AT91SAM9260_BASE_TCB1 + SZ_256 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_tcb1_device = {
-       .name           = "atmel_tcb",
-       .id             = 1,
-       .resource       = tcb1_resources,
-       .num_resources  = ARRAY_SIZE(tcb1_resources),
-};
-
-static void __init at91_add_device_tc(void)
-{
-       platform_device_register(&at91sam9260_tcb0_device);
-       platform_device_register(&at91sam9260_tcb1_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
-/* --------------------------------------------------------------------
- *  RTT
- * -------------------------------------------------------------------- */
-
-static struct resource rtt_resources[] = {
-       {
-               .start  = AT91SAM9260_BASE_RTT,
-               .end    = AT91SAM9260_BASE_RTT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_rtt_device = {
-       .name           = "at91_rtt",
-       .id             = 0,
-       .resource       = rtt_resources,
-};
-
-
-#if IS_ENABLED(CONFIG_RTC_DRV_AT91SAM9)
-static void __init at91_add_device_rtt_rtc(void)
-{
-       at91sam9260_rtt_device.name = "rtc-at91sam9";
-       /*
-        * The second resource is needed:
-        * GPBR will serve as the storage for RTC time offset
-        */
-       at91sam9260_rtt_device.num_resources = 3;
-       rtt_resources[1].start = AT91SAM9260_BASE_GPBR +
-                                4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
-       rtt_resources[1].end = rtt_resources[1].start + 3;
-       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
-       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
-}
-#else
-static void __init at91_add_device_rtt_rtc(void)
-{
-       /* Only one resource is needed: RTT not used as RTC */
-       at91sam9260_rtt_device.num_resources = 1;
-}
-#endif
-
-static void __init at91_add_device_rtt(void)
-{
-       at91_add_device_rtt_rtc();
-       platform_device_register(&at91sam9260_rtt_device);
-}
-
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct resource wdt_resources[] = {
-       {
-               .start  = AT91SAM9260_BASE_WDT,
-               .end    = AT91SAM9260_BASE_WDT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9260_wdt_device = {
-       .name           = "at91_wdt",
-       .id             = -1,
-       .resource       = wdt_resources,
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-       platform_device_register(&at91sam9260_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SSC -- Synchronous Serial Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_SSC,
-               .end    = AT91SAM9260_BASE_SSC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9260_ssc_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 0,
-       .dev    = {
-               .dma_mask               = &ssc_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc_resources,
-       .num_resources  = ARRAY_SIZE(ssc_resources),
-};
-
-static inline void configure_ssc_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PB17, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PB16, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PB18, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PB19, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PB20, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PB21, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-       struct platform_device *pdev;
-
-       /*
-        * NOTE: caller is responsible for passing information matching
-        * "pins" to whatever will be using each particular controller.
-        */
-       switch (id) {
-       case AT91SAM9260_ID_SSC:
-               pdev = &at91sam9260_ssc_device;
-               configure_ssc_pins(pins);
-               break;
-       default:
-               return;
-       }
-
-       platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_DBGU,
-               .end    = AT91SAM9260_BASE_DBGU + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data dbgu_data = {
-       .use_dma_tx     = 0,
-       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_dbgu_device = {
-       .name           = "atmel_usart",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &dbgu_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &dbgu_data,
-       },
-       .resource       = dbgu_resources,
-       .num_resources  = ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-       at91_set_A_periph(AT91_PIN_PB14, 0);            /* DRXD */
-       at91_set_A_periph(AT91_PIN_PB15, 1);            /* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_US0,
-               .end    = AT91SAM9260_BASE_US0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart0_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart0_device = {
-       .name           = "atmel_usart",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &uart0_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart0_data,
-       },
-       .resource       = uart0_resources,
-       .num_resources  = ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB4, 1);             /* TXD0 */
-       at91_set_A_periph(AT91_PIN_PB5, 0);             /* RXD0 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PB26, 0);    /* RTS0 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PB27, 0);    /* CTS0 */
-       if (pins & ATMEL_UART_DTR)
-               at91_set_A_periph(AT91_PIN_PB24, 0);    /* DTR0 */
-       if (pins & ATMEL_UART_DSR)
-               at91_set_A_periph(AT91_PIN_PB22, 0);    /* DSR0 */
-       if (pins & ATMEL_UART_DCD)
-               at91_set_A_periph(AT91_PIN_PB23, 0);    /* DCD0 */
-       if (pins & ATMEL_UART_RI)
-               at91_set_A_periph(AT91_PIN_PB25, 0);    /* RI0 */
-}
-
-static struct resource uart1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_US1,
-               .end    = AT91SAM9260_BASE_US1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart1_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart1_device = {
-       .name           = "atmel_usart",
-       .id             = 2,
-       .dev            = {
-                               .dma_mask               = &uart1_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart1_data,
-       },
-       .resource       = uart1_resources,
-       .num_resources  = ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB6, 1);             /* TXD1 */
-       at91_set_A_periph(AT91_PIN_PB7, 0);             /* RXD1 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PB28, 0);    /* RTS1 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PB29, 0);    /* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_US2,
-               .end    = AT91SAM9260_BASE_US2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart2_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart2_device = {
-       .name           = "atmel_usart",
-       .id             = 3,
-       .dev            = {
-                               .dma_mask               = &uart2_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart2_data,
-       },
-       .resource       = uart2_resources,
-       .num_resources  = ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB8, 1);             /* TXD2 */
-       at91_set_A_periph(AT91_PIN_PB9, 0);             /* RXD2 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PA4, 0);     /* RTS2 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PA5, 0);     /* CTS2 */
-}
-
-static struct resource uart3_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_US3,
-               .end    = AT91SAM9260_BASE_US3 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart3_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart3_device = {
-       .name           = "atmel_usart",
-       .id             = 4,
-       .dev            = {
-                               .dma_mask               = &uart3_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart3_data,
-       },
-       .resource       = uart3_resources,
-       .num_resources  = ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB10, 1);            /* TXD3 */
-       at91_set_A_periph(AT91_PIN_PB11, 0);            /* RXD3 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PC8, 0);     /* RTS3 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PC10, 0);    /* CTS3 */
-}
-
-static struct resource uart4_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_US4,
-               .end    = AT91SAM9260_BASE_US4 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart4_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart4_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart4_device = {
-       .name           = "atmel_usart",
-       .id             = 5,
-       .dev            = {
-                               .dma_mask               = &uart4_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart4_data,
-       },
-       .resource       = uart4_resources,
-       .num_resources  = ARRAY_SIZE(uart4_resources),
-};
-
-static inline void configure_usart4_pins(void)
-{
-       at91_set_B_periph(AT91_PIN_PA31, 1);            /* TXD4 */
-       at91_set_B_periph(AT91_PIN_PA30, 0);            /* RXD4 */
-}
-
-static struct resource uart5_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_US5,
-               .end    = AT91SAM9260_BASE_US5 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart5_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart5_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9260_uart5_device = {
-       .name           = "atmel_usart",
-       .id             = 6,
-       .dev            = {
-                               .dma_mask               = &uart5_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart5_data,
-       },
-       .resource       = uart5_resources,
-       .num_resources  = ARRAY_SIZE(uart5_resources),
-};
-
-static inline void configure_usart5_pins(void)
-{
-       at91_set_A_periph(AT91_PIN_PB12, 1);            /* TXD5 */
-       at91_set_A_periph(AT91_PIN_PB13, 0);            /* RXD5 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];  /* the UARTs to use */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-       struct platform_device *pdev;
-       struct atmel_uart_data *pdata;
-
-       switch (id) {
-               case 0:         /* DBGU */
-                       pdev = &at91sam9260_dbgu_device;
-                       configure_dbgu_pins();
-                       break;
-               case AT91SAM9260_ID_US0:
-                       pdev = &at91sam9260_uart0_device;
-                       configure_usart0_pins(pins);
-                       break;
-               case AT91SAM9260_ID_US1:
-                       pdev = &at91sam9260_uart1_device;
-                       configure_usart1_pins(pins);
-                       break;
-               case AT91SAM9260_ID_US2:
-                       pdev = &at91sam9260_uart2_device;
-                       configure_usart2_pins(pins);
-                       break;
-               case AT91SAM9260_ID_US3:
-                       pdev = &at91sam9260_uart3_device;
-                       configure_usart3_pins(pins);
-                       break;
-               case AT91SAM9260_ID_US4:
-                       pdev = &at91sam9260_uart4_device;
-                       configure_usart4_pins();
-                       break;
-               case AT91SAM9260_ID_US5:
-                       pdev = &at91sam9260_uart5_device;
-                       configure_usart5_pins();
-                       break;
-               default:
-                       return;
-       }
-       pdata = pdev->dev.platform_data;
-       pdata->num = portnr;            /* update to mapped ID */
-
-       if (portnr < ATMEL_MAX_UART)
-               at91_uarts[portnr] = pdev;
-}
-
-void __init at91_add_device_serial(void)
-{
-       int i;
-
-       for (i = 0; i < ATMEL_MAX_UART; i++) {
-               if (at91_uarts[i])
-                       platform_device_register(at91_uarts[i]);
-       }
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  CF/IDE
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
-       defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
-
-static struct at91_cf_data cf0_data;
-
-static struct resource cf0_resources[] = {
-       [0] = {
-               .start  = AT91_CHIPSELECT_4,
-               .end    = AT91_CHIPSELECT_4 + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device cf0_device = {
-       .id             = 0,
-       .dev            = {
-                               .platform_data  = &cf0_data,
-       },
-       .resource       = cf0_resources,
-       .num_resources  = ARRAY_SIZE(cf0_resources),
-};
-
-static struct at91_cf_data cf1_data;
-
-static struct resource cf1_resources[] = {
-       [0] = {
-               .start  = AT91_CHIPSELECT_5,
-               .end    = AT91_CHIPSELECT_5 + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device cf1_device = {
-       .id             = 1,
-       .dev            = {
-                               .platform_data  = &cf1_data,
-       },
-       .resource       = cf1_resources,
-       .num_resources  = ARRAY_SIZE(cf1_resources),
-};
-
-void __init at91_add_device_cf(struct at91_cf_data *data)
-{
-       struct platform_device *pdev;
-       unsigned long csa;
-
-       if (!data)
-               return;
-
-       csa = at91_matrix_read(AT91_MATRIX_EBICSA);
-
-       switch (data->chipselect) {
-       case 4:
-               at91_set_multi_drive(AT91_PIN_PC8, 0);
-               at91_set_A_periph(AT91_PIN_PC8, 0);
-               csa |= AT91_MATRIX_CS4A_SMC_CF1;
-               cf0_data = *data;
-               pdev = &cf0_device;
-               break;
-       case 5:
-               at91_set_multi_drive(AT91_PIN_PC9, 0);
-               at91_set_A_periph(AT91_PIN_PC9, 0);
-               csa |= AT91_MATRIX_CS5A_SMC_CF2;
-               cf1_data = *data;
-               pdev = &cf1_device;
-               break;
-       default:
-               printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n",
-                      data->chipselect);
-               return;
-       }
-
-       at91_matrix_write(AT91_MATRIX_EBICSA, csa);
-
-       if (gpio_is_valid(data->rst_pin)) {
-               at91_set_multi_drive(data->rst_pin, 0);
-               at91_set_gpio_output(data->rst_pin, 1);
-       }
-
-       if (gpio_is_valid(data->irq_pin)) {
-               at91_set_gpio_input(data->irq_pin, 0);
-               at91_set_deglitch(data->irq_pin, 1);
-       }
-
-       if (gpio_is_valid(data->det_pin)) {
-               at91_set_gpio_input(data->det_pin, 0);
-               at91_set_deglitch(data->det_pin, 1);
-       }
-
-       at91_set_B_periph(AT91_PIN_PC6, 0);     /* CFCE1 */
-       at91_set_B_periph(AT91_PIN_PC7, 0);     /* CFCE2 */
-       at91_set_A_periph(AT91_PIN_PC10, 0);    /* CFRNW */
-       at91_set_A_periph(AT91_PIN_PC15, 1);    /* NWAIT */
-
-       if (IS_ENABLED(CONFIG_PATA_AT91) && (data->flags & AT91_CF_TRUE_IDE))
-               pdev->name = "pata_at91";
-       else
-               pdev->name = "at91_cf";
-
-       platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_cf(struct at91_cf_data * data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  ADCs
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_AT91_ADC)
-static struct at91_adc_data adc_data;
-
-static struct resource adc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9260_BASE_ADC,
-               .end    = AT91SAM9260_BASE_ADC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_ADC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_ADC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_adc_device = {
-       .name           = "at91sam9260-adc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data          = &adc_data,
-       },
-       .resource       = adc_resources,
-       .num_resources  = ARRAY_SIZE(adc_resources),
-};
-
-static struct at91_adc_trigger at91_adc_triggers[] = {
-       [0] = {
-               .name = "timer-counter-0",
-               .value = 0x1,
-       },
-       [1] = {
-               .name = "timer-counter-1",
-               .value = 0x3,
-       },
-       [2] = {
-               .name = "timer-counter-2",
-               .value = 0x5,
-       },
-       [3] = {
-               .name = "external",
-               .value = 0xd,
-               .is_external = true,
-       },
-};
-
-void __init at91_add_device_adc(struct at91_adc_data *data)
-{
-       if (!data)
-               return;
-
-       if (test_bit(0, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PC0, 0);
-       if (test_bit(1, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PC1, 0);
-       if (test_bit(2, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PC2, 0);
-       if (test_bit(3, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PC3, 0);
-
-       if (data->use_external_triggers)
-               at91_set_A_periph(AT91_PIN_PA22, 0);
-
-       data->startup_time = 10;
-       data->trigger_number = 4;
-       data->trigger_list = at91_adc_triggers;
-
-       adc_data = *data;
-       platform_device_register(&at91_adc_device);
-}
-#else
-void __init at91_add_device_adc(struct at91_adc_data *data) {}
-#endif
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-       if (of_have_populated_dt())
-               return 0;
-
-       at91_add_device_rtt();
-       at91_add_device_watchdog();
-       at91_add_device_tc();
-       return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
index a8bd35963332f540bdcac00e87f04d09f121b805..d29953ecb0c441aa7fcdf814a708df3c8ba10a53 100644 (file)
  *
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk/at91_pmc.h>
-
-#include <asm/proc-fns.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/cpu.h>
-#include <mach/at91sam9261.h>
 #include <mach/hardware.h>
 
-#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-#include "pm.h"
-
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_PIOA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_PIOB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-       .name           = "pioC_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_PIOC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_US0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_US1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_US2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-       .name           = "mci_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_MCI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udc_clk = {
-       .name           = "udc_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_UDP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi_clk = {
-       .name           = "twi_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_TWI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-       .name           = "spi0_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_SPI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-       .name           = "spi1_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_SPI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc0_clk = {
-       .name           = "ssc0_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_SSC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc1_clk = {
-       .name           = "ssc1_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_SSC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc2_clk = {
-       .name           = "ssc2_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_SSC2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc0_clk = {
-       .name           = "tc0_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_TC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc1_clk = {
-       .name           = "tc1_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_TC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc2_clk = {
-       .name           = "tc2_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_TC2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ohci_clk = {
-       .name           = "ohci_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_UHP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk lcdc_clk = {
-       .name           = "lcdc_clk",
-       .pmc_mask       = 1 << AT91SAM9261_ID_LCDC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-/* HClocks */
-static struct clk hck0 = {
-       .name           = "hck0",
-       .pmc_mask       = AT91_PMC_HCK0,
-       .type           = CLK_TYPE_SYSTEM,
-       .id             = 0,
-};
-static struct clk hck1 = {
-       .name           = "hck1",
-       .pmc_mask       = AT91_PMC_HCK1,
-       .type           = CLK_TYPE_SYSTEM,
-       .id             = 1,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioA_clk,
-       &pioB_clk,
-       &pioC_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &mmc_clk,
-       &udc_clk,
-       &twi_clk,
-       &spi0_clk,
-       &spi1_clk,
-       &ssc0_clk,
-       &ssc1_clk,
-       &ssc2_clk,
-       &tc0_clk,
-       &tc1_clk,
-       &tc2_clk,
-       &ohci_clk,
-       &lcdc_clk,
-       // irq0 .. irq2
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("hclk", "at91sam9261-lcdfb.0", &hck1),
-       CLKDEV_CON_DEV_ID("hclk", "at91sam9g10-lcdfb.0", &hck1),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc2_clk),
-       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
-       CLKDEV_CON_ID("pioA", &pioA_clk),
-       CLKDEV_CON_ID("pioB", &pioB_clk),
-       CLKDEV_CON_ID("pioC", &pioC_clk),
-       /* more lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "ffffb400.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
-       CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &hck0),
-       CLKDEV_CON_DEV_ID("hclk", "600000.fb", &hck1),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffc8000.spi", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffcc000.spi", &spi1_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffac000.i2c", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
-};
-
-static struct clk_lookup usart_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),
-};
-
-/*
- * The four programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-static struct clk pck2 = {
-       .name           = "pck2",
-       .pmc_mask       = AT91_PMC_PCK2,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 2,
-};
-static struct clk pck3 = {
-       .name           = "pck3",
-       .pmc_mask       = AT91_PMC_PCK3,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 3,
-};
-
-static void __init at91sam9261_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-       clkdev_add_table(usart_clocks_lookups,
-                        ARRAY_SIZE(usart_clocks_lookups));
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-       clk_register(&pck2);
-       clk_register(&pck3);
-
-       clk_register(&hck0);
-       clk_register(&hck1);
-}
-#else
-#define at91sam9261_register_clocks NULL
-#endif
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91sam9261_gpio[] __initdata = {
-       {
-               .id             = AT91SAM9261_ID_PIOA,
-               .regbase        = AT91SAM9261_BASE_PIOA,
-       }, {
-               .id             = AT91SAM9261_ID_PIOB,
-               .regbase        = AT91SAM9261_BASE_PIOB,
-       }, {
-               .id             = AT91SAM9261_ID_PIOC,
-               .regbase        = AT91SAM9261_BASE_PIOC,
-       }
-};
 
 /* --------------------------------------------------------------------
  *  AT91SAM9261 processor initialization
@@ -299,119 +29,14 @@ static void __init at91sam9261_map_io(void)
                at91_init_sram(0, AT91SAM9261_SRAM_BASE, AT91SAM9261_SRAM_SIZE);
 }
 
-static void __init at91sam9261_ioremap_registers(void)
-{
-       at91_ioremap_ramc(0, AT91SAM9261_BASE_SDRAMC, 512);
-       at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
-       at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
-       at91_ioremap_matrix(AT91SAM9261_BASE_MATRIX);
-       at91_pm_set_standby(at91sam9_sdram_standby);
-}
-
 static void __init at91sam9261_initialize(void)
 {
        arm_pm_idle = at91sam9_idle;
 
        at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT);
-
-       /* Register GPIO subsystem */
-       at91_gpio_init(at91sam9261_gpio, 3);
-}
-
-static struct resource rstc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_RSTC,
-               .end    = AT91SAM9261_BASE_RSTC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9261_BASE_SDRAMC,
-               .end    = AT91SAM9261_BASE_SDRAMC + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device rstc_device = {
-       .name           = "at91-sam9260-reset",
-       .resource       = rstc_resources,
-       .num_resources  = ARRAY_SIZE(rstc_resources),
-};
-
-static struct resource shdwc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_SHDWC,
-               .end    = AT91SAM9261_BASE_SHDWC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device shdwc_device = {
-       .name           = "at91-poweroff",
-       .resource       = shdwc_resources,
-       .num_resources  = ARRAY_SIZE(shdwc_resources),
-};
-
-static void __init at91sam9261_register_devices(void)
-{
-       platform_device_register(&rstc_device);
-       platform_device_register(&shdwc_device);
-}
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A */
-       1,      /* Parallel IO Controller B */
-       1,      /* Parallel IO Controller C */
-       0,
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       0,      /* Multimedia Card Interface */
-       2,      /* USB Device Port */
-       6,      /* Two-Wire Interface */
-       5,      /* Serial Peripheral Interface 0 */
-       5,      /* Serial Peripheral Interface 1 */
-       4,      /* Serial Synchronous Controller 0 */
-       4,      /* Serial Synchronous Controller 1 */
-       4,      /* Serial Synchronous Controller 2 */
-       0,      /* Timer Counter 0 */
-       0,      /* Timer Counter 1 */
-       0,      /* Timer Counter 2 */
-       2,      /* USB Host port */
-       3,      /* LCD Controller */
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,      /* Advanced Interrupt Controller */
-       0,      /* Advanced Interrupt Controller */
-       0,      /* Advanced Interrupt Controller */
-};
-
-static void __init at91sam9261_init_time(void)
-{
-       at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
 }
 
 AT91_SOC_START(at91sam9261)
        .map_io = at91sam9261_map_io,
-       .default_irq_priority = at91sam9261_default_irq_priority,
-       .extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
-                   | (1 << AT91SAM9261_ID_IRQ2),
-       .ioremap_registers = at91sam9261_ioremap_registers,
-       .register_clocks = at91sam9261_register_clocks,
-       .register_devices = at91sam9261_register_devices,
        .init = at91sam9261_initialize,
-       .init_time = at91sam9261_init_time,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
deleted file mode 100644 (file)
index 29baacb..0000000
+++ /dev/null
@@ -1,1098 +0,0 @@
-/*
- * arch/arm/mach-at91/at91sam9261_devices.c
- *
- *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
- *  Copyright (C) 2005 David Brownell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/i2c-gpio.h>
-
-#include <linux/fb.h>
-#include <video/atmel_lcdc.h>
-
-#include <mach/at91sam9261.h>
-#include <mach/at91sam9261_matrix.h>
-#include <mach/at91_matrix.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/hardware.h>
-
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-/* --------------------------------------------------------------------
- *  USB Host
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_UHP_BASE,
-               .end    = AT91SAM9261_UHP_BASE + SZ_1M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_usbh_device = {
-       .name           = "at91_ohci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &ohci_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &usbh_data,
-       },
-       .resource       = usbh_resources,
-       .num_resources  = ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-       int i;
-
-       if (!data)
-               return;
-
-       /* Enable overcurrent notification */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->overcurrent_pin[i]))
-                       at91_set_gpio_input(data->overcurrent_pin[i], 1);
-       }
-
-       usbh_data = *data;
-       platform_device_register(&at91sam9261_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_UDP,
-               .end    = AT91SAM9261_BASE_UDP + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_udc_device = {
-       .name           = "at91_udc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data          = &udc_data,
-       },
-       .resource       = udc_resources,
-       .num_resources  = ARRAY_SIZE(udc_resources),
-};
-
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->vbus_pin)) {
-               at91_set_gpio_input(data->vbus_pin, 0);
-               at91_set_deglitch(data->vbus_pin, 1);
-       }
-
-       /* Pullup pin is handled internally by USB device peripheral */
-
-       udc_data = *data;
-       platform_device_register(&at91sam9261_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc_data;
-
-static struct resource mmc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_MCI,
-               .end    = AT91SAM9261_BASE_MCI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_mmc_device = {
-       .name           = "atmel_mci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc_data,
-       },
-       .resource       = mmc_resources,
-       .num_resources  = ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-       if (!data)
-               return;
-
-       if (data->slot[0].bus_width) {
-               /* input/irq */
-               if (gpio_is_valid(data->slot[0].detect_pin)) {
-                       at91_set_gpio_input(data->slot[0].detect_pin, 1);
-                       at91_set_deglitch(data->slot[0].detect_pin, 1);
-               }
-               if (gpio_is_valid(data->slot[0].wp_pin))
-                       at91_set_gpio_input(data->slot[0].wp_pin, 1);
-
-               /* CLK */
-               at91_set_B_periph(AT91_PIN_PA2, 0);
-
-               /* CMD */
-               at91_set_B_periph(AT91_PIN_PA1, 1);
-
-               /* DAT0, maybe DAT1..DAT3 */
-               at91_set_B_periph(AT91_PIN_PA0, 1);
-               if (data->slot[0].bus_width == 4) {
-                       at91_set_B_periph(AT91_PIN_PA4, 1);
-                       at91_set_B_periph(AT91_PIN_PA5, 1);
-                       at91_set_B_periph(AT91_PIN_PA6, 1);
-               }
-
-               mmc_data = *data;
-               platform_device_register(&at91sam9261_mmc_device);
-       }
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  NAND / SmartMedia
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE      AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-       {
-               .start  = NAND_BASE,
-               .end    = NAND_BASE + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device atmel_nand_device = {
-       .name           = "atmel_nand",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &nand_data,
-       },
-       .resource       = nand_resources,
-       .num_resources  = ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-       unsigned long csa;
-
-       if (!data)
-               return;
-
-       csa = at91_matrix_read(AT91_MATRIX_EBICSA);
-       at91_matrix_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
-
-       /* enable pin */
-       if (gpio_is_valid(data->enable_pin))
-               at91_set_gpio_output(data->enable_pin, 1);
-
-       /* ready/busy pin */
-       if (gpio_is_valid(data->rdy_pin))
-               at91_set_gpio_input(data->rdy_pin, 1);
-
-       /* card detect pin */
-       if (gpio_is_valid(data->det_pin))
-               at91_set_gpio_input(data->det_pin, 1);
-
-       at91_set_A_periph(AT91_PIN_PC0, 0);             /* NANDOE */
-       at91_set_A_periph(AT91_PIN_PC1, 0);             /* NANDWE */
-
-       nand_data = *data;
-       platform_device_register(&atmel_nand_device);
-}
-
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  TWI (i2c)
- * -------------------------------------------------------------------- */
-
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-       .sda_pin                = AT91_PIN_PA7,
-       .sda_is_open_drain      = 1,
-       .scl_pin                = AT91_PIN_PA8,
-       .scl_is_open_drain      = 1,
-       .udelay                 = 2,            /* ~100 kHz */
-};
-
-static struct platform_device at91sam9261_twi_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 0,
-       .dev.platform_data      = &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       at91_set_GPIO_periph(AT91_PIN_PA7, 1);          /* TWD (SDA) */
-       at91_set_multi_drive(AT91_PIN_PA7, 1);
-
-       at91_set_GPIO_periph(AT91_PIN_PA8, 1);          /* TWCK (SCL) */
-       at91_set_multi_drive(AT91_PIN_PA8, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9261_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_TWI,
-               .end    = AT91SAM9261_BASE_TWI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_twi_device = {
-       .id             = 0,
-       .resource       = twi_resources,
-       .num_resources  = ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       /* IP version is not the same on 9261 and g10 */
-       if (cpu_is_at91sam9g10()) {
-               at91sam9261_twi_device.name = "i2c-at91sam9g10";
-               /* I2C PIO must not be configured as open-drain on this chip */
-       } else {
-               at91sam9261_twi_device.name = "i2c-at91sam9261";
-               at91_set_multi_drive(AT91_PIN_PA7, 1);
-               at91_set_multi_drive(AT91_PIN_PA8, 1);
-       }
-
-       /* pins used for TWI interface */
-       at91_set_A_periph(AT91_PIN_PA7, 0);             /* TWD */
-       at91_set_A_periph(AT91_PIN_PA8, 0);             /* TWCK */
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9261_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_SPI0,
-               .end    = AT91SAM9261_BASE_SPI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_spi0_device = {
-       .name           = "atmel_spi",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi0_resources,
-       .num_resources  = ARRAY_SIZE(spi0_resources),
-};
-
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
-
-static struct resource spi1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_SPI1,
-               .end    = AT91SAM9261_BASE_SPI1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_spi1_device = {
-       .name           = "atmel_spi",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi1_resources,
-       .num_resources  = ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-       int i;
-       unsigned long cs_pin;
-       short enable_spi0 = 0;
-       short enable_spi1 = 0;
-
-       /* Choose SPI chip-selects */
-       for (i = 0; i < nr_devices; i++) {
-               if (devices[i].controller_data)
-                       cs_pin = (unsigned long) devices[i].controller_data;
-               else if (devices[i].bus_num == 0)
-                       cs_pin = spi0_standard_cs[devices[i].chip_select];
-               else
-                       cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-               if (!gpio_is_valid(cs_pin))
-                       continue;
-
-               if (devices[i].bus_num == 0)
-                       enable_spi0 = 1;
-               else
-                       enable_spi1 = 1;
-
-               /* enable chip-select pin */
-               at91_set_gpio_output(cs_pin, 1);
-
-               /* pass chip-select pin to driver */
-               devices[i].controller_data = (void *) cs_pin;
-       }
-
-       spi_register_board_info(devices, nr_devices);
-
-       /* Configure SPI bus(es) */
-       if (enable_spi0) {
-               at91_set_A_periph(AT91_PIN_PA0, 0);     /* SPI0_MISO */
-               at91_set_A_periph(AT91_PIN_PA1, 0);     /* SPI0_MOSI */
-               at91_set_A_periph(AT91_PIN_PA2, 0);     /* SPI0_SPCK */
-
-               platform_device_register(&at91sam9261_spi0_device);
-       }
-       if (enable_spi1) {
-               at91_set_A_periph(AT91_PIN_PB30, 0);    /* SPI1_MISO */
-               at91_set_A_periph(AT91_PIN_PB31, 0);    /* SPI1_MOSI */
-               at91_set_A_periph(AT91_PIN_PB29, 0);    /* SPI1_SPCK */
-
-               platform_device_register(&at91sam9261_spi1_device);
-       }
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  LCD Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_pdata lcdc_data;
-
-static struct resource lcdc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_LCDC_BASE,
-               .end    = AT91SAM9261_LCDC_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
-               .flags  = IORESOURCE_IRQ,
-       },
-#if defined(CONFIG_FB_INTSRAM)
-       [2] = {
-               .start  = AT91SAM9261_SRAM_BASE,
-               .end    = AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-#endif
-};
-
-static struct platform_device at91_lcdc_device = {
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &lcdc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &lcdc_data,
-       },
-       .resource       = lcdc_resources,
-       .num_resources  = ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
-{
-       if (!data) {
-               return;
-       }
-
-       if (cpu_is_at91sam9g10())
-               at91_lcdc_device.name = "at91sam9g10-lcdfb";
-       else
-               at91_lcdc_device.name = "at91sam9261-lcdfb";
-
-#if defined(CONFIG_FB_ATMEL_STN)
-       at91_set_A_periph(AT91_PIN_PB0, 0);     /* LCDVSYNC */
-       at91_set_A_periph(AT91_PIN_PB1, 0);     /* LCDHSYNC */
-       at91_set_A_periph(AT91_PIN_PB2, 0);     /* LCDDOTCK */
-       at91_set_A_periph(AT91_PIN_PB3, 0);     /* LCDDEN */
-       at91_set_A_periph(AT91_PIN_PB4, 0);     /* LCDCC */
-       at91_set_A_periph(AT91_PIN_PB5, 0);     /* LCDD0 */
-       at91_set_A_periph(AT91_PIN_PB6, 0);     /* LCDD1 */
-       at91_set_A_periph(AT91_PIN_PB7, 0);     /* LCDD2 */
-       at91_set_A_periph(AT91_PIN_PB8, 0);     /* LCDD3 */
-#else
-       at91_set_A_periph(AT91_PIN_PB1, 0);     /* LCDHSYNC */
-       at91_set_A_periph(AT91_PIN_PB2, 0);     /* LCDDOTCK */
-       at91_set_A_periph(AT91_PIN_PB3, 0);     /* LCDDEN */
-       at91_set_A_periph(AT91_PIN_PB4, 0);     /* LCDCC */
-       at91_set_A_periph(AT91_PIN_PB7, 0);     /* LCDD2 */
-       at91_set_A_periph(AT91_PIN_PB8, 0);     /* LCDD3 */
-       at91_set_A_periph(AT91_PIN_PB9, 0);     /* LCDD4 */
-       at91_set_A_periph(AT91_PIN_PB10, 0);    /* LCDD5 */
-       at91_set_A_periph(AT91_PIN_PB11, 0);    /* LCDD6 */
-       at91_set_A_periph(AT91_PIN_PB12, 0);    /* LCDD7 */
-       at91_set_A_periph(AT91_PIN_PB15, 0);    /* LCDD10 */
-       at91_set_A_periph(AT91_PIN_PB16, 0);    /* LCDD11 */
-       at91_set_A_periph(AT91_PIN_PB17, 0);    /* LCDD12 */
-       at91_set_A_periph(AT91_PIN_PB18, 0);    /* LCDD13 */
-       at91_set_A_periph(AT91_PIN_PB19, 0);    /* LCDD14 */
-       at91_set_A_periph(AT91_PIN_PB20, 0);    /* LCDD15 */
-       at91_set_B_periph(AT91_PIN_PB23, 0);    /* LCDD18 */
-       at91_set_B_periph(AT91_PIN_PB24, 0);    /* LCDD19 */
-       at91_set_B_periph(AT91_PIN_PB25, 0);    /* LCDD20 */
-       at91_set_B_periph(AT91_PIN_PB26, 0);    /* LCDD21 */
-       at91_set_B_periph(AT91_PIN_PB27, 0);    /* LCDD22 */
-       at91_set_B_periph(AT91_PIN_PB28, 0);    /* LCDD23 */
-#endif
-
-       if (ARRAY_SIZE(lcdc_resources) > 2) {
-               void __iomem *fb;
-               struct resource *fb_res = &lcdc_resources[2];
-               size_t fb_len = resource_size(fb_res);
-
-               fb = ioremap(fb_res->start, fb_len);
-               if (fb) {
-                       memset(fb, 0, fb_len);
-                       iounmap(fb);
-               }
-       }
-       lcdc_data = *data;
-       platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Timer/Counter block
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_TCB0,
-               .end    = AT91SAM9261_BASE_TCB0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_tcb_device = {
-       .name           = "atmel_tcb",
-       .id             = 0,
-       .resource       = tcb_resources,
-       .num_resources  = ARRAY_SIZE(tcb_resources),
-};
-
-static void __init at91_add_device_tc(void)
-{
-       platform_device_register(&at91sam9261_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
-/* --------------------------------------------------------------------
- *  RTT
- * -------------------------------------------------------------------- */
-
-static struct resource rtt_resources[] = {
-       {
-               .start  = AT91SAM9261_BASE_RTT,
-               .end    = AT91SAM9261_BASE_RTT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static struct platform_device at91sam9261_rtt_device = {
-       .name           = "at91_rtt",
-       .id             = 0,
-       .resource       = rtt_resources,
-};
-
-#if IS_ENABLED(CONFIG_RTC_DRV_AT91SAM9)
-static void __init at91_add_device_rtt_rtc(void)
-{
-       at91sam9261_rtt_device.name = "rtc-at91sam9";
-       /*
-        * The second resource is needed:
-        * GPBR will serve as the storage for RTC time offset
-        */
-       at91sam9261_rtt_device.num_resources = 3;
-       rtt_resources[1].start = AT91SAM9261_BASE_GPBR +
-                                4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
-       rtt_resources[1].end = rtt_resources[1].start + 3;
-       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
-       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
-}
-#else
-static void __init at91_add_device_rtt_rtc(void)
-{
-       /* Only one resource is needed: RTT not used as RTC */
-       at91sam9261_rtt_device.num_resources = 1;
-}
-#endif
-
-static void __init at91_add_device_rtt(void)
-{
-       at91_add_device_rtt_rtc();
-       platform_device_register(&at91sam9261_rtt_device);
-}
-
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct resource wdt_resources[] = {
-       {
-               .start  = AT91SAM9261_BASE_WDT,
-               .end    = AT91SAM9261_BASE_WDT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9261_wdt_device = {
-       .name           = "at91_wdt",
-       .id             = -1,
-       .resource       = wdt_resources,
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-       platform_device_register(&at91sam9261_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SSC -- Synchronous Serial Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_SSC0,
-               .end    = AT91SAM9261_BASE_SSC0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_ssc0_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 0,
-       .dev    = {
-               .dma_mask               = &ssc0_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc0_resources,
-       .num_resources  = ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PB21, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PB22, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PB23, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PB24, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PB25, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PB26, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_SSC1,
-               .end    = AT91SAM9261_BASE_SSC1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_ssc1_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 1,
-       .dev    = {
-               .dma_mask               = &ssc1_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc1_resources,
-       .num_resources  = ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_B_periph(AT91_PIN_PA17, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_B_periph(AT91_PIN_PA18, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_B_periph(AT91_PIN_PA19, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_B_periph(AT91_PIN_PA20, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_B_periph(AT91_PIN_PA21, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_B_periph(AT91_PIN_PA22, 1);
-}
-
-static u64 ssc2_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc2_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_SSC2,
-               .end    = AT91SAM9261_BASE_SSC2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9261_ssc2_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 2,
-       .dev    = {
-               .dma_mask               = &ssc2_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc2_resources,
-       .num_resources  = ARRAY_SIZE(ssc2_resources),
-};
-
-static inline void configure_ssc2_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_B_periph(AT91_PIN_PC25, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_B_periph(AT91_PIN_PC26, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_B_periph(AT91_PIN_PC27, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_B_periph(AT91_PIN_PC28, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_B_periph(AT91_PIN_PC29, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_B_periph(AT91_PIN_PC30, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-       struct platform_device *pdev;
-
-       /*
-        * NOTE: caller is responsible for passing information matching
-        * "pins" to whatever will be using each particular controller.
-        */
-       switch (id) {
-       case AT91SAM9261_ID_SSC0:
-               pdev = &at91sam9261_ssc0_device;
-               configure_ssc0_pins(pins);
-               break;
-       case AT91SAM9261_ID_SSC1:
-               pdev = &at91sam9261_ssc1_device;
-               configure_ssc1_pins(pins);
-               break;
-       case AT91SAM9261_ID_SSC2:
-               pdev = &at91sam9261_ssc2_device;
-               configure_ssc2_pins(pins);
-               break;
-       default:
-               return;
-       }
-
-       platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_DBGU,
-               .end    = AT91SAM9261_BASE_DBGU + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data dbgu_data = {
-       .use_dma_tx     = 0,
-       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_dbgu_device = {
-       .name           = "atmel_usart",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &dbgu_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &dbgu_data,
-       },
-       .resource       = dbgu_resources,
-       .num_resources  = ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-       at91_set_A_periph(AT91_PIN_PA9, 0);             /* DRXD */
-       at91_set_A_periph(AT91_PIN_PA10, 1);            /* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_US0,
-               .end    = AT91SAM9261_BASE_US0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart0_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_uart0_device = {
-       .name           = "atmel_usart",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &uart0_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart0_data,
-       },
-       .resource       = uart0_resources,
-       .num_resources  = ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PC8, 1);             /* TXD0 */
-       at91_set_A_periph(AT91_PIN_PC9, 0);             /* RXD0 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PC10, 0);    /* RTS0 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PC11, 0);    /* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_US1,
-               .end    = AT91SAM9261_BASE_US1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart1_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_uart1_device = {
-       .name           = "atmel_usart",
-       .id             = 2,
-       .dev            = {
-                               .dma_mask               = &uart1_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart1_data,
-       },
-       .resource       = uart1_resources,
-       .num_resources  = ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PC12, 1);            /* TXD1 */
-       at91_set_A_periph(AT91_PIN_PC13, 0);            /* RXD1 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PA12, 0);    /* RTS1 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PA13, 0);    /* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-       [0] = {
-               .start  = AT91SAM9261_BASE_US2,
-               .end    = AT91SAM9261_BASE_US2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart2_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9261_uart2_device = {
-       .name           = "atmel_usart",
-       .id             = 3,
-       .dev            = {
-                               .dma_mask               = &uart2_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart2_data,
-       },
-       .resource       = uart2_resources,
-       .num_resources  = ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PC15, 0);            /* RXD2 */
-       at91_set_A_periph(AT91_PIN_PC14, 1);            /* TXD2 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PA15, 0);    /* RTS2*/
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PA16, 0);    /* CTS2 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];  /* the UARTs to use */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-       struct platform_device *pdev;
-       struct atmel_uart_data *pdata;
-
-       switch (id) {
-               case 0:         /* DBGU */
-                       pdev = &at91sam9261_dbgu_device;
-                       configure_dbgu_pins();
-                       break;
-               case AT91SAM9261_ID_US0:
-                       pdev = &at91sam9261_uart0_device;
-                       configure_usart0_pins(pins);
-                       break;
-               case AT91SAM9261_ID_US1:
-                       pdev = &at91sam9261_uart1_device;
-                       configure_usart1_pins(pins);
-                       break;
-               case AT91SAM9261_ID_US2:
-                       pdev = &at91sam9261_uart2_device;
-                       configure_usart2_pins(pins);
-                       break;
-               default:
-                       return;
-       }
-       pdata = pdev->dev.platform_data;
-       pdata->num = portnr;            /* update to mapped ID */
-
-       if (portnr < ATMEL_MAX_UART)
-               at91_uarts[portnr] = pdev;
-}
-
-void __init at91_add_device_serial(void)
-{
-       int i;
-
-       for (i = 0; i < ATMEL_MAX_UART; i++) {
-               if (at91_uarts[i])
-                       platform_device_register(at91_uarts[i]);
-       }
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-       at91_add_device_rtt();
-       at91_add_device_watchdog();
-       at91_add_device_tc();
-       return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
index fbff228cc63ed5e54da7c97f79f140083845dc6d..e7ad148640837d45a9038e58cf7610e3cf35e2a6 100644 (file)
  *
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk/at91_pmc.h>
-
-#include <asm/proc-fns.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <asm/system_misc.h>
-#include <mach/at91sam9263.h>
 #include <mach/hardware.h>
 
-#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-#include "pm.h"
-
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_PIOA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_PIOB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioCDE_clk = {
-       .name           = "pioCDE_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_PIOCDE,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_US0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_US1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_US2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc0_clk = {
-       .name           = "mci0_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_MCI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc1_clk = {
-       .name           = "mci1_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_MCI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk can_clk = {
-       .name           = "can_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_CAN,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi_clk = {
-       .name           = "twi_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_TWI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-       .name           = "spi0_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_SPI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-       .name           = "spi1_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_SPI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc0_clk = {
-       .name           = "ssc0_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_SSC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc1_clk = {
-       .name           = "ssc1_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_SSC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ac97_clk = {
-       .name           = "ac97_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_AC97C,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tcb_clk = {
-       .name           = "tcb_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_TCB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pwm_clk = {
-       .name           = "pwm_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_PWMC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk macb_clk = {
-       .name           = "pclk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_EMAC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk dma_clk = {
-       .name           = "dma_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_DMA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twodge_clk = {
-       .name           = "2dge_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_2DGE,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udc_clk = {
-       .name           = "udc_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_UDP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk isi_clk = {
-       .name           = "isi_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_ISI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk lcdc_clk = {
-       .name           = "lcdc_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_LCDC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ohci_clk = {
-       .name           = "ohci_clk",
-       .pmc_mask       = 1 << AT91SAM9263_ID_UHP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioA_clk,
-       &pioB_clk,
-       &pioCDE_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &mmc0_clk,
-       &mmc1_clk,
-       &can_clk,
-       &twi_clk,
-       &spi0_clk,
-       &spi1_clk,
-       &ssc0_clk,
-       &ssc1_clk,
-       &ac97_clk,
-       &tcb_clk,
-       &pwm_clk,
-       &macb_clk,
-       &twodge_clk,
-       &udc_clk,
-       &isi_clk,
-       &lcdc_clk,
-       &dma_clk,
-       &ohci_clk,
-       // irq0 .. irq1
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       /* One additional fake clock for macb_hclk */
-       CLKDEV_CON_ID("hclk", &macb_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("hclk", "at91sam9263-lcdfb.0", &lcdc_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
-       /* fake hclk clock */
-       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
-       CLKDEV_CON_ID("pioA", &pioA_clk),
-       CLKDEV_CON_ID("pioB", &pioB_clk),
-       CLKDEV_CON_ID("pioC", &pioCDE_clk),
-       CLKDEV_CON_ID("pioD", &pioCDE_clk),
-       CLKDEV_CON_ID("pioE", &pioCDE_clk),
-       /* more usart lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
-       /* more tc lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb_clk),
-       CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioCDE_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCDE_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCDE_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffb8000.pwm", &pwm_clk),
-};
-
-static struct clk_lookup usart_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),
-};
-
-/*
- * The four programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-static struct clk pck2 = {
-       .name           = "pck2",
-       .pmc_mask       = AT91_PMC_PCK2,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 2,
-};
-static struct clk pck3 = {
-       .name           = "pck3",
-       .pmc_mask       = AT91_PMC_PCK3,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 3,
-};
-
-static void __init at91sam9263_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-       clkdev_add_table(usart_clocks_lookups,
-                        ARRAY_SIZE(usart_clocks_lookups));
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-       clk_register(&pck2);
-       clk_register(&pck3);
-}
-#else
-#define at91sam9263_register_clocks NULL
-#endif
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91sam9263_gpio[] __initdata = {
-       {
-               .id             = AT91SAM9263_ID_PIOA,
-               .regbase        = AT91SAM9263_BASE_PIOA,
-       }, {
-               .id             = AT91SAM9263_ID_PIOB,
-               .regbase        = AT91SAM9263_BASE_PIOB,
-       }, {
-               .id             = AT91SAM9263_ID_PIOCDE,
-               .regbase        = AT91SAM9263_BASE_PIOC,
-       }, {
-               .id             = AT91SAM9263_ID_PIOCDE,
-               .regbase        = AT91SAM9263_BASE_PIOD,
-       }, {
-               .id             = AT91SAM9263_ID_PIOCDE,
-               .regbase        = AT91SAM9263_BASE_PIOE,
-       }
-};
 
 /* --------------------------------------------------------------------
  *  AT91SAM9263 processor initialization
@@ -319,121 +26,15 @@ static void __init at91sam9263_map_io(void)
        at91_init_sram(1, AT91SAM9263_SRAM1_BASE, AT91SAM9263_SRAM1_SIZE);
 }
 
-static void __init at91sam9263_ioremap_registers(void)
-{
-       at91_ioremap_ramc(0, AT91SAM9263_BASE_SDRAMC0, 512);
-       at91_ioremap_ramc(1, AT91SAM9263_BASE_SDRAMC1, 512);
-       at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT);
-       at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0);
-       at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1);
-       at91_ioremap_matrix(AT91SAM9263_BASE_MATRIX);
-       at91_pm_set_standby(at91sam9_sdram_standby);
-}
-
 static void __init at91sam9263_initialize(void)
 {
        arm_pm_idle = at91sam9_idle;
 
        at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0);
        at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1);
-
-       /* Register GPIO subsystem */
-       at91_gpio_init(at91sam9263_gpio, 5);
-}
-
-static struct resource rstc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_RSTC,
-               .end    = AT91SAM9263_BASE_RSTC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9263_BASE_SDRAMC0,
-               .end    = AT91SAM9263_BASE_SDRAMC0 + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device rstc_device = {
-       .name           = "at91-sam9260-reset",
-       .resource       = rstc_resources,
-       .num_resources  = ARRAY_SIZE(rstc_resources),
-};
-
-static struct resource shdwc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_SHDWC,
-               .end    = AT91SAM9263_BASE_SHDWC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device shdwc_device = {
-       .name           = "at91-poweroff",
-       .resource       = shdwc_resources,
-       .num_resources  = ARRAY_SIZE(shdwc_resources),
-};
-
-static void __init at91sam9263_register_devices(void)
-{
-       platform_device_register(&rstc_device);
-       platform_device_register(&shdwc_device);
-}
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller (FIQ) */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A */
-       1,      /* Parallel IO Controller B */
-       1,      /* Parallel IO Controller C, D and E */
-       0,
-       0,
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       0,      /* Multimedia Card Interface 0 */
-       0,      /* Multimedia Card Interface 1 */
-       3,      /* CAN */
-       6,      /* Two-Wire Interface */
-       5,      /* Serial Peripheral Interface 0 */
-       5,      /* Serial Peripheral Interface 1 */
-       4,      /* Serial Synchronous Controller 0 */
-       4,      /* Serial Synchronous Controller 1 */
-       5,      /* AC97 Controller */
-       0,      /* Timer Counter 0, 1 and 2 */
-       0,      /* Pulse Width Modulation Controller */
-       3,      /* Ethernet */
-       0,
-       0,      /* 2D Graphic Engine */
-       2,      /* USB Device Port */
-       0,      /* Image Sensor Interface */
-       3,      /* LDC Controller */
-       0,      /* DMA Controller */
-       0,
-       2,      /* USB Host port */
-       0,      /* Advanced Interrupt Controller (IRQ0) */
-       0,      /* Advanced Interrupt Controller (IRQ1) */
-};
-
-static void __init at91sam9263_init_time(void)
-{
-       at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
 }
 
 AT91_SOC_START(at91sam9263)
        .map_io = at91sam9263_map_io,
-       .default_irq_priority = at91sam9263_default_irq_priority,
-       .extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1),
-       .ioremap_registers = at91sam9263_ioremap_registers,
-       .register_clocks = at91sam9263_register_clocks,
-       .register_devices = at91sam9263_register_devices,
        .init = at91sam9263_initialize,
-       .init_time = at91sam9263_init_time,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
deleted file mode 100644 (file)
index cef0e2f..0000000
+++ /dev/null
@@ -1,1538 +0,0 @@
-/*
- * arch/arm/mach-at91/at91sam9263_devices.c
- *
- *  Copyright (C) 2007 Atmel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/i2c-gpio.h>
-
-#include <linux/fb.h>
-#include <video/atmel_lcdc.h>
-
-#include <mach/at91sam9263.h>
-#include <mach/at91sam9263_matrix.h>
-#include <mach/at91_matrix.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/hardware.h>
-
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-/* --------------------------------------------------------------------
- *  USB Host
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_data;
-
-static struct resource usbh_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_UHP_BASE,
-               .end    = AT91SAM9263_UHP_BASE + SZ_1M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_usbh_device = {
-       .name           = "at91_ohci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &ohci_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &usbh_data,
-       },
-       .resource       = usbh_resources,
-       .num_resources  = ARRAY_SIZE(usbh_resources),
-};
-
-void __init at91_add_device_usbh(struct at91_usbh_data *data)
-{
-       int i;
-
-       if (!data)
-               return;
-
-       /* Enable VBus control for UHP ports */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->vbus_pin[i]))
-                       at91_set_gpio_output(data->vbus_pin[i],
-                                            data->vbus_pin_active_low[i]);
-       }
-
-       /* Enable overcurrent notification */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->overcurrent_pin[i]))
-                       at91_set_gpio_input(data->overcurrent_pin[i], 1);
-       }
-
-       usbh_data = *data;
-       platform_device_register(&at91_usbh_device);
-}
-#else
-void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_AT91) || defined(CONFIG_USB_AT91_MODULE)
-static struct at91_udc_data udc_data;
-
-static struct resource udc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_UDP,
-               .end    = AT91SAM9263_BASE_UDP + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_udc_device = {
-       .name           = "at91_udc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data          = &udc_data,
-       },
-       .resource       = udc_resources,
-       .num_resources  = ARRAY_SIZE(udc_resources),
-};
-
-void __init at91_add_device_udc(struct at91_udc_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->vbus_pin)) {
-               at91_set_gpio_input(data->vbus_pin, 0);
-               at91_set_deglitch(data->vbus_pin, 1);
-       }
-
-       /* Pullup pin is handled internally by USB device peripheral */
-
-       udc_data = *data;
-       platform_device_register(&at91_udc_device);
-}
-#else
-void __init at91_add_device_udc(struct at91_udc_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Ethernet
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct macb_platform_data eth_data;
-
-static struct resource eth_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_EMAC,
-               .end    = AT91SAM9263_BASE_EMAC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_eth_device = {
-       .name           = "macb",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &eth_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &eth_data,
-       },
-       .resource       = eth_resources,
-       .num_resources  = ARRAY_SIZE(eth_resources),
-};
-
-void __init at91_add_device_eth(struct macb_platform_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->phy_irq_pin)) {
-               at91_set_gpio_input(data->phy_irq_pin, 0);
-               at91_set_deglitch(data->phy_irq_pin, 1);
-       }
-
-       /* Pins used for MII and RMII */
-       at91_set_A_periph(AT91_PIN_PE21, 0);    /* ETXCK_EREFCK */
-       at91_set_B_periph(AT91_PIN_PC25, 0);    /* ERXDV */
-       at91_set_A_periph(AT91_PIN_PE25, 0);    /* ERX0 */
-       at91_set_A_periph(AT91_PIN_PE26, 0);    /* ERX1 */
-       at91_set_A_periph(AT91_PIN_PE27, 0);    /* ERXER */
-       at91_set_A_periph(AT91_PIN_PE28, 0);    /* ETXEN */
-       at91_set_A_periph(AT91_PIN_PE23, 0);    /* ETX0 */
-       at91_set_A_periph(AT91_PIN_PE24, 0);    /* ETX1 */
-       at91_set_A_periph(AT91_PIN_PE30, 0);    /* EMDIO */
-       at91_set_A_periph(AT91_PIN_PE29, 0);    /* EMDC */
-
-       if (!data->is_rmii) {
-               at91_set_A_periph(AT91_PIN_PE22, 0);    /* ECRS */
-               at91_set_B_periph(AT91_PIN_PC26, 0);    /* ECOL */
-               at91_set_B_periph(AT91_PIN_PC22, 0);    /* ERX2 */
-               at91_set_B_periph(AT91_PIN_PC23, 0);    /* ERX3 */
-               at91_set_B_periph(AT91_PIN_PC27, 0);    /* ERXCK */
-               at91_set_B_periph(AT91_PIN_PC20, 0);    /* ETX2 */
-               at91_set_B_periph(AT91_PIN_PC21, 0);    /* ETX3 */
-               at91_set_B_periph(AT91_PIN_PC24, 0);    /* ETXER */
-       }
-
-       eth_data = *data;
-       platform_device_register(&at91sam9263_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct macb_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_MCI0,
-               .end    = AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_mmc0_device = {
-       .name           = "atmel_mci",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc0_data,
-       },
-       .resource       = mmc0_resources,
-       .num_resources  = ARRAY_SIZE(mmc0_resources),
-};
-
-static struct resource mmc1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_MCI1,
-               .end    = AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_mmc1_device = {
-       .name           = "atmel_mci",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc1_data,
-       },
-       .resource       = mmc1_resources,
-       .num_resources  = ARRAY_SIZE(mmc1_resources),
-};
-
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-       unsigned int i;
-       unsigned int slot_count = 0;
-
-       if (!data)
-               return;
-
-       for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
-
-               if (!data->slot[i].bus_width)
-                       continue;
-
-               /* input/irq */
-               if (gpio_is_valid(data->slot[i].detect_pin)) {
-                       at91_set_gpio_input(data->slot[i].detect_pin,
-                                       1);
-                       at91_set_deglitch(data->slot[i].detect_pin,
-                                       1);
-               }
-               if (gpio_is_valid(data->slot[i].wp_pin))
-                       at91_set_gpio_input(data->slot[i].wp_pin, 1);
-
-               if (mmc_id == 0) {                              /* MCI0 */
-                       switch (i) {
-                       case 0:                                 /* slot A */
-                               /* CMD */
-                               at91_set_A_periph(AT91_PIN_PA1, 1);
-                               /* DAT0, maybe DAT1..DAT3 */
-                               at91_set_A_periph(AT91_PIN_PA0, 1);
-                               if (data->slot[i].bus_width == 4) {
-                                       at91_set_A_periph(AT91_PIN_PA3, 1);
-                                       at91_set_A_periph(AT91_PIN_PA4, 1);
-                                       at91_set_A_periph(AT91_PIN_PA5, 1);
-                               }
-                               slot_count++;
-                               break;
-                       case 1:                                 /* slot B */
-                               /* CMD */
-                               at91_set_A_periph(AT91_PIN_PA16, 1);
-                               /* DAT0, maybe DAT1..DAT3 */
-                               at91_set_A_periph(AT91_PIN_PA17, 1);
-                               if (data->slot[i].bus_width == 4) {
-                                       at91_set_A_periph(AT91_PIN_PA18, 1);
-                                       at91_set_A_periph(AT91_PIN_PA19, 1);
-                                       at91_set_A_periph(AT91_PIN_PA20, 1);
-                               }
-                               slot_count++;
-                               break;
-                       default:
-                               printk(KERN_ERR
-                                      "AT91: SD/MMC slot %d not available\n", i);
-                               break;
-                       }
-                       if (slot_count) {
-                               /* CLK */
-                               at91_set_A_periph(AT91_PIN_PA12, 0);
-
-                               mmc0_data = *data;
-                               platform_device_register(&at91sam9263_mmc0_device);
-                       }
-               } else if (mmc_id == 1) {                       /* MCI1 */
-                       switch (i) {
-                       case 0:                                 /* slot A */
-                               /* CMD */
-                               at91_set_A_periph(AT91_PIN_PA7, 1);
-                               /* DAT0, maybe DAT1..DAT3 */
-                               at91_set_A_periph(AT91_PIN_PA8, 1);
-                               if (data->slot[i].bus_width == 4) {
-                                       at91_set_A_periph(AT91_PIN_PA9, 1);
-                                       at91_set_A_periph(AT91_PIN_PA10, 1);
-                                       at91_set_A_periph(AT91_PIN_PA11, 1);
-                               }
-                               slot_count++;
-                               break;
-                       case 1:                                 /* slot B */
-                               /* CMD */
-                               at91_set_A_periph(AT91_PIN_PA21, 1);
-                               /* DAT0, maybe DAT1..DAT3 */
-                               at91_set_A_periph(AT91_PIN_PA22, 1);
-                               if (data->slot[i].bus_width == 4) {
-                                       at91_set_A_periph(AT91_PIN_PA23, 1);
-                                       at91_set_A_periph(AT91_PIN_PA24, 1);
-                                       at91_set_A_periph(AT91_PIN_PA25, 1);
-                               }
-                               slot_count++;
-                               break;
-                       default:
-                               printk(KERN_ERR
-                                      "AT91: SD/MMC slot %d not available\n", i);
-                               break;
-                       }
-                       if (slot_count) {
-                               /* CLK */
-                               at91_set_A_periph(AT91_PIN_PA6, 0);
-
-                               mmc1_data = *data;
-                               platform_device_register(&at91sam9263_mmc1_device);
-                       }
-               }
-       }
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  Compact Flash (PCMCIA or IDE)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_PATA_AT91) || defined(CONFIG_PATA_AT91_MODULE) || \
-       defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
-
-static struct at91_cf_data cf0_data;
-
-static struct resource cf0_resources[] = {
-       [0] = {
-               .start  = AT91_CHIPSELECT_4,
-               .end    = AT91_CHIPSELECT_4 + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
-       }
-};
-
-static struct platform_device cf0_device = {
-       .id             = 0,
-       .dev            = {
-                               .platform_data  = &cf0_data,
-       },
-       .resource       = cf0_resources,
-       .num_resources  = ARRAY_SIZE(cf0_resources),
-};
-
-static struct at91_cf_data cf1_data;
-
-static struct resource cf1_resources[] = {
-       [0] = {
-               .start  = AT91_CHIPSELECT_5,
-               .end    = AT91_CHIPSELECT_5 + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
-       }
-};
-
-static struct platform_device cf1_device = {
-       .id             = 1,
-       .dev            = {
-                               .platform_data  = &cf1_data,
-       },
-       .resource       = cf1_resources,
-       .num_resources  = ARRAY_SIZE(cf1_resources),
-};
-
-void __init at91_add_device_cf(struct at91_cf_data *data)
-{
-       unsigned long ebi0_csa;
-       struct platform_device *pdev;
-
-       if (!data)
-               return;
-
-       /*
-        * assign CS4 or CS5 to SMC with Compact Flash logic support,
-        * we assume SMC timings are configured by board code,
-        * except True IDE where timings are controlled by driver
-        */
-       ebi0_csa = at91_matrix_read(AT91_MATRIX_EBI0CSA);
-       switch (data->chipselect) {
-       case 4:
-               at91_set_A_periph(AT91_PIN_PD6, 0);  /* EBI0_NCS4/CFCS0 */
-               ebi0_csa |= AT91_MATRIX_EBI0_CS4A_SMC_CF1;
-               cf0_data = *data;
-               pdev = &cf0_device;
-               break;
-       case 5:
-               at91_set_A_periph(AT91_PIN_PD7, 0);  /* EBI0_NCS5/CFCS1 */
-               ebi0_csa |= AT91_MATRIX_EBI0_CS5A_SMC_CF2;
-               cf1_data = *data;
-               pdev = &cf1_device;
-               break;
-       default:
-               printk(KERN_ERR "AT91 CF: bad chip-select requested (%u)\n",
-                      data->chipselect);
-               return;
-       }
-       at91_matrix_write(AT91_MATRIX_EBI0CSA, ebi0_csa);
-
-       if (gpio_is_valid(data->det_pin)) {
-               at91_set_gpio_input(data->det_pin, 1);
-               at91_set_deglitch(data->det_pin, 1);
-       }
-
-       if (gpio_is_valid(data->irq_pin)) {
-               at91_set_gpio_input(data->irq_pin, 1);
-               at91_set_deglitch(data->irq_pin, 1);
-       }
-
-       if (gpio_is_valid(data->vcc_pin))
-               /* initially off */
-               at91_set_gpio_output(data->vcc_pin, 0);
-
-       /* enable EBI controlled pins */
-       at91_set_A_periph(AT91_PIN_PD5, 1);  /* NWAIT */
-       at91_set_A_periph(AT91_PIN_PD8, 0);  /* CFCE1 */
-       at91_set_A_periph(AT91_PIN_PD9, 0);  /* CFCE2 */
-       at91_set_A_periph(AT91_PIN_PD14, 0); /* CFNRW */
-
-       pdev->name = (data->flags & AT91_CF_TRUE_IDE) ? "pata_at91" : "at91_cf";
-       platform_device_register(pdev);
-}
-#else
-void __init at91_add_device_cf(struct at91_cf_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  NAND / SmartMedia
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE      AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-       [0] = {
-               .start  = NAND_BASE,
-               .end    = NAND_BASE + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9263_BASE_ECC0,
-               .end    = AT91SAM9263_BASE_ECC0 + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9263_nand_device = {
-       .name           = "atmel_nand",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &nand_data,
-       },
-       .resource       = nand_resources,
-       .num_resources  = ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-       unsigned long csa;
-
-       if (!data)
-               return;
-
-       csa = at91_matrix_read(AT91_MATRIX_EBI0CSA);
-       at91_matrix_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA);
-
-       /* enable pin */
-       if (gpio_is_valid(data->enable_pin))
-               at91_set_gpio_output(data->enable_pin, 1);
-
-       /* ready/busy pin */
-       if (gpio_is_valid(data->rdy_pin))
-               at91_set_gpio_input(data->rdy_pin, 1);
-
-       /* card detect pin */
-       if (gpio_is_valid(data->det_pin))
-               at91_set_gpio_input(data->det_pin, 1);
-
-       nand_data = *data;
-       platform_device_register(&at91sam9263_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  TWI (i2c)
- * -------------------------------------------------------------------- */
-
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-       .sda_pin                = AT91_PIN_PB4,
-       .sda_is_open_drain      = 1,
-       .scl_pin                = AT91_PIN_PB5,
-       .scl_is_open_drain      = 1,
-       .udelay                 = 2,            /* ~100 kHz */
-};
-
-static struct platform_device at91sam9263_twi_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 0,
-       .dev.platform_data      = &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       at91_set_GPIO_periph(AT91_PIN_PB4, 1);          /* TWD (SDA) */
-       at91_set_multi_drive(AT91_PIN_PB4, 1);
-
-       at91_set_GPIO_periph(AT91_PIN_PB5, 1);          /* TWCK (SCL) */
-       at91_set_multi_drive(AT91_PIN_PB5, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9263_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_TWI,
-               .end    = AT91SAM9263_BASE_TWI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_twi_device = {
-       .name           = "i2c-at91sam9260",
-       .id             = 0,
-       .resource       = twi_resources,
-       .num_resources  = ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       /* pins used for TWI interface */
-       at91_set_A_periph(AT91_PIN_PB4, 0);             /* TWD */
-       at91_set_multi_drive(AT91_PIN_PB4, 1);
-
-       at91_set_A_periph(AT91_PIN_PB5, 0);             /* TWCK */
-       at91_set_multi_drive(AT91_PIN_PB5, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9263_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_SPI0,
-               .end    = AT91SAM9263_BASE_SPI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_spi0_device = {
-       .name           = "atmel_spi",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi0_resources,
-       .num_resources  = ARRAY_SIZE(spi0_resources),
-};
-
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 };
-
-static struct resource spi1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_SPI1,
-               .end    = AT91SAM9263_BASE_SPI1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_spi1_device = {
-       .name           = "atmel_spi",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi1_resources,
-       .num_resources  = ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-       int i;
-       unsigned long cs_pin;
-       short enable_spi0 = 0;
-       short enable_spi1 = 0;
-
-       /* Choose SPI chip-selects */
-       for (i = 0; i < nr_devices; i++) {
-               if (devices[i].controller_data)
-                       cs_pin = (unsigned long) devices[i].controller_data;
-               else if (devices[i].bus_num == 0)
-                       cs_pin = spi0_standard_cs[devices[i].chip_select];
-               else
-                       cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-               if (!gpio_is_valid(cs_pin))
-                       continue;
-
-               if (devices[i].bus_num == 0)
-                       enable_spi0 = 1;
-               else
-                       enable_spi1 = 1;
-
-               /* enable chip-select pin */
-               at91_set_gpio_output(cs_pin, 1);
-
-               /* pass chip-select pin to driver */
-               devices[i].controller_data = (void *) cs_pin;
-       }
-
-       spi_register_board_info(devices, nr_devices);
-
-       /* Configure SPI bus(es) */
-       if (enable_spi0) {
-               at91_set_B_periph(AT91_PIN_PA0, 0);     /* SPI0_MISO */
-               at91_set_B_periph(AT91_PIN_PA1, 0);     /* SPI0_MOSI */
-               at91_set_B_periph(AT91_PIN_PA2, 0);     /* SPI0_SPCK */
-
-               platform_device_register(&at91sam9263_spi0_device);
-       }
-       if (enable_spi1) {
-               at91_set_A_periph(AT91_PIN_PB12, 0);    /* SPI1_MISO */
-               at91_set_A_periph(AT91_PIN_PB13, 0);    /* SPI1_MOSI */
-               at91_set_A_periph(AT91_PIN_PB14, 0);    /* SPI1_SPCK */
-
-               platform_device_register(&at91sam9263_spi1_device);
-       }
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  AC97
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
-static u64 ac97_dmamask = DMA_BIT_MASK(32);
-static struct ac97c_platform_data ac97_data;
-
-static struct resource ac97_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_AC97C,
-               .end    = AT91SAM9263_BASE_AC97C + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_ac97_device = {
-       .name           = "atmel_ac97c",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &ac97_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &ac97_data,
-       },
-       .resource       = ac97_resources,
-       .num_resources  = ARRAY_SIZE(ac97_resources),
-};
-
-void __init at91_add_device_ac97(struct ac97c_platform_data *data)
-{
-       if (!data)
-               return;
-
-       at91_set_A_periph(AT91_PIN_PB0, 0);     /* AC97FS */
-       at91_set_A_periph(AT91_PIN_PB1, 0);     /* AC97CK */
-       at91_set_A_periph(AT91_PIN_PB2, 0);     /* AC97TX */
-       at91_set_A_periph(AT91_PIN_PB3, 0);     /* AC97RX */
-
-       /* reset */
-       if (gpio_is_valid(data->reset_pin))
-               at91_set_gpio_output(data->reset_pin, 0);
-
-       ac97_data = *data;
-       platform_device_register(&at91sam9263_ac97_device);
-}
-#else
-void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  CAN Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_CAN_AT91) || defined(CONFIG_CAN_AT91_MODULE)
-static struct resource can_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_CAN,
-               .end    = AT91SAM9263_BASE_CAN + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_can_device = {
-       .name           = "at91_can",
-       .id             = -1,
-       .resource       = can_resources,
-       .num_resources  = ARRAY_SIZE(can_resources),
-};
-
-void __init at91_add_device_can(struct at91_can_data *data)
-{
-       at91_set_A_periph(AT91_PIN_PA13, 0);    /* CANTX */
-       at91_set_A_periph(AT91_PIN_PA14, 0);    /* CANRX */
-       at91sam9263_can_device.dev.platform_data = data;
-
-       platform_device_register(&at91sam9263_can_device);
-}
-#else
-void __init at91_add_device_can(struct at91_can_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  LCD Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_pdata lcdc_data;
-
-static struct resource lcdc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_LCDC_BASE,
-               .end    = AT91SAM9263_LCDC_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_lcdc_device = {
-       .name           = "at91sam9263-lcdfb",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &lcdc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &lcdc_data,
-       },
-       .resource       = lcdc_resources,
-       .num_resources  = ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
-{
-       if (!data)
-               return;
-
-       at91_set_A_periph(AT91_PIN_PC1, 0);     /* LCDHSYNC */
-       at91_set_A_periph(AT91_PIN_PC2, 0);     /* LCDDOTCK */
-       at91_set_A_periph(AT91_PIN_PC3, 0);     /* LCDDEN */
-       at91_set_B_periph(AT91_PIN_PB9, 0);     /* LCDCC */
-       at91_set_A_periph(AT91_PIN_PC6, 0);     /* LCDD2 */
-       at91_set_A_periph(AT91_PIN_PC7, 0);     /* LCDD3 */
-       at91_set_A_periph(AT91_PIN_PC8, 0);     /* LCDD4 */
-       at91_set_A_periph(AT91_PIN_PC9, 0);     /* LCDD5 */
-       at91_set_A_periph(AT91_PIN_PC10, 0);    /* LCDD6 */
-       at91_set_A_periph(AT91_PIN_PC11, 0);    /* LCDD7 */
-       at91_set_A_periph(AT91_PIN_PC14, 0);    /* LCDD10 */
-       at91_set_A_periph(AT91_PIN_PC15, 0);    /* LCDD11 */
-       at91_set_A_periph(AT91_PIN_PC16, 0);    /* LCDD12 */
-       at91_set_B_periph(AT91_PIN_PC12, 0);    /* LCDD13 */
-       at91_set_A_periph(AT91_PIN_PC18, 0);    /* LCDD14 */
-       at91_set_A_periph(AT91_PIN_PC19, 0);    /* LCDD15 */
-       at91_set_A_periph(AT91_PIN_PC22, 0);    /* LCDD18 */
-       at91_set_A_periph(AT91_PIN_PC23, 0);    /* LCDD19 */
-       at91_set_A_periph(AT91_PIN_PC24, 0);    /* LCDD20 */
-       at91_set_B_periph(AT91_PIN_PC17, 0);    /* LCDD21 */
-       at91_set_A_periph(AT91_PIN_PC26, 0);    /* LCDD22 */
-       at91_set_A_periph(AT91_PIN_PC27, 0);    /* LCDD23 */
-
-       lcdc_data = *data;
-       platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Image Sensor Interface
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_VIDEO_AT91_ISI) || defined(CONFIG_VIDEO_AT91_ISI_MODULE)
-
-struct resource isi_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_ISI,
-               .end    = AT91SAM9263_BASE_ISI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_isi_device = {
-       .name           = "at91_isi",
-       .id             = -1,
-       .resource       = isi_resources,
-       .num_resources  = ARRAY_SIZE(isi_resources),
-};
-
-void __init at91_add_device_isi(struct isi_platform_data *data,
-               bool use_pck_as_mck)
-{
-       at91_set_A_periph(AT91_PIN_PE0, 0);     /* ISI_D0 */
-       at91_set_A_periph(AT91_PIN_PE1, 0);     /* ISI_D1 */
-       at91_set_A_periph(AT91_PIN_PE2, 0);     /* ISI_D2 */
-       at91_set_A_periph(AT91_PIN_PE3, 0);     /* ISI_D3 */
-       at91_set_A_periph(AT91_PIN_PE4, 0);     /* ISI_D4 */
-       at91_set_A_periph(AT91_PIN_PE5, 0);     /* ISI_D5 */
-       at91_set_A_periph(AT91_PIN_PE6, 0);     /* ISI_D6 */
-       at91_set_A_periph(AT91_PIN_PE7, 0);     /* ISI_D7 */
-       at91_set_A_periph(AT91_PIN_PE8, 0);     /* ISI_PCK */
-       at91_set_A_periph(AT91_PIN_PE9, 0);     /* ISI_HSYNC */
-       at91_set_A_periph(AT91_PIN_PE10, 0);    /* ISI_VSYNC */
-       at91_set_B_periph(AT91_PIN_PE12, 0);    /* ISI_PD8 */
-       at91_set_B_periph(AT91_PIN_PE13, 0);    /* ISI_PD9 */
-       at91_set_B_periph(AT91_PIN_PE14, 0);    /* ISI_PD10 */
-       at91_set_B_periph(AT91_PIN_PE15, 0);    /* ISI_PD11 */
-
-       if (use_pck_as_mck) {
-               at91_set_B_periph(AT91_PIN_PE11, 0);    /* ISI_MCK (PCK3) */
-
-               /* TODO: register the PCK for ISI_MCK and set its parent */
-       }
-}
-#else
-void __init at91_add_device_isi(struct isi_platform_data *data,
-               bool use_pck_as_mck) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Timer/Counter block
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_TCB0,
-               .end    = AT91SAM9263_BASE_TCB0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_tcb_device = {
-       .name           = "atmel_tcb",
-       .id             = 0,
-       .resource       = tcb_resources,
-       .num_resources  = ARRAY_SIZE(tcb_resources),
-};
-
-#if defined(CONFIG_OF)
-static struct of_device_id tcb_ids[] = {
-       { .compatible = "atmel,at91rm9200-tcb" },
-       { /*sentinel*/ }
-};
-#endif
-
-static void __init at91_add_device_tc(void)
-{
-#if defined(CONFIG_OF)
-       struct device_node *np;
-
-       np = of_find_matching_node(NULL, tcb_ids);
-       if (np) {
-               of_node_put(np);
-               return;
-       }
-#endif
-
-       platform_device_register(&at91sam9263_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
-/* --------------------------------------------------------------------
- *  RTT
- * -------------------------------------------------------------------- */
-
-static struct resource rtt0_resources[] = {
-       {
-               .start  = AT91SAM9263_BASE_RTT0,
-               .end    = AT91SAM9263_BASE_RTT0 + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static struct platform_device at91sam9263_rtt0_device = {
-       .name           = "at91_rtt",
-       .id             = 0,
-       .resource       = rtt0_resources,
-};
-
-static struct resource rtt1_resources[] = {
-       {
-               .start  = AT91SAM9263_BASE_RTT1,
-               .end    = AT91SAM9263_BASE_RTT1 + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static struct platform_device at91sam9263_rtt1_device = {
-       .name           = "at91_rtt",
-       .id             = 1,
-       .resource       = rtt1_resources,
-};
-
-#if IS_ENABLED(CONFIG_RTC_DRV_AT91SAM9)
-static void __init at91_add_device_rtt_rtc(void)
-{
-       struct platform_device *pdev;
-       struct resource *r;
-
-       switch (CONFIG_RTC_DRV_AT91SAM9_RTT) {
-       case 0:
-               /*
-                * The second resource is needed only for the chosen RTT:
-                * GPBR will serve as the storage for RTC time offset
-                */
-               at91sam9263_rtt0_device.num_resources = 3;
-               at91sam9263_rtt1_device.num_resources = 1;
-               pdev = &at91sam9263_rtt0_device;
-               r = rtt0_resources;
-               break;
-       case 1:
-               at91sam9263_rtt0_device.num_resources = 1;
-               at91sam9263_rtt1_device.num_resources = 3;
-               pdev = &at91sam9263_rtt1_device;
-               r = rtt1_resources;
-               break;
-       default:
-               pr_err("at91sam9263: only supports 2 RTT (%d)\n",
-                      CONFIG_RTC_DRV_AT91SAM9_RTT);
-               return;
-       }
-
-       pdev->name = "rtc-at91sam9";
-       r[1].start = AT91SAM9263_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
-       r[1].end = r[1].start + 3;
-       r[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
-       r[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
-}
-#else
-static void __init at91_add_device_rtt_rtc(void)
-{
-       /* Only one resource is needed: RTT not used as RTC */
-       at91sam9263_rtt0_device.num_resources = 1;
-       at91sam9263_rtt1_device.num_resources = 1;
-}
-#endif
-
-static void __init at91_add_device_rtt(void)
-{
-       at91_add_device_rtt_rtc();
-       platform_device_register(&at91sam9263_rtt0_device);
-       platform_device_register(&at91sam9263_rtt1_device);
-}
-
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct resource wdt_resources[] = {
-       {
-               .start  = AT91SAM9263_BASE_WDT,
-               .end    = AT91SAM9263_BASE_WDT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9263_wdt_device = {
-       .name           = "at91_wdt",
-       .id             = -1,
-       .resource       = wdt_resources,
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-       platform_device_register(&at91sam9263_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  PWM
- * --------------------------------------------------------------------*/
-
-#if IS_ENABLED(CONFIG_PWM_ATMEL)
-static struct resource pwm_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_PWMC,
-               .end    = AT91SAM9263_BASE_PWMC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_pwm0_device = {
-       .name   = "at91sam9rl-pwm",
-       .id     = -1,
-       .resource       = pwm_resources,
-       .num_resources  = ARRAY_SIZE(pwm_resources),
-};
-
-void __init at91_add_device_pwm(u32 mask)
-{
-       if (mask & (1 << AT91_PWM0))
-               at91_set_B_periph(AT91_PIN_PB7, 1);     /* enable PWM0 */
-
-       if (mask & (1 << AT91_PWM1))
-               at91_set_B_periph(AT91_PIN_PB8, 1);     /* enable PWM1 */
-
-       if (mask & (1 << AT91_PWM2))
-               at91_set_B_periph(AT91_PIN_PC29, 1);    /* enable PWM2 */
-
-       if (mask & (1 << AT91_PWM3))
-               at91_set_B_periph(AT91_PIN_PB29, 1);    /* enable PWM3 */
-
-       platform_device_register(&at91sam9263_pwm0_device);
-}
-#else
-void __init at91_add_device_pwm(u32 mask) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SSC -- Synchronous Serial Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_SSC0,
-               .end    = AT91SAM9263_BASE_SSC0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_ssc0_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 0,
-       .dev    = {
-               .dma_mask               = &ssc0_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc0_resources,
-       .num_resources  = ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_B_periph(AT91_PIN_PB0, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_B_periph(AT91_PIN_PB1, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_B_periph(AT91_PIN_PB2, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_B_periph(AT91_PIN_PB3, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_B_periph(AT91_PIN_PB4, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_B_periph(AT91_PIN_PB5, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_SSC1,
-               .end    = AT91SAM9263_BASE_SSC1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9263_ssc1_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 1,
-       .dev    = {
-               .dma_mask               = &ssc1_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc1_resources,
-       .num_resources  = ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PB6, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PB7, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PB8, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PB9, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PB10, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PB11, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-       struct platform_device *pdev;
-
-       /*
-        * NOTE: caller is responsible for passing information matching
-        * "pins" to whatever will be using each particular controller.
-        */
-       switch (id) {
-       case AT91SAM9263_ID_SSC0:
-               pdev = &at91sam9263_ssc0_device;
-               configure_ssc0_pins(pins);
-               break;
-       case AT91SAM9263_ID_SSC1:
-               pdev = &at91sam9263_ssc1_device;
-               configure_ssc1_pins(pins);
-               break;
-       default:
-               return;
-       }
-
-       platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SERIAL_ATMEL)
-
-static struct resource dbgu_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_DBGU,
-               .end    = AT91SAM9263_BASE_DBGU + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data dbgu_data = {
-       .use_dma_tx     = 0,
-       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_dbgu_device = {
-       .name           = "atmel_usart",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &dbgu_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &dbgu_data,
-       },
-       .resource       = dbgu_resources,
-       .num_resources  = ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-       at91_set_A_periph(AT91_PIN_PC30, 0);            /* DRXD */
-       at91_set_A_periph(AT91_PIN_PC31, 1);            /* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_US0,
-               .end    = AT91SAM9263_BASE_US0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart0_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_uart0_device = {
-       .name           = "atmel_usart",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &uart0_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart0_data,
-       },
-       .resource       = uart0_resources,
-       .num_resources  = ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PA26, 1);            /* TXD0 */
-       at91_set_A_periph(AT91_PIN_PA27, 0);            /* RXD0 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PA28, 0);    /* RTS0 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PA29, 0);    /* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_US1,
-               .end    = AT91SAM9263_BASE_US1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart1_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_uart1_device = {
-       .name           = "atmel_usart",
-       .id             = 2,
-       .dev            = {
-                               .dma_mask               = &uart1_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart1_data,
-       },
-       .resource       = uart1_resources,
-       .num_resources  = ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PD0, 1);             /* TXD1 */
-       at91_set_A_periph(AT91_PIN_PD1, 0);             /* RXD1 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PD7, 0);     /* RTS1 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PD8, 0);     /* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-       [0] = {
-               .start  = AT91SAM9263_BASE_US2,
-               .end    = AT91SAM9263_BASE_US2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart2_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9263_uart2_device = {
-       .name           = "atmel_usart",
-       .id             = 3,
-       .dev            = {
-                               .dma_mask               = &uart2_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart2_data,
-       },
-       .resource       = uart2_resources,
-       .num_resources  = ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PD2, 1);             /* TXD2 */
-       at91_set_A_periph(AT91_PIN_PD3, 0);             /* RXD2 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PD5, 0);     /* RTS2 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PD6, 0);     /* CTS2 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];  /* the UARTs to use */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-       struct platform_device *pdev;
-       struct atmel_uart_data *pdata;
-
-       switch (id) {
-               case 0:         /* DBGU */
-                       pdev = &at91sam9263_dbgu_device;
-                       configure_dbgu_pins();
-                       break;
-               case AT91SAM9263_ID_US0:
-                       pdev = &at91sam9263_uart0_device;
-                       configure_usart0_pins(pins);
-                       break;
-               case AT91SAM9263_ID_US1:
-                       pdev = &at91sam9263_uart1_device;
-                       configure_usart1_pins(pins);
-                       break;
-               case AT91SAM9263_ID_US2:
-                       pdev = &at91sam9263_uart2_device;
-                       configure_usart2_pins(pins);
-                       break;
-               default:
-                       return;
-       }
-       pdata = pdev->dev.platform_data;
-       pdata->num = portnr;            /* update to mapped ID */
-
-       if (portnr < ATMEL_MAX_UART)
-               at91_uarts[portnr] = pdev;
-}
-
-void __init at91_add_device_serial(void)
-{
-       int i;
-
-       for (i = 0; i < ATMEL_MAX_UART; i++) {
-               if (at91_uarts[i])
-                       platform_device_register(at91_uarts[i]);
-       }
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-       if (of_have_populated_dt())
-               return 0;
-
-       at91_add_device_rtt();
-       at91_add_device_watchdog();
-       at91_add_device_tc();
-       return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
index 405427ec05f8a923f153fa9d384071fd8f3ef72a..b6117bea9a6f2a4333028bff3000080b39380645 100644 (file)
  *
  */
 
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk/at91_pmc.h>
-#include <linux/platform_device.h>
-
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <asm/system_misc.h>
-#include <mach/at91sam9g45.h>
-#include <mach/cpu.h>
+#include <asm/irq.h>
 #include <mach/hardware.h>
 
-#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-#include "pm.h"
-
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_PIOA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_PIOB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-       .name           = "pioC_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_PIOC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioDE_clk = {
-       .name           = "pioDE_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_PIODE,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk trng_clk = {
-       .name           = "trng_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_TRNG,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_US0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_US1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_US2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_US3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc0_clk = {
-       .name           = "mci0_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_MCI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi0_clk = {
-       .name           = "twi0_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_TWI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi1_clk = {
-       .name           = "twi1_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_TWI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-       .name           = "spi0_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_SPI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-       .name           = "spi1_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_SPI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc0_clk = {
-       .name           = "ssc0_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_SSC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc1_clk = {
-       .name           = "ssc1_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_SSC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tcb0_clk = {
-       .name           = "tcb0_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_TCB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pwm_clk = {
-       .name           = "pwm_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_PWMC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tsc_clk = {
-       .name           = "tsc_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_TSC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk dma_clk = {
-       .name           = "dma_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_DMA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uhphs_clk = {
-       .name           = "uhphs_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_UHPHS,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk lcdc_clk = {
-       .name           = "lcdc_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_LCDC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ac97_clk = {
-       .name           = "ac97_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_AC97C,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk macb_clk = {
-       .name           = "pclk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_EMAC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk isi_clk = {
-       .name           = "isi_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_ISI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udphs_clk = {
-       .name           = "udphs_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_UDPHS,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc1_clk = {
-       .name           = "mci1_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_MCI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-/* Video decoder clock - Only for sam9m10/sam9m11 */
-static struct clk vdec_clk = {
-       .name           = "vdec_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_VDEC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk adc_op_clk = {
-       .name           = "adc_op_clk",
-       .type           = CLK_TYPE_PERIPHERAL,
-       .rate_hz        = 300000,
-};
-
-/* AES/TDES/SHA clock - Only for sam9m11/sam9g56 */
-static struct clk aestdessha_clk = {
-       .name           = "aestdessha_clk",
-       .pmc_mask       = 1 << AT91SAM9G45_ID_AESTDESSHA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioA_clk,
-       &pioB_clk,
-       &pioC_clk,
-       &pioDE_clk,
-       &trng_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &usart3_clk,
-       &mmc0_clk,
-       &twi0_clk,
-       &twi1_clk,
-       &spi0_clk,
-       &spi1_clk,
-       &ssc0_clk,
-       &ssc1_clk,
-       &tcb0_clk,
-       &pwm_clk,
-       &tsc_clk,
-       &dma_clk,
-       &uhphs_clk,
-       &lcdc_clk,
-       &ac97_clk,
-       &macb_clk,
-       &isi_clk,
-       &udphs_clk,
-       &mmc1_clk,
-       &adc_op_clk,
-       &aestdessha_clk,
-       // irq0
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       /* One additional fake clock for macb_hclk */
-       CLKDEV_CON_ID("hclk", &macb_clk),
-       /* One additional fake clock for ohci */
-       CLKDEV_CON_ID("ohci_clk", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("hclk", "at91sam9g45-lcdfb.0", &lcdc_clk),
-       CLKDEV_CON_DEV_ID("hclk", "at91sam9g45es-lcdfb.0", &lcdc_clk),
-       CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
-       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffa0000.ssc", &ssc1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
-       CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
-       CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
-       CLKDEV_CON_DEV_ID(NULL, "atmel_aes", &aestdessha_clk),
-       CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
-       /* more usart lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "ffffee00.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "fff8c000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "fff90000.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "fff94000.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "fff98000.serial", &usart3_clk),
-       /* more tc lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("t0_clk", "fff7c000.timer", &tcb0_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
-       CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
-       CLKDEV_CON_DEV_ID("hclk", "600000.gadget", &utmi_clk),
-       CLKDEV_CON_DEV_ID("pclk", "600000.gadget", &udphs_clk),
-       /* fake hclk clock */
-       CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff200.gpio", &pioA_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioC_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioDE_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioDE_clk),
-
-       CLKDEV_CON_ID("pioA", &pioA_clk),
-       CLKDEV_CON_ID("pioB", &pioB_clk),
-       CLKDEV_CON_ID("pioC", &pioC_clk),
-       CLKDEV_CON_ID("pioD", &pioDE_clk),
-       CLKDEV_CON_ID("pioE", &pioDE_clk),
-       /* Fake adc clock */
-       CLKDEV_CON_ID("adc_clk", &tsc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffb8000.pwm", &pwm_clk),
-};
-
-static struct clk_lookup usart_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.4", &usart3_clk),
-};
-
-/*
- * The two programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-
-static void __init at91sam9g45_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-       clkdev_add_table(usart_clocks_lookups,
-                        ARRAY_SIZE(usart_clocks_lookups));
-
-       if (cpu_is_at91sam9m10() || cpu_is_at91sam9m11())
-               clk_register(&vdec_clk);
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-}
-#else
-#define at91sam9g45_register_clocks NULL
-#endif
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91sam9g45_gpio[] __initdata = {
-       {
-               .id             = AT91SAM9G45_ID_PIOA,
-               .regbase        = AT91SAM9G45_BASE_PIOA,
-       }, {
-               .id             = AT91SAM9G45_ID_PIOB,
-               .regbase        = AT91SAM9G45_BASE_PIOB,
-       }, {
-               .id             = AT91SAM9G45_ID_PIOC,
-               .regbase        = AT91SAM9G45_BASE_PIOC,
-       }, {
-               .id             = AT91SAM9G45_ID_PIODE,
-               .regbase        = AT91SAM9G45_BASE_PIOD,
-       }, {
-               .id             = AT91SAM9G45_ID_PIODE,
-               .regbase        = AT91SAM9G45_BASE_PIOE,
-       }
-};
 
 /* --------------------------------------------------------------------
  *  AT91SAM9G45 processor initialization
@@ -370,125 +26,15 @@ static void __init at91sam9g45_map_io(void)
        at91_init_sram(0, AT91SAM9G45_SRAM_BASE, AT91SAM9G45_SRAM_SIZE);
 }
 
-static void __init at91sam9g45_ioremap_registers(void)
-{
-       at91_ioremap_ramc(0, AT91SAM9G45_BASE_DDRSDRC1, 512);
-       at91_ioremap_ramc(1, AT91SAM9G45_BASE_DDRSDRC0, 512);
-       at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
-       at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC);
-       at91_ioremap_matrix(AT91SAM9G45_BASE_MATRIX);
-       at91_pm_set_standby(at91_ddr_standby);
-}
-
 static void __init at91sam9g45_initialize(void)
 {
        arm_pm_idle = at91sam9_idle;
 
        at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC);
        at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT);
-
-       /* Register GPIO subsystem */
-       at91_gpio_init(at91sam9g45_gpio, 5);
-}
-
-static struct resource rstc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_RSTC,
-               .end    = AT91SAM9G45_BASE_RSTC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9G45_BASE_DDRSDRC1,
-               .end    = AT91SAM9G45_BASE_DDRSDRC1 + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start  = AT91SAM9G45_BASE_DDRSDRC0,
-               .end    = AT91SAM9G45_BASE_DDRSDRC0 + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device rstc_device = {
-       .name           = "at91-sam9g45-reset",
-       .resource       = rstc_resources,
-       .num_resources  = ARRAY_SIZE(rstc_resources),
-};
-
-static struct resource shdwc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_SHDWC,
-               .end    = AT91SAM9G45_BASE_SHDWC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device shdwc_device = {
-       .name           = "at91-poweroff",
-       .resource       = shdwc_resources,
-       .num_resources  = ARRAY_SIZE(shdwc_resources),
-};
-
-static void __init at91sam9g45_register_devices(void)
-{
-       platform_device_register(&rstc_device);
-       platform_device_register(&shdwc_device);
-}
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9g45_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller (FIQ) */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A */
-       1,      /* Parallel IO Controller B */
-       1,      /* Parallel IO Controller C */
-       1,      /* Parallel IO Controller D and E */
-       0,
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       5,      /* USART 3 */
-       0,      /* Multimedia Card Interface 0 */
-       6,      /* Two-Wire Interface 0 */
-       6,      /* Two-Wire Interface 1 */
-       5,      /* Serial Peripheral Interface 0 */
-       5,      /* Serial Peripheral Interface 1 */
-       4,      /* Serial Synchronous Controller 0 */
-       4,      /* Serial Synchronous Controller 1 */
-       0,      /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-       0,      /* Pulse Width Modulation Controller */
-       0,      /* Touch Screen Controller */
-       0,      /* DMA Controller */
-       2,      /* USB Host High Speed port */
-       3,      /* LDC Controller */
-       5,      /* AC97 Controller */
-       3,      /* Ethernet */
-       0,      /* Image Sensor Interface */
-       2,      /* USB Device High speed port */
-       0,      /* AESTDESSHA Crypto HW Accelerators */
-       0,      /* Multimedia Card Interface 1 */
-       0,
-       0,      /* Advanced Interrupt Controller (IRQ0) */
-};
-
-static void __init at91sam9g45_init_time(void)
-{
-       at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
 }
 
 AT91_SOC_START(at91sam9g45)
        .map_io = at91sam9g45_map_io,
-       .default_irq_priority = at91sam9g45_default_irq_priority,
-       .extern_irq = (1 << AT91SAM9G45_ID_IRQ0),
-       .ioremap_registers = at91sam9g45_ioremap_registers,
-       .register_clocks = at91sam9g45_register_clocks,
-       .register_devices = at91sam9g45_register_devices,
        .init = at91sam9g45_initialize,
-       .init_time = at91sam9g45_init_time,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
deleted file mode 100644 (file)
index 21ab782..0000000
+++ /dev/null
@@ -1,1915 +0,0 @@
-/*
- *  On-Chip devices setup code for the AT91SAM9G45 family
- *
- *  Copyright (C) 2009 Atmel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/i2c-gpio.h>
-#include <linux/atmel-mci.h>
-#include <linux/platform_data/crypto-atmel.h>
-
-#include <linux/platform_data/at91_adc.h>
-
-#include <linux/fb.h>
-#include <video/atmel_lcdc.h>
-
-#include <mach/at91sam9g45.h>
-#include <mach/at91sam9g45_matrix.h>
-#include <mach/at91_matrix.h>
-#include <mach/at91sam9_smc.h>
-#include <linux/platform_data/dma-atmel.h>
-#include <mach/atmel-mci.h>
-#include <mach/hardware.h>
-
-#include <media/atmel-isi.h>
-
-#include "board.h"
-#include "generic.h"
-#include "clock.h"
-#include "gpio.h"
-
-
-/* --------------------------------------------------------------------
- *  HDMAC - AHB DMA Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
-static u64 hdmac_dmamask = DMA_BIT_MASK(32);
-
-static struct resource hdmac_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_DMA,
-               .end    = AT91SAM9G45_BASE_DMA + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at_hdmac_device = {
-       .name           = "at91sam9g45_dma",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &hdmac_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = hdmac_resources,
-       .num_resources  = ARRAY_SIZE(hdmac_resources),
-};
-
-void __init at91_add_device_hdmac(void)
-{
-       platform_device_register(&at_hdmac_device);
-}
-#else
-void __init at91_add_device_hdmac(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Host (OHCI)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_ohci_data;
-
-static struct resource usbh_ohci_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_OHCI_BASE,
-               .end    = AT91SAM9G45_OHCI_BASE + SZ_1M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_usbh_ohci_device = {
-       .name           = "at91_ohci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &ohci_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &usbh_ohci_data,
-       },
-       .resource       = usbh_ohci_resources,
-       .num_resources  = ARRAY_SIZE(usbh_ohci_resources),
-};
-
-void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
-{
-       int i;
-
-       if (!data)
-               return;
-
-       /* Enable VBus control for UHP ports */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->vbus_pin[i]))
-                       at91_set_gpio_output(data->vbus_pin[i],
-                                            data->vbus_pin_active_low[i]);
-       }
-
-       /* Enable overcurrent notification */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->overcurrent_pin[i]))
-                       at91_set_gpio_input(data->overcurrent_pin[i], 1);
-       }
-
-       usbh_ohci_data = *data;
-       platform_device_register(&at91_usbh_ohci_device);
-}
-#else
-void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB Host HS (EHCI)
- *  Needs an OHCI host for low and full speed management
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
-static u64 ehci_dmamask = DMA_BIT_MASK(32);
-static struct at91_usbh_data usbh_ehci_data;
-
-static struct resource usbh_ehci_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_EHCI_BASE,
-               .end    = AT91SAM9G45_EHCI_BASE + SZ_1M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_usbh_ehci_device = {
-       .name           = "atmel-ehci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &ehci_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &usbh_ehci_data,
-       },
-       .resource       = usbh_ehci_resources,
-       .num_resources  = ARRAY_SIZE(usbh_ehci_resources),
-};
-
-void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data)
-{
-       int i;
-
-       if (!data)
-               return;
-
-       /* Enable VBus control for UHP ports */
-       for (i = 0; i < data->ports; i++) {
-               if (gpio_is_valid(data->vbus_pin[i]))
-                       at91_set_gpio_output(data->vbus_pin[i],
-                                            data->vbus_pin_active_low[i]);
-       }
-
-       usbh_ehci_data = *data;
-       platform_device_register(&at91_usbh_ehci_device);
-}
-#else
-void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  USB HS Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
-static struct resource usba_udc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_UDPHS_FIFO,
-               .end    = AT91SAM9G45_UDPHS_FIFO + SZ_512K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9G45_BASE_UDPHS,
-               .end    = AT91SAM9G45_BASE_UDPHS + SZ_1K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-#define EP(nam, idx, maxpkt, maxbk, dma, isoc)                 \
-       [idx] = {                                               \
-               .name           = nam,                          \
-               .index          = idx,                          \
-               .fifo_size      = maxpkt,                       \
-               .nr_banks       = maxbk,                        \
-               .can_dma        = dma,                          \
-               .can_isoc       = isoc,                         \
-       }
-
-static struct usba_ep_data usba_udc_ep[] __initdata = {
-       EP("ep0", 0, 64, 1, 0, 0),
-       EP("ep1", 1, 1024, 2, 1, 1),
-       EP("ep2", 2, 1024, 2, 1, 1),
-       EP("ep3", 3, 1024, 3, 1, 0),
-       EP("ep4", 4, 1024, 3, 1, 0),
-       EP("ep5", 5, 1024, 3, 1, 1),
-       EP("ep6", 6, 1024, 3, 1, 1),
-};
-
-#undef EP
-
-/*
- * pdata doesn't have room for any endpoints, so we need to
- * append room for the ones we need right after it.
- */
-static struct {
-       struct usba_platform_data pdata;
-       struct usba_ep_data ep[7];
-} usba_udc_data;
-
-static struct platform_device at91_usba_udc_device = {
-       .name           = "atmel_usba_udc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &usba_udc_data.pdata,
-       },
-       .resource       = usba_udc_resources,
-       .num_resources  = ARRAY_SIZE(usba_udc_resources),
-};
-
-void __init at91_add_device_usba(struct usba_platform_data *data)
-{
-       usba_udc_data.pdata.vbus_pin = -EINVAL;
-       usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
-       memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));
-
-       if (data && gpio_is_valid(data->vbus_pin)) {
-               at91_set_gpio_input(data->vbus_pin, 0);
-               at91_set_deglitch(data->vbus_pin, 1);
-               usba_udc_data.pdata.vbus_pin = data->vbus_pin;
-       }
-
-       /* Pullup pin is handled internally by USB device peripheral */
-
-       platform_device_register(&at91_usba_udc_device);
-}
-#else
-void __init at91_add_device_usba(struct usba_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Ethernet
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
-static u64 eth_dmamask = DMA_BIT_MASK(32);
-static struct macb_platform_data eth_data;
-
-static struct resource eth_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_EMAC,
-               .end    = AT91SAM9G45_BASE_EMAC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_eth_device = {
-       .name           = "macb",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &eth_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &eth_data,
-       },
-       .resource       = eth_resources,
-       .num_resources  = ARRAY_SIZE(eth_resources),
-};
-
-void __init at91_add_device_eth(struct macb_platform_data *data)
-{
-       if (!data)
-               return;
-
-       if (gpio_is_valid(data->phy_irq_pin)) {
-               at91_set_gpio_input(data->phy_irq_pin, 0);
-               at91_set_deglitch(data->phy_irq_pin, 1);
-       }
-
-       /* Pins used for MII and RMII */
-       at91_set_A_periph(AT91_PIN_PA17, 0);    /* ETXCK_EREFCK */
-       at91_set_A_periph(AT91_PIN_PA15, 0);    /* ERXDV */
-       at91_set_A_periph(AT91_PIN_PA12, 0);    /* ERX0 */
-       at91_set_A_periph(AT91_PIN_PA13, 0);    /* ERX1 */
-       at91_set_A_periph(AT91_PIN_PA16, 0);    /* ERXER */
-       at91_set_A_periph(AT91_PIN_PA14, 0);    /* ETXEN */
-       at91_set_A_periph(AT91_PIN_PA10, 0);    /* ETX0 */
-       at91_set_A_periph(AT91_PIN_PA11, 0);    /* ETX1 */
-       at91_set_A_periph(AT91_PIN_PA19, 0);    /* EMDIO */
-       at91_set_A_periph(AT91_PIN_PA18, 0);    /* EMDC */
-
-       if (!data->is_rmii) {
-               at91_set_B_periph(AT91_PIN_PA29, 0);    /* ECRS */
-               at91_set_B_periph(AT91_PIN_PA30, 0);    /* ECOL */
-               at91_set_B_periph(AT91_PIN_PA8,  0);    /* ERX2 */
-               at91_set_B_periph(AT91_PIN_PA9,  0);    /* ERX3 */
-               at91_set_B_periph(AT91_PIN_PA28, 0);    /* ERXCK */
-               at91_set_B_periph(AT91_PIN_PA6,  0);    /* ETX2 */
-               at91_set_B_periph(AT91_PIN_PA7,  0);    /* ETX3 */
-               at91_set_B_periph(AT91_PIN_PA27, 0);    /* ETXER */
-       }
-
-       eth_data = *data;
-       platform_device_register(&at91sam9g45_eth_device);
-}
-#else
-void __init at91_add_device_eth(struct macb_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc0_data, mmc1_data;
-
-static struct resource mmc0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_MCI0,
-               .end    = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_mmc0_device = {
-       .name           = "atmel_mci",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc0_data,
-       },
-       .resource       = mmc0_resources,
-       .num_resources  = ARRAY_SIZE(mmc0_resources),
-};
-
-static struct resource mmc1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_MCI1,
-               .end    = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_mmc1_device = {
-       .name           = "atmel_mci",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc1_data,
-       },
-       .resource       = mmc1_resources,
-       .num_resources  = ARRAY_SIZE(mmc1_resources),
-};
-
-/* Consider only one slot : slot 0 */
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-
-       if (!data)
-               return;
-
-       /* Must have at least one usable slot */
-       if (!data->slot[0].bus_width)
-               return;
-
-#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
-       {
-       struct at_dma_slave     *atslave;
-       struct mci_dma_data     *alt_atslave;
-
-       alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
-       atslave = &alt_atslave->sdata;
-
-       /* DMA slave channel configuration */
-       atslave->dma_dev = &at_hdmac_device.dev;
-       atslave->cfg = ATC_FIFOCFG_HALFFIFO
-                       | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
-       if (mmc_id == 0)        /* MCI0 */
-               atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
-                             | ATC_DST_PER(AT_DMA_ID_MCI0);
-
-       else                    /* MCI1 */
-               atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
-                             | ATC_DST_PER(AT_DMA_ID_MCI1);
-
-       data->dma_slave = alt_atslave;
-       }
-#endif
-
-
-       /* input/irq */
-       if (gpio_is_valid(data->slot[0].detect_pin)) {
-               at91_set_gpio_input(data->slot[0].detect_pin, 1);
-               at91_set_deglitch(data->slot[0].detect_pin, 1);
-       }
-       if (gpio_is_valid(data->slot[0].wp_pin))
-               at91_set_gpio_input(data->slot[0].wp_pin, 1);
-
-       if (mmc_id == 0) {              /* MCI0 */
-
-               /* CLK */
-               at91_set_A_periph(AT91_PIN_PA0, 0);
-
-               /* CMD */
-               at91_set_A_periph(AT91_PIN_PA1, 1);
-
-               /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
-               at91_set_A_periph(AT91_PIN_PA2, 1);
-               if (data->slot[0].bus_width == 4) {
-                       at91_set_A_periph(AT91_PIN_PA3, 1);
-                       at91_set_A_periph(AT91_PIN_PA4, 1);
-                       at91_set_A_periph(AT91_PIN_PA5, 1);
-                       if (data->slot[0].bus_width == 8) {
-                               at91_set_A_periph(AT91_PIN_PA6, 1);
-                               at91_set_A_periph(AT91_PIN_PA7, 1);
-                               at91_set_A_periph(AT91_PIN_PA8, 1);
-                               at91_set_A_periph(AT91_PIN_PA9, 1);
-                       }
-               }
-
-               mmc0_data = *data;
-               platform_device_register(&at91sam9g45_mmc0_device);
-
-       } else {                        /* MCI1 */
-
-               /* CLK */
-               at91_set_A_periph(AT91_PIN_PA31, 0);
-
-               /* CMD */
-               at91_set_A_periph(AT91_PIN_PA22, 1);
-
-               /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
-               at91_set_A_periph(AT91_PIN_PA23, 1);
-               if (data->slot[0].bus_width == 4) {
-                       at91_set_A_periph(AT91_PIN_PA24, 1);
-                       at91_set_A_periph(AT91_PIN_PA25, 1);
-                       at91_set_A_periph(AT91_PIN_PA26, 1);
-                       if (data->slot[0].bus_width == 8) {
-                               at91_set_A_periph(AT91_PIN_PA27, 1);
-                               at91_set_A_periph(AT91_PIN_PA28, 1);
-                               at91_set_A_periph(AT91_PIN_PA29, 1);
-                               at91_set_A_periph(AT91_PIN_PA30, 1);
-                       }
-               }
-
-               mmc1_data = *data;
-               platform_device_register(&at91sam9g45_mmc1_device);
-
-       }
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  NAND / SmartMedia
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE      AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-       [0] = {
-               .start  = NAND_BASE,
-               .end    = NAND_BASE + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9G45_BASE_ECC,
-               .end    = AT91SAM9G45_BASE_ECC + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9g45_nand_device = {
-       .name           = "atmel_nand",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &nand_data,
-       },
-       .resource       = nand_resources,
-       .num_resources  = ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-       unsigned long csa;
-
-       if (!data)
-               return;
-
-       csa = at91_matrix_read(AT91_MATRIX_EBICSA);
-       at91_matrix_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
-
-       /* enable pin */
-       if (gpio_is_valid(data->enable_pin))
-               at91_set_gpio_output(data->enable_pin, 1);
-
-       /* ready/busy pin */
-       if (gpio_is_valid(data->rdy_pin))
-               at91_set_gpio_input(data->rdy_pin, 1);
-
-       /* card detect pin */
-       if (gpio_is_valid(data->det_pin))
-               at91_set_gpio_input(data->det_pin, 1);
-
-       nand_data = *data;
-       platform_device_register(&at91sam9g45_nand_device);
-}
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  TWI (i2c)
- * -------------------------------------------------------------------- */
-
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-static struct i2c_gpio_platform_data pdata_i2c0 = {
-       .sda_pin                = AT91_PIN_PA20,
-       .sda_is_open_drain      = 1,
-       .scl_pin                = AT91_PIN_PA21,
-       .scl_is_open_drain      = 1,
-       .udelay                 = 5,            /* ~100 kHz */
-};
-
-static struct platform_device at91sam9g45_twi0_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 0,
-       .dev.platform_data      = &pdata_i2c0,
-};
-
-static struct i2c_gpio_platform_data pdata_i2c1 = {
-       .sda_pin                = AT91_PIN_PB10,
-       .sda_is_open_drain      = 1,
-       .scl_pin                = AT91_PIN_PB11,
-       .scl_is_open_drain      = 1,
-       .udelay                 = 5,            /* ~100 kHz */
-};
-
-static struct platform_device at91sam9g45_twi1_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 1,
-       .dev.platform_data      = &pdata_i2c1,
-};
-
-void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
-{
-       i2c_register_board_info(i2c_id, devices, nr_devices);
-
-       if (i2c_id == 0) {
-               at91_set_GPIO_periph(AT91_PIN_PA20, 1);         /* TWD (SDA) */
-               at91_set_multi_drive(AT91_PIN_PA20, 1);
-
-               at91_set_GPIO_periph(AT91_PIN_PA21, 1);         /* TWCK (SCL) */
-               at91_set_multi_drive(AT91_PIN_PA21, 1);
-
-               platform_device_register(&at91sam9g45_twi0_device);
-       } else {
-               at91_set_GPIO_periph(AT91_PIN_PB10, 1);         /* TWD (SDA) */
-               at91_set_multi_drive(AT91_PIN_PB10, 1);
-
-               at91_set_GPIO_periph(AT91_PIN_PB11, 1);         /* TWCK (SCL) */
-               at91_set_multi_drive(AT91_PIN_PB11, 1);
-
-               platform_device_register(&at91sam9g45_twi1_device);
-       }
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-static struct resource twi0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_TWI0,
-               .end    = AT91SAM9G45_BASE_TWI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_twi0_device = {
-       .name           = "i2c-at91sam9g10",
-       .id             = 0,
-       .resource       = twi0_resources,
-       .num_resources  = ARRAY_SIZE(twi0_resources),
-};
-
-static struct resource twi1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_TWI1,
-               .end    = AT91SAM9G45_BASE_TWI1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_twi1_device = {
-       .name           = "i2c-at91sam9g10",
-       .id             = 1,
-       .resource       = twi1_resources,
-       .num_resources  = ARRAY_SIZE(twi1_resources),
-};
-
-void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices)
-{
-       i2c_register_board_info(i2c_id, devices, nr_devices);
-
-       /* pins used for TWI interface */
-       if (i2c_id == 0) {
-               at91_set_A_periph(AT91_PIN_PA20, 0);            /* TWD */
-               at91_set_A_periph(AT91_PIN_PA21, 0);            /* TWCK */
-
-               platform_device_register(&at91sam9g45_twi0_device);
-       } else {
-               at91_set_A_periph(AT91_PIN_PB10, 0);            /* TWD */
-               at91_set_A_periph(AT91_PIN_PB11, 0);            /* TWCK */
-
-               platform_device_register(&at91sam9g45_twi1_device);
-       }
-}
-#else
-void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_SPI0,
-               .end    = AT91SAM9G45_BASE_SPI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_spi0_device = {
-       .name           = "atmel_spi",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi0_resources,
-       .num_resources  = ARRAY_SIZE(spi0_resources),
-};
-
-static const unsigned spi0_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PB18, AT91_PIN_PB19, AT91_PIN_PD27 };
-
-static struct resource spi1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_SPI1,
-               .end    = AT91SAM9G45_BASE_SPI1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_spi1_device = {
-       .name           = "atmel_spi",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi1_resources,
-       .num_resources  = ARRAY_SIZE(spi1_resources),
-};
-
-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB17, AT91_PIN_PD28, AT91_PIN_PD18, AT91_PIN_PD19 };
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-       int i;
-       unsigned long cs_pin;
-       short enable_spi0 = 0;
-       short enable_spi1 = 0;
-
-       /* Choose SPI chip-selects */
-       for (i = 0; i < nr_devices; i++) {
-               if (devices[i].controller_data)
-                       cs_pin = (unsigned long) devices[i].controller_data;
-               else if (devices[i].bus_num == 0)
-                       cs_pin = spi0_standard_cs[devices[i].chip_select];
-               else
-                       cs_pin = spi1_standard_cs[devices[i].chip_select];
-
-               if (!gpio_is_valid(cs_pin))
-                       continue;
-
-               if (devices[i].bus_num == 0)
-                       enable_spi0 = 1;
-               else
-                       enable_spi1 = 1;
-
-               /* enable chip-select pin */
-               at91_set_gpio_output(cs_pin, 1);
-
-               /* pass chip-select pin to driver */
-               devices[i].controller_data = (void *) cs_pin;
-       }
-
-       spi_register_board_info(devices, nr_devices);
-
-       /* Configure SPI bus(es) */
-       if (enable_spi0) {
-               at91_set_A_periph(AT91_PIN_PB0, 0);     /* SPI0_MISO */
-               at91_set_A_periph(AT91_PIN_PB1, 0);     /* SPI0_MOSI */
-               at91_set_A_periph(AT91_PIN_PB2, 0);     /* SPI0_SPCK */
-
-               platform_device_register(&at91sam9g45_spi0_device);
-       }
-       if (enable_spi1) {
-               at91_set_A_periph(AT91_PIN_PB14, 0);    /* SPI1_MISO */
-               at91_set_A_periph(AT91_PIN_PB15, 0);    /* SPI1_MOSI */
-               at91_set_A_periph(AT91_PIN_PB16, 0);    /* SPI1_SPCK */
-
-               platform_device_register(&at91sam9g45_spi1_device);
-       }
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  AC97
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
-static u64 ac97_dmamask = DMA_BIT_MASK(32);
-static struct ac97c_platform_data ac97_data;
-
-static struct resource ac97_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_AC97C,
-               .end    = AT91SAM9G45_BASE_AC97C + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_ac97_device = {
-       .name           = "atmel_ac97c",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &ac97_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &ac97_data,
-       },
-       .resource       = ac97_resources,
-       .num_resources  = ARRAY_SIZE(ac97_resources),
-};
-
-void __init at91_add_device_ac97(struct ac97c_platform_data *data)
-{
-       if (!data)
-               return;
-
-       at91_set_A_periph(AT91_PIN_PD8, 0);     /* AC97FS */
-       at91_set_A_periph(AT91_PIN_PD9, 0);     /* AC97CK */
-       at91_set_A_periph(AT91_PIN_PD7, 0);     /* AC97TX */
-       at91_set_A_periph(AT91_PIN_PD6, 0);     /* AC97RX */
-
-       /* reset */
-       if (gpio_is_valid(data->reset_pin))
-               at91_set_gpio_output(data->reset_pin, 0);
-
-       ac97_data = *data;
-       platform_device_register(&at91sam9g45_ac97_device);
-}
-#else
-void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  Image Sensor Interface
- * -------------------------------------------------------------------- */
-#if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE)
-static u64 isi_dmamask = DMA_BIT_MASK(32);
-static struct isi_platform_data isi_data;
-
-struct resource isi_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_ISI,
-               .end    = AT91SAM9G45_BASE_ISI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_isi_device = {
-       .name           = "atmel_isi",
-       .id             = 0,
-       .dev            = {
-                       .dma_mask               = &isi_dmamask,
-                       .coherent_dma_mask      = DMA_BIT_MASK(32),
-                       .platform_data          = &isi_data,
-       },
-       .resource       = isi_resources,
-       .num_resources  = ARRAY_SIZE(isi_resources),
-};
-
-static struct clk_lookup isi_mck_lookups[] = {
-       CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi.0", NULL),
-};
-
-void __init at91_add_device_isi(struct isi_platform_data *data,
-               bool use_pck_as_mck)
-{
-       struct clk *pck;
-       struct clk *parent;
-
-       if (!data)
-               return;
-       isi_data = *data;
-
-       at91_set_A_periph(AT91_PIN_PB20, 0);    /* ISI_D0 */
-       at91_set_A_periph(AT91_PIN_PB21, 0);    /* ISI_D1 */
-       at91_set_A_periph(AT91_PIN_PB22, 0);    /* ISI_D2 */
-       at91_set_A_periph(AT91_PIN_PB23, 0);    /* ISI_D3 */
-       at91_set_A_periph(AT91_PIN_PB24, 0);    /* ISI_D4 */
-       at91_set_A_periph(AT91_PIN_PB25, 0);    /* ISI_D5 */
-       at91_set_A_periph(AT91_PIN_PB26, 0);    /* ISI_D6 */
-       at91_set_A_periph(AT91_PIN_PB27, 0);    /* ISI_D7 */
-       at91_set_A_periph(AT91_PIN_PB28, 0);    /* ISI_PCK */
-       at91_set_A_periph(AT91_PIN_PB30, 0);    /* ISI_HSYNC */
-       at91_set_A_periph(AT91_PIN_PB29, 0);    /* ISI_VSYNC */
-       at91_set_B_periph(AT91_PIN_PB8, 0);     /* ISI_PD8 */
-       at91_set_B_periph(AT91_PIN_PB9, 0);     /* ISI_PD9 */
-       at91_set_B_periph(AT91_PIN_PB10, 0);    /* ISI_PD10 */
-       at91_set_B_periph(AT91_PIN_PB11, 0);    /* ISI_PD11 */
-
-       platform_device_register(&at91sam9g45_isi_device);
-
-       if (use_pck_as_mck) {
-               at91_set_B_periph(AT91_PIN_PB31, 0);    /* ISI_MCK (PCK1) */
-
-               pck = clk_get(NULL, "pck1");
-               parent = clk_get(NULL, "plla");
-
-               BUG_ON(IS_ERR(pck) || IS_ERR(parent));
-
-               if (clk_set_parent(pck, parent)) {
-                       pr_err("Failed to set PCK's parent\n");
-               } else {
-                       /* Register PCK as ISI_MCK */
-                       isi_mck_lookups[0].clk = pck;
-                       clkdev_add_table(isi_mck_lookups,
-                                       ARRAY_SIZE(isi_mck_lookups));
-               }
-
-               clk_put(pck);
-               clk_put(parent);
-       }
-}
-#else
-void __init at91_add_device_isi(struct isi_platform_data *data,
-               bool use_pck_as_mck) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  LCD Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_pdata lcdc_data;
-
-static struct resource lcdc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_LCDC_BASE,
-               .end    = AT91SAM9G45_LCDC_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_lcdc_device = {
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &lcdc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &lcdc_data,
-       },
-       .resource       = lcdc_resources,
-       .num_resources  = ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
-{
-       if (!data)
-               return;
-
-       if (cpu_is_at91sam9g45es())
-               at91_lcdc_device.name = "at91sam9g45es-lcdfb";
-       else
-               at91_lcdc_device.name = "at91sam9g45-lcdfb";
-
-       at91_set_A_periph(AT91_PIN_PE0, 0);     /* LCDDPWR */
-
-       at91_set_A_periph(AT91_PIN_PE2, 0);     /* LCDCC */
-       at91_set_A_periph(AT91_PIN_PE3, 0);     /* LCDVSYNC */
-       at91_set_A_periph(AT91_PIN_PE4, 0);     /* LCDHSYNC */
-       at91_set_A_periph(AT91_PIN_PE5, 0);     /* LCDDOTCK */
-       at91_set_A_periph(AT91_PIN_PE6, 0);     /* LCDDEN */
-       at91_set_A_periph(AT91_PIN_PE7, 0);     /* LCDD0 */
-       at91_set_A_periph(AT91_PIN_PE8, 0);     /* LCDD1 */
-       at91_set_A_periph(AT91_PIN_PE9, 0);     /* LCDD2 */
-       at91_set_A_periph(AT91_PIN_PE10, 0);    /* LCDD3 */
-       at91_set_A_periph(AT91_PIN_PE11, 0);    /* LCDD4 */
-       at91_set_A_periph(AT91_PIN_PE12, 0);    /* LCDD5 */
-       at91_set_A_periph(AT91_PIN_PE13, 0);    /* LCDD6 */
-       at91_set_A_periph(AT91_PIN_PE14, 0);    /* LCDD7 */
-       at91_set_A_periph(AT91_PIN_PE15, 0);    /* LCDD8 */
-       at91_set_A_periph(AT91_PIN_PE16, 0);    /* LCDD9 */
-       at91_set_A_periph(AT91_PIN_PE17, 0);    /* LCDD10 */
-       at91_set_A_periph(AT91_PIN_PE18, 0);    /* LCDD11 */
-       at91_set_A_periph(AT91_PIN_PE19, 0);    /* LCDD12 */
-       at91_set_A_periph(AT91_PIN_PE20, 0);    /* LCDD13 */
-       at91_set_A_periph(AT91_PIN_PE21, 0);    /* LCDD14 */
-       at91_set_A_periph(AT91_PIN_PE22, 0);    /* LCDD15 */
-       at91_set_A_periph(AT91_PIN_PE23, 0);    /* LCDD16 */
-       at91_set_A_periph(AT91_PIN_PE24, 0);    /* LCDD17 */
-       at91_set_A_periph(AT91_PIN_PE25, 0);    /* LCDD18 */
-       at91_set_A_periph(AT91_PIN_PE26, 0);    /* LCDD19 */
-       at91_set_A_periph(AT91_PIN_PE27, 0);    /* LCDD20 */
-       at91_set_A_periph(AT91_PIN_PE28, 0);    /* LCDD21 */
-       at91_set_A_periph(AT91_PIN_PE29, 0);    /* LCDD22 */
-       at91_set_A_periph(AT91_PIN_PE30, 0);    /* LCDD23 */
-
-       lcdc_data = *data;
-       platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Timer/Counter block
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_ATMEL_TCLIB
-static struct resource tcb0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_TCB0,
-               .end    = AT91SAM9G45_BASE_TCB0 + SZ_256 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_tcb0_device = {
-       .name           = "atmel_tcb",
-       .id             = 0,
-       .resource       = tcb0_resources,
-       .num_resources  = ARRAY_SIZE(tcb0_resources),
-};
-
-/* TCB1 begins with TC3 */
-static struct resource tcb1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_TCB1,
-               .end    = AT91SAM9G45_BASE_TCB1 + SZ_256 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_tcb1_device = {
-       .name           = "atmel_tcb",
-       .id             = 1,
-       .resource       = tcb1_resources,
-       .num_resources  = ARRAY_SIZE(tcb1_resources),
-};
-
-static void __init at91_add_device_tc(void)
-{
-       platform_device_register(&at91sam9g45_tcb0_device);
-       platform_device_register(&at91sam9g45_tcb1_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
-/* --------------------------------------------------------------------
- *  RTC
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
-static struct resource rtc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_RTC,
-               .end    = AT91SAM9G45_BASE_RTC + SZ_256 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_rtc_device = {
-       .name           = "at91_rtc",
-       .id             = -1,
-       .resource       = rtc_resources,
-       .num_resources  = ARRAY_SIZE(rtc_resources),
-};
-
-static void __init at91_add_device_rtc(void)
-{
-       platform_device_register(&at91sam9g45_rtc_device);
-}
-#else
-static void __init at91_add_device_rtc(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  ADC and touchscreen
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_AT91_ADC)
-static struct at91_adc_data adc_data;
-
-static struct resource adc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_TSC,
-               .end    = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static struct platform_device at91_adc_device = {
-       .name           = "at91sam9g45-adc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &adc_data,
-       },
-       .resource       = adc_resources,
-       .num_resources  = ARRAY_SIZE(adc_resources),
-};
-
-static struct at91_adc_trigger at91_adc_triggers[] = {
-       [0] = {
-               .name = "external-rising",
-               .value = 1,
-               .is_external = true,
-       },
-       [1] = {
-               .name = "external-falling",
-               .value = 2,
-               .is_external = true,
-       },
-       [2] = {
-               .name = "external-any",
-               .value = 3,
-               .is_external = true,
-       },
-       [3] = {
-               .name = "continuous",
-               .value = 6,
-               .is_external = false,
-       },
-};
-
-void __init at91_add_device_adc(struct at91_adc_data *data)
-{
-       if (!data)
-               return;
-
-       if (test_bit(0, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD20, 0);
-       if (test_bit(1, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD21, 0);
-       if (test_bit(2, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD22, 0);
-       if (test_bit(3, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD23, 0);
-       if (test_bit(4, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD24, 0);
-       if (test_bit(5, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD25, 0);
-       if (test_bit(6, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD26, 0);
-       if (test_bit(7, &data->channels_used))
-               at91_set_gpio_input(AT91_PIN_PD27, 0);
-
-       if (data->use_external_triggers)
-               at91_set_A_periph(AT91_PIN_PD28, 0);
-
-       data->startup_time = 40;
-       data->trigger_number = 4;
-       data->trigger_list = at91_adc_triggers;
-
-       adc_data = *data;
-       platform_device_register(&at91_adc_device);
-}
-#else
-void __init at91_add_device_adc(struct at91_adc_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  RTT
- * -------------------------------------------------------------------- */
-
-static struct resource rtt_resources[] = {
-       {
-               .start  = AT91SAM9G45_BASE_RTT,
-               .end    = AT91SAM9G45_BASE_RTT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static struct platform_device at91sam9g45_rtt_device = {
-       .name           = "at91_rtt",
-       .id             = 0,
-       .resource       = rtt_resources,
-};
-
-#if IS_ENABLED(CONFIG_RTC_DRV_AT91SAM9)
-static void __init at91_add_device_rtt_rtc(void)
-{
-       at91sam9g45_rtt_device.name = "rtc-at91sam9";
-       /*
-        * The second resource is needed:
-        * GPBR will serve as the storage for RTC time offset
-        */
-       at91sam9g45_rtt_device.num_resources = 3;
-       rtt_resources[1].start = AT91SAM9G45_BASE_GPBR +
-                                4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
-       rtt_resources[1].end = rtt_resources[1].start + 3;
-       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
-       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
-}
-#else
-static void __init at91_add_device_rtt_rtc(void)
-{
-       /* Only one resource is needed: RTT not used as RTC */
-       at91sam9g45_rtt_device.num_resources = 1;
-}
-#endif
-
-static void __init at91_add_device_rtt(void)
-{
-       at91_add_device_rtt_rtc();
-       platform_device_register(&at91sam9g45_rtt_device);
-}
-
-
-/* --------------------------------------------------------------------
- *  TRNG
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
-static struct resource trng_resources[] = {
-       {
-               .start  = AT91SAM9G45_BASE_TRNG,
-               .end    = AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device at91sam9g45_trng_device = {
-       .name           = "atmel-trng",
-       .id             = -1,
-       .resource       = trng_resources,
-       .num_resources  = ARRAY_SIZE(trng_resources),
-};
-
-static void __init at91_add_device_trng(void)
-{
-       platform_device_register(&at91sam9g45_trng_device);
-}
-#else
-static void __init at91_add_device_trng(void) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct resource wdt_resources[] = {
-       {
-               .start  = AT91SAM9G45_BASE_WDT,
-               .end    = AT91SAM9G45_BASE_WDT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9g45_wdt_device = {
-       .name           = "at91_wdt",
-       .id             = -1,
-       .resource       = wdt_resources,
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-       platform_device_register(&at91sam9g45_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  PWM
- * --------------------------------------------------------------------*/
-
-#if IS_ENABLED(CONFIG_PWM_ATMEL)
-static struct resource pwm_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_PWMC,
-               .end    = AT91SAM9G45_BASE_PWMC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_pwm0_device = {
-       .name   = "at91sam9rl-pwm",
-       .id     = -1,
-       .resource       = pwm_resources,
-       .num_resources  = ARRAY_SIZE(pwm_resources),
-};
-
-void __init at91_add_device_pwm(u32 mask)
-{
-       if (mask & (1 << AT91_PWM0))
-               at91_set_B_periph(AT91_PIN_PD24, 1);    /* enable PWM0 */
-
-       if (mask & (1 << AT91_PWM1))
-               at91_set_B_periph(AT91_PIN_PD31, 1);    /* enable PWM1 */
-
-       if (mask & (1 << AT91_PWM2))
-               at91_set_B_periph(AT91_PIN_PD26, 1);    /* enable PWM2 */
-
-       if (mask & (1 << AT91_PWM3))
-               at91_set_B_periph(AT91_PIN_PD0, 1);     /* enable PWM3 */
-
-       platform_device_register(&at91sam9g45_pwm0_device);
-}
-#else
-void __init at91_add_device_pwm(u32 mask) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SSC -- Synchronous Serial Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_SSC0,
-               .end    = AT91SAM9G45_BASE_SSC0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_ssc0_device = {
-       .name   = "at91sam9g45_ssc",
-       .id     = 0,
-       .dev    = {
-               .dma_mask               = &ssc0_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc0_resources,
-       .num_resources  = ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PD1, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PD0, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PD2, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PD3, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PD4, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PD5, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_SSC1,
-               .end    = AT91SAM9G45_BASE_SSC1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_ssc1_device = {
-       .name   = "at91sam9g45_ssc",
-       .id     = 1,
-       .dev    = {
-               .dma_mask               = &ssc1_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc1_resources,
-       .num_resources  = ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PD14, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PD12, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PD10, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PD11, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_A_periph(AT91_PIN_PD13, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_A_periph(AT91_PIN_PD15, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-       struct platform_device *pdev;
-
-       /*
-        * NOTE: caller is responsible for passing information matching
-        * "pins" to whatever will be using each particular controller.
-        */
-       switch (id) {
-       case AT91SAM9G45_ID_SSC0:
-               pdev = &at91sam9g45_ssc0_device;
-               configure_ssc0_pins(pins);
-               break;
-       case AT91SAM9G45_ID_SSC1:
-               pdev = &at91sam9g45_ssc1_device;
-               configure_ssc1_pins(pins);
-               break;
-       default:
-               return;
-       }
-
-       platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_DBGU,
-               .end    = AT91SAM9G45_BASE_DBGU + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data dbgu_data = {
-       .use_dma_tx     = 0,
-       .use_dma_rx     = 0,
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_dbgu_device = {
-       .name           = "atmel_usart",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &dbgu_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &dbgu_data,
-       },
-       .resource       = dbgu_resources,
-       .num_resources  = ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-       at91_set_A_periph(AT91_PIN_PB12, 0);            /* DRXD */
-       at91_set_A_periph(AT91_PIN_PB13, 1);            /* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_US0,
-               .end    = AT91SAM9G45_BASE_US0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart0_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart0_device = {
-       .name           = "atmel_usart",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &uart0_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart0_data,
-       },
-       .resource       = uart0_resources,
-       .num_resources  = ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB19, 1);            /* TXD0 */
-       at91_set_A_periph(AT91_PIN_PB18, 0);            /* RXD0 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PB17, 0);    /* RTS0 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PB15, 0);    /* CTS0 */
-}
-
-static struct resource uart1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_US1,
-               .end    = AT91SAM9G45_BASE_US1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart1_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart1_device = {
-       .name           = "atmel_usart",
-       .id             = 2,
-       .dev            = {
-                               .dma_mask               = &uart1_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart1_data,
-       },
-       .resource       = uart1_resources,
-       .num_resources  = ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB4, 1);             /* TXD1 */
-       at91_set_A_periph(AT91_PIN_PB5, 0);             /* RXD1 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PD16, 0);    /* RTS1 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PD17, 0);    /* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_US2,
-               .end    = AT91SAM9G45_BASE_US2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart2_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart2_device = {
-       .name           = "atmel_usart",
-       .id             = 3,
-       .dev            = {
-                               .dma_mask               = &uart2_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart2_data,
-       },
-       .resource       = uart2_resources,
-       .num_resources  = ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB6, 1);             /* TXD2 */
-       at91_set_A_periph(AT91_PIN_PB7, 0);             /* RXD2 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PC9, 0);     /* RTS2 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PC11, 0);    /* CTS2 */
-}
-
-static struct resource uart3_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_US3,
-               .end    = AT91SAM9G45_BASE_US3 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart3_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9g45_uart3_device = {
-       .name           = "atmel_usart",
-       .id             = 4,
-       .dev            = {
-                               .dma_mask               = &uart3_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart3_data,
-       },
-       .resource       = uart3_resources,
-       .num_resources  = ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB8, 1);             /* TXD3 */
-       at91_set_A_periph(AT91_PIN_PB9, 0);             /* RXD3 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PA23, 0);    /* RTS3 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PA24, 0);    /* CTS3 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];  /* the UARTs to use */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-       struct platform_device *pdev;
-       struct atmel_uart_data *pdata;
-
-       switch (id) {
-               case 0:         /* DBGU */
-                       pdev = &at91sam9g45_dbgu_device;
-                       configure_dbgu_pins();
-                       break;
-               case AT91SAM9G45_ID_US0:
-                       pdev = &at91sam9g45_uart0_device;
-                       configure_usart0_pins(pins);
-                       break;
-               case AT91SAM9G45_ID_US1:
-                       pdev = &at91sam9g45_uart1_device;
-                       configure_usart1_pins(pins);
-                       break;
-               case AT91SAM9G45_ID_US2:
-                       pdev = &at91sam9g45_uart2_device;
-                       configure_usart2_pins(pins);
-                       break;
-               case AT91SAM9G45_ID_US3:
-                       pdev = &at91sam9g45_uart3_device;
-                       configure_usart3_pins(pins);
-                       break;
-               default:
-                       return;
-       }
-       pdata = pdev->dev.platform_data;
-       pdata->num = portnr;            /* update to mapped ID */
-
-       if (portnr < ATMEL_MAX_UART)
-               at91_uarts[portnr] = pdev;
-}
-
-void __init at91_add_device_serial(void)
-{
-       int i;
-
-       for (i = 0; i < ATMEL_MAX_UART; i++) {
-               if (at91_uarts[i])
-                       platform_device_register(at91_uarts[i]);
-       }
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  SHA1/SHA256
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_CRYPTO_DEV_ATMEL_SHA) || defined(CONFIG_CRYPTO_DEV_ATMEL_SHA_MODULE)
-static struct resource sha_resources[] = {
-       {
-               .start  = AT91SAM9G45_BASE_SHA,
-               .end    = AT91SAM9G45_BASE_SHA + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_sha_device = {
-       .name   = "atmel_sha",
-       .id             = -1,
-       .resource       = sha_resources,
-       .num_resources  = ARRAY_SIZE(sha_resources),
-};
-
-static void __init at91_add_device_sha(void)
-{
-       platform_device_register(&at91sam9g45_sha_device);
-}
-#else
-static void __init at91_add_device_sha(void) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  DES/TDES
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_CRYPTO_DEV_ATMEL_TDES) || defined(CONFIG_CRYPTO_DEV_ATMEL_TDES_MODULE)
-static struct resource tdes_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_TDES,
-               .end    = AT91SAM9G45_BASE_TDES + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_tdes_device = {
-       .name   = "atmel_tdes",
-       .id             = -1,
-       .resource       = tdes_resources,
-       .num_resources  = ARRAY_SIZE(tdes_resources),
-};
-
-static void __init at91_add_device_tdes(void)
-{
-       platform_device_register(&at91sam9g45_tdes_device);
-}
-#else
-static void __init at91_add_device_tdes(void) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  AES
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_CRYPTO_DEV_ATMEL_AES) || defined(CONFIG_CRYPTO_DEV_ATMEL_AES_MODULE)
-static struct crypto_platform_data aes_data;
-static struct crypto_dma_data alt_atslave;
-static u64 aes_dmamask = DMA_BIT_MASK(32);
-
-static struct resource aes_resources[] = {
-       [0] = {
-               .start  = AT91SAM9G45_BASE_AES,
-               .end    = AT91SAM9G45_BASE_AES + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9g45_aes_device = {
-       .name   = "atmel_aes",
-       .id             = -1,
-       .dev    = {
-               .dma_mask               = &aes_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data          = &aes_data,
-       },
-       .resource       = aes_resources,
-       .num_resources  = ARRAY_SIZE(aes_resources),
-};
-
-static void __init at91_add_device_aes(void)
-{
-       struct at_dma_slave     *atslave;
-
-       /* DMA TX slave channel configuration */
-       atslave = &alt_atslave.txdata;
-       atslave->dma_dev = &at_hdmac_device.dev;
-       atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE  | ATC_SRC_H2SEL_HW |
-                                               ATC_SRC_PER(AT_DMA_ID_AES_RX);
-
-       /* DMA RX slave channel configuration */
-       atslave = &alt_atslave.rxdata;
-       atslave->dma_dev = &at_hdmac_device.dev;
-       atslave->cfg = ATC_FIFOCFG_ENOUGHSPACE  | ATC_DST_H2SEL_HW |
-                                               ATC_DST_PER(AT_DMA_ID_AES_TX);
-
-       aes_data.dma_slave = &alt_atslave;
-       platform_device_register(&at91sam9g45_aes_device);
-}
-#else
-static void __init at91_add_device_aes(void) {}
-#endif
-
-/* -------------------------------------------------------------------- */
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-       if (of_have_populated_dt())
-               return 0;
-
-       at91_add_device_hdmac();
-       at91_add_device_rtc();
-       at91_add_device_rtt();
-       at91_add_device_trng();
-       at91_add_device_watchdog();
-       at91_add_device_tc();
-       at91_add_device_sha();
-       at91_add_device_tdes();
-       at91_add_device_aes();
-       return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
index c8988fe5ff7065861a12a47fe19cd2b11e016f65..dee569b1987ee7c8f5dee1f08fa4e1d99a8927cb 100644 (file)
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk/at91_pmc.h>
+#include <asm/system_misc.h>
+#include <mach/hardware.h>
 
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/at91sam9n12.h>
-#include <mach/cpu.h>
-
-#include "board.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioAB_clk = {
-       .name           = "pioAB_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_PIOAB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioCD_clk = {
-       .name           = "pioCD_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_PIOCD,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_USART0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_USART1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_USART2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_USART3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi0_clk = {
-       .name           = "twi0_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_TWI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi1_clk = {
-       .name           = "twi1_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_TWI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-       .name           = "mci_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_MCI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-       .name           = "spi0_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_SPI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-       .name           = "spi1_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_SPI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uart0_clk = {
-       .name           = "uart0_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_UART0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uart1_clk = {
-       .name           = "uart1_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_UART1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tcb_clk = {
-       .name           = "tcb_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_TCB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pwm_clk = {
-       .name           = "pwm_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_PWM,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk adc_clk = {
-       .name           = "adc_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_ADC,
-       .type   = CLK_TYPE_PERIPHERAL,
-};
-static struct clk dma_clk = {
-       .name           = "dma_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_DMA,
-       .type   = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uhp_clk = {
-       .name           = "uhp",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_UHP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udp_clk = {
-       .name           = "udp_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_UDP,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk lcdc_clk = {
-       .name           = "lcdc_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_LCDC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc_clk = {
-       .name           = "ssc_clk",
-       .pmc_mask       = 1 << AT91SAM9N12_ID_SSC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioAB_clk,
-       &pioCD_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &usart3_clk,
-       &twi0_clk,
-       &twi1_clk,
-       &mmc_clk,
-       &spi0_clk,
-       &spi1_clk,
-       &lcdc_clk,
-       &uart0_clk,
-       &uart1_clk,
-       &tcb_clk,
-       &pwm_clk,
-       &adc_clk,
-       &dma_clk,
-       &uhp_clk,
-       &udp_clk,
-       &ssc_clk,
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       /* lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "f801c000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f0010000.ssc", &ssc_clk),
-       CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "f0000000.spi", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
-       /* additional fake clock for macb_hclk */
-       CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &uhp_clk),
-       CLKDEV_CON_DEV_ID("ohci_clk", "500000.ohci", &uhp_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f8034000.pwm", &pwm_clk),
-};
-
-/*
- * The two programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-
-static void __init at91sam9n12_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-       clk_register(&pck0);
-       clk_register(&pck1);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-
-}
-#else
-#define at91sam9n12_register_clocks NULL
-#endif
 
 /* --------------------------------------------------------------------
  *  AT91SAM9N12 processor initialization
@@ -236,6 +28,5 @@ static void __init at91sam9n12_initialize(void)
 
 AT91_SOC_START(at91sam9n12)
        .map_io = at91sam9n12_map_io,
-       .register_clocks = at91sam9n12_register_clocks,
        .init = at91sam9n12_initialize,
 AT91_SOC_END
index f553e4ea034bade189daebc308c79343939aa813..f25b9aec9c50fd6c297876f3b755816ef9342c4e 100644 (file)
  * more details.
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk/at91_pmc.h>
-
-#include <asm/proc-fns.h>
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
 #include <asm/system_misc.h>
+#include <asm/irq.h>
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
-#include <mach/at91sam9rl.h>
 #include <mach/hardware.h>
 
-#include "at91_aic.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-#include "pm.h"
-
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioA_clk = {
-       .name           = "pioA_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_PIOA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioB_clk = {
-       .name           = "pioB_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_PIOB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioC_clk = {
-       .name           = "pioC_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_PIOC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioD_clk = {
-       .name           = "pioD_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_PIOD,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_US0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_US1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_US2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_US3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc_clk = {
-       .name           = "mci_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_MCI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi0_clk = {
-       .name           = "twi0_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_TWI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi1_clk = {
-       .name           = "twi1_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_TWI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi_clk = {
-       .name           = "spi_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_SPI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc0_clk = {
-       .name           = "ssc0_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_SSC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc1_clk = {
-       .name           = "ssc1_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_SSC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc0_clk = {
-       .name           = "tc0_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_TC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc1_clk = {
-       .name           = "tc1_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_TC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tc2_clk = {
-       .name           = "tc2_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_TC2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pwm_clk = {
-       .name           = "pwm_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_PWMC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tsc_clk = {
-       .name           = "tsc_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_TSC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk dma_clk = {
-       .name           = "dma_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_DMA,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udphs_clk = {
-       .name           = "udphs_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_UDPHS,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk lcdc_clk = {
-       .name           = "lcdc_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_LCDC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ac97_clk = {
-       .name           = "ac97_clk",
-       .pmc_mask       = 1 << AT91SAM9RL_ID_AC97C,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk adc_op_clk = {
-       .name           = "adc_op_clk",
-       .type           = CLK_TYPE_PERIPHERAL,
-       .rate_hz        = 1000000,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioA_clk,
-       &pioB_clk,
-       &pioC_clk,
-       &pioD_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &usart3_clk,
-       &mmc_clk,
-       &twi0_clk,
-       &twi1_clk,
-       &spi_clk,
-       &ssc0_clk,
-       &ssc1_clk,
-       &tc0_clk,
-       &tc1_clk,
-       &tc2_clk,
-       &pwm_clk,
-       &tsc_clk,
-       &dma_clk,
-       &udphs_clk,
-       &lcdc_clk,
-       &ac97_clk,
-       &adc_op_clk,
-       // irq0
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("hclk", "at91sam9rl-lcdfb.0", &lcdc_clk),
-       CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
-       CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "at91sam9rl-pwm", &pwm_clk),
-       CLKDEV_CON_ID("pioA", &pioA_clk),
-       CLKDEV_CON_ID("pioB", &pioB_clk),
-       CLKDEV_CON_ID("pioC", &pioC_clk),
-       CLKDEV_CON_ID("pioD", &pioD_clk),
-       /* more lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "ffffb400.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "ffffb800.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "ffffbc00.serial", &usart3_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
-       CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
-       CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "fffa4000.mmc", &mmc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffa8000.i2c", &twi0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffac000.i2c", &twi1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffc8000.pwm", &pwm_clk),
-       CLKDEV_CON_DEV_ID(NULL, "ffffc800.pwm", &pwm_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioA_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioD_clk),
-       CLKDEV_CON_ID("adc_clk", &tsc_clk),
-};
-
-static struct clk_lookup usart_clocks_lookups[] = {
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.0", &mck),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.1", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.2", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.3", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "atmel_usart.4", &usart3_clk),
-};
-
-/*
- * The two programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-
-static void __init at91sam9rl_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-       clkdev_add_table(usart_clocks_lookups,
-                        ARRAY_SIZE(usart_clocks_lookups));
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-}
-#endif
-
-/* --------------------------------------------------------------------
- *  GPIO
- * -------------------------------------------------------------------- */
-
-static struct at91_gpio_bank at91sam9rl_gpio[] __initdata = {
-       {
-               .id             = AT91SAM9RL_ID_PIOA,
-               .regbase        = AT91SAM9RL_BASE_PIOA,
-       }, {
-               .id             = AT91SAM9RL_ID_PIOB,
-               .regbase        = AT91SAM9RL_BASE_PIOB,
-       }, {
-               .id             = AT91SAM9RL_ID_PIOC,
-               .regbase        = AT91SAM9RL_BASE_PIOC,
-       }, {
-               .id             = AT91SAM9RL_ID_PIOD,
-               .regbase        = AT91SAM9RL_BASE_PIOD,
-       }
-};
 
 /* --------------------------------------------------------------------
  *  AT91SAM9RL processor initialization
@@ -309,121 +39,15 @@ static void __init at91sam9rl_map_io(void)
        at91_init_sram(0, AT91SAM9RL_SRAM_BASE, sram_size);
 }
 
-static void __init at91sam9rl_ioremap_registers(void)
-{
-       at91_ioremap_ramc(0, AT91SAM9RL_BASE_SDRAMC, 512);
-       at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
-       at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
-       at91_ioremap_matrix(AT91SAM9RL_BASE_MATRIX);
-       at91_pm_set_standby(at91sam9_sdram_standby);
-}
-
 static void __init at91sam9rl_initialize(void)
 {
        arm_pm_idle = at91sam9_idle;
 
        at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC);
        at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT);
-
-       /* Register GPIO subsystem */
-       at91_gpio_init(at91sam9rl_gpio, 4);
-}
-
-static struct resource rstc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_RSTC,
-               .end    = AT91SAM9RL_BASE_RSTC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9RL_BASE_SDRAMC,
-               .end    = AT91SAM9RL_BASE_SDRAMC + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device rstc_device = {
-       .name           = "at91-sam9260-reset",
-       .resource       = rstc_resources,
-       .num_resources  = ARRAY_SIZE(rstc_resources),
-};
-
-static struct resource shdwc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_SHDWC,
-               .end    = AT91SAM9RL_BASE_SHDWC + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device shdwc_device = {
-       .name           = "at91-poweroff",
-       .resource       = shdwc_resources,
-       .num_resources  = ARRAY_SIZE(shdwc_resources),
-};
-
-static void __init at91sam9rl_register_devices(void)
-{
-       platform_device_register(&rstc_device);
-       platform_device_register(&shdwc_device);
-}
-
-/* --------------------------------------------------------------------
- *  Interrupt initialization
- * -------------------------------------------------------------------- */
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9rl_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A */
-       1,      /* Parallel IO Controller B */
-       1,      /* Parallel IO Controller C */
-       1,      /* Parallel IO Controller D */
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       5,      /* USART 3 */
-       0,      /* Multimedia Card Interface */
-       6,      /* Two-Wire Interface 0 */
-       6,      /* Two-Wire Interface 1 */
-       5,      /* Serial Peripheral Interface */
-       4,      /* Serial Synchronous Controller 0 */
-       4,      /* Serial Synchronous Controller 1 */
-       0,      /* Timer Counter 0 */
-       0,      /* Timer Counter 1 */
-       0,      /* Timer Counter 2 */
-       0,
-       0,      /* Touch Screen Controller */
-       0,      /* DMA Controller */
-       2,      /* USB Device High speed port */
-       2,      /* LCD Controller */
-       6,      /* AC97 Controller */
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,
-       0,      /* Advanced Interrupt Controller */
-};
-
-static void __init at91sam9rl_init_time(void)
-{
-       at91sam926x_pit_init(NR_IRQS_LEGACY + AT91_ID_SYS);
 }
 
 AT91_SOC_START(at91sam9rl)
        .map_io = at91sam9rl_map_io,
-       .default_irq_priority = at91sam9rl_default_irq_priority,
-       .extern_irq = (1 << AT91SAM9RL_ID_IRQ0),
-       .ioremap_registers = at91sam9rl_ioremap_registers,
-#if defined(CONFIG_OLD_CLK_AT91)
-       .register_clocks = at91sam9rl_register_clocks,
-#endif
-       .register_devices = at91sam9rl_register_devices,
        .init = at91sam9rl_initialize,
-       .init_time = at91sam9rl_init_time,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
deleted file mode 100644 (file)
index 37d1c9e..0000000
+++ /dev/null
@@ -1,1260 +0,0 @@
-/*
- *  Copyright (C) 2007 Atmel Corporation
- *
- * 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 <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/i2c-gpio.h>
-
-#include <linux/fb.h>
-#include <video/atmel_lcdc.h>
-
-#include <mach/at91sam9rl.h>
-#include <mach/at91sam9rl_matrix.h>
-#include <mach/at91_matrix.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/hardware.h>
-#include <linux/platform_data/dma-atmel.h>
-#include <linux/platform_data/at91_adc.h>
-
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-/* --------------------------------------------------------------------
- *  HDMAC - AHB DMA Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
-static u64 hdmac_dmamask = DMA_BIT_MASK(32);
-
-static struct resource hdmac_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_DMA,
-               .end    = AT91SAM9RL_BASE_DMA + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at_hdmac_device = {
-       .name           = "at91sam9rl_dma",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &hdmac_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = hdmac_resources,
-       .num_resources  = ARRAY_SIZE(hdmac_resources),
-};
-
-void __init at91_add_device_hdmac(void)
-{
-       platform_device_register(&at_hdmac_device);
-}
-#else
-void __init at91_add_device_hdmac(void) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  USB HS Device (Gadget)
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
-
-static struct resource usba_udc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_UDPHS_FIFO,
-               .end    = AT91SAM9RL_UDPHS_FIFO + SZ_512K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9RL_BASE_UDPHS,
-               .end    = AT91SAM9RL_BASE_UDPHS + SZ_1K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-#define EP(nam, idx, maxpkt, maxbk, dma, isoc)                 \
-       [idx] = {                                               \
-               .name           = nam,                          \
-               .index          = idx,                          \
-               .fifo_size      = maxpkt,                       \
-               .nr_banks       = maxbk,                        \
-               .can_dma        = dma,                          \
-               .can_isoc       = isoc,                         \
-       }
-
-static struct usba_ep_data usba_udc_ep[] __initdata = {
-       EP("ep0", 0, 64, 1, 0, 0),
-       EP("ep1", 1, 1024, 2, 1, 1),
-       EP("ep2", 2, 1024, 2, 1, 1),
-       EP("ep3", 3, 1024, 3, 1, 0),
-       EP("ep4", 4, 1024, 3, 1, 0),
-       EP("ep5", 5, 1024, 3, 1, 1),
-       EP("ep6", 6, 1024, 3, 1, 1),
-};
-
-#undef EP
-
-/*
- * pdata doesn't have room for any endpoints, so we need to
- * append room for the ones we need right after it.
- */
-static struct {
-       struct usba_platform_data pdata;
-       struct usba_ep_data ep[7];
-} usba_udc_data;
-
-static struct platform_device at91_usba_udc_device = {
-       .name           = "atmel_usba_udc",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &usba_udc_data.pdata,
-       },
-       .resource       = usba_udc_resources,
-       .num_resources  = ARRAY_SIZE(usba_udc_resources),
-};
-
-void __init at91_add_device_usba(struct usba_platform_data *data)
-{
-       /*
-        * Invalid pins are 0 on AT91, but the usba driver is shared
-        * with AVR32, which use negative values instead. Once/if
-        * gpio_is_valid() is ported to AT91, revisit this code.
-        */
-       usba_udc_data.pdata.vbus_pin = -EINVAL;
-       usba_udc_data.pdata.num_ep = ARRAY_SIZE(usba_udc_ep);
-       memcpy(usba_udc_data.ep, usba_udc_ep, sizeof(usba_udc_ep));
-
-       if (data && gpio_is_valid(data->vbus_pin)) {
-               at91_set_gpio_input(data->vbus_pin, 0);
-               at91_set_deglitch(data->vbus_pin, 1);
-               usba_udc_data.pdata.vbus_pin = data->vbus_pin;
-       }
-
-       /* Pullup pin is handled internally by USB device peripheral */
-
-       platform_device_register(&at91_usba_udc_device);
-}
-#else
-void __init at91_add_device_usba(struct usba_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct mci_platform_data mmc_data;
-
-static struct resource mmc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_MCI,
-               .end    = AT91SAM9RL_BASE_MCI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_mmc_device = {
-       .name           = "atmel_mci",
-       .id             = -1,
-       .dev            = {
-                               .dma_mask               = &mmc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &mmc_data,
-       },
-       .resource       = mmc_resources,
-       .num_resources  = ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
-{
-       if (!data)
-               return;
-
-       if (data->slot[0].bus_width) {
-               /* input/irq */
-               if (gpio_is_valid(data->slot[0].detect_pin)) {
-                       at91_set_gpio_input(data->slot[0].detect_pin, 1);
-                       at91_set_deglitch(data->slot[0].detect_pin, 1);
-               }
-               if (gpio_is_valid(data->slot[0].wp_pin))
-                       at91_set_gpio_input(data->slot[0].wp_pin, 1);
-
-               /* CLK */
-               at91_set_A_periph(AT91_PIN_PA2, 0);
-
-               /* CMD */
-               at91_set_A_periph(AT91_PIN_PA1, 1);
-
-               /* DAT0, maybe DAT1..DAT3 */
-               at91_set_A_periph(AT91_PIN_PA0, 1);
-               if (data->slot[0].bus_width == 4) {
-                       at91_set_A_periph(AT91_PIN_PA3, 1);
-                       at91_set_A_periph(AT91_PIN_PA4, 1);
-                       at91_set_A_periph(AT91_PIN_PA5, 1);
-               }
-
-               mmc_data = *data;
-               platform_device_register(&at91sam9rl_mmc_device);
-       }
-}
-#else
-void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  NAND / SmartMedia
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MTD_NAND_ATMEL) || defined(CONFIG_MTD_NAND_ATMEL_MODULE)
-static struct atmel_nand_data nand_data;
-
-#define NAND_BASE      AT91_CHIPSELECT_3
-
-static struct resource nand_resources[] = {
-       [0] = {
-               .start  = NAND_BASE,
-               .end    = NAND_BASE + SZ_256M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = AT91SAM9RL_BASE_ECC,
-               .end    = AT91SAM9RL_BASE_ECC + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device atmel_nand_device = {
-       .name           = "atmel_nand",
-       .id             = -1,
-       .dev            = {
-                               .platform_data  = &nand_data,
-       },
-       .resource       = nand_resources,
-       .num_resources  = ARRAY_SIZE(nand_resources),
-};
-
-void __init at91_add_device_nand(struct atmel_nand_data *data)
-{
-       unsigned long csa;
-
-       if (!data)
-               return;
-
-       csa = at91_matrix_read(AT91_MATRIX_EBICSA);
-       at91_matrix_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC_SMARTMEDIA);
-
-       /* enable pin */
-       if (gpio_is_valid(data->enable_pin))
-               at91_set_gpio_output(data->enable_pin, 1);
-
-       /* ready/busy pin */
-       if (gpio_is_valid(data->rdy_pin))
-               at91_set_gpio_input(data->rdy_pin, 1);
-
-       /* card detect pin */
-       if (gpio_is_valid(data->det_pin))
-               at91_set_gpio_input(data->det_pin, 1);
-
-       at91_set_A_periph(AT91_PIN_PB4, 0);             /* NANDOE */
-       at91_set_A_periph(AT91_PIN_PB5, 0);             /* NANDWE */
-
-       nand_data = *data;
-       platform_device_register(&atmel_nand_device);
-}
-
-#else
-void __init at91_add_device_nand(struct atmel_nand_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  TWI (i2c)
- * -------------------------------------------------------------------- */
-
-/*
- * Prefer the GPIO code since the TWI controller isn't robust
- * (gets overruns and underruns under load) and can only issue
- * repeated STARTs in one scenario (the driver doesn't yet handle them).
- */
-#if defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
-
-static struct i2c_gpio_platform_data pdata = {
-       .sda_pin                = AT91_PIN_PA23,
-       .sda_is_open_drain      = 1,
-       .scl_pin                = AT91_PIN_PA24,
-       .scl_is_open_drain      = 1,
-       .udelay                 = 2,            /* ~100 kHz */
-};
-
-static struct platform_device at91sam9rl_twi_device = {
-       .name                   = "i2c-gpio",
-       .id                     = 0,
-       .dev.platform_data      = &pdata,
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       at91_set_GPIO_periph(AT91_PIN_PA23, 1);         /* TWD (SDA) */
-       at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-       at91_set_GPIO_periph(AT91_PIN_PA24, 1);         /* TWCK (SCL) */
-       at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9rl_twi_device);
-}
-
-#elif defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
-
-static struct resource twi_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_TWI0,
-               .end    = AT91SAM9RL_BASE_TWI0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_twi_device = {
-       .name           = "i2c-at91sam9g20",
-       .id             = 0,
-       .resource       = twi_resources,
-       .num_resources  = ARRAY_SIZE(twi_resources),
-};
-
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
-{
-       /* pins used for TWI interface */
-       at91_set_A_periph(AT91_PIN_PA23, 0);            /* TWD */
-       at91_set_multi_drive(AT91_PIN_PA23, 1);
-
-       at91_set_A_periph(AT91_PIN_PA24, 0);            /* TWCK */
-       at91_set_multi_drive(AT91_PIN_PA24, 1);
-
-       i2c_register_board_info(0, devices, nr_devices);
-       platform_device_register(&at91sam9rl_twi_device);
-}
-#else
-void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SPI
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-static u64 spi_dmamask = DMA_BIT_MASK(32);
-
-static struct resource spi_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_SPI,
-               .end    = AT91SAM9RL_BASE_SPI + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_spi_device = {
-       .name           = "atmel_spi",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &spi_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = spi_resources,
-       .num_resources  = ARRAY_SIZE(spi_resources),
-};
-
-static const unsigned spi_standard_cs[4] = { AT91_PIN_PA28, AT91_PIN_PB7, AT91_PIN_PD8, AT91_PIN_PD9 };
-
-
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
-{
-       int i;
-       unsigned long cs_pin;
-
-       at91_set_A_periph(AT91_PIN_PA25, 0);    /* MISO */
-       at91_set_A_periph(AT91_PIN_PA26, 0);    /* MOSI */
-       at91_set_A_periph(AT91_PIN_PA27, 0);    /* SPCK */
-
-       /* Enable SPI chip-selects */
-       for (i = 0; i < nr_devices; i++) {
-               if (devices[i].controller_data)
-                       cs_pin = (unsigned long) devices[i].controller_data;
-               else
-                       cs_pin = spi_standard_cs[devices[i].chip_select];
-
-               if (!gpio_is_valid(cs_pin))
-                       continue;
-
-               /* enable chip-select pin */
-               at91_set_gpio_output(cs_pin, 1);
-
-               /* pass chip-select pin to driver */
-               devices[i].controller_data = (void *) cs_pin;
-       }
-
-       spi_register_board_info(devices, nr_devices);
-       platform_device_register(&at91sam9rl_spi_device);
-}
-#else
-void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  AC97
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SND_ATMEL_AC97C) || defined(CONFIG_SND_ATMEL_AC97C_MODULE)
-static u64 ac97_dmamask = DMA_BIT_MASK(32);
-static struct ac97c_platform_data ac97_data;
-
-static struct resource ac97_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_AC97C,
-               .end    = AT91SAM9RL_BASE_AC97C + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_ac97_device = {
-       .name           = "atmel_ac97c",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &ac97_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &ac97_data,
-       },
-       .resource       = ac97_resources,
-       .num_resources  = ARRAY_SIZE(ac97_resources),
-};
-
-void __init at91_add_device_ac97(struct ac97c_platform_data *data)
-{
-       if (!data)
-               return;
-
-       at91_set_A_periph(AT91_PIN_PD1, 0);     /* AC97FS */
-       at91_set_A_periph(AT91_PIN_PD2, 0);     /* AC97CK */
-       at91_set_A_periph(AT91_PIN_PD3, 0);     /* AC97TX */
-       at91_set_A_periph(AT91_PIN_PD4, 0);     /* AC97RX */
-
-       /* reset */
-       if (gpio_is_valid(data->reset_pin))
-               at91_set_gpio_output(data->reset_pin, 0);
-
-       ac97_data = *data;
-       platform_device_register(&at91sam9rl_ac97_device);
-}
-#else
-void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  LCD Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_pdata lcdc_data;
-
-static struct resource lcdc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_LCDC_BASE,
-               .end    = AT91SAM9RL_LCDC_BASE + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91_lcdc_device = {
-       .name           = "at91sam9rl-lcdfb",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &lcdc_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &lcdc_data,
-       },
-       .resource       = lcdc_resources,
-       .num_resources  = ARRAY_SIZE(lcdc_resources),
-};
-
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
-{
-       if (!data) {
-               return;
-       }
-
-       at91_set_B_periph(AT91_PIN_PC1, 0);     /* LCDPWR */
-       at91_set_A_periph(AT91_PIN_PC5, 0);     /* LCDHSYNC */
-       at91_set_A_periph(AT91_PIN_PC6, 0);     /* LCDDOTCK */
-       at91_set_A_periph(AT91_PIN_PC7, 0);     /* LCDDEN */
-       at91_set_A_periph(AT91_PIN_PC3, 0);     /* LCDCC */
-       at91_set_B_periph(AT91_PIN_PC9, 0);     /* LCDD3 */
-       at91_set_B_periph(AT91_PIN_PC10, 0);    /* LCDD4 */
-       at91_set_B_periph(AT91_PIN_PC11, 0);    /* LCDD5 */
-       at91_set_B_periph(AT91_PIN_PC12, 0);    /* LCDD6 */
-       at91_set_B_periph(AT91_PIN_PC13, 0);    /* LCDD7 */
-       at91_set_B_periph(AT91_PIN_PC15, 0);    /* LCDD11 */
-       at91_set_B_periph(AT91_PIN_PC16, 0);    /* LCDD12 */
-       at91_set_B_periph(AT91_PIN_PC17, 0);    /* LCDD13 */
-       at91_set_B_periph(AT91_PIN_PC18, 0);    /* LCDD14 */
-       at91_set_B_periph(AT91_PIN_PC19, 0);    /* LCDD15 */
-       at91_set_B_periph(AT91_PIN_PC20, 0);    /* LCDD18 */
-       at91_set_B_periph(AT91_PIN_PC21, 0);    /* LCDD19 */
-       at91_set_B_periph(AT91_PIN_PC22, 0);    /* LCDD20 */
-       at91_set_B_periph(AT91_PIN_PC23, 0);    /* LCDD21 */
-       at91_set_B_periph(AT91_PIN_PC24, 0);    /* LCDD22 */
-       at91_set_B_periph(AT91_PIN_PC25, 0);    /* LCDD23 */
-
-       lcdc_data = *data;
-       platform_device_register(&at91_lcdc_device);
-}
-#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  Timer/Counter block
- * -------------------------------------------------------------------- */
-
-#ifdef CONFIG_ATMEL_TCLIB
-
-static struct resource tcb_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_TCB0,
-               .end    = AT91SAM9RL_BASE_TCB0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_tcb_device = {
-       .name           = "atmel_tcb",
-       .id             = 0,
-       .resource       = tcb_resources,
-       .num_resources  = ARRAY_SIZE(tcb_resources),
-};
-
-static void __init at91_add_device_tc(void)
-{
-       platform_device_register(&at91sam9rl_tcb_device);
-}
-#else
-static void __init at91_add_device_tc(void) { }
-#endif
-
-
-/* --------------------------------------------------------------------
- *  ADC and Touchscreen
- * -------------------------------------------------------------------- */
-
-#if IS_ENABLED(CONFIG_AT91_ADC)
-static struct at91_adc_data adc_data;
-
-static struct resource adc_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_TSC,
-               .end    = AT91SAM9RL_BASE_TSC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static struct platform_device at91_adc_device = {
-       .name           = "at91sam9rl-adc",
-       .id             = -1,
-       .dev            = {
-               .platform_data  = &adc_data,
-       },
-       .resource       = adc_resources,
-       .num_resources  = ARRAY_SIZE(adc_resources),
-};
-
-static struct at91_adc_trigger at91_adc_triggers[] = {
-       [0] = {
-               .name = "external-rising",
-               .value = 1,
-               .is_external = true,
-       },
-       [1] = {
-               .name = "external-falling",
-               .value = 2,
-               .is_external = true,
-       },
-       [2] = {
-               .name = "external-any",
-               .value = 3,
-               .is_external = true,
-       },
-       [3] = {
-               .name = "continuous",
-               .value = 6,
-               .is_external = false,
-       },
-};
-
-void __init at91_add_device_adc(struct at91_adc_data *data)
-{
-       if (!data)
-               return;
-
-       if (test_bit(0, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PA17, 0);
-       if (test_bit(1, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PA18, 0);
-       if (test_bit(2, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PA19, 0);
-       if (test_bit(3, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PA20, 0);
-       if (test_bit(4, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PD6, 0);
-       if (test_bit(5, &data->channels_used))
-               at91_set_A_periph(AT91_PIN_PD7, 0);
-
-       if (data->use_external_triggers)
-               at91_set_A_periph(AT91_PIN_PB15, 0);
-
-       data->startup_time = 40;
-       data->trigger_number = 4;
-       data->trigger_list = at91_adc_triggers;
-
-       adc_data = *data;
-       platform_device_register(&at91_adc_device);
-}
-#else
-void __init at91_add_device_adc(struct at91_adc_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
- *  RTC
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE)
-static struct platform_device at91sam9rl_rtc_device = {
-       .name           = "at91_rtc",
-       .id             = -1,
-       .num_resources  = 0,
-};
-
-static void __init at91_add_device_rtc(void)
-{
-       platform_device_register(&at91sam9rl_rtc_device);
-}
-#else
-static void __init at91_add_device_rtc(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  RTT
- * -------------------------------------------------------------------- */
-
-static struct resource rtt_resources[] = {
-       {
-               .start  = AT91SAM9RL_BASE_RTT,
-               .end    = AT91SAM9RL_BASE_RTT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .flags  = IORESOURCE_IRQ,
-       }
-};
-
-static struct platform_device at91sam9rl_rtt_device = {
-       .name           = "at91_rtt",
-       .id             = 0,
-       .resource       = rtt_resources,
-};
-
-#if IS_ENABLED(CONFIG_RTC_DRV_AT91SAM9)
-static void __init at91_add_device_rtt_rtc(void)
-{
-       at91sam9rl_rtt_device.name = "rtc-at91sam9";
-       /*
-        * The second resource is needed:
-        * GPBR will serve as the storage for RTC time offset
-        */
-       at91sam9rl_rtt_device.num_resources = 3;
-       rtt_resources[1].start = AT91SAM9RL_BASE_GPBR +
-                                4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
-       rtt_resources[1].end = rtt_resources[1].start + 3;
-       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
-       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
-}
-#else
-static void __init at91_add_device_rtt_rtc(void)
-{
-       /* Only one resource is needed: RTT not used as RTC */
-       at91sam9rl_rtt_device.num_resources = 1;
-}
-#endif
-
-static void __init at91_add_device_rtt(void)
-{
-       at91_add_device_rtt_rtc();
-       platform_device_register(&at91sam9rl_rtt_device);
-}
-
-
-/* --------------------------------------------------------------------
- *  Watchdog
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
-static struct resource wdt_resources[] = {
-       {
-               .start  = AT91SAM9RL_BASE_WDT,
-               .end    = AT91SAM9RL_BASE_WDT + SZ_16 - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device at91sam9rl_wdt_device = {
-       .name           = "at91_wdt",
-       .id             = -1,
-       .resource       = wdt_resources,
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-};
-
-static void __init at91_add_device_watchdog(void)
-{
-       platform_device_register(&at91sam9rl_wdt_device);
-}
-#else
-static void __init at91_add_device_watchdog(void) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  PWM
- * --------------------------------------------------------------------*/
-
-#if IS_ENABLED(CONFIG_PWM_ATMEL)
-static struct resource pwm_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_PWMC,
-               .end    = AT91SAM9RL_BASE_PWMC + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_pwm0_device = {
-       .name   = "at91sam9rl-pwm",
-       .id     = -1,
-       .resource       = pwm_resources,
-       .num_resources  = ARRAY_SIZE(pwm_resources),
-};
-
-void __init at91_add_device_pwm(u32 mask)
-{
-       if (mask & (1 << AT91_PWM0))
-               at91_set_B_periph(AT91_PIN_PB8, 1);     /* enable PWM0 */
-
-       if (mask & (1 << AT91_PWM1))
-               at91_set_B_periph(AT91_PIN_PB9, 1);     /* enable PWM1 */
-
-       if (mask & (1 << AT91_PWM2))
-               at91_set_B_periph(AT91_PIN_PD5, 1);     /* enable PWM2 */
-
-       if (mask & (1 << AT91_PWM3))
-               at91_set_B_periph(AT91_PIN_PD8, 1);     /* enable PWM3 */
-
-       platform_device_register(&at91sam9rl_pwm0_device);
-}
-#else
-void __init at91_add_device_pwm(u32 mask) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  SSC -- Synchronous Serial Controller
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_ATMEL_SSC) || defined(CONFIG_ATMEL_SSC_MODULE)
-static u64 ssc0_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_SSC0,
-               .end    = AT91SAM9RL_BASE_SSC0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_ssc0_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 0,
-       .dev    = {
-               .dma_mask               = &ssc0_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc0_resources,
-       .num_resources  = ARRAY_SIZE(ssc0_resources),
-};
-
-static inline void configure_ssc0_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_A_periph(AT91_PIN_PC0, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_A_periph(AT91_PIN_PC1, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_A_periph(AT91_PIN_PA15, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_A_periph(AT91_PIN_PA16, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_B_periph(AT91_PIN_PA10, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_B_periph(AT91_PIN_PA22, 1);
-}
-
-static u64 ssc1_dmamask = DMA_BIT_MASK(32);
-
-static struct resource ssc1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_SSC1,
-               .end    = AT91SAM9RL_BASE_SSC1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device at91sam9rl_ssc1_device = {
-       .name   = "at91rm9200_ssc",
-       .id     = 1,
-       .dev    = {
-               .dma_mask               = &ssc1_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .resource       = ssc1_resources,
-       .num_resources  = ARRAY_SIZE(ssc1_resources),
-};
-
-static inline void configure_ssc1_pins(unsigned pins)
-{
-       if (pins & ATMEL_SSC_TF)
-               at91_set_B_periph(AT91_PIN_PA29, 1);
-       if (pins & ATMEL_SSC_TK)
-               at91_set_B_periph(AT91_PIN_PA30, 1);
-       if (pins & ATMEL_SSC_TD)
-               at91_set_B_periph(AT91_PIN_PA13, 1);
-       if (pins & ATMEL_SSC_RD)
-               at91_set_B_periph(AT91_PIN_PA14, 1);
-       if (pins & ATMEL_SSC_RK)
-               at91_set_B_periph(AT91_PIN_PA9, 1);
-       if (pins & ATMEL_SSC_RF)
-               at91_set_B_periph(AT91_PIN_PA8, 1);
-}
-
-/*
- * SSC controllers are accessed through library code, instead of any
- * kind of all-singing/all-dancing driver.  For example one could be
- * used by a particular I2S audio codec's driver, while another one
- * on the same system might be used by a custom data capture driver.
- */
-void __init at91_add_device_ssc(unsigned id, unsigned pins)
-{
-       struct platform_device *pdev;
-
-       /*
-        * NOTE: caller is responsible for passing information matching
-        * "pins" to whatever will be using each particular controller.
-        */
-       switch (id) {
-       case AT91SAM9RL_ID_SSC0:
-               pdev = &at91sam9rl_ssc0_device;
-               configure_ssc0_pins(pins);
-               break;
-       case AT91SAM9RL_ID_SSC1:
-               pdev = &at91sam9rl_ssc1_device;
-               configure_ssc1_pins(pins);
-               break;
-       default:
-               return;
-       }
-
-       platform_device_register(pdev);
-}
-
-#else
-void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
-#endif
-
-
-/* --------------------------------------------------------------------
- *  UART
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_SERIAL_ATMEL)
-static struct resource dbgu_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_DBGU,
-               .end    = AT91SAM9RL_BASE_DBGU + SZ_512 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data dbgu_data = {
-       .use_dma_tx     = 0,
-       .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-};
-
-static u64 dbgu_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_dbgu_device = {
-       .name           = "atmel_usart",
-       .id             = 0,
-       .dev            = {
-                               .dma_mask               = &dbgu_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &dbgu_data,
-       },
-       .resource       = dbgu_resources,
-       .num_resources  = ARRAY_SIZE(dbgu_resources),
-};
-
-static inline void configure_dbgu_pins(void)
-{
-       at91_set_A_periph(AT91_PIN_PA21, 0);            /* DRXD */
-       at91_set_A_periph(AT91_PIN_PA22, 1);            /* DTXD */
-}
-
-static struct resource uart0_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_US0,
-               .end    = AT91SAM9RL_BASE_US0 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart0_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart0_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart0_device = {
-       .name           = "atmel_usart",
-       .id             = 1,
-       .dev            = {
-                               .dma_mask               = &uart0_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart0_data,
-       },
-       .resource       = uart0_resources,
-       .num_resources  = ARRAY_SIZE(uart0_resources),
-};
-
-static inline void configure_usart0_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PA6, 1);             /* TXD0 */
-       at91_set_A_periph(AT91_PIN_PA7, 0);             /* RXD0 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PA9, 0);     /* RTS0 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PA10, 0);    /* CTS0 */
-       if (pins & ATMEL_UART_DSR)
-               at91_set_A_periph(AT91_PIN_PD14, 0);    /* DSR0 */
-       if (pins & ATMEL_UART_DTR)
-               at91_set_A_periph(AT91_PIN_PD15, 0);    /* DTR0 */
-       if (pins & ATMEL_UART_DCD)
-               at91_set_A_periph(AT91_PIN_PD16, 0);    /* DCD0 */
-       if (pins & ATMEL_UART_RI)
-               at91_set_A_periph(AT91_PIN_PD17, 0);    /* RI0 */
-}
-
-static struct resource uart1_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_US1,
-               .end    = AT91SAM9RL_BASE_US1 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart1_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart1_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart1_device = {
-       .name           = "atmel_usart",
-       .id             = 2,
-       .dev            = {
-                               .dma_mask               = &uart1_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart1_data,
-       },
-       .resource       = uart1_resources,
-       .num_resources  = ARRAY_SIZE(uart1_resources),
-};
-
-static inline void configure_usart1_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PA11, 1);            /* TXD1 */
-       at91_set_A_periph(AT91_PIN_PA12, 0);            /* RXD1 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PA18, 0);    /* RTS1 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PA19, 0);    /* CTS1 */
-}
-
-static struct resource uart2_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_US2,
-               .end    = AT91SAM9RL_BASE_US2 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart2_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart2_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart2_device = {
-       .name           = "atmel_usart",
-       .id             = 3,
-       .dev            = {
-                               .dma_mask               = &uart2_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart2_data,
-       },
-       .resource       = uart2_resources,
-       .num_resources  = ARRAY_SIZE(uart2_resources),
-};
-
-static inline void configure_usart2_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PA13, 1);            /* TXD2 */
-       at91_set_A_periph(AT91_PIN_PA14, 0);            /* RXD2 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_A_periph(AT91_PIN_PA29, 0);    /* RTS2 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_A_periph(AT91_PIN_PA30, 0);    /* CTS2 */
-}
-
-static struct resource uart3_resources[] = {
-       [0] = {
-               .start  = AT91SAM9RL_BASE_US3,
-               .end    = AT91SAM9RL_BASE_US3 + SZ_16K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
-               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct atmel_uart_data uart3_data = {
-       .use_dma_tx     = 1,
-       .use_dma_rx     = 1,
-};
-
-static u64 uart3_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device at91sam9rl_uart3_device = {
-       .name           = "atmel_usart",
-       .id             = 4,
-       .dev            = {
-                               .dma_mask               = &uart3_dmamask,
-                               .coherent_dma_mask      = DMA_BIT_MASK(32),
-                               .platform_data          = &uart3_data,
-       },
-       .resource       = uart3_resources,
-       .num_resources  = ARRAY_SIZE(uart3_resources),
-};
-
-static inline void configure_usart3_pins(unsigned pins)
-{
-       at91_set_A_periph(AT91_PIN_PB0, 1);             /* TXD3 */
-       at91_set_A_periph(AT91_PIN_PB1, 0);             /* RXD3 */
-
-       if (pins & ATMEL_UART_RTS)
-               at91_set_B_periph(AT91_PIN_PD4, 0);     /* RTS3 */
-       if (pins & ATMEL_UART_CTS)
-               at91_set_B_periph(AT91_PIN_PD3, 0);     /* CTS3 */
-}
-
-static struct platform_device *__initdata at91_uarts[ATMEL_MAX_UART];  /* the UARTs to use */
-
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins)
-{
-       struct platform_device *pdev;
-       struct atmel_uart_data *pdata;
-
-       switch (id) {
-               case 0:         /* DBGU */
-                       pdev = &at91sam9rl_dbgu_device;
-                       configure_dbgu_pins();
-                       break;
-               case AT91SAM9RL_ID_US0:
-                       pdev = &at91sam9rl_uart0_device;
-                       configure_usart0_pins(pins);
-                       break;
-               case AT91SAM9RL_ID_US1:
-                       pdev = &at91sam9rl_uart1_device;
-                       configure_usart1_pins(pins);
-                       break;
-               case AT91SAM9RL_ID_US2:
-                       pdev = &at91sam9rl_uart2_device;
-                       configure_usart2_pins(pins);
-                       break;
-               case AT91SAM9RL_ID_US3:
-                       pdev = &at91sam9rl_uart3_device;
-                       configure_usart3_pins(pins);
-                       break;
-               default:
-                       return;
-       }
-       pdata = pdev->dev.platform_data;
-       pdata->num = portnr;            /* update to mapped ID */
-
-       if (portnr < ATMEL_MAX_UART)
-               at91_uarts[portnr] = pdev;
-}
-
-void __init at91_add_device_serial(void)
-{
-       int i;
-
-       for (i = 0; i < ATMEL_MAX_UART; i++) {
-               if (at91_uarts[i])
-                       platform_device_register(at91_uarts[i]);
-       }
-}
-#else
-void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
-void __init at91_add_device_serial(void) {}
-#endif
-
-
-/* -------------------------------------------------------------------- */
-
-/*
- * These devices are always present and don't need any board-specific
- * setup.
- */
-static int __init at91_add_standard_devices(void)
-{
-       at91_add_device_hdmac();
-       at91_add_device_rtc();
-       at91_add_device_rtt();
-       at91_add_device_watchdog();
-       at91_add_device_tc();
-       return 0;
-}
-
-arch_initcall(at91_add_standard_devices);
index 028268ff3722c3589009cd81a7dab38186cefdc8..f0d5a69a7237d66b5936906bb7196546d0a1b48e 100644 (file)
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk/at91_pmc.h>
+#include <asm/system_misc.h>
+#include <mach/hardware.h>
 
-#include <asm/irq.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/at91sam9x5.h>
-#include <mach/cpu.h>
-
-#include "board.h"
 #include "soc.h"
 #include "generic.h"
-#include "sam9_smc.h"
-
-#if defined(CONFIG_OLD_CLK_AT91)
-#include "clock.h"
-/* --------------------------------------------------------------------
- *  Clocks
- * -------------------------------------------------------------------- */
-
-/*
- * The peripheral clocks.
- */
-static struct clk pioAB_clk = {
-       .name           = "pioAB_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_PIOAB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pioCD_clk = {
-       .name           = "pioCD_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_PIOCD,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk smd_clk = {
-       .name           = "smd_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_SMD,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart0_clk = {
-       .name           = "usart0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_USART0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart1_clk = {
-       .name           = "usart1_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_USART1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk usart2_clk = {
-       .name           = "usart2_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_USART2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* USART3 clock - Only for sam9g25/sam9x25 */
-static struct clk usart3_clk = {
-       .name           = "usart3_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_USART3,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi0_clk = {
-       .name           = "twi0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_TWI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi1_clk = {
-       .name           = "twi1_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_TWI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk twi2_clk = {
-       .name           = "twi2_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_TWI2,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc0_clk = {
-       .name           = "mci0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_MCI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi0_clk = {
-       .name           = "spi0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_SPI0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk spi1_clk = {
-       .name           = "spi1_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_SPI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uart0_clk = {
-       .name           = "uart0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_UART0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uart1_clk = {
-       .name           = "uart1_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_UART1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk tcb0_clk = {
-       .name           = "tcb0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_TCB,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk pwm_clk = {
-       .name           = "pwm_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_PWM,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk adc_clk = {
-       .name           = "adc_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_ADC,
-       .type   = CLK_TYPE_PERIPHERAL,
-};
-static struct clk adc_op_clk = {
-       .name           = "adc_op_clk",
-       .type           = CLK_TYPE_PERIPHERAL,
-       .rate_hz        = 5000000,
-};
-static struct clk dma0_clk = {
-       .name           = "dma0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_DMA0,
-       .type   = CLK_TYPE_PERIPHERAL,
-};
-static struct clk dma1_clk = {
-       .name           = "dma1_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_DMA1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk uhphs_clk = {
-       .name           = "uhphs",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_UHPHS,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk udphs_clk = {
-       .name           = "udphs_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_UDPHS,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* emac0 clock - Only for sam9g25/sam9x25/sam9g35/sam9x35 */
-static struct clk macb0_clk = {
-       .name           = "pclk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_EMAC0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* lcd clock - Only for sam9g15/sam9g35/sam9x35 */
-static struct clk lcdc_clk = {
-       .name           = "lcdc_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_LCDC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* isi clock - Only for sam9g25 */
-static struct clk isi_clk = {
-       .name           = "isi_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_ISI,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk mmc1_clk = {
-       .name           = "mci1_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_MCI1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* emac1 clock - Only for sam9x25 */
-static struct clk macb1_clk = {
-       .name           = "pclk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_EMAC1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-static struct clk ssc_clk = {
-       .name           = "ssc_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_SSC,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* can0 clock - Only for sam9x35 */
-static struct clk can0_clk = {
-       .name           = "can0_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_CAN0,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-/* can1 clock - Only for sam9x35 */
-static struct clk can1_clk = {
-       .name           = "can1_clk",
-       .pmc_mask       = 1 << AT91SAM9X5_ID_CAN1,
-       .type           = CLK_TYPE_PERIPHERAL,
-};
-
-static struct clk *periph_clocks[] __initdata = {
-       &pioAB_clk,
-       &pioCD_clk,
-       &smd_clk,
-       &usart0_clk,
-       &usart1_clk,
-       &usart2_clk,
-       &twi0_clk,
-       &twi1_clk,
-       &twi2_clk,
-       &mmc0_clk,
-       &spi0_clk,
-       &spi1_clk,
-       &uart0_clk,
-       &uart1_clk,
-       &tcb0_clk,
-       &pwm_clk,
-       &adc_clk,
-       &adc_op_clk,
-       &dma0_clk,
-       &dma1_clk,
-       &uhphs_clk,
-       &udphs_clk,
-       &mmc1_clk,
-       &ssc_clk,
-       // irq0
-};
-
-static struct clk_lookup periph_clocks_lookups[] = {
-       /* lookup table for DT entries */
-       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
-       CLKDEV_CON_DEV_ID("usart", "f801c000.serial", &usart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8040000.serial", &uart0_clk),
-       CLKDEV_CON_DEV_ID("usart", "f8044000.serial", &uart1_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
-       CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
-       CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
-       CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
-       CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "f0010000.ssc", &ssc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "f0000000.spi", &spi0_clk),
-       CLKDEV_CON_DEV_ID("spi_clk", "f0004000.spi", &spi1_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff400.gpio", &pioAB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioAB_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioCD_clk),
-       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioCD_clk),
-       /* additional fake clock for macb_hclk */
-       CLKDEV_CON_DEV_ID("hclk", "f802c000.ethernet", &macb0_clk),
-       CLKDEV_CON_DEV_ID("hclk", "f8030000.ethernet", &macb1_clk),
-       CLKDEV_CON_DEV_ID("hclk", "600000.ohci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("ohci_clk", "600000.ohci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("ehci_clk", "700000.ehci", &uhphs_clk),
-       CLKDEV_CON_DEV_ID("hclk", "500000.gadget", &utmi_clk),
-       CLKDEV_CON_DEV_ID("pclk", "500000.gadget", &udphs_clk),
-       CLKDEV_CON_DEV_ID(NULL, "f8034000.pwm", &pwm_clk),
-};
-
-/*
- * The two programmable clocks.
- * You must configure pin multiplexing to bring these signals out.
- */
-static struct clk pck0 = {
-       .name           = "pck0",
-       .pmc_mask       = AT91_PMC_PCK0,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 0,
-};
-static struct clk pck1 = {
-       .name           = "pck1",
-       .pmc_mask       = AT91_PMC_PCK1,
-       .type           = CLK_TYPE_PROGRAMMABLE,
-       .id             = 1,
-};
-
-static void __init at91sam9x5_register_clocks(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
-               clk_register(periph_clocks[i]);
-
-       clkdev_add_table(periph_clocks_lookups,
-                        ARRAY_SIZE(periph_clocks_lookups));
-
-       if (cpu_is_at91sam9g25()
-       || cpu_is_at91sam9x25())
-               clk_register(&usart3_clk);
-
-       if (cpu_is_at91sam9g25()
-       || cpu_is_at91sam9x25()
-       || cpu_is_at91sam9g35()
-       || cpu_is_at91sam9x35())
-               clk_register(&macb0_clk);
-
-       if (cpu_is_at91sam9g15()
-       || cpu_is_at91sam9g35()
-       || cpu_is_at91sam9x35())
-               clk_register(&lcdc_clk);
-
-       if (cpu_is_at91sam9g25())
-               clk_register(&isi_clk);
-
-       if (cpu_is_at91sam9x25())
-               clk_register(&macb1_clk);
-
-       if (cpu_is_at91sam9x25()
-       || cpu_is_at91sam9x35()) {
-               clk_register(&can0_clk);
-               clk_register(&can1_clk);
-       }
-
-       clk_register(&pck0);
-       clk_register(&pck1);
-}
-#else
-#define at91sam9x5_register_clocks     NULL
-#endif
 
 /* --------------------------------------------------------------------
  *  AT91SAM9x5 processor initialization
@@ -338,6 +32,5 @@ static void __init at91sam9x5_initialize(void)
 
 AT91_SOC_START(at91sam9x5)
        .map_io = at91sam9x5_map_io,
-       .register_clocks = at91sam9x5_register_clocks,
        .init = at91sam9x5_initialize,
 AT91_SOC_END
diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
deleted file mode 100644 (file)
index 7523f1c..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * arch/arm/mach-at91/at91x40.c
- *
- * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
- * Copyright (C) 2005 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/proc-fns.h>
-#include <asm/system_misc.h>
-#include <asm/mach/arch.h>
-#include <mach/at91x40.h>
-#include <mach/at91_st.h>
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "generic.h"
-
-/*
- * Export the clock functions for the AT91X40. Some external code common
- * to all AT91 family parts relys on this, like the gpio and serial support.
- */
-int clk_enable(struct clk *clk)
-{
-       return 0;
-}
-
-void clk_disable(struct clk *clk)
-{
-}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       return AT91X40_MASTER_CLOCK;
-}
-
-static void at91x40_idle(void)
-{
-       /*
-        * Disable the processor clock.  The processor will be automatically
-        * re-enabled by an interrupt or by a reset.
-        */
-       __raw_writel(AT91_PS_CR_CPU, AT91_IO_P2V(AT91_PS_CR));
-       cpu_do_idle();
-}
-
-void __init at91x40_initialize(unsigned long main_clock)
-{
-       arm_pm_idle = at91x40_idle;
-}
-
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91x40_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller (FIQ) */
-       0,      /* System Peripherals */
-       0,      /* USART 0 */
-       0,      /* USART 1 */
-       2,      /* Timer Counter 0 */
-       2,      /* Timer Counter 1 */
-       2,      /* Timer Counter 2 */
-       0,      /* Watchdog timer */
-       0,      /* Parallel IO Controller A */
-       0,      /* Reserved */
-       0,      /* Reserved */
-       0,      /* Reserved */
-       0,      /* Reserved */
-       0,      /* Reserved */
-       0,      /* Reserved */
-       0,      /* Reserved */
-       0,      /* External IRQ0 */
-       0,      /* External IRQ1 */
-       0,      /* External IRQ2 */
-};
-
-void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])
-{
-       u32  extern_irq = (1 << AT91X40_ID_IRQ0) | (1 << AT91X40_ID_IRQ1)
-                       | (1 << AT91X40_ID_IRQ2);
-       if (!priority)
-               priority = at91x40_default_irq_priority;
-
-       at91_aic_init(priority, extern_irq);
-}
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
deleted file mode 100644 (file)
index 07d0bf2..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * arch/arm/mach-at91/at91x40_time.c
- *
- * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.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
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/time.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/at91x40.h>
-#include <asm/mach/time.h>
-
-#include "at91_tc.h"
-
-#define at91_tc_read(field) \
-       __raw_readl(AT91_IO_P2V(AT91_TC) + field)
-
-#define at91_tc_write(field, value) \
-       __raw_writel(value, AT91_IO_P2V(AT91_TC) + field)
-
-/*
- *     3 counter/timer units present.
- */
-#define        AT91_TC_CLK0BASE        0
-#define        AT91_TC_CLK1BASE        0x40
-#define        AT91_TC_CLK2BASE        0x80
-
-static u32 at91x40_gettimeoffset(void)
-{
-       return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 /
-               (AT91X40_MASTER_CLOCK / 128)) * 1000;
-}
-
-static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id)
-{
-       at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_SR);
-       timer_tick();
-       return IRQ_HANDLED;
-}
-
-static struct irqaction at91x40_timer_irq = {
-       .name           = "at91_tick",
-       .flags          = IRQF_TIMER,
-       .handler        = at91x40_timer_interrupt
-};
-
-void __init at91x40_timer_init(void)
-{
-       unsigned int v;
-
-       arch_gettimeoffset = at91x40_gettimeoffset;
-
-       at91_tc_write(AT91_TC_BCR, 0);
-       v = at91_tc_read(AT91_TC_BMR);
-       v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE;
-       at91_tc_write(AT91_TC_BMR, v);
-
-       at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CCR, AT91_TC_CLKDIS);
-       at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CMR, (AT91_TC_TIMER_CLOCK4 | AT91_TC_CPCTRG));
-       at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_IDR, 0xffffffff);
-       at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_RC, (AT91X40_MASTER_CLOCK / 128) / HZ - 1);
-       at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_IER, (1<<4));
-
-       setup_irq(AT91X40_ID_TC1, &at91x40_timer_irq);
-
-       at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN));
-}
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
deleted file mode 100644 (file)
index 3f6dbcc..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-1arm.c
- *
- *  Copyright (C) 2005 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
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/cpu.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-static void __init onearm_init_early(void)
-{
-       /* Set cpu type: PQFP */
-       at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata onearm_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC4,
-       .is_rmii        = 1,
-};
-
-static struct at91_usbh_data __initdata onearm_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata onearm_udc_data = {
-       .vbus_pin       = AT91_PIN_PC2,
-       .pullup_pin     = AT91_PIN_PC3,
-};
-
-static void __init onearm_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
-       /* USART1 on ttyS2 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                          | ATMEL_UART_RI);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&onearm_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&onearm_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&onearm_udc_data);
-}
-
-MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
-       /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = onearm_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = onearm_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
deleted file mode 100644 (file)
index e76e35c..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-afeb-9260v1.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *  Copyright (C) 2008 Sergey Lapin
- *
- * A custom board designed as open hardware; PCBs and various information
- * is available at http://groups.google.com/group/arm9fpga-evolution-board/
- * Subversion repository: svn://194.85.238.22/home/users/george/svn/arm9eb
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init afeb9260_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata afeb9260_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata afeb9260_udc_data = {
-       .vbus_pin       = AT91_PIN_PC5,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info afeb9260_spi_devices[] = {
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 1,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata afeb9260_macb_data = {
-       .phy_irq_pin    = AT91_PIN_PA9,
-       .is_rmii        = 0,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata afeb9260_nand_partition[] = {
-       {
-               .name   = "bootloader",
-               .offset = 0,
-               .size   = (640 * SZ_1K),
-       },
-       {
-               .name   = "kernel",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = SZ_2M,
-       },
-       {
-               .name   = "rootfs",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata afeb9260_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-       .bus_width_16   = 0,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .parts          = afeb9260_nand_partition,
-       .num_parts      = ARRAY_SIZE(afeb9260_nand_partition),
-       .det_pin        = -EINVAL,
-};
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct mci_platform_data __initdata afeb9260_mci0_data = {
-       .slot[1] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PC9,
-               .wp_pin         = AT91_PIN_PC4,
-       },
-};
-
-
-
-static struct i2c_board_info __initdata afeb9260_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("tlv320aic23", 0x1a),
-       }, {
-               I2C_BOARD_INFO("fm3130", 0x68),
-       }, {
-               I2C_BOARD_INFO("24c64", 0x50),
-       },
-};
-
-/*
- * IDE (CF True IDE mode)
- */
-static struct at91_cf_data afeb9260_cf_data = {
-       .chipselect = 4,
-       .irq_pin    = AT91_PIN_PA6,
-       .det_pin        = -EINVAL,
-       .vcc_pin        = -EINVAL,
-       .rst_pin    = AT91_PIN_PA7,
-       .flags      = AT91_CF_TRUE_IDE,
-};
-
-static void __init afeb9260_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1,
-                            ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR
-                          | ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9260_ID_US1, 2,
-                       ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&afeb9260_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&afeb9260_udc_data);
-       /* SPI */
-       at91_add_device_spi(afeb9260_spi_devices,
-                       ARRAY_SIZE(afeb9260_spi_devices));
-       /* NAND */
-       at91_add_device_nand(&afeb9260_nand_data);
-       /* Ethernet */
-       at91_add_device_eth(&afeb9260_macb_data);
-
-       /* Standard function's pin assignments are not
-        * appropriate for us and generic code provide
-        * no API to configure these pins any other way */
-       at91_set_B_periph(AT91_PIN_PA10, 0);    /* ETX2 */
-       at91_set_B_periph(AT91_PIN_PA11, 0);    /* ETX3 */
-       /* MMC */
-       at91_add_device_mci(0, &afeb9260_mci0_data);
-       /* I2C */
-       at91_add_device_i2c(afeb9260_i2c_devices,
-                       ARRAY_SIZE(afeb9260_i2c_devices));
-       /* Audio */
-       at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
-       /* IDE */
-       at91_add_device_cf(&afeb9260_cf_data);
-}
-
-MACHINE_START(AFEB9260, "Custom afeb9260 board")
-       /* Maintainer: Sergey Lapin <slapin@ossfans.org> */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = afeb9260_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = afeb9260_board_init,
-MACHINE_END
-
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
deleted file mode 100644 (file)
index ae827dd..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * KwikByte CAM60 (KB9260)
- *
- * based on board-sam9260ek.c
- *   Copyright (C) 2005 SAN People
- *   Copyright (C) 2006 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/flash.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/at91sam9_smc.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init cam60_init_early(void)
-{
-       /* Initialize processor: 10 MHz crystal */
-       at91_initialize(10000000);
-}
-
-/*
- * USB Host
- */
-static struct at91_usbh_data __initdata cam60_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-
-/*
- * SPI devices.
- */
-#if defined(CONFIG_MTD_DATAFLASH)
-static struct mtd_partition cam60_spi_partitions[] = {
-       {
-               .name   = "BOOT1",
-               .offset = 0,
-               .size   = 4 * 1056,
-       },
-       {
-               .name   = "BOOT2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 256 * 1056,
-       },
-       {
-               .name   = "kernel",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 2222 * 1056,
-       },
-       {
-               .name   = "file system",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct flash_platform_data cam60_spi_flash_platform_data = {
-       .name           = "spi_flash",
-       .parts          = cam60_spi_partitions,
-       .nr_parts       = ARRAY_SIZE(cam60_spi_partitions)
-};
-#endif
-
-static struct spi_board_info cam60_spi_devices[] __initdata = {
-#if defined(CONFIG_MTD_DATAFLASH)
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-               .platform_data  = &cam60_spi_flash_platform_data
-       },
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data cam60_macb_data __initdata = {
-       .phy_irq_pin    = AT91_PIN_PB5,
-       .is_rmii        = 0,
-};
-
-
-/*
- * NAND Flash
- */
-static struct mtd_partition __initdata cam60_nand_partition[] = {
-       {
-               .name   = "nand_fs",
-               .offset = 0,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata cam60_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PA9,
-       .enable_pin     = AT91_PIN_PA7,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .parts          = cam60_nand_partition,
-       .num_parts      = ARRAY_SIZE(cam60_nand_partition),
-};
-
-static struct sam9_smc_config __initdata cam60_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 3,
-       .nrd_pulse              = 3,
-       .ncs_write_pulse        = 3,
-       .nwe_pulse              = 3,
-
-       .read_cycle             = 5,
-       .write_cycle            = 5,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 2,
-};
-
-static void __init cam60_add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &cam60_nand_smc_config);
-
-       at91_add_device_nand(&cam60_nand_data);
-}
-
-
-static void __init cam60_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-       at91_add_device_serial();
-       /* SPI */
-       at91_add_device_spi(cam60_spi_devices, ARRAY_SIZE(cam60_spi_devices));
-       /* Ethernet */
-       at91_add_device_eth(&cam60_macb_data);
-       /* USB Host */
-       /* enable USB power supply circuit */
-       at91_set_gpio_output(AT91_PIN_PB18, 1);
-       at91_add_device_usbh(&cam60_usbh_data);
-       /* NAND */
-       cam60_add_device_nand();
-}
-
-MACHINE_START(CAM60, "KwikByte CAM60")
-       /* Maintainer: KwikByte */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = cam60_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = cam60_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
deleted file mode 100644 (file)
index 47313d3..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-carmeva.c
- *
- *  Copyright (c) 2005 Peer Georgi
- *                    Conitec Datasystems
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init carmeva_init_early(void)
-{
-       /* Initialize processor: 20.000 MHz crystal */
-       at91_initialize(20000000);
-}
-
-static struct macb_platform_data __initdata carmeva_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC4,
-       .is_rmii        = 1,
-};
-
-static struct at91_usbh_data __initdata carmeva_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata carmeva_udc_data = {
-       .vbus_pin       = AT91_PIN_PD12,
-       .pullup_pin     = AT91_PIN_PD9,
-};
-
-/* FIXME: user dependent */
-// static struct at91_cf_data __initdata carmeva_cf_data = {
-//     .det_pin        = AT91_PIN_PB0,
-//     .rst_pin        = AT91_PIN_PC5,
-       // .irq_pin     = -EINVAL,
-       // .vcc_pin     = -EINVAL,
-// };
-
-static struct mci_platform_data __initdata carmeva_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PB10,
-               .wp_pin         = AT91_PIN_PC14,
-       },
-};
-
-static struct spi_board_info carmeva_spi_devices[] = {
-       { /* DataFlash chip */
-               .modalias = "mtd_dataflash",
-               .chip_select  = 0,
-               .max_speed_hz = 10 * 1000 * 1000,
-       },
-       { /* User accessible spi - cs1 (250KHz) */
-               .modalias = "spi-cs1",
-               .chip_select  = 1,
-               .max_speed_hz = 250 *  1000,
-       },
-       { /* User accessible spi - cs2 (1MHz) */
-               .modalias = "spi-cs2",
-               .chip_select  = 2,
-               .max_speed_hz = 1 * 1000 *  1000,
-       },
-       { /* User accessible spi - cs3 (10MHz) */
-               .modalias = "spi-cs3",
-               .chip_select  = 3,
-               .max_speed_hz = 10 * 1000 *  1000,
-       },
-};
-
-static struct gpio_led carmeva_leds[] = {
-       { /* "user led 1", LED9 */
-               .name                   = "led9",
-               .gpio                   = AT91_PIN_PA21,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       { /* "user led 2", LED10 */
-               .name                   = "led10",
-               .gpio                   = AT91_PIN_PA25,
-               .active_low             = 1,
-       },
-       { /* "user led 3", LED11 */
-               .name                   = "led11",
-               .gpio                   = AT91_PIN_PA26,
-               .active_low             = 1,
-       },
-       { /* "user led 4", LED12 */
-               .name                   = "led12",
-               .gpio                   = AT91_PIN_PA18,
-               .active_low             = 1,
-       }
-};
-
-static void __init carmeva_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                          | ATMEL_UART_RI);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&carmeva_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&carmeva_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&carmeva_udc_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* SPI */
-       at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices));
-       /* Compact Flash */
-//     at91_add_device_cf(&carmeva_cf_data);
-       /* MMC */
-       at91_add_device_mci(0, &carmeva_mci0_data);
-       /* LEDs */
-       at91_gpio_leds(carmeva_leds, ARRAY_SIZE(carmeva_leds));
-}
-
-MACHINE_START(CARMEVA, "Carmeva")
-       /* Maintainer: Conitec Datasystems */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = carmeva_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = carmeva_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
deleted file mode 100644 (file)
index 731c831..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-cpu9krea.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *  Copyright (C) 2009 Eric Benard - 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/at91sam9260_matrix.h>
-#include <mach/at91_matrix.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-static void __init cpu9krea_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata cpu9krea_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata cpu9krea_udc_data = {
-       .vbus_pin       = AT91_PIN_PC8,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata cpu9krea_macb_data = {
-       .phy_irq_pin    = -EINVAL,
-       .is_rmii        = 1,
-};
-
-/*
- * NAND flash
- */
-static struct atmel_nand_data __initdata cpu9krea_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-       .bus_width_16   = 0,
-       .det_pin        = -EINVAL,
-       .ecc_mode       = NAND_ECC_SOFT,
-};
-
-#ifdef CONFIG_MACH_CPU9260
-static struct sam9_smc_config __initdata cpu9krea_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 3,
-       .nrd_pulse              = 3,
-       .ncs_write_pulse        = 3,
-       .nwe_pulse              = 3,
-
-       .read_cycle             = 5,
-       .write_cycle            = 5,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-               | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 2,
-};
-#else
-static struct sam9_smc_config __initdata cpu9krea_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-               | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 3,
-};
-#endif
-
-static void __init cpu9krea_add_device_nand(void)
-{
-       sam9_smc_configure(0, 3, &cpu9krea_nand_smc_config);
-       at91_add_device_nand(&cpu9krea_nand_data);
-}
-
-/*
- * NOR flash
- */
-static struct physmap_flash_data cpuat9260_nor_data = {
-       .width          = 2,
-};
-
-#define NOR_BASE       AT91_CHIPSELECT_0
-#define NOR_SIZE       SZ_64M
-
-static struct resource nor_flash_resources[] = {
-       {
-               .start  = NOR_BASE,
-               .end    = NOR_BASE + NOR_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device cpu9krea_nor_flash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-               .platform_data  = &cpuat9260_nor_data,
-       },
-       .resource       = nor_flash_resources,
-       .num_resources  = ARRAY_SIZE(nor_flash_resources),
-};
-
-#ifdef CONFIG_MACH_CPU9260
-static struct sam9_smc_config __initdata cpu9krea_nor_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 10,
-       .nrd_pulse              = 10,
-       .ncs_write_pulse        = 6,
-       .nwe_pulse              = 6,
-
-       .read_cycle             = 12,
-       .write_cycle            = 8,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE
-                       | AT91_SMC_DBW_16,
-       .tdf_cycles             = 2,
-};
-#else
-static struct sam9_smc_config __initdata cpu9krea_nor_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 13,
-       .nrd_pulse              = 13,
-       .ncs_write_pulse        = 8,
-       .nwe_pulse              = 8,
-
-       .read_cycle             = 15,
-       .write_cycle            = 10,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE
-                       | AT91_SMC_DBW_16,
-       .tdf_cycles             = 2,
-};
-#endif
-
-static __init void cpu9krea_add_device_nor(void)
-{
-       unsigned long csa;
-
-       csa = at91_matrix_read(AT91_MATRIX_EBICSA);
-       at91_matrix_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_VDDIOMSEL_3_3V);
-
-       /* configure chip-select 0 (NOR) */
-       sam9_smc_configure(0, 0, &cpu9krea_nor_smc_config);
-
-       platform_device_register(&cpu9krea_nor_flash);
-}
-
-/*
- * LEDs
- */
-static struct gpio_led cpu9krea_leds[] = {
-       {       /* LED1 */
-               .name                   = "LED1",
-               .gpio                   = AT91_PIN_PC11,
-               .active_low             = 1,
-               .default_trigger        = "timer",
-       },
-       {       /* LED2 */
-               .name                   = "LED2",
-               .gpio                   = AT91_PIN_PC12,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* LED3 */
-               .name                   = "LED3",
-               .gpio                   = AT91_PIN_PC7,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* LED4 */
-               .name                   = "LED4",
-               .gpio                   = AT91_PIN_PC9,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       }
-};
-
-static struct i2c_board_info __initdata cpu9krea_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("ds1339", 0x68),
-       },
-};
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button cpu9krea_buttons[] = {
-       {
-               .gpio           = AT91_PIN_PC3,
-               .code           = BTN_0,
-               .desc           = "BP1",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PB20,
-               .code           = BTN_1,
-               .desc           = "BP2",
-               .active_low     = 1,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data cpu9krea_button_data = {
-       .buttons        = cpu9krea_buttons,
-       .nbuttons       = ARRAY_SIZE(cpu9krea_buttons),
-};
-
-static struct platform_device cpu9krea_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &cpu9krea_button_data,
-       }
-};
-
-static void __init cpu9krea_add_device_buttons(void)
-{
-       at91_set_gpio_input(AT91_PIN_PC3, 1);   /* BP1 */
-       at91_set_deglitch(AT91_PIN_PC3, 1);
-       at91_set_gpio_input(AT91_PIN_PB20, 1);  /* BP2 */
-       at91_set_deglitch(AT91_PIN_PB20, 1);
-
-       platform_device_register(&cpu9krea_button_device);
-}
-#else
-static void __init cpu9krea_add_device_buttons(void)
-{
-}
-#endif
-
-/*
- * MCI (SD/MMC)
- */
-static struct mci_platform_data __initdata cpu9krea_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PA29,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-static void __init cpu9krea_board_init(void)
-{
-       at91_register_devices();
-
-       /* NOR */
-       cpu9krea_add_device_nor();
-       /* Serial */
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS |
-               ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
-               ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS |
-               ATMEL_UART_RTS);
-
-       /* USART2 on ttyS3. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS |
-               ATMEL_UART_RTS);
-
-       /* USART3 on ttyS4. (Rx, Tx) */
-       at91_register_uart(AT91SAM9260_ID_US3, 4, 0);
-
-       /* USART4 on ttyS5. (Rx, Tx) */
-       at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-
-       /* USART5 on ttyS6. (Rx, Tx) */
-       at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&cpu9krea_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&cpu9krea_udc_data);
-       /* NAND */
-       cpu9krea_add_device_nand();
-       /* Ethernet */
-       at91_add_device_eth(&cpu9krea_macb_data);
-       /* MMC */
-       at91_add_device_mci(0, &cpu9krea_mci0_data);
-       /* I2C */
-       at91_add_device_i2c(cpu9krea_i2c_devices,
-               ARRAY_SIZE(cpu9krea_i2c_devices));
-       /* LEDs */
-       at91_gpio_leds(cpu9krea_leds, ARRAY_SIZE(cpu9krea_leds));
-       /* Push Buttons */
-       cpu9krea_add_device_buttons();
-}
-
-#ifdef CONFIG_MACH_CPU9260
-MACHINE_START(CPUAT9260, "Eukrea CPU9260")
-#else
-MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
-#endif
-       /* Maintainer: Eric Benard - EUKREA Electromatique */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = cpu9krea_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = cpu9krea_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
deleted file mode 100644 (file)
index c094350..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-cpuat91.c
- *
- *  Copyright (C) 2009 Eric Benard - 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/plat-ram.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/at91rm9200_mc.h>
-#include <mach/at91_ramc.h>
-#include <mach/cpu.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static struct gpio_led cpuat91_leds[] = {
-       {
-               .name                   = "led1",
-               .default_trigger        = "heartbeat",
-               .active_low             = 1,
-               .gpio                   = AT91_PIN_PC0,
-       },
-};
-
-static void __init cpuat91_init_early(void)
-{
-       /* Set cpu type: PQFP */
-       at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata cpuat91_eth_data = {
-       .phy_irq_pin    = -EINVAL,
-       .is_rmii        = 1,
-};
-
-static struct at91_usbh_data __initdata cpuat91_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata cpuat91_udc_data = {
-       .vbus_pin       = AT91_PIN_PC15,
-       .pullup_pin     = AT91_PIN_PC14,
-};
-
-static struct mci_platform_data __initdata cpuat91_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PC2,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-static struct physmap_flash_data cpuat91_flash_data = {
-       .width          = 2,
-};
-
-static struct resource cpuat91_flash_resource = {
-       .start          = AT91_CHIPSELECT_0,
-       .end            = AT91_CHIPSELECT_0 + SZ_16M - 1,
-       .flags          = IORESOURCE_MEM,
-};
-
-static struct platform_device cpuat91_norflash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev    = {
-               .platform_data  = &cpuat91_flash_data,
-       },
-       .resource       = &cpuat91_flash_resource,
-       .num_resources  = 1,
-};
-
-#ifdef CONFIG_MTD_PLATRAM
-struct platdata_mtd_ram at91_sram_pdata = {
-       .mapname        = "SRAM",
-       .bankwidth      = 2,
-};
-
-static struct resource at91_sram_resource[] = {
-       [0] = {
-               .start = AT91RM9200_SRAM_BASE,
-               .end   = AT91RM9200_SRAM_BASE + AT91RM9200_SRAM_SIZE - 1,
-               .flags = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device at91_sram = {
-       .name           = "mtd-ram",
-       .id             = 0,
-       .resource       = at91_sram_resource,
-       .num_resources  = ARRAY_SIZE(at91_sram_resource),
-       .dev    = {
-               .platform_data = &at91_sram_pdata,
-       },
-};
-#endif /* MTD_PLATRAM */
-
-static struct platform_device *platform_devices[] __initdata = {
-       &cpuat91_norflash,
-#ifdef CONFIG_MTD_PLATRAM
-       &at91_sram,
-#endif /* CONFIG_MTD_PLATRAM */
-};
-
-static void __init cpuat91_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS |
-               ATMEL_UART_RTS);
-
-       /* USART1 on ttyS2. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91RM9200_ID_US1, 2, ATMEL_UART_CTS |
-               ATMEL_UART_RTS | ATMEL_UART_DTR | ATMEL_UART_DSR |
-               ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* USART2 on ttyS3 (Rx, Tx) */
-       at91_register_uart(AT91RM9200_ID_US2, 3, 0);
-
-       /* USART3 on ttyS4 (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91RM9200_ID_US3, 4, ATMEL_UART_CTS |
-               ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* LEDs. */
-       at91_gpio_leds(cpuat91_leds, ARRAY_SIZE(cpuat91_leds));
-       /* Ethernet */
-       at91_add_device_eth(&cpuat91_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&cpuat91_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&cpuat91_udc_data);
-       /* MMC */
-       at91_add_device_mci(0, &cpuat91_mci0_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* Platform devices */
-       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
-
-MACHINE_START(CPUAT91, "Eukrea")
-       /* Maintainer: Eric Benard - EUKREA Electromatique */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = cpuat91_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = cpuat91_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
deleted file mode 100644 (file)
index 0e35a45..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-csb337.c
- *
- *  Copyright (C) 2005 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
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mtd/physmap.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-static void __init csb337_init_early(void)
-{
-       /* Initialize processor: 3.6864 MHz crystal */
-       at91_initialize(3686400);
-}
-
-static struct macb_platform_data __initdata csb337_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC2,
-       .is_rmii        = 0,
-       /* The CSB337 bootloader stores the MAC the wrong-way around */
-       .rev_eth_addr   = 1,
-};
-
-static struct at91_usbh_data __initdata csb337_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata csb337_udc_data = {
-       .pullup_pin     = AT91_PIN_PA24,
-       .vbus_pin       = -EINVAL,
-};
-
-static struct i2c_board_info __initdata csb337_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("ds1307", 0x68),
-       },
-};
-
-static struct at91_cf_data __initdata csb337_cf_data = {
-       /*
-        * connector P4 on the CSB 337 mates to
-        * connector P8 on the CSB 300CF
-        */
-
-       /* CSB337 specific */
-       .det_pin        = AT91_PIN_PC3,
-
-       /* CSB300CF specific */
-       .irq_pin        = AT91_PIN_PA19,
-       .vcc_pin        = AT91_PIN_PD0,
-       .rst_pin        = AT91_PIN_PD2,
-};
-
-static struct mci_platform_data __initdata csb337_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PD5,
-               .wp_pin         = AT91_PIN_PD6,
-       },
-};
-
-static struct spi_board_info csb337_spi_devices[] = {
-       {       /* CAN controller */
-               .modalias       = "sak82c900",
-               .chip_select    = 0,
-               .max_speed_hz   = 6 * 1000 * 1000,
-       },
-};
-
-#define CSB_FLASH_BASE AT91_CHIPSELECT_0
-#define CSB_FLASH_SIZE SZ_8M
-
-static struct mtd_partition csb_flash_partitions[] = {
-       {
-               .name           = "uMON flash",
-               .offset         = 0,
-               .size           = MTDPART_SIZ_FULL,
-               .mask_flags     = MTD_WRITEABLE,        /* read only */
-       }
-};
-
-static struct physmap_flash_data csb_flash_data = {
-       .width          = 2,
-       .parts          = csb_flash_partitions,
-       .nr_parts       = ARRAY_SIZE(csb_flash_partitions),
-};
-
-static struct resource csb_flash_resources[] = {
-       {
-               .start  = CSB_FLASH_BASE,
-               .end    = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device csb_flash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-                               .platform_data = &csb_flash_data,
-                       },
-       .resource       = csb_flash_resources,
-       .num_resources  = ARRAY_SIZE(csb_flash_resources),
-};
-
-/*
- * GPIO Buttons (on CSB300)
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button csb300_buttons[] = {
-       {
-               .gpio           = AT91_PIN_PB29,
-               .code           = BTN_0,
-               .desc           = "sw0",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PB28,
-               .code           = BTN_1,
-               .desc           = "sw1",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PA21,
-               .code           = BTN_2,
-               .desc           = "sw2",
-               .active_low     = 1,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data csb300_button_data = {
-       .buttons        = csb300_buttons,
-       .nbuttons       = ARRAY_SIZE(csb300_buttons),
-};
-
-static struct platform_device csb300_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &csb300_button_data,
-       }
-};
-
-static void __init csb300_add_device_buttons(void)
-{
-       at91_set_gpio_input(AT91_PIN_PB29, 1);  /* sw0 */
-       at91_set_deglitch(AT91_PIN_PB29, 1);
-       at91_set_gpio_input(AT91_PIN_PB28, 1);  /* sw1 */
-       at91_set_deglitch(AT91_PIN_PB28, 1);
-       at91_set_gpio_input(AT91_PIN_PA21, 1);  /* sw2 */
-       at91_set_deglitch(AT91_PIN_PA21, 1);
-
-       platform_device_register(&csb300_button_device);
-}
-#else
-static void __init csb300_add_device_buttons(void) {}
-#endif
-
-static struct gpio_led csb_leds[] = {
-       {       /* "led0", yellow */
-               .name                   = "led0",
-               .gpio                   = AT91_PIN_PB2,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* "led1", green */
-               .name                   = "led1",
-               .gpio                   = AT91_PIN_PB1,
-               .active_low             = 1,
-               .default_trigger        = "mmc0",
-       },
-       {       /* "led2", yellow */
-               .name                   = "led2",
-               .gpio                   = AT91_PIN_PB0,
-               .active_low             = 1,
-               .default_trigger        = "ide-disk",
-       }
-};
-
-
-static void __init csb337_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0 */
-       at91_register_uart(0, 0, 0);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&csb337_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&csb337_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&csb337_udc_data);
-       /* I2C */
-       at91_add_device_i2c(csb337_i2c_devices, ARRAY_SIZE(csb337_i2c_devices));
-       /* Compact Flash */
-       at91_set_gpio_input(AT91_PIN_PB22, 1);          /* IOIS16 */
-       at91_add_device_cf(&csb337_cf_data);
-       /* SPI */
-       at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
-       /* MMC */
-       at91_add_device_mci(0, &csb337_mci0_data);
-       /* NOR flash */
-       platform_device_register(&csb_flash);
-       /* LEDs */
-       at91_gpio_leds(csb_leds, ARRAY_SIZE(csb_leds));
-       /* Switches on CSB300 */
-       csb300_add_device_buttons();
-}
-
-MACHINE_START(CSB337, "Cogent CSB337")
-       /* Maintainer: Bill Gatliff */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = csb337_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = csb337_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
deleted file mode 100644 (file)
index 18d027f..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-csb637.c
- *
- *  Copyright (C) 2005 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
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init csb637_init_early(void)
-{
-       /* Initialize processor: 3.6864 MHz crystal */
-       at91_initialize(3686400);
-}
-
-static struct macb_platform_data __initdata csb637_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC0,
-       .is_rmii        = 0,
-};
-
-static struct at91_usbh_data __initdata csb637_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata csb637_udc_data = {
-       .vbus_pin     = AT91_PIN_PB28,
-       .pullup_pin   = AT91_PIN_PB1,
-};
-
-#define CSB_FLASH_BASE AT91_CHIPSELECT_0
-#define CSB_FLASH_SIZE SZ_16M
-
-static struct mtd_partition csb_flash_partitions[] = {
-       {
-               .name           = "uMON flash",
-               .offset         = 0,
-               .size           = MTDPART_SIZ_FULL,
-               .mask_flags     = MTD_WRITEABLE,        /* read only */
-       }
-};
-
-static struct physmap_flash_data csb_flash_data = {
-       .width          = 2,
-       .parts          = csb_flash_partitions,
-       .nr_parts       = ARRAY_SIZE(csb_flash_partitions),
-};
-
-static struct resource csb_flash_resources[] = {
-       {
-               .start  = CSB_FLASH_BASE,
-               .end    = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device csb_flash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-                               .platform_data = &csb_flash_data,
-                       },
-       .resource       = csb_flash_resources,
-       .num_resources  = ARRAY_SIZE(csb_flash_resources),
-};
-
-static struct gpio_led csb_leds[] = {
-       {       /* "d1", red */
-               .name                   = "d1",
-               .gpio                   = AT91_PIN_PB2,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-};
-
-static void __init csb637_board_init(void)
-{
-       /* LED(s) */
-       at91_gpio_leds(csb_leds, ARRAY_SIZE(csb_leds));
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&csb637_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&csb637_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&csb637_udc_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* SPI */
-       at91_add_device_spi(NULL, 0);
-       /* NOR flash */
-       platform_device_register(&csb_flash);
-}
-
-MACHINE_START(CSB637, "Cogent CSB637")
-       /* Maintainer: Bill Gatliff */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = csb637_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = csb637_board_init,
-MACHINE_END
index 226563f850b85a9b7f9e884b2223f7a1b15eb6f1..76dfe8f9af5042f8a6375cd3d49a8062214310e7 100644 (file)
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include "at91_aic.h"
 #include "generic.h"
 
 static void __init at91rm9200_dt_timer_init(void)
 {
-#if defined(CONFIG_COMMON_CLK)
        of_clk_init(NULL);
-#endif
        at91rm9200_timer_init();
 }
 
index d3048ccdc41f1dd936c1a01d1cf41b0fec8ebe65..f99246aa9b38c60c6fc3aed9ead01dbee1d6c996 100644 (file)
@@ -21,8 +21,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include "at91_aic.h"
-#include "board.h"
 #include "generic.h"
 
 static const char *at91_dt_board_compat[] __initdata = {
index 129e2917506bb29f2d810432c25376b0150ad4bf..8fb9ef5333f17648d8a28aaa0385badc9c0ed65a 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include "at91_aic.h"
 #include "generic.h"
 
 static void __init sama5_dt_device_init(void)
diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c
deleted file mode 100644 (file)
index becf0a6..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * arch/arm/mach-at91/board-eb01.c
- *
- * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.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
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-
-static void __init at91eb01_init_irq(void)
-{
-       at91x40_init_interrupts(NULL);
-}
-
-static void __init at91eb01_init_early(void)
-{
-       at91x40_initialize(40000000);
-}
-
-MACHINE_START(AT91EB01, "Atmel AT91 EB01")
-       /* Maintainer: Greg Ungerer <gerg@snapgear.com> */
-       .init_time      = at91x40_timer_init,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = at91eb01_init_early,
-       .init_irq       = at91eb01_init_irq,
-MACHINE_END
-
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
deleted file mode 100644 (file)
index aa457a8..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-eb9200.c
- *
- *  Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
- *  by Andrew Patrikalakis
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/device.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init eb9200_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata eb9200_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC4,
-       .is_rmii        = 1,
-};
-
-static struct at91_usbh_data __initdata eb9200_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata eb9200_udc_data = {
-       .vbus_pin       = AT91_PIN_PD4,
-       .pullup_pin     = AT91_PIN_PD5,
-};
-
-static struct at91_cf_data __initdata eb9200_cf_data = {
-       .irq_pin        = -EINVAL,
-       .det_pin        = AT91_PIN_PB0,
-       .vcc_pin        = -EINVAL,
-       .rst_pin        = AT91_PIN_PC5,
-};
-
-static struct mci_platform_data __initdata eb9200_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = -EINVAL,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("24c512", 0x50),
-       },
-};
-
-
-static void __init eb9200_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                       | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                       | ATMEL_UART_RI);
-
-       /* USART2 on ttyS2. (Rx, Tx) - IRDA */
-       at91_register_uart(AT91RM9200_ID_US2, 2, 0);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&eb9200_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&eb9200_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&eb9200_udc_data);
-       /* I2C */
-       at91_add_device_i2c(eb9200_i2c_devices, ARRAY_SIZE(eb9200_i2c_devices));
-       /* Compact Flash */
-       at91_add_device_cf(&eb9200_cf_data);
-       /* SPI */
-       at91_add_device_spi(NULL, 0);
-       /* MMC */
-       /* only supports 1 or 4 bit interface, not wired through to SPI */
-       at91_add_device_mci(0, &eb9200_mci0_data);
-}
-
-MACHINE_START(ATEB9200, "Embest ATEB9200")
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = eb9200_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = eb9200_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
deleted file mode 100644 (file)
index ede1373..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * linux/arch/arm/mach-at91rm9200/board-ecbat91.c
- * Copyright (C) 2007 emQbit.com.
- *
- * We started from board-dk.c, which is Copyright (C) 2005 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
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/flash.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/cpu.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ecb_at91init_early(void)
-{
-       /* Set cpu type: PQFP */
-       at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata ecb_at91eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC4,
-       .is_rmii        = 0,
-};
-
-static struct at91_usbh_data __initdata ecb_at91usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct mci_platform_data __initdata ecbat91_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = -EINVAL,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-
-#if defined(CONFIG_MTD_DATAFLASH)
-static struct mtd_partition __initdata my_flash0_partitions[] =
-{
-       {       /* 0x8400 */
-               .name   = "Darrell-loader",
-               .offset = 0,
-               .size   = 12 * 1056,
-       },
-       {
-               .name   = "U-boot",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 110 * 1056,
-       },
-       {       /* 1336 (167 blocks) pages * 1056 bytes = 0x158700 bytes */
-               .name   = "UBoot-env",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 8 * 1056,
-       },
-       {       /* 1336 (167 blocks) pages * 1056 bytes = 0x158700 bytes */
-               .name   = "Kernel",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 1534 * 1056,
-       },
-       {       /* 190200 - jffs2 root filesystem */
-               .name   = "Filesystem",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,     /* 26 sectors */
-       }
-};
-
-static struct flash_platform_data __initdata my_flash0_platform = {
-       .name           = "Removable flash card",
-       .parts          = my_flash0_partitions,
-       .nr_parts       = ARRAY_SIZE(my_flash0_partitions)
-};
-
-#endif
-
-static struct spi_board_info __initdata ecb_at91spi_devices[] = {
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 10 * 1000 * 1000,
-               .bus_num        = 0,
-#if defined(CONFIG_MTD_DATAFLASH)
-               .platform_data  = &my_flash0_platform,
-#endif
-       },
-       {       /* User accessible spi - cs1 (250KHz) */
-               .modalias       = "spi-cs1",
-               .chip_select    = 1,
-               .max_speed_hz   = 250 * 1000,
-       },
-       {       /* User accessible spi - cs2 (1MHz) */
-               .modalias       = "spi-cs2",
-               .chip_select    = 2,
-               .max_speed_hz   = 1 * 1000 * 1000,
-       },
-       {       /* User accessible spi - cs3 (10MHz) */
-               .modalias       = "spi-cs3",
-               .chip_select    = 3,
-               .max_speed_hz   = 10 * 1000 * 1000,
-       },
-};
-
-/*
- * LEDs
- */
-static struct gpio_led ecb_leds[] = {
-       {       /* D1 */
-               .name                   = "led1",
-               .gpio                   = AT91_PIN_PC7,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-static void __init ecb_at91board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx & Tx only) */
-       at91_register_uart(AT91RM9200_ID_US0, 1, 0);
-       at91_add_device_serial();
-
-       /* Ethernet */
-       at91_add_device_eth(&ecb_at91eth_data);
-
-       /* USB Host */
-       at91_add_device_usbh(&ecb_at91usbh_data);
-
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-
-       /* MMC */
-       at91_add_device_mci(0, &ecbat91_mci0_data);
-
-       /* SPI */
-       at91_add_device_spi(ecb_at91spi_devices, ARRAY_SIZE(ecb_at91spi_devices));
-
-       /* LEDs */
-       at91_gpio_leds(ecb_leds, ARRAY_SIZE(ecb_leds));
-}
-
-MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
-       /* Maintainer: emQbit.com */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ecb_at91init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ecb_at91board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
deleted file mode 100644 (file)
index 4e75321..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <mach/at91rm9200_mc.h>
-#include <mach/at91_ramc.h>
-#include <mach/cpu.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init eco920_init_early(void)
-{
-       /* Set cpu type: PQFP */
-       at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata eco920_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC2,
-       .is_rmii        = 1,
-};
-
-static struct at91_usbh_data __initdata eco920_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata eco920_udc_data = {
-       .vbus_pin       = AT91_PIN_PB12,
-       .pullup_pin     = AT91_PIN_PB13,
-};
-
-static struct mci_platform_data __initdata eco920_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 1,
-               .detect_pin     = -EINVAL,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-static struct physmap_flash_data eco920_flash_data = {
-       .width  = 2,
-};
-
-static struct resource eco920_flash_resource = {
-       .start          = 0x11000000,
-       .end            = 0x11ffffff,
-       .flags          = IORESOURCE_MEM,
-};
-
-static struct platform_device eco920_flash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-               .platform_data  = &eco920_flash_data,
-       },
-       .resource       = &eco920_flash_resource,
-       .num_resources  = 1,
-};
-
-static struct spi_board_info eco920_spi_devices[] = {
-       {       /* CAN controller */
-               .modalias       = "tlv5638",
-               .chip_select    = 3,
-               .max_speed_hz   = 20 * 1000 * 1000,
-               .mode           = SPI_CPHA,
-       },
-};
-
-/*
- * LEDs
- */
-static struct gpio_led eco920_leds[] = {
-       {       /* D1 */
-               .name                   = "led1",
-               .gpio                   = AT91_PIN_PB0,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* D2 */
-               .name                   = "led2",
-               .gpio                   = AT91_PIN_PB1,
-               .active_low             = 1,
-               .default_trigger        = "timer",
-       }
-};
-
-static void __init eco920_board_init(void)
-{
-       /* DBGU on ttyS0. (Rx & Tx only */
-       at91_register_uart(0, 0, 0);
-       at91_add_device_serial();
-       at91_add_device_eth(&eco920_eth_data);
-       at91_add_device_usbh(&eco920_usbh_data);
-       at91_add_device_udc(&eco920_udc_data);
-
-       at91_add_device_mci(0, &eco920_mci0_data);
-       platform_device_register(&eco920_flash);
-
-       at91_ramc_write(0, AT91_SMC_CSR(7),     AT91_SMC_RWHOLD_(1)
-                               | AT91_SMC_RWSETUP_(1)
-                               | AT91_SMC_DBW_8
-                               | AT91_SMC_WSEN
-                               | AT91_SMC_NWS_(15));
-
-       at91_set_A_periph(AT91_PIN_PC6, 1);
-
-       at91_set_gpio_input(AT91_PIN_PA23, 0);
-       at91_set_deglitch(AT91_PIN_PA23, 1);
-
-/* Initialization of the Static Memory Controller for Chip Select 3 */
-       at91_ramc_write(0, AT91_SMC_CSR(3),
-               AT91_SMC_DBW_16  |      /* 16 bit */
-               AT91_SMC_WSEN    |
-               AT91_SMC_NWS_(5) |      /* wait states */
-               AT91_SMC_TDF_(1)        /* float time */
-       );
-
-       at91_add_device_spi(eco920_spi_devices, ARRAY_SIZE(eco920_spi_devices));
-       /* LEDs */
-       at91_gpio_leds(eco920_leds, ARRAY_SIZE(eco920_leds));
-}
-
-MACHINE_START(ECO920, "eco920")
-       /* Maintainer: Sascha Hauer */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = eco920_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = eco920_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
deleted file mode 100644 (file)
index a6aa4a2..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-flexibity.c
- *
- *  Copyright (C) 2010-2011 Flexibity
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-static void __init flexibity_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/* USB Host port */
-static struct at91_usbh_data __initdata flexibity_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/* USB Device port */
-static struct at91_udc_data __initdata flexibity_udc_data = {
-       .vbus_pin       = AT91_PIN_PC5,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-/* I2C devices */
-static struct i2c_board_info __initdata flexibity_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("ds1307", 0x68),
-       },
-};
-
-/* SPI devices */
-static struct spi_board_info flexibity_spi_devices[] = {
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 1,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-};
-
-/* MCI (SD/MMC) */
-static struct mci_platform_data __initdata flexibity_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PC9,
-               .wp_pin         = AT91_PIN_PC4,
-       },
-};
-
-/* LEDs */
-static struct gpio_led flexibity_leds[] = {
-       {
-               .name                   = "usb1:green",
-               .gpio                   = AT91_PIN_PA12,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       },
-       {
-               .name                   = "usb1:red",
-               .gpio                   = AT91_PIN_PA13,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       },
-       {
-               .name                   = "usb2:green",
-               .gpio                   = AT91_PIN_PB26,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       },
-       {
-               .name                   = "usb2:red",
-               .gpio                   = AT91_PIN_PB27,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       },
-       {
-               .name                   = "usb3:green",
-               .gpio                   = AT91_PIN_PC8,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       },
-       {
-               .name                   = "usb3:red",
-               .gpio                   = AT91_PIN_PC6,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       },
-       {
-               .name                   = "usb4:green",
-               .gpio                   = AT91_PIN_PB4,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       },
-       {
-               .name                   = "usb4:red",
-               .gpio                   = AT91_PIN_PB5,
-               .active_low             = 1,
-               .default_trigger        = "default-on",
-       }
-};
-
-static void __init flexibity_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&flexibity_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&flexibity_udc_data);
-       /* I2C */
-       at91_add_device_i2c(flexibity_i2c_devices,
-               ARRAY_SIZE(flexibity_i2c_devices));
-       /* SPI */
-       at91_add_device_spi(flexibity_spi_devices,
-               ARRAY_SIZE(flexibity_spi_devices));
-       /* MMC */
-       at91_add_device_mci(0, &flexibity_mci0_data);
-       /* LEDs */
-       at91_gpio_leds(flexibity_leds, ARRAY_SIZE(flexibity_leds));
-}
-
-MACHINE_START(FLEXIBITY, "Flexibity Connect")
-       /* Maintainer: Maxim Osipov */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = flexibity_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = flexibity_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
deleted file mode 100644 (file)
index bf5cc55..0000000
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- *  Copyright (C) 2010 Christian Glindkamp <christian.glindkamp@taskit.de>
- *                     taskit GmbH
- *                2010 Igor Plyatov <plyatov@gmail.com>
- *                     GeoSIG 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.
- *
- * 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/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/w1-gpio.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pcf857x.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <mach/at91sam9_smc.h>
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gsia18s.h"
-#include "stamp9g20.h"
-#include "gpio.h"
-
-static void __init gsia18s_init_early(void)
-{
-       stamp9g20_init_early();
-}
-
-/*
- * Two USB Host ports
- */
-static struct at91_usbh_data __initdata usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata udc_data = {
-       .vbus_pin       = AT91_PIN_PA22,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata macb_data = {
-       .phy_irq_pin    = AT91_PIN_PA28,
-       .is_rmii        = 1,
-};
-
-/*
- * LEDs and GPOs
- */
-static struct gpio_led gpio_leds[] = {
-       {
-               .name                   = "gpo:spi1reset",
-               .gpio                   = AT91_PIN_PC1,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       {
-               .name                   = "gpo:trig_net_out",
-               .gpio                   = AT91_PIN_PB20,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       {
-               .name                   = "gpo:trig_net_dir",
-               .gpio                   = AT91_PIN_PB19,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       {
-               .name                   = "gpo:charge_dis",
-               .gpio                   = AT91_PIN_PC2,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       {
-               .name                   = "led:event",
-               .gpio                   = AT91_PIN_PB17,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       {
-               .name                   = "led:lan",
-               .gpio                   = AT91_PIN_PB18,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       {
-               .name                   = "led:error",
-               .gpio                   = AT91_PIN_PB16,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_ON,
-       }
-};
-
-static struct gpio_led_platform_data gpio_led_info = {
-       .leds           = gpio_leds,
-       .num_leds       = ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds = {
-       .name   = "leds-gpio",
-       .id     = 0,
-       .dev    = {
-               .platform_data  = &gpio_led_info,
-       }
-};
-
-static void __init gsia18s_leds_init(void)
-{
-       platform_device_register(&leds);
-}
-
-/* PCF8574 0x20 GPIO - U1 on the GS_IA18-CB_V3 board */
-static struct gpio_led pcf_gpio_leds1[] = {
-       { /* bit 0 */
-               .name                   = "gpo:hdc_power",
-               .gpio                   = PCF_GPIO_HDC_POWER,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       { /* bit 1 */
-               .name                   = "gpo:wifi_setup",
-               .gpio                   = PCF_GPIO_WIFI_SETUP,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       { /* bit 2 */
-               .name                   = "gpo:wifi_enable",
-               .gpio                   = PCF_GPIO_WIFI_ENABLE,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       { /* bit 3      */
-               .name                   = "gpo:wifi_reset",
-               .gpio                   = PCF_GPIO_WIFI_RESET,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_ON,
-       },
-       /* bit 4 used as GPI    */
-       { /* bit 5 */
-               .name                   = "gpo:gps_setup",
-               .gpio                   = PCF_GPIO_GPS_SETUP,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       { /* bit 6 */
-               .name                   = "gpo:gps_standby",
-               .gpio                   = PCF_GPIO_GPS_STANDBY,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_ON,
-       },
-       { /* bit 7 */
-               .name                   = "gpo:gps_power",
-               .gpio                   = PCF_GPIO_GPS_POWER,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       }
-};
-
-static struct gpio_led_platform_data pcf_gpio_led_info1 = {
-       .leds           = pcf_gpio_leds1,
-       .num_leds       = ARRAY_SIZE(pcf_gpio_leds1),
-};
-
-static struct platform_device pcf_leds1 = {
-       .name   = "leds-gpio", /* GS_IA18-CB_board */
-       .id     = 1,
-       .dev    = {
-               .platform_data  = &pcf_gpio_led_info1,
-       }
-};
-
-/* PCF8574 0x22 GPIO - U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
-static struct gpio_led pcf_gpio_leds2[] = {
-       { /* bit 0 */
-               .name                   = "gpo:alarm_1",
-               .gpio                   = PCF_GPIO_ALARM1,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       { /* bit 1 */
-               .name                   = "gpo:alarm_2",
-               .gpio                   = PCF_GPIO_ALARM2,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       { /* bit 2 */
-               .name                   = "gpo:alarm_3",
-               .gpio                   = PCF_GPIO_ALARM3,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       { /* bit 3 */
-               .name                   = "gpo:alarm_4",
-               .gpio                   = PCF_GPIO_ALARM4,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-       /* bits 4, 5, 6 not used */
-       { /* bit 7 */
-               .name                   = "gpo:alarm_v_relay_on",
-               .gpio                   = PCF_GPIO_ALARM_V_RELAY_ON,
-               .active_low             = 0,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-};
-
-static struct gpio_led_platform_data pcf_gpio_led_info2 = {
-       .leds           = pcf_gpio_leds2,
-       .num_leds       = ARRAY_SIZE(pcf_gpio_leds2),
-};
-
-static struct platform_device pcf_leds2 = {
-       .name   = "leds-gpio",
-       .id     = 2,
-       .dev    = {
-               .platform_data  = &pcf_gpio_led_info2,
-       }
-};
-
-/* PCF8574 0x24 GPIO U1 on the GS_2G-OPT23-A_V0 board (Modem) */
-static struct gpio_led pcf_gpio_leds3[] = {
-       { /* bit 0 */
-               .name                   = "gpo:modem_power",
-               .gpio                   = PCF_GPIO_MODEM_POWER,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_OFF,
-       },
-               /* bits 1 and 2 not used */
-       { /* bit 3 */
-               .name                   = "gpo:modem_reset",
-               .gpio                   = PCF_GPIO_MODEM_RESET,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_ON,
-       },
-               /* bits 4, 5 and 6 not used */
-       { /* bit 7 */
-               .name                   = "gpo:trx_reset",
-               .gpio                   = PCF_GPIO_TRX_RESET,
-               .active_low             = 1,
-               .default_trigger        = "none",
-               .default_state          = LEDS_GPIO_DEFSTATE_ON,
-       }
-};
-
-static struct gpio_led_platform_data pcf_gpio_led_info3 = {
-       .leds           = pcf_gpio_leds3,
-       .num_leds       = ARRAY_SIZE(pcf_gpio_leds3),
-};
-
-static struct platform_device pcf_leds3 = {
-       .name   = "leds-gpio",
-       .id     = 3,
-       .dev    = {
-               .platform_data  = &pcf_gpio_led_info3,
-       }
-};
-
-static void __init gsia18s_pcf_leds_init(void)
-{
-       platform_device_register(&pcf_leds1);
-       platform_device_register(&pcf_leds2);
-       platform_device_register(&pcf_leds3);
-}
-
-/*
- * SPI busses.
- */
-static struct spi_board_info gsia18s_spi_devices[] = {
-       { /* User accessible spi0, cs0 used for communication with MSP RTC */
-               .modalias       = "spidev",
-               .bus_num        = 0,
-               .chip_select    = 0,
-               .max_speed_hz   = 580000,
-               .mode           = SPI_MODE_1,
-       },
-       { /* User accessible spi1, cs0 used for communication with int. DSP */
-               .modalias       = "spidev",
-               .bus_num        = 1,
-               .chip_select    = 0,
-               .max_speed_hz   = 5600000,
-               .mode           = SPI_MODE_0,
-       },
-       { /* User accessible spi1, cs1 used for communication with ext. DSP */
-               .modalias       = "spidev",
-               .bus_num        = 1,
-               .chip_select    = 1,
-               .max_speed_hz   = 5600000,
-               .mode           = SPI_MODE_0,
-       },
-       { /* User accessible spi1, cs2 used for communication with ext. DSP */
-               .modalias       = "spidev",
-               .bus_num        = 1,
-               .chip_select    = 2,
-               .max_speed_hz   = 5600000,
-               .mode           = SPI_MODE_0,
-       },
-       { /* User accessible spi1, cs3 used for communication with ext. DSP */
-               .modalias       = "spidev",
-               .bus_num        = 1,
-               .chip_select    = 3,
-               .max_speed_hz   = 5600000,
-               .mode           = SPI_MODE_0,
-       }
-};
-
-/*
- * GPI Buttons
- */
-static struct gpio_keys_button buttons[] = {
-       {
-               .gpio           = GPIO_TRIG_NET_IN,
-               .code           = BTN_1,
-               .desc           = "TRIG_NET_IN",
-               .type           = EV_KEY,
-               .active_low     = 0,
-               .wakeup         = 1,
-       },
-       { /* SW80 on the GS_IA18_S-MN board*/
-               .gpio           = GPIO_CARD_UNMOUNT_0,
-               .code           = BTN_2,
-               .desc           = "Card umount 0",
-               .type           = EV_KEY,
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       { /* SW79 on the GS_IA18_S-MN board*/
-               .gpio           = GPIO_CARD_UNMOUNT_1,
-               .code           = BTN_3,
-               .desc           = "Card umount 1",
-               .type           = EV_KEY,
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       { /* SW280 on the GS_IA18-CB board*/
-               .gpio           = GPIO_KEY_POWER,
-               .code           = KEY_POWER,
-               .desc           = "Power Off Button",
-               .type           = EV_KEY,
-               .active_low     = 0,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data button_data = {
-       .buttons        = buttons,
-       .nbuttons       = ARRAY_SIZE(buttons),
-};
-
-static struct platform_device button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &button_data,
-       }
-};
-
-static void __init gsia18s_add_device_buttons(void)
-{
-       at91_set_gpio_input(GPIO_TRIG_NET_IN, 1);
-       at91_set_deglitch(GPIO_TRIG_NET_IN, 1);
-       at91_set_gpio_input(GPIO_CARD_UNMOUNT_0, 1);
-       at91_set_deglitch(GPIO_CARD_UNMOUNT_0, 1);
-       at91_set_gpio_input(GPIO_CARD_UNMOUNT_1, 1);
-       at91_set_deglitch(GPIO_CARD_UNMOUNT_1, 1);
-       at91_set_gpio_input(GPIO_KEY_POWER, 0);
-       at91_set_deglitch(GPIO_KEY_POWER, 1);
-
-       platform_device_register(&button_device);
-}
-
-/*
- * I2C
- */
-static int pcf8574x_0x20_setup(struct i2c_client *client, int gpio,
-                               unsigned int ngpio, void *context)
-{
-       int status;
-
-       status = gpio_request(gpio + PCF_GPIO_ETH_DETECT, "eth_det");
-       if (status < 0) {
-               pr_err("error: can't request GPIO%d\n",
-                       gpio + PCF_GPIO_ETH_DETECT);
-               return status;
-       }
-       status = gpio_direction_input(gpio + PCF_GPIO_ETH_DETECT);
-       if (status < 0) {
-               pr_err("error: can't setup GPIO%d as input\n",
-                       gpio + PCF_GPIO_ETH_DETECT);
-               return status;
-       }
-       status = gpio_export(gpio + PCF_GPIO_ETH_DETECT, false);
-       if (status < 0) {
-               pr_err("error: can't export GPIO%d\n",
-                       gpio + PCF_GPIO_ETH_DETECT);
-               return status;
-       }
-       status = gpio_sysfs_set_active_low(gpio + PCF_GPIO_ETH_DETECT, 1);
-       if (status < 0) {
-               pr_err("error: gpio_sysfs_set active_low(GPIO%d, 1)\n",
-                       gpio + PCF_GPIO_ETH_DETECT);
-               return status;
-       }
-
-       return 0;
-}
-
-static int pcf8574x_0x20_teardown(struct i2c_client *client, int gpio,
-                                       unsigned ngpio, void *context)
-{
-       gpio_free(gpio + PCF_GPIO_ETH_DETECT);
-       return 0;
-}
-
-static struct pcf857x_platform_data pcf20_pdata = {
-       .gpio_base      = GS_IA18_S_PCF_GPIO_BASE0,
-       .n_latch        = (1 << 4),
-       .setup          = pcf8574x_0x20_setup,
-       .teardown       = pcf8574x_0x20_teardown,
-};
-
-static struct pcf857x_platform_data pcf22_pdata = {
-       .gpio_base      = GS_IA18_S_PCF_GPIO_BASE1,
-};
-
-static struct pcf857x_platform_data pcf24_pdata = {
-       .gpio_base      = GS_IA18_S_PCF_GPIO_BASE2,
-};
-
-static struct i2c_board_info __initdata gsia18s_i2c_devices[] = {
-       { /* U1 on the GS_IA18-CB_V3 board */
-               I2C_BOARD_INFO("pcf8574", 0x20),
-               .platform_data = &pcf20_pdata,
-       },
-       { /* U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
-               I2C_BOARD_INFO("pcf8574", 0x22),
-               .platform_data = &pcf22_pdata,
-       },
-       { /* U1 on the GS_2G-OPT23-A_V0 board (Modem) */
-               I2C_BOARD_INFO("pcf8574", 0x24),
-               .platform_data = &pcf24_pdata,
-       },
-       { /* U161 on the GS_IA18_S-MN board */
-               I2C_BOARD_INFO("24c1024", 0x50),
-       },
-       { /* U162 on the GS_IA18_S-MN board */
-               I2C_BOARD_INFO("24c01", 0x53),
-       },
-};
-
-/*
- * Compact Flash
- */
-static struct at91_cf_data __initdata gsia18s_cf1_data = {
-       .irq_pin        = AT91_PIN_PA27,
-       .det_pin        = AT91_PIN_PB30,
-       .vcc_pin        = -EINVAL,
-       .rst_pin        = AT91_PIN_PB31,
-       .chipselect     = 5,
-       .flags          = AT91_CF_TRUE_IDE,
-};
-
-/* Power Off by RTC */
-static void gsia18s_power_off(void)
-{
-       pr_notice("Power supply will be switched off automatically now or after 60 seconds without ArmDAS.\n");
-       at91_set_gpio_output(AT91_PIN_PA25, 1);
-       /* Spin to death... */
-       while (1)
-               ;
-}
-
-static int __init gsia18s_power_off_init(void)
-{
-       pm_power_off = gsia18s_power_off;
-       return 0;
-}
-
-/* ---------------------------------------------------------------------------*/
-
-static void __init gsia18s_board_init(void)
-{
-       /*
-        * USART0 on ttyS1 (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI).
-        * Used for Internal Analog Modem.
-        */
-       at91_register_uart(AT91SAM9260_ID_US0, 1,
-                               ATMEL_UART_CTS | ATMEL_UART_RTS |
-                               ATMEL_UART_DTR | ATMEL_UART_DSR |
-                               ATMEL_UART_DCD | ATMEL_UART_RI);
-       /*
-        * USART1 on ttyS2 (Rx, Tx, CTS, RTS).
-        * Used for GPS or WiFi or Data stream.
-        */
-       at91_register_uart(AT91SAM9260_ID_US1, 2,
-                               ATMEL_UART_CTS | ATMEL_UART_RTS);
-       /*
-        * USART2 on ttyS3 (Rx, Tx, CTS, RTS).
-        * Used for External Modem.
-        */
-       at91_register_uart(AT91SAM9260_ID_US2, 3,
-                               ATMEL_UART_CTS | ATMEL_UART_RTS);
-       /*
-        * USART3 on ttyS4 (Rx, Tx, RTS).
-        * Used for RS-485.
-        */
-       at91_register_uart(AT91SAM9260_ID_US3, 4, ATMEL_UART_RTS);
-
-       /*
-        * USART4 on ttyS5 (Rx, Tx).
-        * Used for TRX433 Radio Module.
-        */
-       at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-       stamp9g20_board_init();
-       at91_add_device_usbh(&usbh_data);
-       at91_add_device_udc(&udc_data);
-       at91_add_device_eth(&macb_data);
-       gsia18s_leds_init();
-       gsia18s_pcf_leds_init();
-       gsia18s_add_device_buttons();
-       at91_add_device_i2c(gsia18s_i2c_devices,
-                               ARRAY_SIZE(gsia18s_i2c_devices));
-       at91_add_device_cf(&gsia18s_cf1_data);
-       at91_add_device_spi(gsia18s_spi_devices,
-                               ARRAY_SIZE(gsia18s_spi_devices));
-       gsia18s_power_off_init();
-}
-
-MACHINE_START(GSIA18S, "GS_IA18_S")
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = gsia18s_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = gsia18s_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
deleted file mode 100644 (file)
index 93b1df4..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-kafa.c
- *
- *  Copyright (C) 2006 Sperry-Sun
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/cpu.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init kafa_init_early(void)
-{
-       /* Set cpu type: PQFP */
-       at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata kafa_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC4,
-       .is_rmii        = 0,
-};
-
-static struct at91_usbh_data __initdata kafa_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata kafa_udc_data = {
-       .vbus_pin       = AT91_PIN_PB6,
-       .pullup_pin     = AT91_PIN_PB7,
-};
-
-/*
- * LEDs
- */
-static struct gpio_led kafa_leds[] = {
-       {       /* D1 */
-               .name                   = "led1",
-               .gpio                   = AT91_PIN_PB4,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-};
-
-static void __init kafa_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1 (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91RM9200_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&kafa_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&kafa_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&kafa_udc_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* SPI */
-       at91_add_device_spi(NULL, 0);
-       /* LEDs */
-       at91_gpio_leds(kafa_leds, ARRAY_SIZE(kafa_leds));
-}
-
-MACHINE_START(KAFA, "Sperry-Sun KAFA")
-       /* Maintainer: Sergei Sharonov */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = kafa_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = kafa_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
deleted file mode 100644 (file)
index d58d362..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-kb9202.c
- *
- *  Copyright (c) 2005 kb_admin
- *                    KwikByte, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/cpu.h>
-#include <mach/at91rm9200_mc.h>
-#include <mach/at91_ramc.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init kb9202_init_early(void)
-{
-       /* Set cpu type: PQFP */
-       at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
-       /* Initialize processor: 10 MHz crystal */
-       at91_initialize(10000000);
-}
-
-static struct macb_platform_data __initdata kb9202_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PB29,
-       .is_rmii        = 0,
-};
-
-static struct at91_usbh_data __initdata kb9202_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata kb9202_udc_data = {
-       .vbus_pin       = AT91_PIN_PB24,
-       .pullup_pin     = AT91_PIN_PB22,
-};
-
-static struct mci_platform_data __initdata kb9202_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PB2,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-static struct mtd_partition __initdata kb9202_nand_partition[] = {
-       {
-               .name   = "nand_fs",
-               .offset = 0,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata kb9202_nand_data = {
-       .ale            = 22,
-       .cle            = 21,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PC29,
-       .enable_pin     = AT91_PIN_PC28,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .parts          = kb9202_nand_partition,
-       .num_parts      = ARRAY_SIZE(kb9202_nand_partition),
-};
-
-/*
- * LEDs
- */
-static struct gpio_led kb9202_leds[] = {
-       {       /* D1 */
-               .name                   = "led1",
-               .gpio                   = AT91_PIN_PC19,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* D2 */
-               .name                   = "led2",
-               .gpio                   = AT91_PIN_PC18,
-               .active_low             = 1,
-               .default_trigger        = "timer",
-       }
-};
-
-static void __init kb9202_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1 (Rx & Tx only) */
-       at91_register_uart(AT91RM9200_ID_US0, 1, 0);
-
-       /* USART1 on ttyS2 (Rx & Tx only) - IRDA (optional) */
-       at91_register_uart(AT91RM9200_ID_US1, 2, 0);
-
-       /* USART3 on ttyS3 (Rx, Tx, CTS, RTS) - RS485 (optional) */
-       at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&kb9202_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&kb9202_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&kb9202_udc_data);
-       /* MMC */
-       at91_add_device_mci(0, &kb9202_mci0_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* SPI */
-       at91_add_device_spi(NULL, 0);
-       /* NAND */
-       at91_add_device_nand(&kb9202_nand_data);
-       /* LEDs */
-       at91_gpio_leds(kb9202_leds, ARRAY_SIZE(kb9202_leds));
-}
-
-MACHINE_START(KB9200, "KB920x")
-       /* Maintainer: KwikByte, Inc. */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = kb9202_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = kb9202_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
deleted file mode 100644 (file)
index 9c26b94..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- *  Copyright (C) 2010 Christian Glindkamp <christian.glindkamp@taskit.de>
- *                     taskit GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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
- */
-/*
- * copied and adjusted from board-stamp9g20.c
- * by Peter Gsellmann <pgsellmann@portner-elektronik.at>
- */
-
-#include <linux/mm.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/w1-gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <mach/at91sam9_smc.h>
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "stamp9g20.h"
-#include "gpio.h"
-
-
-static void __init pcontrol_g20_init_early(void)
-{
-       stamp9g20_init_early();
-}
-
-static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
-       .ncs_read_setup         = 16,
-       .nrd_setup              = 18,
-       .ncs_write_setup        = 16,
-       .nwe_setup              = 18,
-
-       .ncs_read_pulse         = 63,
-       .nrd_pulse              = 55,
-       .ncs_write_pulse        = 63,
-       .nwe_pulse              = 55,
-
-       .read_cycle             = 127,
-       .write_cycle            = 127,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_SELECT
-                       | AT91_SMC_DBW_8 | AT91_SMC_PS_4
-                       | AT91_SMC_TDFMODE,
-       .tdf_cycles             = 3,
-}, {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 0,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 8,
-       .nrd_pulse              = 8,
-       .ncs_write_pulse        = 5,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 8,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_SELECT
-                       | AT91_SMC_DBW_16 | AT91_SMC_PS_8
-                       | AT91_SMC_TDFMODE,
-       .tdf_cycles             = 1,
-} };
-
-static void __init add_device_pcontrol(void)
-{
-       /* configure chip-select 4 (IO compatible to 8051  X4 ) */
-       sam9_smc_configure(0, 4, &pcontrol_smc_config[0]);
-       /* configure chip-select 7 (FerroRAM 256KiBx16bit MR2A16A  D4 ) */
-       sam9_smc_configure(0, 7, &pcontrol_smc_config[1]);
-}
-
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata pcontrol_g20_udc_data = {
-       .vbus_pin       = AT91_PIN_PA22,        /* Detect +5V bus voltage */
-       .pullup_pin     = AT91_PIN_PA4,         /* K-state, active low */
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata macb_data = {
-       .phy_irq_pin    = AT91_PIN_PA28,
-       .is_rmii        = 1,
-};
-
-
-/*
- * I2C devices: eeprom and phy/switch
- */
-static struct i2c_board_info __initdata pcontrol_g20_i2c_devices[] = {
-{              /* D7  address width=2, 8KiB */
-       I2C_BOARD_INFO("24c64", 0x50)
-}, {           /* D8  address width=1, 1 byte has 32 bits! */
-       I2C_BOARD_INFO("lan9303", 0x0a)
-}, };
-
-
-/*
- * LEDs
- */
-static struct gpio_led pcontrol_g20_leds[] = {
-       {
-               .name                   = "LED1",       /* red  H5 */
-               .gpio                   = AT91_PIN_PB18,
-               .active_low             = 1,
-               .default_trigger        = "none",       /* supervisor */
-       }, {
-               .name                   = "LED2",       /* yellow  H7 */
-               .gpio                   = AT91_PIN_PB19,
-               .active_low             = 1,
-               .default_trigger        = "mmc0",       /* SD-card activity */
-       }, {
-               .name                   = "LED3",       /* green  H2 */
-               .gpio                   = AT91_PIN_PB20,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",  /* blinky */
-       }, {
-               .name                   = "LED4",       /* red  H3 */
-               .gpio                   = AT91_PIN_PC6,
-               .active_low             = 1,
-               .default_trigger        = "none",       /* connection lost */
-       }, {
-               .name                   = "LED5",       /* yellow  H6 */
-               .gpio                   = AT91_PIN_PC7,
-               .active_low             = 1,
-               .default_trigger        = "none",       /* unsent data */
-       }, {
-               .name                   = "LED6",       /* green  H1 */
-               .gpio                   = AT91_PIN_PC9,
-               .active_low             = 1,
-               .default_trigger        = "none",       /* snafu */
-       }
-};
-
-
-/*
- * SPI devices
- */
-static struct spi_board_info pcontrol_g20_spi_devices[] = {
-       {
-               .modalias       = "spidev",     /* HMI port  X4 */
-               .chip_select    = 1,
-               .max_speed_hz   = 50 * 1000 * 1000,
-               .bus_num        = 0,
-       }, {
-               .modalias       = "spidev",     /* piggyback  A2 */
-               .chip_select    = 0,
-               .max_speed_hz   = 50 * 1000 * 1000,
-               .bus_num        = 1,
-       },
-};
-
-
-static void __init pcontrol_g20_board_init(void)
-{
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
-                                               | ATMEL_UART_RTS);
-
-       /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485  X5 */
-       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
-                                               | ATMEL_UART_RTS);
-
-       /* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
-       at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
-       stamp9g20_board_init();
-       at91_add_device_usbh(&usbh_data);
-       at91_add_device_eth(&macb_data);
-       at91_add_device_i2c(pcontrol_g20_i2c_devices,
-               ARRAY_SIZE(pcontrol_g20_i2c_devices));
-       add_device_pcontrol();
-       at91_add_device_spi(pcontrol_g20_spi_devices,
-               ARRAY_SIZE(pcontrol_g20_spi_devices));
-       at91_add_device_udc(&pcontrol_g20_udc_data);
-       at91_gpio_leds(pcontrol_g20_leds,
-               ARRAY_SIZE(pcontrol_g20_leds));
-       /* piggyback  A2 */
-       at91_set_gpio_output(AT91_PIN_PB31, 1);
-}
-
-
-MACHINE_START(PCONTROL_G20, "PControl G20")
-       /* Maintainer: pgsellmann@portner-elektronik.at */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = pcontrol_g20_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = pcontrol_g20_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
deleted file mode 100644 (file)
index 2c0f2d5..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-picotux200.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2007 Kleinhenz Elektronik GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mtd/physmap.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/at91rm9200_mc.h>
-#include <mach/at91_ramc.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init picotux200_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata picotux200_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC4,
-       .is_rmii        = 1,
-};
-
-static struct at91_usbh_data __initdata picotux200_usbh_data = {
-       .ports          = 1,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct mci_platform_data __initdata picotux200_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PB27,
-               .wp_pin         = AT91_PIN_PA17,
-       },
-};
-
-#define PICOTUX200_FLASH_BASE  AT91_CHIPSELECT_0
-#define PICOTUX200_FLASH_SIZE  SZ_4M
-
-static struct physmap_flash_data picotux200_flash_data = {
-       .width  = 2,
-};
-
-static struct resource picotux200_flash_resource = {
-       .start          = PICOTUX200_FLASH_BASE,
-       .end            = PICOTUX200_FLASH_BASE + PICOTUX200_FLASH_SIZE - 1,
-       .flags          = IORESOURCE_MEM,
-};
-
-static struct platform_device picotux200_flash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-                               .platform_data  = &picotux200_flash_data,
-                       },
-       .resource       = &picotux200_flash_resource,
-       .num_resources  = 1,
-};
-
-static void __init picotux200_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                         | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                         | ATMEL_UART_RI);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&picotux200_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&picotux200_usbh_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* MMC */
-       at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
-       at91_add_device_mci(0, &picotux200_mci0_data);
-       /* NOR Flash */
-       platform_device_register(&picotux200_flash);
-}
-
-MACHINE_START(PICOTUX2XX, "picotux 200")
-       /* Maintainer: Kleinhenz Elektronik GmbH */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = picotux200_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = picotux200_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
deleted file mode 100644 (file)
index 953cea4..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-rm9200ek.c
- *
- *  Copyright (C) 2005 SAN People
- *
- *  Epson S1D framebuffer glue code is:
- *     Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.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.
- *
- * 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/at91rm9200_mc.h>
-#include <mach/at91_ramc.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-static struct macb_platform_data __initdata ek_eth_data = {
-       .phy_irq_pin    = AT91_PIN_PC4,
-       .is_rmii        = 1,
-};
-
-static struct at91_usbh_data __initdata ek_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata ek_udc_data = {
-       .vbus_pin       = AT91_PIN_PD4,
-       .pullup_pin     = AT91_PIN_PD5,
-};
-
-#ifndef CONFIG_MTD_AT91_DATAFLASH_CARD
-static struct mci_platform_data __initdata ek_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PB27,
-               .wp_pin         = AT91_PIN_PA17,
-       }
-};
-#endif
-
-static struct spi_board_info ek_spi_devices[] = {
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-       },
-#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-       {       /* DataFlash card */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 3,
-               .max_speed_hz   = 15 * 1000 * 1000,
-       },
-#endif
-};
-
-static struct i2c_board_info __initdata ek_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("ics1523", 0x26),
-       },
-       {
-               I2C_BOARD_INFO("dac3550", 0x4d),
-       }
-};
-
-#define EK_FLASH_BASE  AT91_CHIPSELECT_0
-#define EK_FLASH_SIZE  SZ_8M
-
-static struct physmap_flash_data ek_flash_data = {
-       .width          = 2,
-};
-
-static struct resource ek_flash_resource = {
-       .start          = EK_FLASH_BASE,
-       .end            = EK_FLASH_BASE + EK_FLASH_SIZE - 1,
-       .flags          = IORESOURCE_MEM,
-};
-
-static struct platform_device ek_flash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-                               .platform_data  = &ek_flash_data,
-                       },
-       .resource       = &ek_flash_resource,
-       .num_resources  = 1,
-};
-
-static struct gpio_led ek_leds[] = {
-       {       /* "user led 1", DS2 */
-               .name                   = "green",
-               .gpio                   = AT91_PIN_PB0,
-               .active_low             = 1,
-               .default_trigger        = "mmc0",
-       },
-       {       /* "user led 2", DS4 */
-               .name                   = "yellow",
-               .gpio                   = AT91_PIN_PB1,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* "user led 3", DS6 */
-               .name                   = "red",
-               .gpio                   = AT91_PIN_PB2,
-               .active_low             = 1,
-       }
-};
-
-static void __init ek_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                          | ATMEL_UART_RI);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&ek_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&ek_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&ek_udc_data);
-       at91_set_multi_drive(ek_udc_data.pullup_pin, 1);        /* pullup_pin is connected to reset */
-       /* I2C */
-       at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
-       /* DataFlash card */
-       at91_set_gpio_output(AT91_PIN_PB22, 0);
-#else
-       /* MMC */
-       at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
-       at91_add_device_mci(0, &ek_mci0_data);
-#endif
-       /* NOR Flash */
-       platform_device_register(&ek_flash);
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-       /* VGA */
-//     ek_add_device_video();
-}
-
-MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
-       /* Maintainer: SAN People/Atmel */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
deleted file mode 100644 (file)
index c2166e3..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-sam9-l9260.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 Atmel
- *  Copyright (C) 2007 Olimex 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.
- *
- * 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/at91sam9_smc.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-       .vbus_pin       = AT91_PIN_PC5,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 1,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-       {       /* DataFlash card */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#endif
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata ek_macb_data = {
-       .phy_irq_pin    = AT91_PIN_PA7,
-       .is_rmii        = 0,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Bootloader Area",
-               .offset = 0,
-               .size   = 10 * SZ_1M,
-       },
-       {
-               .name   = "User Area",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .parts          = ek_nand_partition,
-       .num_parts      = ARRAY_SIZE(ek_nand_partition),
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 3,
-       .nrd_pulse              = 3,
-       .ncs_write_pulse        = 3,
-       .nwe_pulse              = 3,
-
-       .read_cycle             = 5,
-       .write_cycle            = 5,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct mci_platform_data __initdata ek_mci0_data = {
-       .slot[1] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PC8,
-               .wp_pin         = AT91_PIN_PC4,
-       },
-};
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-       {       /* D1 */
-               .name                   = "led1",
-               .gpio                   = AT91_PIN_PA9,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* D2 */
-               .name                   = "led2",
-               .gpio                   = AT91_PIN_PA6,
-               .active_low             = 1,
-               .default_trigger        = "timer",
-       }
-};
-
-static void __init ek_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                          | ATMEL_UART_RI);
-
-       /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&ek_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&ek_udc_data);
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* NAND */
-       ek_add_device_nand();
-       /* Ethernet */
-       at91_add_device_eth(&ek_macb_data);
-       /* MMC */
-       at91_add_device_mci(0, &ek_mci0_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-}
-
-MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
-       /* Maintainer: Olimex */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
deleted file mode 100644 (file)
index bf8a946..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-sam9260ek.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/at73c213.h>
-#include <linux/clk.h>
-#include <linux/platform_data/at24.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/system_rev.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-       .vbus_pin       = AT91_PIN_PC5,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-
-/*
- * Audio
- */
-static struct at73c213_board_info at73c213_data = {
-       .ssc_id         = 0,
-       .shortname      = "AT91SAM9260-EK external DAC",
-};
-
-#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
-static void __init at73c213_set_clk(struct at73c213_board_info *info)
-{
-       struct clk *pck0;
-       struct clk *plla;
-
-       pck0 = clk_get(NULL, "pck0");
-       plla = clk_get(NULL, "plla");
-
-       /* AT73C213 MCK Clock */
-       at91_set_B_periph(AT91_PIN_PC1, 0);     /* PCK0 */
-
-       clk_set_parent(pck0, plla);
-       clk_put(plla);
-
-       info->dac_clk = pck0;
-}
-#else
-static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
-#endif
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 1,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-       {       /* DataFlash card */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#endif
-#endif
-#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
-       {       /* AT73C213 DAC */
-               .modalias       = "at73c213",
-               .chip_select    = 0,
-               .max_speed_hz   = 10 * 1000 * 1000,
-               .bus_num        = 1,
-               .mode           = SPI_MODE_1,
-               .platform_data  = &at73c213_data,
-       },
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata ek_macb_data = {
-       .phy_irq_pin    = AT91_PIN_PA7,
-       .is_rmii        = 1,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Partition 1",
-               .offset = 0,
-               .size   = SZ_256K,
-       },
-       {
-               .name   = "Partition 2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .on_flash_bbt   = 1,
-       .parts          = ek_nand_partition,
-       .num_parts      = ARRAY_SIZE(ek_nand_partition),
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 3,
-       .nrd_pulse              = 3,
-       .ncs_write_pulse        = 3,
-       .nwe_pulse              = 3,
-
-       .read_cycle             = 5,
-       .write_cycle            = 5,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-       .tdf_cycles             = 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       ek_nand_data.bus_width_16 = board_have_nand_16bit();
-       /* setup bus-width (8 or 16) */
-       if (ek_nand_data.bus_width_16)
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-       else
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct mci_platform_data __initdata ek_mci0_data = {
-       .slot[1] = {
-               .bus_width      = 4,
-               .detect_pin     = -EINVAL,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-       {       /* "bottom" led, green, userled1 to be defined */
-               .name                   = "ds5",
-               .gpio                   = AT91_PIN_PA6,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* "power" led, yellow */
-               .name                   = "ds1",
-               .gpio                   = AT91_PIN_PA9,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-/*
- * I2C devices
- */
-static struct at24_platform_data at24c512 = {
-       .byte_len       = SZ_512K / 8,
-       .page_size      = 128,
-       .flags          = AT24_FLAG_ADDR16,
-};
-
-static struct i2c_board_info __initdata ek_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("24c512", 0x50),
-               .platform_data = &at24c512,
-       },
-       /* more devices can be added using expansion connectors */
-};
-
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-       {
-               .gpio           = AT91_PIN_PA30,
-               .code           = BTN_3,
-               .desc           = "Button 3",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PA31,
-               .code           = BTN_4,
-               .desc           = "Button 4",
-               .active_low     = 1,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-       .buttons        = ek_buttons,
-       .nbuttons       = ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_button_data,
-       }
-};
-
-static void __init ek_add_device_buttons(void)
-{
-       at91_set_gpio_input(AT91_PIN_PA30, 1);  /* btn3 */
-       at91_set_deglitch(AT91_PIN_PA30, 1);
-       at91_set_gpio_input(AT91_PIN_PA31, 1);  /* btn4 */
-       at91_set_deglitch(AT91_PIN_PA31, 1);
-
-       platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-
-static void __init ek_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                          | ATMEL_UART_RI);
-
-       /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&ek_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&ek_udc_data);
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* NAND */
-       ek_add_device_nand();
-       /* Ethernet */
-       at91_add_device_eth(&ek_macb_data);
-       /* MMC */
-       at91_add_device_mci(0, &ek_mci0_data);
-       /* I2C */
-       at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
-       /* SSC (to AT73C213) */
-       at73c213_set_clk(&at73c213_data);
-       at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-       /* Push Buttons */
-       ek_add_device_buttons();
-}
-
-MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
deleted file mode 100644 (file)
index e85ada8..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-sam9261ek.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2006 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/ads7846.h>
-#include <linux/spi/at73c213.h>
-#include <linux/clk.h>
-#include <linux/dm9000.h>
-#include <linux/fb.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-
-#include <video/atmel_lcdc.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/system_rev.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * DM9000 ethernet device
- */
-#if defined(CONFIG_DM9000)
-static struct resource dm9000_resource[] = {
-       [0] = {
-               .start  = AT91_CHIPSELECT_2,
-               .end    = AT91_CHIPSELECT_2 + 3,
-               .flags  = IORESOURCE_MEM
-       },
-       [1] = {
-               .start  = AT91_CHIPSELECT_2 + 0x44,
-               .end    = AT91_CHIPSELECT_2 + 0xFF,
-               .flags  = IORESOURCE_MEM
-       },
-       [2] = {
-               .flags  = IORESOURCE_IRQ
-                       | IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE,
-       }
-};
-
-static struct dm9000_plat_data dm9000_platdata = {
-       .flags          = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
-};
-
-static struct platform_device dm9000_device = {
-       .name           = "dm9000",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(dm9000_resource),
-       .resource       = dm9000_resource,
-       .dev            = {
-               .platform_data  = &dm9000_platdata,
-       }
-};
-
-/*
- * SMC timings for the DM9000.
- * Note: These timings were calculated for MASTER_CLOCK = 100000000 according to the DM9000 timings.
- */
-static struct sam9_smc_config __initdata dm9000_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 8,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 8,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 16,
-       .write_cycle            = 16,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16,
-       .tdf_cycles             = 1,
-};
-
-static void __init ek_add_device_dm9000(void)
-{
-       struct resource *r = &dm9000_resource[2];
-
-       /* Configure chip-select 2 (DM9000) */
-       sam9_smc_configure(0, 2, &dm9000_smc_config);
-
-       /* Configure Reset signal as output */
-       at91_set_gpio_output(AT91_PIN_PC10, 0);
-
-       /* Configure Interrupt pin as input, no pull-up */
-       at91_set_gpio_input(AT91_PIN_PC11, 0);
-
-       r->start = r->end = gpio_to_irq(AT91_PIN_PC11);
-       platform_device_register(&dm9000_device);
-}
-#else
-static void __init ek_add_device_dm9000(void) {}
-#endif /* CONFIG_DM9000 */
-
-
-/*
- * USB Host Port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-
-/*
- * USB Device Port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-       .vbus_pin       = AT91_PIN_PB29,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Partition 1",
-               .offset = 0,
-               .size   = SZ_256K,
-       },
-       {
-               .name   = "Partition 2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 22,
-       .cle            = 21,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PC15,
-       .enable_pin     = AT91_PIN_PC14,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .on_flash_bbt   = 1,
-       .parts          = ek_nand_partition,
-       .num_parts      = ARRAY_SIZE(ek_nand_partition),
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 3,
-       .nrd_pulse              = 3,
-       .ncs_write_pulse        = 3,
-       .nwe_pulse              = 3,
-
-       .read_cycle             = 5,
-       .write_cycle            = 5,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-       .tdf_cycles             = 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       ek_nand_data.bus_width_16 = board_have_nand_16bit();
-       /* setup bus-width (8 or 16) */
-       if (ek_nand_data.bus_width_16)
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-       else
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-/*
- * SPI related devices
- */
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-
-/*
- * ADS7846 Touchscreen
- */
-#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-
-static int ads7843_pendown_state(void)
-{
-       return !at91_get_gpio_value(AT91_PIN_PC2);      /* Touchscreen PENIRQ */
-}
-
-static struct ads7846_platform_data ads_info = {
-       .model                  = 7843,
-       .x_min                  = 150,
-       .x_max                  = 3830,
-       .y_min                  = 190,
-       .y_max                  = 3830,
-       .vref_delay_usecs       = 100,
-       .x_plate_ohms           = 450,
-       .y_plate_ohms           = 250,
-       .pressure_max           = 15000,
-       .debounce_max           = 1,
-       .debounce_rep           = 0,
-       .debounce_tol           = (~0),
-       .get_pendown_state      = ads7843_pendown_state,
-};
-
-static void __init ek_add_device_ts(void)
-{
-       at91_set_B_periph(AT91_PIN_PC2, 1);     /* External IRQ0, with pullup */
-       at91_set_gpio_input(AT91_PIN_PA11, 1);  /* Touchscreen BUSY signal */
-}
-#else
-static void __init ek_add_device_ts(void) {}
-#endif
-
-/*
- * Audio
- */
-static struct at73c213_board_info at73c213_data = {
-       .ssc_id         = 1,
-       .shortname      = "AT91SAM9261/9G10-EK external DAC",
-};
-
-#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
-static void __init at73c213_set_clk(struct at73c213_board_info *info)
-{
-       struct clk *pck2;
-       struct clk *plla;
-
-       pck2 = clk_get(NULL, "pck2");
-       plla = clk_get(NULL, "plla");
-
-       /* AT73C213 MCK Clock */
-       at91_set_B_periph(AT91_PIN_PB31, 0);    /* PCK2 */
-
-       clk_set_parent(pck2, plla);
-       clk_put(plla);
-
-       info->dac_clk = pck2;
-}
-#else
-static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
-#endif
-
-/*
- * SPI devices
- */
-static struct spi_board_info ek_spi_devices[] = {
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-       {
-               .modalias       = "ads7846",
-               .chip_select    = 2,
-               .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
-               .bus_num        = 0,
-               .platform_data  = &ads_info,
-               .irq            = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,
-               .controller_data = (void *) AT91_PIN_PA28,      /* CS pin */
-       },
-#endif
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-       {       /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 3,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#elif defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
-       {       /* AT73C213 DAC */
-               .modalias       = "at73c213",
-               .chip_select    = 3,
-               .max_speed_hz   = 10 * 1000 * 1000,
-               .bus_num        = 0,
-               .mode           = SPI_MODE_1,
-               .platform_data  = &at73c213_data,
-               .controller_data = (void*) AT91_PIN_PA29,       /* default for CS3 is PA6, but it must be PA29 */
-       },
-#endif
-};
-
-#else /* CONFIG_SPI_ATMEL_* */
-/* spi0 and mmc/sd share the same PIO pins: cannot be used at the same time */
-
-/*
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
-static struct mci_platform_data __initdata mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = -EINVAL,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-#endif /* CONFIG_SPI_ATMEL_* */
-
-
-/*
- * LCD Controller
- */
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-
-#if defined(CONFIG_FB_ATMEL_STN)
-
-/* STN */
-static struct fb_videomode at91_stn_modes[] = {
-        {
-               .name           = "SP06Q002 @ 75",
-               .refresh        = 75,
-               .xres           = 320,          .yres           = 240,
-               .pixclock       = KHZ2PICOS(1440),
-
-               .left_margin    = 1,            .right_margin   = 1,
-               .upper_margin   = 0,            .lower_margin   = 0,
-               .hsync_len      = 1,            .vsync_len      = 1,
-
-               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               .vmode          = FB_VMODE_NONINTERLACED,
-        },
-};
-
-static struct fb_monspecs at91fb_default_stn_monspecs = {
-        .manufacturer   = "HIT",
-        .monitor        = "SP06Q002",
-
-        .modedb         = at91_stn_modes,
-        .modedb_len     = ARRAY_SIZE(at91_stn_modes),
-        .hfmin          = 15000,
-        .hfmax          = 64000,
-        .vfmin          = 50,
-        .vfmax          = 150,
-};
-
-#define AT91SAM9261_DEFAULT_STN_LCDCON2        (ATMEL_LCDC_MEMOR_LITTLE \
-                                       | ATMEL_LCDC_DISTYPE_STNMONO \
-                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE \
-                                       | ATMEL_LCDC_IFWIDTH_4 \
-                                       | ATMEL_LCDC_SCANMOD_SINGLE)
-
-static void at91_lcdc_stn_power_control(struct atmel_lcdfb_pdata *pdata, int on)
-{
-       /* backlight */
-       if (on) {       /* power up */
-               at91_set_gpio_value(AT91_PIN_PC14, 0);
-               at91_set_gpio_value(AT91_PIN_PC15, 0);
-       } else {        /* power down */
-               at91_set_gpio_value(AT91_PIN_PC14, 1);
-               at91_set_gpio_value(AT91_PIN_PC15, 1);
-       }
-}
-
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
-       .default_bpp                    = 1,
-       .default_dmacon                 = ATMEL_LCDC_DMAEN,
-       .default_lcdcon2                = AT91SAM9261_DEFAULT_STN_LCDCON2,
-       .default_monspecs               = &at91fb_default_stn_monspecs,
-       .atmel_lcdfb_power_control      = at91_lcdc_stn_power_control,
-       .guard_time                     = 1,
-};
-
-#else
-
-/* TFT */
-static struct fb_videomode at91_tft_vga_modes[] = {
-       {
-               .name           = "TX09D50VM1CCA @ 60",
-               .refresh        = 60,
-               .xres           = 240,          .yres           = 320,
-               .pixclock       = KHZ2PICOS(4965),
-
-               .left_margin    = 1,            .right_margin   = 33,
-               .upper_margin   = 1,            .lower_margin   = 0,
-               .hsync_len      = 5,            .vsync_len      = 1,
-
-               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-};
-
-static struct fb_monspecs at91fb_default_tft_monspecs = {
-       .manufacturer   = "HIT",
-       .monitor        = "TX09D50VM1CCA",
-
-       .modedb         = at91_tft_vga_modes,
-       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
-       .hfmin          = 15000,
-       .hfmax          = 64000,
-       .vfmin          = 50,
-       .vfmax          = 150,
-};
-
-#define AT91SAM9261_DEFAULT_TFT_LCDCON2        (ATMEL_LCDC_MEMOR_LITTLE \
-                                       | ATMEL_LCDC_DISTYPE_TFT    \
-                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
-
-static void at91_lcdc_tft_power_control(struct atmel_lcdfb_pdata *pdata, int on)
-{
-       if (on)
-               at91_set_gpio_value(AT91_PIN_PA12, 0);  /* power up */
-       else
-               at91_set_gpio_value(AT91_PIN_PA12, 1);  /* power down */
-}
-
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
-       .lcdcon_is_backlight            = true,
-       .default_bpp                    = 16,
-       .default_dmacon                 = ATMEL_LCDC_DMAEN,
-       .default_lcdcon2                = AT91SAM9261_DEFAULT_TFT_LCDCON2,
-       .default_monspecs               = &at91fb_default_tft_monspecs,
-       .atmel_lcdfb_power_control      = at91_lcdc_tft_power_control,
-       .guard_time                     = 1,
-};
-#endif
-
-#else
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
-#endif
-
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-       {
-               .gpio           = AT91_PIN_PA27,
-               .code           = BTN_0,
-               .desc           = "Button 0",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PA26,
-               .code           = BTN_1,
-               .desc           = "Button 1",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PA25,
-               .code           = BTN_2,
-               .desc           = "Button 2",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PA24,
-               .code           = BTN_3,
-               .desc           = "Button 3",
-               .active_low     = 1,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-       .buttons        = ek_buttons,
-       .nbuttons       = ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_button_data,
-       }
-};
-
-static void __init ek_add_device_buttons(void)
-{
-       at91_set_gpio_input(AT91_PIN_PA27, 1);  /* btn0 */
-       at91_set_deglitch(AT91_PIN_PA27, 1);
-       at91_set_gpio_input(AT91_PIN_PA26, 1);  /* btn1 */
-       at91_set_deglitch(AT91_PIN_PA26, 1);
-       at91_set_gpio_input(AT91_PIN_PA25, 1);  /* btn2 */
-       at91_set_deglitch(AT91_PIN_PA25, 1);
-       at91_set_gpio_input(AT91_PIN_PA24, 1);  /* btn3 */
-       at91_set_deglitch(AT91_PIN_PA24, 1);
-
-       platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-       {       /* "bottom" led, green, userled1 to be defined */
-               .name                   = "ds7",
-               .gpio                   = AT91_PIN_PA14,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* "top" led, green, userled2 to be defined */
-               .name                   = "ds8",
-               .gpio                   = AT91_PIN_PA13,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* "power" led, yellow */
-               .name                   = "ds1",
-               .gpio                   = AT91_PIN_PA23,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-static void __init ek_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-       at91_add_device_serial();
-
-       if (cpu_is_at91sam9g10())
-               ek_lcdc_data.lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB;
-
-       /* USB Host */
-       at91_add_device_usbh(&ek_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&ek_udc_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* NAND */
-       ek_add_device_nand();
-       /* DM9000 ethernet */
-       ek_add_device_dm9000();
-
-       /* spi0 and mmc/sd share the same PIO pins */
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* Touchscreen */
-       ek_add_device_ts();
-       /* SSC (to AT73C213) */
-       at73c213_set_clk(&at73c213_data);
-       at91_add_device_ssc(AT91SAM9261_ID_SSC1, ATMEL_SSC_TX);
-#else
-       /* MMC */
-       at91_add_device_mci(0, &mci0_data);
-#endif
-       /* LCD Controller */
-       at91_add_device_lcdc(&ek_lcdc_data);
-       /* Push Buttons */
-       ek_add_device_buttons();
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-}
-
-MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
-
-MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
deleted file mode 100644 (file)
index d76680f..0000000
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-sam9263ek.c
- *
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2007 Atmel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/ads7846.h>
-#include <linux/platform_data/at24.h>
-#include <linux/fb.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/leds.h>
-#include <linux/pwm.h>
-#include <linux/leds_pwm.h>
-
-#include <video/atmel_lcdc.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/at91sam9_smc.h>
-#include <mach/system_rev.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 16.367 MHz crystal */
-       at91_initialize(16367660);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = { AT91_PIN_PA24, AT91_PIN_PA21 },
-       .vbus_pin_active_low = {1, 1},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-       .vbus_pin       = AT91_PIN_PA25,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-
-/*
- * ADS7846 Touchscreen
- */
-#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-static int ads7843_pendown_state(void)
-{
-       return !at91_get_gpio_value(AT91_PIN_PA15);     /* Touchscreen PENIRQ */
-}
-
-static struct ads7846_platform_data ads_info = {
-       .model                  = 7843,
-       .x_min                  = 150,
-       .x_max                  = 3830,
-       .y_min                  = 190,
-       .y_max                  = 3830,
-       .vref_delay_usecs       = 100,
-       .x_plate_ohms           = 450,
-       .y_plate_ohms           = 250,
-       .pressure_max           = 15000,
-       .debounce_max           = 1,
-       .debounce_rep           = 0,
-       .debounce_tol           = (~0),
-       .get_pendown_state      = ads7843_pendown_state,
-};
-
-static void __init ek_add_device_ts(void)
-{
-       at91_set_B_periph(AT91_PIN_PA15, 1);    /* External IRQ1, with pullup */
-       at91_set_gpio_input(AT91_PIN_PA31, 1);  /* Touchscreen BUSY signal */
-}
-#else
-static void __init ek_add_device_ts(void) {}
-#endif
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-       {       /* DataFlash card */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#endif
-#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-       {
-               .modalias       = "ads7846",
-               .chip_select    = 3,
-               .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
-               .bus_num        = 0,
-               .platform_data  = &ads_info,
-               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
-       },
-#endif
-};
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct mci_platform_data __initdata mci1_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PE18,
-               .wp_pin         = AT91_PIN_PE19,
-       },
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata ek_macb_data = {
-       .phy_irq_pin    = AT91_PIN_PE31,
-       .is_rmii        = 1,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Partition 1",
-               .offset = 0,
-               .size   = SZ_64M,
-       },
-       {
-               .name   = "Partition 2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PA22,
-       .enable_pin     = AT91_PIN_PD15,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .on_flash_bbt   = 1,
-       .parts          = ek_nand_partition,
-       .num_parts      = ARRAY_SIZE(ek_nand_partition),
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 3,
-       .nrd_pulse              = 3,
-       .ncs_write_pulse        = 3,
-       .nwe_pulse              = 3,
-
-       .read_cycle             = 5,
-       .write_cycle            = 5,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-       .tdf_cycles             = 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       ek_nand_data.bus_width_16 = board_have_nand_16bit();
-       /* setup bus-width (8 or 16) */
-       if (ek_nand_data.bus_width_16)
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-       else
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * I2C devices
- */
-static struct at24_platform_data at24c512 = {
-       .byte_len       = SZ_512K / 8,
-       .page_size      = 128,
-       .flags          = AT24_FLAG_ADDR16,
-};
-
-
-static struct i2c_board_info __initdata ek_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("24c512", 0x50),
-               .platform_data = &at24c512,
-       },
-       /* more devices can be added using expansion connectors */
-};
-
-/*
- * LCD Controller
- */
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static struct fb_videomode at91_tft_vga_modes[] = {
-       {
-               .name           = "TX09D50VM1CCA @ 60",
-               .refresh        = 60,
-               .xres           = 240,          .yres           = 320,
-               .pixclock       = KHZ2PICOS(4965),
-
-               .left_margin    = 1,            .right_margin   = 33,
-               .upper_margin   = 1,            .lower_margin   = 0,
-               .hsync_len      = 5,            .vsync_len      = 1,
-
-               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-};
-
-static struct fb_monspecs at91fb_default_monspecs = {
-       .manufacturer   = "HIT",
-       .monitor        = "TX09D70VM1CCA",
-
-       .modedb         = at91_tft_vga_modes,
-       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
-       .hfmin          = 15000,
-       .hfmax          = 64000,
-       .vfmin          = 50,
-       .vfmax          = 150,
-};
-
-#define AT91SAM9263_DEFAULT_LCDCON2    (ATMEL_LCDC_MEMOR_LITTLE \
-                                       | ATMEL_LCDC_DISTYPE_TFT \
-                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
-
-static void at91_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
-{
-       at91_set_gpio_value(AT91_PIN_PA30, on);
-}
-
-/* Driver datas */
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
-       .lcdcon_is_backlight            = true,
-       .default_bpp                    = 16,
-       .default_dmacon                 = ATMEL_LCDC_DMAEN,
-       .default_lcdcon2                = AT91SAM9263_DEFAULT_LCDCON2,
-       .default_monspecs               = &at91fb_default_monspecs,
-       .atmel_lcdfb_power_control      = at91_lcdc_power_control,
-       .guard_time                     = 1,
-};
-
-#else
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
-#endif
-
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-       {       /* BP1, "leftclic" */
-               .code           = BTN_LEFT,
-               .gpio           = AT91_PIN_PC5,
-               .active_low     = 1,
-               .desc           = "left_click",
-               .wakeup         = 1,
-       },
-       {       /* BP2, "rightclic" */
-               .code           = BTN_RIGHT,
-               .gpio           = AT91_PIN_PC4,
-               .active_low     = 1,
-               .desc           = "right_click",
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-       .buttons        = ek_buttons,
-       .nbuttons       = ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_button_data,
-       }
-};
-
-static void __init ek_add_device_buttons(void)
-{
-       at91_set_GPIO_periph(AT91_PIN_PC5, 1);  /* left button */
-       at91_set_deglitch(AT91_PIN_PC5, 1);
-       at91_set_GPIO_periph(AT91_PIN_PC4, 1);  /* right button */
-       at91_set_deglitch(AT91_PIN_PC4, 1);
-
-       platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-
-/*
- * AC97
- * reset_pin is not connected: NRST
- */
-static struct ac97c_platform_data ek_ac97_data = {
-       .reset_pin      = -EINVAL,
-};
-
-
-/*
- * LEDs ... these could all be PWM-driven, for variable brightness
- */
-static struct gpio_led ek_leds[] = {
-       {       /* "right" led, green, userled2 (could be driven by pwm2) */
-               .name                   = "ds2",
-               .gpio                   = AT91_PIN_PC29,
-               .active_low             = 1,
-               .default_trigger        = "nand-disk",
-       },
-       {       /* "power" led, yellow (could be driven by pwm0) */
-               .name                   = "ds3",
-               .gpio                   = AT91_PIN_PB7,
-               .default_trigger        = "heartbeat",
-       },
-#if !IS_ENABLED(CONFIG_LEDS_PWM)
-       {
-               .name                   = "ds1",
-               .gpio                   = AT91_PIN_PB8,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       }
-#endif
-};
-
-/*
- * PWM Leds
- */
-static struct pwm_lookup pwm_lookup[] = {
-       PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "ds1",
-                  5000, PWM_POLARITY_INVERSED),
-};
-
-#if IS_ENABLED(CONFIG_LEDS_PWM)
-static struct led_pwm pwm_leds[] = {
-       {
-               .name = "ds1",
-               .max_brightness = 255,
-       },
-};
-
-static struct led_pwm_platform_data pwm_data = {
-       .num_leds       = ARRAY_SIZE(pwm_leds),
-       .leds           = pwm_leds,
-};
-
-static struct platform_device leds_pwm = {
-       .name   = "leds_pwm",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &pwm_data,
-       },
-};
-#endif
-
-
-/*
- * CAN
- */
-static void sam9263ek_transceiver_switch(int on)
-{
-       if (on) {
-               at91_set_gpio_output(AT91_PIN_PA18, 1); /* CANRXEN */
-               at91_set_gpio_output(AT91_PIN_PA19, 0); /* CANRS */
-       } else {
-               at91_set_gpio_output(AT91_PIN_PA18, 0); /* CANRXEN */
-               at91_set_gpio_output(AT91_PIN_PA19, 1); /* CANRS */
-       }
-}
-
-static struct at91_can_data ek_can_data = {
-       .transceiver_switch = sam9263ek_transceiver_switch,
-};
-
-static struct platform_device *devices[] __initdata = {
-#if IS_ENABLED(CONFIG_LEDS_PWM)
-       &leds_pwm,
-#endif
-};
-
-static void __init ek_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9263_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&ek_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&ek_udc_data);
-       /* SPI */
-       at91_set_gpio_output(AT91_PIN_PE20, 1);         /* select spi0 clock */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* Touchscreen */
-       ek_add_device_ts();
-       /* MMC */
-       at91_add_device_mci(1, &mci1_data);
-       /* Ethernet */
-       at91_add_device_eth(&ek_macb_data);
-       /* NAND */
-       ek_add_device_nand();
-       /* I2C */
-       at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
-       /* LCD Controller */
-       at91_add_device_lcdc(&ek_lcdc_data);
-       /* Push Buttons */
-       ek_add_device_buttons();
-       /* AC97 */
-       at91_add_device_ac97(&ek_ac97_data);
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-       pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
-#if IS_ENABLED(CONFIG_LEDS_PWM)
-       at91_add_device_pwm(1 << AT91_PWM1);
-#endif
-       /* CAN */
-       at91_add_device_can(&ek_can_data);
-       /* Other platform devices */
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
deleted file mode 100644 (file)
index 49f0752..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2008 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/at73c213.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/clk.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/consumer.h>
-
-#include <linux/platform_data/at91_adc.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/at91sam9_smc.h>
-#include <mach/system_rev.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-/*
- * board revision encoding
- * bit 0:
- *     0 => 1 sd/mmc slot
- *     1 => 2 sd/mmc slots connectors (board from revision C)
- */
-#define HAVE_2MMC      (1 << 0)
-static int inline ek_have_2mmc(void)
-{
-       return machine_is_at91sam9g20ek_2mmc() || (system_rev & HAVE_2MMC);
-}
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata ek_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata ek_udc_data = {
-       .vbus_pin       = AT91_PIN_PC5,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 1,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
-       {       /* DataFlash card */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-#endif
-#endif
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata ek_macb_data = {
-       .phy_irq_pin    = AT91_PIN_PA7,
-       .is_rmii        = 1,
-};
-
-static void __init ek_add_device_macb(void)
-{
-       if (ek_have_2mmc())
-               ek_macb_data.phy_irq_pin = AT91_PIN_PB0;
-
-       at91_add_device_eth(&ek_macb_data);
-}
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Bootstrap",
-               .offset = 0,
-               .size   = 4 * SZ_1M,
-       },
-       {
-               .name   = "Partition 1",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 60 * SZ_1M,
-       },
-       {
-               .name   = "Partition 2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-/* det_pin is not connected */
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-       .det_pin        = -EINVAL,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .on_flash_bbt   = 1,
-       .parts          = ek_nand_partition,
-       .num_parts      = ARRAY_SIZE(ek_nand_partition),
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-       .tdf_cycles             = 3,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       ek_nand_data.bus_width_16 = board_have_nand_16bit();
-       /* setup bus-width (8 or 16) */
-       if (ek_nand_data.bus_width_16)
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-       else
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * MCI (SD/MMC)
- * wp_pin and vcc_pin are not connected
- */
-static struct mci_platform_data __initdata ek_mmc_data = {
-       .slot[1] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PC9,
-               .wp_pin         = -EINVAL,
-       },
-
-};
-
-static void __init ek_add_device_mmc(void)
-{
-       if (ek_have_2mmc()) {
-               ek_mmc_data.slot[0].bus_width = 4;
-               ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
-               ek_mmc_data.slot[0].wp_pin = -1;
-       }
-       at91_add_device_mci(0, &ek_mmc_data);
-}
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-       {       /* "bottom" led, green, userled1 to be defined */
-               .name                   = "ds5",
-               .gpio                   = AT91_PIN_PA6,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* "power" led, yellow */
-               .name                   = "ds1",
-               .gpio                   = AT91_PIN_PA9,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-static void __init ek_add_device_gpio_leds(void)
-{
-       if (ek_have_2mmc()) {
-               ek_leds[0].gpio = AT91_PIN_PB8;
-               ek_leds[1].gpio = AT91_PIN_PB9;
-       }
-
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-}
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-       {
-               .gpio           = AT91_PIN_PA30,
-               .code           = BTN_3,
-               .desc           = "Button 3",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PA31,
-               .code           = BTN_4,
-               .desc           = "Button 4",
-               .active_low     = 1,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-       .buttons        = ek_buttons,
-       .nbuttons       = ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_button_data,
-       }
-};
-
-static void __init ek_add_device_buttons(void)
-{
-       at91_set_gpio_input(AT91_PIN_PA30, 1);  /* btn3 */
-       at91_set_deglitch(AT91_PIN_PA30, 1);
-       at91_set_gpio_input(AT91_PIN_PA31, 1);  /* btn4 */
-       at91_set_deglitch(AT91_PIN_PA31, 1);
-
-       platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-/*
- * ADCs
- */
-
-static struct at91_adc_data ek_adc_data = {
-       .channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3),
-       .use_external_triggers = true,
-       .vref = 3300,
-};
-
-#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
-static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
-       REGULATOR_SUPPLY("AVDD", "0-001b"),
-       REGULATOR_SUPPLY("HPVDD", "0-001b"),
-       REGULATOR_SUPPLY("DBVDD", "0-001b"),
-       REGULATOR_SUPPLY("DCVDD", "0-001b"),
-};
-
-static struct regulator_init_data ek_avdd_reg_init_data = {
-       .constraints    = {
-               .name   = "3V3",
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
-       },
-       .consumer_supplies = ek_audio_consumer_supplies,
-       .num_consumer_supplies = ARRAY_SIZE(ek_audio_consumer_supplies),
-};
-
-static struct fixed_voltage_config ek_vdd_pdata = {
-       .supply_name    = "board-3V3",
-       .microvolts     = 3300000,
-       .gpio           = -EINVAL,
-       .enabled_at_boot = 0,
-       .init_data      = &ek_avdd_reg_init_data,
-};
-static struct platform_device ek_voltage_regulator = {
-       .name           = "reg-fixed-voltage",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_vdd_pdata,
-       },
-};
-static void __init ek_add_regulators(void)
-{
-       platform_device_register(&ek_voltage_regulator);
-}
-#else
-static void __init ek_add_regulators(void) {}
-#endif
-
-
-static struct i2c_board_info __initdata ek_i2c_devices[] = {
-        {
-                I2C_BOARD_INFO("24c512", 0x50)
-        },
-        {
-                I2C_BOARD_INFO("wm8731", 0x1b)
-        },
-};
-
-static struct platform_device sam9g20ek_audio_device = {
-       .name   = "at91sam9g20ek-audio",
-       .id     = -1,
-};
-
-static void __init ek_add_device_audio(void)
-{
-       platform_device_register(&sam9g20ek_audio_device);
-}
-
-
-static void __init ek_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                          | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                          | ATMEL_UART_RI);
-
-       /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* USB Host */
-       at91_add_device_usbh(&ek_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&ek_udc_data);
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* NAND */
-       ek_add_device_nand();
-       /* Ethernet */
-       ek_add_device_macb();
-       /* Regulators */
-       ek_add_regulators();
-       /* MMC */
-       ek_add_device_mmc();
-       /* I2C */
-       at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
-       /* LEDs */
-       ek_add_device_gpio_leds();
-       /* Push Buttons */
-       ek_add_device_buttons();
-       /* ADCs */
-       at91_add_device_adc(&ek_adc_data);
-       /* PCK0 provides MCLK to the WM8731 */
-       at91_set_B_periph(AT91_PIN_PC1, 0);
-       /* SSC (for WM8731) */
-       at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
-       ek_add_device_audio();
-}
-
-MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
-
-MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
deleted file mode 100644 (file)
index a517c7f..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- *  Board-specific setup code for the AT91SAM9M10G45 Evaluation Kit family
- *
- *  Covers: * AT91SAM9G45-EKES  board
- *          * AT91SAM9M10G45-EK board
- *
- *  Copyright (C) 2009 Atmel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#include <linux/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/fb.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/leds.h>
-#include <linux/atmel-mci.h>
-#include <linux/delay.h>
-#include <linux/pwm.h>
-#include <linux/leds_pwm.h>
-
-#include <linux/platform_data/at91_adc.h>
-
-#include <mach/hardware.h>
-#include <video/atmel_lcdc.h>
-#include <media/soc_camera.h>
-#include <media/atmel-isi.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/at91sam9_smc.h>
-#include <mach/system_rev.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 12.000 MHz crystal */
-       at91_initialize(12000000);
-}
-
-/*
- * USB HS Host port (common to OHCI & EHCI)
- */
-static struct at91_usbh_data __initdata ek_usbh_hs_data = {
-       .ports          = 2,
-       .vbus_pin       = {AT91_PIN_PD1, AT91_PIN_PD3},
-       .vbus_pin_active_low = {1, 1},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-
-/*
- * USB HS Device port
- */
-static struct usba_platform_data __initdata ek_usba_udc_data = {
-       .vbus_pin       = AT91_PIN_PB19,
-};
-
-
-/*
- * SPI devices.
- */
-static struct spi_board_info ek_spi_devices[] = {
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-};
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct mci_platform_data __initdata mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PD10,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-static struct mci_platform_data __initdata mci1_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PD11,
-               .wp_pin         = AT91_PIN_PD29,
-       },
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata ek_macb_data = {
-       .phy_irq_pin    = AT91_PIN_PD5,
-       .is_rmii        = 1,
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Partition 1",
-               .offset = 0,
-               .size   = SZ_64M,
-       },
-       {
-               .name   = "Partition 2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-/* det_pin is not connected */
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC8,
-       .enable_pin     = AT91_PIN_PC14,
-       .det_pin        = -EINVAL,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .on_flash_bbt   = 1,
-       .parts          = ek_nand_partition,
-       .num_parts      = ARRAY_SIZE(ek_nand_partition),
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
-       .tdf_cycles             = 3,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       ek_nand_data.bus_width_16 = board_have_nand_16bit();
-       /* setup bus-width (8 or 16) */
-       if (ek_nand_data.bus_width_16)
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
-       else
-               ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
-
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- *  ISI
- */
-static struct isi_platform_data __initdata isi_data = {
-       .frate                  = ISI_CFG1_FRATE_CAPTURE_ALL,
-       /* to use codec and preview path simultaneously */
-       .full_mode              = 1,
-       .data_width_flags       = ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10,
-       /* ISI_MCK is provided by programmable clock or external clock */
-       .mck_hz                 = 25000000,
-};
-
-
-/*
- * soc-camera OV2640
- */
-#if defined(CONFIG_SOC_CAMERA_OV2640) || \
-       defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
-static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link)
-{
-       /* ISI board for ek using default 8-bits connection */
-       return SOCAM_DATAWIDTH_8;
-}
-
-static int i2c_camera_power(struct device *dev, int on)
-{
-       /* enable or disable the camera */
-       pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
-       at91_set_gpio_output(AT91_PIN_PD13, !on);
-
-       if (!on)
-               goto out;
-
-       /* If enabled, give a reset impulse */
-       at91_set_gpio_output(AT91_PIN_PD12, 0);
-       msleep(20);
-       at91_set_gpio_output(AT91_PIN_PD12, 1);
-       msleep(100);
-
-out:
-       return 0;
-}
-
-static struct i2c_board_info i2c_camera = {
-       I2C_BOARD_INFO("ov2640", 0x30),
-};
-
-static struct soc_camera_link iclink_ov2640 = {
-       .bus_id                 = 0,
-       .board_info             = &i2c_camera,
-       .i2c_adapter_id         = 0,
-       .power                  = i2c_camera_power,
-       .query_bus_param        = isi_camera_query_bus_param,
-};
-
-static struct platform_device isi_ov2640 = {
-       .name   = "soc-camera-pdrv",
-       .id     = 0,
-       .dev    = {
-               .platform_data = &iclink_ov2640,
-       },
-};
-#endif
-
-
-/*
- * LCD Controller
- */
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static struct fb_videomode at91_tft_vga_modes[] = {
-       {
-               .name           = "LG",
-               .refresh        = 60,
-               .xres           = 480,          .yres           = 272,
-               .pixclock       = KHZ2PICOS(9000),
-
-               .left_margin    = 1,            .right_margin   = 1,
-               .upper_margin   = 40,           .lower_margin   = 1,
-               .hsync_len      = 45,           .vsync_len      = 1,
-
-               .sync           = 0,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-};
-
-static struct fb_monspecs at91fb_default_monspecs = {
-       .manufacturer   = "LG",
-       .monitor        = "LB043WQ1",
-
-       .modedb         = at91_tft_vga_modes,
-       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
-       .hfmin          = 15000,
-       .hfmax          = 17640,
-       .vfmin          = 57,
-       .vfmax          = 67,
-};
-
-#define AT91SAM9G45_DEFAULT_LCDCON2    (ATMEL_LCDC_MEMOR_LITTLE \
-                                       | ATMEL_LCDC_DISTYPE_TFT \
-                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
-
-/* Driver datas */
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
-       .lcdcon_is_backlight            = true,
-       .default_bpp                    = 32,
-       .default_dmacon                 = ATMEL_LCDC_DMAEN,
-       .default_lcdcon2                = AT91SAM9G45_DEFAULT_LCDCON2,
-       .default_monspecs               = &at91fb_default_monspecs,
-       .guard_time                     = 9,
-       .lcd_wiring_mode                = ATMEL_LCDC_WIRING_RGB,
-};
-
-#else
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
-#endif
-
-
-/*
- * ADCs and touchscreen
- */
-static struct at91_adc_data ek_adc_data = {
-       .channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
-       .use_external_triggers = true,
-       .vref = 3300,
-       .touchscreen_type = ATMEL_ADC_TOUCHSCREEN_4WIRE,
-};
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-       {       /* BP1, "leftclic" */
-               .code           = BTN_LEFT,
-               .gpio           = AT91_PIN_PB6,
-               .active_low     = 1,
-               .desc           = "left_click",
-               .wakeup         = 1,
-       },
-       {       /* BP2, "rightclic" */
-               .code           = BTN_RIGHT,
-               .gpio           = AT91_PIN_PB7,
-               .active_low     = 1,
-               .desc           = "right_click",
-               .wakeup         = 1,
-       },
-               /* BP3, "joystick" */
-       {
-               .code           = KEY_LEFT,
-               .gpio           = AT91_PIN_PB14,
-               .active_low     = 1,
-               .desc           = "Joystick Left",
-       },
-       {
-               .code           = KEY_RIGHT,
-               .gpio           = AT91_PIN_PB15,
-               .active_low     = 1,
-               .desc           = "Joystick Right",
-       },
-       {
-               .code           = KEY_UP,
-               .gpio           = AT91_PIN_PB16,
-               .active_low     = 1,
-               .desc           = "Joystick Up",
-       },
-       {
-               .code           = KEY_DOWN,
-               .gpio           = AT91_PIN_PB17,
-               .active_low     = 1,
-               .desc           = "Joystick Down",
-       },
-       {
-               .code           = KEY_ENTER,
-               .gpio           = AT91_PIN_PB18,
-               .active_low     = 1,
-               .desc           = "Joystick Press",
-       },
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-       .buttons        = ek_buttons,
-       .nbuttons       = ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_button_data,
-       }
-};
-
-static void __init ek_add_device_buttons(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ek_buttons); i++) {
-               at91_set_GPIO_periph(ek_buttons[i].gpio, 1);
-               at91_set_deglitch(ek_buttons[i].gpio, 1);
-       }
-
-       platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-
-/*
- * AC97
- * reset_pin is not connected: NRST
- */
-static struct ac97c_platform_data ek_ac97_data = {
-       .reset_pin      = -EINVAL,
-};
-
-
-/*
- * LEDs ... these could all be PWM-driven, for variable brightness
- */
-static struct gpio_led ek_leds[] = {
-       {       /* "top" led, red, powerled */
-               .name                   = "d8",
-               .gpio                   = AT91_PIN_PD30,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* "left" led, green, userled2, pwm3 */
-               .name                   = "d6",
-               .gpio                   = AT91_PIN_PD0,
-               .active_low             = 1,
-               .default_trigger        = "nand-disk",
-       },
-#if !IS_ENABLED(CONFIG_LEDS_PWM)
-       {       /* "right" led, green, userled1, pwm1 */
-               .name                   = "d7",
-               .gpio                   = AT91_PIN_PD31,
-               .active_low             = 1,
-               .default_trigger        = "mmc0",
-       },
-#endif
-};
-
-
-/*
- * PWM Leds
- */
-static struct pwm_lookup pwm_lookup[] = {
-       PWM_LOOKUP("at91sam9rl-pwm", 1, "leds_pwm", "d7",
-                  5000, PWM_POLARITY_INVERSED),
-};
-
-#if IS_ENABLED(CONFIG_LEDS_PWM)
-static struct led_pwm pwm_leds[] = {
-       {       /* "right" led, green, userled1, pwm1 */
-               .name = "d7",
-               .max_brightness = 255,
-       },
-};
-
-static struct led_pwm_platform_data pwm_data = {
-       .num_leds       = ARRAY_SIZE(pwm_leds),
-       .leds           = pwm_leds,
-};
-
-static struct platform_device leds_pwm = {
-       .name   = "leds_pwm",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &pwm_data,
-       },
-};
-#endif
-
-static struct platform_device *devices[] __initdata = {
-#if defined(CONFIG_SOC_CAMERA_OV2640) || \
-       defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
-       &isi_ov2640,
-#endif
-#if IS_ENABLED(CONFIG_LEDS_PWM)
-       &leds_pwm,
-#endif
-};
-
-static void __init ek_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 not connected on the -EK board */
-       /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
-       at91_register_uart(AT91SAM9G45_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* USB HS Host */
-       at91_add_device_usbh_ohci(&ek_usbh_hs_data);
-       at91_add_device_usbh_ehci(&ek_usbh_hs_data);
-       /* USB HS Device */
-       at91_add_device_usba(&ek_usba_udc_data);
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* MMC */
-       at91_add_device_mci(0, &mci0_data);
-       at91_add_device_mci(1, &mci1_data);
-       /* Ethernet */
-       at91_add_device_eth(&ek_macb_data);
-       /* NAND */
-       ek_add_device_nand();
-       /* I2C */
-       at91_add_device_i2c(0, NULL, 0);
-       /* ISI, using programmable clock as ISI_MCK */
-       at91_add_device_isi(&isi_data, true);
-       /* LCD Controller */
-       at91_add_device_lcdc(&ek_lcdc_data);
-       /* ADC and touchscreen */
-       at91_add_device_adc(&ek_adc_data);
-       /* Push Buttons */
-       ek_add_device_buttons();
-       /* AC97 */
-       at91_add_device_ac97(&ek_ac97_data);
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-       pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
-#if IS_ENABLED(CONFIG_LEDS_PWM)
-       at91_add_device_pwm(1 << AT91_PWM1);
-#endif
-       /* Other platform devices */
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
deleted file mode 100644 (file)
index 8bca329..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- *  Copyright (C) 2005 SAN People
- *  Copyright (C) 2007 Atmel Corporation
- *
- * 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/fb.h>
-#include <linux/clk.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-#include <linux/platform_data/at91_adc.h>
-
-#include <video/atmel_lcdc.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/at91sam9_smc.h>
-
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init ek_init_early(void)
-{
-       /* Initialize processor: 12.000 MHz crystal */
-       at91_initialize(12000000);
-}
-
-/*
- * USB HS Device port
- */
-static struct usba_platform_data __initdata ek_usba_udc_data = {
-       .vbus_pin       = AT91_PIN_PA8,
-};
-
-
-/*
- * MCI (SD/MMC)
- */
-static struct mci_platform_data __initdata mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PA15,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-
-/*
- * NAND flash
- */
-static struct mtd_partition __initdata ek_nand_partition[] = {
-       {
-               .name   = "Partition 1",
-               .offset = 0,
-               .size   = SZ_256K,
-       },
-       {
-               .name   = "Partition 2",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata ek_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PD17,
-       .enable_pin     = AT91_PIN_PB6,
-       .ecc_mode       = NAND_ECC_SOFT,
-       .on_flash_bbt   = 1,
-       .parts          = ek_nand_partition,
-       .num_parts      = ARRAY_SIZE(ek_nand_partition),
-};
-
-static struct sam9_smc_config __initdata ek_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 1,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 1,
-
-       .ncs_read_pulse         = 3,
-       .nrd_pulse              = 3,
-       .ncs_write_pulse        = 3,
-       .nwe_pulse              = 3,
-
-       .read_cycle             = 5,
-       .write_cycle            = 5,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 2,
-};
-
-static void __init ek_add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &ek_nand_smc_config);
-
-       at91_add_device_nand(&ek_nand_data);
-}
-
-
-/*
- * SPI devices
- */
-static struct spi_board_info ek_spi_devices[] = {
-       {       /* DataFlash chip */
-               .modalias       = "mtd_dataflash",
-               .chip_select    = 0,
-               .max_speed_hz   = 15 * 1000 * 1000,
-               .bus_num        = 0,
-       },
-};
-
-
-/*
- * LCD Controller
- */
-#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
-static struct fb_videomode at91_tft_vga_modes[] = {
-       {
-               .name           = "TX09D50VM1CCA @ 60",
-               .refresh        = 60,
-               .xres           = 240,          .yres           = 320,
-               .pixclock       = KHZ2PICOS(4965),
-
-               .left_margin    = 1,            .right_margin   = 33,
-               .upper_margin   = 1,            .lower_margin   = 0,
-               .hsync_len      = 5,            .vsync_len      = 1,
-
-               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-               .vmode          = FB_VMODE_NONINTERLACED,
-       },
-};
-
-static struct fb_monspecs at91fb_default_monspecs = {
-       .manufacturer   = "HIT",
-       .monitor        = "TX09D50VM1CCA",
-
-       .modedb         = at91_tft_vga_modes,
-       .modedb_len     = ARRAY_SIZE(at91_tft_vga_modes),
-       .hfmin          = 15000,
-       .hfmax          = 64000,
-       .vfmin          = 50,
-       .vfmax          = 150,
-};
-
-#define AT91SAM9RL_DEFAULT_LCDCON2     (ATMEL_LCDC_MEMOR_LITTLE \
-                                       | ATMEL_LCDC_DISTYPE_TFT \
-                                       | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
-
-static void at91_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
-{
-       if (on)
-               at91_set_gpio_value(AT91_PIN_PC1, 0);   /* power up */
-       else
-               at91_set_gpio_value(AT91_PIN_PC1, 1);   /* power down */
-}
-
-/* Driver datas */
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
-       .lcdcon_is_backlight            = true,
-       .default_bpp                    = 16,
-       .default_dmacon                 = ATMEL_LCDC_DMAEN,
-       .default_lcdcon2                = AT91SAM9RL_DEFAULT_LCDCON2,
-       .default_monspecs               = &at91fb_default_monspecs,
-       .atmel_lcdfb_power_control      = at91_lcdc_power_control,
-       .guard_time                     = 1,
-       .lcd_wiring_mode                = ATMEL_LCDC_WIRING_RGB,
-};
-
-#else
-static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
-#endif
-
-
-/*
- * AC97
- * reset_pin is not connected: NRST
- */
-static struct ac97c_platform_data ek_ac97_data = {
-       .reset_pin      = -EINVAL,
-};
-
-
-/*
- * LEDs
- */
-static struct gpio_led ek_leds[] = {
-       {       /* "bottom" led, green, userled1 to be defined */
-               .name                   = "ds1",
-               .gpio                   = AT91_PIN_PD15,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* "bottom" led, green, userled2 to be defined */
-               .name                   = "ds2",
-               .gpio                   = AT91_PIN_PD16,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       },
-       {       /* "power" led, yellow */
-               .name                   = "ds3",
-               .gpio                   = AT91_PIN_PD14,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-
-/*
- * ADC + Touchscreen
- */
-static struct at91_adc_data ek_adc_data = {
-       .channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
-       .use_external_triggers = true,
-       .vref = 3300,
-       .touchscreen_type = ATMEL_ADC_TOUCHSCREEN_4WIRE,
-};
-
-
-/*
- * GPIO Buttons
- */
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button ek_buttons[] = {
-       {
-               .gpio           = AT91_PIN_PB0,
-               .code           = BTN_2,
-               .desc           = "Right Click",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PB1,
-               .code           = BTN_1,
-               .desc           = "Left Click",
-               .active_low     = 1,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data ek_button_data = {
-       .buttons        = ek_buttons,
-       .nbuttons       = ARRAY_SIZE(ek_buttons),
-};
-
-static struct platform_device ek_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &ek_button_data,
-       }
-};
-
-static void __init ek_add_device_buttons(void)
-{
-       at91_set_gpio_input(AT91_PIN_PB1, 1);   /* btn1 */
-       at91_set_deglitch(AT91_PIN_PB1, 1);
-       at91_set_gpio_input(AT91_PIN_PB0, 1);   /* btn2 */
-       at91_set_deglitch(AT91_PIN_PB0, 1);
-
-       platform_device_register(&ek_button_device);
-}
-#else
-static void __init ek_add_device_buttons(void) {}
-#endif
-
-
-static void __init ek_board_init(void)
-{
-       at91_register_devices();
-
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91SAM9RL_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* USB HS */
-       at91_add_device_usba(&ek_usba_udc_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* NAND */
-       ek_add_device_nand();
-       /* SPI */
-       at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
-       /* MMC */
-       at91_add_device_mci(0, &mci0_data);
-       /* LCD Controller */
-       at91_add_device_lcdc(&ek_lcdc_data);
-       /* AC97 */
-       at91_add_device_ac97(&ek_ac97_data);
-       /* Touch Screen Controller + ADC */
-       at91_add_device_adc(&ek_adc_data);
-       /* LEDs */
-       at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
-       /* Push Buttons */
-       ek_add_device_buttons();
-}
-
-MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
-       /* Maintainer: Atmel */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = ek_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = ek_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
deleted file mode 100644 (file)
index b4aff84..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-snapper9260.c
- *
- *  Copyright (C) 2010 Bluewater System Ltd
- *
- * Author: Andre Renaud <andre@bluewatersys.com>
- * Author: Ryan Mallon
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/init.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/platform_data/pca953x.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <mach/hardware.h>
-#include <mach/at91sam9_smc.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-#define SNAPPER9260_IO_EXP_GPIO(x)     (NR_BUILTIN_GPIO + (x))
-
-static void __init snapper9260_init_early(void)
-{
-       at91_initialize(18432000);
-}
-
-static struct at91_usbh_data __initdata snapper9260_usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-static struct at91_udc_data __initdata snapper9260_udc_data = {
-       .vbus_pin               = SNAPPER9260_IO_EXP_GPIO(5),
-       .vbus_active_low        = 1,
-       .vbus_polled            = 1,
-       .pullup_pin             = -EINVAL,
-};
-
-static struct macb_platform_data snapper9260_macb_data = {
-       .phy_irq_pin    = -EINVAL,
-       .is_rmii        = 1,
-};
-
-static struct mtd_partition __initdata snapper9260_nand_partitions[] = {
-       {
-               .name   = "Preboot",
-               .offset = 0,
-               .size   = SZ_128K,
-       },
-       {
-               .name   = "Bootloader",
-               .offset = MTDPART_OFS_APPEND,
-               .size   = SZ_256K,
-       },
-       {
-               .name   = "Environment",
-               .offset = MTDPART_OFS_APPEND,
-               .size   = SZ_128K,
-       },
-       {
-               .name   = "Kernel",
-               .offset = MTDPART_OFS_APPEND,
-               .size   = SZ_4M,
-       },
-       {
-               .name   = "Filesystem",
-               .offset = MTDPART_OFS_APPEND,
-               .size   = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct atmel_nand_data __initdata snapper9260_nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .parts          = snapper9260_nand_partitions,
-       .num_parts      = ARRAY_SIZE(snapper9260_nand_partitions),
-       .bus_width_16   = 0,
-       .enable_pin     = -EINVAL,
-       .det_pin        = -EINVAL,
-       .ecc_mode       = NAND_ECC_SOFT,
-};
-
-static struct sam9_smc_config __initdata snapper9260_nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 0,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 0,
-
-       .ncs_read_pulse         = 5,
-       .nrd_pulse              = 2,
-       .ncs_write_pulse        = 5,
-       .nwe_pulse              = 2,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = (AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
-                                  AT91_SMC_EXNWMODE_DISABLE),
-       .tdf_cycles             = 1,
-};
-
-static struct pca953x_platform_data snapper9260_io_expander_data = {
-       .gpio_base              = SNAPPER9260_IO_EXP_GPIO(0),
-};
-
-static struct i2c_board_info __initdata snapper9260_i2c_devices[] = {
-       {
-               /* IO expander */
-               I2C_BOARD_INFO("max7312", 0x28),
-               .platform_data = &snapper9260_io_expander_data,
-       },
-       {
-               /* Audio codec */
-               I2C_BOARD_INFO("tlv320aic23", 0x1a),
-       },
-};
-
-static struct i2c_board_info __initdata snapper9260_i2c_isl1208 = {
-               /* RTC */
-               I2C_BOARD_INFO("isl1208", 0x6f),
-};
-
-static void __init snapper9260_add_device_nand(void)
-{
-       at91_set_A_periph(AT91_PIN_PC14, 0);
-       sam9_smc_configure(0, 3, &snapper9260_nand_smc_config);
-       at91_add_device_nand(&snapper9260_nand_data);
-}
-
-static void __init snapper9260_board_init(void)
-{
-       at91_register_devices();
-
-       at91_add_device_i2c(snapper9260_i2c_devices,
-                           ARRAY_SIZE(snapper9260_i2c_devices));
-
-       snapper9260_i2c_isl1208.irq = gpio_to_irq(AT91_PIN_PA31);
-       i2c_register_board_info(0, &snapper9260_i2c_isl1208, 1);
-
-       /* Debug on ttyS0 */
-       at91_register_uart(0, 0, 0);
-
-       at91_register_uart(AT91SAM9260_ID_US0, 1,
-                          ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_register_uart(AT91SAM9260_ID_US1, 2,
-                          ATMEL_UART_CTS | ATMEL_UART_RTS);
-       at91_register_uart(AT91SAM9260_ID_US2, 3, 0);
-       at91_add_device_serial();
-       at91_add_device_usbh(&snapper9260_usbh_data);
-       at91_add_device_udc(&snapper9260_udc_data);
-       at91_add_device_eth(&snapper9260_macb_data);
-       at91_add_device_ssc(AT91SAM9260_ID_SSC, (ATMEL_SSC_TF | ATMEL_SSC_TK |
-                                                ATMEL_SSC_TD | ATMEL_SSC_RD));
-       snapper9260_add_device_nand();
-}
-
-MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = snapper9260_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = snapper9260_board_init,
-MACHINE_END
-
-
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
deleted file mode 100644 (file)
index e825641..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- *  Copyright (C) 2010 Christian Glindkamp <christian.glindkamp@taskit.de>
- *                     taskit GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/mm.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/w1-gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <mach/at91sam9_smc.h>
-#include <mach/hardware.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "sam9_smc.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-void __init stamp9g20_init_early(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * NAND flash
- */
-static struct atmel_nand_data __initdata nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-       .bus_width_16   = 0,
-       .det_pin        = -EINVAL,
-       .ecc_mode       = NAND_ECC_SOFT,
-};
-
-static struct sam9_smc_config __initdata nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 3,
-};
-
-static void __init add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(0, 3, &nand_smc_config);
-
-       at91_add_device_nand(&nand_data);
-}
-
-
-/*
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
-static struct mci_platform_data __initdata mmc_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = -1,
-               .wp_pin         = -1,
-       },
-};
-
-
-/*
- * USB Host port
- */
-static struct at91_usbh_data __initdata usbh_data = {
-       .ports          = 2,
-       .vbus_pin       = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-
-/*
- * USB Device port
- */
-static struct at91_udc_data __initdata portuxg20_udc_data = {
-       .vbus_pin       = AT91_PIN_PC7,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-static struct at91_udc_data __initdata stamp9g20evb_udc_data = {
-       .vbus_pin       = AT91_PIN_PA22,
-       .pullup_pin     = -EINVAL,              /* pull-up driven by UDC */
-};
-
-
-/*
- * MACB Ethernet device
- */
-static struct macb_platform_data __initdata macb_data = {
-       .phy_irq_pin    = AT91_PIN_PA28,
-       .is_rmii        = 1,
-};
-
-
-/*
- * LEDs
- */
-static struct gpio_led portuxg20_leds[] = {
-       {
-               .name                   = "LED2",
-               .gpio                   = AT91_PIN_PC5,
-               .default_trigger        = "none",
-       }, {
-               .name                   = "LED3",
-               .gpio                   = AT91_PIN_PC4,
-               .default_trigger        = "none",
-       }, {
-               .name                   = "LED4",
-               .gpio                   = AT91_PIN_PC10,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-static struct gpio_led stamp9g20evb_leds[] = {
-       {
-               .name                   = "D8",
-               .gpio                   = AT91_PIN_PB18,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       }, {
-               .name                   = "D9",
-               .gpio                   = AT91_PIN_PB19,
-               .active_low             = 1,
-               .default_trigger        = "none",
-       }, {
-               .name                   = "D10",
-               .gpio                   = AT91_PIN_PB20,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       }
-};
-
-
-/*
- * SPI devices
- */
-static struct spi_board_info portuxg20_spi_devices[] = {
-       {
-               .modalias       = "spidev",
-               .chip_select    = 0,
-               .max_speed_hz   = 1 * 1000 * 1000,
-               .bus_num        = 0,
-       }, {
-               .modalias       = "spidev",
-               .chip_select    = 0,
-               .max_speed_hz   = 1 * 1000 * 1000,
-               .bus_num        = 1,
-       },
-};
-
-
-/*
- * Dallas 1-Wire
- */
-static struct w1_gpio_platform_data w1_gpio_pdata = {
-       .pin            = AT91_PIN_PA29,
-       .is_open_drain  = 1,
-       .ext_pullup_enable_pin  = -EINVAL,
-};
-
-static struct platform_device w1_device = {
-       .name                   = "w1-gpio",
-       .id                     = -1,
-       .dev.platform_data      = &w1_gpio_pdata,
-};
-
-void add_w1(void)
-{
-       at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
-       at91_set_multi_drive(w1_gpio_pdata.pin, 1);
-       platform_device_register(&w1_device);
-}
-
-
-void __init stamp9g20_board_init(void)
-{
-       /* Serial */
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-       at91_add_device_serial();
-       /* NAND */
-       add_device_nand();
-       /* MMC */
-       at91_add_device_mci(0, &mmc_data);
-       /* W1 */
-       add_w1();
-}
-
-static void __init portuxg20_board_init(void)
-{
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
-                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
-       /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */
-       at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS);
-
-       /* USART4 on ttyS5. (Rx, Tx only) */
-       at91_register_uart(AT91SAM9260_ID_US4, 5, 0);
-
-       /* USART5 on ttyS6. (Rx, Tx only) */
-       at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-       stamp9g20_board_init();
-       /* USB Host */
-       at91_add_device_usbh(&usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&portuxg20_udc_data);
-       /* Ethernet */
-       at91_add_device_eth(&macb_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* SPI */
-       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
-       /* LEDs */
-       at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));
-}
-
-static void __init stamp9g20evb_board_init(void)
-{
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
-                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
-       stamp9g20_board_init();
-       /* USB Host */
-       at91_add_device_usbh(&usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&stamp9g20evb_udc_data);
-       /* Ethernet */
-       at91_add_device_eth(&macb_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
-       /* LEDs */
-       at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));
-}
-
-MACHINE_START(PORTUXG20, "taskit PortuxG20")
-       /* Maintainer: taskit GmbH */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = stamp9g20_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = portuxg20_board_init,
-MACHINE_END
-
-MACHINE_START(STAMP9G20, "taskit Stamp9G20")
-       /* Maintainer: taskit GmbH */
-       .init_time      = at91_init_time,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = stamp9g20_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = stamp9g20evb_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
deleted file mode 100644 (file)
index 46fdb0c..0000000
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/board-yl-9200.c
- *
- * Adapted from various board files in arch/arm/mach-at91
- *
- * Modifications for YL-9200 platform:
- *  Copyright (C) 2007 S. Birtles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/types.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/ads7846.h>
-#include <linux/mtd/physmap.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/at91rm9200_mc.h>
-#include <mach/at91_ramc.h>
-#include <mach/cpu.h>
-
-#include "at91_aic.h"
-#include "board.h"
-#include "generic.h"
-#include "gpio.h"
-
-
-static void __init yl9200_init_early(void)
-{
-       /* Set cpu type: PQFP */
-       at91rm9200_set_type(ARCH_REVISON_9200_PQFP);
-
-       /* Initialize processor: 18.432 MHz crystal */
-       at91_initialize(18432000);
-}
-
-/*
- * LEDs
- */
-static struct gpio_led yl9200_leds[] = {
-       {       /* D2 */
-               .name                   = "led2",
-               .gpio                   = AT91_PIN_PB17,
-               .active_low             = 1,
-               .default_trigger        = "timer",
-       },
-       {       /* D3 */
-               .name                   = "led3",
-               .gpio                   = AT91_PIN_PB16,
-               .active_low             = 1,
-               .default_trigger        = "heartbeat",
-       },
-       {       /* D4 */
-               .name                   = "led4",
-               .gpio                   = AT91_PIN_PB15,
-               .active_low             = 1,
-       },
-       {       /* D5 */
-               .name                   = "led5",
-               .gpio                   = AT91_PIN_PB8,
-               .active_low             = 1,
-       }
-};
-
-/*
- * Ethernet
- */
-static struct macb_platform_data __initdata yl9200_eth_data = {
-       .phy_irq_pin            = AT91_PIN_PB28,
-       .is_rmii                = 1,
-};
-
-/*
- * USB Host
- */
-static struct at91_usbh_data __initdata yl9200_usbh_data = {
-       .ports                  = 1,    /* PQFP version of AT91RM9200 */
-       .vbus_pin               = {-EINVAL, -EINVAL},
-       .overcurrent_pin= {-EINVAL, -EINVAL},
-};
-
-/*
- * USB Device
- */
-static struct at91_udc_data __initdata yl9200_udc_data = {
-       .pullup_pin             = AT91_PIN_PC4,
-       .vbus_pin               = AT91_PIN_PC5,
-       .pullup_active_low      = 1,    /* Active Low due to PNP transistor (pg 7) */
-
-};
-
-/*
- * MMC
- */
-static struct mci_platform_data __initdata yl9200_mci0_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-               .detect_pin     = AT91_PIN_PB9,
-               .wp_pin         = -EINVAL,
-       },
-};
-
-/*
- * NAND Flash
- */
-static struct mtd_partition __initdata yl9200_nand_partition[] = {
-       {
-               .name   = "AT91 NAND partition 1, boot",
-               .offset = 0,
-               .size   = SZ_256K
-       },
-       {
-               .name   = "AT91 NAND partition 2, kernel",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = (2 * SZ_1M) - SZ_256K
-       },
-       {
-               .name   = "AT91 NAND partition 3, filesystem",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = 14 * SZ_1M
-       },
-       {
-               .name   = "AT91 NAND partition 4, storage",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = SZ_16M
-       },
-       {
-               .name   = "AT91 NAND partition 5, ext-fs",
-               .offset = MTDPART_OFS_NXTBLK,
-               .size   = SZ_32M
-       }
-};
-
-static struct atmel_nand_data __initdata yl9200_nand_data = {
-       .ale            = 6,
-       .cle            = 7,
-       .det_pin        = -EINVAL,
-       .rdy_pin        = AT91_PIN_PC14,        /* R/!B (Sheet10) */
-       .enable_pin     = AT91_PIN_PC15,        /* !CE  (Sheet10) */
-       .ecc_mode       = NAND_ECC_SOFT,
-       .parts          = yl9200_nand_partition,
-       .num_parts      = ARRAY_SIZE(yl9200_nand_partition),
-};
-
-/*
- * NOR Flash
- */
-#define YL9200_FLASH_BASE      AT91_CHIPSELECT_0
-#define YL9200_FLASH_SIZE      SZ_16M
-
-static struct mtd_partition yl9200_flash_partitions[] = {
-       {
-               .name           = "Bootloader",
-               .offset         = 0,
-               .size           = SZ_256K,
-               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
-       },
-       {
-               .name           = "Kernel",
-               .offset         = MTDPART_OFS_NXTBLK,
-               .size           = (2 * SZ_1M) - SZ_256K
-       },
-       {
-               .name           = "Filesystem",
-               .offset         = MTDPART_OFS_NXTBLK,
-               .size           = MTDPART_SIZ_FULL
-       }
-};
-
-static struct physmap_flash_data yl9200_flash_data = {
-       .width          = 2,
-       .parts          = yl9200_flash_partitions,
-       .nr_parts       = ARRAY_SIZE(yl9200_flash_partitions),
-};
-
-static struct resource yl9200_flash_resources[] = {
-       {
-               .start  = YL9200_FLASH_BASE,
-               .end    = YL9200_FLASH_BASE + YL9200_FLASH_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device yl9200_flash = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-                               .platform_data  = &yl9200_flash_data,
-                       },
-       .resource       = yl9200_flash_resources,
-       .num_resources  = ARRAY_SIZE(yl9200_flash_resources),
-};
-
-/*
- * I2C (TWI)
- */
-static struct i2c_board_info __initdata yl9200_i2c_devices[] = {
-       {       /* EEPROM */
-               I2C_BOARD_INFO("24c128", 0x50),
-       }
-};
-
-/*
- * GPIO Buttons
-*/
-#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-static struct gpio_keys_button yl9200_buttons[] = {
-       {
-               .gpio           = AT91_PIN_PA24,
-               .code           = BTN_2,
-               .desc           = "SW2",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PB1,
-               .code           = BTN_3,
-               .desc           = "SW3",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PB2,
-               .code           = BTN_4,
-               .desc           = "SW4",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-       {
-               .gpio           = AT91_PIN_PB6,
-               .code           = BTN_5,
-               .desc           = "SW5",
-               .active_low     = 1,
-               .wakeup         = 1,
-       }
-};
-
-static struct gpio_keys_platform_data yl9200_button_data = {
-       .buttons        = yl9200_buttons,
-       .nbuttons       = ARRAY_SIZE(yl9200_buttons),
-};
-
-static struct platform_device yl9200_button_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .num_resources  = 0,
-       .dev            = {
-               .platform_data  = &yl9200_button_data,
-       }
-};
-
-static void __init yl9200_add_device_buttons(void)
-{
-       at91_set_gpio_input(AT91_PIN_PA24, 1);  /* SW2 */
-       at91_set_deglitch(AT91_PIN_PA24, 1);
-       at91_set_gpio_input(AT91_PIN_PB1, 1);   /* SW3 */
-       at91_set_deglitch(AT91_PIN_PB1, 1);
-       at91_set_gpio_input(AT91_PIN_PB2, 1);   /* SW4 */
-       at91_set_deglitch(AT91_PIN_PB2, 1);
-       at91_set_gpio_input(AT91_PIN_PB6, 1);   /* SW5 */
-       at91_set_deglitch(AT91_PIN_PB6, 1);
-
-       /* Enable buttons (Sheet 5) */
-       at91_set_gpio_output(AT91_PIN_PB7, 1);
-
-       platform_device_register(&yl9200_button_device);
-}
-#else
-static void __init yl9200_add_device_buttons(void) {}
-#endif
-
-/*
- * Touchscreen
- */
-#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-static int ads7843_pendown_state(void)
-{
-       return !at91_get_gpio_value(AT91_PIN_PB11);     /* Touchscreen PENIRQ */
-}
-
-static struct ads7846_platform_data ads_info = {
-       .model                  = 7843,
-       .x_min                  = 150,
-       .x_max                  = 3830,
-       .y_min                  = 190,
-       .y_max                  = 3830,
-       .vref_delay_usecs       = 100,
-
-       /* For a 8" touch-screen */
-       // .x_plate_ohms                = 603,
-       // .y_plate_ohms                = 332,
-
-       /* For a 10.4" touch-screen */
-       // .x_plate_ohms                = 611,
-       // .y_plate_ohms                = 325,
-
-       .x_plate_ohms           = 576,
-       .y_plate_ohms           = 366,
-
-       .pressure_max           = 15000, /* generally nonsense on the 7843 */
-       .debounce_max           = 1,
-       .debounce_rep           = 0,
-       .debounce_tol           = (~0),
-       .get_pendown_state      = ads7843_pendown_state,
-};
-
-static void __init yl9200_add_device_ts(void)
-{
-       at91_set_gpio_input(AT91_PIN_PB11, 1);  /* Touchscreen interrupt pin */
-       at91_set_gpio_input(AT91_PIN_PB10, 1);  /* Touchscreen BUSY signal - not used! */
-}
-#else
-static void __init yl9200_add_device_ts(void) {}
-#endif
-
-/*
- * SPI devices
- */
-static struct spi_board_info yl9200_spi_devices[] = {
-#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-       {       /* Touchscreen */
-               .modalias       = "ads7846",
-               .chip_select    = 0,
-               .max_speed_hz   = 5000 * 26,
-               .platform_data  = &ads_info,
-               .irq            = AT91_PIN_PB11,
-       },
-#endif
-       {       /* CAN */
-               .modalias       = "mcp2510",
-               .chip_select    = 1,
-               .max_speed_hz   = 25000 * 26,
-               .irq            = AT91_PIN_PC0,
-       }
-};
-
-/*
- * LCD / VGA
- *
- * EPSON S1D13806 FB (discontinued chip)
- * EPSON S1D13506 FB
- */
-#if defined(CONFIG_FB_S1D13XXX) || defined(CONFIG_FB_S1D13XXX_MODULE)
-#include <video/s1d13xxxfb.h>
-
-
-static void yl9200_init_video(void)
-{
-       /* NWAIT Signal */
-       at91_set_A_periph(AT91_PIN_PC6, 0);
-
-       /* Initialization of the Static Memory Controller for Chip Select 2 */
-       at91_ramc_write(0, AT91_SMC_CSR(2), AT91_SMC_DBW_16             /* 16 bit */
-                       | AT91_SMC_WSEN | AT91_SMC_NWS_(0x4)    /* wait states */
-                       | AT91_SMC_TDF_(0x100)                  /* float time */
-       );
-}
-
-static struct s1d13xxxfb_regval yl9200_s1dfb_initregs[] =
-{
-       {S1DREG_MISC,                   0x00},  /* Miscellaneous Register*/
-       {S1DREG_COM_DISP_MODE,          0x01},  /* Display Mode Register, LCD only*/
-       {S1DREG_GPIO_CNF0,              0x00},  /* General IO Pins Configuration Register*/
-       {S1DREG_GPIO_CTL0,              0x00},  /* General IO Pins Control Register*/
-       {S1DREG_CLK_CNF,                0x11},  /* Memory Clock Configuration Register*/
-       {S1DREG_LCD_CLK_CNF,            0x10},  /* LCD Pixel Clock Configuration Register*/
-       {S1DREG_CRT_CLK_CNF,            0x12},  /* CRT/TV Pixel Clock Configuration Register*/
-       {S1DREG_MPLUG_CLK_CNF,          0x01},  /* MediaPlug Clock Configuration Register*/
-       {S1DREG_CPU2MEM_WST_SEL,        0x02},  /* CPU To Memory Wait State Select Register*/
-       {S1DREG_MEM_CNF,                0x00},  /* Memory Configuration Register*/
-       {S1DREG_SDRAM_REF_RATE,         0x04},  /* DRAM Refresh Rate Register, MCLK source*/
-       {S1DREG_SDRAM_TC0,              0x12},  /* DRAM Timings Control Register 0*/
-       {S1DREG_SDRAM_TC1,              0x02},  /* DRAM Timings Control Register 1*/
-       {S1DREG_PANEL_TYPE,             0x25},  /* Panel Type Register*/
-       {S1DREG_MOD_RATE,               0x00},  /* MOD Rate Register*/
-       {S1DREG_LCD_DISP_HWIDTH,        0x4F},  /* LCD Horizontal Display Width Register*/
-       {S1DREG_LCD_NDISP_HPER,         0x13},  /* LCD Horizontal Non-Display Period Register*/
-       {S1DREG_TFT_FPLINE_START,       0x01},  /* TFT FPLINE Start Position Register*/
-       {S1DREG_TFT_FPLINE_PWIDTH,      0x0c},  /* TFT FPLINE Pulse Width Register*/
-       {S1DREG_LCD_DISP_VHEIGHT0,      0xDF},  /* LCD Vertical Display Height Register 0*/
-       {S1DREG_LCD_DISP_VHEIGHT1,      0x01},  /* LCD Vertical Display Height Register 1*/
-       {S1DREG_LCD_NDISP_VPER,         0x2c},  /* LCD Vertical Non-Display Period Register*/
-       {S1DREG_TFT_FPFRAME_START,      0x0a},  /* TFT FPFRAME Start Position Register*/
-       {S1DREG_TFT_FPFRAME_PWIDTH,     0x02},  /* TFT FPFRAME Pulse Width Register*/
-       {S1DREG_LCD_DISP_MODE,          0x05},  /* LCD Display Mode Register*/
-       {S1DREG_LCD_MISC,               0x01},  /* LCD Miscellaneous Register*/
-       {S1DREG_LCD_DISP_START0,        0x00},  /* LCD Display Start Address Register 0*/
-       {S1DREG_LCD_DISP_START1,        0x00},  /* LCD Display Start Address Register 1*/
-       {S1DREG_LCD_DISP_START2,        0x00},  /* LCD Display Start Address Register 2*/
-       {S1DREG_LCD_MEM_OFF0,           0x80},  /* LCD Memory Address Offset Register 0*/
-       {S1DREG_LCD_MEM_OFF1,           0x02},  /* LCD Memory Address Offset Register 1*/
-       {S1DREG_LCD_PIX_PAN,            0x03},  /* LCD Pixel Panning Register*/
-       {S1DREG_LCD_DISP_FIFO_HTC,      0x00},  /* LCD Display FIFO High Threshold Control Register*/
-       {S1DREG_LCD_DISP_FIFO_LTC,      0x00},  /* LCD Display FIFO Low Threshold Control Register*/
-       {S1DREG_CRT_DISP_HWIDTH,        0x4F},  /* CRT/TV Horizontal Display Width Register*/
-       {S1DREG_CRT_NDISP_HPER,         0x13},  /* CRT/TV Horizontal Non-Display Period Register*/
-       {S1DREG_CRT_HRTC_START,         0x01},  /* CRT/TV HRTC Start Position Register*/
-       {S1DREG_CRT_HRTC_PWIDTH,        0x0B},  /* CRT/TV HRTC Pulse Width Register*/
-       {S1DREG_CRT_DISP_VHEIGHT0,      0xDF},  /* CRT/TV Vertical Display Height Register 0*/
-       {S1DREG_CRT_DISP_VHEIGHT1,      0x01},  /* CRT/TV Vertical Display Height Register 1*/
-       {S1DREG_CRT_NDISP_VPER,         0x2B},  /* CRT/TV Vertical Non-Display Period Register*/
-       {S1DREG_CRT_VRTC_START,         0x09},  /* CRT/TV VRTC Start Position Register*/
-       {S1DREG_CRT_VRTC_PWIDTH,        0x01},  /* CRT/TV VRTC Pulse Width Register*/
-       {S1DREG_TV_OUT_CTL,             0x18},  /* TV Output Control Register */
-       {S1DREG_CRT_DISP_MODE,          0x05},  /* CRT/TV Display Mode Register, 16BPP*/
-       {S1DREG_CRT_DISP_START0,        0x00},  /* CRT/TV Display Start Address Register 0*/
-       {S1DREG_CRT_DISP_START1,        0x00},  /* CRT/TV Display Start Address Register 1*/
-       {S1DREG_CRT_DISP_START2,        0x00},  /* CRT/TV Display Start Address Register 2*/
-       {S1DREG_CRT_MEM_OFF0,           0x80},  /* CRT/TV Memory Address Offset Register 0*/
-       {S1DREG_CRT_MEM_OFF1,           0x02},  /* CRT/TV Memory Address Offset Register 1*/
-       {S1DREG_CRT_PIX_PAN,            0x00},  /* CRT/TV Pixel Panning Register*/
-       {S1DREG_CRT_DISP_FIFO_HTC,      0x00},  /* CRT/TV Display FIFO High Threshold Control Register*/
-       {S1DREG_CRT_DISP_FIFO_LTC,      0x00},  /* CRT/TV Display FIFO Low Threshold Control Register*/
-       {S1DREG_LCD_CUR_CTL,            0x00},  /* LCD Ink/Cursor Control Register*/
-       {S1DREG_LCD_CUR_START,          0x01},  /* LCD Ink/Cursor Start Address Register*/
-       {S1DREG_LCD_CUR_XPOS0,          0x00},  /* LCD Cursor X Position Register 0*/
-       {S1DREG_LCD_CUR_XPOS1,          0x00},  /* LCD Cursor X Position Register 1*/
-       {S1DREG_LCD_CUR_YPOS0,          0x00},  /* LCD Cursor Y Position Register 0*/
-       {S1DREG_LCD_CUR_YPOS1,          0x00},  /* LCD Cursor Y Position Register 1*/
-       {S1DREG_LCD_CUR_BCTL0,          0x00},  /* LCD Ink/Cursor Blue Color 0 Register*/
-       {S1DREG_LCD_CUR_GCTL0,          0x00},  /* LCD Ink/Cursor Green Color 0 Register*/
-       {S1DREG_LCD_CUR_RCTL0,          0x00},  /* LCD Ink/Cursor Red Color 0 Register*/
-       {S1DREG_LCD_CUR_BCTL1,          0x1F},  /* LCD Ink/Cursor Blue Color 1 Register*/
-       {S1DREG_LCD_CUR_GCTL1,          0x3F},  /* LCD Ink/Cursor Green Color 1 Register*/
-       {S1DREG_LCD_CUR_RCTL1,          0x1F},  /* LCD Ink/Cursor Red Color 1 Register*/
-       {S1DREG_LCD_CUR_FIFO_HTC,       0x00},  /* LCD Ink/Cursor FIFO Threshold Register*/
-       {S1DREG_CRT_CUR_CTL,            0x00},  /* CRT/TV Ink/Cursor Control Register*/
-       {S1DREG_CRT_CUR_START,          0x01},  /* CRT/TV Ink/Cursor Start Address Register*/
-       {S1DREG_CRT_CUR_XPOS0,          0x00},  /* CRT/TV Cursor X Position Register 0*/
-       {S1DREG_CRT_CUR_XPOS1,          0x00},  /* CRT/TV Cursor X Position Register 1*/
-       {S1DREG_CRT_CUR_YPOS0,          0x00},  /* CRT/TV Cursor Y Position Register 0*/
-       {S1DREG_CRT_CUR_YPOS1,          0x00},  /* CRT/TV Cursor Y Position Register 1*/
-       {S1DREG_CRT_CUR_BCTL0,          0x00},  /* CRT/TV Ink/Cursor Blue Color 0 Register*/
-       {S1DREG_CRT_CUR_GCTL0,          0x00},  /* CRT/TV Ink/Cursor Green Color 0 Register*/
-       {S1DREG_CRT_CUR_RCTL0,          0x00},  /* CRT/TV Ink/Cursor Red Color 0 Register*/
-       {S1DREG_CRT_CUR_BCTL1,          0x1F},  /* CRT/TV Ink/Cursor Blue Color 1 Register*/
-       {S1DREG_CRT_CUR_GCTL1,          0x3F},  /* CRT/TV Ink/Cursor Green Color 1 Register*/
-       {S1DREG_CRT_CUR_RCTL1,          0x1F},  /* CRT/TV Ink/Cursor Red Color 1 Register*/
-       {S1DREG_CRT_CUR_FIFO_HTC,       0x00},  /* CRT/TV Ink/Cursor FIFO Threshold Register*/
-       {S1DREG_BBLT_CTL0,              0x00},  /* BitBlt Control Register 0*/
-       {S1DREG_BBLT_CTL1,              0x01},  /* BitBlt Control Register 1*/
-       {S1DREG_BBLT_CC_EXP,            0x00},  /* BitBlt ROP Code/Color Expansion Register*/
-       {S1DREG_BBLT_OP,                0x00},  /* BitBlt Operation Register*/
-       {S1DREG_BBLT_SRC_START0,        0x00},  /* BitBlt Source Start Address Register 0*/
-       {S1DREG_BBLT_SRC_START1,        0x00},  /* BitBlt Source Start Address Register 1*/
-       {S1DREG_BBLT_SRC_START2,        0x00},  /* BitBlt Source Start Address Register 2*/
-       {S1DREG_BBLT_DST_START0,        0x00},  /* BitBlt Destination Start Address Register 0*/
-       {S1DREG_BBLT_DST_START1,        0x00},  /* BitBlt Destination Start Address Register 1*/
-       {S1DREG_BBLT_DST_START2,        0x00},  /* BitBlt Destination Start Address Register 2*/
-       {S1DREG_BBLT_MEM_OFF0,          0x00},  /* BitBlt Memory Address Offset Register 0*/
-       {S1DREG_BBLT_MEM_OFF1,          0x00},  /* BitBlt Memory Address Offset Register 1*/
-       {S1DREG_BBLT_WIDTH0,            0x00},  /* BitBlt Width Register 0*/
-       {S1DREG_BBLT_WIDTH1,            0x00},  /* BitBlt Width Register 1*/
-       {S1DREG_BBLT_HEIGHT0,           0x00},  /* BitBlt Height Register 0*/
-       {S1DREG_BBLT_HEIGHT1,           0x00},  /* BitBlt Height Register 1*/
-       {S1DREG_BBLT_BGC0,              0x00},  /* BitBlt Background Color Register 0*/
-       {S1DREG_BBLT_BGC1,              0x00},  /* BitBlt Background Color Register 1*/
-       {S1DREG_BBLT_FGC0,              0x00},  /* BitBlt Foreground Color Register 0*/
-       {S1DREG_BBLT_FGC1,              0x00},  /* BitBlt Foreground Color Register 1*/
-       {S1DREG_LKUP_MODE,              0x00},  /* Look-Up Table Mode Register*/
-       {S1DREG_LKUP_ADDR,              0x00},  /* Look-Up Table Address Register*/
-       {S1DREG_PS_CNF,                 0x00},  /* Power Save Configuration Register*/
-       {S1DREG_PS_STATUS,              0x00},  /* Power Save Status Register*/
-       {S1DREG_CPU2MEM_WDOGT,          0x00},  /* CPU-to-Memory Access Watchdog Timer Register*/
-       {S1DREG_COM_DISP_MODE,          0x01},  /* Display Mode Register, LCD only*/
-};
-
-static struct s1d13xxxfb_pdata yl9200_s1dfb_pdata = {
-       .initregs               = yl9200_s1dfb_initregs,
-       .initregssize           = ARRAY_SIZE(yl9200_s1dfb_initregs),
-       .platform_init_video    = yl9200_init_video,
-};
-
-#define YL9200_FB_REG_BASE     AT91_CHIPSELECT_7
-#define YL9200_FB_VMEM_BASE    YL9200_FB_REG_BASE + SZ_2M
-#define YL9200_FB_VMEM_SIZE    SZ_2M
-
-static struct resource yl9200_s1dfb_resource[] = {
-       [0] = { /* video mem */
-               .name   = "s1d13xxxfb memory",
-               .start  = YL9200_FB_VMEM_BASE,
-               .end    = YL9200_FB_VMEM_BASE + YL9200_FB_VMEM_SIZE -1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = { /* video registers */
-               .name   = "s1d13xxxfb registers",
-               .start  = YL9200_FB_REG_BASE,
-               .end    = YL9200_FB_REG_BASE + SZ_512 -1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static u64 s1dfb_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device yl9200_s1dfb_device = {
-       .name           = "s1d13806fb",
-       .id             = -1,
-       .dev    = {
-               .dma_mask               = &s1dfb_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data          = &yl9200_s1dfb_pdata,
-       },
-       .resource       = yl9200_s1dfb_resource,
-       .num_resources  = ARRAY_SIZE(yl9200_s1dfb_resource),
-};
-
-void __init yl9200_add_device_video(void)
-{
-       platform_device_register(&yl9200_s1dfb_device);
-}
-#else
-void __init yl9200_add_device_video(void) {}
-#endif
-
-
-static void __init yl9200_board_init(void)
-{
-       /* Serial */
-       /* DBGU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART1 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91RM9200_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                       | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
-                       | ATMEL_UART_RI);
-
-       /* USART0 on ttyS2. (Rx & Tx only to JP3) */
-       at91_register_uart(AT91RM9200_ID_US0, 2, 0);
-
-       /* USART3 on ttyS3. (Rx, Tx, RTS - RS485 interface) */
-       at91_register_uart(AT91RM9200_ID_US3, 3, ATMEL_UART_RTS);
-       at91_add_device_serial();
-       /* Ethernet */
-       at91_add_device_eth(&yl9200_eth_data);
-       /* USB Host */
-       at91_add_device_usbh(&yl9200_usbh_data);
-       /* USB Device */
-       at91_add_device_udc(&yl9200_udc_data);
-       /* I2C */
-       at91_add_device_i2c(yl9200_i2c_devices, ARRAY_SIZE(yl9200_i2c_devices));
-       /* MMC */
-       at91_add_device_mci(0, &yl9200_mci0_data);
-       /* NAND */
-       at91_add_device_nand(&yl9200_nand_data);
-       /* NOR Flash */
-       platform_device_register(&yl9200_flash);
-#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
-       /* SPI */
-       at91_add_device_spi(yl9200_spi_devices, ARRAY_SIZE(yl9200_spi_devices));
-       /* Touchscreen */
-       yl9200_add_device_ts();
-#endif
-       /* LEDs. */
-       at91_gpio_leds(yl9200_leds, ARRAY_SIZE(yl9200_leds));
-       /* Push Buttons */
-       yl9200_add_device_buttons();
-       /* VGA */
-       yl9200_add_device_video();
-}
-
-MACHINE_START(YL9200, "uCdragon YL-9200")
-       /* Maintainer: S.Birtles */
-       .init_time      = at91rm9200_timer_init,
-       .map_io         = at91_map_io,
-       .handle_irq     = at91_aic_handle_irq,
-       .init_early     = yl9200_init_early,
-       .init_irq       = at91_init_irq_default,
-       .init_machine   = yl9200_board_init,
-MACHINE_END
diff --git a/arch/arm/mach-at91/board.h b/arch/arm/mach-at91/board.h
deleted file mode 100644 (file)
index 836e9a5..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/board.h
- *
- *  Copyright (C) 2005 HP Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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
- */
-
-/*
- * These are data structures found in platform_device.dev.platform_data,
- * and describing board-specific data needed by drivers.  For example,
- * which pin is used for a given GPIO role.
- *
- * In 2.6, drivers should strongly avoid board-specific knowledge so
- * that supporting new boards normally won't require driver patches.
- * Most board-specific knowledge should be in arch/.../board-*.c files.
- */
-
-#ifndef __ASM_ARCH_BOARD_H
-#define __ASM_ARCH_BOARD_H
-
-#include <linux/platform_data/atmel.h>
-
- /* USB Device */
-extern void __init at91_add_device_udc(struct at91_udc_data *data);
-
- /* USB High Speed Device */
-extern void __init at91_add_device_usba(struct usba_platform_data *data);
-
- /* Compact Flash */
-extern void __init at91_add_device_cf(struct at91_cf_data *data);
-
- /* MMC / SD */
-  /* atmel-mci platform config */
-extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data);
-
-extern void __init at91_add_device_eth(struct macb_platform_data *data);
-
- /* USB Host */
-extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
-extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
-extern void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data);
-
-extern void __init at91_add_device_nand(struct atmel_nand_data *data);
-
- /* I2C*/
-#if defined(CONFIG_ARCH_AT91SAM9G45)
-extern void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, int nr_devices);
-#else
-extern void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices);
-#endif
-
- /* SPI */
-extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
-
- /* Serial */
-#define ATMEL_UART_CTS 0x01
-#define ATMEL_UART_RTS 0x02
-#define ATMEL_UART_DSR 0x04
-#define ATMEL_UART_DTR 0x08
-#define ATMEL_UART_DCD 0x10
-#define ATMEL_UART_RI  0x20
-
-extern void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins);
-
-extern struct platform_device *atmel_default_console_device;
-
-extern void __init at91_add_device_serial(void);
-
-/*
- * PWM
- */
-#define AT91_PWM0      0
-#define AT91_PWM1      1
-#define AT91_PWM2      2
-#define AT91_PWM3      3
-
-extern void __init at91_add_device_pwm(u32 mask);
-
-/*
- * SSC -- accessed through ssc_request(id).  Drivers don't bind to SSC
- * platform devices.  Their SSC ID is part of their configuration data,
- * along with information about which SSC signals they should use.
- */
-#define ATMEL_SSC_TK   0x01
-#define ATMEL_SSC_TF   0x02
-#define ATMEL_SSC_TD   0x04
-#define ATMEL_SSC_TX   (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD)
-
-#define ATMEL_SSC_RK   0x10
-#define ATMEL_SSC_RF   0x20
-#define ATMEL_SSC_RD   0x40
-#define ATMEL_SSC_RX   (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD)
-
-extern void __init at91_add_device_ssc(unsigned id, unsigned pins);
-
- /* LCD Controller */
-struct atmel_lcdfb_pdata;
-extern void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data);
-
- /* AC97 */
-extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
-
- /* ISI */
-struct isi_platform_data;
-extern void __init at91_add_device_isi(struct isi_platform_data *data,
-               bool use_pck_as_mck);
-
-/* CAN */
-extern void __init at91_add_device_can(struct at91_can_data *data);
-
- /* LEDs */
-extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
-
-#endif
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
deleted file mode 100644 (file)
index d66f102..0000000
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/clock.c
- *
- * Copyright (C) 2005 David Brownell
- * Copyright (C) 2005 Ivan Kokshaysky
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/of_address.h>
-#include <linux/clk/at91_pmc.h>
-
-#include <mach/hardware.h>
-#include <mach/cpu.h>
-
-#include <asm/proc-fns.h>
-
-#include "clock.h"
-#include "generic.h"
-
-void __iomem *at91_pmc_base;
-EXPORT_SYMBOL_GPL(at91_pmc_base);
-
-/*
- * There's a lot more which can be done with clocks, including cpufreq
- * integration, slow clock mode support (for system suspend), letting
- * PLLB be used at other rates (on boards that don't need USB), etc.
- */
-
-#define clk_is_primary(x)      ((x)->type & CLK_TYPE_PRIMARY)
-#define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE)
-#define clk_is_peripheral(x)   ((x)->type & CLK_TYPE_PERIPHERAL)
-#define clk_is_sys(x)          ((x)->type & CLK_TYPE_SYSTEM)
-
-
-/*
- * Chips have some kind of clocks : group them by functionality
- */
-#define cpu_has_utmi()         (  cpu_is_at91sam9rl() \
-                               || cpu_is_at91sam9g45() \
-                               || cpu_is_at91sam9x5() \
-                               || cpu_is_sama5d3())
-
-#define cpu_has_1056M_plla()   (cpu_is_sama5d3())
-
-#define cpu_has_800M_plla()    (  cpu_is_at91sam9g20() \
-                               || cpu_is_at91sam9g45() \
-                               || cpu_is_at91sam9x5() \
-                               || cpu_is_at91sam9n12())
-
-#define cpu_has_300M_plla()    (cpu_is_at91sam9g10())
-
-#define cpu_has_240M_plla()    (cpu_is_at91sam9261() \
-                               || cpu_is_at91sam9263() \
-                               || cpu_is_at91sam9rl())
-
-#define cpu_has_210M_plla()    (cpu_is_at91sam9260())
-
-#define cpu_has_pllb()         (!(cpu_is_at91sam9rl() \
-                               || cpu_is_at91sam9g45() \
-                               || cpu_is_at91sam9x5() \
-                               || cpu_is_sama5d3()))
-
-#define cpu_has_upll()         (cpu_is_at91sam9g45() \
-                               || cpu_is_at91sam9x5() \
-                               || cpu_is_sama5d3())
-
-/* USB host HS & FS */
-#define cpu_has_uhp()          (!cpu_is_at91sam9rl())
-
-/* USB device FS only */
-#define cpu_has_udpfs()                (!(cpu_is_at91sam9rl() \
-                               || cpu_is_at91sam9g45() \
-                               || cpu_is_at91sam9x5() \
-                               || cpu_is_sama5d3()))
-
-#define cpu_has_plladiv2()     (cpu_is_at91sam9g45() \
-                               || cpu_is_at91sam9x5() \
-                               || cpu_is_at91sam9n12() \
-                               || cpu_is_sama5d3())
-
-#define cpu_has_mdiv3()                (cpu_is_at91sam9g45() \
-                               || cpu_is_at91sam9x5() \
-                               || cpu_is_at91sam9n12() \
-                               || cpu_is_sama5d3())
-
-#define cpu_has_alt_prescaler()        (cpu_is_at91sam9x5() \
-                               || cpu_is_at91sam9n12() \
-                               || cpu_is_sama5d3())
-
-static LIST_HEAD(clocks);
-static DEFINE_SPINLOCK(clk_lock);
-
-static u32 at91_pllb_usb_init;
-
-/*
- * Four primary clock sources:  two crystal oscillators (32K, main), and
- * two PLLs.  PLLA usually runs the master clock; and PLLB must run at
- * 48 MHz (unless no USB function clocks are needed).  The main clock and
- * both PLLs are turned off to run in "slow clock mode" (system suspend).
- */
-static struct clk clk32k = {
-       .name           = "clk32k",
-       .rate_hz        = AT91_SLOW_CLOCK,
-       .users          = 1,            /* always on */
-       .id             = 0,
-       .type           = CLK_TYPE_PRIMARY,
-};
-static struct clk main_clk = {
-       .name           = "main",
-       .pmc_mask       = AT91_PMC_MOSCS,       /* in PMC_SR */
-       .id             = 1,
-       .type           = CLK_TYPE_PRIMARY,
-};
-static struct clk plla = {
-       .name           = "plla",
-       .parent         = &main_clk,
-       .pmc_mask       = AT91_PMC_LOCKA,       /* in PMC_SR */
-       .id             = 2,
-       .type           = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
-};
-
-static void pllb_mode(struct clk *clk, int is_on)
-{
-       u32     value;
-
-       if (is_on) {
-               is_on = AT91_PMC_LOCKB;
-               value = at91_pllb_usb_init;
-       } else
-               value = 0;
-
-       // REVISIT: Add work-around for AT91RM9200 Errata #26 ?
-       at91_pmc_write(AT91_CKGR_PLLBR, value);
-
-       do {
-               cpu_relax();
-       } while ((at91_pmc_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on);
-}
-
-static struct clk pllb = {
-       .name           = "pllb",
-       .parent         = &main_clk,
-       .pmc_mask       = AT91_PMC_LOCKB,       /* in PMC_SR */
-       .mode           = pllb_mode,
-       .id             = 3,
-       .type           = CLK_TYPE_PRIMARY | CLK_TYPE_PLL,
-};
-
-static void pmc_sys_mode(struct clk *clk, int is_on)
-{
-       if (is_on)
-               at91_pmc_write(AT91_PMC_SCER, clk->pmc_mask);
-       else
-               at91_pmc_write(AT91_PMC_SCDR, clk->pmc_mask);
-}
-
-static void pmc_uckr_mode(struct clk *clk, int is_on)
-{
-       unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR);
-
-       if (is_on) {
-               is_on = AT91_PMC_LOCKU;
-               at91_pmc_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask);
-       } else
-               at91_pmc_write(AT91_CKGR_UCKR, uckr & ~(clk->pmc_mask));
-
-       do {
-               cpu_relax();
-       } while ((at91_pmc_read(AT91_PMC_SR) & AT91_PMC_LOCKU) != is_on);
-}
-
-/* USB function clocks (PLLB must be 48 MHz) */
-static struct clk udpck = {
-       .name           = "udpck",
-       .parent         = &pllb,
-       .mode           = pmc_sys_mode,
-};
-struct clk utmi_clk = {
-       .name           = "utmi_clk",
-       .parent         = &main_clk,
-       .pmc_mask       = AT91_PMC_UPLLEN,      /* in CKGR_UCKR */
-       .mode           = pmc_uckr_mode,
-       .type           = CLK_TYPE_PLL,
-};
-static struct clk uhpck = {
-       .name           = "uhpck",
-       /*.parent               = ... we choose parent at runtime */
-       .mode           = pmc_sys_mode,
-};
-
-
-/*
- * The master clock is divided from the CPU clock (by 1-4).  It's used for
- * memory, interfaces to on-chip peripherals, the AIC, and sometimes more
- * (e.g baud rate generation).  It's sourced from one of the primary clocks.
- */
-struct clk mck = {
-       .name           = "mck",
-       .pmc_mask       = AT91_PMC_MCKRDY,      /* in PMC_SR */
-};
-
-static void pmc_periph_mode(struct clk *clk, int is_on)
-{
-       u32 regval = 0;
-
-       /*
-        * With sama5d3 devices, we are managing clock division so we have to
-        * use the Peripheral Control Register introduced from at91sam9x5
-        * devices.
-        */
-       if (cpu_is_sama5d3()) {
-               regval |= AT91_PMC_PCR_CMD; /* write command */
-               regval |= clk->pid & AT91_PMC_PCR_PID; /* peripheral selection */
-               regval |= AT91_PMC_PCR_DIV(clk->div);
-               if (is_on)
-                       regval |= AT91_PMC_PCR_EN; /* enable clock */
-               at91_pmc_write(AT91_PMC_PCR, regval);
-       } else {
-               if (is_on)
-                       at91_pmc_write(AT91_PMC_PCER, clk->pmc_mask);
-               else
-                       at91_pmc_write(AT91_PMC_PCDR, clk->pmc_mask);
-       }
-}
-
-static struct clk __init *at91_css_to_clk(unsigned long css)
-{
-       switch (css) {
-               case AT91_PMC_CSS_SLOW:
-                       return &clk32k;
-               case AT91_PMC_CSS_MAIN:
-                       return &main_clk;
-               case AT91_PMC_CSS_PLLA:
-                       return &plla;
-               case AT91_PMC_CSS_PLLB:
-                       if (cpu_has_upll())
-                               /* CSS_PLLB == CSS_UPLL */
-                               return &utmi_clk;
-                       else if (cpu_has_pllb())
-                               return &pllb;
-                       break;
-               /* alternate PMC: can use master clock */
-               case AT91_PMC_CSS_MASTER:
-                       return &mck;
-       }
-
-       return NULL;
-}
-
-static int pmc_prescaler_divider(u32 reg)
-{
-       if (cpu_has_alt_prescaler()) {
-               return 1 << ((reg & AT91_PMC_ALT_PRES) >> PMC_ALT_PRES_OFFSET);
-       } else {
-               return 1 << ((reg & AT91_PMC_PRES) >> PMC_PRES_OFFSET);
-       }
-}
-
-static void __clk_enable(struct clk *clk)
-{
-       if (clk->parent)
-               __clk_enable(clk->parent);
-       if (clk->users++ == 0 && clk->mode)
-               clk->mode(clk, 1);
-}
-
-int clk_enable(struct clk *clk)
-{
-       unsigned long   flags;
-
-       spin_lock_irqsave(&clk_lock, flags);
-       __clk_enable(clk);
-       spin_unlock_irqrestore(&clk_lock, flags);
-       return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-static void __clk_disable(struct clk *clk)
-{
-       BUG_ON(clk->users == 0);
-       if (--clk->users == 0 && clk->mode)
-               clk->mode(clk, 0);
-       if (clk->parent)
-               __clk_disable(clk->parent);
-}
-
-void clk_disable(struct clk *clk)
-{
-       unsigned long   flags;
-
-       spin_lock_irqsave(&clk_lock, flags);
-       __clk_disable(clk);
-       spin_unlock_irqrestore(&clk_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       unsigned long   flags;
-       unsigned long   rate;
-
-       spin_lock_irqsave(&clk_lock, flags);
-       for (;;) {
-               rate = clk->rate_hz;
-               if (rate || !clk->parent)
-                       break;
-               clk = clk->parent;
-       }
-       spin_unlock_irqrestore(&clk_lock, flags);
-       return rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/*------------------------------------------------------------------------*/
-
-/*
- * For now, only the programmable clocks support reparenting (MCK could
- * do this too, with care) or rate changing (the PLLs could do this too,
- * ditto MCK but that's more for cpufreq).  Drivers may reparent to get
- * a better rate match; we don't.
- */
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       unsigned long   flags;
-       unsigned        prescale;
-       unsigned long   actual;
-       unsigned long   prev = ULONG_MAX;
-
-       if (!clk_is_programmable(clk))
-               return -EINVAL;
-       spin_lock_irqsave(&clk_lock, flags);
-
-       actual = clk->parent->rate_hz;
-       for (prescale = 0; prescale < 7; prescale++) {
-               if (actual > rate)
-                       prev = actual;
-
-               if (actual && actual <= rate) {
-                       if ((prev - rate) < (rate - actual)) {
-                               actual = prev;
-                               prescale--;
-                       }
-                       break;
-               }
-               actual >>= 1;
-       }
-
-       spin_unlock_irqrestore(&clk_lock, flags);
-       return (prescale < 7) ? actual : -ENOENT;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       unsigned long   flags;
-       unsigned        prescale;
-       unsigned long   prescale_offset, css_mask;
-       unsigned long   actual;
-
-       if (!clk_is_programmable(clk))
-               return -EINVAL;
-       if (clk->users)
-               return -EBUSY;
-
-       if (cpu_has_alt_prescaler()) {
-               prescale_offset = PMC_ALT_PRES_OFFSET;
-               css_mask = AT91_PMC_ALT_PCKR_CSS;
-       } else {
-               prescale_offset = PMC_PRES_OFFSET;
-               css_mask = AT91_PMC_CSS;
-       }
-
-       spin_lock_irqsave(&clk_lock, flags);
-
-       actual = clk->parent->rate_hz;
-       for (prescale = 0; prescale < 7; prescale++) {
-               if (actual && actual <= rate) {
-                       u32     pckr;
-
-                       pckr = at91_pmc_read(AT91_PMC_PCKR(clk->id));
-                       pckr &= css_mask;       /* keep clock selection */
-                       pckr |= prescale << prescale_offset;
-                       at91_pmc_write(AT91_PMC_PCKR(clk->id), pckr);
-                       clk->rate_hz = actual;
-                       break;
-               }
-               actual >>= 1;
-       }
-
-       spin_unlock_irqrestore(&clk_lock, flags);
-       return (prescale < 7) ? actual : -ENOENT;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-       return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       unsigned long   flags;
-
-       if (clk->users)
-               return -EBUSY;
-       if (!clk_is_primary(parent) || !clk_is_programmable(clk))
-               return -EINVAL;
-
-       if (cpu_is_at91sam9rl() && parent->id == AT91_PMC_CSS_PLLB)
-               return -EINVAL;
-
-       spin_lock_irqsave(&clk_lock, flags);
-
-       clk->rate_hz = parent->rate_hz;
-       clk->parent = parent;
-       at91_pmc_write(AT91_PMC_PCKR(clk->id), parent->id);
-
-       spin_unlock_irqrestore(&clk_lock, flags);
-       return 0;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-/* establish PCK0..PCKN parentage and rate */
-static void __init init_programmable_clock(struct clk *clk)
-{
-       struct clk      *parent;
-       u32             pckr;
-       unsigned int    css_mask;
-
-       if (cpu_has_alt_prescaler())
-               css_mask = AT91_PMC_ALT_PCKR_CSS;
-       else
-               css_mask = AT91_PMC_CSS;
-
-       pckr = at91_pmc_read(AT91_PMC_PCKR(clk->id));
-       parent = at91_css_to_clk(pckr & css_mask);
-       clk->parent = parent;
-       clk->rate_hz = parent->rate_hz / pmc_prescaler_divider(pckr);
-}
-
-/*------------------------------------------------------------------------*/
-
-#ifdef CONFIG_DEBUG_FS
-
-static int at91_clk_show(struct seq_file *s, void *unused)
-{
-       u32             scsr, pcsr, pcsr1 = 0, uckr = 0, sr;
-       struct clk      *clk;
-
-       scsr = at91_pmc_read(AT91_PMC_SCSR);
-       pcsr = at91_pmc_read(AT91_PMC_PCSR);
-       if (cpu_is_sama5d3())
-               pcsr1 = at91_pmc_read(AT91_PMC_PCSR1);
-       sr = at91_pmc_read(AT91_PMC_SR);
-       seq_printf(s, "SCSR = %8x\n", scsr);
-       seq_printf(s, "PCSR = %8x\n", pcsr);
-       if (cpu_is_sama5d3())
-               seq_printf(s, "PCSR1 = %8x\n", pcsr1);
-       seq_printf(s, "MOR  = %8x\n", at91_pmc_read(AT91_CKGR_MOR));
-       seq_printf(s, "MCFR = %8x\n", at91_pmc_read(AT91_CKGR_MCFR));
-       seq_printf(s, "PLLA = %8x\n", at91_pmc_read(AT91_CKGR_PLLAR));
-       if (cpu_has_pllb())
-               seq_printf(s, "PLLB = %8x\n", at91_pmc_read(AT91_CKGR_PLLBR));
-       if (cpu_has_utmi()) {
-               uckr = at91_pmc_read(AT91_CKGR_UCKR);
-               seq_printf(s, "UCKR = %8x\n", uckr);
-       }
-       seq_printf(s, "MCKR = %8x\n", at91_pmc_read(AT91_PMC_MCKR));
-       if (cpu_has_upll() || cpu_is_at91sam9n12())
-               seq_printf(s, "USB  = %8x\n", at91_pmc_read(AT91_PMC_USB));
-       seq_printf(s, "SR   = %8x\n", sr);
-
-       seq_printf(s, "\n");
-
-       list_for_each_entry(clk, &clocks, node) {
-               char    *state;
-
-               if (clk->mode == pmc_sys_mode) {
-                       state = (scsr & clk->pmc_mask) ? "on" : "off";
-               } else if (clk->mode == pmc_periph_mode) {
-                       if (cpu_is_sama5d3()) {
-                               u32 pmc_mask = 1 << (clk->pid % 32);
-
-                               if (clk->pid > 31)
-                                       state = (pcsr1 & pmc_mask) ? "on" : "off";
-                               else
-                                       state = (pcsr & pmc_mask) ? "on" : "off";
-                       } else {
-                               state = (pcsr & clk->pmc_mask) ? "on" : "off";
-                       }
-               } else if (clk->mode == pmc_uckr_mode) {
-                       state = (uckr & clk->pmc_mask) ? "on" : "off";
-               } else if (clk->pmc_mask) {
-                       state = (sr & clk->pmc_mask) ? "on" : "off";
-               } else if (clk == &clk32k || clk == &main_clk) {
-                       state = "on";
-               } else {
-                       state = "";
-               }
-
-               seq_printf(s, "%-10s users=%2d %-3s %9lu Hz %s\n",
-                       clk->name, clk->users, state, clk_get_rate(clk),
-                       clk->parent ? clk->parent->name : "");
-       }
-       return 0;
-}
-
-static int at91_clk_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, at91_clk_show, NULL);
-}
-
-static const struct file_operations at91_clk_operations = {
-       .open           = at91_clk_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init at91_clk_debugfs_init(void)
-{
-       /* /sys/kernel/debug/at91_clk */
-       (void) debugfs_create_file("at91_clk", S_IFREG | S_IRUGO, NULL, NULL, &at91_clk_operations);
-
-       return 0;
-}
-postcore_initcall(at91_clk_debugfs_init);
-
-#endif
-
-/*------------------------------------------------------------------------*/
-
-/* Register a new clock */
-static void __init at91_clk_add(struct clk *clk)
-{
-       list_add_tail(&clk->node, &clocks);
-
-       clk->cl.con_id = clk->name;
-       clk->cl.clk = clk;
-       clkdev_add(&clk->cl);
-}
-
-int __init clk_register(struct clk *clk)
-{
-       if (clk_is_peripheral(clk)) {
-               if (!clk->parent)
-                       clk->parent = &mck;
-               if (cpu_is_sama5d3())
-                       clk->rate_hz = DIV_ROUND_UP(clk->parent->rate_hz,
-                                                   1 << clk->div);
-               clk->mode = pmc_periph_mode;
-       }
-       else if (clk_is_sys(clk)) {
-               clk->parent = &mck;
-               clk->mode = pmc_sys_mode;
-       }
-       else if (clk_is_programmable(clk)) {
-               clk->mode = pmc_sys_mode;
-               init_programmable_clock(clk);
-       }
-
-       at91_clk_add(clk);
-
-       return 0;
-}
-
-/*------------------------------------------------------------------------*/
-
-static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
-{
-       unsigned mul, div;
-
-       div = reg & 0xff;
-       if (cpu_is_sama5d3())
-               mul = AT91_PMC3_MUL_GET(reg);
-       else
-               mul = AT91_PMC_MUL_GET(reg);
-
-       if (div && mul) {
-               freq /= div;
-               freq *= mul + 1;
-       } else
-               freq = 0;
-
-       return freq;
-}
-
-static u32 __init at91_usb_rate(struct clk *pll, u32 freq, u32 reg)
-{
-       if (pll == &pllb && (reg & AT91_PMC_USB96M))
-               return freq / 2;
-       else if (pll == &utmi_clk || cpu_is_at91sam9n12())
-               return freq / (1 + ((reg & AT91_PMC_OHCIUSBDIV) >> 8));
-       else
-               return freq;
-}
-
-static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq)
-{
-       unsigned i, div = 0, mul = 0, diff = 1 << 30;
-       unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
-
-       /* PLL output max 240 MHz (or 180 MHz per errata) */
-       if (out_freq > 240000000)
-               goto fail;
-
-       for (i = 1; i < 256; i++) {
-               int diff1;
-               unsigned input, mul1;
-
-               /*
-                * PLL input between 1MHz and 32MHz per spec, but lower
-                * frequences seem necessary in some cases so allow 100K.
-                * Warning: some newer products need 2MHz min.
-                */
-               input = main_freq / i;
-               if (cpu_is_at91sam9g20() && input < 2000000)
-                       continue;
-               if (input < 100000)
-                       continue;
-               if (input > 32000000)
-                       continue;
-
-               mul1 = out_freq / input;
-               if (cpu_is_at91sam9g20() && mul > 63)
-                       continue;
-               if (mul1 > 2048)
-                       continue;
-               if (mul1 < 2)
-                       goto fail;
-
-               diff1 = out_freq - input * mul1;
-               if (diff1 < 0)
-                       diff1 = -diff1;
-               if (diff > diff1) {
-                       diff = diff1;
-                       div = i;
-                       mul = mul1;
-                       if (diff == 0)
-                               break;
-               }
-       }
-       if (i == 256 && diff > (out_freq >> 5))
-               goto fail;
-       return ret | ((mul - 1) << 16) | div;
-fail:
-       return 0;
-}
-
-static struct clk *const standard_pmc_clocks[] __initconst = {
-       /* four primary clocks */
-       &clk32k,
-       &main_clk,
-       &plla,
-
-       /* MCK */
-       &mck
-};
-
-/* PLLB generated USB full speed clock init */
-static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)
-{
-       unsigned int reg;
-
-       /*
-        * USB clock init:  choose 48 MHz PLLB value,
-        * disable 48MHz clock during usb peripheral suspend.
-        *
-        * REVISIT:  assumes MCK doesn't derive from PLLB!
-        */
-       uhpck.parent = &pllb;
-
-       reg = at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2);
-       pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
-       if (cpu_is_at91rm9200()) {
-               reg = at91_pllb_usb_init |= AT91_PMC_USB96M;
-               uhpck.pmc_mask = AT91RM9200_PMC_UHP;
-               udpck.pmc_mask = AT91RM9200_PMC_UDP;
-               at91_pmc_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
-       } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() ||
-                  cpu_is_at91sam9263() || cpu_is_at91sam9g20() ||
-                  cpu_is_at91sam9g10()) {
-               reg = at91_pllb_usb_init |= AT91_PMC_USB96M;
-               uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-               udpck.pmc_mask = AT91SAM926x_PMC_UDP;
-       } else if (cpu_is_at91sam9n12()) {
-               /* Divider for USB clock is in USB clock register for 9n12 */
-               reg = AT91_PMC_USBS_PLLB;
-
-               /* For PLLB output 96M, set usb divider 2 (USBDIV + 1) */
-               reg |= AT91_PMC_OHCIUSBDIV_2;
-               at91_pmc_write(AT91_PMC_USB, reg);
-
-               /* Still setup masks */
-               uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-               udpck.pmc_mask = AT91SAM926x_PMC_UDP;
-       }
-       at91_pmc_write(AT91_CKGR_PLLBR, 0);
-
-       udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, reg);
-       uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, reg);
-}
-
-/* UPLL generated USB full speed clock init */
-static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
-{
-       /*
-        * USB clock init: choose 480 MHz from UPLL,
-        */
-       unsigned int usbr = AT91_PMC_USBS_UPLL;
-
-       /* Setup divider by 10 to reach 48 MHz */
-       usbr |= ((10 - 1) << 8) & AT91_PMC_OHCIUSBDIV;
-
-       at91_pmc_write(AT91_PMC_USB, usbr);
-
-       /* Now set uhpck values */
-       uhpck.parent = &utmi_clk;
-       uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-       uhpck.rate_hz = at91_usb_rate(&utmi_clk, utmi_clk.rate_hz, usbr);
-}
-
-static int __init at91_pmc_init(unsigned long main_clock)
-{
-       unsigned tmp, freq, mckr;
-       int i;
-       int pll_overclock = false;
-
-       /*
-        * When the bootloader initialized the main oscillator correctly,
-        * there's no problem using the cycle counter.  But if it didn't,
-        * or when using oscillator bypass mode, we must be told the speed
-        * of the main clock.
-        */
-       if (!main_clock) {
-               do {
-                       tmp = at91_pmc_read(AT91_CKGR_MCFR);
-               } while (!(tmp & AT91_PMC_MAINRDY));
-               main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
-       }
-       main_clk.rate_hz = main_clock;
-
-       /* report if PLLA is more than mildly overclocked */
-       plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_pmc_read(AT91_CKGR_PLLAR));
-       if (cpu_has_1056M_plla()) {
-               if (plla.rate_hz > 1056000000)
-                       pll_overclock = true;
-       } else if (cpu_has_800M_plla()) {
-               if (plla.rate_hz > 800000000)
-                       pll_overclock = true;
-       } else if (cpu_has_300M_plla()) {
-               if (plla.rate_hz > 300000000)
-                       pll_overclock = true;
-       } else if (cpu_has_240M_plla()) {
-               if (plla.rate_hz > 240000000)
-                       pll_overclock = true;
-       } else if (cpu_has_210M_plla()) {
-               if (plla.rate_hz > 210000000)
-                       pll_overclock = true;
-       } else {
-               if (plla.rate_hz > 209000000)
-                       pll_overclock = true;
-       }
-       if (pll_overclock)
-               pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
-
-       if (cpu_has_plladiv2()) {
-               mckr = at91_pmc_read(AT91_PMC_MCKR);
-               plla.rate_hz /= (1 << ((mckr & AT91_PMC_PLLADIV2) >> 12));      /* plla divisor by 2 */
-       }
-
-       if (!cpu_has_pllb() && cpu_has_upll()) {
-               /* setup UTMI clock as the fourth primary clock
-                * (instead of pllb) */
-               utmi_clk.type |= CLK_TYPE_PRIMARY;
-               utmi_clk.id = 3;
-       }
-
-
-       /*
-        * USB HS clock init
-        */
-       if (cpu_has_utmi()) {
-               /*
-                * multiplier is hard-wired to 40
-                * (obtain the USB High Speed 480 MHz when input is 12 MHz)
-                */
-               utmi_clk.rate_hz = 40 * utmi_clk.parent->rate_hz;
-
-               /* UTMI bias and PLL are managed at the same time */
-               if (cpu_has_upll())
-                       utmi_clk.pmc_mask |= AT91_PMC_BIASEN;
-       }
-
-       /*
-        * USB FS clock init
-        */
-       if (cpu_has_pllb())
-               at91_pllb_usbfs_clock_init(main_clock);
-       if (cpu_has_upll())
-               /* assumes that we choose UPLL for USB and not PLLA */
-               at91_upll_usbfs_clock_init(main_clock);
-
-       /*
-        * MCK and CPU derive from one of those primary clocks.
-        * For now, assume this parentage won't change.
-        */
-       mckr = at91_pmc_read(AT91_PMC_MCKR);
-       mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
-       freq = mck.parent->rate_hz;
-       freq /= pmc_prescaler_divider(mckr);                                    /* prescale */
-       if (cpu_is_at91rm9200()) {
-               mck.rate_hz = freq / (1 + ((mckr & AT91_PMC_MDIV) >> 8));       /* mdiv */
-       } else if (cpu_is_at91sam9g20()) {
-               mck.rate_hz = (mckr & AT91_PMC_MDIV) ?
-                       freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq;    /* mdiv ; (x >> 7) = ((x >> 8) * 2) */
-               if (mckr & AT91_PMC_PDIV)
-                       freq /= 2;              /* processor clock division */
-       } else if (cpu_has_mdiv3()) {
-               mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ?
-                       freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
-       } else {
-               mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8));              /* mdiv */
-       }
-
-       if (cpu_has_alt_prescaler()) {
-               /* Programmable clocks can use MCK */
-               mck.type |= CLK_TYPE_PRIMARY;
-               mck.id = 4;
-       }
-
-       /* Register the PMC's standard clocks */
-       for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++)
-               at91_clk_add(standard_pmc_clocks[i]);
-
-       if (cpu_has_pllb())
-               at91_clk_add(&pllb);
-
-       if (cpu_has_uhp())
-               at91_clk_add(&uhpck);
-
-       if (cpu_has_udpfs())
-               at91_clk_add(&udpck);
-
-       if (cpu_has_utmi())
-               at91_clk_add(&utmi_clk);
-
-       /* MCK and CPU clock are "always on" */
-       clk_enable(&mck);
-
-       printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
-               freq / 1000000, (unsigned) mck.rate_hz / 1000000,
-               (unsigned) main_clock / 1000000,
-               ((unsigned) main_clock % 1000000) / 1000);
-
-       return 0;
-}
-
-#if defined(CONFIG_OF)
-static struct of_device_id pmc_ids[] = {
-       { .compatible = "atmel,at91rm9200-pmc" },
-       { .compatible = "atmel,at91sam9260-pmc" },
-       { .compatible = "atmel,at91sam9g45-pmc" },
-       { .compatible = "atmel,at91sam9n12-pmc" },
-       { .compatible = "atmel,at91sam9x5-pmc" },
-       { .compatible = "atmel,sama5d3-pmc" },
-       { /*sentinel*/ }
-};
-
-static struct of_device_id osc_ids[] = {
-       { .compatible = "atmel,osc" },
-       { /*sentinel*/ }
-};
-
-int __init at91_dt_clock_init(void)
-{
-       struct device_node *np;
-       u32 main_clock = 0;
-
-       np = of_find_matching_node(NULL, pmc_ids);
-       if (!np)
-               panic("unable to find compatible pmc node in dtb\n");
-
-       at91_pmc_base = of_iomap(np, 0);
-       if (!at91_pmc_base)
-               panic("unable to map pmc cpu registers\n");
-
-       of_node_put(np);
-
-       /* retrieve the freqency of fixed clocks from device tree */
-       np = of_find_matching_node(NULL, osc_ids);
-       if (np) {
-               u32 rate;
-               if (!of_property_read_u32(np, "clock-frequency", &rate))
-                       main_clock = rate;
-       }
-
-       of_node_put(np);
-
-       return at91_pmc_init(main_clock);
-}
-#endif
-
-int __init at91_clock_init(unsigned long main_clock)
-{
-       at91_pmc_base = ioremap(AT91_PMC, 256);
-       if (!at91_pmc_base)
-               panic("Impossible to ioremap AT91_PMC 0x%x\n", AT91_PMC);
-
-       return at91_pmc_init(main_clock);
-}
-
-/*
- * Several unused clocks may be active.  Turn them off.
- */
-static int __init at91_clock_reset(void)
-{
-       unsigned long pcdr = 0;
-       unsigned long pcdr1 = 0;
-       unsigned long scdr = 0;
-       struct clk *clk;
-
-       list_for_each_entry(clk, &clocks, node) {
-               if (clk->users > 0)
-                       continue;
-
-               if (clk->mode == pmc_periph_mode) {
-                       if (cpu_is_sama5d3()) {
-                               u32 pmc_mask = 1 << (clk->pid % 32);
-
-                               if (clk->pid > 31)
-                                       pcdr1 |= pmc_mask;
-                               else
-                                       pcdr |= pmc_mask;
-                       } else
-                               pcdr |= clk->pmc_mask;
-               }
-
-               if (clk->mode == pmc_sys_mode)
-                       scdr |= clk->pmc_mask;
-
-               pr_debug("Clocks: disable unused %s\n", clk->name);
-       }
-
-       at91_pmc_write(AT91_PMC_SCDR, scdr);
-       at91_pmc_write(AT91_PMC_PCDR, pcdr);
-       if (cpu_is_sama5d3())
-               at91_pmc_write(AT91_PMC_PCDR1, pcdr1);
-
-       return 0;
-}
-late_initcall(at91_clock_reset);
-
-void at91sam9_idle(void)
-{
-       at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK);
-       cpu_do_idle();
-}
diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h
deleted file mode 100644 (file)
index a98a39b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/clock.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clkdev.h>
-
-#define CLK_TYPE_PRIMARY       0x1
-#define CLK_TYPE_PLL           0x2
-#define CLK_TYPE_PROGRAMMABLE  0x4
-#define CLK_TYPE_PERIPHERAL    0x8
-#define CLK_TYPE_SYSTEM                0x10
-
-
-struct clk {
-       struct list_head node;
-       const char      *name;          /* unique clock name */
-       struct clk_lookup cl;
-       unsigned long   rate_hz;
-       unsigned        div;            /* parent clock divider */
-       struct clk      *parent;
-       unsigned        pid;            /* peripheral ID */
-       u32             pmc_mask;
-       void            (*mode)(struct clk *, int);
-       unsigned        id:3;           /* PCK0..4, or 32k/main/a/b */
-       unsigned        type;           /* clock type */
-       u16             users;
-};
-
-
-extern int __init clk_register(struct clk *clk);
-extern struct clk mck;
-extern struct clk utmi_clk;
-
-#define CLKDEV_CON_ID(_id, _clk)                       \
-       {                                               \
-               .con_id = _id,                          \
-               .clk = _clk,                            \
-       }
-
-#define CLKDEV_CON_DEV_ID(_con_id, _dev_id, _clk)      \
-       {                                               \
-               .con_id = _con_id,                      \
-               .dev_id = _dev_id,                      \
-               .clk = _clk,                            \
-       }
index 81959cf4a13715ebd60405b768b7e20af423efc2..d53324210adf62310d15a191380eed7b3e2e6e9e 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef _AT91_GENERIC_H
 #define _AT91_GENERIC_H
 
-#include <linux/clkdev.h>
 #include <linux/of.h>
 #include <linux/reboot.h>
 
@@ -23,71 +22,19 @@ extern void __init at91_init_sram(int bank, unsigned long base,
 
  /* Processors */
 extern void __init at91rm9200_set_type(int type);
-extern void __init at91_initialize(unsigned long main_clock);
-extern void __init at91x40_initialize(unsigned long main_clock);
 extern void __init at91rm9200_dt_initialize(void);
 extern void __init at91_dt_initialize(void);
 
  /* Interrupts */
-extern void __init at91_init_irq_default(void);
-extern void __init at91_init_interrupts(unsigned int priority[]);
-extern void __init at91x40_init_interrupts(unsigned int priority[]);
-extern void __init at91_aic_init(unsigned int priority[],
-                                unsigned int ext_irq_mask);
-extern int  __init at91_aic_of_init(struct device_node *node,
-                                   struct device_node *parent);
-extern int  __init at91_aic5_of_init(struct device_node *node,
-                                   struct device_node *parent);
 extern void __init at91_sysirq_mask_rtc(u32 rtc_base);
 extern void __init at91_sysirq_mask_rtt(u32 rtt_base);
 
- /* Devices */
-extern void __init at91_register_devices(void);
-
  /* Timer */
-extern void __init at91_init_time(void);
-extern void at91rm9200_ioremap_st(u32 addr);
 extern void at91rm9200_timer_init(void);
-extern void at91sam926x_ioremap_pit(u32 addr);
-extern void at91sam926x_pit_init(int irq);
-extern void at91x40_timer_init(void);
-
- /* Clocks */
-#ifdef CONFIG_OLD_CLK_AT91
-extern int __init at91_clock_init(unsigned long main_clock);
-extern int __init at91_dt_clock_init(void);
-#else
-static int inline at91_clock_init(unsigned long main_clock) { return 0; }
-static int inline at91_dt_clock_init(void) { return 0; }
-#endif
-struct device;
-
- /* Power Management */
-extern void at91_irq_suspend(void);
-extern void at91_irq_resume(void);
 
 /* idle */
 extern void at91sam9_idle(void);
 
 /* Matrix */
 extern void at91_ioremap_matrix(u32 base_addr);
-
-/* Ram Controler */
-extern void at91_ioremap_ramc(int id, u32 addr, u32 size);
-
- /* GPIO */
-#define AT91RM9200_PQFP                3       /* AT91RM9200 PQFP package has 3 banks */
-#define AT91RM9200_BGA         4       /* AT91RM9200 BGA package has 4 banks */
-
-struct at91_gpio_bank {
-       unsigned short id;              /* peripheral ID */
-       unsigned long regbase;          /* offset from system peripheral base */
-};
-extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
-extern void __init at91_gpio_irq_setup(void);
-extern int  __init at91_gpio_of_irq_setup(struct device_node *node,
-                                         struct device_node *parent);
-
-extern u32 at91_get_extern_irq(void);
-
 #endif /* _AT91_GENERIC_H */
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
deleted file mode 100644 (file)
index d3f05aa..0000000
+++ /dev/null
@@ -1,982 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/gpio.c
- *
- * Copyright (C) 2005 HP Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/errno.h>
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/irqdomain.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/of_address.h>
-
-#include <mach/hardware.h>
-#include <mach/at91_pio.h>
-
-#include "generic.h"
-#include "gpio.h"
-
-#define MAX_NB_GPIO_PER_BANK   32
-
-struct at91_gpio_chip {
-       struct gpio_chip        chip;
-       struct at91_gpio_chip   *next;          /* Bank sharing same clock */
-       int                     pioc_hwirq;     /* PIO bank interrupt identifier on AIC */
-       int                     pioc_virq;      /* PIO bank Linux virtual interrupt */
-       int                     pioc_idx;       /* PIO bank index */
-       void __iomem            *regbase;       /* PIO bank virtual address */
-       struct clk              *clock;         /* associated clock */
-       struct irq_domain       *domain;        /* associated irq domain */
-};
-
-#define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip)
-
-static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset);
-static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
-static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
-static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset);
-static int at91_gpiolib_get_direction(struct gpio_chip *chip, unsigned offset);
-static int at91_gpiolib_direction_output(struct gpio_chip *chip,
-                                        unsigned offset, int val);
-static int at91_gpiolib_direction_input(struct gpio_chip *chip,
-                                       unsigned offset);
-static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset);
-
-#define AT91_GPIO_CHIP(name)                                           \
-       {                                                               \
-               .chip = {                                               \
-                       .label            = name,                       \
-                       .request          = at91_gpiolib_request,       \
-                       .get_direction    = at91_gpiolib_get_direction, \
-                       .direction_input  = at91_gpiolib_direction_input, \
-                       .direction_output = at91_gpiolib_direction_output, \
-                       .get              = at91_gpiolib_get,           \
-                       .set              = at91_gpiolib_set,           \
-                       .dbg_show         = at91_gpiolib_dbg_show,      \
-                       .to_irq           = at91_gpiolib_to_irq,        \
-                       .ngpio            = MAX_NB_GPIO_PER_BANK,       \
-               },                                                      \
-       }
-
-static struct at91_gpio_chip gpio_chip[] = {
-       AT91_GPIO_CHIP("pioA"),
-       AT91_GPIO_CHIP("pioB"),
-       AT91_GPIO_CHIP("pioC"),
-       AT91_GPIO_CHIP("pioD"),
-       AT91_GPIO_CHIP("pioE"),
-};
-
-static int gpio_banks;
-static unsigned long at91_gpio_caps;
-
-/* All PIO controllers support PIO3 features */
-#define AT91_GPIO_CAP_PIO3     (1 <<  0)
-
-#define has_pio3()     (at91_gpio_caps & AT91_GPIO_CAP_PIO3)
-
-/*--------------------------------------------------------------------------*/
-
-static inline void __iomem *pin_to_controller(unsigned pin)
-{
-       pin /= MAX_NB_GPIO_PER_BANK;
-       if (likely(pin < gpio_banks))
-               return gpio_chip[pin].regbase;
-
-       return NULL;
-}
-
-static inline unsigned pin_to_mask(unsigned pin)
-{
-       return 1 << (pin % MAX_NB_GPIO_PER_BANK);
-}
-
-
-static char peripheral_function(void __iomem *pio, unsigned mask)
-{
-       char    ret = 'X';
-       u8      select;
-
-       if (pio) {
-               if (has_pio3()) {
-                       select = !!(__raw_readl(pio + PIO_ABCDSR1) & mask);
-                       select |= (!!(__raw_readl(pio + PIO_ABCDSR2) & mask) << 1);
-                       ret = 'A' + select;
-               } else {
-                       ret = __raw_readl(pio + PIO_ABSR) & mask ?
-                                                       'B' : 'A';
-               }
-       }
-
-       return ret;
-}
-
-/*--------------------------------------------------------------------------*/
-
-/* Not all hardware capabilities are exposed through these calls; they
- * only encapsulate the most common features and modes.  (So if you
- * want to change signals in groups, do it directly.)
- *
- * Bootloaders will usually handle some of the pin multiplexing setup.
- * The intent is certainly that by the time Linux is fully booted, all
- * pins should have been fully initialized.  These setup calls should
- * only be used by board setup routines, or possibly in driver probe().
- *
- * For bootloaders doing all that setup, these calls could be inlined
- * as NOPs so Linux won't duplicate any setup code
- */
-
-
-/*
- * mux the pin to the "GPIO" peripheral role.
- */
-int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-       __raw_writel(mask, pio + PIO_IDR);
-       __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-       __raw_writel(mask, pio + PIO_PER);
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_GPIO_periph);
-
-
-/*
- * mux the pin to the "A" internal peripheral role.
- */
-int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-
-       __raw_writel(mask, pio + PIO_IDR);
-       __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-       if (has_pio3()) {
-               __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask,
-                                                       pio + PIO_ABCDSR1);
-               __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
-                                                       pio + PIO_ABCDSR2);
-       } else {
-               __raw_writel(mask, pio + PIO_ASR);
-       }
-       __raw_writel(mask, pio + PIO_PDR);
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_A_periph);
-
-
-/*
- * mux the pin to the "B" internal peripheral role.
- */
-int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-
-       __raw_writel(mask, pio + PIO_IDR);
-       __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-       if (has_pio3()) {
-               __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask,
-                                                       pio + PIO_ABCDSR1);
-               __raw_writel(__raw_readl(pio + PIO_ABCDSR2) & ~mask,
-                                                       pio + PIO_ABCDSR2);
-       } else {
-               __raw_writel(mask, pio + PIO_BSR);
-       }
-       __raw_writel(mask, pio + PIO_PDR);
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_B_periph);
-
-
-/*
- * mux the pin to the "C" internal peripheral role.
- */
-int __init_or_module at91_set_C_periph(unsigned pin, int use_pullup)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio || !has_pio3())
-               return -EINVAL;
-
-       __raw_writel(mask, pio + PIO_IDR);
-       __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-       __raw_writel(__raw_readl(pio + PIO_ABCDSR1) & ~mask, pio + PIO_ABCDSR1);
-       __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
-       __raw_writel(mask, pio + PIO_PDR);
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_C_periph);
-
-
-/*
- * mux the pin to the "D" internal peripheral role.
- */
-int __init_or_module at91_set_D_periph(unsigned pin, int use_pullup)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio || !has_pio3())
-               return -EINVAL;
-
-       __raw_writel(mask, pio + PIO_IDR);
-       __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-       __raw_writel(__raw_readl(pio + PIO_ABCDSR1) | mask, pio + PIO_ABCDSR1);
-       __raw_writel(__raw_readl(pio + PIO_ABCDSR2) | mask, pio + PIO_ABCDSR2);
-       __raw_writel(mask, pio + PIO_PDR);
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_D_periph);
-
-
-/*
- * mux the pin to the gpio controller (instead of "A", "B", "C"
- * or "D" peripheral), and configure it for an input.
- */
-int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-
-       __raw_writel(mask, pio + PIO_IDR);
-       __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
-       __raw_writel(mask, pio + PIO_ODR);
-       __raw_writel(mask, pio + PIO_PER);
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_gpio_input);
-
-
-/*
- * mux the pin to the gpio controller (instead of "A", "B", "C"
- * or "D" peripheral), and configure it for an output.
- */
-int __init_or_module at91_set_gpio_output(unsigned pin, int value)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-
-       __raw_writel(mask, pio + PIO_IDR);
-       __raw_writel(mask, pio + PIO_PUDR);
-       __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
-       __raw_writel(mask, pio + PIO_OER);
-       __raw_writel(mask, pio + PIO_PER);
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_gpio_output);
-
-
-/*
- * enable/disable the glitch filter; mostly used with IRQ handling.
- */
-int __init_or_module at91_set_deglitch(unsigned pin, int is_on)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-
-       if (has_pio3() && is_on)
-               __raw_writel(mask, pio + PIO_IFSCDR);
-       __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_deglitch);
-
-/*
- * enable/disable the debounce filter;
- */
-int __init_or_module at91_set_debounce(unsigned pin, int is_on, int div)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio || !has_pio3())
-               return -EINVAL;
-
-       if (is_on) {
-               __raw_writel(mask, pio + PIO_IFSCER);
-               __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
-               __raw_writel(mask, pio + PIO_IFER);
-       } else {
-               __raw_writel(mask, pio + PIO_IFDR);
-       }
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_debounce);
-
-/*
- * enable/disable the multi-driver; This is only valid for output and
- * allows the output pin to run as an open collector output.
- */
-int __init_or_module at91_set_multi_drive(unsigned pin, int is_on)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-
-       __raw_writel(mask, pio + (is_on ? PIO_MDER : PIO_MDDR));
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_multi_drive);
-
-/*
- * enable/disable the pull-down.
- * If pull-up already enabled while calling the function, we disable it.
- */
-int __init_or_module at91_set_pulldown(unsigned pin, int is_on)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio || !has_pio3())
-               return -EINVAL;
-
-       /* Disable pull-up anyway */
-       __raw_writel(mask, pio + PIO_PUDR);
-       __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_pulldown);
-
-/*
- * disable Schmitt trigger
- */
-int __init_or_module at91_disable_schmitt_trig(unsigned pin)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio || !has_pio3())
-               return -EINVAL;
-
-       __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
-       return 0;
-}
-EXPORT_SYMBOL(at91_disable_schmitt_trig);
-
-/*
- * assuming the pin is muxed as a gpio output, set its value.
- */
-int at91_set_gpio_value(unsigned pin, int value)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if (!pio)
-               return -EINVAL;
-       __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
-       return 0;
-}
-EXPORT_SYMBOL(at91_set_gpio_value);
-
-
-/*
- * read the pin's value (works even if it's not muxed as a gpio).
- */
-int at91_get_gpio_value(unsigned pin)
-{
-       void __iomem    *pio = pin_to_controller(pin);
-       unsigned        mask = pin_to_mask(pin);
-       u32             pdsr;
-
-       if (!pio)
-               return -EINVAL;
-       pdsr = __raw_readl(pio + PIO_PDSR);
-       return (pdsr & mask) != 0;
-}
-EXPORT_SYMBOL(at91_get_gpio_value);
-
-/*--------------------------------------------------------------------------*/
-
-#ifdef CONFIG_PM
-
-static u32 wakeups[MAX_GPIO_BANKS];
-static u32 backups[MAX_GPIO_BANKS];
-
-static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
-{
-       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-       unsigned        mask = 1 << d->hwirq;
-       unsigned        bank = at91_gpio->pioc_idx;
-
-       if (unlikely(bank >= MAX_GPIO_BANKS))
-               return -EINVAL;
-
-       if (state)
-               wakeups[bank] |= mask;
-       else
-               wakeups[bank] &= ~mask;
-
-       irq_set_irq_wake(at91_gpio->pioc_virq, state);
-
-       return 0;
-}
-
-void at91_gpio_suspend(void)
-{
-       int i;
-
-       for (i = 0; i < gpio_banks; i++) {
-               void __iomem    *pio = gpio_chip[i].regbase;
-
-               backups[i] = __raw_readl(pio + PIO_IMR);
-               __raw_writel(backups[i], pio + PIO_IDR);
-               __raw_writel(wakeups[i], pio + PIO_IER);
-
-               if (!wakeups[i]) {
-                       clk_unprepare(gpio_chip[i].clock);
-                       clk_disable(gpio_chip[i].clock);
-               } else {
-#ifdef CONFIG_PM_DEBUG
-                       printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]);
-#endif
-               }
-       }
-}
-
-void at91_gpio_resume(void)
-{
-       int i;
-
-       for (i = 0; i < gpio_banks; i++) {
-               void __iomem    *pio = gpio_chip[i].regbase;
-
-               if (!wakeups[i]) {
-                       if (clk_prepare(gpio_chip[i].clock) == 0)
-                               clk_enable(gpio_chip[i].clock);
-               }
-
-               __raw_writel(wakeups[i], pio + PIO_IDR);
-               __raw_writel(backups[i], pio + PIO_IER);
-       }
-}
-
-#else
-#define gpio_irq_set_wake      NULL
-#endif
-
-
-/* Several AIC controller irqs are dispatched through this GPIO handler.
- * To use any AT91_PIN_* as an externally triggered IRQ, first call
- * at91_set_gpio_input() then maybe enable its glitch filter.
- * Then just request_irq() with the pin ID; it works like any ARM IRQ
- * handler.
- * First implementation always triggers on rising and falling edges
- * whereas the newer PIO3 can be additionally configured to trigger on
- * level, edge with any polarity.
- *
- * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
- * configuring them with at91_set_a_periph() or at91_set_b_periph().
- * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
- */
-
-static void gpio_irq_mask(struct irq_data *d)
-{
-       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-       void __iomem    *pio = at91_gpio->regbase;
-       unsigned        mask = 1 << d->hwirq;
-
-       if (pio)
-               __raw_writel(mask, pio + PIO_IDR);
-}
-
-static void gpio_irq_unmask(struct irq_data *d)
-{
-       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-       void __iomem    *pio = at91_gpio->regbase;
-       unsigned        mask = 1 << d->hwirq;
-
-       if (pio)
-               __raw_writel(mask, pio + PIO_IER);
-}
-
-static int gpio_irq_type(struct irq_data *d, unsigned type)
-{
-       switch (type) {
-       case IRQ_TYPE_NONE:
-       case IRQ_TYPE_EDGE_BOTH:
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-/* Alternate irq type for PIO3 support */
-static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
-{
-       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
-       void __iomem    *pio = at91_gpio->regbase;
-       unsigned        mask = 1 << d->hwirq;
-
-       switch (type) {
-       case IRQ_TYPE_EDGE_RISING:
-               __raw_writel(mask, pio + PIO_ESR);
-               __raw_writel(mask, pio + PIO_REHLSR);
-               break;
-       case IRQ_TYPE_EDGE_FALLING:
-               __raw_writel(mask, pio + PIO_ESR);
-               __raw_writel(mask, pio + PIO_FELLSR);
-               break;
-       case IRQ_TYPE_LEVEL_LOW:
-               __raw_writel(mask, pio + PIO_LSR);
-               __raw_writel(mask, pio + PIO_FELLSR);
-               break;
-       case IRQ_TYPE_LEVEL_HIGH:
-               __raw_writel(mask, pio + PIO_LSR);
-               __raw_writel(mask, pio + PIO_REHLSR);
-               break;
-       case IRQ_TYPE_EDGE_BOTH:
-               /*
-                * disable additional interrupt modes:
-                * fall back to default behavior
-                */
-               __raw_writel(mask, pio + PIO_AIMDR);
-               return 0;
-       case IRQ_TYPE_NONE:
-       default:
-               pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq));
-               return -EINVAL;
-       }
-
-       /* enable additional interrupt modes */
-       __raw_writel(mask, pio + PIO_AIMER);
-
-       return 0;
-}
-
-static struct irq_chip gpio_irqchip = {
-       .name           = "GPIO",
-       .irq_disable    = gpio_irq_mask,
-       .irq_mask       = gpio_irq_mask,
-       .irq_unmask     = gpio_irq_unmask,
-       /* .irq_set_type is set dynamically */
-       .irq_set_wake   = gpio_irq_set_wake,
-};
-
-static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct irq_data *idata = irq_desc_get_irq_data(desc);
-       struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
-       void __iomem    *pio = at91_gpio->regbase;
-       unsigned long   isr;
-       int             n;
-
-       chained_irq_enter(chip, desc);
-       for (;;) {
-               /* Reading ISR acks pending (edge triggered) GPIO interrupts.
-                * When there none are pending, we're finished unless we need
-                * to process multiple banks (like ID_PIOCDE on sam9263).
-                */
-               isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
-               if (!isr) {
-                       if (!at91_gpio->next)
-                               break;
-                       at91_gpio = at91_gpio->next;
-                       pio = at91_gpio->regbase;
-                       continue;
-               }
-
-               n = find_first_bit(&isr, BITS_PER_LONG);
-               while (n < BITS_PER_LONG) {
-                       generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
-                       n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
-               }
-       }
-       chained_irq_exit(chip, desc);
-       /* now it may re-trigger */
-}
-
-/*--------------------------------------------------------------------------*/
-
-#ifdef CONFIG_DEBUG_FS
-
-static void gpio_printf(struct seq_file *s, void __iomem *pio, unsigned mask)
-{
-       char    *trigger = NULL;
-       char    *polarity = NULL;
-
-       if (__raw_readl(pio + PIO_IMR) & mask) {
-               if (!has_pio3() || !(__raw_readl(pio + PIO_AIMMR) & mask )) {
-                       trigger = "edge";
-                       polarity = "both";
-               } else {
-                       if (__raw_readl(pio + PIO_ELSR) & mask) {
-                               trigger = "level";
-                               polarity = __raw_readl(pio + PIO_FRLHSR) & mask ?
-                                       "high" : "low";
-                       } else {
-                               trigger = "edge";
-                               polarity = __raw_readl(pio + PIO_FRLHSR) & mask ?
-                                               "rising" : "falling";
-                       }
-               }
-               seq_printf(s, "IRQ:%s-%s\t", trigger, polarity);
-       } else {
-               seq_printf(s, "GPIO:%s\t\t",
-                               __raw_readl(pio + PIO_PDSR) & mask ? "1" : "0");
-       }
-}
-
-static int at91_gpio_show(struct seq_file *s, void *unused)
-{
-       int bank, j;
-
-       /* print heading */
-       seq_printf(s, "Pin\t");
-       for (bank = 0; bank < gpio_banks; bank++) {
-               seq_printf(s, "PIO%c\t\t", 'A' + bank);
-       };
-       seq_printf(s, "\n\n");
-
-       /* print pin status */
-       for (j = 0; j < 32; j++) {
-               seq_printf(s, "%i:\t", j);
-
-               for (bank = 0; bank < gpio_banks; bank++) {
-                       unsigned        pin  = (32 * bank) + j;
-                       void __iomem    *pio = pin_to_controller(pin);
-                       unsigned        mask = pin_to_mask(pin);
-
-                       if (__raw_readl(pio + PIO_PSR) & mask)
-                               gpio_printf(s, pio, mask);
-                       else
-                               seq_printf(s, "%c\t\t",
-                                               peripheral_function(pio, mask));
-               }
-
-               seq_printf(s, "\n");
-       }
-
-       return 0;
-}
-
-static int at91_gpio_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, at91_gpio_show, NULL);
-}
-
-static const struct file_operations at91_gpio_operations = {
-       .open           = at91_gpio_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init at91_gpio_debugfs_init(void)
-{
-       /* /sys/kernel/debug/at91_gpio */
-       (void) debugfs_create_file("at91_gpio", S_IFREG | S_IRUGO, NULL, NULL, &at91_gpio_operations);
-       return 0;
-}
-postcore_initcall(at91_gpio_debugfs_init);
-
-#endif
-
-/*--------------------------------------------------------------------------*/
-
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-/*
- * irqdomain initialization: pile up irqdomains on top of AIC range
- */
-static void __init at91_gpio_irqdomain(struct at91_gpio_chip *at91_gpio)
-{
-       int irq_base;
-
-       irq_base = irq_alloc_descs(-1, 0, at91_gpio->chip.ngpio, 0);
-       if (irq_base < 0)
-               panic("at91_gpio.%d: error %d: couldn't allocate IRQ numbers.\n",
-                       at91_gpio->pioc_idx, irq_base);
-       at91_gpio->domain = irq_domain_add_legacy(NULL, at91_gpio->chip.ngpio,
-                                                 irq_base, 0,
-                                                 &irq_domain_simple_ops, NULL);
-       if (!at91_gpio->domain)
-               panic("at91_gpio.%d: couldn't allocate irq domain.\n",
-                       at91_gpio->pioc_idx);
-}
-
-/*
- * Called from the processor-specific init to enable GPIO interrupt support.
- */
-void __init at91_gpio_irq_setup(void)
-{
-       unsigned                pioc;
-       int                     gpio_irqnbr = 0;
-       struct at91_gpio_chip   *this, *prev;
-
-       /* Setup proper .irq_set_type function */
-       if (has_pio3())
-               gpio_irqchip.irq_set_type = alt_gpio_irq_type;
-       else
-               gpio_irqchip.irq_set_type = gpio_irq_type;
-
-       for (pioc = 0, this = gpio_chip, prev = NULL;
-                       pioc++ < gpio_banks;
-                       prev = this, this++) {
-               int offset;
-
-               __raw_writel(~0, this->regbase + PIO_IDR);
-
-               /* setup irq domain for this GPIO controller */
-               at91_gpio_irqdomain(this);
-
-               for (offset = 0; offset < this->chip.ngpio; offset++) {
-                       unsigned int virq = irq_find_mapping(this->domain, offset);
-                       irq_set_lockdep_class(virq, &gpio_lock_class);
-
-                       /*
-                        * Can use the "simple" and not "edge" handler since it's
-                        * shorter, and the AIC handles interrupts sanely.
-                        */
-                       irq_set_chip_and_handler(virq, &gpio_irqchip,
-                                                handle_simple_irq);
-                       set_irq_flags(virq, IRQF_VALID);
-                       irq_set_chip_data(virq, this);
-
-                       gpio_irqnbr++;
-               }
-
-               /* The toplevel handler handles one bank of GPIOs, except
-                * on some SoC it can handles up to three...
-                * We only set up the handler for the first of the list.
-                */
-               if (prev && prev->next == this)
-                       continue;
-
-               this->pioc_virq = irq_create_mapping(NULL, this->pioc_hwirq);
-               irq_set_chip_data(this->pioc_virq, this);
-               irq_set_chained_handler(this->pioc_virq, gpio_irq_handler);
-       }
-       pr_info("AT91: %d gpio irqs in %d banks\n", gpio_irqnbr, gpio_banks);
-}
-
-/* gpiolib support */
-static int at91_gpiolib_request(struct gpio_chip *chip, unsigned offset)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       void __iomem *pio = at91_gpio->regbase;
-       unsigned mask = 1 << offset;
-
-       __raw_writel(mask, pio + PIO_PER);
-       return 0;
-}
-
-static int at91_gpiolib_get_direction(struct gpio_chip *chip, unsigned offset)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       void __iomem *pio = at91_gpio->regbase;
-       unsigned mask = 1 << offset;
-       u32 osr;
-
-       osr = __raw_readl(pio + PIO_OSR);
-       return !(osr & mask);
-}
-
-static int at91_gpiolib_direction_input(struct gpio_chip *chip,
-                                       unsigned offset)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       void __iomem *pio = at91_gpio->regbase;
-       unsigned mask = 1 << offset;
-
-       __raw_writel(mask, pio + PIO_ODR);
-       return 0;
-}
-
-static int at91_gpiolib_direction_output(struct gpio_chip *chip,
-                                        unsigned offset, int val)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       void __iomem *pio = at91_gpio->regbase;
-       unsigned mask = 1 << offset;
-
-       __raw_writel(mask, pio + (val ? PIO_SODR : PIO_CODR));
-       __raw_writel(mask, pio + PIO_OER);
-       return 0;
-}
-
-static int at91_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       void __iomem *pio = at91_gpio->regbase;
-       unsigned mask = 1 << offset;
-       u32 pdsr;
-
-       pdsr = __raw_readl(pio + PIO_PDSR);
-       return (pdsr & mask) != 0;
-}
-
-static void at91_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       void __iomem *pio = at91_gpio->regbase;
-       unsigned mask = 1 << offset;
-
-       __raw_writel(mask, pio + (val ? PIO_SODR : PIO_CODR));
-}
-
-static void at91_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-       int i;
-
-       for (i = 0; i < chip->ngpio; i++) {
-               unsigned pin = chip->base + i;
-               void __iomem *pio = pin_to_controller(pin);
-               unsigned mask = pin_to_mask(pin);
-               const char *gpio_label;
-
-               gpio_label = gpiochip_is_requested(chip, i);
-               if (gpio_label) {
-                       seq_printf(s, "[%s] GPIO%s%d: ",
-                                  gpio_label, chip->label, i);
-                       if (__raw_readl(pio + PIO_PSR) & mask)
-                               seq_printf(s, "[gpio] %s\n",
-                                          at91_get_gpio_value(pin) ?
-                                          "set" : "clear");
-                       else
-                               seq_printf(s, "[periph %c]\n",
-                                          peripheral_function(pio, mask));
-               }
-       }
-}
-
-static int at91_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
-       int virq;
-
-       if (offset < chip->ngpio)
-               virq = irq_create_mapping(at91_gpio->domain, offset);
-       else
-               virq = -ENXIO;
-
-       dev_dbg(chip->dev, "%s: request IRQ for GPIO %d, return %d\n",
-                               chip->label, offset + chip->base, virq);
-       return virq;
-}
-
-static int __init at91_gpio_setup_clk(int idx)
-{
-       struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
-
-       /* retreive PIO controller's clock */
-       at91_gpio->clock = clk_get_sys(NULL, at91_gpio->chip.label);
-       if (IS_ERR(at91_gpio->clock)) {
-               pr_err("at91_gpio.%d, failed to get clock, ignoring.\n", idx);
-               goto err;
-       }
-
-       if (clk_prepare(at91_gpio->clock))
-               goto clk_prep_err;
-
-       /* enable PIO controller's clock */
-       if (clk_enable(at91_gpio->clock)) {
-               pr_err("at91_gpio.%d, failed to enable clock, ignoring.\n", idx);
-               goto clk_err;
-       }
-
-       return 0;
-
-clk_err:
-       clk_unprepare(at91_gpio->clock);
-clk_prep_err:
-       clk_put(at91_gpio->clock);
-err:
-       return -EINVAL;
-}
-
-static void __init at91_gpio_init_one(int idx, u32 regbase, int pioc_hwirq)
-{
-       struct at91_gpio_chip *at91_gpio = &gpio_chip[idx];
-
-       at91_gpio->chip.base = idx * MAX_NB_GPIO_PER_BANK;
-       at91_gpio->pioc_hwirq = pioc_hwirq;
-       at91_gpio->pioc_idx = idx;
-
-       at91_gpio->regbase = ioremap(regbase, 512);
-       if (!at91_gpio->regbase) {
-               pr_err("at91_gpio.%d, failed to map registers, ignoring.\n", idx);
-               return;
-       }
-
-       if (at91_gpio_setup_clk(idx))
-               goto ioremap_err;
-
-       gpio_banks = max(gpio_banks, idx + 1);
-       return;
-
-ioremap_err:
-       iounmap(at91_gpio->regbase);
-}
-
-/*
- * Called from the processor-specific init to enable GPIO pin support.
- */
-void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
-{
-       unsigned i;
-       struct at91_gpio_chip *at91_gpio, *last = NULL;
-
-       BUG_ON(nr_banks > MAX_GPIO_BANKS);
-
-       if (of_have_populated_dt())
-               return;
-
-       for (i = 0; i < nr_banks; i++)
-               at91_gpio_init_one(i, data[i].regbase, data[i].id);
-
-       for (i = 0; i < gpio_banks; i++) {
-               at91_gpio = &gpio_chip[i];
-
-               /*
-                * GPIO controller are grouped on some SoC:
-                * PIOC, PIOD and PIOE can share the same IRQ line
-                */
-               if (last && last->pioc_hwirq == at91_gpio->pioc_hwirq)
-                       last->next = at91_gpio;
-               last = at91_gpio;
-
-               gpiochip_add(&at91_gpio->chip);
-       }
-}
diff --git a/arch/arm/mach-at91/gpio.h b/arch/arm/mach-at91/gpio.h
deleted file mode 100644 (file)
index eed465a..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/gpio.h
- *
- *  Copyright (C) 2005 HP Labs
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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_AT91RM9200_GPIO_H
-#define __ASM_ARCH_AT91RM9200_GPIO_H
-
-#include <linux/kernel.h>
-#include <asm/irq.h>
-
-#define MAX_GPIO_BANKS         5
-#define NR_BUILTIN_GPIO                (MAX_GPIO_BANKS * 32)
-
-/* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
-
-#define        AT91_PIN_PA0    (0x00 + 0)
-#define        AT91_PIN_PA1    (0x00 + 1)
-#define        AT91_PIN_PA2    (0x00 + 2)
-#define        AT91_PIN_PA3    (0x00 + 3)
-#define        AT91_PIN_PA4    (0x00 + 4)
-#define        AT91_PIN_PA5    (0x00 + 5)
-#define        AT91_PIN_PA6    (0x00 + 6)
-#define        AT91_PIN_PA7    (0x00 + 7)
-#define        AT91_PIN_PA8    (0x00 + 8)
-#define        AT91_PIN_PA9    (0x00 + 9)
-#define        AT91_PIN_PA10   (0x00 + 10)
-#define        AT91_PIN_PA11   (0x00 + 11)
-#define        AT91_PIN_PA12   (0x00 + 12)
-#define        AT91_PIN_PA13   (0x00 + 13)
-#define        AT91_PIN_PA14   (0x00 + 14)
-#define        AT91_PIN_PA15   (0x00 + 15)
-#define        AT91_PIN_PA16   (0x00 + 16)
-#define        AT91_PIN_PA17   (0x00 + 17)
-#define        AT91_PIN_PA18   (0x00 + 18)
-#define        AT91_PIN_PA19   (0x00 + 19)
-#define        AT91_PIN_PA20   (0x00 + 20)
-#define        AT91_PIN_PA21   (0x00 + 21)
-#define        AT91_PIN_PA22   (0x00 + 22)
-#define        AT91_PIN_PA23   (0x00 + 23)
-#define        AT91_PIN_PA24   (0x00 + 24)
-#define        AT91_PIN_PA25   (0x00 + 25)
-#define        AT91_PIN_PA26   (0x00 + 26)
-#define        AT91_PIN_PA27   (0x00 + 27)
-#define        AT91_PIN_PA28   (0x00 + 28)
-#define        AT91_PIN_PA29   (0x00 + 29)
-#define        AT91_PIN_PA30   (0x00 + 30)
-#define        AT91_PIN_PA31   (0x00 + 31)
-
-#define        AT91_PIN_PB0    (0x20 + 0)
-#define        AT91_PIN_PB1    (0x20 + 1)
-#define        AT91_PIN_PB2    (0x20 + 2)
-#define        AT91_PIN_PB3    (0x20 + 3)
-#define        AT91_PIN_PB4    (0x20 + 4)
-#define        AT91_PIN_PB5    (0x20 + 5)
-#define        AT91_PIN_PB6    (0x20 + 6)
-#define        AT91_PIN_PB7    (0x20 + 7)
-#define        AT91_PIN_PB8    (0x20 + 8)
-#define        AT91_PIN_PB9    (0x20 + 9)
-#define        AT91_PIN_PB10   (0x20 + 10)
-#define        AT91_PIN_PB11   (0x20 + 11)
-#define        AT91_PIN_PB12   (0x20 + 12)
-#define        AT91_PIN_PB13   (0x20 + 13)
-#define        AT91_PIN_PB14   (0x20 + 14)
-#define        AT91_PIN_PB15   (0x20 + 15)
-#define        AT91_PIN_PB16   (0x20 + 16)
-#define        AT91_PIN_PB17   (0x20 + 17)
-#define        AT91_PIN_PB18   (0x20 + 18)
-#define        AT91_PIN_PB19   (0x20 + 19)
-#define        AT91_PIN_PB20   (0x20 + 20)
-#define        AT91_PIN_PB21   (0x20 + 21)
-#define        AT91_PIN_PB22   (0x20 + 22)
-#define        AT91_PIN_PB23   (0x20 + 23)
-#define        AT91_PIN_PB24   (0x20 + 24)
-#define        AT91_PIN_PB25   (0x20 + 25)
-#define        AT91_PIN_PB26   (0x20 + 26)
-#define        AT91_PIN_PB27   (0x20 + 27)
-#define        AT91_PIN_PB28   (0x20 + 28)
-#define        AT91_PIN_PB29   (0x20 + 29)
-#define        AT91_PIN_PB30   (0x20 + 30)
-#define        AT91_PIN_PB31   (0x20 + 31)
-
-#define        AT91_PIN_PC0    (0x40 + 0)
-#define        AT91_PIN_PC1    (0x40 + 1)
-#define        AT91_PIN_PC2    (0x40 + 2)
-#define        AT91_PIN_PC3    (0x40 + 3)
-#define        AT91_PIN_PC4    (0x40 + 4)
-#define        AT91_PIN_PC5    (0x40 + 5)
-#define        AT91_PIN_PC6    (0x40 + 6)
-#define        AT91_PIN_PC7    (0x40 + 7)
-#define        AT91_PIN_PC8    (0x40 + 8)
-#define        AT91_PIN_PC9    (0x40 + 9)
-#define        AT91_PIN_PC10   (0x40 + 10)
-#define        AT91_PIN_PC11   (0x40 + 11)
-#define        AT91_PIN_PC12   (0x40 + 12)
-#define        AT91_PIN_PC13   (0x40 + 13)
-#define        AT91_PIN_PC14   (0x40 + 14)
-#define        AT91_PIN_PC15   (0x40 + 15)
-#define        AT91_PIN_PC16   (0x40 + 16)
-#define        AT91_PIN_PC17   (0x40 + 17)
-#define        AT91_PIN_PC18   (0x40 + 18)
-#define        AT91_PIN_PC19   (0x40 + 19)
-#define        AT91_PIN_PC20   (0x40 + 20)
-#define        AT91_PIN_PC21   (0x40 + 21)
-#define        AT91_PIN_PC22   (0x40 + 22)
-#define        AT91_PIN_PC23   (0x40 + 23)
-#define        AT91_PIN_PC24   (0x40 + 24)
-#define        AT91_PIN_PC25   (0x40 + 25)
-#define        AT91_PIN_PC26   (0x40 + 26)
-#define        AT91_PIN_PC27   (0x40 + 27)
-#define        AT91_PIN_PC28   (0x40 + 28)
-#define        AT91_PIN_PC29   (0x40 + 29)
-#define        AT91_PIN_PC30   (0x40 + 30)
-#define        AT91_PIN_PC31   (0x40 + 31)
-
-#define        AT91_PIN_PD0    (0x60 + 0)
-#define        AT91_PIN_PD1    (0x60 + 1)
-#define        AT91_PIN_PD2    (0x60 + 2)
-#define        AT91_PIN_PD3    (0x60 + 3)
-#define        AT91_PIN_PD4    (0x60 + 4)
-#define        AT91_PIN_PD5    (0x60 + 5)
-#define        AT91_PIN_PD6    (0x60 + 6)
-#define        AT91_PIN_PD7    (0x60 + 7)
-#define        AT91_PIN_PD8    (0x60 + 8)
-#define        AT91_PIN_PD9    (0x60 + 9)
-#define        AT91_PIN_PD10   (0x60 + 10)
-#define        AT91_PIN_PD11   (0x60 + 11)
-#define        AT91_PIN_PD12   (0x60 + 12)
-#define        AT91_PIN_PD13   (0x60 + 13)
-#define        AT91_PIN_PD14   (0x60 + 14)
-#define        AT91_PIN_PD15   (0x60 + 15)
-#define        AT91_PIN_PD16   (0x60 + 16)
-#define        AT91_PIN_PD17   (0x60 + 17)
-#define        AT91_PIN_PD18   (0x60 + 18)
-#define        AT91_PIN_PD19   (0x60 + 19)
-#define        AT91_PIN_PD20   (0x60 + 20)
-#define        AT91_PIN_PD21   (0x60 + 21)
-#define        AT91_PIN_PD22   (0x60 + 22)
-#define        AT91_PIN_PD23   (0x60 + 23)
-#define        AT91_PIN_PD24   (0x60 + 24)
-#define        AT91_PIN_PD25   (0x60 + 25)
-#define        AT91_PIN_PD26   (0x60 + 26)
-#define        AT91_PIN_PD27   (0x60 + 27)
-#define        AT91_PIN_PD28   (0x60 + 28)
-#define        AT91_PIN_PD29   (0x60 + 29)
-#define        AT91_PIN_PD30   (0x60 + 30)
-#define        AT91_PIN_PD31   (0x60 + 31)
-
-#define        AT91_PIN_PE0    (0x80 + 0)
-#define        AT91_PIN_PE1    (0x80 + 1)
-#define        AT91_PIN_PE2    (0x80 + 2)
-#define        AT91_PIN_PE3    (0x80 + 3)
-#define        AT91_PIN_PE4    (0x80 + 4)
-#define        AT91_PIN_PE5    (0x80 + 5)
-#define        AT91_PIN_PE6    (0x80 + 6)
-#define        AT91_PIN_PE7    (0x80 + 7)
-#define        AT91_PIN_PE8    (0x80 + 8)
-#define        AT91_PIN_PE9    (0x80 + 9)
-#define        AT91_PIN_PE10   (0x80 + 10)
-#define        AT91_PIN_PE11   (0x80 + 11)
-#define        AT91_PIN_PE12   (0x80 + 12)
-#define        AT91_PIN_PE13   (0x80 + 13)
-#define        AT91_PIN_PE14   (0x80 + 14)
-#define        AT91_PIN_PE15   (0x80 + 15)
-#define        AT91_PIN_PE16   (0x80 + 16)
-#define        AT91_PIN_PE17   (0x80 + 17)
-#define        AT91_PIN_PE18   (0x80 + 18)
-#define        AT91_PIN_PE19   (0x80 + 19)
-#define        AT91_PIN_PE20   (0x80 + 20)
-#define        AT91_PIN_PE21   (0x80 + 21)
-#define        AT91_PIN_PE22   (0x80 + 22)
-#define        AT91_PIN_PE23   (0x80 + 23)
-#define        AT91_PIN_PE24   (0x80 + 24)
-#define        AT91_PIN_PE25   (0x80 + 25)
-#define        AT91_PIN_PE26   (0x80 + 26)
-#define        AT91_PIN_PE27   (0x80 + 27)
-#define        AT91_PIN_PE28   (0x80 + 28)
-#define        AT91_PIN_PE29   (0x80 + 29)
-#define        AT91_PIN_PE30   (0x80 + 30)
-#define        AT91_PIN_PE31   (0x80 + 31)
-
-#ifndef __ASSEMBLY__
-/* setup setup routines, called from board init or driver probe() */
-extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_C_periph(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_D_periph(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
-extern int __init_or_module at91_set_gpio_output(unsigned pin, int value);
-extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on);
-extern int __init_or_module at91_set_debounce(unsigned pin, int is_on, int div);
-extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on);
-extern int __init_or_module at91_set_pulldown(unsigned pin, int is_on);
-extern int __init_or_module at91_disable_schmitt_trig(unsigned pin);
-
-/* callable at any time */
-extern int at91_set_gpio_value(unsigned pin, int value);
-extern int at91_get_gpio_value(unsigned pin);
-
-/* callable only from core power-management code */
-extern void at91_gpio_suspend(void);
-extern void at91_gpio_resume(void);
-
-#endif /* __ASSEMBLY__ */
-
-#endif
diff --git a/arch/arm/mach-at91/gsia18s.h b/arch/arm/mach-at91/gsia18s.h
deleted file mode 100644 (file)
index 307c194..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Buttons */
-#define GPIO_TRIG_NET_IN               AT91_PIN_PB21
-#define GPIO_CARD_UNMOUNT_0            AT91_PIN_PB13
-#define GPIO_CARD_UNMOUNT_1            AT91_PIN_PB12
-#define GPIO_KEY_POWER                 AT91_PIN_PA25
-
-/* PCF8574 0x20 GPIO - U1 on the GS_IA18-CB_V3 board */
-#define GS_IA18_S_PCF_GPIO_BASE0       NR_BUILTIN_GPIO
-#define PCF_GPIO_HDC_POWER             (GS_IA18_S_PCF_GPIO_BASE0 + 0)
-#define PCF_GPIO_WIFI_SETUP            (GS_IA18_S_PCF_GPIO_BASE0 + 1)
-#define PCF_GPIO_WIFI_ENABLE           (GS_IA18_S_PCF_GPIO_BASE0 + 2)
-#define PCF_GPIO_WIFI_RESET            (GS_IA18_S_PCF_GPIO_BASE0 + 3)
-#define PCF_GPIO_ETH_DETECT            4 /* this is a GPI */
-#define PCF_GPIO_GPS_SETUP             (GS_IA18_S_PCF_GPIO_BASE0 + 5)
-#define PCF_GPIO_GPS_STANDBY           (GS_IA18_S_PCF_GPIO_BASE0 + 6)
-#define PCF_GPIO_GPS_POWER             (GS_IA18_S_PCF_GPIO_BASE0 + 7)
-
-/* PCF8574 0x22 GPIO - U1 on the GS_2G_OPT1-A_V0 board (Alarm) */
-#define GS_IA18_S_PCF_GPIO_BASE1       (GS_IA18_S_PCF_GPIO_BASE0 + 8)
-#define PCF_GPIO_ALARM1                        (GS_IA18_S_PCF_GPIO_BASE1 + 0)
-#define PCF_GPIO_ALARM2                        (GS_IA18_S_PCF_GPIO_BASE1 + 1)
-#define PCF_GPIO_ALARM3                        (GS_IA18_S_PCF_GPIO_BASE1 + 2)
-#define PCF_GPIO_ALARM4                        (GS_IA18_S_PCF_GPIO_BASE1 + 3)
-/* bits 4, 5, 6 not used */
-#define PCF_GPIO_ALARM_V_RELAY_ON      (GS_IA18_S_PCF_GPIO_BASE1 + 7)
-
-/* PCF8574 0x24 GPIO U1 on the GS_2G-OPT23-A_V0 board (Modem) */
-#define GS_IA18_S_PCF_GPIO_BASE2       (GS_IA18_S_PCF_GPIO_BASE1 + 8)
-#define PCF_GPIO_MODEM_POWER           (GS_IA18_S_PCF_GPIO_BASE2 + 0)
-#define PCF_GPIO_MODEM_RESET           (GS_IA18_S_PCF_GPIO_BASE2 + 3)
-/* bits 1, 2, 4, 5 not used */
-#define PCF_GPIO_TRX_RESET             (GS_IA18_S_PCF_GPIO_BASE2 + 6)
-/* bit 7 not used */
index 3b5948566e520555e53a3f5c888b58d9d3e17865..42925e8f78e4b2774724bd091019b0dd2909e648 100644 (file)
@@ -16,7 +16,6 @@
 #ifndef AT91_DBGU_H
 #define AT91_DBGU_H
 
-#if !defined(CONFIG_ARCH_AT91X40)
 #define AT91_DBGU_CR           (0x00)  /* Control Register */
 #define AT91_DBGU_MR           (0x04)  /* Mode Register */
 #define AT91_DBGU_IER          (0x08)  /* Interrupt Enable Register */
@@ -34,8 +33,6 @@
 #define AT91_DBGU_FNR          (0x48)  /* Force NTRST Register [SAM9 only] */
 #define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
 
-#endif /* AT91_DBGU */
-
 /*
  * Some AT91 parts that don't have full DEBUG units still support the ID
  * and extensions register.
index d8aeb278614ebba4d51cebea15db71b2f3187cb2..e4492b151fee6b80b5bd9ec238d796e80437577a 100644 (file)
@@ -25,8 +25,8 @@ extern void __iomem *at91_ramc_base[];
 #define AT91_MEMCTRL_SDRAMC    1
 #define AT91_MEMCTRL_DDRSDR    2
 
-#include <mach/at91rm9200_sdramc.h>
-#include <mach/at91sam9_ddrsdr.h>
-#include <mach/at91sam9_sdramc.h>
+#include <soc/at91/at91rm9200_sdramc.h>
+#include <soc/at91/at91sam9_ddrsdr.h>
+#include <soc/at91/at91sam9_sdramc.h>
 
 #endif /* __AT91_RAMC_H__ */
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200_sdramc.h b/arch/arm/mach-at91/include/mach/at91rm9200_sdramc.h
deleted file mode 100644 (file)
index aa047f4..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91rm9200_sdramc.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Memory Controllers (SDRAMC only) - 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 AT91RM9200_SDRAMC_H
-#define AT91RM9200_SDRAMC_H
-
-/* SDRAM Controller registers */
-#define AT91RM9200_SDRAMC_MR           0x90                    /* Mode Register */
-#define                AT91RM9200_SDRAMC_MODE  (0xf << 0)              /* Command Mode */
-#define                        AT91RM9200_SDRAMC_MODE_NORMAL           (0 << 0)
-#define                        AT91RM9200_SDRAMC_MODE_NOP              (1 << 0)
-#define                        AT91RM9200_SDRAMC_MODE_PRECHARGE        (2 << 0)
-#define                        AT91RM9200_SDRAMC_MODE_LMR              (3 << 0)
-#define                        AT91RM9200_SDRAMC_MODE_REFRESH  (4 << 0)
-#define                AT91RM9200_SDRAMC_DBW           (1   << 4)              /* Data Bus Width */
-#define                        AT91RM9200_SDRAMC_DBW_32        (0 << 4)
-#define                        AT91RM9200_SDRAMC_DBW_16        (1 << 4)
-
-#define AT91RM9200_SDRAMC_TR           0x94                    /* Refresh Timer Register */
-#define                AT91RM9200_SDRAMC_COUNT (0xfff << 0)            /* Refresh Timer Count */
-
-#define AT91RM9200_SDRAMC_CR           0x98                    /* Configuration Register */
-#define                AT91RM9200_SDRAMC_NC            (3   <<  0)             /* Number of Column Bits */
-#define                        AT91RM9200_SDRAMC_NC_8  (0 << 0)
-#define                        AT91RM9200_SDRAMC_NC_9  (1 << 0)
-#define                        AT91RM9200_SDRAMC_NC_10 (2 << 0)
-#define                        AT91RM9200_SDRAMC_NC_11 (3 << 0)
-#define                AT91RM9200_SDRAMC_NR            (3   <<  2)             /* Number of Row Bits */
-#define                        AT91RM9200_SDRAMC_NR_11 (0 << 2)
-#define                        AT91RM9200_SDRAMC_NR_12 (1 << 2)
-#define                        AT91RM9200_SDRAMC_NR_13 (2 << 2)
-#define                AT91RM9200_SDRAMC_NB            (1   <<  4)             /* Number of Banks */
-#define                        AT91RM9200_SDRAMC_NB_2  (0 << 4)
-#define                        AT91RM9200_SDRAMC_NB_4  (1 << 4)
-#define                AT91RM9200_SDRAMC_CAS           (3   <<  5)             /* CAS Latency */
-#define                        AT91RM9200_SDRAMC_CAS_2 (2 << 5)
-#define                AT91RM9200_SDRAMC_TWR           (0xf <<  7)             /* Write Recovery Delay */
-#define                AT91RM9200_SDRAMC_TRC           (0xf << 11)             /* Row Cycle Delay */
-#define                AT91RM9200_SDRAMC_TRP           (0xf << 15)             /* Row Precharge Delay */
-#define                AT91RM9200_SDRAMC_TRCD  (0xf << 19)             /* Row to Column Delay */
-#define                AT91RM9200_SDRAMC_TRAS  (0xf << 23)             /* Active to Precharge Delay */
-#define                AT91RM9200_SDRAMC_TXSR  (0xf << 27)             /* Exit Self Refresh to Active Delay */
-
-#define AT91RM9200_SDRAMC_SRR          0x9c                    /* Self Refresh Register */
-#define AT91RM9200_SDRAMC_LPR          0xa0                    /* Low Power Register */
-#define AT91RM9200_SDRAMC_IER          0xa4                    /* Interrupt Enable Register */
-#define AT91RM9200_SDRAMC_IDR          0xa8                    /* Interrupt Disable Register */
-#define AT91RM9200_SDRAMC_IMR          0xac                    /* Interrupt Mask Register */
-#define AT91RM9200_SDRAMC_ISR          0xb0                    /* Interrupt Status Register */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h
deleted file mode 100644 (file)
index 0210797..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Header file for the Atmel DDR/SDR SDRAM Controller
- *
- * Copyright (C) 2010 Atmel Corporation
- *     Nicolas Ferre <nicolas.ferre@atmel.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 AT91SAM9_DDRSDR_H
-#define AT91SAM9_DDRSDR_H
-
-#define AT91_DDRSDRC_MR                0x00    /* Mode Register */
-#define                AT91_DDRSDRC_MODE       (0x7 << 0)              /* Command Mode */
-#define                        AT91_DDRSDRC_MODE_NORMAL        0
-#define                        AT91_DDRSDRC_MODE_NOP           1
-#define                        AT91_DDRSDRC_MODE_PRECHARGE     2
-#define                        AT91_DDRSDRC_MODE_LMR           3
-#define                        AT91_DDRSDRC_MODE_REFRESH       4
-#define                        AT91_DDRSDRC_MODE_EXT_LMR       5
-#define                        AT91_DDRSDRC_MODE_DEEP          6
-
-#define AT91_DDRSDRC_RTR       0x04    /* Refresh Timer Register */
-#define                AT91_DDRSDRC_COUNT      (0xfff << 0)            /* Refresh Timer Counter */
-
-#define AT91_DDRSDRC_CR                0x08    /* Configuration Register */
-#define                AT91_DDRSDRC_NC         (3 << 0)                /* Number of Column Bits */
-#define                        AT91_DDRSDRC_NC_SDR8    (0 << 0)
-#define                        AT91_DDRSDRC_NC_SDR9    (1 << 0)
-#define                        AT91_DDRSDRC_NC_SDR10   (2 << 0)
-#define                        AT91_DDRSDRC_NC_SDR11   (3 << 0)
-#define                        AT91_DDRSDRC_NC_DDR9    (0 << 0)
-#define                        AT91_DDRSDRC_NC_DDR10   (1 << 0)
-#define                        AT91_DDRSDRC_NC_DDR11   (2 << 0)
-#define                        AT91_DDRSDRC_NC_DDR12   (3 << 0)
-#define                AT91_DDRSDRC_NR         (3 << 2)                /* Number of Row Bits */
-#define                        AT91_DDRSDRC_NR_11      (0 << 2)
-#define                        AT91_DDRSDRC_NR_12      (1 << 2)
-#define                        AT91_DDRSDRC_NR_13      (2 << 2)
-#define                        AT91_DDRSDRC_NR_14      (3 << 2)
-#define                AT91_DDRSDRC_CAS        (7 << 4)                /* CAS Latency */
-#define                        AT91_DDRSDRC_CAS_2      (2 << 4)
-#define                        AT91_DDRSDRC_CAS_3      (3 << 4)
-#define                        AT91_DDRSDRC_CAS_25     (6 << 4)
-#define                AT91_DDRSDRC_RST_DLL    (1 << 7)                /* Reset DLL */
-#define                AT91_DDRSDRC_DICDS      (1 << 8)                /* Output impedance control */
-#define                AT91_DDRSDRC_DIS_DLL    (1 << 9)                /* Disable DLL [SAM9 Only] */
-#define                AT91_DDRSDRC_OCD        (1 << 12)               /* Off-Chip Driver [SAM9 Only] */
-#define                AT91_DDRSDRC_DQMS       (1 << 16)               /* Mask Data is Shared [SAM9 Only] */
-#define                AT91_DDRSDRC_ACTBST     (1 << 18)               /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */
-
-#define AT91_DDRSDRC_T0PR      0x0C    /* Timing 0 Register */
-#define                AT91_DDRSDRC_TRAS       (0xf <<  0)             /* Active to Precharge delay */
-#define                AT91_DDRSDRC_TRCD       (0xf <<  4)             /* Row to Column delay */
-#define                AT91_DDRSDRC_TWR        (0xf <<  8)             /* Write recovery delay */
-#define                AT91_DDRSDRC_TRC        (0xf << 12)             /* Row cycle delay */
-#define                AT91_DDRSDRC_TRP        (0xf << 16)             /* Row precharge delay */
-#define                AT91_DDRSDRC_TRRD       (0xf << 20)             /* Active BankA to BankB */
-#define                AT91_DDRSDRC_TWTR       (0x7 << 24)             /* Internal Write to Read delay */
-#define                AT91_DDRSDRC_RED_WRRD   (0x1 << 27)             /* Reduce Write to Read Delay [SAM9 Only] */
-#define                AT91_DDRSDRC_TMRD       (0xf << 28)             /* Load mode to active/refresh delay */
-
-#define AT91_DDRSDRC_T1PR      0x10    /* Timing 1 Register */
-#define                AT91_DDRSDRC_TRFC       (0x1f << 0)             /* Row Cycle Delay */
-#define                AT91_DDRSDRC_TXSNR      (0xff << 8)             /* Exit self-refresh to non-read */
-#define                AT91_DDRSDRC_TXSRD      (0xff << 16)            /* Exit self-refresh to read */
-#define                AT91_DDRSDRC_TXP        (0xf  << 24)            /* Exit power-down delay */
-
-#define AT91_DDRSDRC_T2PR      0x14    /* Timing 2 Register [SAM9 Only] */
-#define                AT91_DDRSDRC_TXARD      (0xf  << 0)             /* Exit active power down delay to read command in mode "Fast Exit" */
-#define                AT91_DDRSDRC_TXARDS     (0xf  << 4)             /* Exit active power down delay to read command in mode "Slow Exit" */
-#define                AT91_DDRSDRC_TRPA       (0xf  << 8)             /* Row Precharge All delay */
-#define                AT91_DDRSDRC_TRTP       (0x7  << 12)            /* Read to Precharge delay */
-
-#define AT91_DDRSDRC_LPR       0x1C    /* Low Power Register */
-#define                AT91_DDRSDRC_LPCB       (3 << 0)                /* Low-power Configurations */
-#define                        AT91_DDRSDRC_LPCB_DISABLE               0
-#define                        AT91_DDRSDRC_LPCB_SELF_REFRESH          1
-#define                        AT91_DDRSDRC_LPCB_POWER_DOWN            2
-#define                        AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN       3
-#define                AT91_DDRSDRC_CLKFR      (1 << 2)        /* Clock Frozen */
-#define                AT91_DDRSDRC_PASR       (7 << 4)        /* Partial Array Self Refresh */
-#define                AT91_DDRSDRC_TCSR       (3 << 8)        /* Temperature Compensated Self Refresh */
-#define                AT91_DDRSDRC_DS         (3 << 10)       /* Drive Strength */
-#define                AT91_DDRSDRC_TIMEOUT    (3 << 12)       /* Time to define when Low Power Mode is enabled */
-#define                        AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES       (0 << 12)
-#define                        AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES      (1 << 12)
-#define                        AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES     (2 << 12)
-#define                AT91_DDRSDRC_APDE       (1 << 16)        /* Active power down exit time */
-#define                AT91_DDRSDRC_UPD_MR     (3 << 20)        /* Update load mode register and extended mode register */
-
-#define AT91_DDRSDRC_MDR       0x20    /* Memory Device Register */
-#define                AT91_DDRSDRC_MD         (3 << 0)                /* Memory Device Type */
-#define                        AT91_DDRSDRC_MD_SDR             0
-#define                        AT91_DDRSDRC_MD_LOW_POWER_SDR   1
-#define                        AT91_DDRSDRC_MD_LOW_POWER_DDR   3
-#define                        AT91_DDRSDRC_MD_DDR2            6       /* [SAM9 Only] */
-#define                AT91_DDRSDRC_DBW        (1 << 4)                /* Data Bus Width */
-#define                        AT91_DDRSDRC_DBW_32BITS         (0 <<  4)
-#define                        AT91_DDRSDRC_DBW_16BITS         (1 <<  4)
-
-#define AT91_DDRSDRC_DLL       0x24    /* DLL Information Register */
-#define                AT91_DDRSDRC_MDINC      (1 << 0)                /* Master Delay increment */
-#define                AT91_DDRSDRC_MDDEC      (1 << 1)                /* Master Delay decrement */
-#define                AT91_DDRSDRC_MDOVF      (1 << 2)                /* Master Delay Overflow */
-#define                AT91_DDRSDRC_MDVAL      (0xff <<  8)            /* Master Delay value */
-
-#define AT91_DDRSDRC_HS                0x2C    /* High Speed Register [SAM9 Only] */
-#define                AT91_DDRSDRC_DIS_ATCP_RD        (1 << 2)        /* Anticip read access is disabled */
-
-#define AT91_DDRSDRC_DELAY(n)  (0x30 + (0x4 * (n)))    /* Delay I/O Register n */
-
-#define AT91_DDRSDRC_WPMR      0xE4    /* Write Protect Mode Register [SAM9 Only] */
-#define                AT91_DDRSDRC_WP         (1 << 0)                /* Write protect enable */
-#define                AT91_DDRSDRC_WPKEY      (0xffffff << 8)         /* Write protect key */
-#define                AT91_DDRSDRC_KEY        (0x444452 << 8)         /* Write protect key = "DDR" */
-
-#define AT91_DDRSDRC_WPSR      0xE8    /* Write Protect Status Register [SAM9 Only] */
-#define                AT91_DDRSDRC_WPVS       (1 << 0)                /* Write protect violation status */
-#define                AT91_DDRSDRC_WPVSRC     (0xffff << 8)           /* Write protect violation source */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9_sdramc.h b/arch/arm/mach-at91/include/mach/at91sam9_sdramc.h
deleted file mode 100644 (file)
index 3d085a9..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9_sdramc.h
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 Atmel Corporation.
- *
- * SDRAM Controllers (SDRAMC) - 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 AT91SAM9_SDRAMC_H
-#define AT91SAM9_SDRAMC_H
-
-/* SDRAM Controller (SDRAMC) registers */
-#define AT91_SDRAMC_MR         0x00    /* SDRAM Controller Mode Register */
-#define                AT91_SDRAMC_MODE        (0xf << 0)              /* Command Mode */
-#define                        AT91_SDRAMC_MODE_NORMAL         0
-#define                        AT91_SDRAMC_MODE_NOP            1
-#define                        AT91_SDRAMC_MODE_PRECHARGE      2
-#define                        AT91_SDRAMC_MODE_LMR            3
-#define                        AT91_SDRAMC_MODE_REFRESH        4
-#define                        AT91_SDRAMC_MODE_EXT_LMR        5
-#define                        AT91_SDRAMC_MODE_DEEP           6
-
-#define AT91_SDRAMC_TR         0x04    /* SDRAM Controller Refresh Timer Register */
-#define                AT91_SDRAMC_COUNT       (0xfff << 0)            /* Refresh Timer Counter */
-
-#define AT91_SDRAMC_CR         0x08    /* SDRAM Controller Configuration Register */
-#define                AT91_SDRAMC_NC          (3 << 0)                /* Number of Column Bits */
-#define                        AT91_SDRAMC_NC_8        (0 << 0)
-#define                        AT91_SDRAMC_NC_9        (1 << 0)
-#define                        AT91_SDRAMC_NC_10       (2 << 0)
-#define                        AT91_SDRAMC_NC_11       (3 << 0)
-#define                AT91_SDRAMC_NR          (3 << 2)                /* Number of Row Bits */
-#define                        AT91_SDRAMC_NR_11       (0 << 2)
-#define                        AT91_SDRAMC_NR_12       (1 << 2)
-#define                        AT91_SDRAMC_NR_13       (2 << 2)
-#define                AT91_SDRAMC_NB          (1 << 4)                /* Number of Banks */
-#define                        AT91_SDRAMC_NB_2        (0 << 4)
-#define                        AT91_SDRAMC_NB_4        (1 << 4)
-#define                AT91_SDRAMC_CAS         (3 << 5)                /* CAS Latency */
-#define                        AT91_SDRAMC_CAS_1       (1 << 5)
-#define                        AT91_SDRAMC_CAS_2       (2 << 5)
-#define                        AT91_SDRAMC_CAS_3       (3 << 5)
-#define                AT91_SDRAMC_DBW         (1 << 7)                /* Data Bus Width */
-#define                        AT91_SDRAMC_DBW_32      (0 << 7)
-#define                        AT91_SDRAMC_DBW_16      (1 << 7)
-#define                AT91_SDRAMC_TWR         (0xf <<  8)             /* Write Recovery Delay */
-#define                AT91_SDRAMC_TRC         (0xf << 12)             /* Row Cycle Delay */
-#define                AT91_SDRAMC_TRP         (0xf << 16)             /* Row Precharge Delay */
-#define                AT91_SDRAMC_TRCD        (0xf << 20)             /* Row to Column Delay */
-#define                AT91_SDRAMC_TRAS        (0xf << 24)             /* Active to Precharge Delay */
-#define                AT91_SDRAMC_TXSR        (0xf << 28)             /* Exit Self Refresh to Active Delay */
-
-#define AT91_SDRAMC_LPR                0x10    /* SDRAM Controller Low Power Register */
-#define                AT91_SDRAMC_LPCB                (3 << 0)        /* Low-power Configurations */
-#define                        AT91_SDRAMC_LPCB_DISABLE                0
-#define                        AT91_SDRAMC_LPCB_SELF_REFRESH           1
-#define                        AT91_SDRAMC_LPCB_POWER_DOWN             2
-#define                        AT91_SDRAMC_LPCB_DEEP_POWER_DOWN        3
-#define                AT91_SDRAMC_PASR                (7 << 4)        /* Partial Array Self Refresh */
-#define                AT91_SDRAMC_TCSR                (3 << 8)        /* Temperature Compensated Self Refresh */
-#define                AT91_SDRAMC_DS                  (3 << 10)       /* Drive Strength */
-#define                AT91_SDRAMC_TIMEOUT             (3 << 12)       /* Time to define when Low Power Mode is enabled */
-#define                        AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES        (0 << 12)
-#define                        AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES       (1 << 12)
-#define                        AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES      (2 << 12)
-
-#define AT91_SDRAMC_IER                0x14    /* SDRAM Controller Interrupt Enable Register */
-#define AT91_SDRAMC_IDR                0x18    /* SDRAM Controller Interrupt Disable Register */
-#define AT91_SDRAMC_IMR                0x1C    /* SDRAM Controller Interrupt Mask Register */
-#define AT91_SDRAMC_ISR                0x20    /* SDRAM Controller Interrupt Status Register */
-#define                AT91_SDRAMC_RES         (1 << 0)                /* Refresh Error Status */
-
-#define AT91_SDRAMC_MDR                0x24    /* SDRAM Memory Device Register */
-#define                AT91_SDRAMC_MD          (3 << 0)                /* Memory Device Type */
-#define                        AT91_SDRAMC_MD_SDRAM            0
-#define                        AT91_SDRAMC_MD_LOW_POWER_SDRAM  1
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91x40.h b/arch/arm/mach-at91/include/mach/at91x40.h
deleted file mode 100644 (file)
index 38dca2b..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91x40.h
- *
- * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.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 AT91X40_H
-#define AT91X40_H
-
-/*
- *     IRQ list.
- */
-#define AT91X40_ID_USART0      2       /* USART port 0 */
-#define AT91X40_ID_USART1      3       /* USART port 1 */
-#define AT91X40_ID_TC0         4       /* Timer/Counter 0 */
-#define AT91X40_ID_TC1         5       /* Timer/Counter 1*/
-#define AT91X40_ID_TC2         6       /* Timer/Counter 2*/
-#define AT91X40_ID_WD          7       /* Watchdog? */
-#define AT91X40_ID_PIOA                8       /* Parallel IO Controller A */
-
-#define AT91X40_ID_IRQ0                16      /* External IRQ 0 */
-#define AT91X40_ID_IRQ1                17      /* External IRQ 1 */
-#define AT91X40_ID_IRQ2                18      /* External IRQ 2 */
-
-/*
- * System Peripherals
- */
-#define AT91_BASE_SYS  0xffc00000
-
-#define AT91_EBI       0xffe00000      /* External Bus Interface */
-#define AT91_SF                0xfff00000      /* Special Function */
-#define AT91_USART1    0xfffcc000      /* USART 1 */
-#define AT91_USART0    0xfffd0000      /* USART 0 */
-#define AT91_TC                0xfffe0000      /* Timer Counter */
-#define AT91_PIOA      0xffff0000      /* PIO Controller A */
-#define AT91_PS                0xffff4000      /* Power Save */
-#define AT91_WD                0xffff8000      /* Watchdog Timer */
-
-/*
- * The AT91x40 series doesn't have a debug unit like the other AT91 parts.
- * But it does have a chip identify register and extension ID, so define at
- * least these here.
- */
-#define AT91_DBGU_CIDR (AT91_SF + 0)   /* CIDR in PS segment */
-#define AT91_DBGU_EXID (AT91_SF + 4)   /* EXID in PS segment */
-
-/*
- * Support defines for the simple Power Controller module.
- */
-#define        AT91_PS_CR      (AT91_PS + 0)   /* PS Control register */
-#define        AT91_PS_CR_CPU  (1 << 0)        /* CPU clock disable bit */
-
-#define AT91X40_MASTER_CLOCK   40000000
-
-#endif /* AT91X40_H */
diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h
deleted file mode 100644 (file)
index 3069e41..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __MACH_ATMEL_MCI_H
-#define __MACH_ATMEL_MCI_H
-
-#include <linux/platform_data/dma-atmel.h>
-
-/**
- * struct mci_dma_data - DMA data for MCI interface
- */
-struct mci_dma_data {
-       struct at_dma_slave     sdata;
-};
-
-/* accessor macros */
-#define        slave_data_ptr(s)       (&(s)->sdata)
-#define find_slave_dev(s)      ((s)->sdata.dma_dev)
-
-#endif /* __MACH_ATMEL_MCI_H */
index b27e9ca656538e5d623adf7941ba8839a9ae3394..61914fb35f5d90ff740db6d4e50bbb145615ce98 100644 (file)
@@ -62,7 +62,6 @@
 #define ARCH_EXID_SAMA5D43     0x00000003
 #define ARCH_EXID_SAMA5D44     0x00000004
 
-#define ARCH_FAMILY_AT91X92    0x09200000
 #define ARCH_FAMILY_AT91SAM9   0x01900000
 #define ARCH_FAMILY_AT91SAM9XE 0x02900000
 
index c13797352688de22f63f9a0cef94fdaaf409af46..cacbaa52418f6b17af3b2a1824fcf732871e0c49 100644 (file)
@@ -24,9 +24,6 @@
 /* sama5d4 */
 #define AT91_BASE_DBGU2        0xfc069000
 
-#if defined(CONFIG_ARCH_AT91X40)
-#include <mach/at91x40.h>
-#else
 #include <mach/at91rm9200.h>
 #include <mach/at91sam9260.h>
 #include <mach/at91sam9261.h>
@@ -51,8 +48,6 @@
  */
 #define AT91_BASE_SYS  0xffffc000
 
-#endif
-
 /*
  * On sama5d4 there is no system controller, we map some needed peripherals
  */
  * called as part of the generic suspend/resume path.
  */
 #ifndef __ASSEMBLY__
-#ifdef CONFIG_PINCTRL_AT91
 extern void at91_pinctrl_gpio_suspend(void);
 extern void at91_pinctrl_gpio_resume(void);
-#else
-static inline void at91_pinctrl_gpio_suspend(void) {}
-static inline void at91_pinctrl_gpio_resume(void) {}
-#endif
 #endif
 
 #endif
index acb2d890ad7e1ec58d79caaa1db576a8681a947f..4ebb609369e36895e0da7e68021eb6cbc962532e 100644 (file)
@@ -31,7 +31,6 @@
 
 void __iomem *at91_uart;
 
-#if !defined(CONFIG_ARCH_AT91X40)
 static const u32 uarts_rm9200[] = {
        AT91_BASE_DBGU0,
        AT91RM9200_BASE_US0,
@@ -188,12 +187,6 @@ static inline void arch_decomp_setup(void)
 
        at91_uart = NULL;
 }
-#else
-static inline void arch_decomp_setup(void)
-{
-       at91_uart = NULL;
-}
-#endif
 
 /*
  * The following code assumes the serial port has already been
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
deleted file mode 100644 (file)
index cdb3ec9..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/irq.c
- *
- *  Copyright (C) 2004 SAN People
- *  Copyright (C) 2004 ATMEL
- *  Copyright (C) Rick Bronson
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/bitmap.h>
-#include <linux/types.h>
-#include <linux/irq.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/irqdomain.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/setup.h>
-
-#include <asm/exception.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-
-#include "at91_aic.h"
-
-void __iomem *at91_aic_base;
-static struct irq_domain *at91_aic_domain;
-static struct device_node *at91_aic_np;
-static unsigned int n_irqs = NR_AIC_IRQS;
-
-#ifdef CONFIG_PM
-
-static unsigned long *wakeups;
-static unsigned long *backups;
-
-#define set_backup(bit) set_bit(bit, backups)
-#define clear_backup(bit) clear_bit(bit, backups)
-
-static int at91_aic_pm_init(void)
-{
-       backups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
-       if (!backups)
-               return -ENOMEM;
-
-       wakeups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
-       if (!wakeups) {
-               kfree(backups);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int at91_aic_set_wake(struct irq_data *d, unsigned value)
-{
-       if (unlikely(d->hwirq >= n_irqs))
-               return -EINVAL;
-
-       if (value)
-               set_bit(d->hwirq, wakeups);
-       else
-               clear_bit(d->hwirq, wakeups);
-
-       return 0;
-}
-
-void at91_irq_suspend(void)
-{
-       at91_aic_write(AT91_AIC_IDCR, *backups);
-       at91_aic_write(AT91_AIC_IECR, *wakeups);
-}
-
-void at91_irq_resume(void)
-{
-       at91_aic_write(AT91_AIC_IDCR, *wakeups);
-       at91_aic_write(AT91_AIC_IECR, *backups);
-}
-
-#else
-static inline int at91_aic_pm_init(void)
-{
-       return 0;
-}
-
-#define set_backup(bit)
-#define clear_backup(bit)
-#define at91_aic_set_wake      NULL
-
-#endif /* CONFIG_PM */
-
-asmlinkage void __exception_irq_entry
-at91_aic_handle_irq(struct pt_regs *regs)
-{
-       u32 irqnr;
-       u32 irqstat;
-
-       irqnr = at91_aic_read(AT91_AIC_IVR);
-       irqstat = at91_aic_read(AT91_AIC_ISR);
-
-       /*
-        * ISR value is 0 when there is no current interrupt or when there is
-        * a spurious interrupt
-        */
-       if (!irqstat)
-               at91_aic_write(AT91_AIC_EOICR, 0);
-       else
-               handle_IRQ(irqnr, regs);
-}
-
-static void at91_aic_mask_irq(struct irq_data *d)
-{
-       /* Disable interrupt on AIC */
-       at91_aic_write(AT91_AIC_IDCR, 1 << d->hwirq);
-       /* Update ISR cache */
-       clear_backup(d->hwirq);
-}
-
-static void at91_aic_unmask_irq(struct irq_data *d)
-{
-       /* Enable interrupt on AIC */
-       at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
-       /* Update ISR cache */
-       set_backup(d->hwirq);
-}
-
-static void at91_aic_eoi(struct irq_data *d)
-{
-       /*
-        * Mark end-of-interrupt on AIC, the controller doesn't care about
-        * the value written. Moreover it's a write-only register.
-        */
-       at91_aic_write(AT91_AIC_EOICR, 0);
-}
-
-static unsigned long *at91_extern_irq;
-
-u32 at91_get_extern_irq(void)
-{
-       if (!at91_extern_irq)
-               return 0;
-       return *at91_extern_irq;
-}
-
-#define is_extern_irq(hwirq) test_bit(hwirq, at91_extern_irq)
-
-static int at91_aic_compute_srctype(struct irq_data *d, unsigned type)
-{
-       int srctype;
-
-       switch (type) {
-       case IRQ_TYPE_LEVEL_HIGH:
-               srctype = AT91_AIC_SRCTYPE_HIGH;
-               break;
-       case IRQ_TYPE_EDGE_RISING:
-               srctype = AT91_AIC_SRCTYPE_RISING;
-               break;
-       case IRQ_TYPE_LEVEL_LOW:
-               if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq))               /* only supported on external interrupts */
-                       srctype = AT91_AIC_SRCTYPE_LOW;
-               else
-                       srctype = -EINVAL;
-               break;
-       case IRQ_TYPE_EDGE_FALLING:
-               if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq))               /* only supported on external interrupts */
-                       srctype = AT91_AIC_SRCTYPE_FALLING;
-               else
-                       srctype = -EINVAL;
-               break;
-       default:
-               srctype = -EINVAL;
-       }
-
-       return srctype;
-}
-
-static int at91_aic_set_type(struct irq_data *d, unsigned type)
-{
-       unsigned int smr;
-       int srctype;
-
-       srctype = at91_aic_compute_srctype(d, type);
-       if (srctype < 0)
-               return srctype;
-
-       smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE;
-       at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
-
-       return 0;
-}
-
-static struct irq_chip at91_aic_chip = {
-       .name           = "AIC",
-       .irq_mask       = at91_aic_mask_irq,
-       .irq_unmask     = at91_aic_unmask_irq,
-       .irq_set_type   = at91_aic_set_type,
-       .irq_set_wake   = at91_aic_set_wake,
-       .irq_eoi        = at91_aic_eoi,
-};
-
-static void __init at91_aic_hw_init(unsigned int spu_vector)
-{
-       int i;
-
-       /*
-        * Perform 8 End Of Interrupt Command to make sure AIC
-        * will not Lock out nIRQ
-        */
-       for (i = 0; i < 8; i++)
-               at91_aic_write(AT91_AIC_EOICR, 0);
-
-       /*
-        * Spurious Interrupt ID in Spurious Vector Register.
-        * When there is no current interrupt, the IRQ Vector Register
-        * reads the value stored in AIC_SPU
-        */
-       at91_aic_write(AT91_AIC_SPU, spu_vector);
-
-       /* No debugging in AIC: Debug (Protect) Control Register */
-       at91_aic_write(AT91_AIC_DCR, 0);
-
-       /* Disable and clear all interrupts initially */
-       at91_aic_write(AT91_AIC_IDCR, 0xFFFFFFFF);
-       at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
-}
-
-/*
- * Initialize the AIC interrupt controller.
- */
-void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)
-{
-       unsigned int i;
-       int irq_base;
-
-       at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
-                                 * sizeof(*at91_extern_irq), GFP_KERNEL);
-
-       if (at91_aic_pm_init() || at91_extern_irq == NULL)
-               panic("Unable to allocate bit maps\n");
-
-       *at91_extern_irq = ext_irq_mask;
-
-       at91_aic_base = ioremap(AT91_AIC, 512);
-       if (!at91_aic_base)
-               panic("Unable to ioremap AIC registers\n");
-
-       /* Add irq domain for AIC */
-       irq_base = irq_alloc_descs(-1, 0, n_irqs, 0);
-       if (irq_base < 0) {
-               WARN(1, "Cannot allocate irq_descs, assuming pre-allocated\n");
-               irq_base = 0;
-       }
-       at91_aic_domain = irq_domain_add_legacy(at91_aic_np, n_irqs,
-                                               irq_base, 0,
-                                               &irq_domain_simple_ops, NULL);
-
-       if (!at91_aic_domain)
-               panic("Unable to add AIC irq domain\n");
-
-       irq_set_default_host(at91_aic_domain);
-
-       /*
-        * The IVR is used by macro get_irqnr_and_base to read and verify.
-        * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
-        */
-       for (i = 0; i < n_irqs; i++) {
-               /* Put hardware irq number in Source Vector Register: */
-               at91_aic_write(AT91_AIC_SVR(i), NR_IRQS_LEGACY + i);
-               /* Active Low interrupt, with the specified priority */
-               at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
-               irq_set_chip_and_handler(NR_IRQS_LEGACY + i, &at91_aic_chip, handle_fasteoi_irq);
-               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-       }
-
-       at91_aic_hw_init(n_irqs);
-}
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
deleted file mode 100644 (file)
index eb22e33..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * LED driver for Atmel AT91-based boards.
- *
- *  Copyright (C) SAN People (Pty) 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.
-*/
-
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-
-#include "board.h"
-#include "gpio.h"
-
-
-/* ------------------------------------------------------------------------- */
-
-#if defined(CONFIG_NEW_LEDS)
-
-/*
- * New cross-platform LED support.
- */
-
-static struct gpio_led_platform_data led_data;
-
-static struct platform_device at91_gpio_leds_device = {
-       .name                   = "leds-gpio",
-       .id                     = -1,
-       .dev.platform_data      = &led_data,
-};
-
-void __init at91_gpio_leds(struct gpio_led *leds, int nr)
-{
-       int i;
-
-       if (!nr)
-               return;
-
-       for (i = 0; i < nr; i++)
-               at91_set_gpio_output(leds[i].gpio, leds[i].active_low);
-
-       led_data.leds = leds;
-       led_data.num_leds = nr;
-       platform_device_register(&at91_gpio_leds_device);
-}
-
-#else
-void __init at91_gpio_leds(struct gpio_led *leds, int nr) {}
-#endif
-
index 4073ab7f38f3db39954ae8363071fba8635745b1..9b15169a1c624a182cc2431f9d9040c0034e978d 100644 (file)
 #include <mach/cpu.h>
 #include <mach/hardware.h>
 
-#include "at91_aic.h"
 #include "generic.h"
 #include "pm.h"
-#include "gpio.h"
 
 static void (*at91_pm_standby)(void);
 
@@ -131,23 +129,7 @@ extern u32 at91_slow_clock_sz;
 
 static int at91_pm_enter(suspend_state_t state)
 {
-       if (of_have_populated_dt())
-               at91_pinctrl_gpio_suspend();
-       else
-               at91_gpio_suspend();
-
-       if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base) {
-               at91_irq_suspend();
-
-               pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
-                               /* remember all the always-wake irqs */
-                               (at91_pmc_read(AT91_PMC_PCSR)
-                                               | (1 << AT91_ID_FIQ)
-                                               | (1 << AT91_ID_SYS)
-                                               | (at91_get_extern_irq()))
-                                       & at91_aic_read(AT91_AIC_IMR),
-                               state);
-       }
+       at91_pinctrl_gpio_suspend();
 
        switch (state) {
                /*
@@ -212,21 +194,10 @@ static int at91_pm_enter(suspend_state_t state)
                        goto error;
        }
 
-       if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base)
-               pr_debug("AT91: PM - wakeup %08x\n",
-                        at91_aic_read(AT91_AIC_IPR) &
-                        at91_aic_read(AT91_AIC_IMR));
-
 error:
        target_state = PM_SUSPEND_ON;
 
-       if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base)
-               at91_irq_resume();
-
-       if (of_have_populated_dt())
-               at91_pinctrl_gpio_resume();
-       else
-               at91_gpio_resume();
+       at91_pinctrl_gpio_resume();
        return 0;
 }
 
index c5101dcb4fb04d8d9af68bea524043feb3c289a9..d2c89963af2d168179e01e72d51f6684decc8d5e 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/proc-fns.h>
 
 #include <mach/at91_ramc.h>
-#include <mach/at91rm9200_sdramc.h>
 
 #ifdef CONFIG_PM
 extern void at91_pm_set_standby(void (*at91_standby)(void));
index 961079250b837c25ca7623563285fc090dd09e00..ce25e85720fb695eedef9650d097693e1a714dde 100644 (file)
@@ -42,35 +42,9 @@ void __init at91rm9200_set_type(int type)
                at91_get_soc_subtype(&at91_soc_initdata));
 }
 
-void __init at91_init_irq_default(void)
-{
-       at91_init_interrupts(at91_boot_soc.default_irq_priority);
-}
-
-void __init at91_init_interrupts(unsigned int *priority)
-{
-       /* Initialize the AIC interrupt controller */
-       if (IS_ENABLED(CONFIG_OLD_IRQ_AT91))
-               at91_aic_init(priority, at91_boot_soc.extern_irq);
-
-       /* Enable GPIO interrupts */
-       at91_gpio_irq_setup();
-}
-
 void __iomem *at91_ramc_base[2];
 EXPORT_SYMBOL_GPL(at91_ramc_base);
 
-void __init at91_ioremap_ramc(int id, u32 addr, u32 size)
-{
-       if (id < 0 || id > 1) {
-               pr_emerg("Wrong RAM controller id (%d), cannot continue\n", id);
-               BUG();
-       }
-       at91_ramc_base[id] = ioremap(addr, size);
-       if (!at91_ramc_base[id])
-               panic(pr_fmt("Impossible to ioremap ramc.%d 0x%x\n"), id, addr);
-}
-
 static struct map_desc sram_desc[2] __initdata;
 
 void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
@@ -418,7 +392,6 @@ void __init at91_ioremap_matrix(u32 base_addr)
                panic(pr_fmt("Impossible to ioremap at91_matrix_base\n"));
 }
 
-#if defined(CONFIG_OF) && !defined(CONFIG_ARCH_AT91X40)
 static struct of_device_id ramc_ids[] = {
        { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
        { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
@@ -460,13 +433,6 @@ void __init at91rm9200_dt_initialize(void)
 {
        at91_dt_ramc();
 
-       /* Init clock subsystem */
-       at91_dt_clock_init();
-
-       /* Register the processor-specific clocks */
-       if (at91_boot_soc.register_clocks)
-               at91_boot_soc.register_clocks();
-
        at91_boot_soc.init();
 }
 
@@ -474,39 +440,6 @@ void __init at91_dt_initialize(void)
 {
        at91_dt_ramc();
 
-       /* Init clock subsystem */
-       at91_dt_clock_init();
-
-       /* Register the processor-specific clocks */
-       if (at91_boot_soc.register_clocks)
-               at91_boot_soc.register_clocks();
-
        if (at91_boot_soc.init)
                at91_boot_soc.init();
 }
-#endif
-
-void __init at91_initialize(unsigned long main_clock)
-{
-       at91_boot_soc.ioremap_registers();
-
-       /* Init clock subsystem */
-       at91_clock_init(main_clock);
-
-       /* Register the processor-specific clocks */
-       at91_boot_soc.register_clocks();
-
-       at91_boot_soc.init();
-
-       pinctrl_provide_dummies();
-}
-
-void __init at91_register_devices(void)
-{
-       at91_boot_soc.register_devices();
-}
-
-void __init at91_init_time(void)
-{
-       at91_boot_soc.init_time();
-}
index 9a8fd97a8befe1502c9dc12ed64ecc597b2d98b1..ae6c0b2f1146fd43b683c6bff4a8a2c4b6f549ae 100644 (file)
@@ -6,14 +6,8 @@
 
 struct at91_init_soc {
        int builtin;
-       u32 extern_irq;
-       unsigned int *default_irq_priority;
        void (*map_io)(void);
-       void (*ioremap_registers)(void);
-       void (*register_clocks)(void);
-       void (*register_devices)(void);
        void (*init)(void);
-       void (*init_time)(void);
 };
 
 extern struct at91_init_soc at91_boot_soc;
diff --git a/arch/arm/mach-at91/stamp9g20.h b/arch/arm/mach-at91/stamp9g20.h
deleted file mode 100644 (file)
index f62c0ab..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_STAMP9G20_H
-#define __MACH_STAMP9G20_H
-
-void stamp9g20_init_early(void);
-void stamp9g20_board_init(void);
-
-#endif
index bf47eb09ff7ddae06c877503af79da89db031646..aaeec78c3ec4d05df74531a36245d21c4b9e2dd8 100644 (file)
@@ -5,8 +5,56 @@ menuconfig ARCH_BCM
 
 if ARCH_BCM
 
+comment "IPROC architected SoCs"
+
+config ARCH_BCM_IPROC
+       bool
+       select ARM_GIC
+       select CACHE_L2X0
+       select HAVE_ARM_SCU if SMP
+       select HAVE_ARM_TWD if SMP
+       select ARM_GLOBAL_TIMER
+
+       select CLKSRC_MMIO
+       select ARCH_REQUIRE_GPIOLIB
+       select ARM_AMBA
+       select PINCTRL
+       help
+         This enables support for systems based on Broadcom IPROC architected SoCs.
+         The IPROC complex contains one or more ARM CPUs along with common
+         core periperals. Application specific SoCs are created by adding a
+         uArchitecture containing peripherals outside of the IPROC complex.
+         Currently supported SoCs are Cygnus.
+
+config ARCH_BCM_CYGNUS
+       bool "Broadcom Cygnus Support" if ARCH_MULTI_V7
+       select ARCH_BCM_IPROC
+       help
+         Enable support for the Cygnus family,
+         which includes the following variants:
+         BCM11300, BCM11320, BCM11350, BCM11360,
+         BCM58300, BCM58302, BCM58303, BCM58305.
+
+config ARCH_BCM_5301X
+       bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
+       select ARCH_BCM_IPROC
+       help
+         Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
+
+         This is a network SoC line mostly used in home routers and
+         wifi access points, it's internal name is Northstar.
+         This inclused the following SoC: BCM53010, BCM53011, BCM53012,
+         BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707,
+         BCM4708 and BCM4709.
+
+         Do not confuse this with the BCM4760 which is a totally
+         different SoC or with the older BCM47XX and BCM53XX based
+         network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
+
+comment "KONA architected SoCs"
+
 config ARCH_BCM_MOBILE
-       bool "Broadcom Mobile SoC Support" if ARCH_MULTI_V7
+       bool
        select ARCH_REQUIRE_GPIOLIB
        select ARM_ERRATA_754322
        select ARM_ERRATA_775420
@@ -15,16 +63,13 @@ config ARCH_BCM_MOBILE
        select TICK_ONESHOT
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL
+       select ARCH_BCM_MOBILE_SMP if SMP
        help
          This enables support for systems based on Broadcom mobile SoCs.
 
-if ARCH_BCM_MOBILE
-
-menu "Broadcom Mobile SoC Selection"
-
 config ARCH_BCM_281XX
        bool "Broadcom BCM281XX SoC family"
-       default y
+       select ARCH_BCM_MOBILE
        select HAVE_SMP
        help
          Enable support for the BCM281XX family, which includes
@@ -33,7 +78,7 @@ config ARCH_BCM_281XX
 
 config ARCH_BCM_21664
        bool "Broadcom BCM21664 SoC family"
-       default y
+       select ARCH_BCM_MOBILE
        select HAVE_SMP
        help
          Enable support for the BCM21664 family, which includes
@@ -41,19 +86,18 @@ config ARCH_BCM_21664
 
 config ARCH_BCM_MOBILE_L2_CACHE
        bool "Broadcom mobile SoC level 2 cache support"
-       depends on (ARCH_BCM_281XX || ARCH_BCM_21664)
+       depends on ARCH_BCM_MOBILE
        default y
        select CACHE_L2X0
        select ARCH_BCM_MOBILE_SMC
 
 config ARCH_BCM_MOBILE_SMC
        bool
-       depends on ARCH_BCM_281XX || ARCH_BCM_21664
+       depends on ARCH_BCM_MOBILE
 
 config ARCH_BCM_MOBILE_SMP
-       bool "Broadcom mobile SoC SMP support"
-       depends on (ARCH_BCM_281XX || ARCH_BCM_21664) && SMP
-       default y
+       bool
+       depends on ARCH_BCM_MOBILE
        select HAVE_ARM_SCU
        select ARM_ERRATA_764369
        help
@@ -61,9 +105,7 @@ config ARCH_BCM_MOBILE_SMP
          Provided as an option so SMP support for SoCs of this type
          can be disabled for an SMP-enabled kernel.
 
-endmenu
-
-endif
+comment "Other Architectures"
 
 config ARCH_BCM2835
        bool "Broadcom BCM2835 family" if ARCH_MULTI_V6
@@ -78,27 +120,6 @@ config ARCH_BCM2835
          This enables support for the Broadcom BCM2835 SoC. This SoC is
          used in the Raspberry Pi and Roku 2 devices.
 
-config ARCH_BCM_5301X
-       bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
-       select ARM_GIC
-       select CACHE_L2X0
-       select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if SMP
-       select ARM_GLOBAL_TIMER
-       select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
-       help
-         Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
-
-         This is a network SoC line mostly used in home routers and
-         wifi access points, it's internal name is Northstar.
-         This inclused the following SoC: BCM53010, BCM53011, BCM53012,
-         BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707,
-         BCM4708 and BCM4709.
-
-         Do not confuse this with the BCM4760 which is a totally
-         different SoC or with the older BCM47XX and BCM53XX based
-         network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx
-
 config ARCH_BCM_63XX
        bool "Broadcom BCM63xx DSL SoC" if ARCH_MULTI_V7
        depends on MMU
@@ -118,10 +139,7 @@ config ARCH_BCM_63XX
 
 config ARCH_BRCMSTB
        bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
-       depends on MMU
        select ARM_GIC
-       select MIGHT_HAVE_PCI
-       select HAVE_SMP
        select HAVE_ARM_ARCH_TIMER
        select BRCMSTB_GISB_ARB
        select BRCMSTB_L2_IRQ
index 300ae4b79ae6343eeb17ca2abf899fb699b92b2b..4c38674c73ecb15d92702ca58b4d0f95bf2888fe 100644 (file)
@@ -10,6 +10,9 @@
 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 
+# Cygnus
+obj-$(CONFIG_ARCH_BCM_CYGNUS) +=  bcm_cygnus.o
+
 # BCM281XX
 obj-$(CONFIG_ARCH_BCM_281XX)   += board_bcm281xx.o
 
@@ -38,5 +41,7 @@ obj-$(CONFIG_ARCH_BCM_5301X)  += bcm_5301x.o
 obj-$(CONFIG_ARCH_BCM_63XX)    := bcm63xx.o
 
 ifeq ($(CONFIG_ARCH_BRCMSTB),y)
+CFLAGS_platsmp-brcmstb.o       += -march=armv7-a
 obj-y                          += brcmstb.o
+obj-$(CONFIG_SMP)              += headsmp-brcmstb.o platsmp-brcmstb.o
 endif
diff --git a/arch/arm/mach-bcm/bcm_cygnus.c b/arch/arm/mach-bcm/bcm_cygnus.c
new file mode 100644 (file)
index 0000000..30dc58b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 Broadcom 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/mach/arch.h>
+
+static const char const *bcm_cygnus_dt_compat[] = {
+       "brcm,cygnus",
+       NULL,
+};
+
+DT_MACHINE_START(BCM_CYGNUS_DT, "Broadcom Cygnus SoC")
+       .l2c_aux_val    = 0,
+       .l2c_aux_mask   = ~0,
+       .dt_compat = bcm_cygnus_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-bcm/brcmstb.h b/arch/arm/mach-bcm/brcmstb.h
new file mode 100644 (file)
index 0000000..ec0c3d1
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2013-2014 Broadcom 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __BRCMSTB_H__
+#define __BRCMSTB_H__
+
+void brcmstb_secondary_startup(void);
+
+#endif /* __BRCMSTB_H__ */
diff --git a/arch/arm/mach-bcm/headsmp-brcmstb.S b/arch/arm/mach-bcm/headsmp-brcmstb.S
new file mode 100644 (file)
index 0000000..199c1ea
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * SMP boot code for secondary CPUs
+ * Based on arch/arm/mach-tegra/headsmp.S
+ *
+ * Copyright (C) 2010 NVIDIA, Inc.
+ * Copyright (C) 2013-2014 Broadcom 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/assembler.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+        .section ".text.head", "ax"
+
+ENTRY(brcmstb_secondary_startup)
+        /*
+         * Ensure CPU is in a sane state by disabling all IRQs and switching
+         * into SVC mode.
+         */
+        setmode        PSR_I_BIT | PSR_F_BIT | SVC_MODE, r0
+
+        bl      v7_invalidate_l1
+        b       secondary_startup
+ENDPROC(brcmstb_secondary_startup)
diff --git a/arch/arm/mach-bcm/platsmp-brcmstb.c b/arch/arm/mach-bcm/platsmp-brcmstb.c
new file mode 100644 (file)
index 0000000..31c87a2
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Broadcom STB CPU SMP and hotplug support for ARM
+ *
+ * Copyright (C) 2013-2014 Broadcom 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.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; 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/init.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/printk.h>
+#include <linux/regmap.h>
+#include <linux/smp.h>
+#include <linux/mfd/syscon.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/mach-types.h>
+#include <asm/smp_plat.h>
+
+#include "brcmstb.h"
+
+enum {
+       ZONE_MAN_CLKEN_MASK             = BIT(0),
+       ZONE_MAN_RESET_CNTL_MASK        = BIT(1),
+       ZONE_MAN_MEM_PWR_MASK           = BIT(4),
+       ZONE_RESERVED_1_MASK            = BIT(5),
+       ZONE_MAN_ISO_CNTL_MASK          = BIT(6),
+       ZONE_MANUAL_CONTROL_MASK        = BIT(7),
+       ZONE_PWR_DN_REQ_MASK            = BIT(9),
+       ZONE_PWR_UP_REQ_MASK            = BIT(10),
+       ZONE_BLK_RST_ASSERT_MASK        = BIT(12),
+       ZONE_PWR_OFF_STATE_MASK         = BIT(25),
+       ZONE_PWR_ON_STATE_MASK          = BIT(26),
+       ZONE_DPG_PWR_STATE_MASK         = BIT(28),
+       ZONE_MEM_PWR_STATE_MASK         = BIT(29),
+       ZONE_RESET_STATE_MASK           = BIT(31),
+       CPU0_PWR_ZONE_CTRL_REG          = 1,
+       CPU_RESET_CONFIG_REG            = 2,
+};
+
+static void __iomem *cpubiuctrl_block;
+static void __iomem *hif_cont_block;
+static u32 cpu0_pwr_zone_ctrl_reg;
+static u32 cpu_rst_cfg_reg;
+static u32 hif_cont_reg;
+
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * We must quiesce a dying CPU before it can be killed by the boot CPU. Because
+ * one or more cache may be disabled, we must flush to ensure coherency. We
+ * cannot use traditionl completion structures or spinlocks as they rely on
+ * coherency.
+ */
+static DEFINE_PER_CPU_ALIGNED(int, per_cpu_sw_state);
+
+static int per_cpu_sw_state_rd(u32 cpu)
+{
+       sync_cache_r(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
+       return per_cpu(per_cpu_sw_state, cpu);
+}
+
+static void per_cpu_sw_state_wr(u32 cpu, int val)
+{
+       dmb();
+       per_cpu(per_cpu_sw_state, cpu) = val;
+       sync_cache_w(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
+}
+#else
+static inline void per_cpu_sw_state_wr(u32 cpu, int val) { }
+#endif
+
+static void __iomem *pwr_ctrl_get_base(u32 cpu)
+{
+       void __iomem *base = cpubiuctrl_block + cpu0_pwr_zone_ctrl_reg;
+       base += (cpu_logical_map(cpu) * 4);
+       return base;
+}
+
+static u32 pwr_ctrl_rd(u32 cpu)
+{
+       void __iomem *base = pwr_ctrl_get_base(cpu);
+       return readl_relaxed(base);
+}
+
+static void pwr_ctrl_wr(u32 cpu, u32 val)
+{
+       void __iomem *base = pwr_ctrl_get_base(cpu);
+       writel(val, base);
+}
+
+static void cpu_rst_cfg_set(u32 cpu, int set)
+{
+       u32 val;
+       val = readl_relaxed(cpubiuctrl_block + cpu_rst_cfg_reg);
+       if (set)
+               val |= BIT(cpu_logical_map(cpu));
+       else
+               val &= ~BIT(cpu_logical_map(cpu));
+       writel_relaxed(val, cpubiuctrl_block + cpu_rst_cfg_reg);
+}
+
+static void cpu_set_boot_addr(u32 cpu, unsigned long boot_addr)
+{
+       const int reg_ofs = cpu_logical_map(cpu) * 8;
+       writel_relaxed(0, hif_cont_block + hif_cont_reg + reg_ofs);
+       writel_relaxed(boot_addr, hif_cont_block + hif_cont_reg + 4 + reg_ofs);
+}
+
+static void brcmstb_cpu_boot(u32 cpu)
+{
+       /* Mark this CPU as "up" */
+       per_cpu_sw_state_wr(cpu, 1);
+
+       /*
+        * Set the reset vector to point to the secondary_startup
+        * routine
+        */
+       cpu_set_boot_addr(cpu, virt_to_phys(brcmstb_secondary_startup));
+
+       /* Unhalt the cpu */
+       cpu_rst_cfg_set(cpu, 0);
+}
+
+static void brcmstb_cpu_power_on(u32 cpu)
+{
+       /*
+        * The secondary cores power was cut, so we must go through
+        * power-on initialization.
+        */
+       u32 tmp;
+
+       /* Request zone power up */
+       pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
+
+       /* Wait for the power up FSM to complete */
+       do {
+               tmp = pwr_ctrl_rd(cpu);
+       } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
+}
+
+static int brcmstb_cpu_get_power_state(u32 cpu)
+{
+       int tmp = pwr_ctrl_rd(cpu);
+       return (tmp & ZONE_RESET_STATE_MASK) ? 0 : 1;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void brcmstb_cpu_die(u32 cpu)
+{
+       v7_exit_coherency_flush(all);
+
+       per_cpu_sw_state_wr(cpu, 0);
+
+       /* Sit and wait to die */
+       wfi();
+
+       /* We should never get here... */
+       while (1)
+               ;
+}
+
+static int brcmstb_cpu_kill(u32 cpu)
+{
+       u32 tmp;
+
+       while (per_cpu_sw_state_rd(cpu))
+               ;
+
+       /* Program zone reset */
+       pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
+                             ZONE_PWR_DN_REQ_MASK);
+
+       /* Verify zone reset */
+       tmp = pwr_ctrl_rd(cpu);
+       if (!(tmp & ZONE_RESET_STATE_MASK))
+               pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
+                       __func__, cpu);
+
+       /* Wait for power down */
+       do {
+               tmp = pwr_ctrl_rd(cpu);
+       } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
+
+       /* Flush pipeline before resetting CPU */
+       mb();
+
+       /* Assert reset on the CPU */
+       cpu_rst_cfg_set(cpu, 1);
+
+       return 1;
+}
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
+{
+       int rc = 0;
+       char *name;
+       struct device_node *syscon_np = NULL;
+
+       name = "syscon-cpu";
+
+       syscon_np = of_parse_phandle(np, name, 0);
+       if (!syscon_np) {
+               pr_err("can't find phandle %s\n", name);
+               rc = -EINVAL;
+               goto cleanup;
+       }
+
+       cpubiuctrl_block = of_iomap(syscon_np, 0);
+       if (!cpubiuctrl_block) {
+               pr_err("iomap failed for cpubiuctrl_block\n");
+               rc = -EINVAL;
+               goto cleanup;
+       }
+
+       rc = of_property_read_u32_index(np, name, CPU0_PWR_ZONE_CTRL_REG,
+                                       &cpu0_pwr_zone_ctrl_reg);
+       if (rc) {
+               pr_err("failed to read 1st entry from %s property (%d)\n", name,
+                       rc);
+               rc = -EINVAL;
+               goto cleanup;
+       }
+
+       rc = of_property_read_u32_index(np, name, CPU_RESET_CONFIG_REG,
+                                       &cpu_rst_cfg_reg);
+       if (rc) {
+               pr_err("failed to read 2nd entry from %s property (%d)\n", name,
+                       rc);
+               rc = -EINVAL;
+               goto cleanup;
+       }
+
+cleanup:
+       of_node_put(syscon_np);
+       return rc;
+}
+
+static int __init setup_hifcont_regs(struct device_node *np)
+{
+       int rc = 0;
+       char *name;
+       struct device_node *syscon_np = NULL;
+
+       name = "syscon-cont";
+
+       syscon_np = of_parse_phandle(np, name, 0);
+       if (!syscon_np) {
+               pr_err("can't find phandle %s\n", name);
+               rc = -EINVAL;
+               goto cleanup;
+       }
+
+       hif_cont_block = of_iomap(syscon_np, 0);
+       if (!hif_cont_block) {
+               pr_err("iomap failed for hif_cont_block\n");
+               rc = -EINVAL;
+               goto cleanup;
+       }
+
+       /* Offset is at top of hif_cont_block */
+       hif_cont_reg = 0;
+
+cleanup:
+       of_node_put(syscon_np);
+       return rc;
+}
+
+static void __init brcmstb_cpu_ctrl_setup(unsigned int max_cpus)
+{
+       int rc;
+       struct device_node *np;
+       char *name;
+
+       name = "brcm,brcmstb-smpboot";
+       np = of_find_compatible_node(NULL, NULL, name);
+       if (!np) {
+               pr_err("can't find compatible node %s\n", name);
+               return;
+       }
+
+       rc = setup_hifcpubiuctrl_regs(np);
+       if (rc)
+               return;
+
+       rc = setup_hifcont_regs(np);
+       if (rc)
+               return;
+}
+
+static int brcmstb_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       /* Missing the brcm,brcmstb-smpboot DT node? */
+       if (!cpubiuctrl_block || !hif_cont_block)
+               return -ENODEV;
+
+       /* Bring up power to the core if necessary */
+       if (brcmstb_cpu_get_power_state(cpu) == 0)
+               brcmstb_cpu_power_on(cpu);
+
+       brcmstb_cpu_boot(cpu);
+
+       return 0;
+}
+
+static struct smp_operations brcmstb_smp_ops __initdata = {
+       .smp_prepare_cpus       = brcmstb_cpu_ctrl_setup,
+       .smp_boot_secondary     = brcmstb_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_kill               = brcmstb_cpu_kill,
+       .cpu_die                = brcmstb_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(brcmstb_smp, "brcm,brahma-b15", &brcmstb_smp_ops);
index 24f85be71671080cc9234c7677eefd8c56682c20..3e40a947f3ea4c1552176d6f5e1fe8961de40bb6 100644 (file)
@@ -1,10 +1,11 @@
 menuconfig ARCH_BERLIN
        bool "Marvell Berlin SoCs" if ARCH_MULTI_V7
+       select ARCH_HAS_RESET_CONTROLLER
        select ARCH_REQUIRE_GPIOLIB
        select ARM_GIC
-       select GENERIC_IRQ_CHIP
        select DW_APB_ICTL
        select DW_APB_TIMER_OF
+       select GENERIC_IRQ_CHIP
        select PINCTRL
 
 if ARCH_BERLIN
index 5623131c4f0b6108a289872d445174f1ce2473d9..f8f62fbaa915880399b7a4adff67be1236c5e51d 100644 (file)
@@ -80,8 +80,8 @@ static int da830_evm_usb_ocic_notify(da8xx_ocic_handler_t handler)
                                    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                                    "OHCI over-current indicator", NULL);
                if (error)
-                       printk(KERN_ERR "%s: could not request IRQ to watch "
-                              "over-current indicator changes\n", __func__);
+                       pr_err("%s: could not request IRQ to watch over-current indicator changes\n",
+                              __func__);
        } else
                free_irq(irq, NULL);
 
@@ -145,8 +145,7 @@ static __init void da830_evm_usb_init(void)
        /* USB_REFCLKIN is not used. */
        ret = davinci_cfg_reg(DA830_USB0_DRVVBUS);
        if (ret)
-               pr_warning("%s: USB 2.0 PinMux setup failed: %d\n",
-                          __func__, ret);
+               pr_warn("%s: USB 2.0 PinMux setup failed: %d\n", __func__, ret);
        else {
                /*
                 * TPS2065 switch @ 5V supplies 1 A (sustains 1.5 A),
@@ -154,37 +153,35 @@ static __init void da830_evm_usb_init(void)
                 */
                ret = da8xx_register_usb20(1000, 3);
                if (ret)
-                       pr_warning("%s: USB 2.0 registration failed: %d\n",
-                                  __func__, ret);
+                       pr_warn("%s: USB 2.0 registration failed: %d\n",
+                               __func__, ret);
        }
 
        ret = davinci_cfg_reg_list(da830_evm_usb11_pins);
        if (ret) {
-               pr_warning("%s: USB 1.1 PinMux setup failed: %d\n",
-                          __func__, ret);
+               pr_warn("%s: USB 1.1 PinMux setup failed: %d\n", __func__, ret);
                return;
        }
 
        ret = gpio_request(ON_BD_USB_DRV, "ON_BD_USB_DRV");
        if (ret) {
-               printk(KERN_ERR "%s: failed to request GPIO for USB 1.1 port "
-                      "power control: %d\n", __func__, ret);
+               pr_err("%s: failed to request GPIO for USB 1.1 port power control: %d\n",
+                      __func__, ret);
                return;
        }
        gpio_direction_output(ON_BD_USB_DRV, 0);
 
        ret = gpio_request(ON_BD_USB_OVC, "ON_BD_USB_OVC");
        if (ret) {
-               printk(KERN_ERR "%s: failed to request GPIO for USB 1.1 port "
-                      "over-current indicator: %d\n", __func__, ret);
+               pr_err("%s: failed to request GPIO for USB 1.1 port over-current indicator: %d\n",
+                      __func__, ret);
                return;
        }
        gpio_direction_input(ON_BD_USB_OVC);
 
        ret = da8xx_register_usb11(&da830_evm_usb11_pdata);
        if (ret)
-               pr_warning("%s: USB 1.1 registration failed: %d\n",
-                          __func__, ret);
+               pr_warn("%s: USB 1.1 registration failed: %d\n", __func__, ret);
 }
 
 static const short da830_evm_mcasp1_pins[] = {
@@ -252,31 +249,29 @@ static inline void da830_evm_init_mmc(void)
 
        ret = davinci_cfg_reg_list(da830_evm_mmc_sd_pins);
        if (ret) {
-               pr_warning("da830_evm_init: mmc/sd mux setup failed: %d\n",
-                               ret);
+               pr_warn("%s: mmc/sd mux setup failed: %d\n", __func__, ret);
                return;
        }
 
        ret = gpio_request(DA830_MMCSD_WP_PIN, "MMC WP");
        if (ret) {
-               pr_warning("da830_evm_init: can not open GPIO %d\n",
-                          DA830_MMCSD_WP_PIN);
+               pr_warn("%s: can not open GPIO %d\n",
+                       __func__, DA830_MMCSD_WP_PIN);
                return;
        }
        gpio_direction_input(DA830_MMCSD_WP_PIN);
 
        ret = gpio_request(DA830_MMCSD_CD_PIN, "MMC CD\n");
        if (ret) {
-               pr_warning("da830_evm_init: can not open GPIO %d\n",
-                          DA830_MMCSD_CD_PIN);
+               pr_warn("%s: can not open GPIO %d\n",
+                       __func__, DA830_MMCSD_CD_PIN);
                return;
        }
        gpio_direction_input(DA830_MMCSD_CD_PIN);
 
        ret = da8xx_register_mmcsd0(&da830_evm_mmc_config);
        if (ret) {
-               pr_warning("da830_evm_init: mmc/sd registration failed: %d\n",
-                               ret);
+               pr_warn("%s: mmc/sd registration failed: %d\n", __func__, ret);
                gpio_free(DA830_MMCSD_WP_PIN);
        }
 }
@@ -404,23 +399,21 @@ static inline void da830_evm_init_nand(int mux_mode)
        int ret;
 
        if (HAS_MMC) {
-               pr_warning("WARNING: both MMC/SD and NAND are "
-                               "enabled, but they share AEMIF pins.\n"
-                               "\tDisable MMC/SD for NAND support.\n");
+               pr_warn("WARNING: both MMC/SD and NAND are enabled, but they share AEMIF pins\n"
+                       "\tDisable MMC/SD for NAND support\n");
                return;
        }
 
        ret = davinci_cfg_reg_list(da830_evm_emif25_pins);
        if (ret)
-               pr_warning("da830_evm_init: emif25 mux setup failed: %d\n",
-                               ret);
+               pr_warn("%s: emif25 mux setup failed: %d\n", __func__, ret);
 
        ret = platform_device_register(&da830_evm_nand_device);
        if (ret)
-               pr_warning("da830_evm_init: NAND device not registered.\n");
+               pr_warn("%s: NAND device not registered\n", __func__);
 
        if (davinci_aemif_setup(&da830_evm_nand_device))
-               pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+               pr_warn("%s: Cannot configure AEMIF\n", __func__);
 
        gpio_direction_output(mux_mode, 1);
 }
@@ -435,12 +428,11 @@ static inline void da830_evm_init_lcdc(int mux_mode)
 
        ret = davinci_cfg_reg_list(da830_lcdcntl_pins);
        if (ret)
-               pr_warning("da830_evm_init: lcdcntl mux setup failed: %d\n",
-                               ret);
+               pr_warn("%s: lcdcntl mux setup failed: %d\n", __func__, ret);
 
        ret = da8xx_register_lcdc(&sharp_lcd035q3dg01_pdata);
        if (ret)
-               pr_warning("da830_evm_init: lcd setup failed: %d\n", ret);
+               pr_warn("%s: lcd setup failed: %d\n", __func__, ret);
 
        gpio_direction_output(mux_mode, 0);
 }
@@ -598,22 +590,19 @@ static __init void da830_evm_init(void)
 
        ret = da830_register_gpio();
        if (ret)
-               pr_warn("da830_evm_init: GPIO init failed: %d\n", ret);
+               pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
 
        ret = da830_register_edma(da830_edma_rsv);
        if (ret)
-               pr_warning("da830_evm_init: edma registration failed: %d\n",
-                               ret);
+               pr_warn("%s: edma registration failed: %d\n", __func__, ret);
 
        ret = davinci_cfg_reg_list(da830_i2c0_pins);
        if (ret)
-               pr_warning("da830_evm_init: i2c0 mux setup failed: %d\n",
-                               ret);
+               pr_warn("%s: i2c0 mux setup failed: %d\n", __func__, ret);
 
        ret = da8xx_register_i2c(0, &da830_evm_i2c_0_pdata);
        if (ret)
-               pr_warning("da830_evm_init: i2c0 registration failed: %d\n",
-                               ret);
+               pr_warn("%s: i2c0 registration failed: %d\n", __func__, ret);
 
        da830_evm_usb_init();
 
@@ -622,18 +611,16 @@ static __init void da830_evm_init(void)
 
        ret = davinci_cfg_reg_list(da830_cpgmac_pins);
        if (ret)
-               pr_warning("da830_evm_init: cpgmac mux setup failed: %d\n",
-                               ret);
+               pr_warn("%s: cpgmac mux setup failed: %d\n", __func__, ret);
 
        ret = da8xx_register_emac();
        if (ret)
-               pr_warning("da830_evm_init: emac registration failed: %d\n",
-                               ret);
+               pr_warn("%s: emac registration failed: %d\n", __func__, ret);
 
        ret = da8xx_register_watchdog();
        if (ret)
-               pr_warning("da830_evm_init: watchdog registration failed: %d\n",
-                               ret);
+               pr_warn("%s: watchdog registration failed: %d\n",
+                       __func__, ret);
 
        davinci_serial_init(da8xx_serial_device);
        i2c_register_board_info(1, da830_evm_i2c_devices,
@@ -641,8 +628,7 @@ static __init void da830_evm_init(void)
 
        ret = davinci_cfg_reg_list(da830_evm_mcasp1_pins);
        if (ret)
-               pr_warning("da830_evm_init: mcasp1 mux setup failed: %d\n",
-                               ret);
+               pr_warn("%s: mcasp1 mux setup failed: %d\n", __func__, ret);
 
        da8xx_register_mcasp(1, &da830_evm_snd_data);
 
@@ -650,18 +636,17 @@ static __init void da830_evm_init(void)
 
        ret = da8xx_register_rtc();
        if (ret)
-               pr_warning("da830_evm_init: rtc setup failed: %d\n", ret);
+               pr_warn("%s: rtc setup failed: %d\n", __func__, ret);
 
        ret = spi_register_board_info(da830evm_spi_info,
                                      ARRAY_SIZE(da830evm_spi_info));
        if (ret)
-               pr_warn("%s: spi info registration failed: %d\n", __func__,
-                       ret);
+               pr_warn("%s: spi info registration failed: %d\n",
+                       __func__, ret);
 
        ret = da8xx_register_spi_bus(0, ARRAY_SIZE(da830evm_spi_info));
        if (ret)
-               pr_warning("da830_evm_init: spi 0 registration failed: %d\n",
-                          ret);
+               pr_warn("%s: spi 0 registration failed: %d\n", __func__, ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
index fa11415e906aa566c93c5247e5aa3b191f518146..6b5a97da9fe39da65df47b5c9bbe8fd1359666d8 100644 (file)
@@ -452,8 +452,7 @@ static void da850_evm_ui_keys_init(unsigned gpio)
        for (i = 0; i < DA850_N_UI_PB; i++) {
                button = &da850_evm_ui_keys[i];
                button->code = KEY_F8 - i;
-               button->desc = (char *)
-                               da850_evm_ui_exp[DA850_EVM_UI_EXP_PB8 + i];
+               button->desc = da850_evm_ui_exp[DA850_EVM_UI_EXP_PB8 + i];
                button->gpio = gpio + DA850_EVM_UI_EXP_PB8 + i;
        }
 }
@@ -628,15 +627,13 @@ static void da850_evm_bb_keys_init(unsigned gpio)
        struct gpio_keys_button *button;
 
        button = &da850_evm_bb_keys[0];
-       button->desc = (char *)
-               da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_PB1];
+       button->desc = da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_PB1];
        button->gpio = gpio + DA850_EVM_BB_EXP_USER_PB1;
 
        for (i = 0; i < DA850_N_BB_USER_SW; i++) {
                button = &da850_evm_bb_keys[i + 1];
                button->code = SW_LID + i;
-               button->desc = (char *)
-                               da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_SW1 + i];
+               button->desc = da850_evm_bb_exp[DA850_EVM_BB_EXP_USER_SW1 + i];
                button->gpio = gpio + DA850_EVM_BB_EXP_USER_SW1 + i;
        }
 }
index e583e58b5e1ee7e2f30d782ef133ce76d2935dbf..1a0898c1c17ec40f4c66f2d3fa0f4c7d9da9f357 100644 (file)
@@ -767,9 +767,8 @@ static __init void davinci_evm_init(void)
 
        if (HAS_ATA) {
                if (HAS_NAND || HAS_NOR)
-                       pr_warning("WARNING: both IDE and Flash are "
-                               "enabled, but they share AEMIF pins.\n"
-                               "\tDisable IDE for NAND/NOR support.\n");
+                       pr_warn("WARNING: both IDE and Flash are enabled, but they share AEMIF pins\n"
+                               "\tDisable IDE for NAND/NOR support\n");
                davinci_init_ide();
        } else if (HAS_NAND || HAS_NOR) {
                davinci_cfg_reg(DM644X_HPIEN_DISABLE);
@@ -780,13 +779,12 @@ static __init void davinci_evm_init(void)
                        platform_device_register(&davinci_evm_nandflash_device);
 
                        if (davinci_aemif_setup(&davinci_evm_nandflash_device))
-                               pr_warn("%s: Cannot configure AEMIF.\n",
+                               pr_warn("%s: Cannot configure AEMIF\n",
                                        __func__);
 
                        evm_leds[7].default_trigger = "nand-disk";
                        if (HAS_NOR)
-                               pr_warning("WARNING: both NAND and NOR flash "
-                                       "are enabled; disable one of them.\n");
+                               pr_warn("WARNING: both NAND and NOR flash are enabled; disable one of them.\n");
                } else if (HAS_NOR)
                        platform_device_register(&davinci_evm_norflash_device);
        }
index 96fc00a167f5cc61e5cc877cca97fe5367ae25b4..8cfbfe084535799e4cfa68bcb8031bf15887fade 100644 (file)
@@ -8,6 +8,8 @@
  * any kind, whether express or implied.
  */
 
+#define pr_fmt(fmt) "MityOMAPL138: " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/console.h>
@@ -107,7 +109,7 @@ static void mityomapl138_cpufreq_init(const char *partnum)
 
        ret = da850_register_cpufreq("pll0_sysclk3");
        if (ret)
-               pr_warning("cpufreq registration failed: %d\n", ret);
+               pr_warn("cpufreq registration failed: %d\n", ret);
 }
 #else
 static void mityomapl138_cpufreq_init(const char *partnum) { }
@@ -121,33 +123,31 @@ static void read_factory_config(struct memory_accessor *a, void *context)
 
        ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
        if (ret != sizeof(struct factory_config)) {
-               pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n",
-                               ret);
+               pr_warn("Read Factory Config Failed: %d\n", ret);
                goto bad_config;
        }
 
        if (factory_config.magic != FACTORY_CONFIG_MAGIC) {
-               pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n",
-                               factory_config.magic);
+               pr_warn("Factory Config Magic Wrong (%X)\n",
+                       factory_config.magic);
                goto bad_config;
        }
 
        if (factory_config.version != FACTORY_CONFIG_VERSION) {
-               pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n",
-                               factory_config.version);
+               pr_warn("Factory Config Version Wrong (%X)\n",
+                       factory_config.version);
                goto bad_config;
        }
 
-       pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac);
+       pr_info("Found MAC = %pM\n", factory_config.mac);
        if (is_valid_ether_addr(factory_config.mac))
                memcpy(soc_info->emac_pdata->mac_addr,
                        factory_config.mac, ETH_ALEN);
        else
-               pr_warning("MityOMAPL138: Invalid MAC found "
-                               "in factory config block\n");
+               pr_warn("Invalid MAC found in factory config block\n");
 
        partnum = factory_config.partnum;
-       pr_info("MityOMAPL138: Part Number = %s\n", partnum);
+       pr_info("Part Number = %s\n", partnum);
 
 bad_config:
        /* default maximum speed is valid for all platforms */
@@ -435,7 +435,7 @@ static void __init mityomapl138_setup_nand(void)
                                 ARRAY_SIZE(mityomapl138_devices));
 
        if (davinci_aemif_setup(&mityomapl138_nandflash_device))
-               pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+               pr_warn("%s: Cannot configure AEMIF\n", __func__);
 }
 
 static const short mityomap_mii_pins[] = {
@@ -478,7 +478,7 @@ static void __init mityomapl138_config_emac(void)
        }
 
        if (ret) {
-               pr_warning("mii/rmii mux setup failed: %d\n", ret);
+               pr_warn("mii/rmii mux setup failed: %d\n", ret);
                return;
        }
 
@@ -489,7 +489,7 @@ static void __init mityomapl138_config_emac(void)
 
        ret = da8xx_register_emac();
        if (ret)
-               pr_warning("emac registration failed: %d\n", ret);
+               pr_warn("emac registration failed: %d\n", ret);
 }
 
 static struct davinci_pm_config da850_pm_pdata = {
@@ -511,21 +511,21 @@ static void __init mityomapl138_init(void)
        /* for now, no special EDMA channels are reserved */
        ret = da850_register_edma(NULL);
        if (ret)
-               pr_warning("edma registration failed: %d\n", ret);
+               pr_warn("edma registration failed: %d\n", ret);
 
        ret = da8xx_register_watchdog();
        if (ret)
-               pr_warning("watchdog registration failed: %d\n", ret);
+               pr_warn("watchdog registration failed: %d\n", ret);
 
        davinci_serial_init(da8xx_serial_device);
 
        ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata);
        if (ret)
-               pr_warning("i2c0 registration failed: %d\n", ret);
+               pr_warn("i2c0 registration failed: %d\n", ret);
 
        ret = pmic_tps65023_init();
        if (ret)
-               pr_warning("TPS65023 PMIC init failed: %d\n", ret);
+               pr_warn("TPS65023 PMIC init failed: %d\n", ret);
 
        mityomapl138_setup_nand();
 
@@ -537,22 +537,21 @@ static void __init mityomapl138_init(void)
        ret = da8xx_register_spi_bus(1,
                                     ARRAY_SIZE(mityomapl138_spi_flash_info));
        if (ret)
-               pr_warning("spi 1 registration failed: %d\n", ret);
+               pr_warn("spi 1 registration failed: %d\n", ret);
 
        mityomapl138_config_emac();
 
        ret = da8xx_register_rtc();
        if (ret)
-               pr_warning("rtc setup failed: %d\n", ret);
+               pr_warn("rtc setup failed: %d\n", ret);
 
        ret = da8xx_register_cpuidle();
        if (ret)
-               pr_warning("cpuidle registration failed: %d\n", ret);
+               pr_warn("cpuidle registration failed: %d\n", ret);
 
        ret = da850_register_pm(&da850_pm_device);
        if (ret)
-               pr_warning("da850_evm_init: suspend registration failed: %d\n",
-                               ret);
+               pr_warn("suspend registration failed: %d\n", ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
index bb680af98374e2177702529fd179b0d78d377828..8fcdcf87c47c7a06bd9c86ea18697e7b65be9d9c 100644 (file)
@@ -183,9 +183,8 @@ static __init void davinci_ntosd2_init(void)
 
        if (HAS_ATA) {
                if (HAS_NAND)
-                       pr_warning("WARNING: both IDE and Flash are "
-                               "enabled, but they share AEMIF pins.\n"
-                               "\tDisable IDE for NAND/NOR support.\n");
+                       pr_warn("WARNING: both IDE and Flash are enabled, but they share AEMIF pins\n"
+                               "\tDisable IDE for NAND/NOR support\n");
                davinci_init_ide();
        } else if (HAS_NAND) {
                davinci_cfg_reg(DM644X_HPIEN_DISABLE);
index 985e5fd00fb27d82297c94208a63e911263c6996..c70bb0a4dfb44cb288e671f727199c07a1d0af5f 100644 (file)
@@ -564,7 +564,7 @@ int davinci_set_refclk_rate(unsigned long rate)
 
        refclk = clk_get(NULL, "ref");
        if (IS_ERR(refclk)) {
-               pr_err("%s: failed to get reference clock.\n", __func__);
+               pr_err("%s: failed to get reference clock\n", __func__);
                return PTR_ERR(refclk);
        }
 
index f34a8dcdae2bd43da7b32e35340944b794c94bda..a8eb909a2b6ccd94dd7f66c0c11370afc9503184 100644 (file)
@@ -15,6 +15,9 @@
  *
  * Copyright (C) 2008 Texas Instruments.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
@@ -46,7 +49,7 @@ int __init_or_module davinci_cfg_reg(const unsigned long index)
        }
 
        if (index >= soc_info->pinmux_pins_num) {
-               printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
+               pr_err("Invalid pin mux index: %lu (%lu)\n",
                       index, soc_info->pinmux_pins_num);
                dump_stack();
                return -ENODEV;
@@ -55,7 +58,7 @@ int __init_or_module davinci_cfg_reg(const unsigned long index)
        cfg = &soc_info->pinmux_pins[index];
 
        if (cfg->name == NULL) {
-               printk(KERN_ERR "No entry for the specified index\n");
+               pr_err("No entry for the specified index\n");
                return -ENODEV;
        }
 
@@ -82,15 +85,15 @@ int __init_or_module davinci_cfg_reg(const unsigned long index)
 
        if (warn) {
 #ifdef CONFIG_DAVINCI_MUX_WARNINGS
-               printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+               pr_warn("initialized %s\n", cfg->name);
 #endif
        }
 
 #ifdef CONFIG_DAVINCI_MUX_DEBUG
        if (cfg->debug || warn) {
-               printk(KERN_WARNING "MUX: Setting register %s\n", cfg->name);
-               printk(KERN_WARNING "      %s (0x%08x) = 0x%08x -> 0x%08x\n",
-                      cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
+               pr_warn("Setting register %s\n", cfg->name);
+               pr_warn("   %s (0x%08x) = 0x%08x -> 0x%08x\n",
+                       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
        }
 #endif
 
index 24ad30f32ae327d8e8bd0bb3056232ab78e66da0..160c9602f49064161794a37d7f8af74955d5f734 100644 (file)
@@ -342,8 +342,6 @@ void __init davinci_timer_init(void)
        struct davinci_soc_info *soc_info = &davinci_soc_info;
        unsigned int clockevent_id;
        unsigned int clocksource_id;
-       static char err[] __initdata = KERN_ERR
-               "%s: can't register clocksource!\n";
        int i;
 
        clockevent_id = soc_info->timer_info->clockevent_id;
@@ -364,12 +362,12 @@ void __init davinci_timer_init(void)
 
                /* Only bottom timers can use compare regs */
                if (IS_TIMER_TOP(clockevent_id))
-                       pr_warning("davinci_timer_init: Invalid use"
-                               " of system timers.  Results unpredictable.\n");
+                       pr_warn("%s: Invalid use of system timers.  Results unpredictable.\n",
+                               __func__);
                else if ((dtip[event_timer].cmp_off == 0)
                                || (dtip[event_timer].cmp_irq == 0))
-                       pr_warning("davinci_timer_init:  Invalid timer instance"
-                               " setup.  Results unpredictable.\n");
+                       pr_warn("%s: Invalid timer instance setup.  Results unpredictable.\n",
+                               __func__);
                else {
                        timers[TID_CLOCKEVENT].opts |= TIMER_OPTS_USE_COMPARE;
                        clockevent_davinci.features = CLOCK_EVT_FEAT_ONESHOT;
@@ -389,7 +387,8 @@ void __init davinci_timer_init(void)
        clocksource_davinci.name = id_to_name[clocksource_id];
        if (clocksource_register_hz(&clocksource_davinci,
                                    davinci_clock_tick_rate))
-               printk(err, clocksource_davinci.name);
+               pr_err("%s: can't register clocksource!\n",
+                      clocksource_davinci.name);
 
        sched_clock_register(davinci_read_sched_clock, 32,
                          davinci_clock_tick_rate);
index 11bb0799424b537873adb81761f94bdc97c36b91..69975784acfa8c37e8fd83d31f498b74bfa73cf0 100644 (file)
@@ -29,9 +29,9 @@ u8  __readb(const volatile void __iomem *addr);
 u16 __readw(const volatile void __iomem *addr);
 u32 __readl(const volatile void __iomem *addr);
 
-void __writeb(u8  val, void __iomem *addr);
-void __writew(u16 val, void __iomem *addr);
-void __writel(u32 val, void __iomem *addr);
+void __writeb(u8  val, volatile void __iomem *addr);
+void __writew(u16 val, volatile void __iomem *addr);
+void __writel(u32 val, volatile void __iomem *addr);
 
 /*
  * Argh, someone forgot the IOCS16 line.  We therefore have to handle
@@ -62,20 +62,31 @@ void __writel(u32 val, void __iomem *addr);
 #define writew(v,b)            __writew(v,b)
 #define writel(v,b)            __writel(v,b)
 
+#define insb insb
 extern void insb(unsigned int port, void *buf, int sz);
+#define insw insw
 extern void insw(unsigned int port, void *buf, int sz);
+#define insl insl
 extern void insl(unsigned int port, void *buf, int sz);
 
+#define outsb outsb
 extern void outsb(unsigned int port, const void *buf, int sz);
+#define outsw outsw
 extern void outsw(unsigned int port, const void *buf, int sz);
+#define outsl outsl
 extern void outsl(unsigned int port, const void *buf, int sz);
 
 /* can't support writesb atm */
-extern void writesw(void __iomem *addr, const void *data, int wordlen);
-extern void writesl(void __iomem *addr, const void *data, int longlen);
+#define writesw writesw
+extern void writesw(volatile void __iomem *addr, const void *data, int wordlen);
+#define writesl writesl
+extern void writesl(volatile void __iomem *addr, const void *data, int longlen);
 
 /* can't support readsb atm */
-extern void readsw(const void __iomem *addr, void *data, int wordlen);
-extern void readsl(const void __iomem *addr, void *data, int longlen);
+#define readsw readsw
+extern void readsw(const volatile void __iomem *addr, void *data, int wordlen);
+
+#define readsl readsl
+extern void readsl(const volatile void __iomem *addr, void *data, int longlen);
 
 #endif
index 756cc377a73dcd8d4ad33ecc8f6e7ed30ac825dd..b57980b435fd42f7938c3fe728799f4183faa12a 100644 (file)
@@ -102,7 +102,7 @@ EXPORT_SYMBOL(__readb);
 EXPORT_SYMBOL(__readw);
 EXPORT_SYMBOL(__readl);
 
-void readsw(const void __iomem *addr, void *data, int len)
+void readsw(const volatile void __iomem *addr, void *data, int len)
 {
        void __iomem *a = __isamem_convert_addr(addr);
 
@@ -112,7 +112,7 @@ void readsw(const void __iomem *addr, void *data, int len)
 }
 EXPORT_SYMBOL(readsw);
 
-void readsl(const void __iomem *addr, void *data, int len)
+void readsl(const volatile void __iomem *addr, void *data, int len)
 {
        void __iomem *a = __isamem_convert_addr(addr);
 
@@ -122,7 +122,7 @@ void readsl(const void __iomem *addr, void *data, int len)
 }
 EXPORT_SYMBOL(readsl);
 
-void __writeb(u8 val, void __iomem *addr)
+void __writeb(u8 val, volatile void __iomem *addr)
 {
        void __iomem *a = __isamem_convert_addr(addr);
 
@@ -132,7 +132,7 @@ void __writeb(u8 val, void __iomem *addr)
                __raw_writeb(val, a);
 }
 
-void __writew(u16 val, void __iomem *addr)
+void __writew(u16 val, volatile void __iomem *addr)
 {
        void __iomem *a = __isamem_convert_addr(addr);
 
@@ -142,7 +142,7 @@ void __writew(u16 val, void __iomem *addr)
        __raw_writew(val, a);
 }
 
-void __writel(u32 val, void __iomem *addr)
+void __writel(u32 val, volatile void __iomem *addr)
 {
        void __iomem *a = __isamem_convert_addr(addr);
 
@@ -157,7 +157,7 @@ EXPORT_SYMBOL(__writeb);
 EXPORT_SYMBOL(__writew);
 EXPORT_SYMBOL(__writel);
 
-void writesw(void __iomem *addr, const void *data, int len)
+void writesw(volatile void __iomem *addr, const void *data, int len)
 {
        void __iomem *a = __isamem_convert_addr(addr);
 
@@ -167,7 +167,7 @@ void writesw(void __iomem *addr, const void *data, int len)
 }
 EXPORT_SYMBOL(writesw);
 
-void writesl(void __iomem *addr, const void *data, int len)
+void writesl(volatile void __iomem *addr, const void *data, int len)
 {
        void __iomem *a = __isamem_convert_addr(addr);
 
index d8bfd02f5047f732af84cae4483bd57be12edeb0..88a4c9b089a559c07d6d0d6c2e7159438d036351 100644 (file)
@@ -66,11 +66,15 @@ static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
        .num_channels           = ARRAY_SIZE(ep93xx_dma_m2p_channels),
 };
 
+static u64 ep93xx_dma_m2p_mask = DMA_BIT_MASK(32);
+
 static struct platform_device ep93xx_dma_m2p_device = {
        .name                   = "ep93xx-dma-m2p",
        .id                     = -1,
        .dev                    = {
-               .platform_data  = &ep93xx_dma_m2p_data,
+               .platform_data          = &ep93xx_dma_m2p_data,
+               .dma_mask               = &ep93xx_dma_m2p_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
 };
 
@@ -93,11 +97,15 @@ static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
        .num_channels           = ARRAY_SIZE(ep93xx_dma_m2m_channels),
 };
 
+static u64 ep93xx_dma_m2m_mask = DMA_BIT_MASK(32);
+
 static struct platform_device ep93xx_dma_m2m_device = {
        .name                   = "ep93xx-dma-m2m",
        .id                     = -1,
        .dev                    = {
-               .platform_data  = &ep93xx_dma_m2m_data,
+               .platform_data          = &ep93xx_dma_m2m_data,
+               .dma_mask               = &ep93xx_dma_m2m_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
 };
 
index 2d0240f241b8bf0d2b8b87383f82e448f4cea8d3..b9e3f1c61bafe1bb3bee2b350e488779ab41838b 100644 (file)
@@ -24,6 +24,7 @@ menuconfig ARCH_EXYNOS
        select PM_GENERIC_DOMAINS if PM_RUNTIME
        select S5P_DEV_MFC
        select SRAM
+       select MFD_SYSCON
        help
          Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5)
 
@@ -75,6 +76,11 @@ config SOC_EXYNOS4412
        default y
        depends on ARCH_EXYNOS4
 
+config SOC_EXYNOS4415
+       bool "SAMSUNG EXYNOS4415"
+       default y
+       depends on ARCH_EXYNOS4
+
 config SOC_EXYNOS5250
        bool "SAMSUNG EXYNOS5250"
        default y
@@ -123,4 +129,9 @@ config EXYNOS5420_MCPM
          This is needed to provide CPU and cluster power management
          on Exynos5420 implementing big.LITTLE.
 
+config EXYNOS_CPU_SUSPEND
+       bool
+       select ARM_CPU_SUSPEND
+       default PM_SLEEP || ARM_EXYNOS_CPUIDLE
+
 endif
index 27ae6144679c6a369087420836bf7210b728f116..bcefb5473ee42540b409ba6824d38730c83c2620 100644 (file)
@@ -11,16 +11,15 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)
 
 obj-$(CONFIG_ARCH_EXYNOS)      += exynos.o pmu.o exynos-smc.o firmware.o
 
-obj-$(CONFIG_PM_SLEEP)         += pm.o sleep.o
+obj-$(CONFIG_EXYNOS_CPU_SUSPEND) += pm.o sleep.o
+obj-$(CONFIG_PM_SLEEP)         += suspend.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
 
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
 
-obj-$(CONFIG_HOTPLUG_CPU)      += hotplug.o
-CFLAGS_hotplug.o               += -march=armv7-a
-
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_exynos-smc.o            :=-Wa,-march=armv7-a$(plus_sec)
+AFLAGS_sleep.o                 :=-Wa,-march=armv7-a$(plus_sec)
 
 obj-$(CONFIG_EXYNOS5420_MCPM)  += mcpm-exynos.o
 CFLAGS_mcpm-exynos.o           += -march=armv7-a
index 47b904b3b9732ecdfd728ddb763c9850fed6744e..865f878063cc12d1b614d1874dbf74bed24681f4 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
-#include <linux/reboot.h>
 #include <linux/of.h>
 
 #define EXYNOS3250_SOC_ID      0xE3472000
@@ -111,11 +110,19 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
 #define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
                          soc_is_exynos5420() || soc_is_exynos5800())
 
+extern u32 cp15_save_diag;
+extern u32 cp15_save_power;
+
 extern void __iomem *sysram_ns_base_addr;
 extern void __iomem *sysram_base_addr;
 extern void __iomem *pmu_base_addr;
 void exynos_sysram_init(void);
 
+enum {
+       FW_DO_IDLE_SLEEP,
+       FW_DO_IDLE_AFTR,
+};
+
 void exynos_firmware_init(void);
 
 extern u32 exynos_get_eint_wake_mask(void);
@@ -127,34 +134,20 @@ static inline void exynos_pm_init(void) {}
 #endif
 
 extern void exynos_cpu_resume(void);
+extern void exynos_cpu_resume_ns(void);
 
 extern struct smp_operations exynos_smp_ops;
 
-extern void exynos_cpu_die(unsigned int cpu);
-
-/* PMU(Power Management Unit) support */
-
-#define PMU_TABLE_END  (-1U)
-
-enum sys_powerdown {
-       SYS_AFTR,
-       SYS_LPA,
-       SYS_SLEEP,
-       NUM_SYS_POWERDOWN,
-};
-
-struct exynos_pmu_conf {
-       unsigned int offset;
-       unsigned int val[NUM_SYS_POWERDOWN];
-};
-
-extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
 extern void exynos_cpu_power_down(int cpu);
 extern void exynos_cpu_power_up(int cpu);
 extern int  exynos_cpu_power_state(int cpu);
 extern void exynos_cluster_power_down(int cluster);
 extern void exynos_cluster_power_up(int cluster);
 extern int  exynos_cluster_power_state(int cluster);
+extern void exynos_cpu_save_register(void);
+extern void exynos_cpu_restore_register(void);
+extern void exynos_pm_central_suspend(void);
+extern int exynos_pm_central_resume(void);
 extern void exynos_enter_aftr(void);
 
 extern void s5p_init_cpu(void __iomem *cpuid_addr);
diff --git a/arch/arm/mach-exynos/exynos-pmu.h b/arch/arm/mach-exynos/exynos-pmu.h
new file mode 100644 (file)
index 0000000..a2ab0d5
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Header for EXYNOS PMU Driver support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __EXYNOS_PMU_H
+#define __EXYNOS_PMU_H
+
+enum sys_powerdown {
+       SYS_AFTR,
+       SYS_LPA,
+       SYS_SLEEP,
+       NUM_SYS_POWERDOWN,
+};
+
+extern void exynos_sys_powerdown_conf(enum sys_powerdown mode);
+
+#endif /* __EXYNOS_PMU_H */
index 6b283eb3202ec2ecac7e7742e82ab284f38c808c..c13d0837fa8cd3b5325c84e031416098b4c90fea 100644 (file)
@@ -40,41 +40,11 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSCON),
                .length         = SZ_64K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_TIMER,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_TIMER),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_WATCHDOG,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_SROMC,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_SROMC),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_SYSTIMER,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_COMBINER_BASE,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_COMBINER),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_GIC_CPU,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
-               .length         = SZ_64K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_GIC_DIST,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
-               .length         = SZ_64K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_CMU,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_CMU),
@@ -85,11 +55,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS4_PA_COREPERI),
                .length         = SZ_8K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_L2CC,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_L2CC),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_DMC0,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_DMC0),
@@ -100,11 +65,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS4_PA_DMC1),
                .length         = SZ_64K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_USB_HSPHY,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_HSPHY),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
        },
 };
 
@@ -114,16 +74,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSCON),
                .length         = SZ_64K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_TIMER,
-               .pfn            = __phys_to_pfn(EXYNOS5_PA_TIMER),
-               .length         = SZ_16K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S3C_VA_WATCHDOG,
-               .pfn            = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_SROMC,
                .pfn            = __phys_to_pfn(EXYNOS5_PA_SROMC),
@@ -137,28 +87,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
        },
 };
 
-static void exynos_restart(enum reboot_mode mode, const char *cmd)
-{
-       struct device_node *np;
-       u32 val = 0x1;
-       void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
-
-       if (of_machine_is_compatible("samsung,exynos5440")) {
-               u32 status;
-               np = of_find_compatible_node(NULL, NULL, "samsung,exynos5440-clock");
-
-               addr = of_iomap(np, 0) + 0xbc;
-               status = __raw_readl(addr);
-
-               addr = of_iomap(np, 0) + 0xcc;
-               val = __raw_readl(addr);
-
-               val = (val & 0xffff0000) | (status & 0xffff);
-       }
-
-       __raw_writel(val, addr);
-}
-
 static struct platform_device exynos_cpuidle = {
        .name              = "exynos_cpuidle",
 #ifdef CONFIG_ARM_EXYNOS_CPUIDLE
@@ -252,6 +180,7 @@ static const struct of_device_id exynos_dt_pmu_match[] = {
        { .compatible = "samsung,exynos4210-pmu" },
        { .compatible = "samsung,exynos4212-pmu" },
        { .compatible = "samsung,exynos4412-pmu" },
+       { .compatible = "samsung,exynos4415-pmu" },
        { .compatible = "samsung,exynos5250-pmu" },
        { .compatible = "samsung,exynos5260-pmu" },
        { .compatible = "samsung,exynos5410-pmu" },
@@ -318,7 +247,10 @@ static void __init exynos_dt_machine_init(void)
                exynos_sysram_init();
 
        if (of_machine_is_compatible("samsung,exynos4210") ||
-                       of_machine_is_compatible("samsung,exynos5250"))
+           of_machine_is_compatible("samsung,exynos4212") ||
+           (of_machine_is_compatible("samsung,exynos4412") &&
+            of_machine_is_compatible("samsung,trats2")) ||
+           of_machine_is_compatible("samsung,exynos5250"))
                platform_device_register(&exynos_cpuidle);
 
        platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
@@ -333,6 +265,7 @@ static char const *exynos_dt_compat[] __initconst = {
        "samsung,exynos4210",
        "samsung,exynos4212",
        "samsung,exynos4412",
+       "samsung,exynos4415",
        "samsung,exynos5",
        "samsung,exynos5250",
        "samsung,exynos5260",
@@ -378,7 +311,6 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
        .init_machine   = exynos_dt_machine_init,
        .init_late      = exynos_init_late,
        .dt_compat      = exynos_dt_compat,
-       .restart        = exynos_restart,
        .reserve        = exynos_reserve,
        .dt_fixup       = exynos_dt_fixup,
 MACHINE_END
index e8797bb788715ac68462250ecef539bde885d9e0..766f57d2f029acab61a908050a9c190dd1357b52 100644 (file)
 #include <linux/of.h>
 #include <linux/of_address.h>
 
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
 #include <asm/firmware.h>
+#include <asm/suspend.h>
 
 #include <mach/map.h>
 
 #include "common.h"
 #include "smc.h"
 
-static int exynos_do_idle(void)
+#define EXYNOS_SLEEP_MAGIC     0x00000bad
+#define EXYNOS_AFTR_MAGIC      0xfcba0d10
+#define EXYNOS_BOOT_ADDR       0x8
+#define EXYNOS_BOOT_FLAG       0xc
+
+static void exynos_save_cp15(void)
 {
-       exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
+       /* Save Power control and Diagnostic registers */
+       asm ("mrc p15, 0, %0, c15, c0, 0\n"
+            "mrc p15, 0, %1, c15, c0, 1\n"
+            : "=r" (cp15_save_power), "=r" (cp15_save_diag)
+            : : "cc");
+}
+
+static int exynos_do_idle(unsigned long mode)
+{
+       switch (mode) {
+       case FW_DO_IDLE_AFTR:
+               if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
+                       exynos_save_cp15();
+               __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);
+               break;
+       case FW_DO_IDLE_SLEEP:
+               exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
+       }
        return 0;
 }
 
@@ -69,10 +97,43 @@ static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
        return 0;
 }
 
+static int exynos_cpu_suspend(unsigned long arg)
+{
+       flush_cache_all();
+       outer_flush_all();
+
+       exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
+
+       pr_info("Failed to suspend the system\n");
+       writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
+       return 1;
+}
+
+static int exynos_suspend(void)
+{
+       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
+               exynos_save_cp15();
+
+       writel(EXYNOS_SLEEP_MAGIC, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
+       writel(virt_to_phys(exynos_cpu_resume_ns),
+               sysram_ns_base_addr + EXYNOS_BOOT_ADDR);
+
+       return cpu_suspend(0, exynos_cpu_suspend);
+}
+
+static int exynos_resume(void)
+{
+       writel(0, sysram_ns_base_addr + EXYNOS_BOOT_FLAG);
+
+       return 0;
+}
+
 static const struct firmware_ops exynos_firmware_ops = {
-       .do_idle                = exynos_do_idle,
+       .do_idle                = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_do_idle : NULL,
        .set_cpu_boot_addr      = exynos_set_cpu_boot_addr,
        .cpu_boot               = exynos_cpu_boot,
+       .suspend                = IS_ENABLED(CONFIG_PM_SLEEP) ? exynos_suspend : NULL,
+       .resume                 = IS_ENABLED(CONFIG_EXYNOS_CPU_SUSPEND) ? exynos_resume : NULL,
 };
 
 void __init exynos_firmware_init(void)
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
deleted file mode 100644 (file)
index 4d86961..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  Cloned from linux/arch/arm/mach-realview/hotplug.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  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.
-*/
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-#include <asm/cp15.h>
-#include <asm/smp_plat.h>
-
-#include "common.h"
-#include "regs-pmu.h"
-
-static inline void cpu_leave_lowpower(void)
-{
-       unsigned int v;
-
-       asm volatile(
-       "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, %1\n"
-       "       mcr     p15, 0, %0, c1, c0, 0\n"
-       "       mrc     p15, 0, %0, c1, c0, 1\n"
-       "       orr     %0, %0, %2\n"
-       "       mcr     p15, 0, %0, c1, c0, 1\n"
-         : "=&r" (v)
-         : "Ir" (CR_C), "Ir" (0x40)
-         : "cc");
-}
-
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
-{
-       u32 mpidr = cpu_logical_map(cpu);
-       u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-
-       for (;;) {
-
-               /* Turn the CPU off on next WFI instruction. */
-               exynos_cpu_power_down(core_id);
-
-               wfi();
-
-               if (pen_release == core_id) {
-                       /*
-                        * OK, proper wakeup, we're done
-                        */
-                       break;
-               }
-
-               /*
-                * Getting here, means that we have come out of WFI without
-                * having been woken up - this shouldn't happen
-                *
-                * Just note it happening - when we're woken, we can report
-                * its occurrence.
-                */
-               (*spurious)++;
-       }
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void __ref exynos_cpu_die(unsigned int cpu)
-{
-       int spurious = 0;
-
-       v7_exit_coherency_flush(louis);
-
-       platform_do_lowpower(cpu, &spurious);
-
-       /*
-        * bring this CPU back into the world of cache
-        * coherency, and then restore interrupts
-        */
-       cpu_leave_lowpower();
-
-       if (spurious)
-               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
-}
index f0b7e92bad6cf665bb42c292fbeed797527736ee..1ad3f496ef566ec060349762280a1d054200e93e 100644 (file)
 #define EXYNOS4_PA_CMU                 0x10030000
 #define EXYNOS5_PA_CMU                 0x10010000
 
-#define EXYNOS4_PA_SYSTIMER            0x10050000
-
-#define EXYNOS4_PA_WATCHDOG            0x10060000
-#define EXYNOS5_PA_WATCHDOG            0x101D0000
-
 #define EXYNOS4_PA_DMC0                        0x10400000
 #define EXYNOS4_PA_DMC1                        0x10410000
 
-#define EXYNOS4_PA_COMBINER            0x10440000
-#define EXYNOS5_PA_COMBINER            0x10440000
-
-#define EXYNOS4_PA_GIC_CPU             0x10480000
-#define EXYNOS4_PA_GIC_DIST            0x10490000
-#define EXYNOS5_PA_GIC_CPU             0x10482000
-#define EXYNOS5_PA_GIC_DIST            0x10481000
-
 #define EXYNOS4_PA_COREPERI            0x10500000
 #define EXYNOS4_PA_L2CC                        0x10502000
 
 #define EXYNOS4_PA_SROMC               0x12570000
 #define EXYNOS5_PA_SROMC               0x12250000
 
-#define EXYNOS4_PA_HSPHY               0x125B0000
-
-#define EXYNOS4_PA_UART                        0x13800000
-#define EXYNOS5_PA_UART                        0x12C00000
-
-#define EXYNOS4_PA_TIMER               0x139D0000
-#define EXYNOS5_PA_TIMER               0x12DD0000
-
 /* Compatibility UART */
 
 #define EXYNOS5440_PA_UART0            0x000B0000
 
-#define S3C_VA_UARTx(x)                        (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-
 #endif /* __ASM_ARCH_MAP_H */
index dc9a764a7c371d9b1ad5f27e14038cdbeca8690f..b0d3c2e876fbe9227d651b8c2bcc86de22fc0fc7 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/cputype.h>
 #include <asm/cp15.h>
@@ -30,6 +31,8 @@
 #define EXYNOS5420_USE_ARM_CORE_DOWN_STATE     BIT(29)
 #define EXYNOS5420_USE_L2_COMMON_UP_STATE      BIT(30)
 
+static void __iomem *ns_sram_base_addr;
+
 /*
  * The common v7_exit_coherency_flush API could not be used because of the
  * Erratum 799270 workaround. This macro is the same as the common one (in
@@ -318,10 +321,26 @@ static const struct of_device_id exynos_dt_mcpm_match[] = {
        {},
 };
 
+static void exynos_mcpm_setup_entry_point(void)
+{
+       /*
+        * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
+        * as part of secondary_cpu_start().  Let's redirect it to the
+        * mcpm_entry_point(). This is done during both secondary boot-up as
+        * well as system resume.
+        */
+       __raw_writel(0xe59f0000, ns_sram_base_addr);     /* ldr r0, [pc, #0] */
+       __raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx  r0 */
+       __raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
+}
+
+static struct syscore_ops exynos_mcpm_syscore_ops = {
+       .resume = exynos_mcpm_setup_entry_point,
+};
+
 static int __init exynos_mcpm_init(void)
 {
        struct device_node *node;
-       void __iomem *ns_sram_base_addr;
        unsigned int value, i;
        int ret;
 
@@ -387,16 +406,9 @@ static int __init exynos_mcpm_init(void)
                pmu_raw_writel(value, EXYNOS_COMMON_OPTION(i));
        }
 
-       /*
-        * U-Boot SPL is hardcoded to jump to the start of ns_sram_base_addr
-        * as part of secondary_cpu_start().  Let's redirect it to the
-        * mcpm_entry_point().
-        */
-       __raw_writel(0xe59f0000, ns_sram_base_addr);     /* ldr r0, [pc, #0] */
-       __raw_writel(0xe12fff10, ns_sram_base_addr + 4); /* bx  r0 */
-       __raw_writel(virt_to_phys(mcpm_entry_point), ns_sram_base_addr + 8);
+       exynos_mcpm_setup_entry_point();
 
-       iounmap(ns_sram_base_addr);
+       register_syscore_ops(&exynos_mcpm_syscore_ops);
 
        return ret;
 }
index 41ae28d69e6f7e2012fe86d006e6d8151f26927d..7a1ebfeeeeb8cf01ffff3494b0162db36c91d7af 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/firmware.h>
 
 extern void exynos4_secondary_startup(void);
 
+/*
+ * Set or clear the USE_DELAYED_RESET_ASSERTION option, set on Exynos4 SoCs
+ * during hot-(un)plugging CPUx.
+ *
+ * The feature can be cleared safely during first boot of secondary CPU.
+ *
+ * Exynos4 SoCs require setting USE_DELAYED_RESET_ASSERTION during powering
+ * down a CPU so the CPU idle clock down feature could properly detect global
+ * idle state when CPUx is off.
+ */
+static void exynos_set_delayed_reset_assertion(u32 core_id, bool enable)
+{
+       if (soc_is_exynos4()) {
+               unsigned int tmp;
+
+               tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
+               if (enable)
+                       tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
+               else
+                       tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
+               pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
+       }
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static inline void cpu_leave_lowpower(u32 core_id)
+{
+       unsigned int v;
+
+       asm volatile(
+       "mrc    p15, 0, %0, c1, c0, 0\n"
+       "       orr     %0, %0, %1\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       orr     %0, %0, %2\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+         : "=&r" (v)
+         : "Ir" (CR_C), "Ir" (0x40)
+         : "cc");
+
+        exynos_set_delayed_reset_assertion(core_id, false);
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+       u32 mpidr = cpu_logical_map(cpu);
+       u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+
+       for (;;) {
+
+               /* Turn the CPU off on next WFI instruction. */
+               exynos_cpu_power_down(core_id);
+
+               /*
+                * Exynos4 SoCs require setting
+                * USE_DELAYED_RESET_ASSERTION so the CPU idle
+                * clock down feature could properly detect
+                * global idle state when CPUx is off.
+                */
+               exynos_set_delayed_reset_assertion(core_id, true);
+
+               wfi();
+
+               if (pen_release == core_id) {
+                       /*
+                        * OK, proper wakeup, we're done
+                        */
+                       break;
+               }
+
+               /*
+                * Getting here, means that we have come out of WFI without
+                * having been woken up - this shouldn't happen
+                *
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
+                */
+               (*spurious)++;
+       }
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 /**
  * exynos_core_power_down : power down the specified cpu
  * @cpu : the cpu to power down
@@ -43,6 +126,18 @@ extern void exynos4_secondary_startup(void);
  */
 void exynos_cpu_power_down(int cpu)
 {
+       if (cpu == 0 && (of_machine_is_compatible("samsung,exynos5420") ||
+               of_machine_is_compatible("samsung,exynos5800"))) {
+               /*
+                * Bypass power down for CPU0 during suspend. Check for
+                * the SYS_PWR_REG value to decide if we are suspending
+                * the system.
+                */
+               int val = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
+
+               if (!(val & S5P_CORE_LOCAL_PWR_EN))
+                       return;
+       }
        pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
 }
 
@@ -120,6 +215,26 @@ static inline void __iomem *cpu_boot_reg(int cpu)
        return boot_reg;
 }
 
+/*
+ * Set wake up by local power mode and execute software reset for given core.
+ *
+ * Currently this is needed only when booting secondary CPU on Exynos3250.
+ */
+static void exynos_core_restart(u32 core_id)
+{
+       u32 val;
+
+       if (!of_machine_is_compatible("samsung,exynos3250"))
+               return;
+
+       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));
+
+       pr_info("CPU%u: Software reset\n", core_id);
+       pmu_raw_writel(EXYNOS_CORE_PO_RESET(core_id), EXYNOS_SWRESET);
+}
+
 /*
  * Write pen_release in a way that is guaranteed to be visible to all
  * observers, irrespective of whether they're taking part in coherency
@@ -196,6 +311,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
                        return -ETIMEDOUT;
                }
        }
+
+       exynos_core_restart(core_id);
+
        /*
         * Send the secondary CPU a soft interrupt, thereby causing
         * the boot monitor to read the system wide flags register,
@@ -237,6 +355,9 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
                udelay(10);
        }
 
+       /* No harm if this is called during first boot of secondary CPU */
+       exynos_set_delayed_reset_assertion(core_id, false);
+
        /*
         * now the secondary core is starting up let it run its
         * calibrations, then wait for it to finish
@@ -318,6 +439,33 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
        }
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+static void exynos_cpu_die(unsigned int cpu)
+{
+       int spurious = 0;
+       u32 mpidr = cpu_logical_map(cpu);
+       u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+
+       v7_exit_coherency_flush(louis);
+
+       platform_do_lowpower(cpu, &spurious);
+
+       /*
+        * bring this CPU back into the world of cache
+        * coherency, and then restore interrupts
+        */
+       cpu_leave_lowpower(core_id);
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 struct smp_operations exynos_smp_ops __initdata = {
        .smp_init_cpus          = exynos_smp_init_cpus,
        .smp_prepare_cpus       = exynos_smp_prepare_cpus,
index abefacb45976a7b466b47c7271c212fd46275383..86f3ecd88f78f92c492e23b2043902b290f2dc2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
  * EXYNOS - Power Management support
 
 #include <linux/init.h>
 #include <linux/suspend.h>
-#include <linux/syscore_ops.h>
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 
-#include <asm/cacheflush.h>
-#include <asm/hardware/cache-l2x0.h>
+#include <asm/firmware.h>
 #include <asm/smp_scu.h>
 #include <asm/suspend.h>
 
 #include <plat/pm-common.h>
-#include <plat/regs-srom.h>
-
-#include <mach/map.h>
 
 #include "common.h"
+#include "exynos-pmu.h"
 #include "regs-pmu.h"
 #include "regs-sys.h"
 
-/**
- * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
- * @hwirq: Hardware IRQ signal of the GIC
- * @mask: Mask in PMU wake-up mask register
- */
-struct exynos_wkup_irq {
-       unsigned int hwirq;
-       u32 mask;
-};
-
-static struct sleep_save exynos5_sys_save[] = {
-       SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
-};
-
-static struct sleep_save exynos_core_save[] = {
-       /* SROM side */
-       SAVE_ITEM(S5P_SROM_BW),
-       SAVE_ITEM(S5P_SROM_BC0),
-       SAVE_ITEM(S5P_SROM_BC1),
-       SAVE_ITEM(S5P_SROM_BC2),
-       SAVE_ITEM(S5P_SROM_BC3),
-};
-
-/*
- * GIC wake-up support
- */
-
-static u32 exynos_irqwake_intmask = 0xffffffff;
-
-static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
-       { 76, BIT(1) }, /* RTC alarm */
-       { 77, BIT(2) }, /* RTC tick */
-       { /* sentinel */ },
-};
-
-static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
-       { 75, BIT(1) }, /* RTC alarm */
-       { 76, BIT(2) }, /* RTC tick */
-       { /* sentinel */ },
-};
-
-static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
+static inline void __iomem *exynos_boot_vector_addr(void)
 {
-       const struct exynos_wkup_irq *wkup_irq;
-
-       if (soc_is_exynos5250())
-               wkup_irq = exynos5250_wkup_irq;
-       else
-               wkup_irq = exynos4_wkup_irq;
-
-       while (wkup_irq->mask) {
-               if (wkup_irq->hwirq == data->hwirq) {
-                       if (!state)
-                               exynos_irqwake_intmask |= wkup_irq->mask;
-                       else
-                               exynos_irqwake_intmask &= ~wkup_irq->mask;
-                       return 0;
-               }
-               ++wkup_irq;
-       }
-
-       return -ENOENT;
+       if (samsung_rev() == EXYNOS4210_REV_1_1)
+               return pmu_base_addr + S5P_INFORM7;
+       else if (samsung_rev() == EXYNOS4210_REV_1_0)
+               return sysram_base_addr + 0x24;
+       return pmu_base_addr + S5P_INFORM0;
 }
 
-#define EXYNOS_BOOT_VECTOR_ADDR        (samsung_rev() == EXYNOS4210_REV_1_1 ? \
-                       pmu_base_addr + S5P_INFORM7 : \
-                       (samsung_rev() == EXYNOS4210_REV_1_0 ? \
-                       (sysram_base_addr + 0x24) : \
-                       pmu_base_addr + S5P_INFORM0))
-#define EXYNOS_BOOT_VECTOR_FLAG        (samsung_rev() == EXYNOS4210_REV_1_1 ? \
-                       pmu_base_addr + S5P_INFORM6 : \
-                       (samsung_rev() == EXYNOS4210_REV_1_0 ? \
-                       (sysram_base_addr + 0x20) : \
-                       pmu_base_addr + S5P_INFORM1))
+static inline void __iomem *exynos_boot_vector_flag(void)
+{
+       if (samsung_rev() == EXYNOS4210_REV_1_1)
+               return pmu_base_addr + S5P_INFORM6;
+       else if (samsung_rev() == EXYNOS4210_REV_1_0)
+               return sysram_base_addr + 0x20;
+       return pmu_base_addr + S5P_INFORM1;
+}
 
 #define S5P_CHECK_AFTR  0xFCBA0D10
-#define S5P_CHECK_SLEEP 0x00000BAD
 
 /* For Cortex-A9 Diagnostic and Power control register */
 static unsigned int save_arm_register[2];
 
-static void exynos_cpu_save_register(void)
+void exynos_cpu_save_register(void)
 {
        unsigned long tmp;
 
@@ -134,7 +70,7 @@ static void exynos_cpu_save_register(void)
        save_arm_register[1] = tmp;
 }
 
-static void exynos_cpu_restore_register(void)
+void exynos_cpu_restore_register(void)
 {
        unsigned long tmp;
 
@@ -153,7 +89,7 @@ static void exynos_cpu_restore_register(void)
                      : "cc");
 }
 
-static void exynos_pm_central_suspend(void)
+void exynos_pm_central_suspend(void)
 {
        unsigned long tmp;
 
@@ -161,9 +97,13 @@ static void exynos_pm_central_suspend(void)
        tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
        tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
        pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+       /* Setting SEQ_OPTION register */
+       pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
+                      S5P_CENTRAL_SEQ_OPTION);
 }
 
-static int exynos_pm_central_resume(void)
+int exynos_pm_central_resume(void)
 {
        unsigned long tmp;
 
@@ -194,17 +134,26 @@ static void exynos_set_wakeupmask(long mask)
 
 static void exynos_cpu_set_boot_vector(long flags)
 {
-       __raw_writel(virt_to_phys(exynos_cpu_resume), EXYNOS_BOOT_VECTOR_ADDR);
-       __raw_writel(flags, EXYNOS_BOOT_VECTOR_FLAG);
+       __raw_writel(virt_to_phys(exynos_cpu_resume),
+                    exynos_boot_vector_addr());
+       __raw_writel(flags, exynos_boot_vector_flag());
 }
 
 static int exynos_aftr_finisher(unsigned long flags)
 {
+       int ret;
+
        exynos_set_wakeupmask(0x0000ff3e);
-       exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
        /* Set value of power down register for aftr mode */
        exynos_sys_powerdown_conf(SYS_AFTR);
-       cpu_do_idle();
+
+       ret = call_firmware_op(do_idle, FW_DO_IDLE_AFTR);
+       if (ret == -ENOSYS) {
+               if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
+                       exynos_cpu_save_register();
+               exynos_cpu_set_boot_vector(S5P_CHECK_AFTR);
+               cpu_do_idle();
+       }
 
        return 1;
 }
@@ -214,196 +163,16 @@ void exynos_enter_aftr(void)
        cpu_pm_enter();
 
        exynos_pm_central_suspend();
-       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
-               exynos_cpu_save_register();
 
        cpu_suspend(0, exynos_aftr_finisher);
 
        if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
                scu_enable(S5P_VA_SCU);
-               exynos_cpu_restore_register();
+               if (call_firmware_op(resume) == -ENOSYS)
+                       exynos_cpu_restore_register();
        }
 
        exynos_pm_central_resume();
 
        cpu_pm_exit();
 }
-
-static int exynos_cpu_suspend(unsigned long arg)
-{
-#ifdef CONFIG_CACHE_L2X0
-       outer_flush_all();
-#endif
-
-       if (soc_is_exynos5250())
-               flush_cache_all();
-
-       /* issue the standby signal into the pm unit. */
-       cpu_do_idle();
-
-       pr_info("Failed to suspend the system\n");
-       return 1; /* Aborting suspend */
-}
-
-static void exynos_pm_prepare(void)
-{
-       unsigned int tmp;
-
-       /* Set wake-up mask registers */
-       pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
-       pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
-
-       s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
-       if (soc_is_exynos5250()) {
-               s3c_pm_do_save(exynos5_sys_save, ARRAY_SIZE(exynos5_sys_save));
-               /* Disable USE_RETENTION of JPEG_MEM_OPTION */
-               tmp = pmu_raw_readl(EXYNOS5_JPEG_MEM_OPTION);
-               tmp &= ~EXYNOS5_OPTION_USE_RETENTION;
-               pmu_raw_writel(tmp, EXYNOS5_JPEG_MEM_OPTION);
-       }
-
-       /* Set value of power down register for sleep mode */
-
-       exynos_sys_powerdown_conf(SYS_SLEEP);
-       pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
-
-       /* ensure at least INFORM0 has the resume address */
-
-       pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
-}
-
-static int exynos_pm_suspend(void)
-{
-       unsigned long tmp;
-
-       exynos_pm_central_suspend();
-
-       /* Setting SEQ_OPTION register */
-
-       tmp = (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0);
-       pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
-
-       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
-               exynos_cpu_save_register();
-
-       return 0;
-}
-
-static void exynos_pm_resume(void)
-{
-       if (exynos_pm_central_resume())
-               goto early_wakeup;
-
-       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
-               exynos_cpu_restore_register();
-
-       /* For release retention */
-
-       pmu_raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
-       pmu_raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
-       pmu_raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
-       pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
-       pmu_raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
-       pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
-       pmu_raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
-
-       if (soc_is_exynos5250())
-               s3c_pm_do_restore(exynos5_sys_save,
-                       ARRAY_SIZE(exynos5_sys_save));
-
-       s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
-       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
-               scu_enable(S5P_VA_SCU);
-
-early_wakeup:
-
-       /* Clear SLEEP mode set in INFORM1 */
-       pmu_raw_writel(0x0, S5P_INFORM1);
-
-       return;
-}
-
-static struct syscore_ops exynos_pm_syscore_ops = {
-       .suspend        = exynos_pm_suspend,
-       .resume         = exynos_pm_resume,
-};
-
-/*
- * Suspend Ops
- */
-
-static int exynos_suspend_enter(suspend_state_t state)
-{
-       int ret;
-
-       s3c_pm_debug_init();
-
-       S3C_PMDBG("%s: suspending the system...\n", __func__);
-
-       S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
-                       exynos_irqwake_intmask, exynos_get_eint_wake_mask());
-
-       if (exynos_irqwake_intmask == -1U
-           && exynos_get_eint_wake_mask() == -1U) {
-               pr_err("%s: No wake-up sources!\n", __func__);
-               pr_err("%s: Aborting sleep\n", __func__);
-               return -EINVAL;
-       }
-
-       s3c_pm_save_uarts();
-       exynos_pm_prepare();
-       flush_cache_all();
-       s3c_pm_check_store();
-
-       ret = cpu_suspend(0, exynos_cpu_suspend);
-       if (ret)
-               return ret;
-
-       s3c_pm_restore_uarts();
-
-       S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
-                       pmu_raw_readl(S5P_WAKEUP_STAT));
-
-       s3c_pm_check_restore();
-
-       S3C_PMDBG("%s: resuming the system...\n", __func__);
-
-       return 0;
-}
-
-static int exynos_suspend_prepare(void)
-{
-       s3c_pm_check_prepare();
-
-       return 0;
-}
-
-static void exynos_suspend_finish(void)
-{
-       s3c_pm_check_cleanup();
-}
-
-static const struct platform_suspend_ops exynos_suspend_ops = {
-       .enter          = exynos_suspend_enter,
-       .prepare        = exynos_suspend_prepare,
-       .finish         = exynos_suspend_finish,
-       .valid          = suspend_valid_only_mem,
-};
-
-void __init exynos_pm_init(void)
-{
-       u32 tmp;
-
-       /* Platform-specific GIC callback */
-       gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
-
-       /* All wakeup disable */
-       tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
-       tmp |= ((0xFF << 8) | (0x1F << 1));
-       pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
-
-       register_syscore_ops(&exynos_pm_syscore_ops);
-       suspend_set_ops(&exynos_suspend_ops);
-}
index ff9d23f0a7d99676e2aba9a8b553e6cc2df779e2..c15761ca2f187faaca0a6950f67a681820040a89 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
  * EXYNOS - CPU PMU(Power Management Unit) support
  */
 
 #include <linux/io.h>
-#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
 
-#include "common.h"
+
+#include "exynos-pmu.h"
 #include "regs-pmu.h"
 
-static const struct exynos_pmu_conf *exynos_pmu_config;
+#define PMU_TABLE_END  (-1U)
+
+struct exynos_pmu_conf {
+       unsigned int offset;
+       u8 val[NUM_SYS_POWERDOWN];
+};
+
+struct exynos_pmu_data {
+       const struct exynos_pmu_conf *pmu_config;
+       const struct exynos_pmu_conf *pmu_config_extra;
+
+       void (*pmu_init)(void);
+       void (*powerdown_conf)(enum sys_powerdown);
+       void (*powerdown_conf_extra)(enum sys_powerdown);
+};
+
+struct exynos_pmu_context {
+       struct device *dev;
+       const struct exynos_pmu_data *pmu_data;
+};
+
+static void __iomem *pmu_base_addr;
+static struct exynos_pmu_context *pmu_context;
+
+static inline void pmu_raw_writel(u32 val, u32 offset)
+{
+       writel_relaxed(val, pmu_base_addr + offset);
+}
+
+static inline u32 pmu_raw_readl(u32 offset)
+{
+       return readl_relaxed(pmu_base_addr + offset);
+}
+
+static struct exynos_pmu_conf exynos3250_pmu_config[] = {
+       /* { .offset = offset, .val = { AFTR, W-AFTR, SLEEP } */
+       { EXYNOS3_ARM_CORE0_SYS_PWR_REG,                { 0x0, 0x0, 0x2} },
+       { EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG,  { 0x0, 0x0, 0x0} },
+       { EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
+       { EXYNOS3_ARM_CORE1_SYS_PWR_REG,                { 0x0, 0x0, 0x2} },
+       { EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG,  { 0x0, 0x0, 0x0} },
+       { EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
+       { EXYNOS3_ISP_ARM_SYS_PWR_REG,                  { 0x1, 0x0, 0x0} },
+       { EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG,    { 0x0, 0x0, 0x0} },
+       { EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG,  { 0x0, 0x0, 0x0} },
+       { EXYNOS3_ARM_COMMON_SYS_PWR_REG,               { 0x0, 0x0, 0x2} },
+       { EXYNOS3_ARM_L2_SYS_PWR_REG,                   { 0x0, 0x0, 0x3} },
+       { EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG,             { 0x1, 0x1, 0x0} },
+       { EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG,             { 0x1, 0x1, 0x0} },
+       { EXYNOS3_CMU_RESET_SYS_PWR_REG,                { 0x1, 0x1, 0x0} },
+       { EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG,           { 0x1, 0x1, 0x1} },
+       { EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG,            { 0x1, 0x1, 0x1} },
+       { EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG,       { 0x1, 0x1, 0x1} },
+       { EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG,     { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG,     { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG,        { 0x1, 0x1, 0x0} },
+       { EXYNOS3_APLL_SYSCLK_SYS_PWR_REG,              { 0x1, 0x0, 0x0} },
+       { EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG,              { 0x1, 0x0, 0x0} },
+       { EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG,              { 0x1, 0x0, 0x0} },
+       { EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG,              { 0x1, 0x1, 0x0} },
+       { EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG,              { 0x1, 0x0, 0x0} },
+       { EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG,              { 0x1, 0x1, 0x1} },
+       { EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG,         { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG,       { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG,           { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG,         { 0x1, 0x0, 0x0} },
+       { EXYNOS3_TOP_BUS_SYS_PWR_REG,                  { 0x3, 0x0, 0x0} },
+       { EXYNOS3_TOP_RETENTION_SYS_PWR_REG,            { 0x1, 0x1, 0x1} },
+       { EXYNOS3_TOP_PWR_SYS_PWR_REG,                  { 0x3, 0x3, 0x3} },
+       { EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG,          { 0x3, 0x0, 0x0} },
+       { EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG,    { 0x1, 0x1, 0x1} },
+       { EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG,          { 0x3, 0x3, 0x3} },
+       { EXYNOS3_LOGIC_RESET_SYS_PWR_REG,              { 0x1, 0x1, 0x0} },
+       { EXYNOS3_OSCCLK_GATE_SYS_PWR_REG,              { 0x1, 0x1, 0x1} },
+       { EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG,      { 0x1, 0x1, 0x0} },
+       { EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG,      { 0x1, 0x0, 0x1} },
+       { EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG,     { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG,        { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG,       { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_ISOLATION_SYS_PWR_REG,            { 0x1, 0x1, 0x0} },
+       { EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG,              { 0x1, 0x1, 0x0} },
+       { EXYNOS3_XUSBXTI_SYS_PWR_REG,                  { 0x1, 0x1, 0x0} },
+       { EXYNOS3_XXTI_SYS_PWR_REG,                     { 0x1, 0x1, 0x0} },
+       { EXYNOS3_EXT_REGULATOR_SYS_PWR_REG,            { 0x1, 0x1, 0x0} },
+       { EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG,    { 0x1, 0x1, 0x0} },
+       { EXYNOS3_GPIO_MODE_SYS_PWR_REG,                { 0x1, 0x1, 0x0} },
+       { EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG,         { 0x1, 0x1, 0x0} },
+       { EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG,            { 0x1, 0x1, 0x0} },
+       { EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG,        { 0x1, 0x1, 0x0} },
+       { EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG,    { 0x1, 0x1, 0x0} },
+       { EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG, { 0x1, 0x1, 0x0} },
+       { EXYNOS3_CAM_SYS_PWR_REG,                      { 0x7, 0x0, 0x0} },
+       { EXYNOS3_MFC_SYS_PWR_REG,                      { 0x7, 0x0, 0x0} },
+       { EXYNOS3_G3D_SYS_PWR_REG,                      { 0x7, 0x0, 0x0} },
+       { EXYNOS3_LCD0_SYS_PWR_REG,                     { 0x7, 0x0, 0x0} },
+       { EXYNOS3_ISP_SYS_PWR_REG,                      { 0x7, 0x0, 0x0} },
+       { EXYNOS3_MAUDIO_SYS_PWR_REG,                   { 0x7, 0x0, 0x0} },
+       { EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG,           { 0x1, 0x0, 0x0} },
+       { PMU_TABLE_END,},
+};
 
 static const struct exynos_pmu_conf exynos4210_pmu_config[] = {
        /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
@@ -264,6 +388,7 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
        { EXYNOS5_INTRAM_MEM_SYS_PWR_REG,               { 0x3, 0x0, 0x0} },
        { EXYNOS5_INTROM_MEM_SYS_PWR_REG,               { 0x3, 0x0, 0x0} },
        { EXYNOS5_JPEG_MEM_SYS_PWR_REG,                 { 0x3, 0x0, 0x0} },
+       { EXYNOS5_JPEG_MEM_OPTION,                      { 0x10, 0x10, 0x0} },
        { EXYNOS5_HSI_MEM_SYS_PWR_REG,                  { 0x3, 0x0, 0x0} },
        { EXYNOS5_MCUIOP_MEM_SYS_PWR_REG,               { 0x3, 0x0, 0x0} },
        { EXYNOS5_SATA_MEM_SYS_PWR_REG,                 { 0x3, 0x0, 0x0} },
@@ -315,6 +440,189 @@ static const struct exynos_pmu_conf exynos5250_pmu_config[] = {
        { PMU_TABLE_END,},
 };
 
+static struct exynos_pmu_conf exynos5420_pmu_config[] = {
+       /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
+       { EXYNOS5_ARM_CORE0_SYS_PWR_REG,                        { 0x0, 0x0, 0x0} },
+       { EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG,          { 0x0, 0x0, 0x0} },
+       { EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG,        { 0x0, 0x0, 0x0} },
+       { EXYNOS5_ARM_CORE1_SYS_PWR_REG,                        { 0x0, 0x0, 0x0} },
+       { EXYNOS5_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG,          { 0x0, 0x0, 0x0} },
+       { EXYNOS5_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG,        { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_ARM_CORE2_SYS_PWR_REG,                     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG,       { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG,     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_ARM_CORE3_SYS_PWR_REG,                     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG,       { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG,     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_KFC_CORE0_SYS_PWR_REG,                     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG,       { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG,     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_KFC_CORE1_SYS_PWR_REG,                     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG,       { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG,     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_KFC_CORE2_SYS_PWR_REG,                     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG,       { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG,     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_KFC_CORE3_SYS_PWR_REG,                     { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG,       { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG,     { 0x0, 0x0, 0x0} },
+       { EXYNOS5_ISP_ARM_SYS_PWR_REG,                          { 0x1, 0x0, 0x0} },
+       { EXYNOS5_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG,          { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_ARM_COMMON_SYS_PWR_REG,                    { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_KFC_COMMON_SYS_PWR_REG,                    { 0x0, 0x0, 0x0} },
+       { EXYNOS5_ARM_L2_SYS_PWR_REG,                           { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_KFC_L2_SYS_PWR_REG,                        { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_ACLKSTOP_SYS_PWR_REG,                     { 0x1, 0x0, 0x0} },
+       { EXYNOS5_CMU_SCLKSTOP_SYS_PWR_REG,                     { 0x1, 0x0, 0x1} },
+       { EXYNOS5_CMU_RESET_SYS_PWR_REG,                        { 0x1, 0x1, 0x0} },
+       { EXYNOS5_CMU_ACLKSTOP_SYSMEM_SYS_PWR_REG,              { 0x1, 0x0, 0x0} },
+       { EXYNOS5_CMU_SCLKSTOP_SYSMEM_SYS_PWR_REG,              { 0x1, 0x0, 0x1} },
+       { EXYNOS5_CMU_RESET_SYSMEM_SYS_PWR_REG,                 { 0x1, 0x1, 0x0} },
+       { EXYNOS5_DRAM_FREQ_DOWN_SYS_PWR_REG,                   { 0x1, 0x0, 0x1} },
+       { EXYNOS5_DDRPHY_DLLOFF_SYS_PWR_REG,                    { 0x1, 0x1, 0x1} },
+       { EXYNOS5_DDRPHY_DLLLOCK_SYS_PWR_REG,                   { 0x1, 0x0, 0x1} },
+       { EXYNOS5_APLL_SYSCLK_SYS_PWR_REG,                      { 0x1, 0x0, 0x0} },
+       { EXYNOS5_MPLL_SYSCLK_SYS_PWR_REG,                      { 0x1, 0x0, 0x0} },
+       { EXYNOS5_VPLL_SYSCLK_SYS_PWR_REG,                      { 0x1, 0x0, 0x0} },
+       { EXYNOS5_EPLL_SYSCLK_SYS_PWR_REG,                      { 0x1, 0x1, 0x0} },
+       { EXYNOS5_BPLL_SYSCLK_SYS_PWR_REG,                      { 0x1, 0x0, 0x0} },
+       { EXYNOS5_CPLL_SYSCLK_SYS_PWR_REG,                      { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG,                   { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG,                   { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG,                   { 0x1, 0x0, 0x0} },
+       { EXYNOS5_MPLLUSER_SYSCLK_SYS_PWR_REG,                  { 0x1, 0x0, 0x0} },
+       { EXYNOS5_BPLLUSER_SYSCLK_SYS_PWR_REG,                  { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG,                   { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG,                   { 0x1, 0x0, 0x0} },
+       { EXYNOS5_TOP_BUS_SYS_PWR_REG,                          { 0x3, 0x0, 0x0} },
+       { EXYNOS5_TOP_RETENTION_SYS_PWR_REG,                    { 0x1, 0x1, 0x1} },
+       { EXYNOS5_TOP_PWR_SYS_PWR_REG,                          { 0x3, 0x3, 0x0} },
+       { EXYNOS5_TOP_BUS_SYSMEM_SYS_PWR_REG,                   { 0x3, 0x0, 0x0} },
+       { EXYNOS5_TOP_RETENTION_SYSMEM_SYS_PWR_REG,             { 0x1, 0x0, 0x1} },
+       { EXYNOS5_TOP_PWR_SYSMEM_SYS_PWR_REG,                   { 0x3, 0x0, 0x0} },
+       { EXYNOS5_LOGIC_RESET_SYS_PWR_REG,                      { 0x1, 0x1, 0x0} },
+       { EXYNOS5_OSCCLK_GATE_SYS_PWR_REG,                      { 0x1, 0x0, 0x1} },
+       { EXYNOS5_LOGIC_RESET_SYSMEM_SYS_PWR_REG,               { 0x1, 0x0, 0x0} },
+       { EXYNOS5_OSCCLK_GATE_SYSMEM_SYS_PWR_REG,               { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_INTRAM_MEM_SYS_PWR_REG,                    { 0x3, 0x0, 0x3} },
+       { EXYNOS5420_INTROM_MEM_SYS_PWR_REG,                    { 0x3, 0x0, 0x3} },
+       { EXYNOS5_PAD_RETENTION_DRAM_SYS_PWR_REG,               { 0x1, 0x0, 0x0} },
+       { EXYNOS5_PAD_RETENTION_MAU_SYS_PWR_REG,                { 0x1, 0x1, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG,            { 0x1, 0x1, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG,             { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG,            { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG,             { 0x1, 0x0, 0x0} },
+       { EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG,    { 0x1, 0x0, 0x0} },
+       { EXYNOS5_PAD_ISOLATION_SYS_PWR_REG,                    { 0x1, 0x1, 0x0} },
+       { EXYNOS5_PAD_ISOLATION_SYSMEM_SYS_PWR_REG,             { 0x1, 0x0, 0x0} },
+       { EXYNOS5_PAD_ALV_SEL_SYS_PWR_REG,                      { 0x1, 0x0, 0x0} },
+       { EXYNOS5_XUSBXTI_SYS_PWR_REG,                          { 0x1, 0x1, 0x0} },
+       { EXYNOS5_XXTI_SYS_PWR_REG,                             { 0x1, 0x1, 0x0} },
+       { EXYNOS5_EXT_REGULATOR_SYS_PWR_REG,                    { 0x1, 0x1, 0x0} },
+       { EXYNOS5_GPIO_MODE_SYS_PWR_REG,                        { 0x1, 0x0, 0x0} },
+       { EXYNOS5_GPIO_MODE_SYSMEM_SYS_PWR_REG,                 { 0x1, 0x1, 0x0} },
+       { EXYNOS5_GPIO_MODE_MAU_SYS_PWR_REG,                    { 0x1, 0x1, 0x0} },
+       { EXYNOS5_TOP_ASB_RESET_SYS_PWR_REG,                    { 0x1, 0x1, 0x0} },
+       { EXYNOS5_TOP_ASB_ISOLATION_SYS_PWR_REG,                { 0x1, 0x0, 0x0} },
+       { EXYNOS5_GSCL_SYS_PWR_REG,                             { 0x7, 0x0, 0x0} },
+       { EXYNOS5_ISP_SYS_PWR_REG,                              { 0x7, 0x0, 0x0} },
+       { EXYNOS5_MFC_SYS_PWR_REG,                              { 0x7, 0x0, 0x0} },
+       { EXYNOS5_G3D_SYS_PWR_REG,                              { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_DISP1_SYS_PWR_REG,                         { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_MAU_SYS_PWR_REG,                           { 0x7, 0x7, 0x0} },
+       { EXYNOS5420_G2D_SYS_PWR_REG,                           { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_MSC_SYS_PWR_REG,                           { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_FSYS_SYS_PWR_REG,                          { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_FSYS2_SYS_PWR_REG,                         { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_PSGEN_SYS_PWR_REG,                         { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_PERIC_SYS_PWR_REG,                         { 0x7, 0x0, 0x0} },
+       { EXYNOS5420_WCORE_SYS_PWR_REG,                         { 0x7, 0x0, 0x0} },
+       { EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG,                 { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG,                  { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_CLKSTOP_MFC_SYS_PWR_REG,                  { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG,                  { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG,             { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG,              { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG,             { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG,             { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG,             { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG,                  { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG,                   { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_SYSCLK_MFC_SYS_PWR_REG,                   { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG,                   { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG,              { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG,                { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG,                { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG,                { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG,              { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG,              { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG,              { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG,              { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG,                   { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG,                    { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_RESET_MFC_SYS_PWR_REG,                    { 0x0, 0x0, 0x0} },
+       { EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG,                    { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG,               { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG,                 { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG,                 { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG,                 { 0x0, 0x0, 0x0} },
+       { EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG,                { 0x0, 0x0, 0x0} },
+       { PMU_TABLE_END,},
+};
+
+static unsigned int const exynos3250_list_feed[] = {
+       EXYNOS3_ARM_CORE_OPTION(0),
+       EXYNOS3_ARM_CORE_OPTION(1),
+       EXYNOS3_ARM_CORE_OPTION(2),
+       EXYNOS3_ARM_CORE_OPTION(3),
+       EXYNOS3_ARM_COMMON_OPTION,
+       EXYNOS3_TOP_PWR_OPTION,
+       EXYNOS3_CORE_TOP_PWR_OPTION,
+       S5P_CAM_OPTION,
+       S5P_MFC_OPTION,
+       S5P_G3D_OPTION,
+       S5P_LCD0_OPTION,
+       S5P_ISP_OPTION,
+};
+
+static void exynos3250_powerdown_conf_extra(enum sys_powerdown mode)
+{
+       unsigned int i;
+       unsigned int tmp;
+
+       /* Enable only SC_FEEDBACK */
+       for (i = 0; i < ARRAY_SIZE(exynos3250_list_feed); i++) {
+               tmp = pmu_raw_readl(exynos3250_list_feed[i]);
+               tmp &= ~(EXYNOS3_OPTION_USE_SC_COUNTER);
+               tmp |= EXYNOS3_OPTION_USE_SC_FEEDBACK;
+               pmu_raw_writel(tmp, exynos3250_list_feed[i]);
+       }
+
+       if (mode != SYS_SLEEP)
+               return;
+
+       pmu_raw_writel(XUSBXTI_DURATION, EXYNOS3_XUSBXTI_DURATION);
+       pmu_raw_writel(XXTI_DURATION, EXYNOS3_XXTI_DURATION);
+       pmu_raw_writel(EXT_REGULATOR_DURATION, EXYNOS3_EXT_REGULATOR_DURATION);
+       pmu_raw_writel(EXT_REGULATOR_COREBLK_DURATION,
+                      EXYNOS3_EXT_REGULATOR_COREBLK_DURATION);
+}
+
 static unsigned int const exynos5_list_both_cnt_feed[] = {
        EXYNOS5_ARM_CORE0_OPTION,
        EXYNOS5_ARM_CORE1_OPTION,
@@ -329,13 +637,82 @@ static unsigned int const exynos5_list_both_cnt_feed[] = {
        EXYNOS5_TOP_PWR_SYSMEM_OPTION,
 };
 
-static unsigned int const exynos5_list_diable_wfi_wfe[] = {
+static unsigned int const exynos5_list_disable_wfi_wfe[] = {
        EXYNOS5_ARM_CORE1_OPTION,
        EXYNOS5_FSYS_ARM_OPTION,
        EXYNOS5_ISP_ARM_OPTION,
 };
 
-static void exynos5_init_pmu(void)
+static unsigned int const exynos5420_list_disable_pmu_reg[] = {
+       EXYNOS5_CMU_CLKSTOP_GSCL_SYS_PWR_REG,
+       EXYNOS5_CMU_CLKSTOP_ISP_SYS_PWR_REG,
+       EXYNOS5_CMU_CLKSTOP_G3D_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG,
+       EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG,
+       EXYNOS5_CMU_SYSCLK_GSCL_SYS_PWR_REG,
+       EXYNOS5_CMU_SYSCLK_ISP_SYS_PWR_REG,
+       EXYNOS5_CMU_SYSCLK_G3D_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG,
+       EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG,
+       EXYNOS5_CMU_RESET_GSCL_SYS_PWR_REG,
+       EXYNOS5_CMU_RESET_ISP_SYS_PWR_REG,
+       EXYNOS5_CMU_RESET_G3D_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG,
+       EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG,
+};
+
+static void exynos5_power_off(void)
+{
+       unsigned int tmp;
+
+       pr_info("Power down.\n");
+       tmp = pmu_raw_readl(EXYNOS_PS_HOLD_CONTROL);
+       tmp ^= (1 << 8);
+       pmu_raw_writel(tmp, EXYNOS_PS_HOLD_CONTROL);
+
+       /* Wait a little so we don't give a false warning below */
+       mdelay(100);
+
+       pr_err("Power down failed, please power off system manually.\n");
+       while (1)
+               ;
+}
+
+void exynos5420_powerdown_conf(enum sys_powerdown mode)
+{
+       u32 this_cluster;
+
+       this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
+
+       /*
+        * set the cluster id to IROM register to ensure that we wake
+        * up with the current cluster.
+        */
+       pmu_raw_writel(this_cluster, EXYNOS_IROM_DATA2);
+}
+
+
+static void exynos5_powerdown_conf(enum sys_powerdown mode)
 {
        unsigned int i;
        unsigned int tmp;
@@ -343,7 +720,7 @@ static void exynos5_init_pmu(void)
        /*
         * Enable both SC_FEEDBACK and SC_COUNTER
         */
-       for (i = 0 ; i < ARRAY_SIZE(exynos5_list_both_cnt_feed) ; i++) {
+       for (i = 0; i < ARRAY_SIZE(exynos5_list_both_cnt_feed); i++) {
                tmp = pmu_raw_readl(exynos5_list_both_cnt_feed[i]);
                tmp |= (EXYNOS5_USE_SC_FEEDBACK |
                        EXYNOS5_USE_SC_COUNTER);
@@ -360,11 +737,11 @@ static void exynos5_init_pmu(void)
        /*
         * Disable WFI/WFE on XXX_OPTION
         */
-       for (i = 0 ; i < ARRAY_SIZE(exynos5_list_diable_wfi_wfe) ; i++) {
-               tmp = pmu_raw_readl(exynos5_list_diable_wfi_wfe[i]);
+       for (i = 0; i < ARRAY_SIZE(exynos5_list_disable_wfi_wfe); i++) {
+               tmp = pmu_raw_readl(exynos5_list_disable_wfi_wfe[i]);
                tmp &= ~(EXYNOS5_OPTION_USE_STANDBYWFE |
                         EXYNOS5_OPTION_USE_STANDBYWFI);
-               pmu_raw_writel(tmp, exynos5_list_diable_wfi_wfe[i]);
+               pmu_raw_writel(tmp, exynos5_list_disable_wfi_wfe[i]);
        }
 }
 
@@ -372,51 +749,257 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
 {
        unsigned int i;
 
-       if (soc_is_exynos5250())
-               exynos5_init_pmu();
+       const struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
+
+       if (pmu_data->powerdown_conf)
+               pmu_data->powerdown_conf(mode);
+
+       if (pmu_data->pmu_config) {
+               for (i = 0; (pmu_data->pmu_config[i].offset != PMU_TABLE_END); i++)
+                       pmu_raw_writel(pmu_data->pmu_config[i].val[mode],
+                                       pmu_data->pmu_config[i].offset);
+       }
 
-       for (i = 0; (exynos_pmu_config[i].offset != PMU_TABLE_END) ; i++)
-               pmu_raw_writel(exynos_pmu_config[i].val[mode],
-                               exynos_pmu_config[i].offset);
+       if (pmu_data->powerdown_conf_extra)
+               pmu_data->powerdown_conf_extra(mode);
 
-       if (soc_is_exynos4412()) {
-               for (i = 0; exynos4412_pmu_config[i].offset != PMU_TABLE_END ; i++)
-                       pmu_raw_writel(exynos4412_pmu_config[i].val[mode],
-                                       exynos4412_pmu_config[i].offset);
+       if (pmu_data->pmu_config_extra) {
+               for (i = 0; pmu_data->pmu_config_extra[i].offset != PMU_TABLE_END; i++)
+                       pmu_raw_writel(pmu_data->pmu_config_extra[i].val[mode],
+                                       pmu_data->pmu_config_extra[i].offset);
        }
 }
 
-static int __init exynos_pmu_init(void)
+static void exynos3250_pmu_init(void)
+{
+       unsigned int value;
+
+       /*
+        * To prevent from issuing new bus request form L2 memory system
+        * If core status is power down, should be set '1' to L2 power down
+        */
+       value = pmu_raw_readl(EXYNOS3_ARM_COMMON_OPTION);
+       value |= EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
+       pmu_raw_writel(value, EXYNOS3_ARM_COMMON_OPTION);
+
+       /* Enable USE_STANDBY_WFI for all CORE */
+       pmu_raw_writel(S5P_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
+
+       /*
+        * Set PSHOLD port for output high
+        */
+       value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
+       value |= S5P_PS_HOLD_OUTPUT_HIGH;
+       pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);
+
+       /*
+        * Enable signal for PSHOLD port
+        */
+       value = pmu_raw_readl(S5P_PS_HOLD_CONTROL);
+       value |= S5P_PS_HOLD_EN;
+       pmu_raw_writel(value, S5P_PS_HOLD_CONTROL);
+}
+
+static void exynos5250_pmu_init(void)
 {
        unsigned int value;
+       /*
+        * When SYS_WDTRESET is set, watchdog timer reset request
+        * is ignored by power management unit.
+        */
+       value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
+       value &= ~EXYNOS5_SYS_WDTRESET;
+       pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
+
+       value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
+       value &= ~EXYNOS5_SYS_WDTRESET;
+       pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
+}
+
+static void exynos5420_pmu_init(void)
+{
+       unsigned int value;
+       int i;
+
+       /*
+        * Set the CMU_RESET, CMU_SYSCLK and CMU_CLKSTOP registers
+        * for local power blocks to Low initially as per Table 8-4:
+        * "System-Level Power-Down Configuration Registers".
+        */
+       for (i = 0; i < ARRAY_SIZE(exynos5420_list_disable_pmu_reg); i++)
+               pmu_raw_writel(0, exynos5420_list_disable_pmu_reg[i]);
+
+       /* Enable USE_STANDBY_WFI for all CORE */
+       pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL, S5P_CENTRAL_SEQ_OPTION);
+
+       value  = pmu_raw_readl(EXYNOS_L2_OPTION(0));
+       value &= ~EXYNOS5_USE_RETENTION;
+       pmu_raw_writel(value, EXYNOS_L2_OPTION(0));
+
+       value = pmu_raw_readl(EXYNOS_L2_OPTION(1));
+       value &= ~EXYNOS5_USE_RETENTION;
+       pmu_raw_writel(value, EXYNOS_L2_OPTION(1));
+
+       /*
+        * If L2_COMMON is turned off, clocks related to ATB async
+        * bridge are gated. Thus, when ISP power is gated, LPI
+        * may get stuck.
+        */
+       value = pmu_raw_readl(EXYNOS5420_LPI_MASK);
+       value |= EXYNOS5420_ATB_ISP_ARM;
+       pmu_raw_writel(value, EXYNOS5420_LPI_MASK);
+
+       value  = pmu_raw_readl(EXYNOS5420_LPI_MASK1);
+       value |= EXYNOS5420_ATB_KFC;
+       pmu_raw_writel(value, EXYNOS5420_LPI_MASK1);
+
+       /* Prevent issue of new bus request from L2 memory */
+       value = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
+       value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
+       pmu_raw_writel(value, EXYNOS5420_ARM_COMMON_OPTION);
+
+       value = pmu_raw_readl(EXYNOS5420_KFC_COMMON_OPTION);
+       value |= EXYNOS5_SKIP_DEACTIVATE_ACEACP_IN_PWDN;
+       pmu_raw_writel(value, EXYNOS5420_KFC_COMMON_OPTION);
+
+       /* This setting is to reduce suspend/resume time */
+       pmu_raw_writel(DUR_WAIT_RESET, EXYNOS5420_LOGIC_RESET_DURATION3);
+
+       /* Serialized CPU wakeup of Eagle */
+       pmu_raw_writel(SPREAD_ENABLE, EXYNOS5420_ARM_INTR_SPREAD_ENABLE);
+
+       pmu_raw_writel(SPREAD_USE_STANDWFI,
+                       EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI);
+
+       pmu_raw_writel(0x1, EXYNOS5420_UP_SCHEDULER);
+
+       pm_power_off = exynos5_power_off;
+       pr_info("EXYNOS5420 PMU initialized\n");
+}
+
+static int pmu_restart_notify(struct notifier_block *this,
+               unsigned long code, void *unused)
+{
+       pmu_raw_writel(0x1, EXYNOS_SWRESET);
+
+       return NOTIFY_DONE;
+}
+
+static const struct exynos_pmu_data exynos3250_pmu_data = {
+       .pmu_config     = exynos3250_pmu_config,
+       .pmu_init       = exynos3250_pmu_init,
+       .powerdown_conf_extra   = exynos3250_powerdown_conf_extra,
+};
 
-       exynos_pmu_config = exynos4210_pmu_config;
-
-       if (soc_is_exynos4210()) {
-               exynos_pmu_config = exynos4210_pmu_config;
-               pr_info("EXYNOS4210 PMU Initialize\n");
-       } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
-               exynos_pmu_config = exynos4x12_pmu_config;
-               pr_info("EXYNOS4x12 PMU Initialize\n");
-       } else if (soc_is_exynos5250()) {
-               /*
-                * When SYS_WDTRESET is set, watchdog timer reset request
-                * is ignored by power management unit.
-                */
-               value = pmu_raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
-               value &= ~EXYNOS5_SYS_WDTRESET;
-               pmu_raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
-
-               value = pmu_raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
-               value &= ~EXYNOS5_SYS_WDTRESET;
-               pmu_raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
-
-               exynos_pmu_config = exynos5250_pmu_config;
-               pr_info("EXYNOS5250 PMU Initialize\n");
-       } else {
-               pr_info("EXYNOS: PMU not supported\n");
+static const struct exynos_pmu_data exynos4210_pmu_data = {
+       .pmu_config     = exynos4210_pmu_config,
+};
+
+static const struct exynos_pmu_data exynos4212_pmu_data = {
+       .pmu_config     = exynos4x12_pmu_config,
+};
+
+static const struct exynos_pmu_data exynos4412_pmu_data = {
+       .pmu_config             = exynos4x12_pmu_config,
+       .pmu_config_extra       = exynos4412_pmu_config,
+};
+
+static const struct exynos_pmu_data exynos5250_pmu_data = {
+       .pmu_config     = exynos5250_pmu_config,
+       .pmu_init       = exynos5250_pmu_init,
+       .powerdown_conf = exynos5_powerdown_conf,
+};
+
+static struct exynos_pmu_data exynos5420_pmu_data = {
+       .pmu_config     = exynos5420_pmu_config,
+       .pmu_init       = exynos5420_pmu_init,
+       .powerdown_conf = exynos5420_powerdown_conf,
+};
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static const struct of_device_id exynos_pmu_of_device_ids[] = {
+       {
+               .compatible = "samsung,exynos3250-pmu",
+               .data = &exynos3250_pmu_data,
+       }, {
+               .compatible = "samsung,exynos4210-pmu",
+               .data = &exynos4210_pmu_data,
+       }, {
+               .compatible = "samsung,exynos4212-pmu",
+               .data = &exynos4212_pmu_data,
+       }, {
+               .compatible = "samsung,exynos4412-pmu",
+               .data = &exynos4412_pmu_data,
+       }, {
+               .compatible = "samsung,exynos5250-pmu",
+               .data = &exynos5250_pmu_data,
+       }, {
+               .compatible = "samsung,exynos5420-pmu",
+               .data = &exynos5420_pmu_data,
+       },
+       { /*sentinel*/ },
+};
+
+/*
+ * Exynos PMU restart notifier, handles restart functionality
+ */
+static struct notifier_block pmu_restart_handler = {
+       .notifier_call = pmu_restart_notify,
+       .priority = 128,
+};
+
+static int exynos_pmu_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pmu_base_addr = devm_ioremap_resource(dev, res);
+       if (IS_ERR(pmu_base_addr))
+               return PTR_ERR(pmu_base_addr);
+
+       pmu_context = devm_kzalloc(&pdev->dev,
+                       sizeof(struct exynos_pmu_context),
+                       GFP_KERNEL);
+       if (!pmu_context) {
+               dev_err(dev, "Cannot allocate memory.\n");
+               return -ENOMEM;
        }
+       pmu_context->dev = dev;
+
+       match = of_match_node(exynos_pmu_of_device_ids, dev->of_node);
+
+       pmu_context->pmu_data = match->data;
+
+       if (pmu_context->pmu_data->pmu_init)
+               pmu_context->pmu_data->pmu_init();
+
+       platform_set_drvdata(pdev, pmu_context);
 
+       ret = register_restart_handler(&pmu_restart_handler);
+       if (ret)
+               dev_warn(dev, "can't register restart handler err=%d\n", ret);
+
+       dev_dbg(dev, "Exynos PMU Driver probe done\n");
        return 0;
 }
-arch_initcall(exynos_pmu_init);
+
+static struct platform_driver exynos_pmu_driver = {
+       .driver  = {
+               .name   = "exynos-pmu",
+               .owner  = THIS_MODULE,
+               .of_match_table = exynos_pmu_of_device_ids,
+       },
+       .probe = exynos_pmu_probe,
+};
+
+static int __init exynos_pmu_init(void)
+{
+       return platform_driver_register(&exynos_pmu_driver);
+
+}
+postcore_initcall(exynos_pmu_init);
index 96a1569262b5233a9621f11b0a64c62bfdce2a57..b5f4406fc1b5d3614c95af23408d0dd66217984e 100644 (file)
 #define S5P_CENTRAL_SEQ_OPTION                 0x0208
 
 #define S5P_USE_STANDBY_WFI0                   (1 << 16)
+#define S5P_USE_STANDBY_WFI1                   (1 << 17)
+#define S5P_USE_STANDBY_WFI2                   (1 << 19)
+#define S5P_USE_STANDBY_WFI3                   (1 << 20)
 #define S5P_USE_STANDBY_WFE0                   (1 << 24)
+#define S5P_USE_STANDBY_WFE1                   (1 << 25)
+#define S5P_USE_STANDBY_WFE2                   (1 << 27)
+#define S5P_USE_STANDBY_WFE3                   (1 << 28)
 
+#define S5P_USE_STANDBY_WFI_ALL \
+       (S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFI1 | \
+        S5P_USE_STANDBY_WFI2 | S5P_USE_STANDBY_WFI3 | \
+        S5P_USE_STANDBY_WFE0 | S5P_USE_STANDBY_WFE1 | \
+        S5P_USE_STANDBY_WFE2 | S5P_USE_STANDBY_WFE3)
+
+#define S5P_USE_DELAYED_RESET_ASSERTION                BIT(12)
+
+#define EXYNOS_CORE_PO_RESET(n)                        ((1 << 4) << n)
+#define EXYNOS_WAKEUP_FROM_LOWPWR              (1 << 28)
 #define EXYNOS_SWRESET                         0x0400
 #define EXYNOS5440_SWRESET                     0x00C4
 
@@ -35,6 +51,7 @@
 #define S5P_INFORM7                            0x081C
 #define S5P_PMU_SPARE3                         0x090C
 
+#define EXYNOS_IROM_DATA2                      0x0988
 #define S5P_ARM_CORE0_LOWPWR                   0x1000
 #define S5P_DIS_IRQ_CORE0                      0x1004
 #define S5P_DIS_IRQ_CENTRAL0                   0x1008
                        (EXYNOS_ARM_CORE0_CONFIGURATION + (0x80 * (_nr)))
 #define EXYNOS_ARM_CORE_STATUS(_nr)            \
                        (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x4)
+#define EXYNOS_ARM_CORE_OPTION(_nr)            \
+                       (EXYNOS_ARM_CORE_CONFIGURATION(_nr) + 0x8)
 
 #define EXYNOS_ARM_COMMON_CONFIGURATION                0x2500
 #define EXYNOS_COMMON_CONFIGURATION(_nr)       \
 #define EXYNOS_COMMON_OPTION(_nr)              \
                        (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
 
+#define EXYNOS_CORE_LOCAL_PWR_EN               0x3
+
+#define EXYNOS_ARM_COMMON_STATUS               0x2504
+#define EXYNOS_COMMON_OPTION(_nr)              \
+                       (EXYNOS_COMMON_CONFIGURATION(_nr) + 0x8)
+
+#define EXYNOS_ARM_L2_CONFIGURATION            0x2600
+#define EXYNOS_L2_CONFIGURATION(_nr)           \
+                       (EXYNOS_ARM_L2_CONFIGURATION + ((_nr) * 0x80))
+#define EXYNOS_L2_STATUS(_nr)                  \
+                       (EXYNOS_L2_CONFIGURATION(_nr) + 0x4)
+#define EXYNOS_L2_OPTION(_nr)                  \
+                       (EXYNOS_L2_CONFIGURATION(_nr) + 0x8)
+#define EXYNOS_L2_COMMON_PWR_EN                        0x3
+
+#define EXYNOS_ARM_CORE_X_STATUS_OFFSET                0x4
+
+#define EXYNOS5_APLL_SYSCLK_CONFIGURATION      0x2A00
+#define EXYNOS5_APLL_SYSCLK_STATUS             0x2A04
+
+#define EXYNOS5_ARM_L2_OPTION                  0x2608
+#define EXYNOS5_USE_RETENTION                  BIT(4)
+
+#define EXYNOS5_L2RSTDISABLE_VALUE             BIT(3)
+
 #define S5P_PAD_RET_MAUDIO_OPTION              0x3028
 #define S5P_PAD_RET_GPIO_OPTION                        0x3108
 #define S5P_PAD_RET_UART_OPTION                        0x3128
 #define S5P_PAD_RET_EBIA_OPTION                        0x3188
 #define S5P_PAD_RET_EBIB_OPTION                        0x31A8
 
+#define S5P_PS_HOLD_CONTROL                    0x330C
+#define S5P_PS_HOLD_EN                         (1 << 31)
+#define S5P_PS_HOLD_OUTPUT_HIGH                        (3 << 8)
+
+#define S5P_CAM_OPTION                         0x3C08
+#define S5P_MFC_OPTION                         0x3C48
+#define S5P_G3D_OPTION                         0x3C68
+#define S5P_LCD0_OPTION                                0x3C88
+#define S5P_LCD1_OPTION                                0x3CA8
+#define S5P_ISP_OPTION                         S5P_LCD1_OPTION
+
 #define S5P_CORE_LOCAL_PWR_EN                  0x3
+#define S5P_CORE_WAKEUP_FROM_LOCAL_CFG         (0x3 << 8)
 
 /* Only for EXYNOS4210 */
 #define S5P_CMU_CLKSTOP_LCD1_LOWPWR    0x1154
 #define S5P_DIS_IRQ_CORE3                      0x1034
 #define S5P_DIS_IRQ_CENTRAL3                   0x1038
 
+/* Only for EXYNOS3XXX */
+#define EXYNOS3_ARM_CORE0_SYS_PWR_REG                  0x1000
+#define EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG    0x1004
+#define EXYNOS3_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG  0x1008
+#define EXYNOS3_ARM_CORE1_SYS_PWR_REG                  0x1010
+#define EXYNOS3_DIS_IRQ_ARM_CORE1_LOCAL_SYS_PWR_REG    0x1014
+#define EXYNOS3_DIS_IRQ_ARM_CORE1_CENTRAL_SYS_PWR_REG  0x1018
+#define EXYNOS3_ISP_ARM_SYS_PWR_REG                    0x1050
+#define EXYNOS3_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG      0x1054
+#define EXYNOS3_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG    0x1058
+#define EXYNOS3_ARM_COMMON_SYS_PWR_REG                 0x1080
+#define EXYNOS3_ARM_L2_SYS_PWR_REG                     0x10C0
+#define EXYNOS3_CMU_ACLKSTOP_SYS_PWR_REG               0x1100
+#define EXYNOS3_CMU_SCLKSTOP_SYS_PWR_REG               0x1104
+#define EXYNOS3_CMU_RESET_SYS_PWR_REG                  0x110C
+#define EXYNOS3_CMU_ACLKSTOP_COREBLK_SYS_PWR_REG       0x1110
+#define EXYNOS3_CMU_SCLKSTOP_COREBLK_SYS_PWR_REG       0x1114
+#define EXYNOS3_CMU_RESET_COREBLK_SYS_PWR_REG          0x111C
+#define EXYNOS3_APLL_SYSCLK_SYS_PWR_REG                        0x1120
+#define EXYNOS3_MPLL_SYSCLK_SYS_PWR_REG                        0x1124
+#define EXYNOS3_VPLL_SYSCLK_SYS_PWR_REG                        0x1128
+#define EXYNOS3_EPLL_SYSCLK_SYS_PWR_REG                        0x112C
+#define EXYNOS3_MPLLUSER_SYSCLK_SYS_PWR_REG            0x1130
+#define EXYNOS3_BPLLUSER_SYSCLK_SYS_PWR_REG            0x1134
+#define EXYNOS3_EPLLUSER_SYSCLK_SYS_PWR_REG            0x1138
+#define EXYNOS3_CMU_CLKSTOP_CAM_SYS_PWR_REG            0x1140
+#define EXYNOS3_CMU_CLKSTOP_MFC_SYS_PWR_REG            0x1148
+#define EXYNOS3_CMU_CLKSTOP_G3D_SYS_PWR_REG            0x114C
+#define EXYNOS3_CMU_CLKSTOP_LCD0_SYS_PWR_REG           0x1150
+#define EXYNOS3_CMU_CLKSTOP_ISP_SYS_PWR_REG            0x1154
+#define EXYNOS3_CMU_CLKSTOP_MAUDIO_SYS_PWR_REG         0x1158
+#define EXYNOS3_CMU_RESET_CAM_SYS_PWR_REG              0x1160
+#define EXYNOS3_CMU_RESET_MFC_SYS_PWR_REG              0x1168
+#define EXYNOS3_CMU_RESET_G3D_SYS_PWR_REG              0x116C
+#define EXYNOS3_CMU_RESET_LCD0_SYS_PWR_REG             0x1170
+#define EXYNOS3_CMU_RESET_ISP_SYS_PWR_REG              0x1174
+#define EXYNOS3_CMU_RESET_MAUDIO_SYS_PWR_REG           0x1178
+#define EXYNOS3_TOP_BUS_SYS_PWR_REG                    0x1180
+#define EXYNOS3_TOP_RETENTION_SYS_PWR_REG              0x1184
+#define EXYNOS3_TOP_PWR_SYS_PWR_REG                    0x1188
+#define EXYNOS3_TOP_BUS_COREBLK_SYS_PWR_REG            0x1190
+#define EXYNOS3_TOP_RETENTION_COREBLK_SYS_PWR_REG      0x1194
+#define EXYNOS3_TOP_PWR_COREBLK_SYS_PWR_REG            0x1198
+#define EXYNOS3_LOGIC_RESET_SYS_PWR_REG                        0x11A0
+#define EXYNOS3_OSCCLK_GATE_SYS_PWR_REG                        0x11A4
+#define EXYNOS3_LOGIC_RESET_COREBLK_SYS_PWR_REG                0x11B0
+#define EXYNOS3_OSCCLK_GATE_COREBLK_SYS_PWR_REG                0x11B4
+#define EXYNOS3_PAD_RETENTION_DRAM_SYS_PWR_REG         0x1200
+#define EXYNOS3_PAD_RETENTION_MAUDIO_SYS_PWR_REG       0x1204
+#define EXYNOS3_PAD_RETENTION_SPI_SYS_PWR_REG          0x1208
+#define EXYNOS3_PAD_RETENTION_MMC2_SYS_PWR_REG         0x1218
+#define EXYNOS3_PAD_RETENTION_GPIO_SYS_PWR_REG         0x1220
+#define EXYNOS3_PAD_RETENTION_UART_SYS_PWR_REG         0x1224
+#define EXYNOS3_PAD_RETENTION_MMC0_SYS_PWR_REG         0x1228
+#define EXYNOS3_PAD_RETENTION_MMC1_SYS_PWR_REG         0x122C
+#define EXYNOS3_PAD_RETENTION_EBIA_SYS_PWR_REG         0x1230
+#define EXYNOS3_PAD_RETENTION_EBIB_SYS_PWR_REG         0x1234
+#define EXYNOS3_PAD_RETENTION_JTAG_SYS_PWR_REG         0x1238
+#define EXYNOS3_PAD_ISOLATION_SYS_PWR_REG              0x1240
+#define EXYNOS3_PAD_ALV_SEL_SYS_PWR_REG                        0x1260
+#define EXYNOS3_XUSBXTI_SYS_PWR_REG                    0x1280
+#define EXYNOS3_XXTI_SYS_PWR_REG                       0x1284
+#define EXYNOS3_EXT_REGULATOR_SYS_PWR_REG              0x12C0
+#define EXYNOS3_EXT_REGULATOR_COREBLK_SYS_PWR_REG      0x12C4
+#define EXYNOS3_GPIO_MODE_SYS_PWR_REG                  0x1300
+#define EXYNOS3_GPIO_MODE_MAUDIO_SYS_PWR_REG           0x1340
+#define EXYNOS3_TOP_ASB_RESET_SYS_PWR_REG              0x1344
+#define EXYNOS3_TOP_ASB_ISOLATION_SYS_PWR_REG          0x1348
+#define EXYNOS3_TOP_ASB_RESET_COREBLK_SYS_PWR_REG      0x1350
+#define EXYNOS3_TOP_ASB_ISOLATION_COREBLK_SYS_PWR_REG  0x1354
+#define EXYNOS3_CAM_SYS_PWR_REG                                0x1380
+#define EXYNOS3_MFC_SYS_PWR_REG                                0x1388
+#define EXYNOS3_G3D_SYS_PWR_REG                                0x138C
+#define EXYNOS3_LCD0_SYS_PWR_REG                       0x1390
+#define EXYNOS3_ISP_SYS_PWR_REG                                0x1394
+#define EXYNOS3_MAUDIO_SYS_PWR_REG                     0x1398
+#define EXYNOS3_DRAM_FREQ_DOWN_SYS_PWR_REG             0x13B0
+#define EXYNOS3_DDRPHY_DLLOFF_SYS_PWR_REG              0x13B4
+#define EXYNOS3_CMU_SYSCLK_ISP_SYS_PWR_REG             0x13B8
+#define EXYNOS3_LPDDR_PHY_DLL_LOCK_SYS_PWR_REG         0x13C0
+#define EXYNOS3_BPLL_SYSCLK_SYS_PWR_REG                        0x13C4
+#define EXYNOS3_UPLL_SYSCLK_SYS_PWR_REG                        0x13C8
+
+#define EXYNOS3_ARM_CORE0_OPTION                       0x2008
+#define EXYNOS3_ARM_CORE_OPTION(_nr)   \
+                       (EXYNOS3_ARM_CORE0_OPTION + ((_nr) * 0x80))
+
+#define EXYNOS3_ARM_COMMON_OPTION                      0x2408
+#define EXYNOS3_TOP_PWR_OPTION                         0x2C48
+#define EXYNOS3_CORE_TOP_PWR_OPTION                    0x2CA8
+#define EXYNOS3_XUSBXTI_DURATION                       0x341C
+#define EXYNOS3_XXTI_DURATION                          0x343C
+#define EXYNOS3_EXT_REGULATOR_DURATION                 0x361C
+#define EXYNOS3_EXT_REGULATOR_COREBLK_DURATION         0x363C
+#define XUSBXTI_DURATION                               0x00000BB8
+#define XXTI_DURATION                                  XUSBXTI_DURATION
+#define EXT_REGULATOR_DURATION                         0x00001D4C
+#define EXT_REGULATOR_COREBLK_DURATION                 EXT_REGULATOR_DURATION
+
+/* for XXX_OPTION */
+#define EXYNOS3_OPTION_USE_SC_COUNTER                  (1 << 0)
+#define EXYNOS3_OPTION_USE_SC_FEEDBACK                 (1 << 1)
+#define EXYNOS3_OPTION_SKIP_DEACTIVATE_ACEACP_IN_PWDN  (1 << 7)
+
 /* For EXYNOS5 */
 
 #define EXYNOS5_AUTO_WDTRESET_DISABLE                          0x0408
 #define EXYNOS5_MASK_WDTRESET_REQUEST                          0x040C
 
+#define EXYNOS5_USE_RETENTION                  BIT(4)
 #define EXYNOS5_SYS_WDTRESET                                   (1 << 20)
 
 #define EXYNOS5_ARM_CORE0_SYS_PWR_REG                          0x1000
@@ -326,4 +487,204 @@ static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
                 + MPIDR_AFFINITY_LEVEL(mpidr, 0));
 }
 
+/* Only for EXYNOS5420 */
+#define EXYNOS5420_ISP_ARM_OPTION                              0x2488
+#define EXYNOS5420_L2RSTDISABLE_VALUE                          BIT(3)
+
+#define EXYNOS5420_LPI_MASK                                    0x0004
+#define EXYNOS5420_LPI_MASK1                                   0x0008
+#define EXYNOS5420_UFS                                         BIT(8)
+#define EXYNOS5420_ATB_KFC                                     BIT(13)
+#define EXYNOS5420_ATB_ISP_ARM                                 BIT(19)
+#define EXYNOS5420_EMULATION                                   BIT(31)
+#define ATB_ISP_ARM                                            BIT(12)
+#define ATB_KFC                                                        BIT(13)
+#define ATB_NOC                                                        BIT(14)
+
+#define EXYNOS5420_ARM_INTR_SPREAD_ENABLE                      0x0100
+#define EXYNOS5420_ARM_INTR_SPREAD_USE_STANDBYWFI              0x0104
+#define EXYNOS5420_UP_SCHEDULER                                        0x0120
+#define SPREAD_ENABLE                                          0xF
+#define SPREAD_USE_STANDWFI                                    0xF
+
+#define EXYNOS5420_BB_CON1                                     0x0784
+#define EXYNOS5420_BB_SEL_EN                                   BIT(31)
+#define EXYNOS5420_BB_PMOS_EN                                  BIT(7)
+#define EXYNOS5420_BB_1300X                                    0XF
+
+#define EXYNOS5420_ARM_CORE2_SYS_PWR_REG                       0x1020
+#define EXYNOS5420_DIS_IRQ_ARM_CORE2_LOCAL_SYS_PWR_REG         0x1024
+#define EXYNOS5420_DIS_IRQ_ARM_CORE2_CENTRAL_SYS_PWR_REG       0x1028
+#define EXYNOS5420_ARM_CORE3_SYS_PWR_REG                       0x1030
+#define EXYNOS5420_DIS_IRQ_ARM_CORE3_LOCAL_SYS_PWR_REG         0x1034
+#define EXYNOS5420_DIS_IRQ_ARM_CORE3_CENTRAL_SYS_PWR_REG       0x1038
+#define EXYNOS5420_KFC_CORE0_SYS_PWR_REG                       0x1040
+#define EXYNOS5420_DIS_IRQ_KFC_CORE0_LOCAL_SYS_PWR_REG         0x1044
+#define EXYNOS5420_DIS_IRQ_KFC_CORE0_CENTRAL_SYS_PWR_REG       0x1048
+#define EXYNOS5420_KFC_CORE1_SYS_PWR_REG                       0x1050
+#define EXYNOS5420_DIS_IRQ_KFC_CORE1_LOCAL_SYS_PWR_REG         0x1054
+#define EXYNOS5420_DIS_IRQ_KFC_CORE1_CENTRAL_SYS_PWR_REG       0x1058
+#define EXYNOS5420_KFC_CORE2_SYS_PWR_REG                       0x1060
+#define EXYNOS5420_DIS_IRQ_KFC_CORE2_LOCAL_SYS_PWR_REG         0x1064
+#define EXYNOS5420_DIS_IRQ_KFC_CORE2_CENTRAL_SYS_PWR_REG       0x1068
+#define EXYNOS5420_KFC_CORE3_SYS_PWR_REG                       0x1070
+#define EXYNOS5420_DIS_IRQ_KFC_CORE3_LOCAL_SYS_PWR_REG         0x1074
+#define EXYNOS5420_DIS_IRQ_KFC_CORE3_CENTRAL_SYS_PWR_REG       0x1078
+#define EXYNOS5420_ISP_ARM_SYS_PWR_REG                         0x1090
+#define EXYNOS5420_DIS_IRQ_ISP_ARM_LOCAL_SYS_PWR_REG           0x1094
+#define EXYNOS5420_DIS_IRQ_ISP_ARM_CENTRAL_SYS_PWR_REG         0x1098
+#define EXYNOS5420_ARM_COMMON_SYS_PWR_REG                      0x10A0
+#define EXYNOS5420_KFC_COMMON_SYS_PWR_REG                      0x10B0
+#define EXYNOS5420_KFC_L2_SYS_PWR_REG                          0x10D0
+#define EXYNOS5420_DPLL_SYSCLK_SYS_PWR_REG                     0x1158
+#define EXYNOS5420_IPLL_SYSCLK_SYS_PWR_REG                     0x115C
+#define EXYNOS5420_KPLL_SYSCLK_SYS_PWR_REG                     0x1160
+#define EXYNOS5420_RPLL_SYSCLK_SYS_PWR_REG                      0x1174
+#define EXYNOS5420_SPLL_SYSCLK_SYS_PWR_REG                      0x1178
+#define EXYNOS5420_INTRAM_MEM_SYS_PWR_REG                       0x11B8
+#define EXYNOS5420_INTROM_MEM_SYS_PWR_REG                       0x11BC
+#define EXYNOS5420_ONENANDXL_MEM_SYS_PWR                       0x11C0
+#define EXYNOS5420_USBDEV_MEM_SYS_PWR                          0x11CC
+#define EXYNOS5420_USBDEV1_MEM_SYS_PWR                         0x11D0
+#define EXYNOS5420_SDMMC_MEM_SYS_PWR                           0x11D4
+#define EXYNOS5420_CSSYS_MEM_SYS_PWR                           0x11D8
+#define EXYNOS5420_SECSS_MEM_SYS_PWR                           0x11DC
+#define EXYNOS5420_ROTATOR_MEM_SYS_PWR                         0x11E0
+#define EXYNOS5420_INTRAM_MEM_SYS_PWR                          0x11E4
+#define EXYNOS5420_INTROM_MEM_SYS_PWR                          0x11E8
+#define EXYNOS5420_PAD_RETENTION_JTAG_SYS_PWR_REG              0x1208
+#define EXYNOS5420_PAD_RETENTION_DRAM_SYS_PWR_REG              0x1210
+#define EXYNOS5420_PAD_RETENTION_UART_SYS_PWR_REG              0x1214
+#define EXYNOS5420_PAD_RETENTION_MMC0_SYS_PWR_REG              0x1218
+#define EXYNOS5420_PAD_RETENTION_MMC1_SYS_PWR_REG              0x121C
+#define EXYNOS5420_PAD_RETENTION_MMC2_SYS_PWR_REG              0x1220
+#define EXYNOS5420_PAD_RETENTION_HSI_SYS_PWR_REG               0x1224
+#define EXYNOS5420_PAD_RETENTION_EBIA_SYS_PWR_REG              0x1228
+#define EXYNOS5420_PAD_RETENTION_EBIB_SYS_PWR_REG              0x122C
+#define EXYNOS5420_PAD_RETENTION_SPI_SYS_PWR_REG               0x1230
+#define EXYNOS5420_PAD_RETENTION_DRAM_COREBLK_SYS_PWR_REG      0x1234
+#define EXYNOS5420_DISP1_SYS_PWR_REG                           0x1410
+#define EXYNOS5420_MAU_SYS_PWR_REG                             0x1414
+#define EXYNOS5420_G2D_SYS_PWR_REG                             0x1418
+#define EXYNOS5420_MSC_SYS_PWR_REG                             0x141C
+#define EXYNOS5420_FSYS_SYS_PWR_REG                            0x1420
+#define EXYNOS5420_FSYS2_SYS_PWR_REG                           0x1424
+#define EXYNOS5420_PSGEN_SYS_PWR_REG                           0x1428
+#define EXYNOS5420_PERIC_SYS_PWR_REG                           0x142C
+#define EXYNOS5420_WCORE_SYS_PWR_REG                           0x1430
+#define EXYNOS5420_CMU_CLKSTOP_DISP1_SYS_PWR_REG               0x1490
+#define EXYNOS5420_CMU_CLKSTOP_MAU_SYS_PWR_REG                 0x1494
+#define EXYNOS5420_CMU_CLKSTOP_G2D_SYS_PWR_REG                 0x1498
+#define EXYNOS5420_CMU_CLKSTOP_MSC_SYS_PWR_REG                 0x149C
+#define EXYNOS5420_CMU_CLKSTOP_FSYS_SYS_PWR_REG                        0x14A0
+#define EXYNOS5420_CMU_CLKSTOP_FSYS2_SYS_PWR_REG               0x14A4
+#define EXYNOS5420_CMU_CLKSTOP_PSGEN_SYS_PWR_REG               0x14A8
+#define EXYNOS5420_CMU_CLKSTOP_PERIC_SYS_PWR_REG               0x14AC
+#define EXYNOS5420_CMU_CLKSTOP_WCORE_SYS_PWR_REG               0x14B0
+#define EXYNOS5420_CMU_SYSCLK_TOPPWR_SYS_PWR_REG               0x14BC
+#define EXYNOS5420_CMU_SYSCLK_DISP1_SYS_PWR_REG                        0x14D0
+#define EXYNOS5420_CMU_SYSCLK_MAU_SYS_PWR_REG                  0x14D4
+#define EXYNOS5420_CMU_SYSCLK_G2D_SYS_PWR_REG                  0x14D8
+#define EXYNOS5420_CMU_SYSCLK_MSC_SYS_PWR_REG                  0x14DC
+#define EXYNOS5420_CMU_SYSCLK_FSYS_SYS_PWR_REG                 0x14E0
+#define EXYNOS5420_CMU_SYSCLK_FSYS2_SYS_PWR_REG                        0x14E4
+#define EXYNOS5420_CMU_SYSCLK_PSGEN_SYS_PWR_REG                        0x14E8
+#define EXYNOS5420_CMU_SYSCLK_PERIC_SYS_PWR_REG                        0x14EC
+#define EXYNOS5420_CMU_SYSCLK_WCORE_SYS_PWR_REG                        0x14F0
+#define EXYNOS5420_CMU_SYSCLK_SYSMEM_TOPPWR_SYS_PWR_REG                0x14F4
+#define EXYNOS5420_CMU_RESET_FSYS2_SYS_PWR_REG                 0x1570
+#define EXYNOS5420_CMU_RESET_PSGEN_SYS_PWR_REG                 0x1574
+#define EXYNOS5420_CMU_RESET_PERIC_SYS_PWR_REG                 0x1578
+#define EXYNOS5420_CMU_RESET_WCORE_SYS_PWR_REG                 0x157C
+#define EXYNOS5420_CMU_RESET_DISP1_SYS_PWR_REG                 0x1590
+#define EXYNOS5420_CMU_RESET_MAU_SYS_PWR_REG                   0x1594
+#define EXYNOS5420_CMU_RESET_G2D_SYS_PWR_REG                   0x1598
+#define EXYNOS5420_CMU_RESET_MSC_SYS_PWR_REG                   0x159C
+#define EXYNOS5420_CMU_RESET_FSYS_SYS_PWR_REG                  0x15A0
+#define EXYNOS5420_SFR_AXI_CGDIS1                              0x15E4
+#define EXYNOS_ARM_CORE2_CONFIGURATION                         0x2100
+#define EXYNOS5420_ARM_CORE2_OPTION                            0x2108
+#define EXYNOS_ARM_CORE3_CONFIGURATION                         0x2180
+#define EXYNOS5420_ARM_CORE3_OPTION                            0x2188
+#define EXYNOS5420_ARM_COMMON_STATUS                           0x2504
+#define EXYNOS5420_ARM_COMMON_OPTION                           0x2508
+#define EXYNOS5420_KFC_COMMON_STATUS                           0x2584
+#define EXYNOS5420_KFC_COMMON_OPTION                           0x2588
+#define EXYNOS5420_LOGIC_RESET_DURATION3                       0x2D1C
+
+#define EXYNOS5420_PAD_RET_GPIO_OPTION                         0x30C8
+#define EXYNOS5420_PAD_RET_UART_OPTION                         0x30E8
+#define EXYNOS5420_PAD_RET_MMCA_OPTION                         0x3108
+#define EXYNOS5420_PAD_RET_MMCB_OPTION                         0x3128
+#define EXYNOS5420_PAD_RET_MMCC_OPTION                         0x3148
+#define EXYNOS5420_PAD_RET_HSI_OPTION                          0x3168
+#define EXYNOS5420_PAD_RET_SPI_OPTION                          0x31C8
+#define EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION                 0x31E8
+#define EXYNOS_PAD_RET_DRAM_OPTION                             0x3008
+#define EXYNOS_PAD_RET_MAUDIO_OPTION                           0x3028
+#define EXYNOS_PAD_RET_JTAG_OPTION                             0x3048
+#define EXYNOS_PAD_RET_GPIO_OPTION                             0x3108
+#define EXYNOS_PAD_RET_UART_OPTION                             0x3128
+#define EXYNOS_PAD_RET_MMCA_OPTION                             0x3148
+#define EXYNOS_PAD_RET_MMCB_OPTION                             0x3168
+#define EXYNOS_PAD_RET_EBIA_OPTION                             0x3188
+#define EXYNOS_PAD_RET_EBIB_OPTION                             0x31A8
+
+#define EXYNOS_PS_HOLD_CONTROL                                 0x330C
+
+/* For SYS_PWR_REG */
+#define EXYNOS_SYS_PWR_CFG                                     BIT(0)
+
+#define EXYNOS5420_MFC_CONFIGURATION                           0x4060
+#define EXYNOS5420_MFC_STATUS                                  0x4064
+#define EXYNOS5420_MFC_OPTION                                  0x4068
+#define EXYNOS5420_G3D_CONFIGURATION                           0x4080
+#define EXYNOS5420_G3D_STATUS                                  0x4084
+#define EXYNOS5420_G3D_OPTION                                  0x4088
+#define EXYNOS5420_DISP0_CONFIGURATION                         0x40A0
+#define EXYNOS5420_DISP0_STATUS                                        0x40A4
+#define EXYNOS5420_DISP0_OPTION                                        0x40A8
+#define EXYNOS5420_DISP1_CONFIGURATION                         0x40C0
+#define EXYNOS5420_DISP1_STATUS                                        0x40C4
+#define EXYNOS5420_DISP1_OPTION                                        0x40C8
+#define EXYNOS5420_MAU_CONFIGURATION                           0x40E0
+#define EXYNOS5420_MAU_STATUS                                  0x40E4
+#define EXYNOS5420_MAU_OPTION                                  0x40E8
+#define EXYNOS5420_FSYS2_OPTION                                        0x4168
+#define EXYNOS5420_PSGEN_OPTION                                        0x4188
+
+/* For EXYNOS_CENTRAL_SEQ_OPTION */
+#define EXYNOS5_USE_STANDBYWFI_ARM_CORE0                       BIT(16)
+#define EXYNOS5_USE_STANDBYWFI_ARM_CORE1                       BUT(17)
+#define EXYNOS5_USE_STANDBYWFE_ARM_CORE0                       BIT(24)
+#define EXYNOS5_USE_STANDBYWFE_ARM_CORE1                       BIT(25)
+
+#define EXYNOS5420_ARM_USE_STANDBY_WFI0                                BIT(4)
+#define EXYNOS5420_ARM_USE_STANDBY_WFI1                                BIT(5)
+#define EXYNOS5420_ARM_USE_STANDBY_WFI2                                BIT(6)
+#define EXYNOS5420_ARM_USE_STANDBY_WFI3                                BIT(7)
+#define EXYNOS5420_KFC_USE_STANDBY_WFI0                                BIT(8)
+#define EXYNOS5420_KFC_USE_STANDBY_WFI1                                BIT(9)
+#define EXYNOS5420_KFC_USE_STANDBY_WFI2                                BIT(10)
+#define EXYNOS5420_KFC_USE_STANDBY_WFI3                                BIT(11)
+#define EXYNOS5420_ARM_USE_STANDBY_WFE0                                BIT(16)
+#define EXYNOS5420_ARM_USE_STANDBY_WFE1                                BIT(17)
+#define EXYNOS5420_ARM_USE_STANDBY_WFE2                                BIT(18)
+#define EXYNOS5420_ARM_USE_STANDBY_WFE3                                BIT(19)
+#define EXYNOS5420_KFC_USE_STANDBY_WFE0                                BIT(20)
+#define EXYNOS5420_KFC_USE_STANDBY_WFE1                                BIT(21)
+#define EXYNOS5420_KFC_USE_STANDBY_WFE2                                BIT(22)
+#define EXYNOS5420_KFC_USE_STANDBY_WFE3                                BIT(23)
+
+#define DUR_WAIT_RESET                         0xF
+
+#define EXYNOS5420_USE_STANDBY_WFI_ALL (EXYNOS5420_ARM_USE_STANDBY_WFI0    \
+                                        | EXYNOS5420_ARM_USE_STANDBY_WFI1  \
+                                        | EXYNOS5420_ARM_USE_STANDBY_WFI2  \
+                                        | EXYNOS5420_ARM_USE_STANDBY_WFI3  \
+                                        | EXYNOS5420_KFC_USE_STANDBY_WFI0  \
+                                        | EXYNOS5420_KFC_USE_STANDBY_WFI1  \
+                                        | EXYNOS5420_KFC_USE_STANDBY_WFI2  \
+                                        | EXYNOS5420_KFC_USE_STANDBY_WFI3)
+
 #endif /* __ASM_ARCH_REGS_PMU_H */
index 108a45f4bb62077fc718bb9e2f473ddfd5b9533b..e3c373082bbee355c736d6f784717f02277df2ca 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/linkage.h>
+#include "smc.h"
 
 #define CPU_MASK       0xff0ffff0
 #define CPU_CORTEX_A9  0x410fc090
@@ -55,3 +56,30 @@ ENTRY(exynos_cpu_resume)
 #endif
        b       cpu_resume
 ENDPROC(exynos_cpu_resume)
+
+       .align
+
+ENTRY(exynos_cpu_resume_ns)
+       mrc     p15, 0, r0, c0, c0, 0
+       ldr     r1, =CPU_MASK
+       and     r0, r0, r1
+       ldr     r1, =CPU_CORTEX_A9
+       cmp     r0, r1
+       bne     skip_cp15
+
+       adr     r0, cp15_save_power
+       ldr     r1, [r0]
+       adr     r0, cp15_save_diag
+       ldr     r2, [r0]
+       mov     r0, #SMC_CMD_C15RESUME
+       dsb
+       smc     #0
+skip_cp15:
+       b       cpu_resume
+ENDPROC(exynos_cpu_resume_ns)
+       .globl cp15_save_diag
+cp15_save_diag:
+       .long   0       @ cp15 diagnostic
+       .globl cp15_save_power
+cp15_save_power:
+       .long   0       @ cp15 power control
index 13a1dc8ecbf2e00ce8427edeaf358b73cf99273a..f7b82f9c1e213053c53aaab321fb0e9f558b8b73 100644 (file)
 #define SMC_CMD_L2X0INVALL     (-24)
 #define SMC_CMD_L2X0DEBUG      (-25)
 
+#ifndef __ASSEMBLY__
+
 extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
 
+#endif /* __ASSEMBLY__ */
+
 #endif
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
new file mode 100644 (file)
index 0000000..f8e7dcd
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * EXYNOS - Suspend support
+ *
+ * Based on arch/arm/mach-s3c2410/pm.c
+ * Copyright (c) 2006 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.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/init.h>
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
+#include <linux/cpu_pm.h>
+#include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/err.h>
+#include <linux/regulator/machine.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/firmware.h>
+#include <asm/mcpm.h>
+#include <asm/smp_scu.h>
+#include <asm/suspend.h>
+
+#include <plat/pm-common.h>
+#include <plat/regs-srom.h>
+
+#include "common.h"
+#include "regs-pmu.h"
+#include "regs-sys.h"
+#include "exynos-pmu.h"
+
+#define S5P_CHECK_SLEEP 0x00000BAD
+
+#define REG_TABLE_END (-1U)
+
+#define EXYNOS5420_CPU_STATE   0x28
+
+/**
+ * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
+ * @hwirq: Hardware IRQ signal of the GIC
+ * @mask: Mask in PMU wake-up mask register
+ */
+struct exynos_wkup_irq {
+       unsigned int hwirq;
+       u32 mask;
+};
+
+static struct sleep_save exynos5_sys_save[] = {
+       SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
+};
+
+static struct sleep_save exynos_core_save[] = {
+       /* SROM side */
+       SAVE_ITEM(S5P_SROM_BW),
+       SAVE_ITEM(S5P_SROM_BC0),
+       SAVE_ITEM(S5P_SROM_BC1),
+       SAVE_ITEM(S5P_SROM_BC2),
+       SAVE_ITEM(S5P_SROM_BC3),
+};
+
+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;
+
+       void (*pm_prepare)(void);
+       void (*pm_resume_prepare)(void);
+       void (*pm_resume)(void);
+       int (*pm_suspend)(void);
+       int (*cpu_suspend)(unsigned long);
+};
+
+struct exynos_pm_data *pm_data;
+
+static int exynos5420_cpu_state;
+static unsigned int exynos_pmu_spare3;
+
+/*
+ * GIC wake-up support
+ */
+
+static u32 exynos_irqwake_intmask = 0xffffffff;
+
+static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
+       { 76, BIT(1) }, /* RTC alarm */
+       { 77, BIT(2) }, /* RTC tick */
+       { /* sentinel */ },
+};
+
+static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
+       { 75, BIT(1) }, /* RTC alarm */
+       { 76, BIT(2) }, /* RTC tick */
+       { /* sentinel */ },
+};
+
+unsigned int exynos_release_ret_regs[] = {
+       S5P_PAD_RET_MAUDIO_OPTION,
+       S5P_PAD_RET_GPIO_OPTION,
+       S5P_PAD_RET_UART_OPTION,
+       S5P_PAD_RET_MMCA_OPTION,
+       S5P_PAD_RET_MMCB_OPTION,
+       S5P_PAD_RET_EBIA_OPTION,
+       S5P_PAD_RET_EBIB_OPTION,
+       REG_TABLE_END,
+};
+
+unsigned int exynos5420_release_ret_regs[] = {
+       EXYNOS_PAD_RET_DRAM_OPTION,
+       EXYNOS_PAD_RET_MAUDIO_OPTION,
+       EXYNOS_PAD_RET_JTAG_OPTION,
+       EXYNOS5420_PAD_RET_GPIO_OPTION,
+       EXYNOS5420_PAD_RET_UART_OPTION,
+       EXYNOS5420_PAD_RET_MMCA_OPTION,
+       EXYNOS5420_PAD_RET_MMCB_OPTION,
+       EXYNOS5420_PAD_RET_MMCC_OPTION,
+       EXYNOS5420_PAD_RET_HSI_OPTION,
+       EXYNOS_PAD_RET_EBIA_OPTION,
+       EXYNOS_PAD_RET_EBIB_OPTION,
+       EXYNOS5420_PAD_RET_SPI_OPTION,
+       EXYNOS5420_PAD_RET_DRAM_COREBLK_OPTION,
+       REG_TABLE_END,
+};
+
+static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
+{
+       const struct exynos_wkup_irq *wkup_irq;
+
+       if (!pm_data->wkup_irq)
+               return -ENOENT;
+       wkup_irq = pm_data->wkup_irq;
+
+       while (wkup_irq->mask) {
+               if (wkup_irq->hwirq == data->hwirq) {
+                       if (!state)
+                               exynos_irqwake_intmask |= wkup_irq->mask;
+                       else
+                               exynos_irqwake_intmask &= ~wkup_irq->mask;
+                       return 0;
+               }
+               ++wkup_irq;
+       }
+
+       return -ENOENT;
+}
+
+static int exynos_cpu_do_idle(void)
+{
+       /* issue the standby signal into the pm unit. */
+       cpu_do_idle();
+
+       pr_info("Failed to suspend the system\n");
+       return 1; /* Aborting suspend */
+}
+static void exynos_flush_cache_all(void)
+{
+       flush_cache_all();
+       outer_flush_all();
+}
+
+static int exynos_cpu_suspend(unsigned long arg)
+{
+       exynos_flush_cache_all();
+       return exynos_cpu_do_idle();
+}
+
+static int exynos5420_cpu_suspend(unsigned long arg)
+{
+       /* MCPM works with HW CPU identifiers */
+       unsigned int mpidr = read_cpuid_mpidr();
+       unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+
+       __raw_writel(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE);
+
+       if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) {
+               mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
+
+               /*
+                * Residency value passed to mcpm_cpu_suspend back-end
+                * has to be given clear semantics. Set to 0 as a
+                * temporary value.
+                */
+               mcpm_cpu_suspend(0);
+       }
+
+       pr_info("Failed to suspend the system\n");
+
+       /* return value != 0 means failure */
+       return 1;
+}
+
+static void exynos_pm_set_wakeup_mask(void)
+{
+       /* Set wake-up mask registers */
+       pmu_raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
+       pmu_raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
+}
+
+static void exynos_pm_enter_sleep_mode(void)
+{
+       /* Set value of power down register for sleep mode */
+       exynos_sys_powerdown_conf(SYS_SLEEP);
+       pmu_raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+}
+
+static void exynos_pm_prepare(void)
+{
+       /* Set wake-up mask registers */
+       exynos_pm_set_wakeup_mask();
+
+       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 */
+       pmu_raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
+}
+
+static void exynos5420_pm_prepare(void)
+{
+       unsigned int tmp;
+
+       /* Set wake-up mask registers */
+       exynos_pm_set_wakeup_mask();
+
+       s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
+
+       exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
+       /*
+        * The cpu state needs to be saved and restored so that the
+        * secondary CPUs will enter low power start. Though the U-Boot
+        * is setting the cpu state with low power flag, the kernel
+        * needs to restore it back in case, the primary cpu fails to
+        * suspend for any reason.
+        */
+       exynos5420_cpu_state = __raw_readl(sysram_base_addr +
+                                               EXYNOS5420_CPU_STATE);
+
+       exynos_pm_enter_sleep_mode();
+
+       /* ensure at least INFORM0 has the resume address */
+       if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
+               pmu_raw_writel(virt_to_phys(mcpm_entry_point), S5P_INFORM0);
+
+       tmp = pmu_raw_readl(EXYNOS5_ARM_L2_OPTION);
+       tmp &= ~EXYNOS5_USE_RETENTION;
+       pmu_raw_writel(tmp, EXYNOS5_ARM_L2_OPTION);
+
+       tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
+       tmp |= EXYNOS5420_UFS;
+       pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
+
+       tmp = pmu_raw_readl(EXYNOS5420_ARM_COMMON_OPTION);
+       tmp &= ~EXYNOS5420_L2RSTDISABLE_VALUE;
+       pmu_raw_writel(tmp, EXYNOS5420_ARM_COMMON_OPTION);
+
+       tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
+       tmp |= EXYNOS5420_EMULATION;
+       pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
+
+       tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
+       tmp |= EXYNOS5420_EMULATION;
+       pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
+}
+
+
+static int exynos_pm_suspend(void)
+{
+       exynos_pm_central_suspend();
+
+       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
+               exynos_cpu_save_register();
+
+       return 0;
+}
+
+static int exynos5420_pm_suspend(void)
+{
+       u32 this_cluster;
+
+       exynos_pm_central_suspend();
+
+       /* Setting SEQ_OPTION register */
+
+       this_cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
+       if (!this_cluster)
+               pmu_raw_writel(EXYNOS5420_ARM_USE_STANDBY_WFI0,
+                               S5P_CENTRAL_SEQ_OPTION);
+       else
+               pmu_raw_writel(EXYNOS5420_KFC_USE_STANDBY_WFI0,
+                               S5P_CENTRAL_SEQ_OPTION);
+       return 0;
+}
+
+static void exynos_pm_release_retention(void)
+{
+       unsigned int i;
+
+       for (i = 0; (pm_data->release_ret_regs[i] != REG_TABLE_END); i++)
+               pmu_raw_writel(EXYNOS_WAKEUP_FROM_LOWPWR,
+                               pm_data->release_ret_regs[i]);
+}
+
+static void exynos_pm_resume(void)
+{
+       u32 cpuid = read_cpuid_part();
+
+       if (exynos_pm_central_resume())
+               goto early_wakeup;
+
+       /* 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)
+               scu_enable(S5P_VA_SCU);
+
+       if (call_firmware_op(resume) == -ENOSYS
+           && cpuid == ARM_CPU_PART_CORTEX_A9)
+               exynos_cpu_restore_register();
+
+early_wakeup:
+
+       /* Clear SLEEP mode set in INFORM1 */
+       pmu_raw_writel(0x0, S5P_INFORM1);
+}
+
+static void exynos5420_prepare_pm_resume(void)
+{
+       if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM))
+               WARN_ON(mcpm_cpu_powered_up());
+}
+
+static void exynos5420_pm_resume(void)
+{
+       unsigned long tmp;
+
+       /* Restore the CPU0 low power state register */
+       tmp = pmu_raw_readl(EXYNOS5_ARM_CORE0_SYS_PWR_REG);
+       pmu_raw_writel(tmp | S5P_CORE_LOCAL_PWR_EN,
+               EXYNOS5_ARM_CORE0_SYS_PWR_REG);
+
+       /* Restore the sysram cpu state register */
+       __raw_writel(exynos5420_cpu_state,
+               sysram_base_addr + EXYNOS5420_CPU_STATE);
+
+       pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
+                       S5P_CENTRAL_SEQ_OPTION);
+
+       if (exynos_pm_central_resume())
+               goto early_wakeup;
+
+       /* For release retention */
+       exynos_pm_release_retention();
+
+       pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
+
+       s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
+
+early_wakeup:
+
+       tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
+       tmp &= ~EXYNOS5420_UFS;
+       pmu_raw_writel(tmp, EXYNOS5420_SFR_AXI_CGDIS1);
+
+       tmp = pmu_raw_readl(EXYNOS5420_FSYS2_OPTION);
+       tmp &= ~EXYNOS5420_EMULATION;
+       pmu_raw_writel(tmp, EXYNOS5420_FSYS2_OPTION);
+
+       tmp = pmu_raw_readl(EXYNOS5420_PSGEN_OPTION);
+       tmp &= ~EXYNOS5420_EMULATION;
+       pmu_raw_writel(tmp, EXYNOS5420_PSGEN_OPTION);
+
+       /* Clear SLEEP mode set in INFORM1 */
+       pmu_raw_writel(0x0, S5P_INFORM1);
+}
+
+/*
+ * Suspend Ops
+ */
+
+static int exynos_suspend_enter(suspend_state_t state)
+{
+       int ret;
+
+       s3c_pm_debug_init();
+
+       S3C_PMDBG("%s: suspending the system...\n", __func__);
+
+       S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
+                       exynos_irqwake_intmask, exynos_get_eint_wake_mask());
+
+       if (exynos_irqwake_intmask == -1U
+           && exynos_get_eint_wake_mask() == -1U) {
+               pr_err("%s: No wake-up sources!\n", __func__);
+               pr_err("%s: Aborting sleep\n", __func__);
+               return -EINVAL;
+       }
+
+       s3c_pm_save_uarts();
+       if (pm_data->pm_prepare)
+               pm_data->pm_prepare();
+       flush_cache_all();
+       s3c_pm_check_store();
+
+       ret = call_firmware_op(suspend);
+       if (ret == -ENOSYS)
+               ret = cpu_suspend(0, pm_data->cpu_suspend);
+       if (ret)
+               return ret;
+
+       if (pm_data->pm_resume_prepare)
+               pm_data->pm_resume_prepare();
+       s3c_pm_restore_uarts();
+
+       S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
+                       pmu_raw_readl(S5P_WAKEUP_STAT));
+
+       s3c_pm_check_restore();
+
+       S3C_PMDBG("%s: resuming the system...\n", __func__);
+
+       return 0;
+}
+
+static int exynos_suspend_prepare(void)
+{
+       int ret;
+
+       /*
+        * REVISIT: It would be better if struct platform_suspend_ops
+        * .prepare handler get the suspend_state_t as a parameter to
+        * avoid hard-coding the suspend to mem state. It's safe to do
+        * it now only because the suspend_valid_only_mem function is
+        * used as the .valid callback used to check if a given state
+        * is supported by the platform anyways.
+        */
+       ret = regulator_suspend_prepare(PM_SUSPEND_MEM);
+       if (ret) {
+               pr_err("Failed to prepare regulators for suspend (%d)\n", ret);
+               return ret;
+       }
+
+       s3c_pm_check_prepare();
+
+       return 0;
+}
+
+static void exynos_suspend_finish(void)
+{
+       int ret;
+
+       s3c_pm_check_cleanup();
+
+       ret = regulator_suspend_finish();
+       if (ret)
+               pr_warn("Failed to resume regulators from suspend (%d)\n", ret);
+}
+
+static const struct platform_suspend_ops exynos_suspend_ops = {
+       .enter          = exynos_suspend_enter,
+       .prepare        = exynos_suspend_prepare,
+       .finish         = exynos_suspend_finish,
+       .valid          = suspend_valid_only_mem,
+};
+
+static const struct exynos_pm_data exynos4_pm_data = {
+       .wkup_irq       = exynos4_wkup_irq,
+       .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
+       .release_ret_regs = exynos_release_ret_regs,
+       .pm_suspend     = exynos_pm_suspend,
+       .pm_resume      = exynos_pm_resume,
+       .pm_prepare     = exynos_pm_prepare,
+       .cpu_suspend    = exynos_cpu_suspend,
+};
+
+static const struct exynos_pm_data exynos5250_pm_data = {
+       .wkup_irq       = exynos5250_wkup_irq,
+       .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)),
+       .release_ret_regs = exynos_release_ret_regs,
+       .extra_save     = exynos5_sys_save,
+       .num_extra_save = ARRAY_SIZE(exynos5_sys_save),
+       .pm_suspend     = exynos_pm_suspend,
+       .pm_resume      = exynos_pm_resume,
+       .pm_prepare     = exynos_pm_prepare,
+       .cpu_suspend    = exynos_cpu_suspend,
+};
+
+static 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,
+       .pm_resume_prepare = exynos5420_prepare_pm_resume,
+       .pm_resume      = exynos5420_pm_resume,
+       .pm_suspend     = exynos5420_pm_suspend,
+       .pm_prepare     = exynos5420_pm_prepare,
+       .cpu_suspend    = exynos5420_cpu_suspend,
+};
+
+static struct of_device_id exynos_pmu_of_device_ids[] = {
+       {
+               .compatible = "samsung,exynos4210-pmu",
+               .data = &exynos4_pm_data,
+       }, {
+               .compatible = "samsung,exynos4212-pmu",
+               .data = &exynos4_pm_data,
+       }, {
+               .compatible = "samsung,exynos4412-pmu",
+               .data = &exynos4_pm_data,
+       }, {
+               .compatible = "samsung,exynos5250-pmu",
+               .data = &exynos5250_pm_data,
+       }, {
+               .compatible = "samsung,exynos5420-pmu",
+               .data = &exynos5420_pm_data,
+       },
+       { /*sentinel*/ },
+};
+
+static struct syscore_ops exynos_pm_syscore_ops;
+
+void __init exynos_pm_init(void)
+{
+       const struct of_device_id *match;
+       u32 tmp;
+
+       of_find_matching_node_and_match(NULL, exynos_pmu_of_device_ids, &match);
+       if (!match) {
+               pr_err("Failed to find PMU node\n");
+               return;
+       }
+       pm_data = (struct exynos_pm_data *) match->data;
+
+       /* Platform-specific GIC callback */
+       gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
+
+       /* All wakeup disable */
+       tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
+       tmp |= pm_data->wake_disable_mask;
+       pmu_raw_writel(tmp, S5P_WAKEUP_MASK);
+
+       exynos_pm_syscore_ops.suspend   = pm_data->pm_suspend;
+       exynos_pm_syscore_ops.resume    = pm_data->pm_resume;
+
+       register_syscore_ops(&exynos_pm_syscore_ops);
+       suspend_set_ops(&exynos_suspend_ops);
+}
index 8c35ae4ff17640acb17610d1000ed720257623a3..07a09570175d8b034082a3639ddfa01999bf59d3 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
index 11b2957f792ba63211dccb975b1d66eacd472e0a..e8627e04e1e669e6485d8eb71e142c2acda25fea 100644 (file)
@@ -633,12 +633,41 @@ config SOC_VF610
        bool "Vybrid Family VF610 support"
        select ARM_GIC
        select PINCTRL_VF610
-       select VF_PIT_TIMER
        select PL310_ERRATA_769419 if CACHE_L2X0
 
        help
          This enable support for Freescale Vybrid VF610 processor.
 
+choice
+       prompt "Clocksource for scheduler clock"
+       depends on SOC_VF610
+       default VF_USE_ARM_GLOBAL_TIMER
+
+       config VF_USE_ARM_GLOBAL_TIMER
+               bool "Use ARM Global Timer"
+               select ARM_GLOBAL_TIMER
+               select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
+               help
+                 Use the ARM Global Timer as clocksource
+
+       config VF_USE_PIT_TIMER
+               bool "Use PIT timer"
+               select VF_PIT_TIMER
+               help
+                 Use SoC Periodic Interrupt Timer (PIT) as clocksource
+
+endchoice
+
+config SOC_LS1021A
+       bool "Freescale LS1021A support"
+       select ARM_GIC
+       select HAVE_ARM_ARCH_TIMER
+       select PCI_DOMAINS if PCI
+       select ZONE_DMA if ARM_LPAE
+
+       help
+         This enable support for Freescale LS1021A processor.
+
 endif
 
 source "arch/arm/mach-imx/devices/Kconfig"
index 6e4fcd8339cdbe24297724ffb631a68517efb491..f5ac685a29fc4d554f63133677c460a8f3d1640c 100644 (file)
@@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
 
 imx5-pm-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
                            clk-pfd.o clk-busy.o clk.o \
@@ -89,7 +89,7 @@ obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
 obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
 obj-$(CONFIG_HAVE_IMX_SRC) += src.o
-ifdef CONFIG_SOC_IMX6
+ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_LS1021A),)
 AFLAGS_headsmp.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
@@ -110,4 +110,6 @@ obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
 
 obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
 
+obj-$(CONFIG_SOC_LS1021A) += mach-ls1021a.o
+
 obj-y += devices/
index 8259a625a920ba3fca9cf567893b2be03e7892c7..7f262fe4ba77d7d28d95aaed8e4d56cf745c83bc 100644 (file)
 #define ANADIG_DIGPROG_IMX6SL  0x280
 
 #define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG   0x40000
+#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN      0x8
 #define BM_ANADIG_REG_CORE_FET_ODRIVE          0x20000000
 #define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG   0x1000
+/* Below MISC0_DISCON_HIGH_SNVS is only for i.MX6SL */
+#define BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS   0x2000
 #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B   0x80000
 #define BM_ANADIG_USB_CHRG_DETECT_EN_B         0x100000
 
@@ -56,16 +59,43 @@ static void imx_anatop_enable_fet_odrive(bool enable)
                BM_ANADIG_REG_CORE_FET_ODRIVE);
 }
 
+static inline void imx_anatop_enable_2p5_pulldown(bool enable)
+{
+       regmap_write(anatop, ANADIG_REG_2P5 + (enable ? REG_SET : REG_CLR),
+               BM_ANADIG_REG_2P5_ENABLE_PULLDOWN);
+}
+
+static inline void imx_anatop_disconnect_high_snvs(bool enable)
+{
+       regmap_write(anatop, ANADIG_ANA_MISC0 + (enable ? REG_SET : REG_CLR),
+               BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS);
+}
+
 void imx_anatop_pre_suspend(void)
 {
-       imx_anatop_enable_weak2p5(true);
+       if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+               imx_anatop_enable_2p5_pulldown(true);
+       else
+               imx_anatop_enable_weak2p5(true);
+
        imx_anatop_enable_fet_odrive(true);
+
+       if (cpu_is_imx6sl())
+               imx_anatop_disconnect_high_snvs(true);
 }
 
 void imx_anatop_post_resume(void)
 {
+       if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
+               imx_anatop_enable_2p5_pulldown(false);
+       else
+               imx_anatop_enable_weak2p5(false);
+
        imx_anatop_enable_fet_odrive(false);
-       imx_anatop_enable_weak2p5(false);
+
+       if (cpu_is_imx6sl())
+               imx_anatop_disconnect_high_snvs(false);
+
 }
 
 static void imx_anatop_usb_chrg_detect_disable(void)
diff --git a/arch/arm/mach-imx/clk-cpu.c b/arch/arm/mach-imx/clk-cpu.c
new file mode 100644 (file)
index 0000000..aa1c345
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, 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.
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+
+struct clk_cpu {
+       struct clk_hw   hw;
+       struct clk      *div;
+       struct clk      *mux;
+       struct clk      *pll;
+       struct clk      *step;
+};
+
+static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw)
+{
+       return container_of(hw, struct clk_cpu, hw);
+}
+
+static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct clk_cpu *cpu = to_clk_cpu(hw);
+
+       return clk_get_rate(cpu->div);
+}
+
+static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
+                              unsigned long *prate)
+{
+       struct clk_cpu *cpu = to_clk_cpu(hw);
+
+       return clk_round_rate(cpu->pll, rate);
+}
+
+static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+                           unsigned long parent_rate)
+{
+       struct clk_cpu *cpu = to_clk_cpu(hw);
+       int ret;
+
+       /* switch to PLL bypass clock */
+       ret = clk_set_parent(cpu->mux, cpu->step);
+       if (ret)
+               return ret;
+
+       /* reprogram PLL */
+       ret = clk_set_rate(cpu->pll, rate);
+       if (ret) {
+               clk_set_parent(cpu->mux, cpu->pll);
+               return ret;
+       }
+       /* switch back to PLL clock */
+       clk_set_parent(cpu->mux, cpu->pll);
+
+       /* Ensure the divider is what we expect */
+       clk_set_rate(cpu->div, rate);
+
+       return 0;
+}
+
+static const struct clk_ops clk_cpu_ops = {
+       .recalc_rate    = clk_cpu_recalc_rate,
+       .round_rate     = clk_cpu_round_rate,
+       .set_rate       = clk_cpu_set_rate,
+};
+
+struct clk *imx_clk_cpu(const char *name, const char *parent_name,
+               struct clk *div, struct clk *mux, struct clk *pll,
+               struct clk *step)
+{
+       struct clk_cpu *cpu;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       cpu = kzalloc(sizeof(*cpu), GFP_KERNEL);
+       if (!cpu)
+               return ERR_PTR(-ENOMEM);
+
+       cpu->div = div;
+       cpu->mux = mux;
+       cpu->pll = pll;
+       cpu->step = step;
+
+       init.name = name;
+       init.ops = &clk_cpu_ops;
+       init.flags = 0;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       cpu->hw.init = &init;
+
+       clk = clk_register(NULL, &cpu->hw);
+       if (IS_ERR(clk))
+               kfree(cpu);
+
+       return clk;
+}
index 72d65214223e3520c0c3f2b9987e62f8e5619531..0f7e536147cb09d3d86783bb30550b931d971a22 100644 (file)
@@ -125,6 +125,8 @@ static const char *mx53_spdif_xtal_sel[] = { "osc", "ckih", "ckih2", "pll4_sw",
 static const char *spdif_sel[] = { "pll1_sw", "pll2_sw", "pll3_sw", "spdif_xtal_sel", };
 static const char *spdif0_com_sel[] = { "spdif0_podf", "ssi1_root_gate", };
 static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", };
+static const char *step_sels[] = { "lp_apm", };
+static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
 
 static struct clk *clk[IMX5_CLK_END];
 static struct clk_onecell_data clk_data;
@@ -193,7 +195,9 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
        clk[IMX5_CLK_USB_PHY_PODF]      = imx_clk_divider("usb_phy_podf", "usb_phy_pred", MXC_CCM_CDCDR, 0, 3);
        clk[IMX5_CLK_USB_PHY_SEL]       = imx_clk_mux("usb_phy_sel", MXC_CCM_CSCMR1, 26, 1,
                                                usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
-       clk[IMX5_CLK_CPU_PODF]          = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
+       clk[IMX5_CLK_STEP_SEL]          = imx_clk_mux("step_sel", MXC_CCM_CCSR, 7, 2, step_sels, ARRAY_SIZE(step_sels));
+       clk[IMX5_CLK_CPU_PODF_SEL]      = imx_clk_mux("cpu_podf_sel", MXC_CCM_CCSR, 2, 1, cpu_podf_sels, ARRAY_SIZE(cpu_podf_sels));
+       clk[IMX5_CLK_CPU_PODF]          = imx_clk_divider("cpu_podf", "cpu_podf_sel", MXC_CCM_CACRR, 0, 3);
        clk[IMX5_CLK_DI_PRED]           = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
        clk[IMX5_CLK_IIM_GATE]          = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
        clk[IMX5_CLK_UART1_IPG_GATE]    = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
@@ -537,6 +541,11 @@ static void __init mx53_clocks_init(struct device_node *np)
        clk[IMX5_CLK_CKO2]              = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
        clk[IMX5_CLK_SPDIF_XTAL_SEL]    = imx_clk_mux("spdif_xtal_sel", MXC_CCM_CSCMR1, 2, 2,
                                                mx53_spdif_xtal_sel, ARRAY_SIZE(mx53_spdif_xtal_sel));
+       clk[IMX5_CLK_ARM]               = imx_clk_cpu("arm", "cpu_podf",
+                                               clk[IMX5_CLK_CPU_PODF],
+                                               clk[IMX5_CLK_CPU_PODF_SEL],
+                                               clk[IMX5_CLK_PLL1_SW],
+                                               clk[IMX5_CLK_STEP_SEL]);
 
        imx_check_clocks(clk, ARRAY_SIZE(clk));
 
@@ -551,6 +560,9 @@ static void __init mx53_clocks_init(struct device_node *np)
        /* move can bus clk to 24MHz */
        clk_set_parent(clk[IMX5_CLK_CAN_SEL], clk[IMX5_CLK_LP_APM]);
 
+       /* make sure step clock is running from 24MHz */
+       clk_set_parent(clk[IMX5_CLK_STEP_SEL], clk[IMX5_CLK_LP_APM]);
+
        clk_prepare_enable(clk[IMX5_CLK_IIM_GATE]);
        imx_print_silicon_rev("i.MX53", mx53_revision());
        clk_disable_unprepare(clk[IMX5_CLK_IIM_GATE]);
index 1412daf4a7145c2464420faabad509a1d11dc4ae..5951660d1bd2363db0326cd83b07fcec7cc908f1 100644 (file)
@@ -50,8 +50,8 @@ static const char *pcie_axi_sels[]    = { "axi", "ahb", };
 static const char *ssi_sels[]          = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", };
 static const char *usdhc_sels[]        = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
-static const char *emi_sels[]          = { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
-static const char *emi_slow_sels[]      = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *eim_sels[]          = { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
+static const char *eim_slow_sels[]      = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *vdo_axi_sels[]      = { "axi", "ahb", };
 static const char *vpu_axi_sels[]      = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
@@ -145,7 +145,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                post_div_table[2].div = 1;
                video_div_table[1].div = 1;
                video_div_table[2].div = 1;
-       };
+       }
 
        clk[IMX6QDL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
        clk[IMX6QDL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 2, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
@@ -302,8 +302,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_USDHC3_SEL]       = imx_clk_fixup_mux("usdhc3_sel", base + 0x1c, 18, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
        clk[IMX6QDL_CLK_USDHC4_SEL]       = imx_clk_fixup_mux("usdhc4_sel", base + 0x1c, 19, 1, usdhc_sels,        ARRAY_SIZE(usdhc_sels), imx_cscmr1_fixup);
        clk[IMX6QDL_CLK_ENFC_SEL]         = imx_clk_mux("enfc_sel",         base + 0x2c, 16, 2, enfc_sels,         ARRAY_SIZE(enfc_sels));
-       clk[IMX6QDL_CLK_EMI_SEL]          = imx_clk_fixup_mux("emi_sel",      base + 0x1c, 27, 2, emi_sels,        ARRAY_SIZE(emi_sels), imx_cscmr1_fixup);
-       clk[IMX6QDL_CLK_EMI_SLOW_SEL]     = imx_clk_fixup_mux("emi_slow_sel", base + 0x1c, 29, 2, emi_slow_sels,   ARRAY_SIZE(emi_slow_sels), imx_cscmr1_fixup);
+       clk[IMX6QDL_CLK_EIM_SEL]          = imx_clk_fixup_mux("eim_sel",      base + 0x1c, 27, 2, eim_sels,        ARRAY_SIZE(eim_sels), imx_cscmr1_fixup);
+       clk[IMX6QDL_CLK_EIM_SLOW_SEL]     = imx_clk_fixup_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels,   ARRAY_SIZE(eim_slow_sels), imx_cscmr1_fixup);
        clk[IMX6QDL_CLK_VDO_AXI_SEL]      = imx_clk_mux("vdo_axi_sel",      base + 0x18, 11, 1, vdo_axi_sels,      ARRAY_SIZE(vdo_axi_sels));
        clk[IMX6QDL_CLK_VPU_AXI_SEL]      = imx_clk_mux("vpu_axi_sel",      base + 0x18, 14, 2, vpu_axi_sels,      ARRAY_SIZE(vpu_axi_sels));
        clk[IMX6QDL_CLK_CKO1_SEL]         = imx_clk_mux("cko1_sel",         base + 0x60, 0,  4, cko1_sels,         ARRAY_SIZE(cko1_sels));
@@ -354,8 +354,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_USDHC4_PODF]      = imx_clk_divider("usdhc4_podf",      "usdhc4_sel",        base + 0x24, 22, 3);
        clk[IMX6QDL_CLK_ENFC_PRED]        = imx_clk_divider("enfc_pred",        "enfc_sel",          base + 0x2c, 18, 3);
        clk[IMX6QDL_CLK_ENFC_PODF]        = imx_clk_divider("enfc_podf",        "enfc_pred",         base + 0x2c, 21, 6);
-       clk[IMX6QDL_CLK_EMI_PODF]         = imx_clk_fixup_divider("emi_podf",   "emi_sel",           base + 0x1c, 20, 3, imx_cscmr1_fixup);
-       clk[IMX6QDL_CLK_EMI_SLOW_PODF]    = imx_clk_fixup_divider("emi_slow_podf", "emi_slow_sel",   base + 0x1c, 23, 3, imx_cscmr1_fixup);
+       clk[IMX6QDL_CLK_EIM_PODF]         = imx_clk_fixup_divider("eim_podf",   "eim_sel",           base + 0x1c, 20, 3, imx_cscmr1_fixup);
+       clk[IMX6QDL_CLK_EIM_SLOW_PODF]    = imx_clk_fixup_divider("eim_slow_podf", "eim_slow_sel",   base + 0x1c, 23, 3, imx_cscmr1_fixup);
        clk[IMX6QDL_CLK_VPU_AXI_PODF]     = imx_clk_divider("vpu_axi_podf",     "vpu_axi_sel",       base + 0x24, 25, 3);
        clk[IMX6QDL_CLK_CKO1_PODF]        = imx_clk_divider("cko1_podf",        "cko1_sel",          base + 0x60, 4,  3);
        clk[IMX6QDL_CLK_CKO2_PODF]        = imx_clk_divider("cko2_podf",        "cko2_sel",          base + 0x60, 21, 3);
@@ -456,7 +456,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_USDHC2]       = imx_clk_gate2("usdhc2",        "usdhc2_podf",       base + 0x80, 4);
        clk[IMX6QDL_CLK_USDHC3]       = imx_clk_gate2("usdhc3",        "usdhc3_podf",       base + 0x80, 6);
        clk[IMX6QDL_CLK_USDHC4]       = imx_clk_gate2("usdhc4",        "usdhc4_podf",       base + 0x80, 8);
-       clk[IMX6QDL_CLK_EIM_SLOW]     = imx_clk_gate2("eim_slow",      "emi_slow_podf",     base + 0x80, 10);
+       clk[IMX6QDL_CLK_EIM_SLOW]     = imx_clk_gate2("eim_slow",      "eim_slow_podf",     base + 0x80, 10);
        clk[IMX6QDL_CLK_VDO_AXI]      = imx_clk_gate2("vdo_axi",       "vdo_axi_sel",       base + 0x80, 12);
        clk[IMX6QDL_CLK_VPU_AXI]      = imx_clk_gate2("vpu_axi",       "vpu_axi_podf",      base + 0x80, 14);
        clk[IMX6QDL_CLK_CKO1]         = imx_clk_gate("cko1",           "cko1_podf",         base + 0x60, 7);
index 57de74da0acfe1aac907e1aa1d5424fffd48530d..0ad6e5442fd8cc80db0027981511a656f8df6103 100644 (file)
@@ -69,7 +69,6 @@ static int clk_pllv3_prepare(struct clk_hw *hw)
 {
        struct clk_pllv3 *pll = to_clk_pllv3(hw);
        u32 val;
-       int ret;
 
        val = readl_relaxed(pll->base);
        if (pll->powerup_set)
@@ -78,11 +77,7 @@ static int clk_pllv3_prepare(struct clk_hw *hw)
                val &= ~BM_PLL_POWER;
        writel_relaxed(val, pll->base);
 
-       ret = clk_pllv3_wait_lock(pll);
-       if (ret)
-               return ret;
-
-       return 0;
+       return clk_pllv3_wait_lock(pll);
 }
 
 static void clk_pllv3_unprepare(struct clk_hw *hw)
index a1781847505075c48b3b91fb206bc74441c88cc6..5937ddee1a99ae8e93fbbcdfa2f8b2cf9beee197 100644 (file)
 #define PFD_PLL1_BASE          (anatop_base + 0x2b0)
 #define PFD_PLL2_BASE          (anatop_base + 0x100)
 #define PFD_PLL3_BASE          (anatop_base + 0xf0)
+#define PLL1_CTRL              (anatop_base + 0x270)
+#define PLL2_CTRL              (anatop_base + 0x30)
 #define PLL3_CTRL              (anatop_base + 0x10)
+#define PLL4_CTRL              (anatop_base + 0x70)
+#define PLL5_CTRL              (anatop_base + 0xe0)
+#define PLL6_CTRL              (anatop_base + 0xa0)
 #define PLL7_CTRL              (anatop_base + 0x20)
+#define ANA_MISC1              (anatop_base + 0x160)
 
 static void __iomem *anatop_base;
 static void __iomem *ccm_base;
@@ -67,25 +73,34 @@ static void __iomem *ccm_base;
 /* sources for multiplexer clocks, this is used multiple times */
 static const char *fast_sels[] = { "firc", "fxosc", };
 static const char *slow_sels[] = { "sirc_32k", "sxosc", };
-static const char *pll1_sels[] = { "pll1_main", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", };
-static const char *pll2_sels[] = { "pll2_main", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", };
-static const char *sys_sels[]  = { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_main", "pll1_pfd_sel", "pll3_main", };
+static const char *pll1_sels[] = { "pll1_sys", "pll1_pfd1", "pll1_pfd2", "pll1_pfd3", "pll1_pfd4", };
+static const char *pll2_sels[] = { "pll2_bus", "pll2_pfd1", "pll2_pfd2", "pll2_pfd3", "pll2_pfd4", };
+static const char *pll_bypass_src_sels[] = { "fast_clk_sel", "lvds1_in", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *sys_sels[]  = { "fast_clk_sel", "slow_clk_sel", "pll2_pfd_sel", "pll2_bus", "pll1_pfd_sel", "pll3_usb_otg", };
 static const char *ddr_sels[]  = { "pll2_pfd2", "sys_sel", };
 static const char *rmii_sels[] = { "enet_ext", "audio_ext", "enet_50m", "enet_25m", };
 static const char *enet_ts_sels[]      = { "enet_ext", "fxosc", "audio_ext", "usb", "enet_ts", "enet_25m", "enet_50m", };
-static const char *esai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", };
-static const char *sai_sels[]  = { "audio_ext", "mlb", "spdif_rx", "pll4_main_div", };
+static const char *esai_sels[] = { "audio_ext", "mlb", "spdif_rx", "pll4_audio_div", };
+static const char *sai_sels[]  = { "audio_ext", "mlb", "spdif_rx", "pll4_audio_div", };
 static const char *nfc_sels[]  = { "platform_bus", "pll1_pfd1", "pll3_pfd1", "pll3_pfd3", };
-static const char *qspi_sels[] = { "pll3_main", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", };
-static const char *esdhc_sels[]        = { "pll3_main", "pll3_pfd3", "pll1_pfd3", "platform_bus", };
-static const char *dcu_sels[]  = { "pll1_pfd2", "pll3_main", };
+static const char *qspi_sels[] = { "pll3_usb_otg", "pll3_pfd4", "pll2_pfd4", "pll1_pfd4", };
+static const char *esdhc_sels[]        = { "pll3_usb_otg", "pll3_pfd3", "pll1_pfd3", "platform_bus", };
+static const char *dcu_sels[]  = { "pll1_pfd2", "pll3_usb_otg", };
 static const char *gpu_sels[]  = { "pll2_pfd2", "pll3_pfd2", };
-static const char *vadc_sels[] = { "pll6_main_div", "pll3_main_div", "pll3_main", };
+static const char *vadc_sels[] = { "pll6_video_div", "pll3_usb_otg_div", "pll3_usb_otg", };
 /* FTM counter clock source, not module clock */
 static const char *ftm_ext_sels[]      = {"sirc_128k", "sxosc", "fxosc_half", "audio_ext", };
 static const char *ftm_fix_sels[]      = { "sxosc", "ipg_bus", };
 
-static struct clk_div_table pll4_main_div_table[] = {
+
+static struct clk_div_table pll4_audio_div_table[] = {
        { .val = 0, .div = 1 },
        { .val = 1, .div = 2 },
        { .val = 2, .div = 6 },
@@ -105,6 +120,17 @@ static unsigned int const clks_init_on[] __initconst = {
        VF610_CLK_DDR_SEL,
 };
 
+static struct clk * __init vf610_get_fixed_clock(
+                               struct device_node *ccm_node, const char *name)
+{
+       struct clk *clk = of_clk_get_by_name(ccm_node, name);
+
+       /* Backward compatibility if device tree is missing clks assignments */
+       if (IS_ERR(clk))
+               clk = imx_obtain_fixed_clock(name, 0);
+       return clk;
+};
+
 static void __init vf610_clocks_init(struct device_node *ccm_node)
 {
        struct device_node *np;
@@ -115,10 +141,13 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_SIRC_32K] = imx_clk_fixed("sirc_32k", 32000);
        clk[VF610_CLK_FIRC] = imx_clk_fixed("firc", 24000000);
 
-       clk[VF610_CLK_SXOSC] = imx_obtain_fixed_clock("sxosc", 0);
-       clk[VF610_CLK_FXOSC] = imx_obtain_fixed_clock("fxosc", 0);
-       clk[VF610_CLK_AUDIO_EXT] = imx_obtain_fixed_clock("audio_ext", 0);
-       clk[VF610_CLK_ENET_EXT] = imx_obtain_fixed_clock("enet_ext", 0);
+       clk[VF610_CLK_SXOSC] = vf610_get_fixed_clock(ccm_node, "sxosc");
+       clk[VF610_CLK_FXOSC] = vf610_get_fixed_clock(ccm_node, "fxosc");
+       clk[VF610_CLK_AUDIO_EXT] = vf610_get_fixed_clock(ccm_node, "audio_ext");
+       clk[VF610_CLK_ENET_EXT] = vf610_get_fixed_clock(ccm_node, "enet_ext");
+
+       /* Clock source from external clock via LVDs PAD */
+       clk[VF610_CLK_ANACLK1] = vf610_get_fixed_clock(ccm_node, "anaclk1");
 
        clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half", "fxosc", 1, 2);
 
@@ -133,31 +162,63 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel", CCM_CCSR, 4, 1, slow_sels, ARRAY_SIZE(slow_sels));
        clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel", CCM_CCSR, 5, 1, fast_sels, ARRAY_SIZE(fast_sels));
 
-       clk[VF610_CLK_PLL1_MAIN] = imx_clk_fixed_factor("pll1_main", "fast_clk_sel", 22, 1);
-       clk[VF610_CLK_PLL1_PFD1] = imx_clk_pfd("pll1_pfd1", "pll1_main", PFD_PLL1_BASE, 0);
-       clk[VF610_CLK_PLL1_PFD2] = imx_clk_pfd("pll1_pfd2", "pll1_main", PFD_PLL1_BASE, 1);
-       clk[VF610_CLK_PLL1_PFD3] = imx_clk_pfd("pll1_pfd3", "pll1_main", PFD_PLL1_BASE, 2);
-       clk[VF610_CLK_PLL1_PFD4] = imx_clk_pfd("pll1_pfd4", "pll1_main", PFD_PLL1_BASE, 3);
-
-       clk[VF610_CLK_PLL2_MAIN] = imx_clk_fixed_factor("pll2_main", "fast_clk_sel", 22, 1);
-       clk[VF610_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_main", PFD_PLL2_BASE, 0);
-       clk[VF610_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_main", PFD_PLL2_BASE, 1);
-       clk[VF610_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3", "pll2_main", PFD_PLL2_BASE, 2);
-       clk[VF610_CLK_PLL2_PFD4] = imx_clk_pfd("pll2_pfd4", "pll2_main", PFD_PLL2_BASE, 3);
-
-       clk[VF610_CLK_PLL3_MAIN] = imx_clk_fixed_factor("pll3_main", "fast_clk_sel", 20, 1);
-       clk[VF610_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_main", PFD_PLL3_BASE, 0);
-       clk[VF610_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_main", PFD_PLL3_BASE, 1);
-       clk[VF610_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_main", PFD_PLL3_BASE, 2);
-       clk[VF610_CLK_PLL3_PFD4] = imx_clk_pfd("pll3_pfd4", "pll3_main", PFD_PLL3_BASE, 3);
-
-       clk[VF610_CLK_PLL4_MAIN] = imx_clk_fixed_factor("pll4_main", "fast_clk_sel", 25, 1);
-       /* Enet pll: fixed 50Mhz */
-       clk[VF610_CLK_PLL5_MAIN] = imx_clk_fixed_factor("pll5_main", "fast_clk_sel", 125, 6);
-       /* pll6: default 960Mhz */
-       clk[VF610_CLK_PLL6_MAIN] = imx_clk_fixed_factor("pll6_main", "fast_clk_sel", 40, 1);
-       /* pll7: USB1 PLL at 480MHz */
-       clk[VF610_CLK_PLL7_MAIN] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_main", "fast_clk_sel", PLL7_CTRL, 0x2);
+       clk[VF610_CLK_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", PLL1_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clk[VF610_CLK_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", PLL2_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clk[VF610_CLK_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", PLL3_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clk[VF610_CLK_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", PLL4_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clk[VF610_CLK_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", PLL5_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clk[VF610_CLK_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", PLL6_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+       clk[VF610_CLK_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", PLL7_CTRL, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+       clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1);
+       clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1);
+       clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1);
+       clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f);
+       clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET,    "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3);
+       clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV,      "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f);
+       clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB,     "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1);
+
+       clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       clk[VF610_PLL3_BYPASS] = imx_clk_mux_flags("pll3_bypass", PLL3_CTRL, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
+       clk[VF610_PLL4_BYPASS] = imx_clk_mux_flags("pll4_bypass", PLL4_CTRL, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels), CLK_SET_RATE_PARENT);
+       clk[VF610_PLL5_BYPASS] = imx_clk_mux_flags("pll5_bypass", PLL5_CTRL, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
+       clk[VF610_PLL6_BYPASS] = imx_clk_mux_flags("pll6_bypass", PLL6_CTRL, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
+       clk[VF610_PLL7_BYPASS] = imx_clk_mux_flags("pll7_bypass", PLL7_CTRL, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
+
+       /* Do not bypass PLLs initially */
+       clk_set_parent(clk[VF610_PLL1_BYPASS], clk[VF610_CLK_PLL1]);
+       clk_set_parent(clk[VF610_PLL2_BYPASS], clk[VF610_CLK_PLL2]);
+       clk_set_parent(clk[VF610_PLL3_BYPASS], clk[VF610_CLK_PLL3]);
+       clk_set_parent(clk[VF610_PLL4_BYPASS], clk[VF610_CLK_PLL4]);
+       clk_set_parent(clk[VF610_PLL5_BYPASS], clk[VF610_CLK_PLL5]);
+       clk_set_parent(clk[VF610_PLL6_BYPASS], clk[VF610_CLK_PLL6]);
+       clk_set_parent(clk[VF610_PLL7_BYPASS], clk[VF610_CLK_PLL7]);
+
+       clk[VF610_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", PLL1_CTRL, 13);
+       clk[VF610_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", PLL2_CTRL, 13);
+       clk[VF610_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", PLL3_CTRL, 13);
+       clk[VF610_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", PLL4_CTRL, 13);
+       clk[VF610_CLK_PLL5_ENET]     = imx_clk_gate("pll5_enet",     "pll5_bypass", PLL5_CTRL, 13);
+       clk[VF610_CLK_PLL6_VIDEO]    = imx_clk_gate("pll6_video",    "pll6_bypass", PLL6_CTRL, 13);
+       clk[VF610_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", PLL7_CTRL, 13);
+
+       clk[VF610_CLK_LVDS1_IN]  = imx_clk_gate_exclusive("lvds1_in", "anaclk1", ANA_MISC1, 12, BIT(10));
+
+       clk[VF610_CLK_PLL1_PFD1] = imx_clk_pfd("pll1_pfd1", "pll1_sys", PFD_PLL1_BASE, 0);
+       clk[VF610_CLK_PLL1_PFD2] = imx_clk_pfd("pll1_pfd2", "pll1_sys", PFD_PLL1_BASE, 1);
+       clk[VF610_CLK_PLL1_PFD3] = imx_clk_pfd("pll1_pfd3", "pll1_sys", PFD_PLL1_BASE, 2);
+       clk[VF610_CLK_PLL1_PFD4] = imx_clk_pfd("pll1_pfd4", "pll1_sys", PFD_PLL1_BASE, 3);
+
+       clk[VF610_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1", "pll2_bus", PFD_PLL2_BASE, 0);
+       clk[VF610_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2", "pll2_bus", PFD_PLL2_BASE, 1);
+       clk[VF610_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3", "pll2_bus", PFD_PLL2_BASE, 2);
+       clk[VF610_CLK_PLL2_PFD4] = imx_clk_pfd("pll2_pfd4", "pll2_bus", PFD_PLL2_BASE, 3);
+
+       clk[VF610_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1", "pll3_usb_otg", PFD_PLL3_BASE, 0);
+       clk[VF610_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", PFD_PLL3_BASE, 1);
+       clk[VF610_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", PFD_PLL3_BASE, 2);
+       clk[VF610_CLK_PLL3_PFD4] = imx_clk_pfd("pll3_pfd4", "pll3_usb_otg", PFD_PLL3_BASE, 3);
 
        clk[VF610_CLK_PLL1_PFD_SEL] = imx_clk_mux("pll1_pfd_sel", CCM_CCSR, 16, 3, pll1_sels, 5);
        clk[VF610_CLK_PLL2_PFD_SEL] = imx_clk_mux("pll2_pfd_sel", CCM_CCSR, 19, 3, pll2_sels, 5);
@@ -167,12 +228,12 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_PLATFORM_BUS] = imx_clk_divider("platform_bus", "sys_bus", CCM_CACRR, 3, 3);
        clk[VF610_CLK_IPG_BUS] = imx_clk_divider("ipg_bus", "platform_bus", CCM_CACRR, 11, 2);
 
-       clk[VF610_CLK_PLL3_MAIN_DIV] = imx_clk_divider("pll3_main_div", "pll3_main", CCM_CACRR, 20, 1);
-       clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_main_div", "pll4_main", 0, CCM_CACRR, 6, 3, 0, pll4_main_div_table, &imx_ccm_lock);
-       clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_main_div", "pll6_main", CCM_CACRR, 21, 1);
+       clk[VF610_CLK_PLL3_MAIN_DIV] = imx_clk_divider("pll3_usb_otg_div", "pll3_usb_otg", CCM_CACRR, 20, 1);
+       clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock);
+       clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1);
 
-       clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_main", PLL3_CTRL, 6);
-       clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_main", PLL7_CTRL, 6);
+       clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6);
+       clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6);
 
        clk[VF610_CLK_USBC0] = imx_clk_gate2("usbc0", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(4));
        clk[VF610_CLK_USBC1] = imx_clk_gate2("usbc1", "ipg_bus", CCM_CCGR7, CCM_CCGRx_CGn(4));
@@ -191,8 +252,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_QSPI1_X1_DIV] = imx_clk_divider("qspi1_x1", "qspi1_x2", CCM_CSCDR3, 11, 1);
        clk[VF610_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_x1", CCM_CCGR8, CCM_CCGRx_CGn(4));
 
-       clk[VF610_CLK_ENET_50M] = imx_clk_fixed_factor("enet_50m", "pll5_main", 1, 10);
-       clk[VF610_CLK_ENET_25M] = imx_clk_fixed_factor("enet_25m", "pll5_main", 1, 20);
+       clk[VF610_CLK_ENET_50M] = imx_clk_fixed_factor("enet_50m", "pll5_enet", 1, 10);
+       clk[VF610_CLK_ENET_25M] = imx_clk_fixed_factor("enet_25m", "pll5_enet", 1, 20);
        clk[VF610_CLK_ENET_SEL] = imx_clk_mux("enet_sel", CCM_CSCMR2, 4, 2, rmii_sels, 4);
        clk[VF610_CLK_ENET_TS_SEL] = imx_clk_mux("enet_ts_sel", CCM_CSCMR2, 0, 3, enet_ts_sels, 7);
        clk[VF610_CLK_ENET] = imx_clk_gate("enet", "enet_sel", CCM_CSCDR1, 24);
index 4cdf8b6a74e8e7d8616400aa2a2c971a5d2d133a..5ef82e2f8fc510ce552b920487fc8c9046d37d50 100644 (file)
@@ -131,4 +131,8 @@ static inline struct clk *imx_clk_fixed_factor(const char *name,
                        CLK_SET_RATE_PARENT, mult, div);
 }
 
+struct clk *imx_clk_cpu(const char *name, const char *parent_name,
+               struct clk *div, struct clk *mux, struct clk *pll,
+               struct clk *step);
+
 #endif
index 1dabf435c592220f1929c4495ad39101392079a7..cfcdb623d78fc5be98092a7f2a65fa735056c7cc 100644 (file)
@@ -61,7 +61,6 @@ struct platform_device *mxc_register_gpio(char *name, int id,
 void mxc_set_cpu_type(unsigned int type);
 void mxc_restart(enum reboot_mode, const char *);
 void mxc_arch_reset_init(void __iomem *);
-void mxc_arch_reset_init_dt(void);
 int mx51_revision(void);
 int mx53_revision(void);
 void imx_set_aips(void __iomem *);
@@ -108,14 +107,15 @@ void imx_gpc_pre_suspend(bool arm_power_off);
 void imx_gpc_post_resume(void);
 void imx_gpc_mask_all(void);
 void imx_gpc_restore_all(void);
-void imx_gpc_irq_mask(struct irq_data *d);
-void imx_gpc_irq_unmask(struct irq_data *d);
+void imx_gpc_hwirq_mask(unsigned int hwirq);
+void imx_gpc_hwirq_unmask(unsigned int hwirq);
 void imx_anatop_init(void);
 void imx_anatop_pre_suspend(void);
 void imx_anatop_post_resume(void);
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
 void imx6q_set_int_mem_clk_lpm(bool enable);
 void imx6sl_set_wait_clk(bool enter);
+int imx_mmdc_get_ddr_type(void);
 
 void imx_cpu_die(unsigned int cpu);
 int imx_cpu_kill(unsigned int cpu);
@@ -157,5 +157,6 @@ static inline void imx_init_l2cache(void) {}
 #endif
 
 extern struct smp_operations imx_smp_ops;
+extern struct smp_operations ls1021a_smp_ops;
 
 #endif
index 82ea74e68482433bd32f58cfed7fb540008a61b0..5f3602ec74fac50c8d0dd827e76782cbd8514f32 100644 (file)
@@ -56,14 +56,14 @@ void imx_gpc_post_resume(void)
 
 static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-       unsigned int idx = d->irq / 32 - 1;
+       unsigned int idx = d->hwirq / 32 - 1;
        u32 mask;
 
        /* Sanity check for SPI irq */
-       if (d->irq < 32)
+       if (d->hwirq < 32)
                return -EINVAL;
 
-       mask = 1 << d->irq % 32;
+       mask = 1 << d->hwirq % 32;
        gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
                                  gpc_wake_irqs[idx] & ~mask;
 
@@ -91,34 +91,44 @@ void imx_gpc_restore_all(void)
                writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
 }
 
-void imx_gpc_irq_unmask(struct irq_data *d)
+void imx_gpc_hwirq_unmask(unsigned int hwirq)
 {
        void __iomem *reg;
        u32 val;
 
-       /* Sanity check for SPI irq */
-       if (d->irq < 32)
-               return;
-
-       reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+       reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
        val = readl_relaxed(reg);
-       val &= ~(1 << d->irq % 32);
+       val &= ~(1 << hwirq % 32);
        writel_relaxed(val, reg);
 }
 
-void imx_gpc_irq_mask(struct irq_data *d)
+void imx_gpc_hwirq_mask(unsigned int hwirq)
 {
        void __iomem *reg;
        u32 val;
 
+       reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
+       val = readl_relaxed(reg);
+       val |= 1 << (hwirq % 32);
+       writel_relaxed(val, reg);
+}
+
+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);
+}
+
+static void imx_gpc_irq_mask(struct irq_data *d)
+{
        /* Sanity check for SPI irq */
-       if (d->irq < 32)
+       if (d->hwirq < 32)
                return;
 
-       reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
-       val = readl_relaxed(reg);
-       val |= 1 << (d->irq % 32);
-       writel_relaxed(val, reg);
+       imx_gpc_hwirq_mask(d->hwirq);
 }
 
 void __init imx_gpc_init(void)
index cf8032bae277071c3ab06e7be2ceba817e2416c1..25defbdb06c434ca93837b3a259c10fefadf28c2 100644 (file)
 #include "common.h"
 #include "mx25.h"
 
-static void __init imx25_dt_init(void)
-{
-       mxc_arch_reset_init_dt();
-
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char * const imx25_dt_board_compat[] __initconst = {
        "fsl,imx25",
        NULL
@@ -33,7 +26,5 @@ 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,
-       .init_machine   = imx25_dt_init,
        .dt_compat      = imx25_dt_board_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index dc8f1a6f45f20a9551045105400a30587d00b1a1..bd42d1bd10aff1a1f0f28db8ea4fe3fac7ee4adc 100644 (file)
@@ -22,8 +22,6 @@ static void __init imx27_dt_init(void)
 {
        struct platform_device_info devinfo = { .name = "cpufreq-dt", };
 
-       mxc_arch_reset_init_dt();
-
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        platform_device_register_full(&devinfo);
@@ -40,5 +38,4 @@ DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)")
        .init_irq       = mx27_init_irq,
        .init_machine   = imx27_dt_init,
        .dt_compat      = imx27_dt_board_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index 418dbc82adc41765c7da7473c5f4af4468fb1941..32100222a01779ab697f27ec0f00d01e18d19ef7 100644 (file)
 #include "common.h"
 #include "mx31.h"
 
-static void __init imx31_dt_init(void)
-{
-       mxc_arch_reset_init_dt();
-
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char * const imx31_dt_board_compat[] __initconst = {
        "fsl,imx31",
        NULL
@@ -40,7 +33,5 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)")
        .init_early     = imx31_init_early,
        .init_irq       = mx31_init_irq,
        .init_time      = imx31_dt_timer_init,
-       .init_machine   = imx31_dt_init,
        .dt_compat      = imx31_dt_board_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index 584fbe1055798fe1f525174f7d660c8393cc3e52..e9396037235dace2db93079ebd5ea0f61c1cfd76 100644 (file)
 #include "common.h"
 #include "mx35.h"
 
-static void __init imx35_dt_init(void)
-{
-       mxc_arch_reset_init_dt();
-
-       of_platform_populate(NULL, of_default_bus_match_table,
-                            NULL, NULL);
-}
-
 static void __init imx35_irq_init(void)
 {
        imx_init_l2cache();
@@ -43,7 +35,5 @@ DT_MACHINE_START(IMX35_DT, "Freescale i.MX35 (Device Tree Support)")
        .map_io         = mx35_map_io,
        .init_early     = imx35_init_early,
        .init_irq       = imx35_irq_init,
-       .init_machine   = imx35_dt_init,
        .dt_compat      = imx35_dt_board_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index 1657fe64cd0fc6a0373ced554d1c4d0b3602b303..d6a30753ca7cb27c9d5c5704e417102d065a2d60 100644 (file)
@@ -44,9 +44,11 @@ static unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
 /*
  * set the mode for a IOMUX pin.
  */
-int mxc_iomux_mode(unsigned int pin_mode)
+void mxc_iomux_mode(unsigned int pin_mode)
 {
-       u32 field, l, mode, ret = 0;
+       u32 field;
+       u32 l;
+       u32 mode;
        void __iomem *reg;
 
        reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK);
@@ -61,8 +63,6 @@ int mxc_iomux_mode(unsigned int pin_mode)
        __raw_writel(l, reg);
 
        spin_unlock(&gpio_mux_lock);
-
-       return ret;
 }
 
 /*
index f79f78a1c0edbe16fe10fbc1478d931c398a75a5..0a5adba61e0b989e84604e95ecb2f2a9daa11113 100644 (file)
@@ -144,7 +144,7 @@ void mxc_iomux_set_gpr(enum iomux_gp_func, bool en);
  * It is called by the setup functions and should not be called directly anymore.
  * It is here visible for backward compatibility
  */
-int mxc_iomux_mode(unsigned int pin_mode);
+void mxc_iomux_mode(unsigned int pin_mode);
 
 #define IOMUX_PADNUM_MASK      0x1ff
 #define IOMUX_GPIONUM_SHIFT    9
index b1e56a94a38289138c209a599b503a40716f3b32..ecf58b9e974b136a8beff6388eab9ee31abd694e 100644 (file)
 
 #include "common.h"
 
-static void __init imx50_dt_init(void)
-{
-       mxc_arch_reset_init_dt();
-
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char * const imx50_dt_board_compat[] __initconst = {
        "fsl,imx50",
        NULL
@@ -30,7 +23,5 @@ static const char * const imx50_dt_board_compat[] __initconst = {
 
 DT_MACHINE_START(IMX50_DT, "Freescale i.MX50 (Device Tree Support)")
        .init_irq       = tzic_init_irq,
-       .init_machine   = imx50_dt_init,
        .dt_compat      = imx50_dt_board_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index 2c5fcaf8675b96bfdd4ee391871c1602eba5ae08..b015129e4045847a3e62b72fb001a71e8b80c55c 100644 (file)
@@ -53,7 +53,6 @@ static void __init imx51_dt_init(void)
 {
        struct platform_device_info devinfo = { .name = "cpufreq-dt", };
 
-       mxc_arch_reset_init_dt();
        imx51_ipu_mipi_setup();
        imx_src_init();
 
@@ -78,5 +77,4 @@ DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
        .init_machine   = imx51_dt_init,
        .init_late      = imx51_init_late,
        .dt_compat      = imx51_dt_board_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index 03dd6ea13accb9688c650c8e5c75617d4cad3555..86316a979297fbafdafb815e4a140a24540d4bc8 100644 (file)
@@ -30,7 +30,6 @@ static void __init imx53_init_early(void)
 
 static void __init imx53_dt_init(void)
 {
-       mxc_arch_reset_init_dt();
        imx_src_init();
 
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -41,6 +40,8 @@ static void __init imx53_dt_init(void)
 static void __init imx53_init_late(void)
 {
        imx53_pm_init();
+
+       platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
 }
 
 static const char * const imx53_dt_board_compat[] __initconst = {
@@ -54,5 +55,4 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
        .init_machine   = imx53_dt_init,
        .init_late      = imx53_init_late,
        .dt_compat      = imx53_dt_board_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index d51c6e99a2e9e287e98fadc1223c73ffcf86315e..5057d61298b71ace2c14c8dd0eb271f0506a0964 100644 (file)
@@ -268,8 +268,6 @@ static void __init imx6q_init_machine(void)
        imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
                              imx_get_soc_revision());
 
-       mxc_arch_reset_init_dt();
-
        parent = imx_soc_device_init();
        if (parent == NULL)
                pr_warn("failed to initialize soc device\n");
@@ -409,5 +407,4 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
        .init_machine   = imx6q_init_machine,
        .init_late      = imx6q_init_late,
        .dt_compat      = imx6q_dt_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index ed263a21d928da397ba003353195c50d5e9ca26a..24bfaaf944c8459f4e2947b1d855ce37cb8dd9b7 100644 (file)
@@ -48,8 +48,6 @@ static void __init imx6sl_init_machine(void)
 {
        struct device *parent;
 
-       mxc_arch_reset_init_dt();
-
        parent = imx_soc_device_init();
        if (parent == NULL)
                pr_warn("failed to initialize soc device\n");
@@ -76,10 +74,8 @@ static const char * const imx6sl_dt_compat[] __initconst = {
 };
 
 DT_MACHINE_START(IMX6SL, "Freescale i.MX6 SoloLite (Device Tree)")
-       .map_io         = debug_ll_io_init,
        .init_irq       = imx6sl_init_irq,
        .init_machine   = imx6sl_init_machine,
        .init_late      = imx6sl_init_late,
        .dt_compat      = imx6sl_dt_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index 3de3b7369aef10ca59968ce9d7a9d89b2d47bec3..7a96c65772344f20e385993b6dd17057bd2af658 100644 (file)
@@ -8,24 +8,73 @@
 
 #include <linux/irqchip.h>
 #include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include "common.h"
 #include "cpuidle.h"
 
+static int ar8031_phy_fixup(struct phy_device *dev)
+{
+       u16 val;
+
+       /* Set RGMII IO voltage to 1.8V */
+       phy_write(dev, 0x1d, 0x1f);
+       phy_write(dev, 0x1e, 0x8);
+
+       /* introduce tx clock delay */
+       phy_write(dev, 0x1d, 0x5);
+       val = phy_read(dev, 0x1e);
+       val |= 0x0100;
+       phy_write(dev, 0x1e, val);
+
+       return 0;
+}
+
+#define PHY_ID_AR8031   0x004dd074
+static void __init imx6sx_enet_phy_init(void)
+{
+       if (IS_BUILTIN(CONFIG_PHYLIB))
+               phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
+                                          ar8031_phy_fixup);
+}
+
+static void __init imx6sx_enet_clk_sel(void)
+{
+       struct regmap *gpr;
+
+       gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
+       if (!IS_ERR(gpr)) {
+               regmap_update_bits(gpr, IOMUXC_GPR1,
+                                  IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0);
+               regmap_update_bits(gpr, IOMUXC_GPR1,
+                                  IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0);
+       } else {
+               pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
+       }
+}
+
+static inline void imx6sx_enet_init(void)
+{
+       imx6sx_enet_phy_init();
+       imx6sx_enet_clk_sel();
+}
+
 static void __init imx6sx_init_machine(void)
 {
        struct device *parent;
 
-       mxc_arch_reset_init_dt();
-
        parent = imx_soc_device_init();
        if (parent == NULL)
                pr_warn("failed to initialize soc device\n");
 
        of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
+       imx6sx_enet_init();
        imx_anatop_init();
        imx6sx_pm_init();
 }
@@ -53,10 +102,8 @@ static const char * const imx6sx_dt_compat[] __initconst = {
 };
 
 DT_MACHINE_START(IMX6SX, "Freescale i.MX6 SoloX (Device Tree)")
-       .map_io         = debug_ll_io_init,
        .init_irq       = imx6sx_init_irq,
        .init_machine   = imx6sx_init_machine,
        .dt_compat      = imx6sx_dt_compat,
        .init_late      = imx6sx_init_late,
-       .restart        = mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-ls1021a.c b/arch/arm/mach-imx/mach-ls1021a.c
new file mode 100644 (file)
index 0000000..b89c858
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static const char * const ls1021a_dt_compat[] __initconst = {
+       "fsl,ls1021a",
+       NULL,
+};
+
+DT_MACHINE_START(LS1021A, "Freescale LS1021A")
+       .smp            = smp_ops(ls1021a_smp_ops),
+       .dt_compat      = ls1021a_dt_compat,
+MACHINE_END
index ee7e57b752a75b82b56faa66a0190e8d4203b285..c11ab6a1dc87f7d18d12c8c3e391dc49acc6afd3 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#include "common.h"
-
-static void __init vf610_init_machine(void)
-{
-       mxc_arch_reset_init_dt();
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char * const vf610_dt_compat[] __initconst = {
        "fsl,vf610",
        NULL,
@@ -28,7 +20,5 @@ static const char * const vf610_dt_compat[] __initconst = {
 DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)")
        .l2c_aux_val    = 0,
        .l2c_aux_mask   = ~0,
-       .init_machine   = vf610_init_machine,
        .dt_compat      = vf610_dt_compat,
-       .restart        = mxc_restart,
 MACHINE_END
index 7a9686ad994ce99fed6431692040d162f3c0f5ce..3729d90cfa461c73a3f0790704af0c0294b4cfb9 100644 (file)
 #define BP_MMDC_MAPSR_PSD      0
 #define BP_MMDC_MAPSR_PSS      4
 
+#define MMDC_MDMISC            0x18
+#define BM_MMDC_MDMISC_DDR_TYPE        0x18
+#define BP_MMDC_MDMISC_DDR_TYPE        0x3
+
+static int ddr_type;
+
 static int imx_mmdc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -31,6 +37,12 @@ static int imx_mmdc_probe(struct platform_device *pdev)
        mmdc_base = of_iomap(np, 0);
        WARN_ON(!mmdc_base);
 
+       reg = mmdc_base + MMDC_MDMISC;
+       /* Get ddr type */
+       val = readl_relaxed(reg);
+       ddr_type = (val & BM_MMDC_MDMISC_DDR_TYPE) >>
+                BP_MMDC_MDMISC_DDR_TYPE;
+
        reg = mmdc_base + MMDC_MAPSR;
 
        /* Enable automatic power saving */
@@ -51,6 +63,11 @@ static int imx_mmdc_probe(struct platform_device *pdev)
        return 0;
 }
 
+int imx_mmdc_get_ddr_type(void)
+{
+       return ddr_type;
+}
+
 static struct of_device_id imx_mmdc_dt_ids[] = {
        { .compatible = "fsl,imx6q-mmdc", },
        { /* sentinel */ }
index 17a41ca65acf89154daecfe55eb0152744110932..4c1343df2ba495b511ecdbf064c8da11f91310ab 100644 (file)
@@ -55,6 +55,8 @@
 #define IMX_CHIP_REVISION_3_3          0x33
 #define IMX_CHIP_REVISION_UNKNOWN      0xff
 
+#define IMX_DDR_TYPE_LPDDR2            1
+
 #ifndef __ASSEMBLY__
 extern unsigned int __mxc_cpu_type;
 #endif
index 771bd25c1025fc94cb1209b8a3d14c644cf123dd..7f270015fe5803dcf5e66e6f6e905abdfa3d876b 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
 #include <linux/smp.h>
+
 #include <asm/cacheflush.h>
 #include <asm/page.h>
 #include <asm/smp_scu.h>
@@ -94,3 +97,33 @@ struct smp_operations  imx_smp_ops __initdata = {
        .cpu_kill               = imx_cpu_kill,
 #endif
 };
+
+#define DCFG_CCSR_SCRATCHRW1   0x200
+
+static int ls1021a_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+       return 0;
+}
+
+static void __init ls1021a_smp_prepare_cpus(unsigned int max_cpus)
+{
+       struct device_node *np;
+       void __iomem *dcfg_base;
+       unsigned long paddr;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,ls1021a-dcfg");
+       dcfg_base = of_iomap(np, 0);
+       BUG_ON(!dcfg_base);
+
+       paddr = virt_to_phys(secondary_startup);
+       writel_relaxed(cpu_to_be32(paddr), dcfg_base + DCFG_CCSR_SCRATCHRW1);
+
+       iounmap(dcfg_base);
+}
+
+struct smp_operations  ls1021a_smp_ops __initdata = {
+       .smp_prepare_cpus       = ls1021a_smp_prepare_cpus,
+       .smp_boot_secondary     = ls1021a_boot_secondary,
+};
index 5c3af8f993d0c490db6c58a7a8c349e0fb282fc6..5d2c1bd5f5ef911834a477d82de71909ec0e80d7 100644 (file)
@@ -88,7 +88,7 @@ struct imx6_pm_base {
 };
 
 struct imx6_pm_socdata {
-       u32 cpu_type;
+       u32 ddr_type;
        const char *mmdc_compat;
        const char *src_compat;
        const char *iomuxc_compat;
@@ -138,7 +138,6 @@ static const u32 imx6sx_mmdc_io_offset[] __initconst = {
 };
 
 static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
-       .cpu_type = MXC_CPU_IMX6Q,
        .mmdc_compat = "fsl,imx6q-mmdc",
        .src_compat = "fsl,imx6q-src",
        .iomuxc_compat = "fsl,imx6q-iomuxc",
@@ -148,7 +147,6 @@ static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
 };
 
 static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
-       .cpu_type = MXC_CPU_IMX6DL,
        .mmdc_compat = "fsl,imx6q-mmdc",
        .src_compat = "fsl,imx6q-src",
        .iomuxc_compat = "fsl,imx6dl-iomuxc",
@@ -158,7 +156,6 @@ static const struct imx6_pm_socdata imx6dl_pm_data __initconst = {
 };
 
 static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
-       .cpu_type = MXC_CPU_IMX6SL,
        .mmdc_compat = "fsl,imx6sl-mmdc",
        .src_compat = "fsl,imx6sl-src",
        .iomuxc_compat = "fsl,imx6sl-iomuxc",
@@ -168,7 +165,6 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
 };
 
 static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
-       .cpu_type = MXC_CPU_IMX6SX,
        .mmdc_compat = "fsl,imx6sx-mmdc",
        .src_compat = "fsl,imx6sx-src",
        .iomuxc_compat = "fsl,imx6sx-iomuxc",
@@ -187,7 +183,7 @@ static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
 struct imx6_cpu_pm_info {
        phys_addr_t pbase; /* The physical address of pm_info. */
        phys_addr_t resume_addr; /* The physical resume address for asm code */
-       u32 cpu_type;
+       u32 ddr_type;
        u32 pm_info_size; /* Size of pm_info. */
        struct imx6_pm_base mmdc_base;
        struct imx6_pm_base src_base;
@@ -261,7 +257,6 @@ static void imx6q_enable_wb(bool enable)
 
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
 {
-       struct irq_data *iomuxc_irq_data = irq_get_irq_data(32);
        u32 val = readl_relaxed(ccm_base + CLPCR);
 
        val &= ~BM_CLPCR_LPM;
@@ -316,9 +311,9 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
         * 3) Software should mask IRQ #32 right after CCM Low-Power mode
         *    is set (set bits 0-1 of CCM_CLPCR).
         */
-       imx_gpc_irq_unmask(iomuxc_irq_data);
+       imx_gpc_hwirq_unmask(32);
        writel_relaxed(val, ccm_base + CLPCR);
-       imx_gpc_irq_mask(iomuxc_irq_data);
+       imx_gpc_hwirq_mask(32);
 
        return 0;
 }
@@ -522,7 +517,7 @@ static int __init imx6q_suspend_init(const struct imx6_pm_socdata *socdata)
                goto pl310_cache_map_failed;
        }
 
-       pm_info->cpu_type = socdata->cpu_type;
+       pm_info->ddr_type = imx_mmdc_get_ddr_type();
        pm_info->mmdc_io_num = socdata->mmdc_io_num;
        mmdc_offset_array = socdata->mmdc_io_offset;
 
index ca4ea2daf25b3e7da3bae73151abff8146154bf3..b99987b023fa426bc8a225aaa3e2bb362d940c3a 100644 (file)
@@ -45,7 +45,7 @@
  */
 #define PM_INFO_PBASE_OFFSET                   0x0
 #define PM_INFO_RESUME_ADDR_OFFSET             0x4
-#define PM_INFO_CPU_TYPE_OFFSET                        0x8
+#define PM_INFO_DDR_TYPE_OFFSET                        0x8
 #define PM_INFO_PM_INFO_SIZE_OFFSET            0xC
 #define PM_INFO_MX6Q_MMDC_P_OFFSET             0x10
 #define PM_INFO_MX6Q_MMDC_V_OFFSET             0x14
        ldreq   r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
        ldrne   r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
 
-       cmp     r3, #MXC_CPU_IMX6SL
+       cmp     r3, #IMX_DDR_TYPE_LPDDR2
        bne     4f
 
        /* reset read FIFO, RST_RD_FIFO */
 ENTRY(imx6_suspend)
        ldr     r1, [r0, #PM_INFO_PBASE_OFFSET]
        ldr     r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
-       ldr     r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
+       ldr     r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
        ldr     r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
 
        /*
@@ -209,8 +209,8 @@ poll_dvfs_set:
        ldr     r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
        ldr     r8, =PM_INFO_MMDC_IO_VAL_OFFSET
        add     r8, r8, r0
-       /* i.MX6SL's last 3 IOs need special setting */
-       cmp     r3, #MXC_CPU_IMX6SL
+       /* LPDDR2's last 3 IOs need special setting */
+       cmp     r3, #IMX_DDR_TYPE_LPDDR2
        subeq   r7, r7, #0x3
 set_mmdc_io_lpm:
        ldr     r9, [r8], #0x8
@@ -218,7 +218,7 @@ set_mmdc_io_lpm:
        subs    r7, r7, #0x1
        bne     set_mmdc_io_lpm
 
-       cmp     r3, #MXC_CPU_IMX6SL
+       cmp     r3, #IMX_DDR_TYPE_LPDDR2
        bne     set_mmdc_io_lpm_done
        ldr     r6, =0x1000
        ldr     r9, [r8], #0x8
@@ -324,7 +324,7 @@ resume:
        str     r7, [r11, #MX6Q_SRC_GPR1]
        str     r7, [r11, #MX6Q_SRC_GPR2]
 
-       ldr     r3, [r0, #PM_INFO_CPU_TYPE_OFFSET]
+       ldr     r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
        mov     r5, #0x1
        resume_mmdc
 
index d14c33fd6b037b5627eb700777f770a833acd9ab..51c35013b673b0d356c12ae8d0853557243c1f34 100644 (file)
@@ -89,21 +89,6 @@ void __init mxc_arch_reset_init(void __iomem *base)
                clk_prepare(wdog_clk);
 }
 
-void __init mxc_arch_reset_init_dt(void)
-{
-       struct device_node *np;
-
-       np = of_find_compatible_node(NULL, NULL, "fsl,imx21-wdt");
-       wdog_base = of_iomap(np, 0);
-       WARN_ON(!wdog_base);
-
-       wdog_clk = of_clk_get(np, 0);
-       if (IS_ERR(wdog_clk))
-               pr_warn("%s: failed to get wdog clock\n", __func__);
-       else
-               clk_prepare(wdog_clk);
-}
-
 #ifdef CONFIG_CACHE_L2X0
 void __init imx_init_l2cache(void)
 {
index c455e974bbfe4f2c05bc4451f1e50ae317482019..02d083489a2641ac5f9d71ca390e53a4965c1570 100644 (file)
@@ -1,3 +1,26 @@
+config ARCH_INTEGRATOR
+       bool "ARM Ltd. Integrator family" if (ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V6)
+       select ARM_AMBA
+       select ARM_PATCH_PHYS_VIRT if MMU
+       select AUTO_ZRELADDR
+       select COMMON_CLK
+       select COMMON_CLK_VERSATILE
+       select GENERIC_CLOCKEVENTS
+       select HAVE_TCM
+       select ICST
+       select MFD_SYSCON
+       select MULTI_IRQ_HANDLER
+       select PLAT_VERSATILE
+       select POWER_RESET
+       select POWER_RESET_VERSATILE
+       select POWER_SUPPLY
+       select SOC_INTEGRATOR_CM
+       select SPARSE_IRQ
+       select USE_OF
+       select VERSATILE_FPGA_IRQ
+       help
+         Support for ARM's Integrator platform.
+
 if ARCH_INTEGRATOR
 
 menu "Integrator Options"
index ec759ded7b609c541204b9ec72dd5814b8c6dea0..1ebe45356b09ca18b85a7dc1da4b0e012685e885 100644 (file)
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y                                  := core.o lm.o leds.o
+obj-y                                  := core.o lm.o
 obj-$(CONFIG_ARCH_INTEGRATOR_AP)       += integrator_ap.o
 obj-$(CONFIG_ARCH_INTEGRATOR_CP)       += integrator_cp.o
 
index 4ecff7bff482e4b6d2108d5f1ec1d417d884ee3c..5b8ba8247f45404d7d4c6d8f318a9295e9ce6e15 100644 (file)
@@ -11,7 +11,6 @@ void cm_clear_irqs(void);
 #define CM_CTRL_LED                    (1 << 0)
 #define CM_CTRL_nMBDET                 (1 << 1)
 #define CM_CTRL_REMAP                  (1 << 2)
-#define CM_CTRL_RESET                  (1 << 3)
 
 /*
  * Integrator/AP,PP2 specific
index ad0ac5547b2c6284988ffba604cd7dae1d83a9c5..96c9dc56cabfc2644d4cf7c832c26d4e87651574 100644 (file)
@@ -4,5 +4,3 @@ extern struct amba_pl010_data ap_uart_data;
 void integrator_init_early(void);
 int integrator_init(bool is_cp);
 void integrator_reserve(void);
-void integrator_restart(enum reboot_mode, const char *);
-void integrator_init_sysfs(struct device *parent, u32 id);
index e3f3aca43efbe65bc9a05e59aa429359ab56918d..948872a419c192e8c66ab287b7128adcdebe365a 100644 (file)
@@ -60,40 +60,6 @@ void cm_control(u32 mask, u32 set)
        raw_spin_unlock_irqrestore(&cm_lock, flags);
 }
 
-static const char *integrator_arch_str(u32 id)
-{
-       switch ((id >> 16) & 0xff) {
-       case 0x00:
-               return "ASB little-endian";
-       case 0x01:
-               return "AHB little-endian";
-       case 0x03:
-               return "AHB-Lite system bus, bi-endian";
-       case 0x04:
-               return "AHB";
-       case 0x08:
-               return "AHB system bus, ASB processor bus";
-       default:
-               return "Unknown";
-       }
-}
-
-static const char *integrator_fpga_str(u32 id)
-{
-       switch ((id >> 12) & 0xf) {
-       case 0x01:
-               return "XC4062";
-       case 0x02:
-               return "XC4085";
-       case 0x03:
-               return "XVC600";
-       case 0x04:
-               return "EPM7256AE (Altera PLD)";
-       default:
-               return "Unknown";
-       }
-}
-
 void cm_clear_irqs(void)
 {
        /* disable core module IRQs */
@@ -109,7 +75,6 @@ static const struct of_device_id cm_match[] = {
 void cm_init(void)
 {
        struct device_node *cm = of_find_matching_node(NULL, cm_match);
-       u32 val;
 
        if (!cm) {
                pr_crit("no core module node found in device tree\n");
@@ -121,13 +86,6 @@ void cm_init(void)
                return;
        }
        cm_clear_irqs();
-       val = readl(cm_base + INTEGRATOR_HDR_ID_OFFSET);
-       pr_info("Detected ARM core module:\n");
-       pr_info("    Manufacturer: %02x\n", (val >> 24));
-       pr_info("    Architecture: %s\n", integrator_arch_str(val));
-       pr_info("    FPGA: %s\n", integrator_fpga_str(val));
-       pr_info("    Build: %02x\n", (val >> 4) & 0xFF);
-       pr_info("    Rev: %c\n", ('A' + (val & 0x03)));
 }
 
 /*
@@ -139,64 +97,3 @@ void __init integrator_reserve(void)
 {
        memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
 }
-
-/*
- * To reset, we hit the on-board reset register in the system FPGA
- */
-void integrator_restart(enum reboot_mode mode, const char *cmd)
-{
-       cm_control(CM_CTRL_RESET, CM_CTRL_RESET);
-}
-
-static u32 integrator_id;
-
-static ssize_t intcp_get_manf(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return sprintf(buf, "%02x\n", integrator_id >> 24);
-}
-
-static struct device_attribute intcp_manf_attr =
-       __ATTR(manufacturer,  S_IRUGO, intcp_get_manf,  NULL);
-
-static ssize_t intcp_get_arch(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return sprintf(buf, "%s\n", integrator_arch_str(integrator_id));
-}
-
-static struct device_attribute intcp_arch_attr =
-       __ATTR(architecture,  S_IRUGO, intcp_get_arch,  NULL);
-
-static ssize_t intcp_get_fpga(struct device *dev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return sprintf(buf, "%s\n", integrator_fpga_str(integrator_id));
-}
-
-static struct device_attribute intcp_fpga_attr =
-       __ATTR(fpga,  S_IRUGO, intcp_get_fpga,  NULL);
-
-static ssize_t intcp_get_build(struct device *dev,
-                              struct device_attribute *attr,
-                              char *buf)
-{
-       return sprintf(buf, "%02x\n", (integrator_id >> 4) & 0xFF);
-}
-
-static struct device_attribute intcp_build_attr =
-       __ATTR(build,  S_IRUGO, intcp_get_build,  NULL);
-
-
-
-void integrator_init_sysfs(struct device *parent, u32 id)
-{
-       integrator_id = id;
-       device_create_file(parent, &intcp_manf_attr);
-       device_create_file(parent, &intcp_arch_attr);
-       device_create_file(parent, &intcp_fpga_attr);
-       device_create_file(parent, &intcp_build_attr);
-}
diff --git a/arch/arm/mach-integrator/include/mach/uncompress.h b/arch/arm/mach-integrator/include/mach/uncompress.h
deleted file mode 100644 (file)
index 8f3cc99..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  arch/arm/mach-integrator/include/mach/uncompress.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; 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
- */
-
-#define AMBA_UART_DR   (*(volatile unsigned char *)0x16000000)
-#define AMBA_UART_LCRH (*(volatile unsigned char *)0x16000008)
-#define AMBA_UART_LCRM (*(volatile unsigned char *)0x1600000c)
-#define AMBA_UART_LCRL (*(volatile unsigned char *)0x16000010)
-#define AMBA_UART_CR   (*(volatile unsigned char *)0x16000014)
-#define AMBA_UART_FR   (*(volatile unsigned char *)0x16000018)
-
-/*
- * This does not append a newline
- */
-static void putc(int c)
-{
-       while (AMBA_UART_FR & (1 << 5))
-               barrier();
-
-       AMBA_UART_DR = c;
-}
-
-static inline void flush(void)
-{
-       while (AMBA_UART_FR & (1 << 3))
-               barrier();
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
index 8ca290b479b1ffb04eb931db39183999caa1b7d8..30003ba447a580563428a644ca93d22c9865ea2e 100644 (file)
 #include <linux/syscore_ops.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/kmi.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/mtd/physmap.h>
-#include <linux/clk.h>
 #include <linux/platform_data/clk-integrator.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/stat.h>
-#include <linux/sys_soc.h>
 #include <linux/termios.h>
-#include <linux/sched_clock.h>
-#include <linux/clk-provider.h>
 
 #include <asm/hardware/arm_timer.h>
 #include <asm/setup.h>
@@ -89,11 +82,6 @@ static void __iomem *ebi_base;
 
 static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
        {
-               .virtual        = IO_ADDRESS(INTEGRATOR_CT_BASE),
-               .pfn            = __phys_to_pfn(INTEGRATOR_CT_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE
-       }, {
                .virtual        = IO_ADDRESS(INTEGRATOR_IC_BASE),
                .pfn            = __phys_to_pfn(INTEGRATOR_IC_BASE),
                .length         = SZ_4K,
@@ -257,188 +245,10 @@ struct amba_pl010_data ap_uart_data = {
        .set_mctrl = integrator_uart_set_mctrl,
 };
 
-/*
- * Where is the timer (VA)?
- */
-#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
-#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
-#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
-
-static unsigned long timer_reload;
-
-static u64 notrace integrator_read_sched_clock(void)
-{
-       return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
-}
-
-static void integrator_clocksource_init(unsigned long inrate,
-                                       void __iomem *base)
-{
-       u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
-       unsigned long rate = inrate;
-
-       if (rate >= 1500000) {
-               rate /= 16;
-               ctrl |= TIMER_CTRL_DIV16;
-       }
-
-       writel(0xffff, base + TIMER_LOAD);
-       writel(ctrl, base + TIMER_CTRL);
-
-       clocksource_mmio_init(base + TIMER_VALUE, "timer2",
-                       rate, 200, 16, clocksource_mmio_readl_down);
-       sched_clock_register(integrator_read_sched_clock, 16, rate);
-}
-
-static void __iomem * clkevt_base;
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
-{
-       struct clock_event_device *evt = dev_id;
-
-       /* clear the interrupt */
-       writel(1, clkevt_base + TIMER_INTCLR);
-
-       evt->event_handler(evt);
-
-       return IRQ_HANDLED;
-}
-
-static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
-{
-       u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
-
-       /* Disable timer */
-       writel(ctrl, clkevt_base + TIMER_CTRL);
-
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               /* Enable the timer and start the periodic tick */
-               writel(timer_reload, clkevt_base + TIMER_LOAD);
-               ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
-               writel(ctrl, clkevt_base + TIMER_CTRL);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-               /* Leave the timer disabled, .set_next_event will enable it */
-               ctrl &= ~TIMER_CTRL_PERIODIC;
-               writel(ctrl, clkevt_base + TIMER_CTRL);
-               break;
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-       case CLOCK_EVT_MODE_RESUME:
-       default:
-               /* Just leave in disabled state */
-               break;
-       }
-
-}
-
-static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
-{
-       unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
-
-       writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
-       writel(next, clkevt_base + TIMER_LOAD);
-       writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
-
-       return 0;
-}
-
-static struct clock_event_device integrator_clockevent = {
-       .name           = "timer1",
-       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .set_mode       = clkevt_set_mode,
-       .set_next_event = clkevt_set_next_event,
-       .rating         = 300,
-};
-
-static struct irqaction integrator_timer_irq = {
-       .name           = "timer",
-       .flags          = IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = integrator_timer_interrupt,
-       .dev_id         = &integrator_clockevent,
-};
-
-static void integrator_clockevent_init(unsigned long inrate,
-                               void __iomem *base, int irq)
-{
-       unsigned long rate = inrate;
-       unsigned int ctrl = 0;
-
-       clkevt_base = base;
-       /* Calculate and program a divisor */
-       if (rate > 0x100000 * HZ) {
-               rate /= 256;
-               ctrl |= TIMER_CTRL_DIV256;
-       } else if (rate > 0x10000 * HZ) {
-               rate /= 16;
-               ctrl |= TIMER_CTRL_DIV16;
-       }
-       timer_reload = rate / HZ;
-       writel(ctrl, clkevt_base + TIMER_CTRL);
-
-       setup_irq(irq, &integrator_timer_irq);
-       clockevents_config_and_register(&integrator_clockevent,
-                                       rate,
-                                       1,
-                                       0xffffU);
-}
-
 void __init ap_init_early(void)
 {
 }
 
-static void __init ap_of_timer_init(void)
-{
-       struct device_node *node;
-       const char *path;
-       void __iomem *base;
-       int err;
-       int irq;
-       struct clk *clk;
-       unsigned long rate;
-
-       of_clk_init(NULL);
-
-       err = of_property_read_string(of_aliases,
-                               "arm,timer-primary", &path);
-       if (WARN_ON(err))
-               return;
-       node = of_find_node_by_path(path);
-       base = of_iomap(node, 0);
-       if (WARN_ON(!base))
-               return;
-
-       clk = of_clk_get(node, 0);
-       BUG_ON(IS_ERR(clk));
-       clk_prepare_enable(clk);
-       rate = clk_get_rate(clk);
-
-       writel(0, base + TIMER_CTRL);
-       integrator_clocksource_init(rate, base);
-
-       err = of_property_read_string(of_aliases,
-                               "arm,timer-secondary", &path);
-       if (WARN_ON(err))
-               return;
-       node = of_find_node_by_path(path);
-       base = of_iomap(node, 0);
-       if (WARN_ON(!base))
-               return;
-       irq = irq_of_parse_and_map(node, 0);
-
-       clk = of_clk_get(node, 0);
-       BUG_ON(IS_ERR(clk));
-       clk_prepare_enable(clk);
-       rate = clk_get_rate(clk);
-
-       writel(0, base + TIMER_CTRL);
-       integrator_clockevent_init(rate, base, irq);
-}
-
 static void __init ap_init_irq_of(void)
 {
        cm_init();
@@ -477,10 +287,6 @@ static void __init ap_init_of(void)
        unsigned long sc_dec;
        struct device_node *syscon;
        struct device_node *ebi;
-       struct device *parent;
-       struct soc_device *soc_dev;
-       struct soc_device_attribute *soc_dev_attr;
-       u32 ap_sc_id;
        int i;
 
        syscon = of_find_matching_node(NULL, ap_syscon_match);
@@ -500,28 +306,6 @@ static void __init ap_init_of(void)
        of_platform_populate(NULL, of_default_bus_match_table,
                        ap_auxdata_lookup, NULL);
 
-       ap_sc_id = readl(ap_syscon_base);
-
-       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
-       if (!soc_dev_attr)
-               return;
-
-       soc_dev_attr->soc_id = "XVC";
-       soc_dev_attr->machine = "Integrator/AP";
-       soc_dev_attr->family = "Integrator";
-       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
-                                          'A' + (ap_sc_id & 0x0f));
-
-       soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR(soc_dev)) {
-               kfree(soc_dev_attr->revision);
-               kfree(soc_dev_attr);
-               return;
-       }
-
-       parent = soc_device_to_device(soc_dev);
-       integrator_init_sysfs(parent, ap_sc_id);
-
        sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
        for (i = 0; i < 4; i++) {
                struct lm_device *lmdev;
@@ -553,8 +337,6 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
        .map_io         = ap_map_io,
        .init_early     = ap_init_early,
        .init_irq       = ap_init_irq_of,
-       .init_time      = ap_of_timer_init,
        .init_machine   = ap_init_of,
-       .restart        = integrator_restart,
        .dt_compat      = ap_dt_board_compat,
 MACHINE_END
index cca02eb75eb5680674eb05e9728d1bfed9dfd97d..b5fb71a36ee63961899709af0f5332fb7ee0a062 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
-#include <linux/sys_soc.h>
 #include <linux/sched_clock.h>
 
 #include <asm/setup.h>
@@ -274,10 +273,6 @@ static const struct of_device_id intcp_syscon_match[] = {
 static void __init intcp_init_of(void)
 {
        struct device_node *cpcon;
-       struct device *parent;
-       struct soc_device *soc_dev;
-       struct soc_device_attribute *soc_dev_attr;
-       u32 intcp_sc_id;
 
        cpcon = of_find_matching_node(NULL, intcp_syscon_match);
        if (!cpcon)
@@ -289,28 +284,6 @@ static void __init intcp_init_of(void)
 
        of_platform_populate(NULL, of_default_bus_match_table,
                             intcp_auxdata_lookup, NULL);
-
-       intcp_sc_id = readl(intcp_con_base);
-
-       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
-       if (!soc_dev_attr)
-               return;
-
-       soc_dev_attr->soc_id = "XCV";
-       soc_dev_attr->machine = "Integrator/CP";
-       soc_dev_attr->family = "Integrator";
-       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
-                                          'A' + (intcp_sc_id & 0x0f));
-
-       soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR(soc_dev)) {
-               kfree(soc_dev_attr->revision);
-               kfree(soc_dev_attr);
-               return;
-       }
-
-       parent = soc_device_to_device(soc_dev);
-       integrator_init_sysfs(parent, intcp_sc_id);
 }
 
 static const char * intcp_dt_board_compat[] = {
@@ -324,6 +297,5 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq_of,
        .init_machine   = intcp_init_of,
-       .restart        = integrator_restart,
        .dt_compat      = intcp_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
deleted file mode 100644 (file)
index f1dcb57..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Driver for the 4 user LEDs found on the Integrator AP/CP baseboard
- * Based on Versatile and RealView machine LED code
- *
- * License terms: GNU General Public License (GPL) version 2
- * Author: Bryan Wu <bryan.wu@canonical.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/leds.h>
-
-#include "hardware.h"
-#include "cm.h"
-
-#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
-
-#define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE)
-#define LEDREG (__io_address(INTEGRATOR_DBG_BASE) + INTEGRATOR_DBG_LEDS_OFFSET)
-
-struct integrator_led {
-       struct led_classdev     cdev;
-       u8                      mask;
-};
-
-/*
- * The triggers lines up below will only be used if the
- * LED triggers are compiled in.
- */
-static const struct {
-       const char *name;
-       const char *trigger;
-} integrator_leds[] = {
-       { "integrator:green0", "heartbeat", },
-       { "integrator:yellow", },
-       { "integrator:red", },
-       { "integrator:green1", },
-       { "integrator:core_module", "cpu0", },
-};
-
-static void integrator_led_set(struct led_classdev *cdev,
-                             enum led_brightness b)
-{
-       struct integrator_led *led = container_of(cdev,
-                                                struct integrator_led, cdev);
-       u32 reg = __raw_readl(LEDREG);
-
-       if (b != LED_OFF)
-               reg |= led->mask;
-       else
-               reg &= ~led->mask;
-
-       while (__raw_readl(ALPHA_REG) & 1)
-               cpu_relax();
-
-       __raw_writel(reg, LEDREG);
-}
-
-static enum led_brightness integrator_led_get(struct led_classdev *cdev)
-{
-       struct integrator_led *led = container_of(cdev,
-                                                struct integrator_led, cdev);
-       u32 reg = __raw_readl(LEDREG);
-
-       return (reg & led->mask) ? LED_FULL : LED_OFF;
-}
-
-static void cm_led_set(struct led_classdev *cdev,
-                             enum led_brightness b)
-{
-       if (b != LED_OFF)
-               cm_control(CM_CTRL_LED, CM_CTRL_LED);
-       else
-               cm_control(CM_CTRL_LED, 0);
-}
-
-static enum led_brightness cm_led_get(struct led_classdev *cdev)
-{
-       u32 reg = cm_get();
-
-       return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF;
-}
-
-static int __init integrator_leds_init(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(integrator_leds); i++) {
-               struct integrator_led *led;
-
-               led = kzalloc(sizeof(*led), GFP_KERNEL);
-               if (!led)
-                       break;
-
-
-               led->cdev.name = integrator_leds[i].name;
-
-               if (i == 4) { /* Setting for LED in core module */
-                       led->cdev.brightness_set = cm_led_set;
-                       led->cdev.brightness_get = cm_led_get;
-               } else {
-                       led->cdev.brightness_set = integrator_led_set;
-                       led->cdev.brightness_get = integrator_led_get;
-               }
-
-               led->cdev.default_trigger = integrator_leds[i].trigger;
-               led->mask = BIT(i);
-
-               if (led_classdev_register(NULL, &led->cdev) < 0) {
-                       kfree(led);
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Since we may have triggers on any subsystem, defer registration
- * until after subsystem_init.
- */
-fs_initcall(integrator_leds_init);
-#endif
index fc4b7b24265e91d5c3007cc5d2ffe42229b85427..8537d4c41e34540a58d9230328b27278919012db 100644 (file)
@@ -652,7 +652,7 @@ static void __iomem *ixp4xx_ioremap_caller(phys_addr_t addr, size_t size,
        return (void __iomem *)addr;
 }
 
-static void ixp4xx_iounmap(void __iomem *addr)
+static void ixp4xx_iounmap(volatile void __iomem *addr)
 {
        if (!is_pci_memory((__force u32)addr))
                __iounmap(addr);
index 559c69a477317b2b0e718ae64af18ebf5a67b5e5..6a722860e34dc2a4fb0d79f095656067d191bd4a 100644 (file)
@@ -58,6 +58,10 @@ static inline int is_pci_memory(u32 addr)
 #define writew(v, p)                   __indirect_writew(v, p)
 #define writel(v, p)                   __indirect_writel(v, p)
 
+#define writeb_relaxed(v, p)           __indirect_writeb(v, p)
+#define writew_relaxed(v, p)           __indirect_writew(v, p)
+#define writel_relaxed(v, p)           __indirect_writel(v, p)
+
 #define writesb(p, v, l)               __indirect_writesb(p, v, l)
 #define writesw(p, v, l)               __indirect_writesw(p, v, l)
 #define writesl(p, v, l)               __indirect_writesl(p, v, l)
@@ -66,6 +70,10 @@ static inline int is_pci_memory(u32 addr)
 #define readw(p)                       __indirect_readw(p)
 #define readl(p)                       __indirect_readl(p)
 
+#define readb_relaxed(p)               __indirect_readb(p)
+#define readw_relaxed(p)               __indirect_readw(p)
+#define readl_relaxed(p)               __indirect_readl(p)
+
 #define readsb(p, v, l)                        __indirect_readsb(p, v, l)
 #define readsw(p, v, l)                        __indirect_readsw(p, v, l)
 #define readsl(p, v, l)                        __indirect_readsl(p, v, l)
@@ -76,7 +84,7 @@ static inline void __indirect_writeb(u8 value, volatile void __iomem *p)
        u32 n, byte_enables, data;
 
        if (!is_pci_memory(addr)) {
-               __raw_writeb(value, addr);
+               __raw_writeb(value, p);
                return;
        }
 
@@ -99,7 +107,7 @@ static inline void __indirect_writew(u16 value, volatile void __iomem *p)
        u32 n, byte_enables, data;
 
        if (!is_pci_memory(addr)) {
-               __raw_writew(value, addr);
+               __raw_writew(value, p);
                return;
        }
 
@@ -141,7 +149,7 @@ static inline unsigned char __indirect_readb(const volatile void __iomem *p)
        u32 n, byte_enables, data;
 
        if (!is_pci_memory(addr))
-               return __raw_readb(addr);
+               return __raw_readb(p);
 
        n = addr % 4;
        byte_enables = (0xf & ~BIT(n)) << IXP4XX_PCI_NP_CBE_BESL;
@@ -164,7 +172,7 @@ static inline unsigned short __indirect_readw(const volatile void __iomem *p)
        u32 n, byte_enables, data;
 
        if (!is_pci_memory(addr))
-               return __raw_readw(addr);
+               return __raw_readw(p);
 
        n = addr % 4;
        byte_enables = (0xf & ~(BIT(n) | BIT(n+1))) << IXP4XX_PCI_NP_CBE_BESL;
@@ -226,6 +234,7 @@ static inline void __indirect_readsl(const volatile void __iomem *bus_addr,
  * I/O functions.
  */
 
+#define outb outb
 static inline void outb(u8 value, u32 addr)
 {
        u32 n, byte_enables, data;
@@ -235,12 +244,14 @@ static inline void outb(u8 value, u32 addr)
        ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data);
 }
 
+#define outsb outsb
 static inline void outsb(u32 io_addr, const u8 *vaddr, u32 count)
 {
        while (count--)
                outb(*vaddr++, io_addr);
 }
 
+#define outw outw
 static inline void outw(u16 value, u32 addr)
 {
        u32 n, byte_enables, data;
@@ -250,23 +261,27 @@ static inline void outw(u16 value, u32 addr)
        ixp4xx_pci_write(addr, byte_enables | NP_CMD_IOWRITE, data);
 }
 
+#define outsw outsw
 static inline void outsw(u32 io_addr, const u16 *vaddr, u32 count)
 {
        while (count--)
                outw(cpu_to_le16(*vaddr++), io_addr);
 }
 
+#define outl outl
 static inline void outl(u32 value, u32 addr)
 {
        ixp4xx_pci_write(addr, NP_CMD_IOWRITE, value);
 }
 
+#define outsl outsl
 static inline void outsl(u32 io_addr, const u32 *vaddr, u32 count)
 {
        while (count--)
                outl(cpu_to_le32(*vaddr++), io_addr);
 }
 
+#define inb inb
 static inline u8 inb(u32 addr)
 {
        u32 n, byte_enables, data;
@@ -278,12 +293,14 @@ static inline u8 inb(u32 addr)
        return data >> (8*n);
 }
 
+#define insb insb
 static inline void insb(u32 io_addr, u8 *vaddr, u32 count)
 {
        while (count--)
                *vaddr++ = inb(io_addr);
 }
 
+#define inw inw
 static inline u16 inw(u32 addr)
 {
        u32 n, byte_enables, data;
@@ -295,12 +312,14 @@ static inline u16 inw(u32 addr)
        return data>>(8*n);
 }
 
+#define insw insw
 static inline void insw(u32 io_addr, u16 *vaddr, u32 count)
 {
        while (count--)
                *vaddr++ = le16_to_cpu(inw(io_addr));
 }
 
+#define inl inl
 static inline u32 inl(u32 addr)
 {
        u32 data;
@@ -310,6 +329,7 @@ static inline u32 inl(u32 addr)
        return data;
 }
 
+#define insl insl
 static inline void insl(u32 io_addr, u32 *vaddr, u32 count)
 {
        while (count--)
index 98a156afaa94bb5854d2b0eb3a83c6f1d6e2e3cd..ea955f6db8b7edd77324879de7b3551aac118ea5 100644 (file)
@@ -9,6 +9,8 @@ config ARCH_KEYSTONE
        select COMMON_CLK_KEYSTONE
        select ARCH_SUPPORTS_BIG_ENDIAN
        select ZONE_DMA if ARM_LPAE
+       select MIGHT_HAVE_PCI
+       select PCI_DOMAINS if PCI
        help
          Support for boards based on the Texas Instruments Keystone family of
          SoCs.
index 2c043a210db00e923fb3161e7cac2ee5f0e8c4b0..f73f588f649cdc7ea3f1cee5e2ed50d334dc575b 100644 (file)
@@ -1,6 +1,6 @@
 config ARCH_MEDIATEK
-       bool "Mediatek MT6589 SoC" if ARCH_MULTI_V7
+       bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
        select ARM_GIC
        select MTK_TIMER
        help
-         Support for Mediatek Cortex-A7 Quad-Core-SoC MT6589.
+         Support for Mediatek MT65xx & MT81xx SoCs
index f2acf075350df967285aa1bcf76d982baf0d2c1f..a9549005097e035271ca34fae7a6a71caffdf956 100644 (file)
@@ -19,6 +19,9 @@
 
 static const char * const mediatek_board_dt_compat[] = {
        "mediatek,mt6589",
+       "mediatek,mt6592",
+       "mediatek,mt8127",
+       "mediatek,mt8135",
        NULL,
 };
 
index 2c1154e1794a30ab212c3b30bff017fef6130952..18301dc9d2e7c2459344b4096a2187f5ae03305d 100644 (file)
@@ -2,6 +2,7 @@ menuconfig ARCH_MESON
        bool "Amlogic Meson SoCs" if ARCH_MULTI_V7
        select GENERIC_IRQ_CHIP
        select ARM_GIC
+       select CACHE_L2X0
 
 if ARCH_MESON
 
@@ -10,4 +11,9 @@ config MACH_MESON6
        default ARCH_MESON
        select MESON6_TIMER
 
+config MACH_MESON8
+       bool "Amlogic Meson8 SoCs support"
+       default ARCH_MESON
+       select MESON6_TIMER
+
 endif
index 5ee064f5a89f67930571ab27036dc0d47367b4d5..5d6affe6a694d38a37a34fe4d57e60f3c5ab7b7c 100644 (file)
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 
-static const char * const m6_common_board_compat[] = {
+static const char * const meson_common_board_compat[] = {
        "amlogic,meson6",
+       "amlogic,meson8",
        NULL,
 };
 
-DT_MACHINE_START(AML8726_MX, "Amlogic Meson6 platform")
-       .dt_compat      = m6_common_board_compat,
+DT_MACHINE_START(MESON, "Amlogic Meson platform")
+       .dt_compat      = meson_common_board_compat,
+       .l2c_aux_val    = 0,
+       .l2c_aux_mask   = ~0,
 MACHINE_END
-
index e24136b42765f69384c3143732961c8975652cab..b4f01497ce0bba1db1bf865b8a850714feca3082 100644 (file)
@@ -7,7 +7,7 @@ CFLAGS_pmsu.o                   := -march=armv7-a
 obj-$(CONFIG_MACH_MVEBU_ANY)    += system-controller.o mvebu-soc-id.o
 
 ifeq ($(CONFIG_MACH_MVEBU_V7),y)
-obj-y                           += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o
+obj-y                           += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o pm.o pm-board.o
 obj-$(CONFIG_SMP)               += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o
 endif
 
index 84cd90d9b8609a1990fb4f2d0ce2a999740973fc..c55bbf81de0ec5a09f4c53e25ff5b3f12b8fabbd 100644 (file)
 #define __MACH_ARMADA_370_XP_H
 
 #ifdef CONFIG_SMP
-#include <linux/cpumask.h>
-
-#define ARMADA_XP_MAX_CPUS 4
-
 void armada_xp_secondary_startup(void);
 extern struct smp_operations armada_xp_smp_ops;
 #endif
 
-int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
-
 #endif /* __MACH_ARMADA_370_XP_H */
index d0d39f150fabf845d33a5ecff9c1d2687d387bb3..89a139ed7d5bd3969f04d651d3cb29b122afb3e3 100644 (file)
 #include <linux/init.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
 #include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
+#include <linux/memblock.h>
 #include <linux/mbus.h>
 #include <linux/signal.h>
 #include <linux/slab.h>
@@ -56,6 +58,54 @@ void __iomem *mvebu_get_scu_base(void)
        return scu_base;
 }
 
+/*
+ * When returning from suspend, the platform goes through the
+ * bootloader, which executes its DDR3 training code. This code has
+ * the unfortunate idea of using the first 10 KB of each DRAM bank to
+ * exercise the RAM and calculate the optimal timings. Therefore, this
+ * area of RAM is overwritten, and shouldn't be used by the kernel if
+ * suspend/resume is supported.
+ */
+
+#ifdef CONFIG_SUSPEND
+#define MVEBU_DDR_TRAINING_AREA_SZ (10 * SZ_1K)
+static int __init mvebu_scan_mem(unsigned long node, const char *uname,
+                                int depth, void *data)
+{
+       const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+       const __be32 *reg, *endp;
+       int l;
+
+       if (type == NULL || strcmp(type, "memory"))
+               return 0;
+
+       reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+       if (reg == NULL)
+               reg = of_get_flat_dt_prop(node, "reg", &l);
+       if (reg == NULL)
+               return 0;
+
+       endp = reg + (l / sizeof(__be32));
+       while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+               u64 base, size;
+
+               base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+               size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+               memblock_reserve(base, MVEBU_DDR_TRAINING_AREA_SZ);
+       }
+
+       return 0;
+}
+
+static void __init mvebu_memblock_reserve(void)
+{
+       of_scan_flat_dt(mvebu_scan_mem, NULL);
+}
+#else
+static void __init mvebu_memblock_reserve(void) {}
+#endif
+
 /*
  * Early versions of Armada 375 SoC have a bug where the BootROM
  * leaves an external data abort pending. The kernel is hit by this
@@ -124,76 +174,12 @@ static void __init i2c_quirk(void)
        return;
 }
 
-#define A375_Z1_THERMAL_FIXUP_OFFSET 0xc
-
-static void __init thermal_quirk(void)
-{
-       struct device_node *np;
-       u32 dev, rev;
-       int res;
-
-       /*
-        * The early SoC Z1 revision needs a quirk to be applied in order
-        * for the thermal controller to work properly. This quirk breaks
-        * the thermal support if applied on a SoC that doesn't need it,
-        * so we enforce the SoC revision to be known.
-        */
-       res = mvebu_get_soc_id(&dev, &rev);
-       if (res < 0 || (res == 0 && rev > ARMADA_375_Z1_REV))
-               return;
-
-       for_each_compatible_node(np, NULL, "marvell,armada375-thermal") {
-               struct property *prop;
-               __be32 newval, *newprop, *oldprop;
-               int len;
-
-               /*
-                * The register offset is at a wrong location. This quirk
-                * creates a new reg property as a clone of the previous
-                * one and corrects the offset.
-                */
-               oldprop = (__be32 *)of_get_property(np, "reg", &len);
-               if (!oldprop)
-                       continue;
-
-               /* Create a duplicate of the 'reg' property */
-               prop = kzalloc(sizeof(*prop), GFP_KERNEL);
-               prop->length = len;
-               prop->name = kstrdup("reg", GFP_KERNEL);
-               prop->value = kzalloc(len, GFP_KERNEL);
-               memcpy(prop->value, oldprop, len);
-
-               /* Fixup the register offset of the second entry */
-               oldprop += 2;
-               newprop = (__be32 *)prop->value + 2;
-               newval = cpu_to_be32(be32_to_cpu(*oldprop) -
-                                    A375_Z1_THERMAL_FIXUP_OFFSET);
-               *newprop = newval;
-               of_update_property(np, prop);
-
-               /*
-                * The thermal controller needs some quirk too, so let's change
-                * the compatible string to reflect this and allow the driver
-                * the take the necessary action.
-                */
-               prop = kzalloc(sizeof(*prop), GFP_KERNEL);
-               prop->name = kstrdup("compatible", GFP_KERNEL);
-               prop->length = sizeof("marvell,armada375-z1-thermal");
-               prop->value = kstrdup("marvell,armada375-z1-thermal",
-                                               GFP_KERNEL);
-               of_update_property(np, prop);
-       }
-       return;
-}
-
 static void __init mvebu_dt_init(void)
 {
        if (of_machine_is_compatible("marvell,armadaxp"))
                i2c_quirk();
-       if (of_machine_is_compatible("marvell,a375-db")) {
+       if (of_machine_is_compatible("marvell,a375-db"))
                external_abort_quirk();
-               thermal_quirk();
-       }
 
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
@@ -206,10 +192,16 @@ static const char * const armada_370_xp_dt_compat[] = {
 DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)")
        .l2c_aux_val    = 0,
        .l2c_aux_mask   = ~0,
+/*
+ * The following field (.smp) is still needed to ensure backward
+ * compatibility with old Device Trees that were not specifying the
+ * cpus enable-method property.
+ */
        .smp            = smp_ops(armada_xp_smp_ops),
        .init_machine   = mvebu_dt_init,
        .init_irq       = mvebu_init_irq,
        .restart        = mvebu_restart,
+       .reserve        = mvebu_memblock_reserve,
        .dt_compat      = armada_370_xp_dt_compat,
 MACHINE_END
 
index 2bdc3233abe2bcc78c527bf8efe4b0032a5880dc..3585cb394e9b952388e4f26bfb5e950bfd0ad9eb 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Coherency fabric (Aurora) support for Armada 370 and XP platforms.
+ * Coherency fabric (Aurora) support for Armada 370, 375, 38x and XP
+ * platforms.
  *
  * Copyright (C) 2012 Marvell
  *
@@ -11,7 +12,7 @@
  * License version 2.  This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
  *
- * The Armada 370 and Armada XP SOCs have a coherency fabric which is
+ * The Armada 370, 375, 38x and XP SOCs have a coherency fabric which is
  * responsible for ensuring hardware coherency between all CPUs and between
  * CPUs and I/O masters. This file initializes the coherency fabric and
  * supplies basic routines for configuring and controlling hardware coherency
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/mbus.h>
-#include <linux/clk.h>
 #include <linux/pci.h>
 #include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
 #include <asm/mach/map.h>
-#include "armada-370-xp.h"
 #include "coherency.h"
 #include "mvebu-soc-id.h"
 
@@ -42,8 +41,6 @@ void __iomem *coherency_base;
 static void __iomem *coherency_cpu_base;
 
 /* Coherency fabric registers */
-#define COHERENCY_FABRIC_CFG_OFFSET               0x4
-
 #define IO_SYNC_BARRIER_CTL_OFFSET                0x0
 
 enum {
@@ -79,157 +76,8 @@ int set_cpu_coherent(void)
        return ll_enable_coherency();
 }
 
-/*
- * The below code implements the I/O coherency workaround on Armada
- * 375. This workaround consists in using the two channels of the
- * first XOR engine to trigger a XOR transaction that serves as the
- * I/O coherency barrier.
- */
-
-static void __iomem *xor_base, *xor_high_base;
-static dma_addr_t coherency_wa_buf_phys[CONFIG_NR_CPUS];
-static void *coherency_wa_buf[CONFIG_NR_CPUS];
-static bool coherency_wa_enabled;
-
-#define XOR_CONFIG(chan)            (0x10 + (chan * 4))
-#define XOR_ACTIVATION(chan)        (0x20 + (chan * 4))
-#define WINDOW_BAR_ENABLE(chan)     (0x240 + ((chan) << 2))
-#define WINDOW_BASE(w)              (0x250 + ((w) << 2))
-#define WINDOW_SIZE(w)              (0x270 + ((w) << 2))
-#define WINDOW_REMAP_HIGH(w)        (0x290 + ((w) << 2))
-#define WINDOW_OVERRIDE_CTRL(chan)  (0x2A0 + ((chan) << 2))
-#define XOR_DEST_POINTER(chan)      (0x2B0 + (chan * 4))
-#define XOR_BLOCK_SIZE(chan)        (0x2C0 + (chan * 4))
-#define XOR_INIT_VALUE_LOW           0x2E0
-#define XOR_INIT_VALUE_HIGH          0x2E4
-
-static inline void mvebu_hwcc_armada375_sync_io_barrier_wa(void)
-{
-       int idx = smp_processor_id();
-
-       /* Write '1' to the first word of the buffer */
-       writel(0x1, coherency_wa_buf[idx]);
-
-       /* Wait until the engine is idle */
-       while ((readl(xor_base + XOR_ACTIVATION(idx)) >> 4) & 0x3)
-               ;
-
-       dmb();
-
-       /* Trigger channel */
-       writel(0x1, xor_base + XOR_ACTIVATION(idx));
-
-       /* Poll the data until it is cleared by the XOR transaction */
-       while (readl(coherency_wa_buf[idx]))
-               ;
-}
-
-static void __init armada_375_coherency_init_wa(void)
-{
-       const struct mbus_dram_target_info *dram;
-       struct device_node *xor_node;
-       struct property *xor_status;
-       struct clk *xor_clk;
-       u32 win_enable = 0;
-       int i;
-
-       pr_warn("enabling coherency workaround for Armada 375 Z1, one XOR engine disabled\n");
-
-       /*
-        * Since the workaround uses one XOR engine, we grab a
-        * reference to its Device Tree node first.
-        */
-       xor_node = of_find_compatible_node(NULL, NULL, "marvell,orion-xor");
-       BUG_ON(!xor_node);
-
-       /*
-        * Then we mark it as disabled so that the real XOR driver
-        * will not use it.
-        */
-       xor_status = kzalloc(sizeof(struct property), GFP_KERNEL);
-       BUG_ON(!xor_status);
-
-       xor_status->value = kstrdup("disabled", GFP_KERNEL);
-       BUG_ON(!xor_status->value);
-
-       xor_status->length = 8;
-       xor_status->name = kstrdup("status", GFP_KERNEL);
-       BUG_ON(!xor_status->name);
-
-       of_update_property(xor_node, xor_status);
-
-       /*
-        * And we remap the registers, get the clock, and do the
-        * initial configuration of the XOR engine.
-        */
-       xor_base = of_iomap(xor_node, 0);
-       xor_high_base = of_iomap(xor_node, 1);
-
-       xor_clk = of_clk_get_by_name(xor_node, NULL);
-       BUG_ON(!xor_clk);
-
-       clk_prepare_enable(xor_clk);
-
-       dram = mv_mbus_dram_info();
-
-       for (i = 0; i < 8; i++) {
-               writel(0, xor_base + WINDOW_BASE(i));
-               writel(0, xor_base + WINDOW_SIZE(i));
-               if (i < 4)
-                       writel(0, xor_base + WINDOW_REMAP_HIGH(i));
-       }
-
-       for (i = 0; i < dram->num_cs; i++) {
-               const struct mbus_dram_window *cs = dram->cs + i;
-               writel((cs->base & 0xffff0000) |
-                      (cs->mbus_attr << 8) |
-                      dram->mbus_dram_target_id, xor_base + WINDOW_BASE(i));
-               writel((cs->size - 1) & 0xffff0000, xor_base + WINDOW_SIZE(i));
-
-               win_enable |= (1 << i);
-               win_enable |= 3 << (16 + (2 * i));
-       }
-
-       writel(win_enable, xor_base + WINDOW_BAR_ENABLE(0));
-       writel(win_enable, xor_base + WINDOW_BAR_ENABLE(1));
-       writel(0, xor_base + WINDOW_OVERRIDE_CTRL(0));
-       writel(0, xor_base + WINDOW_OVERRIDE_CTRL(1));
-
-       for (i = 0; i < CONFIG_NR_CPUS; i++) {
-               coherency_wa_buf[i] = kzalloc(PAGE_SIZE, GFP_KERNEL);
-               BUG_ON(!coherency_wa_buf[i]);
-
-               /*
-                * We can't use the DMA mapping API, since we don't
-                * have a valid 'struct device' pointer
-                */
-               coherency_wa_buf_phys[i] =
-                       virt_to_phys(coherency_wa_buf[i]);
-               BUG_ON(!coherency_wa_buf_phys[i]);
-
-               /*
-                * Configure the XOR engine for memset operation, with
-                * a 128 bytes block size
-                */
-               writel(0x444, xor_base + XOR_CONFIG(i));
-               writel(128, xor_base + XOR_BLOCK_SIZE(i));
-               writel(coherency_wa_buf_phys[i],
-                      xor_base + XOR_DEST_POINTER(i));
-       }
-
-       writel(0x0, xor_base + XOR_INIT_VALUE_LOW);
-       writel(0x0, xor_base + XOR_INIT_VALUE_HIGH);
-
-       coherency_wa_enabled = true;
-}
-
 static inline void mvebu_hwcc_sync_io_barrier(void)
 {
-       if (coherency_wa_enabled) {
-               mvebu_hwcc_armada375_sync_io_barrier_wa();
-               return;
-       }
-
        writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
        while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
 }
@@ -361,25 +209,41 @@ static int coherency_type(void)
 {
        struct device_node *np;
        const struct of_device_id *match;
+       int type;
 
-       np = of_find_matching_node_and_match(NULL, of_coherency_table, &match);
-       if (np) {
-               int type = (int) match->data;
+       /*
+        * The coherency fabric is needed:
+        * - For coherency between processors on Armada XP, so only
+        *   when SMP is enabled.
+        * - For coherency between the processor and I/O devices, but
+        *   this coherency requires many pre-requisites (write
+        *   allocate cache policy, shareable pages, SMP bit set) that
+        *   are only meant in SMP situations.
+        *
+        * Note that this means that on Armada 370, there is currently
+        * no way to use hardware I/O coherency, because even when
+        * CONFIG_SMP is enabled, is_smp() returns false due to the
+        * Armada 370 being a single-core processor. To lift this
+        * limitation, we would have to find a way to make the cache
+        * policy set to write-allocate (on all Armada SoCs), and to
+        * set the shareable attribute in page tables (on all Armada
+        * SoCs except the Armada 370). Unfortunately, such decisions
+        * are taken very early in the kernel boot process, at a point
+        * where we don't know yet on which SoC we are running.
 
-               /* Armada 370/XP coherency works in both UP and SMP */
-               if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
-                       return type;
+        */
+       if (!is_smp())
+               return COHERENCY_FABRIC_TYPE_NONE;
 
-               /* Armada 375 coherency works only on SMP */
-               else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 && is_smp())
-                       return type;
+       np = of_find_matching_node_and_match(NULL, of_coherency_table, &match);
+       if (!np)
+               return COHERENCY_FABRIC_TYPE_NONE;
 
-               /* Armada 380 coherency works only on SMP */
-               else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380 && is_smp())
-                       return type;
-       }
+       type = (int) match->data;
 
-       return COHERENCY_FABRIC_TYPE_NONE;
+       of_node_put(np);
+
+       return type;
 }
 
 int coherency_available(void)
@@ -400,27 +264,16 @@ int __init coherency_init(void)
                 type == COHERENCY_FABRIC_TYPE_ARMADA_380)
                armada_375_380_coherency_init(np);
 
+       of_node_put(np);
+
        return 0;
 }
 
 static int __init coherency_late_init(void)
 {
-       int type = coherency_type();
-
-       if (type == COHERENCY_FABRIC_TYPE_NONE)
-               return 0;
-
-       if (type == COHERENCY_FABRIC_TYPE_ARMADA_375) {
-               u32 dev, rev;
-
-               if (mvebu_get_soc_id(&dev, &rev) == 0 &&
-                   rev == ARMADA_375_Z1_REV)
-                       armada_375_coherency_init_wa();
-       }
-
-       bus_register_notifier(&platform_bus_type,
-                             &mvebu_hwcc_nb);
-
+       if (coherency_available())
+               bus_register_notifier(&platform_bus_type,
+                                     &mvebu_hwcc_nb);
        return 0;
 }
 
index f5d881b5d0f77add65bba38263aaf7b35a51213c..8b2fbc8b6bc6ff46ab2fd38fbb335c5f74d4ec82 100644 (file)
 #include <asm/cp15.h>
 
        .text
-/* Returns the coherency base address in r1 (r0 is untouched) */
+/*
+ * Returns the coherency base address in r1 (r0 is untouched), or 0 if
+ * the coherency fabric is not enabled.
+ */
 ENTRY(ll_get_coherency_base)
        mrc     p15, 0, r1, c1, c0, 0
        tst     r1, #CR_M @ Check MMU bit enabled
@@ -32,8 +35,13 @@ ENTRY(ll_get_coherency_base)
 
        /*
         * MMU is disabled, use the physical address of the coherency
-        * base address.
+        * base address. However, if the coherency fabric isn't mapped
+        * (i.e its virtual address is zero), it means coherency is
+        * not enabled, so we return 0.
         */
+       ldr     r1, =coherency_base
+       cmp     r1, #0
+       beq     2f
        adr     r1, 3f
        ldr     r3, [r1]
        ldr     r1, [r1, r3]
@@ -85,6 +93,9 @@ ENTRY(ll_add_cpu_to_smp_group)
         */
        mov     r0, lr
        bl      ll_get_coherency_base
+       /* Bail out if the coherency is not enabled */
+       cmp     r1, #0
+       reteq   r0
        bl      ll_get_coherency_cpumask
        mov     lr, r0
        add     r0, r1, #ARMADA_XP_CFB_CFG_REG_OFFSET
@@ -107,6 +118,9 @@ ENTRY(ll_enable_coherency)
         */
        mov r0, lr
        bl      ll_get_coherency_base
+       /* Bail out if the coherency is not enabled */
+       cmp     r1, #0
+       reteq   r0
        bl      ll_get_coherency_cpumask
        mov lr, r0
        add     r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
@@ -131,6 +145,9 @@ ENTRY(ll_disable_coherency)
         */
        mov     r0, lr
        bl      ll_get_coherency_base
+       /* Bail out if the coherency is not enabled */
+       cmp     r1, #0
+       reteq   r0
        bl      ll_get_coherency_cpumask
        mov     lr, r0
        add     r0, r1, #ARMADA_XP_CFB_CTL_REG_OFFSET
index 3ccb40c3bf94d1af6c9afcedd1ff38b9f0a3f4e0..3e0aca1f288aee526b9bb76c9538bb7040d1e076 100644 (file)
@@ -25,4 +25,6 @@ int mvebu_system_controller_get_soc_id(u32 *dev, u32 *rev);
 
 void __iomem *mvebu_get_scu_base(void);
 
+int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd));
+
 #endif
index 60fb537870047d2850e8681a57e92f3e4a399460..4a2cadd6b48e218a30ebe44167a1173e4afb2f40 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/resource.h>
-#include "armada-370-xp.h"
 
 static void __iomem *cpu_reset_base;
 static size_t cpu_reset_size;
index be51c998c0cd2f45ba0dcc92401ef9361805b514..08d5ed46b996be2d36ad44285008ab801c90b479 100644 (file)
@@ -22,5 +22,6 @@
 ENTRY(mvebu_cortex_a9_secondary_startup)
 ARM_BE8(setend be)
        bl      v7_invalidate_l1
+       bl      armada_38x_scu_power_up
        b       secondary_startup
 ENDPROC(mvebu_cortex_a9_secondary_startup)
index 47a71a924b965f130b6e21a667eaaa5d7adb53d5..2ec1a42b432152dafadd1bedf793b17f036037d2 100644 (file)
@@ -43,21 +43,70 @@ static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
        else
                mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup);
        smp_wmb();
+
+       /*
+        * Doing this before deasserting the CPUs is needed to wake up CPUs
+        * in the offline state after using CPU hotplug.
+        */
+       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
        ret = mvebu_cpu_reset_deassert(hw_cpu);
        if (ret) {
                pr_err("Could not start the secondary CPU: %d\n", ret);
                return ret;
        }
-       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
        return 0;
 }
+/*
+ * When a CPU is brought back online, either through CPU hotplug, or
+ * because of the boot of a kexec'ed kernel, the PMSU configuration
+ * for this CPU might be in the deep idle state, preventing this CPU
+ * from receiving interrupts. Here, we therefore take out the current
+ * CPU from this state, which was entered by armada_38x_cpu_die()
+ * below.
+ */
+static void armada_38x_secondary_init(unsigned int cpu)
+{
+       mvebu_v7_pmsu_idle_exit();
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void armada_38x_cpu_die(unsigned int cpu)
+{
+       /*
+        * CPU hotplug is implemented by putting offline CPUs into the
+        * deep idle sleep state.
+        */
+       armada_38x_do_cpu_suspend(true);
+}
+
+/*
+ * We need a dummy function, so that platform_can_cpu_hotplug() knows
+ * we support CPU hotplug. However, the function does not need to do
+ * anything, because CPUs going offline can enter the deep idle state
+ * by themselves, without any help from a still alive CPU.
+ */
+static int armada_38x_cpu_kill(unsigned int cpu)
+{
+       return 1;
+}
+#endif
 
 static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = {
        .smp_boot_secondary     = mvebu_cortex_a9_boot_secondary,
 };
 
+static struct smp_operations armada_38x_smp_ops __initdata = {
+       .smp_boot_secondary     = mvebu_cortex_a9_boot_secondary,
+       .smp_secondary_init     = armada_38x_secondary_init,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die                = armada_38x_cpu_die,
+       .cpu_kill               = armada_38x_cpu_kill,
+#endif
+};
+
 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",
-                     &mvebu_cortex_a9_smp_ops);
+                     &armada_38x_smp_ops);
index 895dc373c8a1cce357d8ed93876ef5432673acdc..58cc8c1575eb7e5f8139b69dd7c658f3d50e2efd 100644 (file)
 #include "pmsu.h"
 #include "coherency.h"
 
+#define ARMADA_XP_MAX_CPUS 4
+
 #define AXP_BOOTROM_BASE 0xfff00000
 #define AXP_BOOTROM_SIZE 0x100000
 
-static struct clk *__init get_cpu_clk(int cpu)
+static struct clk *get_cpu_clk(int cpu)
 {
        struct clk *cpu_clk;
        struct device_node *np = of_get_cpu_node(cpu, NULL);
@@ -46,29 +48,28 @@ static struct clk *__init get_cpu_clk(int cpu)
        return cpu_clk;
 }
 
-static void __init set_secondary_cpus_clock(void)
+static void set_secondary_cpu_clock(unsigned int cpu)
 {
-       int thiscpu, cpu;
+       int thiscpu;
        unsigned long rate;
        struct clk *cpu_clk;
 
-       thiscpu = smp_processor_id();
+       thiscpu = get_cpu();
+
        cpu_clk = get_cpu_clk(thiscpu);
        if (!cpu_clk)
-               return;
+               goto out;
        clk_prepare_enable(cpu_clk);
        rate = clk_get_rate(cpu_clk);
 
-       /* set all the other CPU clk to the same rate than the boot CPU */
-       for_each_possible_cpu(cpu) {
-               if (cpu == thiscpu)
-                       continue;
-               cpu_clk = get_cpu_clk(cpu);
-               if (!cpu_clk)
-                       return;
-               clk_set_rate(cpu_clk, rate);
-               clk_prepare_enable(cpu_clk);
-       }
+       cpu_clk = get_cpu_clk(cpu);
+       if (!cpu_clk)
+               goto out;
+       clk_set_rate(cpu_clk, rate);
+       clk_prepare_enable(cpu_clk);
+
+out:
+       put_cpu();
 }
 
 static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -78,6 +79,7 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
        pr_info("Booting CPU %d\n", cpu);
 
        hw_cpu = cpu_logical_map(cpu);
+       set_secondary_cpu_clock(hw_cpu);
        mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup);
 
        /*
@@ -126,7 +128,6 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
        struct resource res;
        int err;
 
-       set_secondary_cpus_clock();
        flush_cache_all();
        set_cpu_coherent();
 
diff --git a/arch/arm/mach-mvebu/pm-board.c b/arch/arm/mach-mvebu/pm-board.c
new file mode 100644 (file)
index 0000000..6dfd4ab
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Board-level suspend/resume support.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * 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/delay.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include "common.h"
+
+#define ARMADA_XP_GP_PIC_NR_GPIOS 3
+
+static void __iomem *gpio_ctrl;
+static int pic_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];
+static int pic_raw_gpios[ARMADA_XP_GP_PIC_NR_GPIOS];
+
+static void mvebu_armada_xp_gp_pm_enter(void __iomem *sdram_reg, u32 srcmd)
+{
+       u32 reg, ackcmd;
+       int i;
+
+       /* Put 001 as value on the GPIOs */
+       reg = readl(gpio_ctrl);
+       for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
+               reg &= ~BIT(pic_raw_gpios[i]);
+       reg |= BIT(pic_raw_gpios[0]);
+       writel(reg, gpio_ctrl);
+
+       /* Prepare writing 111 to the GPIOs */
+       ackcmd = readl(gpio_ctrl);
+       for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++)
+               ackcmd |= BIT(pic_raw_gpios[i]);
+
+       /*
+        * Wait a while, the PIC needs quite a bit of time between the
+        * two GPIO commands.
+        */
+       mdelay(3000);
+
+       asm volatile (
+               /* Align to a cache line */
+               ".balign 32\n\t"
+
+               /* Enter self refresh */
+               "str %[srcmd], [%[sdram_reg]]\n\t"
+
+               /*
+                * Wait 100 cycles for DDR to enter self refresh, by
+                * doing 50 times two instructions.
+                */
+               "mov r1, #50\n\t"
+               "1: subs r1, r1, #1\n\t"
+               "bne 1b\n\t"
+
+               /* Issue the command ACK */
+               "str %[ackcmd], [%[gpio_ctrl]]\n\t"
+
+               /* Trap the processor */
+               "b .\n\t"
+               : : [srcmd] "r" (srcmd), [sdram_reg] "r" (sdram_reg),
+                 [ackcmd] "r" (ackcmd), [gpio_ctrl] "r" (gpio_ctrl) : "r1");
+}
+
+static int mvebu_armada_xp_gp_pm_init(void)
+{
+       struct device_node *np;
+       struct device_node *gpio_ctrl_np;
+       int ret = 0, i;
+
+       if (!of_machine_is_compatible("marvell,axp-gp"))
+               return -ENODEV;
+
+       np = of_find_node_by_name(NULL, "pm_pic");
+       if (!np)
+               return -ENODEV;
+
+       for (i = 0; i < ARMADA_XP_GP_PIC_NR_GPIOS; i++) {
+               char *name;
+               struct of_phandle_args args;
+
+               pic_gpios[i] = of_get_named_gpio(np, "ctrl-gpios", i);
+               if (pic_gpios[i] < 0) {
+                       ret = -ENODEV;
+                       goto out;
+               }
+
+               name = kasprintf(GFP_KERNEL, "pic-pin%d", i);
+               if (!name) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               ret = gpio_request(pic_gpios[i], name);
+               if (ret < 0) {
+                       kfree(name);
+                       goto out;
+               }
+
+               ret = gpio_direction_output(pic_gpios[i], 0);
+               if (ret < 0) {
+                       gpio_free(pic_gpios[i]);
+                       kfree(name);
+                       goto out;
+               }
+
+               ret = of_parse_phandle_with_fixed_args(np, "ctrl-gpios", 2,
+                                                      i, &args);
+               if (ret < 0) {
+                       gpio_free(pic_gpios[i]);
+                       kfree(name);
+                       goto out;
+               }
+
+               gpio_ctrl_np = args.np;
+               pic_raw_gpios[i] = args.args[0];
+       }
+
+       gpio_ctrl = of_iomap(gpio_ctrl_np, 0);
+       if (!gpio_ctrl)
+               return -ENOMEM;
+
+       mvebu_pm_init(mvebu_armada_xp_gp_pm_enter);
+
+out:
+       of_node_put(np);
+       return ret;
+}
+
+late_initcall(mvebu_armada_xp_gp_pm_init);
diff --git a/arch/arm/mach-mvebu/pm.c b/arch/arm/mach-mvebu/pm.c
new file mode 100644 (file)
index 0000000..6573a8f
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Suspend/resume support. Currently supporting Armada XP only.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * 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/cpu_pm.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mbus.h>
+#include <linux/of_address.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/outercache.h>
+#include <asm/suspend.h>
+
+#include "coherency.h"
+#include "pmsu.h"
+
+#define SDRAM_CONFIG_OFFS                  0x0
+#define  SDRAM_CONFIG_SR_MODE_BIT          BIT(24)
+#define SDRAM_OPERATION_OFFS               0x18
+#define  SDRAM_OPERATION_SELF_REFRESH      0x7
+#define SDRAM_DLB_EVICTION_OFFS            0x30c
+#define  SDRAM_DLB_EVICTION_THRESHOLD_MASK 0xff
+
+static void (*mvebu_board_pm_enter)(void __iomem *sdram_reg, u32 srcmd);
+static void __iomem *sdram_ctrl;
+
+static int mvebu_pm_powerdown(unsigned long data)
+{
+       u32 reg, srcmd;
+
+       flush_cache_all();
+       outer_flush_all();
+
+       /*
+        * Issue a Data Synchronization Barrier instruction to ensure
+        * that all state saving has been completed.
+        */
+       dsb();
+
+       /* Flush the DLB and wait ~7 usec */
+       reg = readl(sdram_ctrl + SDRAM_DLB_EVICTION_OFFS);
+       reg &= ~SDRAM_DLB_EVICTION_THRESHOLD_MASK;
+       writel(reg, sdram_ctrl + SDRAM_DLB_EVICTION_OFFS);
+
+       udelay(7);
+
+       /* Set DRAM in battery backup mode */
+       reg = readl(sdram_ctrl + SDRAM_CONFIG_OFFS);
+       reg &= ~SDRAM_CONFIG_SR_MODE_BIT;
+       writel(reg, sdram_ctrl + SDRAM_CONFIG_OFFS);
+
+       /* Prepare to go to self-refresh */
+
+       srcmd = readl(sdram_ctrl + SDRAM_OPERATION_OFFS);
+       srcmd &= ~0x1F;
+       srcmd |= SDRAM_OPERATION_SELF_REFRESH;
+
+       mvebu_board_pm_enter(sdram_ctrl + SDRAM_OPERATION_OFFS, srcmd);
+
+       return 0;
+}
+
+#define BOOT_INFO_ADDR      0x3000
+#define BOOT_MAGIC_WORD            0xdeadb002
+#define BOOT_MAGIC_LIST_END 0xffffffff
+
+/*
+ * Those registers are accessed before switching the internal register
+ * base, which is why we hardcode the 0xd0000000 base address, the one
+ * used by the SoC out of reset.
+ */
+#define MBUS_WINDOW_12_CTRL       0xd00200b0
+#define MBUS_INTERNAL_REG_ADDRESS 0xd0020080
+
+#define SDRAM_WIN_BASE_REG(x)  (0x20180 + (0x8*x))
+#define SDRAM_WIN_CTRL_REG(x)  (0x20184 + (0x8*x))
+
+static phys_addr_t mvebu_internal_reg_base(void)
+{
+       struct device_node *np;
+       __be32 in_addr[2];
+
+       np = of_find_node_by_name(NULL, "internal-regs");
+       BUG_ON(!np);
+
+       /*
+        * Ask the DT what is the internal register address on this
+        * platform. In the mvebu-mbus DT binding, 0xf0010000
+        * corresponds to the internal register window.
+        */
+       in_addr[0] = cpu_to_be32(0xf0010000);
+       in_addr[1] = 0x0;
+
+       return of_translate_address(np, in_addr);
+}
+
+static void mvebu_pm_store_bootinfo(void)
+{
+       u32 *store_addr;
+       phys_addr_t resume_pc;
+
+       store_addr = phys_to_virt(BOOT_INFO_ADDR);
+       resume_pc = virt_to_phys(armada_370_xp_cpu_resume);
+
+       /*
+        * The bootloader expects the first two words to be a magic
+        * value (BOOT_MAGIC_WORD), followed by the address of the
+        * resume code to jump to. Then, it expects a sequence of
+        * (address, value) pairs, which can be used to restore the
+        * value of certain registers. This sequence must end with the
+        * BOOT_MAGIC_LIST_END magic value.
+        */
+
+       writel(BOOT_MAGIC_WORD, store_addr++);
+       writel(resume_pc, store_addr++);
+
+       /*
+        * Some platforms remap their internal register base address
+        * to 0xf1000000. However, out of reset, window 12 starts at
+        * 0xf0000000 and ends at 0xf7ffffff, which would overlap with
+        * the internal registers. Therefore, disable window 12.
+        */
+       writel(MBUS_WINDOW_12_CTRL, store_addr++);
+       writel(0x0, store_addr++);
+
+       /*
+        * Set the internal register base address to the value
+        * expected by Linux, as read from the Device Tree.
+        */
+       writel(MBUS_INTERNAL_REG_ADDRESS, store_addr++);
+       writel(mvebu_internal_reg_base(), store_addr++);
+
+       /*
+        * Ask the mvebu-mbus driver to store the SDRAM window
+        * configuration, which has to be restored by the bootloader
+        * before re-entering the kernel on resume.
+        */
+       store_addr += mvebu_mbus_save_cpu_target(store_addr);
+
+       writel(BOOT_MAGIC_LIST_END, store_addr);
+}
+
+static int mvebu_pm_enter(suspend_state_t state)
+{
+       if (state != PM_SUSPEND_MEM)
+               return -EINVAL;
+
+       cpu_pm_enter();
+
+       mvebu_pm_store_bootinfo();
+       cpu_suspend(0, mvebu_pm_powerdown);
+
+       outer_resume();
+
+       mvebu_v7_pmsu_idle_exit();
+
+       set_cpu_coherent();
+
+       cpu_pm_exit();
+
+       return 0;
+}
+
+static const struct platform_suspend_ops mvebu_pm_ops = {
+       .enter = mvebu_pm_enter,
+       .valid = suspend_valid_only_mem,
+};
+
+int mvebu_pm_init(void (*board_pm_enter)(void __iomem *sdram_reg, u32 srcmd))
+{
+       struct device_node *np;
+       struct resource res;
+
+       if (!of_machine_is_compatible("marvell,armadaxp"))
+               return -ENODEV;
+
+       np = of_find_compatible_node(NULL, NULL,
+                                    "marvell,armada-xp-sdram-controller");
+       if (!np)
+               return -ENODEV;
+
+       if (of_address_to_resource(np, 0, &res)) {
+               of_node_put(np);
+               return -ENODEV;
+       }
+
+       if (!request_mem_region(res.start, resource_size(&res),
+                               np->full_name)) {
+               of_node_put(np);
+               return -EBUSY;
+       }
+
+       sdram_ctrl = ioremap(res.start, resource_size(&res));
+       if (!sdram_ctrl) {
+               release_mem_region(res.start, resource_size(&res));
+               of_node_put(np);
+               return -ENOMEM;
+       }
+
+       of_node_put(np);
+
+       mvebu_board_pm_enter = board_pm_enter;
+
+       suspend_set_ops(&mvebu_pm_ops);
+
+       return 0;
+}
index bbd8664d1bacb2732ec58072d630e70d963904de..d8ab605a44fa7f80a87edbd2ffeadd386903ea16 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/clk.h>
 #include <linux/cpu_pm.h>
+#include <linux/cpufreq-dt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -39,7 +40,6 @@
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
 #include "common.h"
-#include "armada-370-xp.h"
 
 
 #define PMSU_BASE_OFFSET    0x100
@@ -312,7 +312,7 @@ static int armada_370_xp_cpu_suspend(unsigned long deepidle)
        return cpu_suspend(deepidle, armada_370_xp_pmsu_idle_enter);
 }
 
-static int armada_38x_do_cpu_suspend(unsigned long deepidle)
+int armada_38x_do_cpu_suspend(unsigned long deepidle)
 {
        unsigned long flags = 0;
 
@@ -572,6 +572,10 @@ int mvebu_pmsu_dfs_request(int cpu)
        return 0;
 }
 
+struct cpufreq_dt_platform_data cpufreq_dt_pd = {
+       .independent_clocks = true,
+};
+
 static int __init armada_xp_pmsu_cpufreq_init(void)
 {
        struct device_node *np;
@@ -644,7 +648,8 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
                }
        }
 
-       platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+       platform_device_register_data(NULL, "cpufreq-dt", -1,
+                                     &cpufreq_dt_pd, sizeof(cpufreq_dt_pd));
        return 0;
 }
 
index 6b58c1fe2b0d8e07ec10480100fbd95ba9e716c6..ea79269c270234ad844fde047c6a12d984e26a14 100644 (file)
@@ -17,5 +17,8 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
                              phys_addr_t resume_addr_reg);
 
 void mvebu_v7_pmsu_idle_exit(void);
+void armada_370_xp_cpu_resume(void);
 
+int armada_370_xp_pmsu_idle_enter(unsigned long deepidle);
+int armada_38x_do_cpu_suspend(unsigned long deepidle);
 #endif /* __MACH_370_XP_PMSU_H */
index a945756cfb45865d6fd0f9bd5927b6c6729e984d..88651221dbdd74270cc98f0ed5647120bc77018b 100644 (file)
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
+
+ENTRY(armada_38x_scu_power_up)
+       mrc     p15, 4, r1, c15, c0     @ get SCU base address
+       orr     r1, r1, #0x8            @ SCU CPU Power Status Register
+       mrc     15, 0, r0, cr0, cr0, 5  @ get the CPU ID
+       and     r0, r0, #15
+       add     r1, r1, r0
+       mov     r0, #0x0
+       strb    r0, [r1]                @ switch SCU power state to Normal mode
+       ret     lr
+ENDPROC(armada_38x_scu_power_up)
+
 /*
  * This is the entry point through which CPUs exiting cpuidle deep
  * idle state are going.
  */
 ENTRY(armada_370_xp_cpu_resume)
 ARM_BE8(setend be )                    @ go BE8 if entered LE
+       /*
+        * Disable the MMU that might have been enabled in BootROM if
+        * this code is used in the resume path of a suspend/resume
+        * cycle.
+        */
+       mrc     p15, 0, r1, c1, c0, 0
+       bic     r1, #1
+       mcr     p15, 0, r1, c1, c0, 0
        bl      ll_add_cpu_to_smp_group
        bl      ll_enable_coherency
        b       cpu_resume
@@ -27,13 +47,7 @@ ENTRY(armada_38x_cpu_resume)
        /* do we need it for Armada 38x*/
 ARM_BE8(setend be )                    @ go BE8 if entered LE
        bl      v7_invalidate_l1
-       mrc     p15, 4, r1, c15, c0     @ get SCU base address
-       orr     r1, r1, #0x8            @ SCU CPU Power Status Register
-       mrc     15, 0, r0, cr0, cr0, 5  @ get the CPU ID
-       and     r0, r0, #15
-       add     r1, r1, r0
-       mov     r0, #0x0
-       strb    r0, [r1]                @ switch SCU power state to Normal mode
+       bl      armada_38x_scu_power_up
        b       cpu_resume
 ENDPROC(armada_38x_cpu_resume)
 
index 9116ca476d7ce391b00a76bccac239c2eaef838b..9bda46f1fab7315c0b1bb7a47ea803ae68222f9b 100644 (file)
@@ -144,6 +144,7 @@ static int __init cpu8815_mmcsd_init(void)
 device_initcall(cpu8815_mmcsd_init);
 
 static const char * cpu8815_board_compat[] = {
+       "st,nomadik-nhk-15",
        "calaosystems,usb-s8815",
        NULL,
 };
index f4d06aea84605993bc2464313adf4f79628ab914..6e249324fdd775e594582e6cb6c3380716499a92 100644 (file)
@@ -79,7 +79,9 @@ config ARCH_OMAP2PLUS
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
        select MACH_OMAP_GENERIC
+       select MEMORY
        select OMAP_DM_TIMER
+       select OMAP_GPMC
        select PINCTRL
        select SOC_BUS
        select TI_PRIV_EDMA
@@ -235,12 +237,6 @@ config MACH_TOUCHBOOK
        default y
        select OMAP_PACKAGE_CBB
 
-config MACH_OMAP_3430SDP
-       bool "OMAP 3430 SDP board"
-       depends on ARCH_OMAP3
-       default y
-       select OMAP_PACKAGE_CBB
-
 config MACH_NOKIA_N810
        bool
 
@@ -282,16 +278,6 @@ config MACH_SBC3530
        default y
        select OMAP_PACKAGE_CUS
 
-config MACH_TI8168EVM
-       bool "TI8168 Evaluation Module"
-       depends on SOC_TI81XX
-       default y
-
-config MACH_TI8148EVM
-       bool "TI8148 Evaluation Module"
-       depends on SOC_TI81XX
-       default y
-
 config OMAP3_EMU
        bool "OMAP3 debugging peripherals"
        depends on ARCH_OMAP3
index d9e94122073ecc44efd9058e5ad80cf047e6abff..08cc94474d1749c8b3be489ed7daa884b25f35ab 100644 (file)
@@ -6,7 +6,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
        -I$(srctree)/arch/arm/plat-omap/include
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o gpmc.o timer.o pm.o \
+obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o timer.o pm.o \
         common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
         omap_device.o sram.o drm.o
 
@@ -113,7 +113,7 @@ obj-y                                       += prm_common.o cm_common.o
 obj-$(CONFIG_ARCH_OMAP2)               += prm2xxx_3xxx.o prm2xxx.o cm2xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += prm2xxx_3xxx.o prm3xxx.o cm3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += vc3xxx_data.o vp3xxx_data.o
-omap-prcm-4-5-common                   =  cminst44xx.o cm44xx.o prm44xx.o \
+omap-prcm-4-5-common                   =  cminst44xx.o prm44xx.o \
                                           prcm_mpu44xx.o prminst44xx.o \
                                           vc44xx_data.o vp44xx_data.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(omap-prcm-4-5-common)
@@ -246,7 +246,6 @@ obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
 obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
 obj-$(CONFIG_MACH_OVERO)               += board-overo.o
 obj-$(CONFIG_MACH_OMAP3_PANDORA)       += board-omap3pandora.o
-obj-$(CONFIG_MACH_OMAP_3430SDP)                += board-3430sdp.o
 obj-$(CONFIG_MACH_NOKIA_N8X0)          += board-n8x0.o
 obj-$(CONFIG_MACH_NOKIA_RX51)          += board-rx51.o sdram-nokia.o
 obj-$(CONFIG_MACH_NOKIA_RX51)          += board-rx51-peripherals.o
@@ -260,8 +259,6 @@ obj-$(CONFIG_MACH_OMAP3517EVM)              += board-am3517evm.o
 obj-$(CONFIG_MACH_CRANEBOARD)          += board-am3517crane.o
 
 obj-$(CONFIG_MACH_SBC3530)             += board-omap3stalker.o
-obj-$(CONFIG_MACH_TI8168EVM)           += board-ti8168evm.o
-obj-$(CONFIG_MACH_TI8148EVM)           += board-ti8168evm.o
 
 # Platform specific device init code
 
@@ -284,9 +281,6 @@ obj-y                                       += $(onenand-m) $(onenand-y)
 nand-$(CONFIG_MTD_NAND_OMAP2)          := gpmc-nand.o
 obj-y                                  += $(nand-m) $(nand-y)
 
-smc91x-$(CONFIG_SMC91X)                        := gpmc-smc91x.o
-obj-y                                  += $(smc91x-m) $(smc91x-y)
-
 smsc911x-$(CONFIG_SMSC911X)            := gpmc-smsc911x.o
 obj-y                                  += $(smsc911x-m) $(smsc911x-y)
 ifneq ($(CONFIG_HWSPINLOCK_OMAP),)
index c88d8df753c2d49b44db050e450c8dcb8fada2de..5bace6a45ffb3700065013dca4b1cc8211c2134b 100644 (file)
@@ -9,8 +9,7 @@
 #include <linux/reboot.h>
 
 #include "common.h"
-#include "prm-regbits-33xx.h"
-#include "prm33xx.h"
+#include "prm.h"
 
 /**
  * am3xx_restart - trigger a software restart of the SoC
@@ -24,12 +23,5 @@ void am33xx_restart(enum reboot_mode mode, const char *cmd)
 {
        /* TODO: Handle mode and cmd if necessary */
 
-       am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK,
-                               AM33XX_RST_GLOBAL_WARM_SW_MASK,
-                               AM33XX_PRM_DEVICE_MOD,
-                               AM33XX_PRM_RSTCTRL_OFFSET);
-
-       /* OCP barrier */
-       (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
-                                 AM33XX_PRM_RSTCTRL_OFFSET);
+       omap_prm_reset_system();
 }
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
deleted file mode 100644 (file)
index d21a304..0000000
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/board-3430sdp.c
- *
- * Copyright (C) 2007 Texas Instruments
- *
- * Modified from mach-omap2/board-generic.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/input.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/spi/spi.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/machine.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_data/spi-omap2-mcspi.h>
-#include <linux/platform_data/omap-twl4030.h>
-#include <linux/usb/phy.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include <linux/omap-dma.h>
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#include "gpmc.h"
-#include "gpmc-smc91x.h"
-
-#include "soc.h"
-#include "board-flash.h"
-#include "mux.h"
-#include "sdram-qimonda-hyb18m512160af-6.h"
-#include "hsmmc.h"
-#include "pm.h"
-#include "control.h"
-#include "common-board-devices.h"
-
-#define CONFIG_DISABLE_HFCLK 1
-
-#define SDP3430_TS_GPIO_IRQ_SDPV1      3
-#define SDP3430_TS_GPIO_IRQ_SDPV2      2
-
-#define ENABLE_VAUX3_DEDICATED 0x03
-#define ENABLE_VAUX3_DEV_GRP   0x20
-
-#define TWL4030_MSECURE_GPIO 22
-
-static uint32_t board_keymap[] = {
-       KEY(0, 0, KEY_LEFT),
-       KEY(0, 1, KEY_RIGHT),
-       KEY(0, 2, KEY_A),
-       KEY(0, 3, KEY_B),
-       KEY(0, 4, KEY_C),
-       KEY(1, 0, KEY_DOWN),
-       KEY(1, 1, KEY_UP),
-       KEY(1, 2, KEY_E),
-       KEY(1, 3, KEY_F),
-       KEY(1, 4, KEY_G),
-       KEY(2, 0, KEY_ENTER),
-       KEY(2, 1, KEY_I),
-       KEY(2, 2, KEY_J),
-       KEY(2, 3, KEY_K),
-       KEY(2, 4, KEY_3),
-       KEY(3, 0, KEY_M),
-       KEY(3, 1, KEY_N),
-       KEY(3, 2, KEY_O),
-       KEY(3, 3, KEY_P),
-       KEY(3, 4, KEY_Q),
-       KEY(4, 0, KEY_R),
-       KEY(4, 1, KEY_4),
-       KEY(4, 2, KEY_T),
-       KEY(4, 3, KEY_U),
-       KEY(4, 4, KEY_D),
-       KEY(5, 0, KEY_V),
-       KEY(5, 1, KEY_W),
-       KEY(5, 2, KEY_L),
-       KEY(5, 3, KEY_S),
-       KEY(5, 4, KEY_H),
-       0
-};
-
-static struct matrix_keymap_data board_map_data = {
-       .keymap                 = board_keymap,
-       .keymap_size            = ARRAY_SIZE(board_keymap),
-};
-
-static struct twl4030_keypad_data sdp3430_kp_data = {
-       .keymap_data    = &board_map_data,
-       .rows           = 5,
-       .cols           = 6,
-       .rep            = 1,
-};
-
-#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO       8
-#define SDP3430_LCD_PANEL_ENABLE_GPIO          5
-
-static void __init sdp3430_display_init(void)
-{
-       int r;
-
-       /*
-        * the backlight GPIO doesn't directly go to the panel, it enables
-        * an internal circuit on 3430sdp to create the signal V_BKL_28V,
-        * this is connected to LED+ pin of the sharp panel. This GPIO
-        * is left enabled in the board file, and not passed to the panel
-        * as platform_data.
-        */
-       r = gpio_request_one(SDP3430_LCD_PANEL_BACKLIGHT_GPIO,
-                               GPIOF_OUT_INIT_HIGH, "LCD Backlight");
-       if (r)
-               pr_err("failed to get LCD Backlight GPIO\n");
-
-}
-
-static struct panel_sharp_ls037v7dw01_platform_data sdp3430_lcd_pdata = {
-       .name                   = "lcd",
-       .source                 = "dpi.0",
-
-       .data_lines             = 16,
-
-       .resb_gpio              = SDP3430_LCD_PANEL_ENABLE_GPIO,
-       .ini_gpio               = -1,
-       .mo_gpio                = -1,
-       .lr_gpio                = -1,
-       .ud_gpio                = -1,
-};
-
-static struct platform_device sdp3430_lcd_device = {
-       .name                   = "panel-sharp-ls037v7dw01",
-       .id                     = 0,
-       .dev.platform_data      = &sdp3430_lcd_pdata,
-};
-
-static struct connector_dvi_platform_data sdp3430_dvi_connector_pdata = {
-       .name                   = "dvi",
-       .source                 = "tfp410.0",
-       .i2c_bus_num            = -1,
-};
-
-static struct platform_device sdp3430_dvi_connector_device = {
-       .name                   = "connector-dvi",
-       .id                     = 0,
-       .dev.platform_data      = &sdp3430_dvi_connector_pdata,
-};
-
-static struct encoder_tfp410_platform_data sdp3430_tfp410_pdata = {
-       .name                   = "tfp410.0",
-       .source                 = "dpi.0",
-       .data_lines             = 24,
-       .power_down_gpio        = -1,
-};
-
-static struct platform_device sdp3430_tfp410_device = {
-       .name                   = "tfp410",
-       .id                     = 0,
-       .dev.platform_data      = &sdp3430_tfp410_pdata,
-};
-
-static struct connector_atv_platform_data sdp3430_tv_pdata = {
-       .name = "tv",
-       .source = "venc.0",
-       .connector_type = OMAP_DSS_VENC_TYPE_SVIDEO,
-       .invert_polarity = false,
-};
-
-static struct platform_device sdp3430_tv_connector_device = {
-       .name                   = "connector-analog-tv",
-       .id                     = 0,
-       .dev.platform_data      = &sdp3430_tv_pdata,
-};
-
-static struct omap_dss_board_info sdp3430_dss_data = {
-       .default_display_name = "lcd",
-};
-
-static struct omap2_hsmmc_info mmc[] = {
-       {
-               .mmc            = 1,
-               /* 8 bits (default) requires S6.3 == ON,
-                * so the SIM card isn't used; else 4 bits.
-                */
-               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-               .gpio_wp        = 4,
-               .deferred       = true,
-       },
-       {
-               .mmc            = 2,
-               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-               .gpio_wp        = 7,
-               .deferred       = true,
-       },
-       {}      /* Terminator */
-};
-
-static struct omap_tw4030_pdata omap_twl4030_audio_data = {
-       .voice_connected = true,
-       .custom_routing = true,
-
-       .has_hs         = OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT,
-       .has_hf         = OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT,
-
-       .has_mainmic    = true,
-       .has_submic     = true,
-       .has_hsmic      = true,
-       .has_linein     = OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT,
-};
-
-static int sdp3430_twl_gpio_setup(struct device *dev,
-               unsigned gpio, unsigned ngpio)
-{
-       /* gpio + 0 is "mmc0_cd" (input/IRQ),
-        * gpio + 1 is "mmc1_cd" (input/IRQ)
-        */
-       mmc[0].gpio_cd = gpio + 0;
-       mmc[1].gpio_cd = gpio + 1;
-       omap_hsmmc_late_init(mmc);
-
-       /* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
-       gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl");
-
-       /* gpio + 15 is "sub_lcd_nRST" (output) */
-       gpio_request_one(gpio + 15, GPIOF_OUT_INIT_LOW, "sub_lcd_nRST");
-
-       omap_twl4030_audio_data.jack_detect = gpio + 2;
-       omap_twl4030_audio_init("SDP3430", &omap_twl4030_audio_data);
-
-       return 0;
-}
-
-static struct twl4030_gpio_platform_data sdp3430_gpio_data = {
-       .pulldowns      = BIT(2) | BIT(6) | BIT(8) | BIT(13)
-                               | BIT(16) | BIT(17),
-       .setup          = sdp3430_twl_gpio_setup,
-};
-
-/* regulator consumer mappings */
-
-/* ads7846 on SPI */
-static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = {
-       REGULATOR_SUPPLY("vcc", "spi1.0"),
-};
-
-static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = {
-       REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-static struct regulator_consumer_supply sdp3430_vsim_supplies[] = {
-       REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
-};
-
-static struct regulator_consumer_supply sdp3430_vmmc2_supplies[] = {
-       REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
-};
-
-/*
- * Apply all the fixed voltages since most versions of U-Boot
- * don't bother with that initialization.
- */
-
-/* VAUX1 for mainboard (irda and sub-lcd) */
-static struct regulator_init_data sdp3430_vaux1 = {
-       .constraints = {
-               .min_uV                 = 2800000,
-               .max_uV                 = 2800000,
-               .apply_uV               = true,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-};
-
-/* VAUX2 for camera module */
-static struct regulator_init_data sdp3430_vaux2 = {
-       .constraints = {
-               .min_uV                 = 2800000,
-               .max_uV                 = 2800000,
-               .apply_uV               = true,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-};
-
-/* VAUX3 for LCD board */
-static struct regulator_init_data sdp3430_vaux3 = {
-       .constraints = {
-               .min_uV                 = 2800000,
-               .max_uV                 = 2800000,
-               .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(sdp3430_vaux3_supplies),
-       .consumer_supplies              = sdp3430_vaux3_supplies,
-};
-
-/* VAUX4 for OMAP VDD_CSI2 (camera) */
-static struct regulator_init_data sdp3430_vaux4 = {
-       .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,
-       },
-};
-
-/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
-static struct regulator_init_data sdp3430_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(sdp3430_vmmc1_supplies),
-       .consumer_supplies      = sdp3430_vmmc1_supplies,
-};
-
-/* VMMC2 for MMC2 card */
-static struct regulator_init_data sdp3430_vmmc2 = {
-       .constraints = {
-               .min_uV                 = 1850000,
-               .max_uV                 = 1850000,
-               .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(sdp3430_vmmc2_supplies),
-       .consumer_supplies      = sdp3430_vmmc2_supplies,
-};
-
-/* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */
-static struct regulator_init_data sdp3430_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(sdp3430_vsim_supplies),
-       .consumer_supplies      = sdp3430_vsim_supplies,
-};
-
-static struct twl4030_platform_data sdp3430_twldata = {
-       /* platform_data for children goes here */
-       .gpio           = &sdp3430_gpio_data,
-       .keypad         = &sdp3430_kp_data,
-
-       .vaux1          = &sdp3430_vaux1,
-       .vaux2          = &sdp3430_vaux2,
-       .vaux3          = &sdp3430_vaux3,
-       .vaux4          = &sdp3430_vaux4,
-       .vmmc1          = &sdp3430_vmmc1,
-       .vmmc2          = &sdp3430_vmmc2,
-       .vsim           = &sdp3430_vsim,
-};
-
-static int __init omap3430_i2c_init(void)
-{
-       /* i2c1 for PMIC only */
-       omap3_pmic_get_config(&sdp3430_twldata,
-                       TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI |
-                       TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO,
-                       TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
-       sdp3430_twldata.vdac->constraints.apply_uV = true;
-       sdp3430_twldata.vpll2->constraints.apply_uV = true;
-       sdp3430_twldata.vpll2->constraints.name = "VDVI";
-
-       sdp3430_twldata.audio->codec->hs_extmute = 1;
-       sdp3430_twldata.audio->codec->hs_extmute_gpio = -EINVAL;
-
-       omap3_pmic_init("twl4030", &sdp3430_twldata);
-
-       /* i2c2 on camera connector (for sensor control) and optional isp1301 */
-       omap_register_i2c_bus(2, 400, NULL, 0);
-       /* i2c3 on display connector (for DVI, tfp410) */
-       omap_register_i2c_bus(3, 400, NULL, 0);
-       return 0;
-}
-
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-
-static struct omap_smc91x_platform_data board_smc91x_data = {
-       .cs             = 3,
-       .flags          = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
-                               IORESOURCE_IRQ_LOWLEVEL,
-};
-
-static void __init board_smc91x_init(void)
-{
-       if (omap_rev() > OMAP3430_REV_ES1_0)
-               board_smc91x_data.gpio_irq = 6;
-       else
-               board_smc91x_data.gpio_irq = 29;
-
-       gpmc_smc91x_init(&board_smc91x_data);
-}
-
-#else
-
-static inline void board_smc91x_init(void)
-{
-}
-
-#endif
-
-static void enable_board_wakeup_source(void)
-{
-       /* T2 interrupt line (keypad) */
-       omap_mux_init_signal("sys_nirq",
-               OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
-}
-
-static struct usbhs_phy_data phy_data[] __initdata = {
-       {
-               .port = 1,
-               .reset_gpio = 57,
-               .vcc_gpio = -EINVAL,
-       },
-       {
-               .port = 2,
-               .reset_gpio = 61,
-               .vcc_gpio = -EINVAL,
-       },
-};
-
-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,
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-       { .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define board_mux      NULL
-#endif
-
-/*
- * SDP3430 V2 Board CS organization
- * Different from SDP3430 V1. Now 4 switches used to specify CS
- *
- * See also the Switch S8 settings in the comments.
- */
-static char chip_sel_3430[][GPMC_CS_NUM] = {
-       {PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */
-       {PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */
-       {PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */
-};
-
-static struct mtd_partition sdp_nor_partitions[] = {
-       /* bootloader (U-Boot, etc) in first sector */
-       {
-               .name           = "Bootloader-NOR",
-               .offset         = 0,
-               .size           = SZ_256K,
-               .mask_flags     = MTD_WRITEABLE, /* force read-only */
-       },
-       /* bootloader params in the next sector */
-       {
-               .name           = "Params-NOR",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = SZ_256K,
-               .mask_flags     = 0,
-       },
-       /* kernel */
-       {
-               .name           = "Kernel-NOR",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = SZ_2M,
-               .mask_flags     = 0
-       },
-       /* file system */
-       {
-               .name           = "Filesystem-NOR",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = MTDPART_SIZ_FULL,
-               .mask_flags     = 0
-       }
-};
-
-static struct mtd_partition sdp_onenand_partitions[] = {
-       {
-               .name           = "X-Loader-OneNAND",
-               .offset         = 0,
-               .size           = 4 * (64 * 2048),
-               .mask_flags     = MTD_WRITEABLE  /* force read-only */
-       },
-       {
-               .name           = "U-Boot-OneNAND",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = 2 * (64 * 2048),
-               .mask_flags     = MTD_WRITEABLE  /* force read-only */
-       },
-       {
-               .name           = "U-Boot Environment-OneNAND",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = 1 * (64 * 2048),
-       },
-       {
-               .name           = "Kernel-OneNAND",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = 16 * (64 * 2048),
-       },
-       {
-               .name           = "File System-OneNAND",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct mtd_partition sdp_nand_partitions[] = {
-       /* All the partition sizes are listed in terms of NAND block size */
-       {
-               .name           = "X-Loader-NAND",
-               .offset         = 0,
-               .size           = 4 * (64 * 2048),
-               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
-       },
-       {
-               .name           = "U-Boot-NAND",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
-               .size           = 10 * (64 * 2048),
-               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
-       },
-       {
-               .name           = "Boot Env-NAND",
-
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x1c0000 */
-               .size           = 6 * (64 * 2048),
-       },
-       {
-               .name           = "Kernel-NAND",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
-               .size           = 40 * (64 * 2048),
-       },
-       {
-               .name           = "File System - NAND",
-               .size           = MTDPART_SIZ_FULL,
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x780000 */
-       },
-};
-
-static struct flash_partitions sdp_flash_partitions[] = {
-       {
-               .parts = sdp_nor_partitions,
-               .nr_parts = ARRAY_SIZE(sdp_nor_partitions),
-       },
-       {
-               .parts = sdp_onenand_partitions,
-               .nr_parts = ARRAY_SIZE(sdp_onenand_partitions),
-       },
-       {
-               .parts = sdp_nand_partitions,
-               .nr_parts = ARRAY_SIZE(sdp_nand_partitions),
-       },
-};
-
-static void __init omap_3430sdp_init(void)
-{
-       int gpio_pendown;
-
-       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-       omap_hsmmc_init(mmc);
-       omap3430_i2c_init();
-       omap_display_init(&sdp3430_dss_data);
-       platform_device_register(&sdp3430_lcd_device);
-       platform_device_register(&sdp3430_tfp410_device);
-       platform_device_register(&sdp3430_dvi_connector_device);
-       platform_device_register(&sdp3430_tv_connector_device);
-
-       if (omap_rev() > OMAP3430_REV_ES1_0)
-               gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV2;
-       else
-               gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
-       omap_ads7846_init(1, gpio_pendown, 310, NULL);
-       omap_serial_init();
-       omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
-       usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-       usb_musb_init(NULL);
-       board_smc91x_init();
-       board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
-       sdp3430_display_init();
-       enable_board_wakeup_source();
-
-       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
-       usbhs_init(&usbhs_bdata);
-}
-
-MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
-       /* Maintainer: Syed Khasim - Texas Instruments Inc */
-       .atag_offset    = 0x100,
-       .reserve        = omap_reserve,
-       .map_io         = omap3_map_io,
-       .init_early     = omap3430_init_early,
-       .init_irq       = omap3_init_irq,
-       .init_machine   = omap_3430sdp_init,
-       .init_late      = omap3430_init_late,
-       .init_time      = omap3_sync32k_timer_init,
-       .restart        = omap3xxx_restart,
-MACHINE_END
index 212c3160de183810438a3f8ca2e725674231edb3..8168ddabaeda93004228eaf87b1ca3e44c7bd379 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/omap-gpmc.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
index c6df8eec45532d2ed26d0180480e416aecf2696f..91738a14ecbe424ad31ee1140946f16f50c7c84b 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/input/matrix_keypad.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/omap-gpmc.h>
 #include <linux/platform_data/gpio-omap.h>
 
 #include <linux/platform_data/at24.h>
@@ -51,8 +52,6 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
-#include "gpmc.h"
-#include "gpmc-nand.h"
 
 #define CM_T35_GPIO_PENDOWN            57
 #define SB_T35_USB_HUB_RESET_GPIO      167
index 8a2c1677964cbb5c0d60c56bb27645b237e1b2fb..794756df8529a13a986343ac108765bdf68117f7 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/omap-gpmc.h>
 #include <linux/rtc-v3020.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -41,7 +42,6 @@
 
 #include "common.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include "gpmc.h"
 
 #include "am35xx.h"
 
@@ -50,7 +50,6 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 #include "am35xx-emac.h"
-#include "gpmc-nand.h"
 
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
 static struct gpio_led cm_t3517_leds[] = {
index 2d245c2e641cd9314378def624b45093951a59cc..70b21cc279ba45c5ada11bdffea8051b18f5fb0a 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/omap-gpmc.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/io.h>
@@ -23,8 +24,6 @@
 #include "soc.h"
 #include "common.h"
 #include "board-flash.h"
-#include "gpmc-onenand.h"
-#include "gpmc-nand.h"
 
 #define REG_FPGA_REV                   0x10
 #define REG_FPGA_DIP_SWITCH_INPUT2     0x60
index 2fb5d41a9fae2679781a9c759913a032b1a69e9e..ea9aaebe11e7f1e0c85df5851f074a0de50d6d52 100644 (file)
@@ -12,7 +12,6 @@
  */
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include "gpmc.h"
 
 #define PDC_NOR                1
 #define PDC_NAND       2
index 97767a27ca9d8b3a27b6206b6867903044f9da29..b6443a4e0c78002d6665479a608e7915b1801015 100644 (file)
@@ -21,8 +21,9 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/musb.h>
+#include <linux/mmc/host.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
-#include <linux/platform_data/mtd-onenand-omap2.h>
+#include <linux/platform_data/mmc-omap.h>
 #include <linux/mfd/menelaus.h>
 #include <sound/tlv320aic3x.h>
 
@@ -32,7 +33,6 @@
 #include "common.h"
 #include "mmc.h"
 #include "soc.h"
-#include "gpmc-onenand.h"
 #include "common-board-devices.h"
 
 #define TUSB6010_ASYNC_CS      1
index f32201656cf30b5af416d53176c282d467ea2491..7f1708738c3079227377806376a794dafb5aed46 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/spi/spi.h>
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/omap-gpmc.h>
 #include <linux/wl12xx.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
@@ -51,7 +52,6 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
-#include "gpmc-nand.h"
 
 #define PANDORA_WIFI_IRQ_GPIO          21
 #define PANDORA_WIFI_NRESET_GPIO       23
index ddfc8df83c6a9adf2c0d128c688d16e094708ac2..03502abe4f2efbd82d3140c3cddd0a244275d0ee 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
+#include <linux/omap-gpmc.h>
 #include <linux/mmc/host.h>
 #include <linux/power/isp1704_charger.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
@@ -32,7 +33,6 @@
 
 #include "common.h"
 #include <linux/omap-dma.h>
-#include "gpmc-smc91x.h"
 
 #include "board-rx51.h"
 
@@ -55,8 +55,6 @@
 #include "omap-pm.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
-#include "gpmc.h"
-#include "gpmc-onenand.h"
 #include "soc.h"
 #include "omap-secure.h"
 
@@ -484,7 +482,7 @@ static struct omap_mux_partition *partition;
  * Current flows to eMMC when eMMC is off and the data lines are pulled up,
  * so pull them down. N.B. we pull 8 lines because we are using 8 lines.
  */
-static void rx51_mmc2_remux(struct device *dev, int slot, int power_on)
+static void rx51_mmc2_remux(struct device *dev, int power_on)
 {
        if (power_on)
                omap_mux_write_array(partition, rx51_mmc2_on_mux);
@@ -500,7 +498,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
                .cover_only     = true,
                .gpio_cd        = 160,
                .gpio_wp        = -EINVAL,
-               .power_saving   = true,
        },
        {
                .name           = "internal",
@@ -510,7 +507,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
-               .power_saving   = true,
                .remux          = rx51_mmc2_remux,
        },
        {}      /* Terminator */
@@ -1146,33 +1142,6 @@ static struct omap_onenand_platform_data board_onenand_data[] = {
 };
 #endif
 
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-
-static struct omap_smc91x_platform_data board_smc91x_data = {
-       .cs             = 1,
-       .gpio_irq       = 54,
-       .gpio_pwrdwn    = 86,
-       .gpio_reset     = 164,
-       .flags          = GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHLEVEL,
-};
-
-static void __init board_smc91x_init(void)
-{
-       omap_mux_init_gpio(54, OMAP_PIN_INPUT_PULLDOWN);
-       omap_mux_init_gpio(86, OMAP_PIN_OUTPUT);
-       omap_mux_init_gpio(164, OMAP_PIN_OUTPUT);
-
-       gpmc_smc91x_init(&board_smc91x_data);
-}
-
-#else
-
-static inline void board_smc91x_init(void)
-{
-}
-
-#endif
-
 static struct gpio rx51_wl1251_gpios[] __initdata = {
        { RX51_WL1251_IRQ_GPIO,   GPIOF_IN,             "wl1251 irq"    },
 };
@@ -1303,7 +1272,6 @@ void __init rx51_peripherals_init(void)
        rx51_i2c_init();
        regulator_has_full_constraints();
        gpmc_onenand_init(board_onenand_data);
-       board_smc91x_init();
        rx51_add_gpio_keys();
        rx51_init_wl1251();
        rx51_init_tsc2005();
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
deleted file mode 100644 (file)
index 6273c28..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Code for TI8168/TI8148 EVM.
- *
- * Copyright (C) 2010 Texas Instruments, Inc. - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; 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/usb/musb.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-static struct omap_musb_board_data musb_board_data = {
-       .set_phy_power  = ti81xx_musb_phy_power,
-       .interface_type = MUSB_INTERFACE_ULPI,
-       .mode           = MUSB_OTG,
-       .power          = 500,
-};
-
-static void __init ti81xx_evm_init(void)
-{
-       omap_serial_init();
-       omap_sdrc_init(NULL, NULL);
-       usb_musb_init(&musb_board_data);
-}
-
-MACHINE_START(TI8168EVM, "ti8168evm")
-       /* Maintainer: Texas Instruments */
-       .atag_offset    = 0x100,
-       .map_io         = ti81xx_map_io,
-       .init_early     = ti81xx_init_early,
-       .init_irq       = ti81xx_init_irq,
-       .init_time      = omap3_sync32k_timer_init,
-       .init_machine   = ti81xx_evm_init,
-       .init_late      = ti81xx_init_late,
-       .restart        = omap44xx_restart,
-MACHINE_END
-
-MACHINE_START(TI8148EVM, "ti8148evm")
-       /* Maintainer: Texas Instruments */
-       .atag_offset    = 0x100,
-       .map_io         = ti81xx_map_io,
-       .init_early     = ti81xx_init_early,
-       .init_irq       = ti81xx_init_irq,
-       .init_time      = omap3_sync32k_timer_init,
-       .init_machine   = ti81xx_evm_init,
-       .init_late      = ti81xx_init_late,
-       .restart        = omap44xx_restart,
-MACHINE_END
index eb8c75ec3b1ac28ad121969fdbbd586bfca69b20..5c5ebb4db5f73031b5ba25a960e8efee5ec885fb 100644 (file)
@@ -257,6 +257,9 @@ static const struct clk_ops dpll1_ck_ops = {
        .get_parent     = &omap2_init_dpll_parent,
        .recalc_rate    = &omap3_dpll_recalc,
        .set_rate       = &omap3_noncore_dpll_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_noncore_dpll_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
        .round_rate     = &omap2_dpll_round_rate,
 };
 
@@ -367,6 +370,9 @@ static const struct clk_ops dpll4_ck_ops = {
        .get_parent     = &omap2_init_dpll_parent,
        .recalc_rate    = &omap3_dpll_recalc,
        .set_rate       = &omap3_dpll4_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_dpll4_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
        .round_rate     = &omap2_dpll_round_rate,
 };
 
index 500530d1364a384859a6720c783ef1394545b983..6ad5b4dbd33ec9e79834ed440f10fa38d246b2ce 100644 (file)
@@ -171,7 +171,8 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
                _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
                                     idlest_val, __clk_get_name(clk->hw.clk));
        } else {
-               cm_wait_module_ready(prcm_mod, idlest_reg_id, idlest_bit);
+               omap_cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
+                                         idlest_bit);
        };
 }
 
@@ -771,4 +772,8 @@ void __init ti_clk_init_features(void)
                ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
        else if (cpu_is_omap34xx())
                ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
+
+       /* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
+       if (omap_rev() == OMAP3430_REV_ES1_0)
+               ti_clk_features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
 }
index 4592a2762592fef88c69be32aa1ce42cc6f18a4a..641337c6cde9a43fdfb24e589b9946464924ec01 100644 (file)
@@ -234,6 +234,7 @@ struct ti_clk_features {
 };
 
 #define TI_CLK_DPLL_HAS_FREQSEL                (1 << 0)
+#define TI_CLK_DPLL4_DENY_REPROGRAM    (1 << 1)
 
 extern struct ti_clk_features ti_clk_features;
 
index 0b02b4161d71f9806fd10acea364d3dbfe005505..a9e86db5daf9f08de3137dd04ed8b52e6f979c59 100644 (file)
 
 /* needed by omap3_core_dpll_m2_set_rate() */
 struct clk *sdrc_ick_p, *arm_fck_p;
+
+/**
+ * omap3_dpll4_set_rate - set rate for omap3 per-dpll
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Check if the current SoC supports the per-dpll reprogram operation
+ * or not, and then do the rate change if supported. Returns -EINVAL
+ * if not supported, 0 for success, and potential error codes from the
+ * clock rate change.
+ */
 int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long parent_rate)
 {
@@ -46,7 +58,7 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
         * on 3430ES1 prevents us from changing DPLL multipliers or dividers
         * on DPLL4.
         */
-       if (omap_rev() == OMAP3430_REV_ES1_0) {
+       if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
                pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
                return -EINVAL;
        }
@@ -54,6 +66,30 @@ int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
        return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
 }
 
+/**
+ * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ * @index: parent index, 0 - reference clock, 1 - bypass clock
+ *
+ * Check if the current SoC support the per-dpll reprogram operation
+ * or not, and then do the rate + parent change if supported. Returns
+ * -EINVAL if not supported, 0 for success, and potential error codes
+ * from the clock rate change.
+ */
+int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate, u8 index)
+{
+       if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
+               pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
+               return -EINVAL;
+       }
+
+       return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
+                                                     index);
+}
+
 void __init omap3_clk_lock_dpll5(void)
 {
        struct clk *dpll5_clk;
index 93473f9a551cba1675aa4bd1306ca329ae70f732..6222e87a79b623e7299e2c694e01246979d1accd 100644 (file)
@@ -45,17 +45,29 @@ extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
  * struct cm_ll_data - fn ptrs to per-SoC CM function implementations
  * @split_idlest_reg: ptr to the SoC CM-specific split_idlest_reg impl
  * @wait_module_ready: ptr to the SoC CM-specific wait_module_ready impl
+ * @wait_module_idle: ptr to the SoC CM-specific wait_module_idle impl
+ * @module_enable: ptr to the SoC CM-specific module_enable impl
+ * @module_disable: ptr to the SoC CM-specific module_disable impl
  */
 struct cm_ll_data {
        int (*split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
                                u8 *idlest_reg_id);
-       int (*wait_module_ready)(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
+       int (*wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
+                                u8 idlest_shift);
+       int (*wait_module_idle)(u8 part, s16 prcm_mod, u16 idlest_reg,
+                               u8 idlest_shift);
+       void (*module_enable)(u8 mode, u8 part, u16 inst, u16 clkctrl_offs);
+       void (*module_disable)(u8 part, u16 inst, u16 clkctrl_offs);
 };
 
 extern int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
                               u8 *idlest_reg_id);
-extern int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift);
-
+int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
+                             u8 idlest_shift);
+int omap_cm_wait_module_idle(u8 part, s16 prcm_mod, u16 idlest_reg,
+                            u8 idlest_shift);
+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);
 
index 5ae8fe39d6ee5cfa838bea5e693194484be4ef56..a5949927b66105fe0d2d663bc0cbda4c188f3a9c 100644 (file)
@@ -25,8 +25,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM1_44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM1_44XX_H
 
-#include "cm_44xx_54xx.h"
-
 /* CM1 base address */
 #define OMAP4430_CM1_BASE              0x4a004000
 
index 90b3348e6672888836bccd4c986d9a3d2f1a03c1..fd245dfa7391513baa32cc0c34e53ce4a0574d18 100644 (file)
@@ -22,8 +22,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM1_54XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM1_54XX_H
 
-#include "cm_44xx_54xx.h"
-
 /* CM1 base address */
 #define OMAP54XX_CM_CORE_AON_BASE              0x4a004000
 
index ca6fa1febaac41ca4c04749c50dfacd6366a3b52..2f1c09eea021d7ec6a67c2b0dad811e8251c7f94 100644 (file)
@@ -23,8 +23,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM1_7XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM1_7XX_H
 
-#include "cm_44xx_54xx.h"
-
 /* CM1 base address */
 #define DRA7XX_CM_CORE_AON_BASE                0x4a005000
 
index ee5136d7cddac06029d7eb12313602c59943c6ea..7521abf3d8305dfc99b4e02e62bf8f319c8fa323 100644 (file)
@@ -25,8 +25,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM2_44XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM2_44XX_H
 
-#include "cm_44xx_54xx.h"
-
 /* CM2 base address */
 #define OMAP4430_CM2_BASE              0x4a008000
 
index 2683231b299bdb6c29653081f2da9872c8ddb3da..ff4040c196d83b8f791e8218fc6b3b23fdafe70b 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM2_54XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM2_54XX_H
 
-#include "cm_44xx_54xx.h"
-
 /* CM2 base address */
 #define OMAP54XX_CM_CORE_BASE          0x4a008000
 
index e966e3a3c93190e5704d4fdcfe6cce3a17db10f9..ce63fdb6805621241c6f2c4428da69316241681f 100644 (file)
@@ -22,8 +22,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CM2_7XX_H
 #define __ARCH_ARM_MACH_OMAP2_CM2_7XX_H
 
-#include "cm_44xx_54xx.h"
-
 /* CM2 base address */
 #define DRA7XX_CM_CORE_BASE            0x4a008000
 
index 8be6ea50c092475040b450094cdce3a60e1b532b..a96d901b1d5d3615543a2733a6bbcd49079bfd33 100644 (file)
@@ -53,7 +53,7 @@ static void _write_clktrctrl(u8 c, s16 module, u32 mask)
        omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
 }
 
-bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
+static bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
 {
        u32 v;
 
@@ -64,12 +64,12 @@ bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
        return (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
 }
 
-void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
+static void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
 {
        _write_clktrctrl(OMAP24XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
 }
 
-void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
+static void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
 {
        _write_clktrctrl(OMAP24XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
 }
@@ -150,7 +150,7 @@ static int _omap2xxx_apll_enable(u8 enable_bit, u8 status_bit)
        v |= m;
        omap2_cm_write_mod_reg(v, PLL_MOD, CM_CLKEN);
 
-       omap2xxx_cm_wait_module_ready(PLL_MOD, 1, status_bit);
+       omap2xxx_cm_wait_module_ready(0, PLL_MOD, 1, status_bit);
 
        /*
         * REVISIT: Should we return an error code if
@@ -204,8 +204,9 @@ void omap2xxx_cm_apll96_disable(void)
  * XXX This function is only needed until absolute register addresses are
  * removed from the OMAP struct clk records.
  */
-int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
-                                u8 *idlest_reg_id)
+static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+                                       s16 *prcm_inst,
+                                       u8 *idlest_reg_id)
 {
        unsigned long offs;
        u8 idlest_offs;
@@ -238,6 +239,7 @@ int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
 
 /**
  * omap2xxx_cm_wait_module_ready - wait for a module to leave idle or standby
+ * @part: PRCM partition, ignored for OMAP2
  * @prcm_mod: PRCM module offset
  * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
  * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
@@ -246,7 +248,8 @@ int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
  * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
  * success or -EBUSY if the module doesn't enable in time.
  */
-int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+int omap2xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
+                                 u8 idlest_shift)
 {
        int ena = 0, i = 0;
        u8 cm_idlest_reg;
index 891d81c3c8f4b6bf7f50ff0a325298e54ed4c3ad..c89502b168ae718d2353e4f30c0477ffcb41a71a 100644 (file)
@@ -46,9 +46,6 @@
 
 #ifndef __ASSEMBLER__
 
-extern void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
-extern void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
-
 extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
 extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
 
@@ -57,11 +54,8 @@ extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
 extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
 extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
 
-extern bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
-extern int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
-                                        u8 idlest_shift);
-extern int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
-                                       s16 *prcm_inst, u8 *idlest_reg_id);
+int omap2xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
+                                 u8 idlest_shift);
 extern int omap2xxx_cm_fclks_active(void);
 extern int omap2xxx_cm_mpu_retention_allowed(void);
 extern u32 omap2xxx_cm_get_core_clk_src(void);
index b3f99e93def001506cf979c42d6150c89810d890..b9ad463a368a2ba35c234042a90b800d3b80aa94 100644 (file)
@@ -96,13 +96,12 @@ static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask)
 /**
  * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to
  * bit 0.
  */
-static u32 _clkctrl_idlest(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static u32 _clkctrl_idlest(u16 inst, u16 clkctrl_offs)
 {
        u32 v = am33xx_cm_read_reg(inst, clkctrl_offs);
        v &= AM33XX_IDLEST_MASK;
@@ -113,17 +112,16 @@ static u32 _clkctrl_idlest(u16 inst, s16 cdoffs, u16 clkctrl_offs)
 /**
  * _is_module_ready - can module registers be accessed without causing an abort?
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either
  * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise.
  */
-static bool _is_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static bool _is_module_ready(u16 inst, u16 clkctrl_offs)
 {
        u32 v;
 
-       v = _clkctrl_idlest(inst, cdoffs, clkctrl_offs);
+       v = _clkctrl_idlest(inst, clkctrl_offs);
 
        return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
                v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
@@ -158,7 +156,7 @@ static void _clktrctrl_write(u8 c, u16 inst, u16 cdoffs)
  * Returns true if the clockdomain referred to by (@inst, @cdoffs)
  * is in hardware-supervised idle mode, or 0 otherwise.
  */
-bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs)
+static bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs)
 {
        u32 v;
 
@@ -177,7 +175,7 @@ bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs)
  * Put a clockdomain referred to by (@inst, @cdoffs) into
  * hardware-supervised idle mode.  No return value.
  */
-void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs)
+static void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, inst, cdoffs);
 }
@@ -191,7 +189,7 @@ void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs)
  * software-supervised idle mode, i.e., controlled manually by the
  * Linux OMAP clockdomain code.  No return value.
  */
-void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs)
+static void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, inst, cdoffs);
 }
@@ -204,7 +202,7 @@ void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs)
  * Put a clockdomain referred to by (@inst, @cdoffs) into idle
  * No return value.
  */
-void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs)
+static void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, inst, cdoffs);
 }
@@ -217,7 +215,7 @@ void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs)
  * Take a clockdomain referred to by (@inst, @cdoffs) out of idle,
  * waking it up.  No return value.
  */
-void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs)
+static void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, inst, cdoffs);
 }
@@ -228,20 +226,22 @@ void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs)
 
 /**
  * am33xx_cm_wait_module_ready - wait for a module to be in 'func' state
+ * @part: PRCM partition, ignored for AM33xx
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ * @bit_shift: bit shift for the register, ignored for AM33xx
  *
  * Wait for the module IDLEST to be functional. If the idle state is in any
  * the non functional state (trans, idle or disabled), module and thus the
  * sysconfig cannot be accessed and will probably lead to an "imprecise
  * external abort"
  */
-int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static int am33xx_cm_wait_module_ready(u8 part, s16 inst, u16 clkctrl_offs,
+                                      u8 bit_shift)
 {
        int i = 0;
 
-       omap_test_timeout(_is_module_ready(inst, cdoffs, clkctrl_offs),
+       omap_test_timeout(_is_module_ready(inst, clkctrl_offs),
                          MAX_MODULE_READY_TIME, i);
 
        return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
@@ -250,22 +250,24 @@ int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
 /**
  * am33xx_cm_wait_module_idle - wait for a module to be in 'disabled'
  * state
+ * @part: CM partition, ignored for AM33xx
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ * @bit_shift: bit shift for the register, ignored for AM33xx
  *
  * Wait for the module IDLEST to be disabled. Some PRCM transition,
  * like reset assertion or parent clock de-activation must wait the
  * module to be fully disabled.
  */
-int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static int am33xx_cm_wait_module_idle(u8 part, s16 inst, u16 clkctrl_offs,
+                                     u8 bit_shift)
 {
        int i = 0;
 
        if (!clkctrl_offs)
                return 0;
 
-       omap_test_timeout((_clkctrl_idlest(inst, cdoffs, clkctrl_offs) ==
+       omap_test_timeout((_clkctrl_idlest(inst, clkctrl_offs) ==
                                CLKCTRL_IDLEST_DISABLED),
                                MAX_MODULE_READY_TIME, i);
 
@@ -275,13 +277,14 @@ int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, u16 clkctrl_offs)
 /**
  * am33xx_cm_module_enable - Enable the modulemode inside CLKCTRL
  * @mode: Module mode (SW or HW)
+ * @part: CM partition, ignored for AM33xx
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * No return value.
  */
-void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static void am33xx_cm_module_enable(u8 mode, u8 part, u16 inst,
+                                   u16 clkctrl_offs)
 {
        u32 v;
 
@@ -293,13 +296,13 @@ void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, u16 clkctrl_offs)
 
 /**
  * am33xx_cm_module_disable - Disable the module inside CLKCTRL
+ * @part: CM partition, ignored for AM33xx
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * No return value.
  */
-void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static void am33xx_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
 {
        u32 v;
 
@@ -362,3 +365,21 @@ struct clkdm_ops am33xx_clkdm_operations = {
        .clkdm_clk_enable       = am33xx_clkdm_clk_enable,
        .clkdm_clk_disable      = am33xx_clkdm_clk_disable,
 };
+
+static struct cm_ll_data am33xx_cm_ll_data = {
+       .wait_module_ready      = &am33xx_cm_wait_module_ready,
+       .wait_module_idle       = &am33xx_cm_wait_module_idle,
+       .module_enable          = &am33xx_cm_module_enable,
+       .module_disable         = &am33xx_cm_module_disable,
+};
+
+int __init am33xx_cm_init(void)
+{
+       return cm_register(&am33xx_cm_ll_data);
+}
+
+static void __exit am33xx_cm_exit(void)
+{
+       cm_unregister(&am33xx_cm_ll_data);
+}
+__exitcall(am33xx_cm_exit);
index bd244179077972e2c4538588799c146666730eea..046b4b2bc9d93db7a584554c3dc4f93ae0342639 100644 (file)
 
 
 #ifndef __ASSEMBLER__
-bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs);
-void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs);
-void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs);
-void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs);
-void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs);
-
-#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
-extern int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs);
-extern void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs);
-extern void am33xx_cm_module_disable(u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs);
-extern int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs);
-#else
-static inline int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs)
-{
-       return 0;
-}
-static inline void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs)
-{
-}
-static inline void am33xx_cm_module_disable(u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs)
-{
-}
-static inline int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs)
-{
-       return 0;
-}
-#endif
-
+int am33xx_cm_init(void);
 #endif /* ASSEMBLER */
 #endif
index 129a4e7f6ef56418565668813edf9b42ed945589..ebead8f035f986d257e7d406bbe12d4bcf3089fa 100644 (file)
@@ -42,7 +42,7 @@ static void _write_clktrctrl(u8 c, s16 module, u32 mask)
        omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
 }
 
-bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
+static bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
 {
        u32 v;
 
@@ -53,22 +53,22 @@ bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
        return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
 }
 
-void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
+static void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
 {
        _write_clktrctrl(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
 }
 
-void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
+static void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
 {
        _write_clktrctrl(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
 }
 
-void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
+static void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask)
 {
        _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, module, mask);
 }
 
-void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
+static void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
 {
        _write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
 }
@@ -79,6 +79,7 @@ void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
 
 /**
  * omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
+ * @part: PRCM partition, ignored for OMAP3
  * @prcm_mod: PRCM module offset
  * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
  * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
@@ -87,7 +88,8 @@ void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
  * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
  * success or -EBUSY if the module doesn't enable in time.
  */
-int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
+                                        u8 idlest_shift)
 {
        int ena = 0, i = 0;
        u8 cm_idlest_reg;
@@ -116,8 +118,9 @@ int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
  * XXX This function is only needed until absolute register addresses are
  * removed from the OMAP struct clk records.
  */
-int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
-                                u8 *idlest_reg_id)
+static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+                                       s16 *prcm_inst,
+                                       u8 *idlest_reg_id)
 {
        unsigned long offs;
        u8 idlest_offs;
index 7a16b5598127320b5f4b30d42b2ced459f4981ae..734a8581c0c4e07d8286e7cd7725357955481384 100644 (file)
 
 #ifndef __ASSEMBLER__
 
-extern void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
-extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
-extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
-extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
-
-extern bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
-extern int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
-                                        u8 idlest_shift);
-
-extern int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
-                                       s16 *prcm_inst, u8 *idlest_reg_id);
-
 extern void omap3_cm_save_context(void);
 extern void omap3_cm_restore_context(void);
 extern void omap3_cm_save_scratchpad_contents(u32 *ptr);
diff --git a/arch/arm/mach-omap2/cm44xx.c b/arch/arm/mach-omap2/cm44xx.c
deleted file mode 100644 (file)
index fe5cc7b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * OMAP4 CM1, CM2 module low-level functions
- *
- * Copyright (C) 2010 Nokia Corporation
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * These functions are intended to be used only by the cminst44xx.c file.
- * XXX Perhaps we should just move them there and make them static.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include "cm.h"
-#include "cm1_44xx.h"
-#include "cm2_44xx.h"
-
-/* CM1 hardware module low-level functions */
-
-/* Read a register in CM1 */
-u32 omap4_cm1_read_inst_reg(s16 inst, u16 reg)
-{
-       return readl_relaxed(cm_base + inst + reg);
-}
-
-/* Write into a register in CM1 */
-void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 reg)
-{
-       writel_relaxed(val, cm_base + inst + reg);
-}
-
-/* Read a register in CM2 */
-u32 omap4_cm2_read_inst_reg(s16 inst, u16 reg)
-{
-       return readl_relaxed(cm2_base + inst + reg);
-}
-
-/* Write into a register in CM2 */
-void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 reg)
-{
-       writel_relaxed(val, cm2_base + inst + reg);
-}
index 3380beeace6e2173db2e06017bceb1457999eaf4..728d06a4af198f16cd5afab63ecccb752c68936f 100644 (file)
@@ -23,4 +23,7 @@
 #define OMAP4_CM_CLKSTCTRL                             0x0000
 #define OMAP4_CM_STATICDEP                             0x0004
 
+void omap_cm_base_init(void);
+int omap4_cm_init(void);
+
 #endif
diff --git a/arch/arm/mach-omap2/cm_44xx_54xx.h b/arch/arm/mach-omap2/cm_44xx_54xx.h
deleted file mode 100644 (file)
index cbb2116..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * OMAP44xx and OMAP54xx CM1/CM2 function prototypes
- *
- * Copyright (C) 2009-2013 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
- *
- * Paul Walmsley (paul@pwsan.com)
- * Rajendra Nayak (rnayak@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_CM_44XX_54XX_H
-#define __ARCH_ARM_MACH_OMAP2_CM_44XX_55XX_H
-
-/* CM1 Function prototypes */
-extern u32 omap4_cm1_read_inst_reg(s16 inst, u16 idx);
-extern void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 idx);
-extern u32 omap4_cm1_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
-
-/* CM2 Function prototypes */
-extern u32 omap4_cm2_read_inst_reg(s16 inst, u16 idx);
-extern void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 idx);
-extern u32 omap4_cm2_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
-
-#endif
index 8f6c4710877e073e2d4b8a5c1158b8cee62f5fff..8fe02fcedc48e3974bc90388753efa8a9c27aab6 100644 (file)
@@ -72,9 +72,10 @@ int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
 }
 
 /**
- * cm_wait_module_ready - wait for a module to leave idle or standby
+ * omap_cm_wait_module_ready - wait for a module to leave idle or standby
+ * @part: PRCM partition
  * @prcm_mod: PRCM module offset
- * @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
+ * @idlest_reg: CM_IDLESTx register
  * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
  *
  * Wait for the PRCM to indicate that the module identified by
@@ -83,7 +84,8 @@ int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
  * no per-SoC wait_module_ready() function pointer has been registered
  * or if the idlest register is unknown on the SoC.
  */
-int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
+int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
+                             u8 idlest_shift)
 {
        if (!cm_ll_data->wait_module_ready) {
                WARN_ONCE(1, "cm: %s: no low-level function defined\n",
@@ -91,7 +93,79 @@ int cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
                return -EINVAL;
        }
 
-       return cm_ll_data->wait_module_ready(prcm_mod, idlest_id, idlest_shift);
+       return cm_ll_data->wait_module_ready(part, prcm_mod, idlest_reg,
+                                            idlest_shift);
+}
+
+/**
+ * omap_cm_wait_module_idle - wait for a module to enter idle or standby
+ * @part: PRCM partition
+ * @prcm_mod: PRCM module offset
+ * @idlest_reg: CM_IDLESTx register
+ * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
+ *
+ * Wait for the PRCM to indicate that the module identified by
+ * (@prcm_mod, @idlest_id, @idlest_shift) is no longer clocked.  Return
+ * 0 upon success, -EBUSY if the module doesn't enable in time, or
+ * -EINVAL if no per-SoC wait_module_idle() function pointer has been
+ * registered or if the idlest register is unknown on the SoC.
+ */
+int omap_cm_wait_module_idle(u8 part, s16 prcm_mod, u16 idlest_reg,
+                            u8 idlest_shift)
+{
+       if (!cm_ll_data->wait_module_idle) {
+               WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+                         __func__);
+               return -EINVAL;
+       }
+
+       return cm_ll_data->wait_module_idle(part, prcm_mod, idlest_reg,
+                                           idlest_shift);
+}
+
+/**
+ * omap_cm_module_enable - enable a module
+ * @mode: target mode for the module
+ * @part: PRCM partition
+ * @inst: PRCM instance
+ * @clkctrl_offs: CM_CLKCTRL register offset for the module
+ *
+ * Enables clocks for a module identified by (@part, @inst, @clkctrl_offs)
+ * making its IO space accessible. Return 0 upon success, -EINVAL if no
+ * per-SoC module_enable() function pointer has been registered.
+ */
+int omap_cm_module_enable(u8 mode, u8 part, u16 inst, u16 clkctrl_offs)
+{
+       if (!cm_ll_data->module_enable) {
+               WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+                         __func__);
+               return -EINVAL;
+       }
+
+       cm_ll_data->module_enable(mode, part, inst, clkctrl_offs);
+       return 0;
+}
+
+/**
+ * omap_cm_module_disable - disable a module
+ * @part: PRCM partition
+ * @inst: PRCM instance
+ * @clkctrl_offs: CM_CLKCTRL register offset for the module
+ *
+ * Disables clocks for a module identified by (@part, @inst, @clkctrl_offs)
+ * makings its IO space inaccessible. Return 0 upon success, -EINVAL if
+ * no per-SoC module_disable() function pointer has been registered.
+ */
+int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
+{
+       if (!cm_ll_data->module_disable) {
+               WARN_ONCE(1, "cm: %s: no low-level function defined\n",
+                         __func__);
+               return -EINVAL;
+       }
+
+       cm_ll_data->module_disable(part, inst, clkctrl_offs);
+       return 0;
 }
 
 /**
index 12aca56942c09dff2c85b67de94f73015e6dd528..95a8cff66aff5adf51320dda23c58b773adf67b6 100644 (file)
@@ -26,7 +26,6 @@
 #include "cm1_44xx.h"
 #include "cm2_44xx.h"
 #include "cm44xx.h"
-#include "cminst44xx.h"
 #include "cm-regbits-34xx.h"
 #include "prcm44xx.h"
 #include "prm44xx.h"
@@ -74,17 +73,18 @@ void omap_cm_base_init(void)
 
 /* Private functions */
 
+static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx);
+
 /**
  * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to
  * bit 0.
  */
-static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static u32 _clkctrl_idlest(u8 part, u16 inst, u16 clkctrl_offs)
 {
        u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs);
        v &= OMAP4430_IDLEST_MASK;
@@ -96,26 +96,23 @@ static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
  * _is_module_ready - can module registers be accessed without causing an abort?
  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either
  * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise.
  */
-static bool _is_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static bool _is_module_ready(u8 part, u16 inst, u16 clkctrl_offs)
 {
        u32 v;
 
-       v = _clkctrl_idlest(part, inst, cdoffs, clkctrl_offs);
+       v = _clkctrl_idlest(part, inst, clkctrl_offs);
 
        return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
                v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
 }
 
-/* Public functions */
-
 /* Read a register in a CM instance */
-u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx)
+static u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx)
 {
        BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
               part == OMAP4430_INVALID_PRCM_PARTITION ||
@@ -124,7 +121,7 @@ u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx)
 }
 
 /* Write into a register in a CM instance */
-void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx)
+static void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx)
 {
        BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
               part == OMAP4430_INVALID_PRCM_PARTITION ||
@@ -133,8 +130,8 @@ void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx)
 }
 
 /* Read-modify-write a register in CM1. Caller must lock */
-u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, u16 inst,
-                                  s16 idx)
+static u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, u16 inst,
+                                         s16 idx)
 {
        u32 v;
 
@@ -146,17 +143,18 @@ u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, u16 inst,
        return v;
 }
 
-u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, u16 inst, s16 idx)
+static u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, u16 inst, s16 idx)
 {
        return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx);
 }
 
-u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, u16 inst, s16 idx)
+static u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, u16 inst,
+                                           s16 idx)
 {
        return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx);
 }
 
-u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask)
+static u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask)
 {
        u32 v;
 
@@ -200,7 +198,7 @@ static void _clktrctrl_write(u8 c, u8 part, u16 inst, u16 cdoffs)
  * Returns true if the clockdomain referred to by (@part, @inst, @cdoffs)
  * is in hardware-supervised idle mode, or 0 otherwise.
  */
-bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs)
+static bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs)
 {
        u32 v;
 
@@ -220,7 +218,7 @@ bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs)
  * Put a clockdomain referred to by (@part, @inst, @cdoffs) into
  * hardware-supervised idle mode.  No return value.
  */
-void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs)
+static void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, part, inst, cdoffs);
 }
@@ -235,7 +233,7 @@ void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs)
  * software-supervised idle mode, i.e., controlled manually by the
  * Linux OMAP clockdomain code.  No return value.
  */
-void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs)
+static void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs);
 }
@@ -249,7 +247,7 @@ void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs)
  * Take a clockdomain referred to by (@part, @inst, @cdoffs) out of idle,
  * waking it up.  No return value.
  */
-void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs)
+static void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, part, inst, cdoffs);
 }
@@ -258,7 +256,7 @@ void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs)
  *
  */
 
-void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs)
+static void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs)
 {
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, part, inst, cdoffs);
 }
@@ -267,23 +265,23 @@ void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs)
  * omap4_cminst_wait_module_ready - wait for a module to be in 'func' state
  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ * @bit_shift: bit shift for the register, ignored for OMAP4+
  *
  * Wait for the module IDLEST to be functional. If the idle state is in any
  * the non functional state (trans, idle or disabled), module and thus the
  * sysconfig cannot be accessed and will probably lead to an "imprecise
  * external abort"
  */
-int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs,
-                                  u16 clkctrl_offs)
+static int omap4_cminst_wait_module_ready(u8 part, s16 inst, u16 clkctrl_offs,
+                                         u8 bit_shift)
 {
        int i = 0;
 
        if (!clkctrl_offs)
                return 0;
 
-       omap_test_timeout(_is_module_ready(part, inst, cdoffs, clkctrl_offs),
+       omap_test_timeout(_is_module_ready(part, inst, clkctrl_offs),
                          MAX_MODULE_READY_TIME, i);
 
        return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
@@ -294,21 +292,22 @@ int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs,
  * state
  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ * @bit_shift: Bit shift for the register, ignored for OMAP4+
  *
  * Wait for the module IDLEST to be disabled. Some PRCM transition,
  * like reset assertion or parent clock de-activation must wait the
  * module to be fully disabled.
  */
-int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+static int omap4_cminst_wait_module_idle(u8 part, s16 inst, u16 clkctrl_offs,
+                                        u8 bit_shift)
 {
        int i = 0;
 
        if (!clkctrl_offs)
                return 0;
 
-       omap_test_timeout((_clkctrl_idlest(part, inst, cdoffs, clkctrl_offs) ==
+       omap_test_timeout((_clkctrl_idlest(part, inst, clkctrl_offs) ==
                           CLKCTRL_IDLEST_DISABLED),
                          MAX_MODULE_DISABLE_TIME, i);
 
@@ -320,13 +319,12 @@ int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_off
  * @mode: Module mode (SW or HW)
  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * No return value.
  */
-void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
-                           u16 clkctrl_offs)
+static void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst,
+                                      u16 clkctrl_offs)
 {
        u32 v;
 
@@ -340,13 +338,11 @@ void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
  * omap4_cminst_module_disable - Disable the module inside CLKCTRL
  * @part: PRCM partition ID that the CM_CLKCTRL register exists in
  * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
  * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
  *
  * No return value.
  */
-void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
-                            u16 clkctrl_offs)
+static void omap4_cminst_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
 {
        u32 v;
 
@@ -510,3 +506,21 @@ struct clkdm_ops am43xx_clkdm_operations = {
        .clkdm_clk_enable       = omap4_clkdm_clk_enable,
        .clkdm_clk_disable      = omap4_clkdm_clk_disable,
 };
+
+static struct cm_ll_data omap4xxx_cm_ll_data = {
+       .wait_module_ready      = &omap4_cminst_wait_module_ready,
+       .wait_module_idle       = &omap4_cminst_wait_module_idle,
+       .module_enable          = &omap4_cminst_module_enable,
+       .module_disable         = &omap4_cminst_module_disable,
+};
+
+int __init omap4_cm_init(void)
+{
+       return cm_register(&omap4xxx_cm_ll_data);
+}
+
+static void __exit omap4_cm_exit(void)
+{
+       cm_unregister(&omap4xxx_cm_ll_data);
+}
+__exitcall(omap4_cm_exit);
diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
deleted file mode 100644 (file)
index 7f56ea4..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * OMAP4 Clock Management (CM) function prototypes
- *
- * Copyright (C) 2010 Nokia Corporation
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ARCH_ASM_MACH_OMAP2_CMINST44XX_H
-#define __ARCH_ASM_MACH_OMAP2_CMINST44XX_H
-
-bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs);
-void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs);
-void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs);
-void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs);
-void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs);
-extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
-extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
-                                        u16 clkctrl_offs);
-extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
-                                      u16 clkctrl_offs);
-extern void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs);
-/*
- * In an ideal world, we would not export these low-level functions,
- * but this will probably take some time to fix properly
- */
-u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx);
-void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx);
-u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
-                                  u16 inst, s16 idx);
-u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, u16 inst,
-                                  s16 idx);
-u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, u16 inst,
-                                    s16 idx);
-extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
-                                          u32 mask);
-
-extern void omap_cm_base_init(void);
-
-#endif
index 324f02bf8a51da6b3d3395d30c309447a8f7c793..a7bc4ce81e19e3ebc979c56b158a58afd79b461b 100644 (file)
@@ -49,7 +49,7 @@ static int __init omap3_l3_init(void)
         * To avoid code running on other OMAPs in
         * multi-omap builds
         */
-       if (!(cpu_is_omap34xx()))
+       if (!(cpu_is_omap34xx()) || of_have_populated_dt())
                return -ENODEV;
 
        snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
@@ -67,40 +67,6 @@ static int __init omap3_l3_init(void)
 }
 omap_postcore_initcall(omap3_l3_init);
 
-static int __init omap4_l3_init(void)
-{
-       int i;
-       struct omap_hwmod *oh[3];
-       struct platform_device *pdev;
-       char oh_name[L3_MODULES_MAX_LEN];
-
-       /* If dtb is there, the devices will be created dynamically */
-       if (of_have_populated_dt())
-               return -ENODEV;
-
-       /*
-        * To avoid code running on other OMAPs in
-        * multi-omap builds
-        */
-       if (!cpu_is_omap44xx() && !soc_is_omap54xx())
-               return -ENODEV;
-
-       for (i = 0; i < L3_MODULES; i++) {
-               snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main_%d", i+1);
-
-               oh[i] = omap_hwmod_lookup(oh_name);
-               if (!(oh[i]))
-                       pr_err("could not look up %s\n", oh_name);
-       }
-
-       pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL, 0);
-
-       WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
-
-       return PTR_RET(pdev);
-}
-omap_postcore_initcall(omap4_l3_init);
-
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
 static struct resource omap2cam_resources[] = {
@@ -445,3 +411,29 @@ static int __init omap2_init_devices(void)
        return 0;
 }
 omap_arch_initcall(omap2_init_devices);
+
+static int __init omap_gpmc_init(void)
+{
+       struct omap_hwmod *oh;
+       struct platform_device *pdev;
+       char *oh_name = "gpmc";
+
+       /*
+        * if the board boots up with a populated DT, do not
+        * manually add the device from this initcall
+        */
+       if (of_have_populated_dt())
+               return -ENODEV;
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("Could not look up %s\n", oh_name);
+               return -ENODEV;
+       }
+
+       pdev = omap_device_build("omap-gpmc", -1, oh, NULL, 0);
+       WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
+
+       return PTR_RET(pdev);
+}
+omap_postcore_initcall(omap_gpmc_init);
index ac3d789ac3cd8b2ec5de9d4870bae6b0b65f2693..20e120d071dd5853b228106d1164c0e251b2cf45 100644 (file)
@@ -460,25 +460,24 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
 /* Non-CORE DPLL rate set code */
 
 /**
- * omap3_noncore_dpll_set_rate - set non-core DPLL rate
- * @clk: struct clk * of DPLL to set
- * @rate: rounded target rate
+ * omap3_noncore_dpll_determine_rate - determine rate for a DPLL
+ * @hw: pointer to the clock to determine rate for
+ * @rate: target rate for the DPLL
+ * @best_parent_rate: pointer for returning best parent rate
+ * @best_parent_clk: pointer for returning best parent clock
  *
- * Set the DPLL CLKOUT to the target rate.  If the DPLL can enter
- * low-power bypass, and the target rate is the bypass source clock
- * rate, then configure the DPLL for bypass.  Otherwise, round the
- * target rate if it hasn't been done already, then program and lock
- * the DPLL.  Returns -EINVAL upon error, or 0 upon success.
+ * Determines which DPLL mode to use for reaching a desired target rate.
+ * Checks whether the DPLL shall be in bypass or locked mode, and if
+ * locked, calculates the M,N values for the DPLL via round-rate.
+ * Returns a positive clock rate with success, negative error value
+ * in failure.
  */
-int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
-                                       unsigned long parent_rate)
+long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
+                                      unsigned long *best_parent_rate,
+                                      struct clk **best_parent_clk)
 {
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       struct clk *new_parent = NULL;
-       unsigned long rrate;
-       u16 freqsel = 0;
        struct dpll_data *dd;
-       int ret;
 
        if (!hw || !rate)
                return -EINVAL;
@@ -489,61 +488,121 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        if (__clk_get_rate(dd->clk_bypass) == rate &&
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
-               pr_debug("%s: %s: set rate: entering bypass.\n",
-                        __func__, __clk_get_name(hw->clk));
+               *best_parent_clk = dd->clk_bypass;
+       } else {
+               rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
+               *best_parent_clk = dd->clk_ref;
+       }
+
+       *best_parent_rate = rate;
+
+       return rate;
+}
+
+/**
+ * omap3_noncore_dpll_set_parent - set parent for a DPLL clock
+ * @hw: pointer to the clock to set parent for
+ * @index: parent index to select
+ *
+ * Sets parent for a DPLL clock. This sets the DPLL into bypass or
+ * locked mode. Returns 0 with success, negative error value otherwise.
+ */
+int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       int ret;
 
-               __clk_prepare(dd->clk_bypass);
-               clk_enable(dd->clk_bypass);
+       if (!hw)
+               return -EINVAL;
+
+       if (index)
                ret = _omap3_noncore_dpll_bypass(clk);
-               if (!ret)
-                       new_parent = dd->clk_bypass;
-               clk_disable(dd->clk_bypass);
-               __clk_unprepare(dd->clk_bypass);
-       } else {
-               __clk_prepare(dd->clk_ref);
-               clk_enable(dd->clk_ref);
-
-               /* XXX this check is probably pointless in the CCF context */
-               if (dd->last_rounded_rate != rate) {
-                       rrate = __clk_round_rate(hw->clk, rate);
-                       if (rrate != rate) {
-                               pr_warn("%s: %s: final rate %lu does not match desired rate %lu\n",
-                                       __func__, __clk_get_name(hw->clk),
-                                       rrate, rate);
-                               rate = rrate;
-                       }
-               }
+       else
+               ret = _omap3_noncore_dpll_lock(clk);
 
-               if (dd->last_rounded_rate == 0)
-                       return -EINVAL;
+       return ret;
+}
 
-               /* Freqsel is available only on OMAP343X devices */
-               if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
-                       freqsel = _omap3_dpll_compute_freqsel(clk,
-                                               dd->last_rounded_n);
-                       WARN_ON(!freqsel);
-               }
+/**
+ * omap3_noncore_dpll_set_rate - set rate for a DPLL clock
+ * @hw: pointer to the clock to set parent for
+ * @rate: target rate for the clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Sets rate for a DPLL clock. First checks if the clock parent is
+ * reference clock (in bypass mode, the rate of the clock can't be
+ * changed) and proceeds with the rate change operation. Returns 0
+ * with success, negative error value otherwise.
+ */
+int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *dd;
+       u16 freqsel = 0;
+       int ret;
+
+       if (!hw || !rate)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
 
-               pr_debug("%s: %s: set rate: locking rate to %lu.\n",
-                        __func__, __clk_get_name(hw->clk), rate);
+       if (__clk_get_parent(hw->clk) != dd->clk_ref)
+               return -EINVAL;
+
+       if (dd->last_rounded_rate == 0)
+               return -EINVAL;
 
-               ret = omap3_noncore_dpll_program(clk, freqsel);
-               if (!ret)
-                       new_parent = dd->clk_ref;
-               clk_disable(dd->clk_ref);
-               __clk_unprepare(dd->clk_ref);
+       /* Freqsel is available only on OMAP343X devices */
+       if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) {
+               freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
+               WARN_ON(!freqsel);
        }
-       /*
-       * FIXME - this is all wrong.  common code handles reparenting and
-       * migrating prepare/enable counts.  dplls should be a multiplexer
-       * clock and this should be a set_parent operation so that all of that
-       * stuff is inherited for free
-       */
 
-       if (!ret && clk_get_parent(hw->clk) != new_parent)
-               __clk_reparent(hw->clk, new_parent);
+       pr_debug("%s: %s: set rate: locking rate to %lu.\n", __func__,
+                __clk_get_name(hw->clk), rate);
 
-       return 0;
+       ret = omap3_noncore_dpll_program(clk, freqsel);
+
+       return ret;
+}
+
+/**
+ * omap3_noncore_dpll_set_rate_and_parent - set rate and parent for a DPLL clock
+ * @hw: pointer to the clock to set rate and parent for
+ * @rate: target rate for the DPLL
+ * @parent_rate: clock rate of the DPLL parent
+ * @index: new parent index for the DPLL, 0 - reference, 1 - bypass
+ *
+ * Sets rate and parent for a DPLL clock. If new parent is the bypass
+ * clock, only selects the parent. Otherwise proceeds with a rate
+ * change, as this will effectively also change the parent as the
+ * DPLL is put into locked mode. Returns 0 with success, negative error
+ * value otherwise.
+ */
+int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
+                                          unsigned long rate,
+                                          unsigned long parent_rate,
+                                          u8 index)
+{
+       int ret;
+
+       if (!hw || !rate)
+               return -EINVAL;
+
+       /*
+        * clk-ref at index[0], in which case we only need to set rate,
+        * the parent will be changed automatically with the lock sequence.
+        * With clk-bypass case we only need to change parent.
+        */
+       if (index)
+               ret = omap3_noncore_dpll_set_parent(hw, index);
+       else
+               ret = omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+
+       return ret;
 }
 
 /* DPLL autoidle read/set code */
index 4613f1e86988751072826fb549a0f920d7df25e8..535822fcf4bbbd1e57a1211d122449d0a8a5807d 100644 (file)
@@ -207,3 +207,44 @@ out:
 
        return dd->last_rounded_rate;
 }
+
+/**
+ * omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL
+ * @hw: pointer to the clock to determine rate for
+ * @rate: target rate for the DPLL
+ * @best_parent_rate: pointer for returning best parent rate
+ * @best_parent_clk: pointer for returning best parent clock
+ *
+ * Determines which DPLL mode to use for reaching a desired rate.
+ * Checks whether the DPLL shall be in bypass or locked mode, and if
+ * locked, calculates the M,N values for the DPLL via round-rate.
+ * Returns a positive clock rate with success, negative error value
+ * in failure.
+ */
+long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *best_parent_rate,
+                                       struct clk **best_parent_clk)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *dd;
+
+       if (!hw || !rate)
+               return -EINVAL;
+
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
+
+       if (__clk_get_rate(dd->clk_bypass) == rate &&
+           (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+               *best_parent_clk = dd->clk_bypass;
+       } else {
+               rate = omap4_dpll_regm4xen_round_rate(hw, rate,
+                                                     best_parent_rate);
+               *best_parent_clk = dd->clk_ref;
+       }
+
+       *best_parent_rate = rate;
+
+       return rate;
+}
index cb7764314f1736206c9dba849e2e777c76cbb1e7..d5951b17b7368c0713b5bddd56e03cff34b6cc17 100644 (file)
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/omap-gpmc.h>
 #include <linux/mtd/nand.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #include <asm/mach/flash.h>
 
-#include "gpmc.h"
 #include "soc.h"
-#include "gpmc-nand.h"
 
 /* minimum size for IO mapping */
 #define        NAND_IO_SIZE    4
diff --git a/arch/arm/mach-omap2/gpmc-nand.h b/arch/arm/mach-omap2/gpmc-nand.h
deleted file mode 100644 (file)
index d59e128..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  arch/arm/mach-omap2/gpmc-nand.h
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#ifndef        __OMAP2_GPMC_NAND_H
-#define        __OMAP2_GPMC_NAND_H
-
-#include "gpmc.h"
-#include <linux/platform_data/mtd-nand-omap2.h>
-
-#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d,
-                         struct gpmc_timings *gpmc_t);
-#else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d,
-                                struct gpmc_timings *gpmc_t)
-{
-       return 0;
-}
-#endif
-
-#endif
index 8b6876c98ce1a320c793e7485c35d23bd3a5b923..53d197e0c1f34525b828e256bff935e41ebe7d33 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/mtd/onenand_regs.h>
 #include <linux/io.h>
+#include <linux/omap-gpmc.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
 #include <linux/err.h>
 
 #include <asm/mach/flash.h>
 
-#include "gpmc.h"
 #include "soc.h"
-#include "gpmc-onenand.h"
 
 #define        ONENAND_IO_SIZE SZ_128K
 
diff --git a/arch/arm/mach-omap2/gpmc-onenand.h b/arch/arm/mach-omap2/gpmc-onenand.h
deleted file mode 100644 (file)
index 216f23a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  arch/arm/mach-omap2/gpmc-onenand.h
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#ifndef        __OMAP2_GPMC_ONENAND_H
-#define        __OMAP2_GPMC_ONENAND_H
-
-#include <linux/platform_data/mtd-onenand-omap2.h>
-
-#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
-#else
-#define board_onenand_data     NULL
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
-{
-}
-#endif
-
-#endif
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
deleted file mode 100644 (file)
index 61a0635..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/gpmc-smc91x.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Contact:    Tony Lindgren
- *
- * This program is free software; you can 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/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/smc91x.h>
-
-#include "gpmc.h"
-#include "gpmc-smc91x.h"
-
-#include "soc.h"
-
-static struct omap_smc91x_platform_data *gpmc_cfg;
-
-static struct resource gpmc_smc91x_resources[] = {
-       [0] = {
-               .flags          = IORESOURCE_MEM,
-       },
-       [1] = {
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct smc91x_platdata gpmc_smc91x_info = {
-       .flags  = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0,
-       .leda   = RPC_LED_100_10,
-       .ledb   = RPC_LED_TX_RX,
-};
-
-static struct platform_device gpmc_smc91x_device = {
-       .name           = "smc91x",
-       .id             = -1,
-       .dev            = {
-               .platform_data = &gpmc_smc91x_info,
-       },
-       .num_resources  = ARRAY_SIZE(gpmc_smc91x_resources),
-       .resource       = gpmc_smc91x_resources,
-};
-
-static struct gpmc_settings smc91x_settings = {
-       .device_width = GPMC_DEVWIDTH_16BIT,
-};
-
-/*
- * Set the gpmc timings for smc91c96. The timings are taken
- * from the data sheet available at:
- * http://www.smsc.com/main/catalog/lan91c96.html
- * REVISIT: Level shifters can add at least to the access latency.
- */
-static int smc91c96_gpmc_retime(void)
-{
-       struct gpmc_timings t;
-       struct gpmc_device_timings dev_t;
-       const int t3 = 10;      /* Figure 12.2 read and 12.4 write */
-       const int t4_r = 20;    /* Figure 12.2 read */
-       const int t4_w = 5;     /* Figure 12.4 write */
-       const int t5 = 25;      /* Figure 12.2 read */
-       const int t6 = 15;      /* Figure 12.2 read */
-       const int t7 = 5;       /* Figure 12.4 write */
-       const int t8 = 5;       /* Figure 12.4 write */
-       const int t20 = 185;    /* Figure 12.2 read and 12.4 write */
-
-       /*
-        * FIXME: Calculate the address and data bus muxed timings.
-        * Note that at least adv_rd_off needs to be changed according
-        * to omap3430 TRM Figure 11-11. Are the sdp boards using the
-        * FPGA in between smc91x and omap as the timings are different
-        * from above?
-        */
-       if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-               return 0;
-
-       memset(&dev_t, 0, sizeof(dev_t));
-
-       dev_t.t_oeasu = t3 * 1000;
-       dev_t.t_oe = t5 * 1000;
-       dev_t.t_cez_r = t4_r * 1000;
-       dev_t.t_oez = t6 * 1000;
-       dev_t.t_rd_cycle = (t20 - t3) * 1000;
-
-       dev_t.t_weasu = t3 * 1000;
-       dev_t.t_wpl = t7 * 1000;
-       dev_t.t_wph = t8 * 1000;
-       dev_t.t_cez_w = t4_w * 1000;
-       dev_t.t_wr_cycle = (t20 - t3) * 1000;
-
-       gpmc_calc_timings(&t, &smc91x_settings, &dev_t);
-
-       return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
-}
-
-/*
- * Initialize smc91x device connected to the GPMC. Note that we
- * assume that pin multiplexing is done in the board-*.c file,
- * or in the bootloader.
- */
-void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
-{
-       unsigned long cs_mem_base;
-       int ret;
-
-       gpmc_cfg = board_data;
-
-       if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96)
-               gpmc_cfg->retime = smc91c96_gpmc_retime;
-
-       if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-               printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-               return;
-       }
-
-       gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
-       gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
-       gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
-
-       if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-               smc91x_settings.mux_add_data = GPMC_MUX_AD;
-       if (gpmc_cfg->flags & GPMC_READ_MON)
-               smc91x_settings.wait_on_read = true;
-       if (gpmc_cfg->flags & GPMC_WRITE_MON)
-               smc91x_settings.wait_on_write = true;
-       if (gpmc_cfg->wait_pin)
-               smc91x_settings.wait_pin = gpmc_cfg->wait_pin;
-       ret = gpmc_cs_program_settings(gpmc_cfg->cs, &smc91x_settings);
-       if (ret < 0)
-               goto free1;
-
-       if (gpmc_cfg->retime) {
-               ret = gpmc_cfg->retime();
-               if (ret != 0)
-                       goto free1;
-       }
-
-       if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "SMC91X irq") < 0)
-               goto free1;
-
-       gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
-
-       if (gpmc_cfg->gpio_pwrdwn) {
-               ret = gpio_request_one(gpmc_cfg->gpio_pwrdwn,
-                                      GPIOF_OUT_INIT_LOW, "SMC91X powerdown");
-               if (ret)
-                       goto free2;
-       }
-
-       if (gpmc_cfg->gpio_reset) {
-               ret = gpio_request_one(gpmc_cfg->gpio_reset,
-                                      GPIOF_OUT_INIT_LOW, "SMC91X reset");
-               if (ret)
-                       goto free3;
-
-               gpio_set_value(gpmc_cfg->gpio_reset, 1);
-               msleep(100);
-               gpio_set_value(gpmc_cfg->gpio_reset, 0);
-       }
-
-       if (platform_device_register(&gpmc_smc91x_device) < 0) {
-               printk(KERN_ERR "Unable to register smc91x device\n");
-               gpio_free(gpmc_cfg->gpio_reset);
-               goto free3;
-       }
-
-       return;
-
-free3:
-       if (gpmc_cfg->gpio_pwrdwn)
-               gpio_free(gpmc_cfg->gpio_pwrdwn);
-free2:
-       gpio_free(gpmc_cfg->gpio_irq);
-free1:
-       gpmc_cs_free(gpmc_cfg->cs);
-
-       printk(KERN_ERR "Could not initialize smc91x\n");
-}
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.h b/arch/arm/mach-omap2/gpmc-smc91x.h
deleted file mode 100644 (file)
index b64fbee..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/gpmc-smc91x.h
- *
- * Copyright (C) 2009 Nokia 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 __ASM_ARCH_OMAP_GPMC_SMC91X_H__
-
-#define GPMC_TIMINGS_SMC91C96  (1 << 4)
-#define GPMC_MUX_ADD_DATA      (1 << 5) /* GPMC_CONFIG1_MUXADDDATA */
-#define GPMC_READ_MON          (1 << 6) /* GPMC_CONFIG1_WAIT_READ_MON */
-#define GPMC_WRITE_MON         (1 << 7) /* GPMC_CONFIG1_WAIT_WRITE_MON */
-
-struct omap_smc91x_platform_data {
-       int     cs;
-       int     gpio_irq;
-       int     gpio_pwrdwn;
-       int     gpio_reset;
-       int     wait_pin;       /* Optional GPMC_CONFIG1_WAITPINSELECT */
-       u32     flags;
-       int     (*retime)(void);
-};
-
-#if defined(CONFIG_SMC91X) || \
-       defined(CONFIG_SMC91X_MODULE)
-
-extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
-
-#else
-
-#define board_smc91x_data      NULL
-
-static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
-{
-}
-
-#endif
-#endif
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
deleted file mode 100644 (file)
index 5fa3755..0000000
+++ /dev/null
@@ -1,1891 +0,0 @@
-/*
- * GPMC support functions
- *
- * Copyright (C) 2005-2006 Nokia Corporation
- *
- * Author: Juha Yrjola
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@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.
- */
-#undef DEBUG
-
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_mtd.h>
-#include <linux/of_device.h>
-#include <linux/mtd/nand.h>
-#include <linux/pm_runtime.h>
-
-#include <linux/platform_data/mtd-nand-omap2.h>
-
-#include <asm/mach-types.h>
-
-#include "soc.h"
-#include "common.h"
-#include "omap_device.h"
-#include "gpmc.h"
-#include "gpmc-nand.h"
-#include "gpmc-onenand.h"
-
-#define        DEVICE_NAME             "omap-gpmc"
-
-/* GPMC register offsets */
-#define GPMC_REVISION          0x00
-#define GPMC_SYSCONFIG         0x10
-#define GPMC_SYSSTATUS         0x14
-#define GPMC_IRQSTATUS         0x18
-#define GPMC_IRQENABLE         0x1c
-#define GPMC_TIMEOUT_CONTROL   0x40
-#define GPMC_ERR_ADDRESS       0x44
-#define GPMC_ERR_TYPE          0x48
-#define GPMC_CONFIG            0x50
-#define GPMC_STATUS            0x54
-#define GPMC_PREFETCH_CONFIG1  0x1e0
-#define GPMC_PREFETCH_CONFIG2  0x1e4
-#define GPMC_PREFETCH_CONTROL  0x1ec
-#define GPMC_PREFETCH_STATUS   0x1f0
-#define GPMC_ECC_CONFIG                0x1f4
-#define GPMC_ECC_CONTROL       0x1f8
-#define GPMC_ECC_SIZE_CONFIG   0x1fc
-#define GPMC_ECC1_RESULT        0x200
-#define GPMC_ECC_BCH_RESULT_0   0x240   /* not available on OMAP2 */
-#define        GPMC_ECC_BCH_RESULT_1   0x244   /* not available on OMAP2 */
-#define        GPMC_ECC_BCH_RESULT_2   0x248   /* not available on OMAP2 */
-#define        GPMC_ECC_BCH_RESULT_3   0x24c   /* not available on OMAP2 */
-#define        GPMC_ECC_BCH_RESULT_4   0x300   /* not available on OMAP2 */
-#define        GPMC_ECC_BCH_RESULT_5   0x304   /* not available on OMAP2 */
-#define        GPMC_ECC_BCH_RESULT_6   0x308   /* not available on OMAP2 */
-
-/* GPMC ECC control settings */
-#define GPMC_ECC_CTRL_ECCCLEAR         0x100
-#define GPMC_ECC_CTRL_ECCDISABLE       0x000
-#define GPMC_ECC_CTRL_ECCREG1          0x001
-#define GPMC_ECC_CTRL_ECCREG2          0x002
-#define GPMC_ECC_CTRL_ECCREG3          0x003
-#define GPMC_ECC_CTRL_ECCREG4          0x004
-#define GPMC_ECC_CTRL_ECCREG5          0x005
-#define GPMC_ECC_CTRL_ECCREG6          0x006
-#define GPMC_ECC_CTRL_ECCREG7          0x007
-#define GPMC_ECC_CTRL_ECCREG8          0x008
-#define GPMC_ECC_CTRL_ECCREG9          0x009
-
-#define        GPMC_CONFIG2_CSEXTRADELAY               BIT(7)
-#define        GPMC_CONFIG3_ADVEXTRADELAY              BIT(7)
-#define        GPMC_CONFIG4_OEEXTRADELAY               BIT(7)
-#define        GPMC_CONFIG4_WEEXTRADELAY               BIT(23)
-#define        GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN        BIT(6)
-#define        GPMC_CONFIG6_CYCLE2CYCLESAMECSEN        BIT(7)
-
-#define GPMC_CS0_OFFSET                0x60
-#define GPMC_CS_SIZE           0x30
-#define        GPMC_BCH_SIZE           0x10
-
-#define GPMC_MEM_END           0x3FFFFFFF
-
-#define GPMC_CHUNK_SHIFT       24              /* 16 MB */
-#define GPMC_SECTION_SHIFT     28              /* 128 MB */
-
-#define CS_NUM_SHIFT           24
-#define ENABLE_PREFETCH                (0x1 << 7)
-#define DMA_MPU_MODE           2
-
-#define        GPMC_REVISION_MAJOR(l)          ((l >> 4) & 0xf)
-#define        GPMC_REVISION_MINOR(l)          (l & 0xf)
-
-#define        GPMC_HAS_WR_ACCESS              0x1
-#define        GPMC_HAS_WR_DATA_MUX_BUS        0x2
-#define        GPMC_HAS_MUX_AAD                0x4
-
-#define GPMC_NR_WAITPINS               4
-
-/* XXX: Only NAND irq has been considered,currently these are the only ones used
- */
-#define        GPMC_NR_IRQ             2
-
-struct gpmc_client_irq {
-       unsigned                irq;
-       u32                     bitmask;
-};
-
-/* Structure to save gpmc cs context */
-struct gpmc_cs_config {
-       u32 config1;
-       u32 config2;
-       u32 config3;
-       u32 config4;
-       u32 config5;
-       u32 config6;
-       u32 config7;
-       int is_valid;
-};
-
-/*
- * Structure to save/restore gpmc context
- * to support core off on OMAP3
- */
-struct omap3_gpmc_regs {
-       u32 sysconfig;
-       u32 irqenable;
-       u32 timeout_ctrl;
-       u32 config;
-       u32 prefetch_config1;
-       u32 prefetch_config2;
-       u32 prefetch_control;
-       struct gpmc_cs_config cs_context[GPMC_CS_NUM];
-};
-
-static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
-static struct irq_chip gpmc_irq_chip;
-static int gpmc_irq_start;
-
-static struct resource gpmc_mem_root;
-static struct resource gpmc_cs_mem[GPMC_CS_NUM];
-static DEFINE_SPINLOCK(gpmc_mem_lock);
-/* Define chip-selects as reserved by default until probe completes */
-static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
-static unsigned int gpmc_cs_num = GPMC_CS_NUM;
-static unsigned int gpmc_nr_waitpins;
-static struct device *gpmc_dev;
-static int gpmc_irq;
-static resource_size_t phys_base, mem_size;
-static unsigned gpmc_capability;
-static void __iomem *gpmc_base;
-
-static struct clk *gpmc_l3_clk;
-
-static irqreturn_t gpmc_handle_irq(int irq, void *dev);
-
-static void gpmc_write_reg(int idx, u32 val)
-{
-       writel_relaxed(val, gpmc_base + idx);
-}
-
-static u32 gpmc_read_reg(int idx)
-{
-       return readl_relaxed(gpmc_base + idx);
-}
-
-void gpmc_cs_write_reg(int cs, int idx, u32 val)
-{
-       void __iomem *reg_addr;
-
-       reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-       writel_relaxed(val, reg_addr);
-}
-
-static u32 gpmc_cs_read_reg(int cs, int idx)
-{
-       void __iomem *reg_addr;
-
-       reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-       return readl_relaxed(reg_addr);
-}
-
-/* TODO: Add support for gpmc_fck to clock framework and use it */
-static unsigned long gpmc_get_fclk_period(void)
-{
-       unsigned long rate = clk_get_rate(gpmc_l3_clk);
-
-       if (rate == 0) {
-               printk(KERN_WARNING "gpmc_l3_clk not enabled\n");
-               return 0;
-       }
-
-       rate /= 1000;
-       rate = 1000000000 / rate;       /* In picoseconds */
-
-       return rate;
-}
-
-static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
-{
-       unsigned long tick_ps;
-
-       /* Calculate in picosecs to yield more exact results */
-       tick_ps = gpmc_get_fclk_period();
-
-       return (time_ns * 1000 + tick_ps - 1) / tick_ps;
-}
-
-static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
-{
-       unsigned long tick_ps;
-
-       /* Calculate in picosecs to yield more exact results */
-       tick_ps = gpmc_get_fclk_period();
-
-       return (time_ps + tick_ps - 1) / tick_ps;
-}
-
-unsigned int gpmc_ticks_to_ns(unsigned int ticks)
-{
-       return ticks * gpmc_get_fclk_period() / 1000;
-}
-
-static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
-{
-       return ticks * gpmc_get_fclk_period();
-}
-
-static unsigned int gpmc_round_ps_to_ticks(unsigned int time_ps)
-{
-       unsigned long ticks = gpmc_ps_to_ticks(time_ps);
-
-       return ticks * gpmc_get_fclk_period();
-}
-
-static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
-{
-       u32 l;
-
-       l = gpmc_cs_read_reg(cs, reg);
-       if (value)
-               l |= mask;
-       else
-               l &= ~mask;
-       gpmc_cs_write_reg(cs, reg, l);
-}
-
-static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
-{
-       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
-                          GPMC_CONFIG1_TIME_PARA_GRAN,
-                          p->time_para_granularity);
-       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
-                          GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
-       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
-                          GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
-       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
-                          GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
-       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
-                          GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
-       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
-                          GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
-                          p->cycle2cyclesamecsen);
-       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
-                          GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
-                          p->cycle2cyclediffcsen);
-}
-
-#ifdef DEBUG
-static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
-                              int time, const char *name)
-#else
-static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
-                              int time)
-#endif
-{
-       u32 l;
-       int ticks, mask, nr_bits;
-
-       if (time == 0)
-               ticks = 0;
-       else
-               ticks = gpmc_ns_to_ticks(time);
-       nr_bits = end_bit - st_bit + 1;
-       if (ticks >= 1 << nr_bits) {
-#ifdef DEBUG
-               printk(KERN_INFO "GPMC CS%d: %-10s* %3d ns, %3d ticks >= %d\n",
-                               cs, name, time, ticks, 1 << nr_bits);
-#endif
-               return -1;
-       }
-
-       mask = (1 << nr_bits) - 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,
-                       (l >> st_bit) & mask, time);
-#endif
-       l &= ~(mask << st_bit);
-       l |= ticks << st_bit;
-       gpmc_cs_write_reg(cs, reg, l);
-
-       return 0;
-}
-
-#ifdef DEBUG
-#define GPMC_SET_ONE(reg, st, end, field) \
-       if (set_gpmc_timing_reg(cs, (reg), (st), (end),         \
-                       t->field, #field) < 0)                  \
-               return -1
-#else
-#define GPMC_SET_ONE(reg, st, end, field) \
-       if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \
-               return -1
-#endif
-
-int gpmc_calc_divider(unsigned int sync_clk)
-{
-       int div;
-       u32 l;
-
-       l = sync_clk + (gpmc_get_fclk_period() - 1);
-       div = l / gpmc_get_fclk_period();
-       if (div > 4)
-               return -1;
-       if (div <= 0)
-               div = 1;
-
-       return div;
-}
-
-int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
-{
-       int div;
-       u32 l;
-
-       div = gpmc_calc_divider(t->sync_clk);
-       if (div < 0)
-               return div;
-
-       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);
-
-       GPMC_SET_ONE(GPMC_CS_CONFIG3,  0,  3, adv_on);
-       GPMC_SET_ONE(GPMC_CS_CONFIG3,  8, 12, adv_rd_off);
-       GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off);
-
-       GPMC_SET_ONE(GPMC_CS_CONFIG4,  0,  3, oe_on);
-       GPMC_SET_ONE(GPMC_CS_CONFIG4,  8, 12, oe_off);
-       GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on);
-       GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off);
-
-       GPMC_SET_ONE(GPMC_CS_CONFIG5,  0,  4, rd_cycle);
-       GPMC_SET_ONE(GPMC_CS_CONFIG5,  8, 12, wr_cycle);
-       GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access);
-
-       GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
-
-       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)) {
-#ifdef DEBUG
-               printk(KERN_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);
-
-       return 0;
-}
-
-static int gpmc_cs_enable_mem(int cs, u32 base, u32 size)
-{
-       u32 l;
-       u32 mask;
-
-       /*
-        * Ensure that base address is aligned on a
-        * boundary equal to or greater than size.
-        */
-       if (base & (size - 1))
-               return -EINVAL;
-
-       mask = (1 << GPMC_SECTION_SHIFT) - size;
-       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_CSVALID;
-       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
-
-       return 0;
-}
-
-static void gpmc_cs_disable_mem(int cs)
-{
-       u32 l;
-
-       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-       l &= ~GPMC_CONFIG7_CSVALID;
-       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
-}
-
-static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
-{
-       u32 l;
-       u32 mask;
-
-       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-       *base = (l & 0x3f) << GPMC_CHUNK_SHIFT;
-       mask = (l >> 8) & 0x0f;
-       *size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT);
-}
-
-static int gpmc_cs_mem_enabled(int cs)
-{
-       u32 l;
-
-       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-       return l & GPMC_CONFIG7_CSVALID;
-}
-
-static void gpmc_cs_set_reserved(int cs, int reserved)
-{
-       gpmc_cs_map &= ~(1 << cs);
-       gpmc_cs_map |= (reserved ? 1 : 0) << cs;
-}
-
-static bool gpmc_cs_reserved(int cs)
-{
-       return gpmc_cs_map & (1 << cs);
-}
-
-static unsigned long gpmc_mem_align(unsigned long size)
-{
-       int order;
-
-       size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1);
-       order = GPMC_CHUNK_SHIFT - 1;
-       do {
-               size >>= 1;
-               order++;
-       } while (size);
-       size = 1 << order;
-       return size;
-}
-
-static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
-{
-       struct resource *res = &gpmc_cs_mem[cs];
-       int r;
-
-       size = gpmc_mem_align(size);
-       spin_lock(&gpmc_mem_lock);
-       res->start = base;
-       res->end = base + size - 1;
-       r = request_resource(&gpmc_mem_root, res);
-       spin_unlock(&gpmc_mem_lock);
-
-       return r;
-}
-
-static int gpmc_cs_delete_mem(int cs)
-{
-       struct resource *res = &gpmc_cs_mem[cs];
-       int r;
-
-       spin_lock(&gpmc_mem_lock);
-       r = release_resource(res);
-       res->start = 0;
-       res->end = 0;
-       spin_unlock(&gpmc_mem_lock);
-
-       return r;
-}
-
-/**
- * gpmc_cs_remap - remaps a chip-select physical base address
- * @cs:                chip-select to remap
- * @base:      physical base address to re-map chip-select to
- *
- * Re-maps a chip-select to a new physical base address specified by
- * "base". Returns 0 on success and appropriate negative error code
- * on failure.
- */
-static int gpmc_cs_remap(int cs, u32 base)
-{
-       int ret;
-       u32 old_base, size;
-
-       if (cs > gpmc_cs_num) {
-               pr_err("%s: requested chip-select is disabled\n", __func__);
-               return -ENODEV;
-       }
-
-       /*
-        * Make sure we ignore any device offsets from the GPMC partition
-        * allocated for the chip select and that the new base confirms
-        * to the GPMC 16MB minimum granularity.
-        */ 
-       base &= ~(SZ_16M - 1);
-
-       gpmc_cs_get_memconf(cs, &old_base, &size);
-       if (base == old_base)
-               return 0;
-       gpmc_cs_disable_mem(cs);
-       ret = gpmc_cs_delete_mem(cs);
-       if (ret < 0)
-               return ret;
-       ret = gpmc_cs_insert_mem(cs, base, size);
-       if (ret < 0)
-               return ret;
-       ret = gpmc_cs_enable_mem(cs, base, size);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
-{
-       struct resource *res = &gpmc_cs_mem[cs];
-       int r = -1;
-
-       if (cs > gpmc_cs_num) {
-               pr_err("%s: requested chip-select is disabled\n", __func__);
-               return -ENODEV;
-       }
-       size = gpmc_mem_align(size);
-       if (size > (1 << GPMC_SECTION_SHIFT))
-               return -ENOMEM;
-
-       spin_lock(&gpmc_mem_lock);
-       if (gpmc_cs_reserved(cs)) {
-               r = -EBUSY;
-               goto out;
-       }
-       if (gpmc_cs_mem_enabled(cs))
-               r = adjust_resource(res, res->start & ~(size - 1), size);
-       if (r < 0)
-               r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
-                                     size, NULL, NULL);
-       if (r < 0)
-               goto out;
-
-       r = gpmc_cs_enable_mem(cs, res->start, resource_size(res));
-       if (r < 0) {
-               release_resource(res);
-               goto out;
-       }
-
-       *base = res->start;
-       gpmc_cs_set_reserved(cs, 1);
-out:
-       spin_unlock(&gpmc_mem_lock);
-       return r;
-}
-EXPORT_SYMBOL(gpmc_cs_request);
-
-void gpmc_cs_free(int cs)
-{
-       struct resource *res = &gpmc_cs_mem[cs];
-
-       spin_lock(&gpmc_mem_lock);
-       if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
-               printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
-               BUG();
-               spin_unlock(&gpmc_mem_lock);
-               return;
-       }
-       gpmc_cs_disable_mem(cs);
-       if (res->flags)
-               release_resource(res);
-       gpmc_cs_set_reserved(cs, 0);
-       spin_unlock(&gpmc_mem_lock);
-}
-EXPORT_SYMBOL(gpmc_cs_free);
-
-/**
- * gpmc_configure - write request to configure gpmc
- * @cmd: command type
- * @wval: value to write
- * @return status of the operation
- */
-int gpmc_configure(int cmd, int wval)
-{
-       u32 regval;
-
-       switch (cmd) {
-       case GPMC_ENABLE_IRQ:
-               gpmc_write_reg(GPMC_IRQENABLE, wval);
-               break;
-
-       case GPMC_SET_IRQ_STATUS:
-               gpmc_write_reg(GPMC_IRQSTATUS, wval);
-               break;
-
-       case GPMC_CONFIG_WP:
-               regval = gpmc_read_reg(GPMC_CONFIG);
-               if (wval)
-                       regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
-               else
-                       regval |= GPMC_CONFIG_WRITEPROTECT;  /* WP is OFF */
-               gpmc_write_reg(GPMC_CONFIG, regval);
-               break;
-
-       default:
-               pr_err("%s: command not supported\n", __func__);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(gpmc_configure);
-
-void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
-{
-       int i;
-
-       reg->gpmc_status = gpmc_base + GPMC_STATUS;
-       reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
-                               GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
-       reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET +
-                               GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
-       reg->gpmc_nand_data = gpmc_base + GPMC_CS0_OFFSET +
-                               GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
-       reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1;
-       reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2;
-       reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL;
-       reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS;
-       reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG;
-       reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
-       reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
-       reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
-
-       for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) {
-               reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 +
-                                          GPMC_BCH_SIZE * i;
-               reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 +
-                                          GPMC_BCH_SIZE * i;
-               reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 +
-                                          GPMC_BCH_SIZE * i;
-               reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
-                                          GPMC_BCH_SIZE * i;
-               reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
-                                          i * GPMC_BCH_SIZE;
-               reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
-                                          i * GPMC_BCH_SIZE;
-               reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
-                                          i * GPMC_BCH_SIZE;
-       }
-}
-
-int gpmc_get_client_irq(unsigned irq_config)
-{
-       int i;
-
-       if (hweight32(irq_config) > 1)
-               return 0;
-
-       for (i = 0; i < GPMC_NR_IRQ; i++)
-               if (gpmc_client_irq[i].bitmask & irq_config)
-                       return gpmc_client_irq[i].irq;
-
-       return 0;
-}
-
-static int gpmc_irq_endis(unsigned irq, bool endis)
-{
-       int i;
-       u32 regval;
-
-       for (i = 0; i < GPMC_NR_IRQ; i++)
-               if (irq == gpmc_client_irq[i].irq) {
-                       regval = gpmc_read_reg(GPMC_IRQENABLE);
-                       if (endis)
-                               regval |= gpmc_client_irq[i].bitmask;
-                       else
-                               regval &= ~gpmc_client_irq[i].bitmask;
-                       gpmc_write_reg(GPMC_IRQENABLE, regval);
-                       break;
-               }
-
-       return 0;
-}
-
-static void gpmc_irq_disable(struct irq_data *p)
-{
-       gpmc_irq_endis(p->irq, false);
-}
-
-static void gpmc_irq_enable(struct irq_data *p)
-{
-       gpmc_irq_endis(p->irq, true);
-}
-
-static void gpmc_irq_noop(struct irq_data *data) { }
-
-static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
-
-static int gpmc_setup_irq(void)
-{
-       int i;
-       u32 regval;
-
-       if (!gpmc_irq)
-               return -EINVAL;
-
-       gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
-       if (gpmc_irq_start < 0) {
-               pr_err("irq_alloc_descs failed\n");
-               return gpmc_irq_start;
-       }
-
-       gpmc_irq_chip.name = "gpmc";
-       gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret;
-       gpmc_irq_chip.irq_enable = gpmc_irq_enable;
-       gpmc_irq_chip.irq_disable = gpmc_irq_disable;
-       gpmc_irq_chip.irq_shutdown = gpmc_irq_noop;
-       gpmc_irq_chip.irq_ack = gpmc_irq_noop;
-       gpmc_irq_chip.irq_mask = gpmc_irq_noop;
-       gpmc_irq_chip.irq_unmask = gpmc_irq_noop;
-
-       gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE;
-       gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT;
-
-       for (i = 0; i < GPMC_NR_IRQ; i++) {
-               gpmc_client_irq[i].irq = gpmc_irq_start + i;
-               irq_set_chip_and_handler(gpmc_client_irq[i].irq,
-                                       &gpmc_irq_chip, handle_simple_irq);
-               set_irq_flags(gpmc_client_irq[i].irq,
-                               IRQF_VALID | IRQF_NOAUTOEN);
-       }
-
-       /* Disable interrupts */
-       gpmc_write_reg(GPMC_IRQENABLE, 0);
-
-       /* clear interrupts */
-       regval = gpmc_read_reg(GPMC_IRQSTATUS);
-       gpmc_write_reg(GPMC_IRQSTATUS, regval);
-
-       return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL);
-}
-
-static int gpmc_free_irq(void)
-{
-       int i;
-
-       if (gpmc_irq)
-               free_irq(gpmc_irq, NULL);
-
-       for (i = 0; i < GPMC_NR_IRQ; i++) {
-               irq_set_handler(gpmc_client_irq[i].irq, NULL);
-               irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip);
-               irq_modify_status(gpmc_client_irq[i].irq, 0, 0);
-       }
-
-       irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ);
-
-       return 0;
-}
-
-static void gpmc_mem_exit(void)
-{
-       int cs;
-
-       for (cs = 0; cs < gpmc_cs_num; cs++) {
-               if (!gpmc_cs_mem_enabled(cs))
-                       continue;
-               gpmc_cs_delete_mem(cs);
-       }
-
-}
-
-static void gpmc_mem_init(void)
-{
-       int cs;
-
-       /*
-        * The first 1MB of GPMC address space is typically mapped to
-        * the internal ROM. Never allocate the first page, to
-        * facilitate bug detection; even if we didn't boot from ROM.
-        */
-       gpmc_mem_root.start = SZ_1M;
-       gpmc_mem_root.end = GPMC_MEM_END;
-
-       /* Reserve all regions that has been set up by bootloader */
-       for (cs = 0; cs < gpmc_cs_num; cs++) {
-               u32 base, size;
-
-               if (!gpmc_cs_mem_enabled(cs))
-                       continue;
-               gpmc_cs_get_memconf(cs, &base, &size);
-               if (gpmc_cs_insert_mem(cs, base, size)) {
-                       pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n",
-                               __func__, cs, base, base + size);
-                       gpmc_cs_disable_mem(cs);
-               }
-       }
-}
-
-static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
-{
-       u32 temp;
-       int div;
-
-       div = gpmc_calc_divider(sync_clk);
-       temp = gpmc_ps_to_ticks(time_ps);
-       temp = (temp + div - 1) / div;
-       return gpmc_ticks_to_ps(temp * div);
-}
-
-/* XXX: can the cycles be avoided ? */
-static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
-                                      struct gpmc_device_timings *dev_t,
-                                      bool mux)
-{
-       u32 temp;
-
-       /* adv_rd_off */
-       temp = dev_t->t_avdp_r;
-       /* XXX: mux check required ? */
-       if (mux) {
-               /* XXX: t_avdp not to be required for sync, only added for tusb
-                * this indirectly necessitates requirement of t_avdp_r and
-                * t_avdp_w instead of having a single t_avdp
-                */
-               temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_avdh);
-               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
-       }
-       gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
-
-       /* oe_on */
-       temp = dev_t->t_oeasu; /* XXX: remove this ? */
-       if (mux) {
-               temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_ach);
-               temp = max_t(u32, temp, gpmc_t->adv_rd_off +
-                               gpmc_ticks_to_ps(dev_t->cyc_aavdh_oe));
-       }
-       gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
-
-       /* access */
-       /* XXX: any scope for improvement ?, by combining oe_on
-        * and clk_activation, need to check whether
-        * access = clk_activation + round to sync clk ?
-        */
-       temp = max_t(u32, dev_t->t_iaa, dev_t->cyc_iaa * gpmc_t->sync_clk);
-       temp += gpmc_t->clk_activation;
-       if (dev_t->cyc_oe)
-               temp = max_t(u32, temp, gpmc_t->oe_on +
-                               gpmc_ticks_to_ps(dev_t->cyc_oe));
-       gpmc_t->access = gpmc_round_ps_to_ticks(temp);
-
-       gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
-       gpmc_t->cs_rd_off = gpmc_t->oe_off;
-
-       /* rd_cycle */
-       temp = max_t(u32, dev_t->t_cez_r, dev_t->t_oez);
-       temp = gpmc_round_ps_to_sync_clk(temp, gpmc_t->sync_clk) +
-                                                       gpmc_t->access;
-       /* XXX: barter t_ce_rdyz with t_cez_r ? */
-       if (dev_t->t_ce_rdyz)
-               temp = max_t(u32, temp, gpmc_t->cs_rd_off + dev_t->t_ce_rdyz);
-       gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
-
-       return 0;
-}
-
-static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
-                                       struct gpmc_device_timings *dev_t,
-                                       bool mux)
-{
-       u32 temp;
-
-       /* adv_wr_off */
-       temp = dev_t->t_avdp_w;
-       if (mux) {
-               temp = max_t(u32, temp,
-                       gpmc_t->clk_activation + dev_t->t_avdh);
-               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
-       }
-       gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
-
-       /* wr_data_mux_bus */
-       temp = max_t(u32, dev_t->t_weasu,
-                       gpmc_t->clk_activation + dev_t->t_rdyo);
-       /* XXX: shouldn't mux be kept as a whole for wr_data_mux_bus ?,
-        * and in that case remember to handle we_on properly
-        */
-       if (mux) {
-               temp = max_t(u32, temp,
-                       gpmc_t->adv_wr_off + dev_t->t_aavdh);
-               temp = max_t(u32, temp, gpmc_t->adv_wr_off +
-                               gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
-       }
-       gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
-
-       /* we_on */
-       if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
-               gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
-       else
-               gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
-
-       /* wr_access */
-       /* XXX: gpmc_capability check reqd ? , even if not, will not harm */
-       gpmc_t->wr_access = gpmc_t->access;
-
-       /* we_off */
-       temp = gpmc_t->we_on + dev_t->t_wpl;
-       temp = max_t(u32, temp,
-                       gpmc_t->wr_access + gpmc_ticks_to_ps(1));
-       temp = max_t(u32, temp,
-               gpmc_t->we_on + gpmc_ticks_to_ps(dev_t->cyc_wpl));
-       gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
-
-       gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
-                                                       dev_t->t_wph);
-
-       /* wr_cycle */
-       temp = gpmc_round_ps_to_sync_clk(dev_t->t_cez_w, gpmc_t->sync_clk);
-       temp += gpmc_t->wr_access;
-       /* XXX: barter t_ce_rdyz with t_cez_w ? */
-       if (dev_t->t_ce_rdyz)
-               temp = max_t(u32, temp,
-                                gpmc_t->cs_wr_off + dev_t->t_ce_rdyz);
-       gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
-
-       return 0;
-}
-
-static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
-                                       struct gpmc_device_timings *dev_t,
-                                       bool mux)
-{
-       u32 temp;
-
-       /* adv_rd_off */
-       temp = dev_t->t_avdp_r;
-       if (mux)
-               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
-       gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
-
-       /* oe_on */
-       temp = dev_t->t_oeasu;
-       if (mux)
-               temp = max_t(u32, temp,
-                       gpmc_t->adv_rd_off + dev_t->t_aavdh);
-       gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
-
-       /* access */
-       temp = max_t(u32, dev_t->t_iaa, /* XXX: remove t_iaa in async ? */
-                               gpmc_t->oe_on + dev_t->t_oe);
-       temp = max_t(u32, temp,
-                               gpmc_t->cs_on + dev_t->t_ce);
-       temp = max_t(u32, temp,
-                               gpmc_t->adv_on + dev_t->t_aa);
-       gpmc_t->access = gpmc_round_ps_to_ticks(temp);
-
-       gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
-       gpmc_t->cs_rd_off = gpmc_t->oe_off;
-
-       /* rd_cycle */
-       temp = max_t(u32, dev_t->t_rd_cycle,
-                       gpmc_t->cs_rd_off + dev_t->t_cez_r);
-       temp = max_t(u32, temp, gpmc_t->oe_off + dev_t->t_oez);
-       gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
-
-       return 0;
-}
-
-static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
-                                        struct gpmc_device_timings *dev_t,
-                                        bool mux)
-{
-       u32 temp;
-
-       /* adv_wr_off */
-       temp = dev_t->t_avdp_w;
-       if (mux)
-               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
-       gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
-
-       /* wr_data_mux_bus */
-       temp = dev_t->t_weasu;
-       if (mux) {
-               temp = max_t(u32, temp, gpmc_t->adv_wr_off + dev_t->t_aavdh);
-               temp = max_t(u32, temp, gpmc_t->adv_wr_off +
-                               gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
-       }
-       gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
-
-       /* we_on */
-       if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
-               gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
-       else
-               gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
-
-       /* we_off */
-       temp = gpmc_t->we_on + dev_t->t_wpl;
-       gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
-
-       gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
-                                                       dev_t->t_wph);
-
-       /* wr_cycle */
-       temp = max_t(u32, dev_t->t_wr_cycle,
-                               gpmc_t->cs_wr_off + dev_t->t_cez_w);
-       gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
-
-       return 0;
-}
-
-static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
-                       struct gpmc_device_timings *dev_t)
-{
-       u32 temp;
-
-       gpmc_t->sync_clk = gpmc_calc_divider(dev_t->clk) *
-                                               gpmc_get_fclk_period();
-
-       gpmc_t->page_burst_access = gpmc_round_ps_to_sync_clk(
-                                       dev_t->t_bacc,
-                                       gpmc_t->sync_clk);
-
-       temp = max_t(u32, dev_t->t_ces, dev_t->t_avds);
-       gpmc_t->clk_activation = gpmc_round_ps_to_ticks(temp);
-
-       if (gpmc_calc_divider(gpmc_t->sync_clk) != 1)
-               return 0;
-
-       if (dev_t->ce_xdelay)
-               gpmc_t->bool_timings.cs_extra_delay = true;
-       if (dev_t->avd_xdelay)
-               gpmc_t->bool_timings.adv_extra_delay = true;
-       if (dev_t->oe_xdelay)
-               gpmc_t->bool_timings.oe_extra_delay = true;
-       if (dev_t->we_xdelay)
-               gpmc_t->bool_timings.we_extra_delay = true;
-
-       return 0;
-}
-
-static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
-                                   struct gpmc_device_timings *dev_t,
-                                   bool sync)
-{
-       u32 temp;
-
-       /* cs_on */
-       gpmc_t->cs_on = gpmc_round_ps_to_ticks(dev_t->t_ceasu);
-
-       /* adv_on */
-       temp = dev_t->t_avdasu;
-       if (dev_t->t_ce_avd)
-               temp = max_t(u32, temp,
-                               gpmc_t->cs_on + dev_t->t_ce_avd);
-       gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
-
-       if (sync)
-               gpmc_calc_sync_common_timings(gpmc_t, dev_t);
-
-       return 0;
-}
-
-/* TODO: remove this function once all peripherals are confirmed to
- * work with generic timing. Simultaneously gpmc_cs_set_timings()
- * has to be modified to handle timings in ps instead of ns
-*/
-static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
-{
-       t->cs_on /= 1000;
-       t->cs_rd_off /= 1000;
-       t->cs_wr_off /= 1000;
-       t->adv_on /= 1000;
-       t->adv_rd_off /= 1000;
-       t->adv_wr_off /= 1000;
-       t->we_on /= 1000;
-       t->we_off /= 1000;
-       t->oe_on /= 1000;
-       t->oe_off /= 1000;
-       t->page_burst_access /= 1000;
-       t->access /= 1000;
-       t->rd_cycle /= 1000;
-       t->wr_cycle /= 1000;
-       t->bus_turnaround /= 1000;
-       t->cycle2cycle_delay /= 1000;
-       t->wait_monitoring /= 1000;
-       t->clk_activation /= 1000;
-       t->wr_access /= 1000;
-       t->wr_data_mux_bus /= 1000;
-}
-
-int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
-                     struct gpmc_settings *gpmc_s,
-                     struct gpmc_device_timings *dev_t)
-{
-       bool mux = false, sync = false;
-
-       if (gpmc_s) {
-               mux = gpmc_s->mux_add_data ? true : false;
-               sync = (gpmc_s->sync_read || gpmc_s->sync_write);
-       }
-
-       memset(gpmc_t, 0, sizeof(*gpmc_t));
-
-       gpmc_calc_common_timings(gpmc_t, dev_t, sync);
-
-       if (gpmc_s && gpmc_s->sync_read)
-               gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux);
-       else
-               gpmc_calc_async_read_timings(gpmc_t, dev_t, mux);
-
-       if (gpmc_s && gpmc_s->sync_write)
-               gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux);
-       else
-               gpmc_calc_async_write_timings(gpmc_t, dev_t, mux);
-
-       /* TODO: remove, see function definition */
-       gpmc_convert_ps_to_ns(gpmc_t);
-
-       return 0;
-}
-
-/**
- * gpmc_cs_program_settings - programs non-timing related settings
- * @cs:                GPMC chip-select to program
- * @p:         pointer to GPMC settings structure
- *
- * Programs non-timing related settings for a GPMC chip-select, such as
- * bus-width, burst configuration, etc. Function should be called once
- * for each chip-select that is being used and must be called before
- * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
- * register will be initialised to zero by this function. Returns 0 on
- * success and appropriate negative error code on failure.
- */
-int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
-{
-       u32 config1;
-
-       if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) {
-               pr_err("%s: invalid width %d!", __func__, p->device_width);
-               return -EINVAL;
-       }
-
-       /* Address-data multiplexing not supported for NAND devices */
-       if (p->device_nand && p->mux_add_data) {
-               pr_err("%s: invalid configuration!\n", __func__);
-               return -EINVAL;
-       }
-
-       if ((p->mux_add_data > GPMC_MUX_AD) ||
-           ((p->mux_add_data == GPMC_MUX_AAD) &&
-            !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
-               pr_err("%s: invalid multiplex configuration!\n", __func__);
-               return -EINVAL;
-       }
-
-       /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
-       if (p->burst_read || p->burst_write) {
-               switch (p->burst_len) {
-               case GPMC_BURST_4:
-               case GPMC_BURST_8:
-               case GPMC_BURST_16:
-                       break;
-               default:
-                       pr_err("%s: invalid page/burst-length (%d)\n",
-                              __func__, p->burst_len);
-                       return -EINVAL;
-               }
-       }
-
-       if (p->wait_pin > gpmc_nr_waitpins) {
-               pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
-               return -EINVAL;
-       }
-
-       config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
-
-       if (p->sync_read)
-               config1 |= GPMC_CONFIG1_READTYPE_SYNC;
-       if (p->sync_write)
-               config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
-       if (p->wait_on_read)
-               config1 |= GPMC_CONFIG1_WAIT_READ_MON;
-       if (p->wait_on_write)
-               config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
-       if (p->wait_on_read || p->wait_on_write)
-               config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
-       if (p->device_nand)
-               config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
-       if (p->mux_add_data)
-               config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
-       if (p->burst_read)
-               config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
-       if (p->burst_write)
-               config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
-       if (p->burst_read || p->burst_write) {
-               config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
-               config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
-       }
-
-       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
-
-       return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id gpmc_dt_ids[] = {
-       { .compatible = "ti,omap2420-gpmc" },
-       { .compatible = "ti,omap2430-gpmc" },
-       { .compatible = "ti,omap3430-gpmc" },   /* omap3430 & omap3630 */
-       { .compatible = "ti,omap4430-gpmc" },   /* omap4430 & omap4460 & omap543x */
-       { .compatible = "ti,am3352-gpmc" },     /* am335x devices */
-       { }
-};
-MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
-
-/**
- * gpmc_read_settings_dt - read gpmc settings from device-tree
- * @np:                pointer to device-tree node for a gpmc child device
- * @p:         pointer to gpmc settings structure
- *
- * Reads the GPMC settings for a GPMC child device from device-tree and
- * stores them in the GPMC settings structure passed. The GPMC settings
- * structure is initialised to zero by this function and so any
- * previously stored settings will be cleared.
- */
-void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
-{
-       memset(p, 0, sizeof(struct gpmc_settings));
-
-       p->sync_read = of_property_read_bool(np, "gpmc,sync-read");
-       p->sync_write = of_property_read_bool(np, "gpmc,sync-write");
-       of_property_read_u32(np, "gpmc,device-width", &p->device_width);
-       of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
-
-       if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
-               p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap");
-               p->burst_read = of_property_read_bool(np, "gpmc,burst-read");
-               p->burst_write = of_property_read_bool(np, "gpmc,burst-write");
-               if (!p->burst_read && !p->burst_write)
-                       pr_warn("%s: page/burst-length set but not used!\n",
-                               __func__);
-       }
-
-       if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
-               p->wait_on_read = of_property_read_bool(np,
-                                                       "gpmc,wait-on-read");
-               p->wait_on_write = of_property_read_bool(np,
-                                                        "gpmc,wait-on-write");
-               if (!p->wait_on_read && !p->wait_on_write)
-                       pr_debug("%s: rd/wr wait monitoring not enabled!\n",
-                                __func__);
-       }
-}
-
-static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
-                                               struct gpmc_timings *gpmc_t)
-{
-       struct gpmc_bool_timings *p;
-
-       if (!np || !gpmc_t)
-               return;
-
-       memset(gpmc_t, 0, sizeof(*gpmc_t));
-
-       /* minimum clock period for syncronous mode */
-       of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk);
-
-       /* chip select timtings */
-       of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on);
-       of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off);
-       of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off);
-
-       /* ADV signal timings */
-       of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on);
-       of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off);
-       of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off);
-
-       /* WE signal timings */
-       of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on);
-       of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off);
-
-       /* OE signal timings */
-       of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on);
-       of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off);
-
-       /* access and cycle timings */
-       of_property_read_u32(np, "gpmc,page-burst-access-ns",
-                            &gpmc_t->page_burst_access);
-       of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access);
-       of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle);
-       of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle);
-       of_property_read_u32(np, "gpmc,bus-turnaround-ns",
-                            &gpmc_t->bus_turnaround);
-       of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns",
-                            &gpmc_t->cycle2cycle_delay);
-       of_property_read_u32(np, "gpmc,wait-monitoring-ns",
-                            &gpmc_t->wait_monitoring);
-       of_property_read_u32(np, "gpmc,clk-activation-ns",
-                            &gpmc_t->clk_activation);
-
-       /* only applicable to OMAP3+ */
-       of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access);
-       of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns",
-                            &gpmc_t->wr_data_mux_bus);
-
-       /* bool timing parameters */
-       p = &gpmc_t->bool_timings;
-
-       p->cycle2cyclediffcsen =
-               of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen");
-       p->cycle2cyclesamecsen =
-               of_property_read_bool(np, "gpmc,cycle2cycle-samecsen");
-       p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay");
-       p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay");
-       p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay");
-       p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay");
-       p->time_para_granularity =
-               of_property_read_bool(np, "gpmc,time-para-granularity");
-}
-
-#if IS_ENABLED(CONFIG_MTD_NAND)
-
-static const char * const nand_xfer_types[] = {
-       [NAND_OMAP_PREFETCH_POLLED]             = "prefetch-polled",
-       [NAND_OMAP_POLLED]                      = "polled",
-       [NAND_OMAP_PREFETCH_DMA]                = "prefetch-dma",
-       [NAND_OMAP_PREFETCH_IRQ]                = "prefetch-irq",
-};
-
-static int gpmc_probe_nand_child(struct platform_device *pdev,
-                                struct device_node *child)
-{
-       u32 val;
-       const char *s;
-       struct gpmc_timings gpmc_t;
-       struct omap_nand_platform_data *gpmc_nand_data;
-
-       if (of_property_read_u32(child, "reg", &val) < 0) {
-               dev_err(&pdev->dev, "%s has no 'reg' property\n",
-                       child->full_name);
-               return -ENODEV;
-       }
-
-       gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
-                                     GFP_KERNEL);
-       if (!gpmc_nand_data)
-               return -ENOMEM;
-
-       gpmc_nand_data->cs = val;
-       gpmc_nand_data->of_node = child;
-
-       /* Detect availability of ELM module */
-       gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
-       if (gpmc_nand_data->elm_of_node == NULL)
-               gpmc_nand_data->elm_of_node =
-                                       of_parse_phandle(child, "elm_id", 0);
-       if (gpmc_nand_data->elm_of_node == NULL)
-               pr_warn("%s: ti,elm-id property not found\n", __func__);
-
-       /* select ecc-scheme for NAND */
-       if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
-               pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
-               return -ENODEV;
-       }
-
-       if (!strcmp(s, "sw"))
-               gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
-       else if (!strcmp(s, "ham1") ||
-                !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
-               gpmc_nand_data->ecc_opt =
-                               OMAP_ECC_HAM1_CODE_HW;
-       else if (!strcmp(s, "bch4"))
-               if (gpmc_nand_data->elm_of_node)
-                       gpmc_nand_data->ecc_opt =
-                               OMAP_ECC_BCH4_CODE_HW;
-               else
-                       gpmc_nand_data->ecc_opt =
-                               OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
-       else if (!strcmp(s, "bch8"))
-               if (gpmc_nand_data->elm_of_node)
-                       gpmc_nand_data->ecc_opt =
-                               OMAP_ECC_BCH8_CODE_HW;
-               else
-                       gpmc_nand_data->ecc_opt =
-                               OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
-       else if (!strcmp(s, "bch16"))
-               if (gpmc_nand_data->elm_of_node)
-                       gpmc_nand_data->ecc_opt =
-                               OMAP_ECC_BCH16_CODE_HW;
-               else
-                       pr_err("%s: BCH16 requires ELM support\n", __func__);
-       else
-               pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
-
-       /* select data transfer mode for NAND controller */
-       if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
-               for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
-                       if (!strcasecmp(s, nand_xfer_types[val])) {
-                               gpmc_nand_data->xfer_type = val;
-                               break;
-                       }
-
-       gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child);
-
-       val = of_get_nand_bus_width(child);
-       if (val == 16)
-               gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
-
-       gpmc_read_timings_dt(child, &gpmc_t);
-       gpmc_nand_init(gpmc_nand_data, &gpmc_t);
-
-       return 0;
-}
-#else
-static int gpmc_probe_nand_child(struct platform_device *pdev,
-                                struct device_node *child)
-{
-       return 0;
-}
-#endif
-
-#if IS_ENABLED(CONFIG_MTD_ONENAND)
-static int gpmc_probe_onenand_child(struct platform_device *pdev,
-                                struct device_node *child)
-{
-       u32 val;
-       struct omap_onenand_platform_data *gpmc_onenand_data;
-
-       if (of_property_read_u32(child, "reg", &val) < 0) {
-               dev_err(&pdev->dev, "%s has no 'reg' property\n",
-                       child->full_name);
-               return -ENODEV;
-       }
-
-       gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data),
-                                        GFP_KERNEL);
-       if (!gpmc_onenand_data)
-               return -ENOMEM;
-
-       gpmc_onenand_data->cs = val;
-       gpmc_onenand_data->of_node = child;
-       gpmc_onenand_data->dma_channel = -1;
-
-       if (!of_property_read_u32(child, "dma-channel", &val))
-               gpmc_onenand_data->dma_channel = val;
-
-       gpmc_onenand_init(gpmc_onenand_data);
-
-       return 0;
-}
-#else
-static int gpmc_probe_onenand_child(struct platform_device *pdev,
-                                   struct device_node *child)
-{
-       return 0;
-}
-#endif
-
-/**
- * gpmc_probe_generic_child - configures the gpmc for a child device
- * @pdev:      pointer to gpmc platform device
- * @child:     pointer to device-tree node for child device
- *
- * Allocates and configures a GPMC chip-select for a child device.
- * Returns 0 on success and appropriate negative error code on failure.
- */
-static int gpmc_probe_generic_child(struct platform_device *pdev,
-                               struct device_node *child)
-{
-       struct gpmc_settings gpmc_s;
-       struct gpmc_timings gpmc_t;
-       struct resource res;
-       unsigned long base;
-       int ret, cs;
-
-       if (of_property_read_u32(child, "reg", &cs) < 0) {
-               dev_err(&pdev->dev, "%s has no 'reg' property\n",
-                       child->full_name);
-               return -ENODEV;
-       }
-
-       if (of_address_to_resource(child, 0, &res) < 0) {
-               dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
-                       child->full_name);
-               return -ENODEV;
-       }
-
-       ret = gpmc_cs_request(cs, resource_size(&res), &base);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
-               return ret;
-       }
-
-       /*
-        * For some GPMC devices we still need to rely on the bootloader
-        * timings because the devices can be connected via FPGA. So far
-        * the list is smc91x on the omap2 SDP boards, and 8250 on zooms.
-        * REVISIT: Add timing support from slls644g.pdf and from the
-        * lan91c96 manual.
-        */
-       if (of_device_is_compatible(child, "ns16550a") ||
-           of_device_is_compatible(child, "smsc,lan91c94") ||
-           of_device_is_compatible(child, "smsc,lan91c111")) {
-               dev_warn(&pdev->dev,
-                        "%s using bootloader timings on CS%d\n",
-                        child->name, cs);
-               goto no_timings;
-       }
-
-       /*
-        * FIXME: gpmc_cs_request() will map the CS to an arbitary
-        * location in the gpmc address space. When booting with
-        * device-tree we want the NOR flash to be mapped to the
-        * location specified in the device-tree blob. So remap the
-        * CS to this location. Once DT migration is complete should
-        * just make gpmc_cs_request() map a specific address.
-        */
-       ret = gpmc_cs_remap(cs, res.start);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n",
-                       cs, &res.start);
-               goto err;
-       }
-
-       gpmc_read_settings_dt(child, &gpmc_s);
-
-       ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
-       if (ret < 0)
-               goto err;
-
-       ret = gpmc_cs_program_settings(cs, &gpmc_s);
-       if (ret < 0)
-               goto err;
-
-       gpmc_read_timings_dt(child, &gpmc_t);
-       gpmc_cs_set_timings(cs, &gpmc_t);
-
-no_timings:
-       if (of_platform_device_create(child, NULL, &pdev->dev))
-               return 0;
-
-       dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
-       ret = -ENODEV;
-
-err:
-       gpmc_cs_free(cs);
-
-       return ret;
-}
-
-static int gpmc_probe_dt(struct platform_device *pdev)
-{
-       int ret;
-       struct device_node *child;
-       const struct of_device_id *of_id =
-               of_match_device(gpmc_dt_ids, &pdev->dev);
-
-       if (!of_id)
-               return 0;
-
-       ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-cs",
-                                  &gpmc_cs_num);
-       if (ret < 0) {
-               pr_err("%s: number of chip-selects not defined\n", __func__);
-               return ret;
-       } else if (gpmc_cs_num < 1) {
-               pr_err("%s: all chip-selects are disabled\n", __func__);
-               return -EINVAL;
-       } else if (gpmc_cs_num > GPMC_CS_NUM) {
-               pr_err("%s: number of supported chip-selects cannot be > %d\n",
-                                        __func__, GPMC_CS_NUM);
-               return -EINVAL;
-       }
-
-       ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
-                                  &gpmc_nr_waitpins);
-       if (ret < 0) {
-               pr_err("%s: number of wait pins not found!\n", __func__);
-               return ret;
-       }
-
-       for_each_available_child_of_node(pdev->dev.of_node, child) {
-
-               if (!child->name)
-                       continue;
-
-               if (of_node_cmp(child->name, "nand") == 0)
-                       ret = gpmc_probe_nand_child(pdev, child);
-               else if (of_node_cmp(child->name, "onenand") == 0)
-                       ret = gpmc_probe_onenand_child(pdev, child);
-               else if (of_node_cmp(child->name, "ethernet") == 0 ||
-                        of_node_cmp(child->name, "nor") == 0 ||
-                        of_node_cmp(child->name, "uart") == 0)
-                       ret = gpmc_probe_generic_child(pdev, child);
-
-               if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
-                        __func__, child->full_name))
-                       of_node_put(child);
-       }
-
-       return 0;
-}
-#else
-static int gpmc_probe_dt(struct platform_device *pdev)
-{
-       return 0;
-}
-#endif
-
-static int gpmc_probe(struct platform_device *pdev)
-{
-       int rc;
-       u32 l;
-       struct resource *res;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL)
-               return -ENOENT;
-
-       phys_base = res->start;
-       mem_size = resource_size(res);
-
-       gpmc_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(gpmc_base))
-               return PTR_ERR(gpmc_base);
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (res == NULL)
-               dev_warn(&pdev->dev, "Failed to get resource: irq\n");
-       else
-               gpmc_irq = res->start;
-
-       gpmc_l3_clk = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(gpmc_l3_clk)) {
-               dev_err(&pdev->dev, "error: clk_get\n");
-               gpmc_irq = 0;
-               return PTR_ERR(gpmc_l3_clk);
-       }
-
-       pm_runtime_enable(&pdev->dev);
-       pm_runtime_get_sync(&pdev->dev);
-
-       gpmc_dev = &pdev->dev;
-
-       l = gpmc_read_reg(GPMC_REVISION);
-
-       /*
-        * FIXME: Once device-tree migration is complete the below flags
-        * should be populated based upon the device-tree compatible
-        * string. For now just use the IP revision. OMAP3+ devices have
-        * the wr_access and wr_data_mux_bus register fields. OMAP4+
-        * devices support the addr-addr-data multiplex protocol.
-        *
-        * GPMC IP revisions:
-        * - OMAP24xx                   = 2.0
-        * - OMAP3xxx                   = 5.0
-        * - OMAP44xx/54xx/AM335x       = 6.0
-        */
-       if (GPMC_REVISION_MAJOR(l) > 0x4)
-               gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
-       if (GPMC_REVISION_MAJOR(l) > 0x5)
-               gpmc_capability |= GPMC_HAS_MUX_AAD;
-       dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
-                GPMC_REVISION_MINOR(l));
-
-       gpmc_mem_init();
-
-       if (gpmc_setup_irq() < 0)
-               dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
-
-       /* Now the GPMC is initialised, unreserve the chip-selects */
-       gpmc_cs_map = 0;
-
-       if (!pdev->dev.of_node) {
-               gpmc_cs_num      = GPMC_CS_NUM;
-               gpmc_nr_waitpins = GPMC_NR_WAITPINS;
-       }
-
-       rc = gpmc_probe_dt(pdev);
-       if (rc < 0) {
-               pm_runtime_put_sync(&pdev->dev);
-               clk_put(gpmc_l3_clk);
-               dev_err(gpmc_dev, "failed to probe DT parameters\n");
-               return rc;
-       }
-
-       return 0;
-}
-
-static int gpmc_remove(struct platform_device *pdev)
-{
-       gpmc_free_irq();
-       gpmc_mem_exit();
-       pm_runtime_put_sync(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
-       gpmc_dev = NULL;
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int gpmc_suspend(struct device *dev)
-{
-       omap3_gpmc_save_context();
-       pm_runtime_put_sync(dev);
-       return 0;
-}
-
-static int gpmc_resume(struct device *dev)
-{
-       pm_runtime_get_sync(dev);
-       omap3_gpmc_restore_context();
-       return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(gpmc_pm_ops, gpmc_suspend, gpmc_resume);
-
-static struct platform_driver gpmc_driver = {
-       .probe          = gpmc_probe,
-       .remove         = gpmc_remove,
-       .driver         = {
-               .name   = DEVICE_NAME,
-               .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(gpmc_dt_ids),
-               .pm     = &gpmc_pm_ops,
-       },
-};
-
-static __init int gpmc_init(void)
-{
-       return platform_driver_register(&gpmc_driver);
-}
-
-static __exit void gpmc_exit(void)
-{
-       platform_driver_unregister(&gpmc_driver);
-
-}
-
-omap_postcore_initcall(gpmc_init);
-module_exit(gpmc_exit);
-
-static int __init omap_gpmc_init(void)
-{
-       struct omap_hwmod *oh;
-       struct platform_device *pdev;
-       char *oh_name = "gpmc";
-
-       /*
-        * if the board boots up with a populated DT, do not
-        * manually add the device from this initcall
-        */
-       if (of_have_populated_dt())
-               return -ENODEV;
-
-       oh = omap_hwmod_lookup(oh_name);
-       if (!oh) {
-               pr_err("Could not look up %s\n", oh_name);
-               return -ENODEV;
-       }
-
-       pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0);
-       WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
-
-       return PTR_RET(pdev);
-}
-omap_postcore_initcall(omap_gpmc_init);
-
-static irqreturn_t gpmc_handle_irq(int irq, void *dev)
-{
-       int i;
-       u32 regval;
-
-       regval = gpmc_read_reg(GPMC_IRQSTATUS);
-
-       if (!regval)
-               return IRQ_NONE;
-
-       for (i = 0; i < GPMC_NR_IRQ; i++)
-               if (regval & gpmc_client_irq[i].bitmask)
-                       generic_handle_irq(gpmc_client_irq[i].irq);
-
-       gpmc_write_reg(GPMC_IRQSTATUS, regval);
-
-       return IRQ_HANDLED;
-}
-
-static struct omap3_gpmc_regs gpmc_context;
-
-void omap3_gpmc_save_context(void)
-{
-       int i;
-
-       gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
-       gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE);
-       gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
-       gpmc_context.config = gpmc_read_reg(GPMC_CONFIG);
-       gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
-       gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
-       gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
-       for (i = 0; i < gpmc_cs_num; i++) {
-               gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
-               if (gpmc_context.cs_context[i].is_valid) {
-                       gpmc_context.cs_context[i].config1 =
-                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG1);
-                       gpmc_context.cs_context[i].config2 =
-                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG2);
-                       gpmc_context.cs_context[i].config3 =
-                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG3);
-                       gpmc_context.cs_context[i].config4 =
-                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG4);
-                       gpmc_context.cs_context[i].config5 =
-                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG5);
-                       gpmc_context.cs_context[i].config6 =
-                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG6);
-                       gpmc_context.cs_context[i].config7 =
-                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG7);
-               }
-       }
-}
-
-void omap3_gpmc_restore_context(void)
-{
-       int i;
-
-       gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig);
-       gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable);
-       gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl);
-       gpmc_write_reg(GPMC_CONFIG, gpmc_context.config);
-       gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
-       gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
-       gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
-       for (i = 0; i < gpmc_cs_num; i++) {
-               if (gpmc_context.cs_context[i].is_valid) {
-                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
-                               gpmc_context.cs_context[i].config1);
-                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG2,
-                               gpmc_context.cs_context[i].config2);
-                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG3,
-                               gpmc_context.cs_context[i].config3);
-                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG4,
-                               gpmc_context.cs_context[i].config4);
-                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG5,
-                               gpmc_context.cs_context[i].config5);
-                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG6,
-                               gpmc_context.cs_context[i].config6);
-                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG7,
-                               gpmc_context.cs_context[i].config7);
-               }
-       }
-}
index 707f6d58edd53d300a1b266cc229b3f9c1edd8f3..9caa41a6cb04e011621371d9b9fd58ea65a22319 100644 (file)
@@ -6,226 +6,9 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * Do not include this file in any new code, this will get removed
+ * once omap3 boots in device tree only mode.
+ *
  */
-
-#ifndef __OMAP2_GPMC_H
-#define __OMAP2_GPMC_H
-
-#include <linux/platform_data/mtd-nand-omap2.h>
-
-/* Maximum Number of Chip Selects */
-#define GPMC_CS_NUM            8
-
-#define GPMC_CS_CONFIG1                0x00
-#define GPMC_CS_CONFIG2                0x04
-#define GPMC_CS_CONFIG3                0x08
-#define GPMC_CS_CONFIG4                0x0c
-#define GPMC_CS_CONFIG5                0x10
-#define GPMC_CS_CONFIG6                0x14
-#define GPMC_CS_CONFIG7                0x18
-#define GPMC_CS_NAND_COMMAND   0x1c
-#define GPMC_CS_NAND_ADDRESS   0x20
-#define GPMC_CS_NAND_DATA      0x24
-
-/* Control Commands */
-#define GPMC_CONFIG_RDY_BSY    0x00000001
-#define GPMC_CONFIG_DEV_SIZE   0x00000002
-#define GPMC_CONFIG_DEV_TYPE   0x00000003
-#define GPMC_SET_IRQ_STATUS    0x00000004
-#define GPMC_CONFIG_WP         0x00000005
-
-#define GPMC_ENABLE_IRQ                0x0000000d
-
-/* ECC commands */
-#define GPMC_ECC_READ          0 /* Reset Hardware ECC for read */
-#define GPMC_ECC_WRITE         1 /* Reset Hardware ECC for write */
-#define GPMC_ECC_READSYN       2 /* Reset before syndrom is read back */
-
-#define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
-#define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
-#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
-#define GPMC_CONFIG1_READTYPE_SYNC      (1 << 29)
-#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28)
-#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
-#define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
-#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
-#define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
-#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_PIN_SEL(val)  ((val & 3) << 16)
-#define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
-#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(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_TIME_PARA_GRAN     (1 << 4)
-#define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
-#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
-#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
-#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
-#define GPMC_CONFIG7_CSVALID           (1 << 6)
-
-#define GPMC_DEVICETYPE_NOR            0
-#define GPMC_DEVICETYPE_NAND           2
-#define GPMC_CONFIG_WRITEPROTECT       0x00000010
-#define WR_RD_PIN_MONITORING           0x00600000
-#define GPMC_IRQ_FIFOEVENTENABLE       0x01
-#define GPMC_IRQ_COUNT_EVENT           0x02
-
-#define GPMC_BURST_4                   4       /* 4 word burst */
-#define GPMC_BURST_8                   8       /* 8 word burst */
-#define GPMC_BURST_16                  16      /* 16 word burst */
-#define GPMC_DEVWIDTH_8BIT             1       /* 8-bit device width */
-#define GPMC_DEVWIDTH_16BIT            2       /* 16-bit device width */
-#define GPMC_MUX_AAD                   1       /* Addr-Addr-Data multiplex */
-#define GPMC_MUX_AD                    2       /* Addr-Data multiplex */
-
-/* bool type time settings */
-struct gpmc_bool_timings {
-       bool cycle2cyclediffcsen;
-       bool cycle2cyclesamecsen;
-       bool we_extra_delay;
-       bool oe_extra_delay;
-       bool adv_extra_delay;
-       bool cs_extra_delay;
-       bool time_para_granularity;
-};
-
-/*
- * Note that all values in this struct are in nanoseconds except sync_clk
- * (which is in picoseconds), while the register values are in gpmc_fck cycles.
- */
-struct gpmc_timings {
-       /* Minimum clock period for synchronous mode (in picoseconds) */
-       u32 sync_clk;
-
-       /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
-       u32 cs_on;              /* Assertion time */
-       u32 cs_rd_off;          /* Read deassertion time */
-       u32 cs_wr_off;          /* Write deassertion time */
-
-       /* ADV signal timings corresponding to GPMC_CONFIG3 */
-       u32 adv_on;             /* Assertion time */
-       u32 adv_rd_off;         /* Read deassertion time */
-       u32 adv_wr_off;         /* Write deassertion time */
-
-       /* WE signals timings corresponding to GPMC_CONFIG4 */
-       u32 we_on;              /* WE assertion time */
-       u32 we_off;             /* WE deassertion time */
-
-       /* OE signals timings corresponding to GPMC_CONFIG4 */
-       u32 oe_on;              /* OE assertion time */
-       u32 oe_off;             /* OE deassertion time */
-
-       /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
-       u32 page_burst_access;  /* Multiple access word delay */
-       u32 access;             /* Start-cycle to first data valid delay */
-       u32 rd_cycle;           /* Total read cycle time */
-       u32 wr_cycle;           /* Total write cycle time */
-
-       u32 bus_turnaround;
-       u32 cycle2cycle_delay;
-
-       u32 wait_monitoring;
-       u32 clk_activation;
-
-       /* The following are only on OMAP3430 */
-       u32 wr_access;          /* WRACCESSTIME */
-       u32 wr_data_mux_bus;    /* WRDATAONADMUXBUS */
-
-       struct gpmc_bool_timings bool_timings;
-};
-
-/* Device timings in picoseconds */
-struct gpmc_device_timings {
-       u32 t_ceasu;    /* address setup to CS valid */
-       u32 t_avdasu;   /* address setup to ADV valid */
-       /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is
-        * of tusb using these timings even for sync whilst
-        * ideally for adv_rd/(wr)_off it should have considered
-        * t_avdh instead. This indirectly necessitates r/w
-        * variations of t_avdp as it is possible to have one
-        * sync & other async
-        */
-       u32 t_avdp_r;   /* ADV low time (what about t_cer ?) */
-       u32 t_avdp_w;
-       u32 t_aavdh;    /* address hold time */
-       u32 t_oeasu;    /* address setup to OE valid */
-       u32 t_aa;       /* access time from ADV assertion */
-       u32 t_iaa;      /* initial access time */
-       u32 t_oe;       /* access time from OE assertion */
-       u32 t_ce;       /* access time from CS asertion */
-       u32 t_rd_cycle; /* read cycle time */
-       u32 t_cez_r;    /* read CS deassertion to high Z */
-       u32 t_cez_w;    /* write CS deassertion to high Z */
-       u32 t_oez;      /* OE deassertion to high Z */
-       u32 t_weasu;    /* address setup to WE valid */
-       u32 t_wpl;      /* write assertion time */
-       u32 t_wph;      /* write deassertion time */
-       u32 t_wr_cycle; /* write cycle time */
-
-       u32 clk;
-       u32 t_bacc;     /* burst access valid clock to output delay */
-       u32 t_ces;      /* CS setup time to clk */
-       u32 t_avds;     /* ADV setup time to clk */
-       u32 t_avdh;     /* ADV hold time from clk */
-       u32 t_ach;      /* address hold time from clk */
-       u32 t_rdyo;     /* clk to ready valid */
-
-       u32 t_ce_rdyz;  /* XXX: description ?, or use t_cez instead */
-       u32 t_ce_avd;   /* CS on to ADV on delay */
-
-       /* XXX: check the possibility of combining
-        * cyc_aavhd_oe & cyc_aavdh_we
-        */
-       u8 cyc_aavdh_oe;/* read address hold time in cycles */
-       u8 cyc_aavdh_we;/* write address hold time in cycles */
-       u8 cyc_oe;      /* access time from OE assertion in cycles */
-       u8 cyc_wpl;     /* write deassertion time in cycles */
-       u32 cyc_iaa;    /* initial access time in cycles */
-
-       /* extra delays */
-       bool ce_xdelay;
-       bool avd_xdelay;
-       bool oe_xdelay;
-       bool we_xdelay;
-};
-
-struct gpmc_settings {
-       bool burst_wrap;        /* enables wrap bursting */
-       bool burst_read;        /* enables read page/burst mode */
-       bool burst_write;       /* enables write page/burst mode */
-       bool device_nand;       /* device is NAND */
-       bool sync_read;         /* enables synchronous reads */
-       bool sync_write;        /* enables synchronous writes */
-       bool wait_on_read;      /* monitor wait on reads */
-       bool wait_on_write;     /* monitor wait on writes */
-       u32 burst_len;          /* page/burst length */
-       u32 device_width;       /* device bus width (8 or 16 bit) */
-       u32 mux_add_data;       /* multiplex address & data */
-       u32 wait_pin;           /* wait-pin to be used */
-};
-
-extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
-                            struct gpmc_settings *gpmc_s,
-                            struct gpmc_device_timings *dev_t);
-
-extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
-extern int gpmc_get_client_irq(unsigned irq_config);
-
-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_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);
-extern void omap3_gpmc_save_context(void);
-extern void omap3_gpmc_restore_context(void);
-extern int gpmc_configure(int cmd, int wval);
-extern void gpmc_read_settings_dt(struct device_node *np,
-                                 struct gpmc_settings *p);
-
-#endif
+#include <linux/omap-gpmc.h>
index 07d4c7b357544b461e7979620d7f00de8968f734..dc6e79c4484abbfb097abb322298c37a8b9dd5ca 100644 (file)
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/mmc/host.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/hsmmc-omap.h>
 
 #include "soc.h"
 #include "omap_device.h"
 #include "omap-pm.h"
 
 #include "mux.h"
-#include "mmc.h"
 #include "hsmmc.h"
 #include "control.h"
 
@@ -32,25 +33,14 @@ static u16 control_devconf1_offset;
 
 #define HSMMC_NAME_LEN 9
 
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
-
-static int hsmmc_get_context_loss(struct device *dev)
-{
-       return omap_pm_get_dev_context_loss_count(dev);
-}
-
-#else
-#define hsmmc_get_context_loss NULL
-#endif
-
-static void omap_hsmmc1_before_set_reg(struct device *dev, int slot,
-                                 int power_on, int vdd)
+static void omap_hsmmc1_before_set_reg(struct device *dev,
+                                      int power_on, int vdd)
 {
        u32 reg, prog_io;
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_platform_data *mmc = dev->platform_data;
 
-       if (mmc->slots[0].remux)
-               mmc->slots[0].remux(dev, slot, power_on);
+       if (mmc->remux)
+               mmc->remux(dev, power_on);
 
        /*
         * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the
@@ -72,7 +62,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot,
                        omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1);
                }
 
-               if (mmc->slots[0].internal_clock) {
+               if (mmc->internal_clock) {
                        reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
                        reg |= OMAP2_MMCSDIO1ADPCLKISEL;
                        omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0);
@@ -96,8 +86,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot,
        }
 }
 
-static void omap_hsmmc1_after_set_reg(struct device *dev, int slot,
-                                int power_on, int vdd)
+static void omap_hsmmc1_after_set_reg(struct device *dev, int power_on, int vdd)
 {
        u32 reg;
 
@@ -120,34 +109,32 @@ static void omap_hsmmc1_after_set_reg(struct device *dev, int slot,
        }
 }
 
-static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc)
+static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc)
 {
        u32 reg;
 
        reg = omap_ctrl_readl(control_devconf1_offset);
-       if (mmc->slots[0].internal_clock)
+       if (mmc->internal_clock)
                reg |= OMAP2_MMCSDIO2ADPCLKISEL;
        else
                reg &= ~OMAP2_MMCSDIO2ADPCLKISEL;
        omap_ctrl_writel(reg, control_devconf1_offset);
 }
 
-static void hsmmc2_before_set_reg(struct device *dev, int slot,
-                                  int power_on, int vdd)
+static void hsmmc2_before_set_reg(struct device *dev, int power_on, int vdd)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_platform_data *mmc = dev->platform_data;
 
-       if (mmc->slots[0].remux)
-               mmc->slots[0].remux(dev, slot, power_on);
+       if (mmc->remux)
+               mmc->remux(dev, power_on);
 
        if (power_on)
                hsmmc2_select_input_clk_src(mmc);
 }
 
-static int am35x_hsmmc2_set_power(struct device *dev, int slot,
-                                 int power_on, int vdd)
+static int am35x_hsmmc2_set_power(struct device *dev, int power_on, int vdd)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_platform_data *mmc = dev->platform_data;
 
        if (power_on)
                hsmmc2_select_input_clk_src(mmc);
@@ -155,23 +142,22 @@ static int am35x_hsmmc2_set_power(struct device *dev, int slot,
        return 0;
 }
 
-static int nop_mmc_set_power(struct device *dev, int slot, int power_on,
-                                                       int vdd)
+static int nop_mmc_set_power(struct device *dev, int power_on, int vdd)
 {
        return 0;
 }
 
-static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
-                       int controller_nr)
+static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data
+                                 *mmc_controller, int controller_nr)
 {
-       if (gpio_is_valid(mmc_controller->slots[0].switch_pin) &&
-               (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
-               omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
-                                       OMAP_PIN_INPUT_PULLUP);
-       if (gpio_is_valid(mmc_controller->slots[0].gpio_wp) &&
-               (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
-               omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
-                                       OMAP_PIN_INPUT_PULLUP);
+       if (gpio_is_valid(mmc_controller->switch_pin) &&
+           (mmc_controller->switch_pin < OMAP_MAX_GPIO_LINES))
+               omap_mux_init_gpio(mmc_controller->switch_pin,
+                                  OMAP_PIN_INPUT_PULLUP);
+       if (gpio_is_valid(mmc_controller->gpio_wp) &&
+           (mmc_controller->gpio_wp < OMAP_MAX_GPIO_LINES))
+               omap_mux_init_gpio(mmc_controller->gpio_wp,
+                                  OMAP_PIN_INPUT_PULLUP);
        if (cpu_is_omap34xx()) {
                if (controller_nr == 0) {
                        omap_mux_init_signal("sdmmc1_clk",
@@ -180,7 +166,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                OMAP_PIN_INPUT_PULLUP);
                        omap_mux_init_signal("sdmmc1_dat0",
                                OMAP_PIN_INPUT_PULLUP);
-                       if (mmc_controller->slots[0].caps &
+                       if (mmc_controller->caps &
                                (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
                                omap_mux_init_signal("sdmmc1_dat1",
                                        OMAP_PIN_INPUT_PULLUP);
@@ -189,7 +175,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                omap_mux_init_signal("sdmmc1_dat3",
                                        OMAP_PIN_INPUT_PULLUP);
                        }
-                       if (mmc_controller->slots[0].caps &
+                       if (mmc_controller->caps &
                                                MMC_CAP_8_BIT_DATA) {
                                omap_mux_init_signal("sdmmc1_dat4",
                                        OMAP_PIN_INPUT_PULLUP);
@@ -214,7 +200,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
                         * For 8 wire configurations, Lines DAT4, 5, 6 and 7
                         * need to be muxed in the board-*.c files
                         */
-                       if (mmc_controller->slots[0].caps &
+                       if (mmc_controller->caps &
                                (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
                                omap_mux_init_signal("sdmmc2_dat1",
                                        OMAP_PIN_INPUT_PULLUP);
@@ -223,7 +209,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                omap_mux_init_signal("sdmmc2_dat3",
                                        OMAP_PIN_INPUT_PULLUP);
                        }
-                       if (mmc_controller->slots[0].caps &
+                       if (mmc_controller->caps &
                                                        MMC_CAP_8_BIT_DATA) {
                                omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
                                        OMAP_PIN_INPUT_PULLUP);
@@ -243,7 +229,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
 }
 
 static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
-                                       struct omap_mmc_platform_data *mmc)
+                                       struct omap_hsmmc_platform_data *mmc)
 {
        char *hc_name;
 
@@ -259,38 +245,22 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
        else
                snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i",
                                                                c->mmc, 1);
-       mmc->slots[0].name = hc_name;
-       mmc->nr_slots = 1;
-       mmc->slots[0].caps = c->caps;
-       mmc->slots[0].pm_caps = c->pm_caps;
-       mmc->slots[0].internal_clock = !c->ext_clock;
-       mmc->max_freq = c->max_freq;
+       mmc->name = hc_name;
+       mmc->caps = c->caps;
+       mmc->internal_clock = !c->ext_clock;
        mmc->reg_offset = 0;
-       mmc->get_context_loss_count = hsmmc_get_context_loss;
 
-       mmc->slots[0].switch_pin = c->gpio_cd;
-       mmc->slots[0].gpio_wp = c->gpio_wp;
+       mmc->switch_pin = c->gpio_cd;
+       mmc->gpio_wp = c->gpio_wp;
 
-       mmc->slots[0].remux = c->remux;
-       mmc->slots[0].init_card = c->init_card;
+       mmc->remux = c->remux;
+       mmc->init_card = c->init_card;
 
        if (c->cover_only)
-               mmc->slots[0].cover = 1;
+               mmc->cover = 1;
 
        if (c->nonremovable)
-               mmc->slots[0].nonremovable = 1;
-
-       if (c->power_saving)
-               mmc->slots[0].power_saving = 1;
-
-       if (c->no_off)
-               mmc->slots[0].no_off = 1;
-
-       if (c->no_off_init)
-               mmc->slots[0].no_regulator_off_init = c->no_off_init;
-
-       if (c->vcc_aux_disable_is_sleep)
-               mmc->slots[0].vcc_aux_disable_is_sleep = 1;
+               mmc->nonremovable = 1;
 
        /*
         * NOTE:  MMC slots should have a Vcc regulator set up.
@@ -300,42 +270,42 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
         * temporary HACK: ocr_mask instead of fixed supply
         */
        if (soc_is_am35xx())
-               mmc->slots[0].ocr_mask = MMC_VDD_165_195 |
+               mmc->ocr_mask = MMC_VDD_165_195 |
                                         MMC_VDD_26_27 |
                                         MMC_VDD_27_28 |
                                         MMC_VDD_29_30 |
                                         MMC_VDD_30_31 |
                                         MMC_VDD_31_32;
        else
-               mmc->slots[0].ocr_mask = c->ocr_mask;
+               mmc->ocr_mask = c->ocr_mask;
 
        if (!soc_is_am35xx())
-               mmc->slots[0].features |= HSMMC_HAS_PBIAS;
+               mmc->features |= HSMMC_HAS_PBIAS;
 
        switch (c->mmc) {
        case 1:
-               if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
+               if (mmc->features & HSMMC_HAS_PBIAS) {
                        /* on-chip level shifting via PBIAS0/PBIAS1 */
-                       mmc->slots[0].before_set_reg =
+                       mmc->before_set_reg =
                                        omap_hsmmc1_before_set_reg;
-                       mmc->slots[0].after_set_reg =
+                       mmc->after_set_reg =
                                        omap_hsmmc1_after_set_reg;
                }
 
                if (soc_is_am35xx())
-                       mmc->slots[0].set_power = nop_mmc_set_power;
+                       mmc->set_power = nop_mmc_set_power;
 
                /* OMAP3630 HSMMC1 supports only 4-bit */
                if (cpu_is_omap3630() &&
                                (c->caps & MMC_CAP_8_BIT_DATA)) {
                        c->caps &= ~MMC_CAP_8_BIT_DATA;
                        c->caps |= MMC_CAP_4_BIT_DATA;
-                       mmc->slots[0].caps = c->caps;
+                       mmc->caps = c->caps;
                }
                break;
        case 2:
                if (soc_is_am35xx())
-                       mmc->slots[0].set_power = am35x_hsmmc2_set_power;
+                       mmc->set_power = am35x_hsmmc2_set_power;
 
                if (c->ext_clock)
                        c->transceiver = 1;
@@ -343,17 +313,17 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
                        c->caps &= ~MMC_CAP_8_BIT_DATA;
                        c->caps |= MMC_CAP_4_BIT_DATA;
                }
-               if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
+               if (mmc->features & HSMMC_HAS_PBIAS) {
                        /* off-chip level shifting, or none */
-                       mmc->slots[0].before_set_reg = hsmmc2_before_set_reg;
-                       mmc->slots[0].after_set_reg = NULL;
+                       mmc->before_set_reg = hsmmc2_before_set_reg;
+                       mmc->after_set_reg = NULL;
                }
                break;
        case 3:
        case 4:
        case 5:
-               mmc->slots[0].before_set_reg = NULL;
-               mmc->slots[0].after_set_reg = NULL;
+               mmc->before_set_reg = NULL;
+               mmc->after_set_reg = NULL;
                break;
        default:
                pr_err("MMC%d configuration not supported!\n", c->mmc);
@@ -368,7 +338,7 @@ static int omap_hsmmc_done;
 void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
 {
        struct platform_device *pdev;
-       struct omap_mmc_platform_data *mmc_pdata;
+       struct omap_hsmmc_platform_data *mmc_pdata;
        int res;
 
        if (omap_hsmmc_done != 1)
@@ -388,8 +358,8 @@ void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
                if (!mmc_pdata)
                        continue;
 
-               mmc_pdata->slots[0].switch_pin = c->gpio_cd;
-               mmc_pdata->slots[0].gpio_wp = c->gpio_wp;
+               mmc_pdata->switch_pin = c->gpio_cd;
+               mmc_pdata->gpio_wp = c->gpio_wp;
 
                res = omap_device_register(pdev);
                if (res)
@@ -408,12 +378,12 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
        struct omap_device *od;
        struct platform_device *pdev;
        char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
-       struct omap_mmc_platform_data *mmc_data;
-       struct omap_mmc_dev_attr *mmc_dev_attr;
+       struct omap_hsmmc_platform_data *mmc_data;
+       struct omap_hsmmc_dev_attr *mmc_dev_attr;
        char *name;
        int res;
 
-       mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
+       mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL);
        if (!mmc_data) {
                pr_err("Cannot allocate memory for mmc device!\n");
                return;
@@ -463,7 +433,7 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo,
        }
 
        res = platform_device_add_data(pdev, mmc_data,
-                             sizeof(struct omap_mmc_platform_data));
+                             sizeof(struct omap_hsmmc_platform_data));
        if (res) {
                pr_err("Could not add pdata for %s\n", name);
                goto put_pdev;
@@ -489,7 +459,7 @@ put_pdev:
        platform_device_put(pdev);
 
 free_name:
-       kfree(mmc_data->slots[0].name);
+       kfree(mmc_data->name);
 
 free_mmc:
        kfree(mmc_data);
index 7f2e790e0929a9a23a13015c32cc119b81593c2d..148cd9b15499a4b11a5eef326c183168c3e82457 100644 (file)
@@ -12,25 +12,18 @@ struct omap2_hsmmc_info {
        u8      mmc;            /* controller 1/2/3 */
        u32     caps;           /* 4/8 wires and any additional host
                                 * capabilities OR'd (ref. linux/mmc/host.h) */
-       u32     pm_caps;        /* PM capabilities */
        bool    transceiver;    /* MMC-2 option */
        bool    ext_clock;      /* use external pin for input clock */
        bool    cover_only;     /* No card detect - just cover switch */
        bool    nonremovable;   /* Nonremovable e.g. eMMC */
-       bool    power_saving;   /* Try to sleep or power off when possible */
-       bool    no_off;         /* power_saving and power is not to go off */
-       bool    no_off_init;    /* no power off when not in MMC sleep state */
-       bool    vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */
        bool    deferred;       /* mmc needs a deferred probe */
        int     gpio_cd;        /* or -EINVAL */
        int     gpio_wp;        /* or -EINVAL */
        char    *name;          /* or NULL for default */
        struct platform_device *pdev;   /* mmc controller instance */
        int     ocr_mask;       /* temporary HACK */
-       int     max_freq;       /* maximum clock, if constrained by external
-                                * circuitry, or 0 for default */
        /* Remux (pad configuration) when powering on/off */
-       void (*remux)(struct device *dev, int slot, int power_on);
+       void (*remux)(struct device *dev, int power_on);
        /* init some special card */
        void (*init_card)(struct mmc_card *card);
 };
index 03cbb16898a3f0eeef87144ea70f5b8d96849650..4fc838354e313cf7ce2ac828746c0031e9102ef0 100644 (file)
 #include "sram.h"
 #include "cm2xxx.h"
 #include "cm3xxx.h"
+#include "cm33xx.h"
+#include "cm44xx.h"
 #include "prm.h"
 #include "cm.h"
 #include "prcm_mpu44xx.h"
 #include "prminst44xx.h"
-#include "cminst44xx.h"
 #include "prm2xxx.h"
 #include "prm3xxx.h"
+#include "prm33xx.h"
 #include "prm44xx.h"
 #include "opp2xxx.h"
 
@@ -565,6 +567,8 @@ void __init am33xx_init_early(void)
        omap2_set_globals_cm(AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE), NULL);
        omap3xxx_check_revision();
        am33xx_check_features();
+       am33xx_prm_init();
+       am33xx_cm_init();
        am33xx_powerdomains_init();
        am33xx_clockdomains_init();
        am33xx_hwmod_init();
@@ -591,6 +595,8 @@ void __init am43xx_init_early(void)
        omap_cm_base_init();
        omap3xxx_check_revision();
        am33xx_check_features();
+       omap44xx_prm_init();
+       omap4_cm_init();
        am43xx_powerdomains_init();
        am43xx_clockdomains_init();
        am43xx_hwmod_init();
@@ -620,6 +626,7 @@ void __init omap4430_init_early(void)
        omap_cm_base_init();
        omap4xxx_check_revision();
        omap4xxx_check_features();
+       omap4_cm_init();
        omap4_pm_init_early();
        omap44xx_prm_init();
        omap44xx_voltagedomains_init();
@@ -655,6 +662,7 @@ void __init omap5_init_early(void)
        omap_cm_base_init();
        omap44xx_prm_init();
        omap5xxx_check_revision();
+       omap4_cm_init();
        omap54xx_voltagedomains_init();
        omap54xx_powerdomains_init();
        omap54xx_clockdomains_init();
@@ -686,6 +694,7 @@ void __init dra7xx_init_early(void)
        omap_cm_base_init();
        omap44xx_prm_init();
        dra7xxx_check_revision();
+       omap4_cm_init();
        dra7xx_powerdomains_init();
        dra7xx_clockdomains_init();
        dra7xx_hwmod_init();
index 0cd4b089da9c5724484500ac2889b71207a21a14..30d39b97e7dd3fdefe1f9e1d6064a275d97c9ec1 100644 (file)
@@ -1,5 +1,3 @@
-#include <linux/mmc/host.h>
-#include <linux/platform_data/mmc-omap.h>
 
 #define OMAP24XX_NR_MMC                2
 #define OMAP2420_MMC_SIZE      OMAP1_MMC_SIZE
@@ -7,14 +5,6 @@
 
 #define OMAP4_MMC_REG_OFFSET   0x100
 
-#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
-void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data);
-#else
-static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
-{
-}
-#endif
-
 struct omap_hwmod;
 int omap_msdi_reset(struct omap_hwmod *oh);
 
index 6944ae3674e85d624d9bba85808125c3c56a0dfb..79f49d904a06f208ae5567c7a2992ce5264f5cc0 100644 (file)
@@ -227,7 +227,7 @@ static void __init save_l2x0_context(void)
 int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 {
        struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
-       unsigned int save_state = 0;
+       unsigned int save_state = 0, cpu_logic_state = PWRDM_POWER_RET;
        unsigned int wakeup_cpu;
 
        if (omap_rev() == OMAP4430_REV_ES1_0)
@@ -239,6 +239,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
                save_state = 0;
                break;
        case PWRDM_POWER_OFF:
+               cpu_logic_state = PWRDM_POWER_OFF;
                save_state = 1;
                break;
        case PWRDM_POWER_RET:
@@ -270,6 +271,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 
        cpu_clear_prev_logic_pwrst(cpu);
        pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
+       pwrdm_set_logic_retst(pm_info->pwrdm, cpu_logic_state);
        set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.resume));
        omap_pm_ops.scu_prepare(cpu, power_state);
        l2x0_pwrst_prepare(cpu, save_state);
index 68423e26399d9ae8e618d506cdbb3c21cbbf0014..d937b2e4040be2dcb45a70ff0ca1e591c0b4c3bc 100644 (file)
@@ -15,7 +15,7 @@
 
 #include "soc.h"
 #include "common.h"
-#include "prm2xxx.h"
+#include "prm.h"
 
 /*
  * reset_virt_prcm_set_ck, reset_sys_ck: pointers to the virt_prcm_set
@@ -40,8 +40,7 @@ void omap2xxx_restart(enum reboot_mode mode, const char *cmd)
 
        /* XXX Should save the cmd argument for use after the reboot */
 
-       omap2xxx_prm_dpll_reset(); /* never returns */
-       while (1);
+       omap_prm_reset_system();
 }
 
 /**
index 5de2a0c2979d228d1da969cceeb986d2bd14ddb4..103a49f68bcb34ee60fc03ed94299df9bc2037d7 100644 (file)
 #include <linux/init.h>
 #include <linux/reboot.h>
 
-#include "iomap.h"
-#include "common.h"
 #include "control.h"
-#include "prm3xxx.h"
+#include "prm.h"
 
 /* Global address base setup code */
 
@@ -32,6 +30,5 @@
 void omap3xxx_restart(enum reboot_mode mode, const char *cmd)
 {
        omap3_ctrl_write_boot_mode((cmd ? (u8)*cmd : 0));
-       omap3xxx_prm_dpll3_reset(); /* never returns */
-       while (1);
+       omap_prm_reset_system();
 }
index 16b20cedc38dd434c085de0e8963eb80e74916d2..b7cb44abe49b35a7a03c3c9f172eca5daeb7b4a7 100644 (file)
@@ -36,7 +36,6 @@
 #include "soc.h"
 #include "iomap.h"
 #include "common.h"
-#include "mmc.h"
 #include "prminst44xx.h"
 #include "prcm_mpu44xx.h"
 #include "omap4-sar-layout.h"
index 41dfd7da8170952abe0f97a4295f21c97f9dfde6..a99e7f7fb5bec2a44920d3c34c5ea327a08f57f1 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/reboot.h>
-#include "prminst44xx.h"
+#include "prm.h"
 
 /**
  * omap44xx_restart - trigger a software restart of the SoC
@@ -22,7 +22,5 @@
 void omap44xx_restart(enum reboot_mode mode, const char *cmd)
 {
        /* XXX Should save 'cmd' into scratchpad for use after reboot */
-       omap4_prminst_global_warm_sw_reset(); /* never returns */
-       while (1)
-               ;
+       omap_prm_reset_system();
 }
index d22c30d3ccfa0809d2662cbd5390c20f40b24a55..8c58b71c2727cbf544582f9b3f6cd4fc00984035 100644 (file)
@@ -917,6 +917,10 @@ static int __init omap_device_late_idle(struct device *dev, void *data)
 static int __init omap_device_late_init(void)
 {
        bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
+
+       WARN(!of_have_populated_dt(),
+               "legacy booting deprecated, please update to boot with .dts\n");
+
        return 0;
 }
 omap_late_initcall_sync(omap_device_late_init);
index 716247ed9e0c3a9b419f84332b97ee83aab28371..cbb908dc5cf0e09bec45ce7fbf7814936883d9fc 100644 (file)
 #include "powerdomain.h"
 #include "cm2xxx.h"
 #include "cm3xxx.h"
-#include "cminst44xx.h"
 #include "cm33xx.h"
 #include "prm.h"
 #include "prm3xxx.h"
@@ -979,31 +978,9 @@ static void _omap4_enable_module(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: %s: %d\n",
                 oh->name, __func__, oh->prcm.omap4.modulemode);
 
-       omap4_cminst_module_enable(oh->prcm.omap4.modulemode,
-                                  oh->clkdm->prcm_partition,
-                                  oh->clkdm->cm_inst,
-                                  oh->clkdm->clkdm_offs,
-                                  oh->prcm.omap4.clkctrl_offs);
-}
-
-/**
- * _am33xx_enable_module - enable CLKCTRL modulemode on AM33XX
- * @oh: struct omap_hwmod *
- *
- * Enables the PRCM module mode related to the hwmod @oh.
- * No return value.
- */
-static void _am33xx_enable_module(struct omap_hwmod *oh)
-{
-       if (!oh->clkdm || !oh->prcm.omap4.modulemode)
-               return;
-
-       pr_debug("omap_hwmod: %s: %s: %d\n",
-                oh->name, __func__, oh->prcm.omap4.modulemode);
-
-       am33xx_cm_module_enable(oh->prcm.omap4.modulemode, oh->clkdm->cm_inst,
-                               oh->clkdm->clkdm_offs,
-                               oh->prcm.omap4.clkctrl_offs);
+       omap_cm_module_enable(oh->prcm.omap4.modulemode,
+                             oh->clkdm->prcm_partition,
+                             oh->clkdm->cm_inst, oh->prcm.omap4.clkctrl_offs);
 }
 
 /**
@@ -1026,35 +1003,9 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh)
        if (oh->flags & HWMOD_NO_IDLEST)
                return 0;
 
-       return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
-                                            oh->clkdm->cm_inst,
-                                            oh->clkdm->clkdm_offs,
-                                            oh->prcm.omap4.clkctrl_offs);
-}
-
-/**
- * _am33xx_wait_target_disable - wait for a module to be disabled on AM33XX
- * @oh: struct omap_hwmod *
- *
- * Wait for a module @oh to enter slave idle.  Returns 0 if the module
- * does not have an IDLEST bit or if the module successfully enters
- * slave idle; otherwise, pass along the return value of the
- * appropriate *_cm*_wait_module_idle() function.
- */
-static int _am33xx_wait_target_disable(struct omap_hwmod *oh)
-{
-       if (!oh)
-               return -EINVAL;
-
-       if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
-               return 0;
-
-       if (oh->flags & HWMOD_NO_IDLEST)
-               return 0;
-
-       return am33xx_cm_wait_module_idle(oh->clkdm->cm_inst,
-                                            oh->clkdm->clkdm_offs,
-                                            oh->prcm.omap4.clkctrl_offs);
+       return omap_cm_wait_module_idle(oh->clkdm->prcm_partition,
+                                       oh->clkdm->cm_inst,
+                                       oh->prcm.omap4.clkctrl_offs, 0);
 }
 
 /**
@@ -1859,10 +1810,8 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
 
        pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
 
-       omap4_cminst_module_disable(oh->clkdm->prcm_partition,
-                                   oh->clkdm->cm_inst,
-                                   oh->clkdm->clkdm_offs,
-                                   oh->prcm.omap4.clkctrl_offs);
+       omap_cm_module_disable(oh->clkdm->prcm_partition, oh->clkdm->cm_inst,
+                              oh->prcm.omap4.clkctrl_offs);
 
        v = _omap4_wait_target_disable(oh);
        if (v)
@@ -1872,36 +1821,6 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
        return 0;
 }
 
-/**
- * _am33xx_disable_module - enable CLKCTRL modulemode on AM33XX
- * @oh: struct omap_hwmod *
- *
- * Disable the PRCM module mode related to the hwmod @oh.
- * Return EINVAL if the modulemode is not supported and 0 in case of success.
- */
-static int _am33xx_disable_module(struct omap_hwmod *oh)
-{
-       int v;
-
-       if (!oh->clkdm || !oh->prcm.omap4.modulemode)
-               return -EINVAL;
-
-       pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
-
-       if (_are_any_hardreset_lines_asserted(oh))
-               return 0;
-
-       am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs,
-                                oh->prcm.omap4.clkctrl_offs);
-
-       v = _am33xx_wait_target_disable(oh);
-       if (v)
-               pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
-                       oh->name);
-
-       return 0;
-}
-
 /**
  * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
  * @oh: struct omap_hwmod *
@@ -2065,10 +1984,7 @@ static void _reconfigure_io_chain(void)
 
        spin_lock_irqsave(&io_chain_lock, flags);
 
-       if (cpu_is_omap34xx())
-               omap3xxx_prm_reconfigure_io_chain();
-       else if (cpu_is_omap44xx())
-               omap44xx_prm_reconfigure_io_chain();
+       omap_prm_reconfigure_io_chain();
 
        spin_unlock_irqrestore(&io_chain_lock, flags);
 }
@@ -2719,11 +2635,33 @@ static int __init _setup(struct omap_hwmod *oh, void *data)
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return 0;
 
+       if (oh->parent_hwmod) {
+               int r;
+
+               r = _enable(oh->parent_hwmod);
+               WARN(r, "hwmod: %s: setup: failed to enable parent hwmod %s\n",
+                    oh->name, oh->parent_hwmod->name);
+       }
+
        _setup_iclk_autoidle(oh);
 
        if (!_setup_reset(oh))
                _setup_postsetup(oh);
 
+       if (oh->parent_hwmod) {
+               u8 postsetup_state;
+
+               postsetup_state = oh->parent_hwmod->_postsetup_state;
+
+               if (postsetup_state == _HWMOD_STATE_IDLE)
+                       _idle(oh->parent_hwmod);
+               else if (postsetup_state == _HWMOD_STATE_DISABLED)
+                       _shutdown(oh->parent_hwmod);
+               else if (postsetup_state != _HWMOD_STATE_ENABLED)
+                       WARN(1, "hwmod: %s: unknown postsetup state %d! defaulting to enabled\n",
+                            oh->parent_hwmod->name, postsetup_state);
+       }
+
        return 0;
 }
 
@@ -2832,12 +2770,10 @@ static int __init _add_link(struct omap_hwmod_ocp_if *oi)
        _alloc_links(&ml, &sl);
 
        ml->ocp_if = oi;
-       INIT_LIST_HEAD(&ml->node);
        list_add(&ml->node, &oi->master->master_ports);
        oi->master->masters_cnt++;
 
        sl->ocp_if = oi;
-       INIT_LIST_HEAD(&sl->node);
        list_add(&sl->node, &oi->slave->slave_ports);
        oi->slave->slaves_cnt++;
 
@@ -2927,34 +2863,7 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
 /* Static functions intended only for use in soc_ops field function pointers */
 
 /**
- * _omap2xxx_wait_target_ready - wait for a module to leave slave idle
- * @oh: struct omap_hwmod *
- *
- * Wait for a module @oh to leave slave idle.  Returns 0 if the module
- * does not have an IDLEST bit or if the module successfully leaves
- * slave idle; otherwise, pass along the return value of the
- * appropriate *_cm*_wait_module_ready() function.
- */
-static int _omap2xxx_wait_target_ready(struct omap_hwmod *oh)
-{
-       if (!oh)
-               return -EINVAL;
-
-       if (oh->flags & HWMOD_NO_IDLEST)
-               return 0;
-
-       if (!_find_mpu_rt_port(oh))
-               return 0;
-
-       /* XXX check module SIDLEMODE, hardreset status, enabled clocks */
-
-       return omap2xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs,
-                                            oh->prcm.omap2.idlest_reg_id,
-                                            oh->prcm.omap2.idlest_idle_bit);
-}
-
-/**
- * _omap3xxx_wait_target_ready - wait for a module to leave slave idle
+ * _omap2xxx_3xxx_wait_target_ready - wait for a module to leave slave idle
  * @oh: struct omap_hwmod *
  *
  * Wait for a module @oh to leave slave idle.  Returns 0 if the module
@@ -2962,7 +2871,7 @@ static int _omap2xxx_wait_target_ready(struct omap_hwmod *oh)
  * slave idle; otherwise, pass along the return value of the
  * appropriate *_cm*_wait_module_ready() function.
  */
-static int _omap3xxx_wait_target_ready(struct omap_hwmod *oh)
+static int _omap2xxx_3xxx_wait_target_ready(struct omap_hwmod *oh)
 {
        if (!oh)
                return -EINVAL;
@@ -2975,9 +2884,9 @@ static int _omap3xxx_wait_target_ready(struct omap_hwmod *oh)
 
        /* XXX check module SIDLEMODE, hardreset status, enabled clocks */
 
-       return omap3xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs,
-                                            oh->prcm.omap2.idlest_reg_id,
-                                            oh->prcm.omap2.idlest_idle_bit);
+       return omap_cm_wait_module_ready(0, oh->prcm.omap2.module_offs,
+                                        oh->prcm.omap2.idlest_reg_id,
+                                        oh->prcm.omap2.idlest_idle_bit);
 }
 
 /**
@@ -3002,37 +2911,9 @@ static int _omap4_wait_target_ready(struct omap_hwmod *oh)
 
        /* XXX check module SIDLEMODE, hardreset status */
 
-       return omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition,
-                                             oh->clkdm->cm_inst,
-                                             oh->clkdm->clkdm_offs,
-                                             oh->prcm.omap4.clkctrl_offs);
-}
-
-/**
- * _am33xx_wait_target_ready - wait for a module to leave slave idle
- * @oh: struct omap_hwmod *
- *
- * Wait for a module @oh to leave slave idle.  Returns 0 if the module
- * does not have an IDLEST bit or if the module successfully leaves
- * slave idle; otherwise, pass along the return value of the
- * appropriate *_cm*_wait_module_ready() function.
- */
-static int _am33xx_wait_target_ready(struct omap_hwmod *oh)
-{
-       if (!oh || !oh->clkdm)
-               return -EINVAL;
-
-       if (oh->flags & HWMOD_NO_IDLEST)
-               return 0;
-
-       if (!_find_mpu_rt_port(oh))
-               return 0;
-
-       /* XXX check module SIDLEMODE, hardreset status */
-
-       return am33xx_cm_wait_module_ready(oh->clkdm->cm_inst,
-                                             oh->clkdm->clkdm_offs,
-                                             oh->prcm.omap4.clkctrl_offs);
+       return omap_cm_wait_module_ready(oh->clkdm->prcm_partition,
+                                        oh->clkdm->cm_inst,
+                                        oh->prcm.omap4.clkctrl_offs, 0);
 }
 
 /**
@@ -3049,8 +2930,8 @@ static int _am33xx_wait_target_ready(struct omap_hwmod *oh)
 static int _omap2_assert_hardreset(struct omap_hwmod *oh,
                                   struct omap_hwmod_rst_info *ohri)
 {
-       return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
-                                         ohri->rst_shift);
+       return omap_prm_assert_hardreset(ohri->rst_shift, 0,
+                                        oh->prcm.omap2.module_offs, 0);
 }
 
 /**
@@ -3067,9 +2948,8 @@ static int _omap2_assert_hardreset(struct omap_hwmod *oh,
 static int _omap2_deassert_hardreset(struct omap_hwmod *oh,
                                     struct omap_hwmod_rst_info *ohri)
 {
-       return omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
-                                           ohri->rst_shift,
-                                           ohri->st_shift);
+       return omap_prm_deassert_hardreset(ohri->rst_shift, ohri->st_shift, 0,
+                                          oh->prcm.omap2.module_offs, 0, 0);
 }
 
 /**
@@ -3087,8 +2967,8 @@ static int _omap2_deassert_hardreset(struct omap_hwmod *oh,
 static int _omap2_is_hardreset_asserted(struct omap_hwmod *oh,
                                        struct omap_hwmod_rst_info *ohri)
 {
-       return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
-                                              ohri->st_shift);
+       return omap_prm_is_hardreset_asserted(ohri->st_shift, 0,
+                                             oh->prcm.omap2.module_offs, 0);
 }
 
 /**
@@ -3109,10 +2989,10 @@ static int _omap4_assert_hardreset(struct omap_hwmod *oh,
        if (!oh->clkdm)
                return -EINVAL;
 
-       return omap4_prminst_assert_hardreset(ohri->rst_shift,
-                               oh->clkdm->pwrdm.ptr->prcm_partition,
-                               oh->clkdm->pwrdm.ptr->prcm_offs,
-                               oh->prcm.omap4.rstctrl_offs);
+       return omap_prm_assert_hardreset(ohri->rst_shift,
+                                        oh->clkdm->pwrdm.ptr->prcm_partition,
+                                        oh->clkdm->pwrdm.ptr->prcm_offs,
+                                        oh->prcm.omap4.rstctrl_offs);
 }
 
 /**
@@ -3136,10 +3016,10 @@ static int _omap4_deassert_hardreset(struct omap_hwmod *oh,
        if (ohri->st_shift)
                pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
                       oh->name, ohri->name);
-       return omap4_prminst_deassert_hardreset(ohri->rst_shift,
-                               oh->clkdm->pwrdm.ptr->prcm_partition,
-                               oh->clkdm->pwrdm.ptr->prcm_offs,
-                               oh->prcm.omap4.rstctrl_offs);
+       return omap_prm_deassert_hardreset(ohri->rst_shift, 0,
+                                          oh->clkdm->pwrdm.ptr->prcm_partition,
+                                          oh->clkdm->pwrdm.ptr->prcm_offs,
+                                          oh->prcm.omap4.rstctrl_offs, 0);
 }
 
 /**
@@ -3160,10 +3040,11 @@ static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh,
        if (!oh->clkdm)
                return -EINVAL;
 
-       return omap4_prminst_is_hardreset_asserted(ohri->rst_shift,
-                               oh->clkdm->pwrdm.ptr->prcm_partition,
-                               oh->clkdm->pwrdm.ptr->prcm_offs,
-                               oh->prcm.omap4.rstctrl_offs);
+       return omap_prm_is_hardreset_asserted(ohri->rst_shift,
+                                             oh->clkdm->pwrdm.ptr->
+                                             prcm_partition,
+                                             oh->clkdm->pwrdm.ptr->prcm_offs,
+                                             oh->prcm.omap4.rstctrl_offs);
 }
 
 /**
@@ -3182,9 +3063,9 @@ static int _am33xx_assert_hardreset(struct omap_hwmod *oh,
                                   struct omap_hwmod_rst_info *ohri)
 
 {
-       return am33xx_prm_assert_hardreset(ohri->rst_shift,
-                               oh->clkdm->pwrdm.ptr->prcm_offs,
-                               oh->prcm.omap4.rstctrl_offs);
+       return omap_prm_assert_hardreset(ohri->rst_shift, 0,
+                                        oh->clkdm->pwrdm.ptr->prcm_offs,
+                                        oh->prcm.omap4.rstctrl_offs);
 }
 
 /**
@@ -3202,11 +3083,10 @@ static int _am33xx_assert_hardreset(struct omap_hwmod *oh,
 static int _am33xx_deassert_hardreset(struct omap_hwmod *oh,
                                     struct omap_hwmod_rst_info *ohri)
 {
-       return am33xx_prm_deassert_hardreset(ohri->rst_shift,
-                               ohri->st_shift,
-                               oh->clkdm->pwrdm.ptr->prcm_offs,
-                               oh->prcm.omap4.rstctrl_offs,
-                               oh->prcm.omap4.rstst_offs);
+       return omap_prm_deassert_hardreset(ohri->rst_shift, ohri->st_shift, 0,
+                                          oh->clkdm->pwrdm.ptr->prcm_offs,
+                                          oh->prcm.omap4.rstctrl_offs,
+                                          oh->prcm.omap4.rstst_offs);
 }
 
 /**
@@ -3224,9 +3104,9 @@ static int _am33xx_deassert_hardreset(struct omap_hwmod *oh,
 static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh,
                                        struct omap_hwmod_rst_info *ohri)
 {
-       return am33xx_prm_is_hardreset_asserted(ohri->rst_shift,
-                               oh->clkdm->pwrdm.ptr->prcm_offs,
-                               oh->prcm.omap4.rstctrl_offs);
+       return omap_prm_is_hardreset_asserted(ohri->rst_shift, 0,
+                                             oh->clkdm->pwrdm.ptr->prcm_offs,
+                                             oh->prcm.omap4.rstctrl_offs);
 }
 
 /* Public functions */
@@ -4234,12 +4114,12 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx)
 void __init omap_hwmod_init(void)
 {
        if (cpu_is_omap24xx()) {
-               soc_ops.wait_target_ready = _omap2xxx_wait_target_ready;
+               soc_ops.wait_target_ready = _omap2xxx_3xxx_wait_target_ready;
                soc_ops.assert_hardreset = _omap2_assert_hardreset;
                soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
                soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
        } else if (cpu_is_omap34xx()) {
-               soc_ops.wait_target_ready = _omap3xxx_wait_target_ready;
+               soc_ops.wait_target_ready = _omap2xxx_3xxx_wait_target_ready;
                soc_ops.assert_hardreset = _omap2_assert_hardreset;
                soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
                soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
@@ -4258,14 +4138,14 @@ void __init omap_hwmod_init(void)
                soc_ops.enable_module = _omap4_enable_module;
                soc_ops.disable_module = _omap4_disable_module;
                soc_ops.wait_target_ready = _omap4_wait_target_ready;
-               soc_ops.assert_hardreset = _am33xx_assert_hardreset;
-               soc_ops.deassert_hardreset = _am33xx_deassert_hardreset;
-               soc_ops.is_hardreset_asserted = _am33xx_is_hardreset_asserted;
+               soc_ops.assert_hardreset = _omap4_assert_hardreset;
+               soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
+               soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
                soc_ops.init_clkdm = _init_clkdm;
        } else if (soc_is_am33xx()) {
-               soc_ops.enable_module = _am33xx_enable_module;
-               soc_ops.disable_module = _am33xx_disable_module;
-               soc_ops.wait_target_ready = _am33xx_wait_target_ready;
+               soc_ops.enable_module = _omap4_enable_module;
+               soc_ops.disable_module = _omap4_disable_module;
+               soc_ops.wait_target_ready = _omap4_wait_target_ready;
                soc_ops.assert_hardreset = _am33xx_assert_hardreset;
                soc_ops.deassert_hardreset = _am33xx_deassert_hardreset;
                soc_ops.is_hardreset_asserted = _am33xx_is_hardreset_asserted;
index 512f809a3f4d1324c2f8a0a6661ac183d256240b..35ca6efbec31eb533ce039761024a7260371b2a1 100644 (file)
@@ -633,6 +633,7 @@ struct omap_hwmod_link {
  * @flags: hwmod flags (documented below)
  * @_lock: spinlock serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
+ * @parent_hwmod: (temporary) a pointer to the hierarchical parent of this hwmod
  *
  * @main_clk refers to this module's "main clock," which for our
  * purposes is defined as "the functional clock needed for register
@@ -643,6 +644,12 @@ struct omap_hwmod_link {
  * the omap_hwmod code and should not be set during initialization.
  *
  * @masters and @slaves are now deprecated.
+ *
+ * @parent_hwmod is temporary; there should be no need for it, as this
+ * information should already be expressed in the OCP interface
+ * structures.  @parent_hwmod is present as a workaround until we improve
+ * handling for hwmods with multiple parents (e.g., OMAP4+ DSS with
+ * multiple register targets across different interconnects).
  */
 struct omap_hwmod {
        const char                      *name;
@@ -680,6 +687,7 @@ struct omap_hwmod {
        u8                              _int_flags;
        u8                              _state;
        u8                              _postsetup_state;
+       struct omap_hwmod               *parent_hwmod;
 };
 
 struct omap_hwmod *omap_hwmod_lookup(const char *name);
index c2555cb95e7116765f2132bf711d1f959723765d..79127b35fe60b8023859417fa1db9e5c6674ca1b 100644 (file)
 
 #include <linux/i2c-omap.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/omap-dma.h>
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod.h"
-#include "mmc.h"
 #include "l3_2xxx.h"
 
 #include "soc.h"
@@ -372,7 +372,7 @@ static struct omap_hwmod_opt_clk omap2430_mmc1_opt_clks[] = {
        { .role = "dbck", .clk = "mmchsdb1_fck" },
 };
 
-static struct omap_mmc_dev_attr mmc1_dev_attr = {
+static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
        .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
index a579b89ce9b733a425e5ad9719ed2056783afbba..cabc5695b5043dd3c55db960de5103f4dcdbd2f9 100644 (file)
  */
 
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include "omap_hwmod.h"
 #include "i2c.h"
-#include "mmc.h"
 #include "wd_timer.h"
 #include "cm33xx.h"
 #include "prm33xx.h"
@@ -836,7 +836,7 @@ static struct omap_hwmod_class am33xx_mmc_hwmod_class = {
 };
 
 /* mmc0 */
-static struct omap_mmc_dev_attr am33xx_mmc0_dev_attr = {
+static struct omap_hsmmc_dev_attr am33xx_mmc0_dev_attr = {
        .flags          = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
@@ -854,7 +854,7 @@ struct omap_hwmod am33xx_mmc0_hwmod = {
 };
 
 /* mmc1 */
-static struct omap_mmc_dev_attr am33xx_mmc1_dev_attr = {
+static struct omap_hsmmc_dev_attr am33xx_mmc1_dev_attr = {
        .flags          = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
@@ -872,7 +872,7 @@ struct omap_hwmod am33xx_mmc1_hwmod = {
 };
 
 /* mmc2 */
-static struct omap_mmc_dev_attr am33xx_mmc2_dev_attr = {
+static struct omap_hsmmc_dev_attr am33xx_mmc2_dev_attr = {
        .flags          = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 struct omap_hwmod am33xx_mmc2_hwmod = {
index 6b406ca4bd3b49769884ce1534c1d132e224957a..0cf7b563dcd137702921b1033c1215d0108bd811 100644 (file)
@@ -27,7 +27,6 @@
 #include "prm33xx.h"
 #include "prm-regbits-33xx.h"
 #include "i2c.h"
-#include "mmc.h"
 #include "wd_timer.h"
 #include "omap_hwmod_33xx_43xx_common_data.h"
 
index 2a78b093c0ce9f23df8cc44025f276eb93832a2c..11468eea3871240c6e4078c365ac947119c0fea7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/i2c-omap.h>
 #include <linux/power/smartreflex.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/hsmmc-omap.h>
 
 #include <linux/omap-dma.h>
 #include "l3_3xxx.h"
@@ -37,7 +38,6 @@
 #include "cm-regbits-34xx.h"
 
 #include "i2c.h"
-#include "mmc.h"
 #include "wd_timer.h"
 #include "serial.h"
 
@@ -1786,12 +1786,12 @@ static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = {
        { .role = "dbck", .clk = "omap_32k_fck", },
 };
 
-static struct omap_mmc_dev_attr mmc1_dev_attr = {
+static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
        .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
 /* See 35xx errata 2.1.1.128 in SPRZ278F */
-static struct omap_mmc_dev_attr mmc1_pre_es3_dev_attr = {
+static struct omap_hsmmc_dev_attr mmc1_pre_es3_dev_attr = {
        .flags = (OMAP_HSMMC_SUPPORTS_DUAL_VOLT |
                  OMAP_HSMMC_BROKEN_MULTIBLOCK_READ),
 };
@@ -1854,7 +1854,7 @@ static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = {
 };
 
 /* See 35xx errata 2.1.1.128 in SPRZ278F */
-static struct omap_mmc_dev_attr mmc2_pre_es3_dev_attr = {
+static struct omap_hsmmc_dev_attr mmc2_pre_es3_dev_attr = {
        .flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ,
 };
 
index fea01aa3ef425846a0ae42f6eff5f706ae43a260..5c6c8410160ed7e147b19ae56320b220610cdfeb 100644 (file)
@@ -417,6 +417,37 @@ static struct omap_hwmod am43xx_qspi_hwmod = {
        },
 };
 
+/*
+ * 'adc/tsc' class
+ * TouchScreen Controller (Analog-To-Digital Converter)
+ */
+static struct omap_hwmod_class_sysconfig am43xx_adc_tsc_sysc = {
+       .rev_offs       = 0x00,
+       .sysc_offs      = 0x10,
+       .sysc_flags     = SYSC_HAS_SIDLEMODE,
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                         SIDLE_SMART_WKUP),
+       .sysc_fields    = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am43xx_adc_tsc_hwmod_class = {
+       .name           = "adc_tsc",
+       .sysc           = &am43xx_adc_tsc_sysc,
+};
+
+static struct omap_hwmod am43xx_adc_tsc_hwmod = {
+       .name           = "adc_tsc",
+       .class          = &am43xx_adc_tsc_hwmod_class,
+       .clkdm_name     = "l3s_tsc_clkdm",
+       .main_clk       = "adc_tsc_fck",
+       .prcm           = {
+               .omap4  = {
+                       .clkctrl_offs   = AM43XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET,
+                       .modulemode     = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
 /* dss */
 
 static struct omap_hwmod am43xx_dss_core_hwmod = {
@@ -547,6 +578,13 @@ static struct omap_hwmod_ocp_if am43xx_l4_wkup__gpio0 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__adc_tsc = {
+       .master         = &am33xx_l4_wkup_hwmod,
+       .slave          = &am43xx_adc_tsc_hwmod,
+       .clk            = "dpll_core_m4_div2_ck",
+       .user           = OCP_USER_MPU,
+};
+
 static struct omap_hwmod_ocp_if am43xx_l4_hs__cpgmac0 = {
        .master         = &am43xx_l4_hs_hwmod,
        .slave          = &am33xx_cpgmac0_hwmod,
@@ -789,6 +827,7 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
        &am43xx_l4_wkup__i2c1,
        &am43xx_l4_wkup__gpio0,
        &am43xx_l4_wkup__wd_timer1,
+       &am43xx_l4_wkup__adc_tsc,
        &am43xx_l3_s__qspi,
        &am33xx_l4_per__dcan0,
        &am33xx_l4_per__dcan1,
index 44e5634bba3450e3660a62c2f1341ba3231cf304..c314b3c31117e8cbee248db6aec7c0feb64f4fa9 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
 #include <linux/i2c-omap.h>
 
@@ -39,7 +40,6 @@
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
 #include "i2c.h"
-#include "mmc.h"
 #include "wd_timer.h"
 
 /* Base offset for all OMAP4 interrupts external to MPUSS */
@@ -589,6 +589,7 @@ static struct omap_hwmod omap44xx_dss_hwmod = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
                        .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
                },
        },
        .opt_clks       = dss_opt_clks,
@@ -647,7 +648,8 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
                        .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
-       .dev_attr       = &omap44xx_dss_dispc_dev_attr
+       .dev_attr       = &omap44xx_dss_dispc_dev_attr,
+       .parent_hwmod   = &omap44xx_dss_hwmod,
 };
 
 /*
@@ -701,6 +703,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
        },
        .opt_clks       = dss_dsi1_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_dsi1_opt_clks),
+       .parent_hwmod   = &omap44xx_dss_hwmod,
 };
 
 /* dss_dsi2 */
@@ -733,6 +736,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
        },
        .opt_clks       = dss_dsi2_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_dsi2_opt_clks),
+       .parent_hwmod   = &omap44xx_dss_hwmod,
 };
 
 /*
@@ -790,6 +794,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
        },
        .opt_clks       = dss_hdmi_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_hdmi_opt_clks),
+       .parent_hwmod   = &omap44xx_dss_hwmod,
 };
 
 /*
@@ -819,7 +824,7 @@ static struct omap_hwmod_dma_info omap44xx_dss_rfbi_sdma_reqs[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
-       { .role = "ick", .clk = "dss_fck" },
+       { .role = "ick", .clk = "l3_div_ck" },
 };
 
 static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
@@ -836,6 +841,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
        },
        .opt_clks       = dss_rfbi_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
+       .parent_hwmod   = &omap44xx_dss_hwmod,
 };
 
 /*
@@ -859,6 +865,7 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
                        .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
+       .parent_hwmod   = &omap44xx_dss_hwmod,
 };
 
 /*
@@ -1952,7 +1959,7 @@ static struct omap_hwmod_dma_info omap44xx_mmc1_sdma_reqs[] = {
 };
 
 /* mmc1 dev_attr */
-static struct omap_mmc_dev_attr mmc1_dev_attr = {
+static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
        .flags  = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
@@ -3671,7 +3678,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_hwmod,
-       .clk            = "dss_fck",
+       .clk            = "l3_div_ck",
        .addr           = omap44xx_dss_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -3707,7 +3714,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_dispc_hwmod,
-       .clk            = "dss_fck",
+       .clk            = "l3_div_ck",
        .addr           = omap44xx_dss_dispc_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -3743,7 +3750,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_dsi1_hwmod,
-       .clk            = "dss_fck",
+       .clk            = "l3_div_ck",
        .addr           = omap44xx_dss_dsi1_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -3779,7 +3786,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_dsi2_hwmod,
-       .clk            = "dss_fck",
+       .clk            = "l3_div_ck",
        .addr           = omap44xx_dss_dsi2_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -3815,7 +3822,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_hdmi_hwmod,
-       .clk            = "dss_fck",
+       .clk            = "l3_div_ck",
        .addr           = omap44xx_dss_hdmi_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -3851,7 +3858,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_rfbi_hwmod,
-       .clk            = "dss_fck",
+       .clk            = "l3_div_ck",
        .addr           = omap44xx_dss_rfbi_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
@@ -3887,7 +3894,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_dss_venc_hwmod,
-       .clk            = "dss_fck",
+       .clk            = "l3_div_ck",
        .addr           = omap44xx_dss_venc_dma_addrs,
        .user           = OCP_USER_SDMA,
 };
index 1103aa0e0d2941af13e417d8f71fb56794e85913..3e9523084b2ace3005adbd18ceae347eaef3e66a 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
 #include <linux/i2c-omap.h>
 
@@ -33,7 +34,6 @@
 #include "cm2_54xx.h"
 #include "prm54xx.h"
 #include "i2c.h"
-#include "mmc.h"
 #include "wd_timer.h"
 
 /* Base offset for all OMAP5 interrupts external to MPUSS */
@@ -421,6 +421,7 @@ static struct omap_hwmod omap54xx_dss_dispc_hwmod = {
        .opt_clks       = dss_dispc_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_dispc_opt_clks),
        .dev_attr       = &dss_dispc_dev_attr,
+       .parent_hwmod   = &omap54xx_dss_hwmod,
 };
 
 /*
@@ -462,6 +463,7 @@ static struct omap_hwmod omap54xx_dss_dsi1_a_hwmod = {
        },
        .opt_clks       = dss_dsi1_a_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_dsi1_a_opt_clks),
+       .parent_hwmod   = &omap54xx_dss_hwmod,
 };
 
 /* dss_dsi1_c */
@@ -482,6 +484,7 @@ static struct omap_hwmod omap54xx_dss_dsi1_c_hwmod = {
        },
        .opt_clks       = dss_dsi1_c_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_dsi1_c_opt_clks),
+       .parent_hwmod   = &omap54xx_dss_hwmod,
 };
 
 /*
@@ -521,6 +524,7 @@ static struct omap_hwmod omap54xx_dss_hdmi_hwmod = {
        },
        .opt_clks       = dss_hdmi_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_hdmi_opt_clks),
+       .parent_hwmod   = &omap54xx_dss_hwmod,
 };
 
 /*
@@ -560,6 +564,7 @@ static struct omap_hwmod omap54xx_dss_rfbi_hwmod = {
        },
        .opt_clks       = dss_rfbi_opt_clks,
        .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
+       .parent_hwmod   = &omap54xx_dss_hwmod,
 };
 
 /*
@@ -1269,7 +1274,7 @@ static struct omap_hwmod_opt_clk mmc1_opt_clks[] = {
 };
 
 /* mmc1 dev_attr */
-static struct omap_mmc_dev_attr mmc1_dev_attr = {
+static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
        .flags  = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
index 5684f112654bb9dc6688f43fc2defa58dcbf7d65..ffd6604cd546432c5c12e755414566bca9e907c7 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
 #include <linux/i2c-omap.h>
 
@@ -33,7 +34,6 @@
 #include "cm2_7xx.h"
 #include "prm7xx.h"
 #include "i2c.h"
-#include "mmc.h"
 #include "wd_timer.h"
 #include "soc.h"
 
@@ -1301,7 +1301,7 @@ static struct omap_hwmod_opt_clk mmc1_opt_clks[] = {
 };
 
 /* mmc1 dev_attr */
-static struct omap_mmc_dev_attr mmc1_dev_attr = {
+static struct omap_hsmmc_dev_attr mmc1_dev_attr = {
        .flags  = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
@@ -2075,6 +2075,70 @@ static struct omap_hwmod dra7xx_uart6_hwmod = {
        },
 };
 
+/* uart7 */
+static struct omap_hwmod dra7xx_uart7_hwmod = {
+       .name           = "uart7",
+       .class          = &dra7xx_uart_hwmod_class,
+       .clkdm_name     = "l4per2_clkdm",
+       .main_clk       = "uart7_gfclk_mux",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER2_UART7_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER2_UART7_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* uart8 */
+static struct omap_hwmod dra7xx_uart8_hwmod = {
+       .name           = "uart8",
+       .class          = &dra7xx_uart_hwmod_class,
+       .clkdm_name     = "l4per2_clkdm",
+       .main_clk       = "uart8_gfclk_mux",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER2_UART8_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER2_UART8_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* uart9 */
+static struct omap_hwmod dra7xx_uart9_hwmod = {
+       .name           = "uart9",
+       .class          = &dra7xx_uart_hwmod_class,
+       .clkdm_name     = "l4per2_clkdm",
+       .main_clk       = "uart9_gfclk_mux",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER2_UART9_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER2_UART9_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* uart10 */
+static struct omap_hwmod dra7xx_uart10_hwmod = {
+       .name           = "uart10",
+       .class          = &dra7xx_uart_hwmod_class,
+       .clkdm_name     = "wkupaon_clkdm",
+       .main_clk       = "uart10_gfclk_mux",
+       .flags          = HWMOD_SWSUP_SIDLE_ACT,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_WKUPAON_UART10_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_WKUPAON_UART10_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
 /*
  * 'usb_otg_ss' class
  *
@@ -3095,6 +3159,38 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart6 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per2 -> uart7 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart7 = {
+       .master         = &dra7xx_l4_per2_hwmod,
+       .slave          = &dra7xx_uart7_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per2 -> uart8 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart8 = {
+       .master         = &dra7xx_l4_per2_hwmod,
+       .slave          = &dra7xx_uart8_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per2 -> uart9 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart9 = {
+       .master         = &dra7xx_l4_per2_hwmod,
+       .slave          = &dra7xx_uart9_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> uart10 */
+static struct omap_hwmod_ocp_if dra7xx_l4_wkup__uart10 = {
+       .master         = &dra7xx_l4_wkup_hwmod,
+       .slave          = &dra7xx_uart10_hwmod,
+       .clk            = "wkupaon_iclk_mux",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per3 -> usb_otg_ss1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per3__usb_otg_ss1 = {
        .master         = &dra7xx_l4_per3_hwmod,
@@ -3259,6 +3355,10 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l4_per1__uart4,
        &dra7xx_l4_per1__uart5,
        &dra7xx_l4_per1__uart6,
+       &dra7xx_l4_per2__uart7,
+       &dra7xx_l4_per2__uart8,
+       &dra7xx_l4_per2__uart9,
+       &dra7xx_l4_wkup__uart10,
        &dra7xx_l4_per3__usb_otg_ss1,
        &dra7xx_l4_per3__usb_otg_ss2,
        &dra7xx_l4_per3__usb_otg_ss3,
index 50640b38f0bf7330635708d0091659e97649cb75..1a19fa096babe7c50df56a6e8416716f93b6390d 100644 (file)
@@ -21,6 +21,8 @@
   *
   */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
@@ -97,13 +99,13 @@ void am35x_musb_phy_power(u8 on)
 
                omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
 
-               pr_info(KERN_INFO "Waiting for PHY clock good...\n");
+               pr_info("Waiting for PHY clock good...\n");
                while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
                                & CONF2_PHYCLKGD)) {
                        cpu_relax();
 
                        if (time_after(jiffies, timeout)) {
-                               pr_err(KERN_ERR "musb PHY clock good timed out\n");
+                               pr_err("musb PHY clock good timed out\n");
                                break;
                        }
                }
@@ -145,7 +147,7 @@ void am35x_set_mode(u8 musb_mode)
                devconf2 |= CONF2_NO_OVERRIDE;
                break;
        default:
-               pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
+               pr_info("Unsupported mode %u\n", musb_mode);
        }
 
        omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
index c95346c948297fcb14f5f6a5dd33d71b7247166a..3d7eee1d3cfa7c2060b027141847c03eb57a2fed 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #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>
@@ -130,17 +131,45 @@ 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);
-       omap_ads7846_init(1, 57, 0, NULL);
 }
 
 static void __init omap3_sbc_t3530_legacy_init(void)
 {
        omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub");
-       omap_ads7846_init(1, 57, 0, NULL);
 }
 
-static void __init omap3_igep0020_legacy_init(void)
+struct ti_st_plat_data wilink_pdata = {
+       .nshutdown_gpio = 137,
+       .dev_name = "/dev/ttyO1",
+       .flow_cntrl = 1,
+       .baud_rate = 300000,
+};
+
+static struct platform_device wl18xx_device = {
+       .name   = "kim",
+       .id     = -1,
+       .dev    = {
+               .platform_data = &wilink_pdata,
+       }
+};
+
+static struct platform_device btwilink_device = {
+       .name   = "btwilink",
+       .id     = -1,
+};
+
+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);
 }
 
 static void __init omap3_evm_legacy_init(void)
@@ -218,7 +247,6 @@ static void __init omap3_sbc_t3517_legacy_init(void)
        hsmmc2_internal_input_clk();
        omap3_sbc_t3517_wifi_init();
        legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 145);
-       omap_ads7846_init(1, 57, 0, NULL);
 }
 
 static void __init am3517_evm_legacy_init(void)
@@ -252,9 +280,6 @@ static void __init nokia_n900_legacy_init(void)
                platform_device_register(&omap3_rom_rng_device);
 
        }
-
-       /* Only on some development boards */
-       gpio_request_one(164, GPIOF_OUT_INIT_LOW, "smc91x reset");
 }
 
 static void __init omap3_tao3530_legacy_init(void)
@@ -393,7 +418,8 @@ static struct pdata_init pdata_quirks[] __initdata = {
        { "nokia,omap3-n900", nokia_n900_legacy_init, },
        { "nokia,omap3-n9", hsmmc2_internal_input_clk, },
        { "nokia,omap3-n950", hsmmc2_internal_input_clk, },
-       { "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
+       { "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, },
index 175564c88a3035dcdaba4d1be9d2d00e5437078e..88721df6001d0ef7741aa377ef853dc89cb67bca 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/omap-dma.h>
+#include <linux/omap-gpmc.h>
 #include <linux/platform_data/gpio-omap.h>
 
 #include <trace/events/power.h>
@@ -43,7 +44,6 @@
 #include "common.h"
 #include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
-#include "gpmc.h"
 #include "prm-regbits-34xx.h"
 #include "prm3xxx.h"
 #include "pm.h"
index 503097c72b826d0f6ddf96547be2d165156271c2..d697cecf762b4501b8c3849d2bece4b25ab86967 100644 (file)
@@ -37,6 +37,16 @@ struct power_state {
        struct list_head node;
 };
 
+/**
+ * struct static_dep_map - Static dependency map
+ * @from:      from clockdomain
+ * @to:                to clockdomain
+  */
+struct static_dep_map {
+       const char *from;
+       const char *to;
+};
+
 static u32 cpu_suspend_state = PWRDM_POWER_OFF;
 
 static LIST_HEAD(pwrst_list);
@@ -148,94 +158,61 @@ static void omap_default_idle(void)
        omap_do_wfi();
 }
 
-/**
- * omap4_init_static_deps - Add OMAP4 static dependencies
- *
- * Add needed static clockdomain dependencies on OMAP4 devices.
- * Return: 0 on success or 'err' on failures
+/*
+ * The dynamic dependency between MPUSS -> MEMIF and
+ * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
+ * expected. The hardware recommendation is to enable static
+ * dependencies for these to avoid system lock ups or random crashes.
+ * The L4 wakeup depedency is added to workaround the OCP sync hardware
+ * BUG with 32K synctimer which lead to incorrect timer value read
+ * from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which
+ * are part of L4 wakeup clockdomain.
  */
-static inline int omap4_init_static_deps(void)
-{
-       struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm;
-       struct clockdomain *ducati_clkdm, *l3_2_clkdm;
-       int ret = 0;
-
-       if (omap_rev() == OMAP4430_REV_ES1_0) {
-               WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
-               return -ENODEV;
-       }
-
-       pr_err("Power Management for TI OMAP4.\n");
-       /*
-        * OMAP4 chip PM currently works only with certain (newer)
-        * versions of bootloaders. This is due to missing code in the
-        * kernel to properly reset and initialize some devices.
-        * http://www.spinics.net/lists/arm-kernel/msg218641.html
-        */
-       pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n");
-
-       ret = pwrdm_for_each(pwrdms_setup, NULL);
-       if (ret) {
-               pr_err("Failed to setup powerdomains\n");
-               return ret;
-       }
-
-       /*
-        * The dynamic dependency between MPUSS -> MEMIF and
-        * MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
-        * expected. The hardware recommendation is to enable static
-        * dependencies for these to avoid system lock ups or random crashes.
-        * The L4 wakeup depedency is added to workaround the OCP sync hardware
-        * BUG with 32K synctimer which lead to incorrect timer value read
-        * from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which
-        * are part of L4 wakeup clockdomain.
-        */
-       mpuss_clkdm = clkdm_lookup("mpuss_clkdm");
-       emif_clkdm = clkdm_lookup("l3_emif_clkdm");
-       l3_1_clkdm = clkdm_lookup("l3_1_clkdm");
-       l3_2_clkdm = clkdm_lookup("l3_2_clkdm");
-       ducati_clkdm = clkdm_lookup("ducati_clkdm");
-       if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
-               (!l3_2_clkdm) || (!ducati_clkdm))
-               return -EINVAL;
-
-       ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
-       ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
-       ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm);
-       ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm);
-       ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
-       if (ret) {
-               pr_err("Failed to add MPUSS -> L3/EMIF/L4PER, DUCATI -> L3 wakeup dependency\n");
-               return -EINVAL;
-       }
+static const struct static_dep_map omap4_static_dep_map[] = {
+       {.from = "mpuss_clkdm", .to = "l3_emif_clkdm"},
+       {.from = "mpuss_clkdm", .to = "l3_1_clkdm"},
+       {.from = "mpuss_clkdm", .to = "l3_2_clkdm"},
+       {.from = "ducati_clkdm", .to = "l3_1_clkdm"},
+       {.from = "ducati_clkdm", .to = "l3_2_clkdm"},
+       {.from  = NULL} /* TERMINATION */
+};
 
-       return ret;
-}
+static const struct static_dep_map omap5_dra7_static_dep_map[] = {
+       {.from = "mpu_clkdm", .to = "emif_clkdm"},
+       {.from  = NULL} /* TERMINATION */
+};
 
 /**
- * omap5_dra7_init_static_deps - Init static clkdm dependencies on OMAP5 and
- *                              DRA7
- *
- * The dynamic dependency between MPUSS -> EMIF is broken and has
- * not worked as expected. The hardware recommendation is to
- * enable static dependencies for these to avoid system
- * lock ups or random crashes.
+ * omap4plus_init_static_deps() - Initialize a static dependency map
+ * @map:       Mapping of clock domains
  */
-static inline int omap5_dra7_init_static_deps(void)
+static inline int omap4plus_init_static_deps(const struct static_dep_map *map)
 {
-       struct clockdomain *mpuss_clkdm, *emif_clkdm;
        int ret;
+       struct clockdomain *from, *to;
+
+       if (!map)
+               return 0;
 
-       mpuss_clkdm = clkdm_lookup("mpu_clkdm");
-       emif_clkdm = clkdm_lookup("emif_clkdm");
-       if (!mpuss_clkdm || !emif_clkdm)
-               return -EINVAL;
+       while (map->from) {
+               from = clkdm_lookup(map->from);
+               to = clkdm_lookup(map->to);
+               if (!from || !to) {
+                       pr_err("Failed lookup %s or %s for wakeup dependency\n",
+                              map->from, map->to);
+                       return -EINVAL;
+               }
+               ret = clkdm_add_wkdep(from, to);
+               if (ret) {
+                       pr_err("Failed to add %s -> %s wakeup dependency(%d)\n",
+                              map->from, map->to, ret);
+                       return ret;
+               }
 
-       ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm);
-       if (ret)
-               pr_err("Failed to add MPUSS -> EMIF wakeup dependency\n");
+               map++;
+       };
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -272,6 +249,15 @@ int __init omap4_pm_init(void)
 
        pr_info("Power Management for TI OMAP4+ devices.\n");
 
+       /*
+        * OMAP4 chip PM currently works only with certain (newer)
+        * versions of bootloaders. This is due to missing code in the
+        * kernel to properly reset and initialize some devices.
+        * http://www.spinics.net/lists/arm-kernel/msg218641.html
+        */
+       if (cpu_is_omap44xx())
+               pr_warn("OMAP4 PM: u-boot >= v2012.07 is required for full PM support\n");
+
        ret = pwrdm_for_each(pwrdms_setup, NULL);
        if (ret) {
                pr_err("Failed to setup powerdomains.\n");
@@ -279,9 +265,9 @@ int __init omap4_pm_init(void)
        }
 
        if (cpu_is_omap44xx())
-               ret = omap4_init_static_deps();
+               ret = omap4plus_init_static_deps(omap4_static_dep_map);
        else if (soc_is_omap54xx() || soc_is_dra7xx())
-               ret = omap5_dra7_init_static_deps();
+               ret = omap4plus_init_static_deps(omap5_dra7_static_dep_map);
 
        if (ret) {
                pr_err("Failed to initialise static dependencies.\n");
index 48480d557b61f82541068b174b430e4f8a1c53b5..77752e49d8d4c666a2f48fb816546ccfbf53b212 100644 (file)
@@ -29,6 +29,7 @@ int of_prcm_init(void);
  * PRM_HAS_VOLTAGE: has voltage domains
  */
 #define PRM_HAS_IO_WAKEUP      (1 << 0)
+#define PRM_HAS_VOLTAGE                (1 << 1)
 
 /*
  * MAX_MODULE_SOFTRESET_WAIT: Maximum microseconds to wait for OMAP
@@ -127,6 +128,8 @@ struct prm_reset_src_map {
  * @was_any_context_lost_old: ptr to the SoC PRM context loss test fn
  * @clear_context_loss_flags_old: ptr to the SoC PRM context loss flag clear fn
  * @late_init: ptr to the late init function
+ * @assert_hardreset: ptr to the SoC PRM hardreset assert impl
+ * @deassert_hardreset: ptr to the SoC PRM hardreset deassert impl
  *
  * XXX @was_any_context_lost_old and @clear_context_loss_flags_old are
  * deprecated.
@@ -136,14 +139,27 @@ struct prm_ll_data {
        bool (*was_any_context_lost_old)(u8 part, s16 inst, u16 idx);
        void (*clear_context_loss_flags_old)(u8 part, s16 inst, u16 idx);
        int (*late_init)(void);
+       int (*assert_hardreset)(u8 shift, u8 part, s16 prm_mod, u16 offset);
+       int (*deassert_hardreset)(u8 shift, u8 st_shift, u8 part, s16 prm_mod,
+                                 u16 offset, u16 st_offset);
+       int (*is_hardreset_asserted)(u8 shift, u8 part, s16 prm_mod,
+                                    u16 offset);
+       void (*reset_system)(void);
 };
 
 extern int prm_register(struct prm_ll_data *pld);
 extern int prm_unregister(struct prm_ll_data *pld);
 
+int omap_prm_assert_hardreset(u8 shift, u8 part, s16 prm_mod, u16 offset);
+int omap_prm_deassert_hardreset(u8 shift, u8 st_shift, u8 part, s16 prm_mod,
+                               u16 offset, u16 st_offset);
+int omap_prm_is_hardreset_asserted(u8 shift, u8 part, s16 prm_mod, u16 offset);
 extern u32 prm_read_reset_sources(void);
 extern bool prm_was_any_context_lost_old(u8 part, s16 inst, u16 idx);
 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);
 
 #endif
 
index 86958050547a4a803c6a86604c6ba17b2b5011e7..af0f15278fc2afc2d7480da370cba6cafac9d2f6 100644 (file)
@@ -106,7 +106,7 @@ static int omap2xxx_pwrst_to_common_pwrst(u8 omap2xxx_pwrst)
  * Set the DPLL reset bit, which should reboot the SoC.  This is the
  * recommended way to restart the SoC.  No return value.
  */
-void omap2xxx_prm_dpll_reset(void)
+static void omap2xxx_prm_dpll_reset(void)
 {
        omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, WKUP_MOD,
                                   OMAP2_RM_RSTCTRL);
@@ -212,6 +212,10 @@ struct pwrdm_ops omap2_pwrdm_operations = {
 
 static struct prm_ll_data omap2xxx_prm_ll_data = {
        .read_reset_sources = &omap2xxx_prm_read_reset_sources,
+       .assert_hardreset = &omap2_prm_assert_hardreset,
+       .deassert_hardreset = &omap2_prm_deassert_hardreset,
+       .is_hardreset_asserted = &omap2_prm_is_hardreset_asserted,
+       .reset_system = &omap2xxx_prm_dpll_reset,
 };
 
 int __init omap2xxx_prm_init(void)
index d73414139292478a99b3f35aaadb1bad0fdab0b7..1d51643062f7957dec8b9be7a66fcbf11d3e5de9 100644 (file)
 extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
 extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
 
-extern void omap2xxx_prm_dpll_reset(void);
 void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask);
 
 extern int __init omap2xxx_prm_init(void);
index c13b4e293ffaeb3ac89b24baead5a1d2da8adf4c..cc3341f263cd9223105ed3e7692425286b68ca1b 100644 (file)
 /**
  * omap2_prm_is_hardreset_asserted - read the HW reset line state of
  * submodules contained in the hwmod module
- * @prm_mod: PRM submodule base (e.g. CORE_MOD)
  * @shift: register bit shift corresponding to the reset line to check
+ * @part: PRM partition, ignored for OMAP2
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @offset: register offset, ignored for OMAP2
  *
  * Returns 1 if the (sub)module hardreset line is currently asserted,
  * 0 if the (sub)module hardreset line is not currently asserted, or
  * -EINVAL if called while running on a non-OMAP2/3 chip.
  */
-int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
+int omap2_prm_is_hardreset_asserted(u8 shift, u8 part, s16 prm_mod, u16 offset)
 {
        return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
                                       (1 << shift));
@@ -39,8 +41,10 @@ int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
 
 /**
  * omap2_prm_assert_hardreset - assert the HW reset line of a submodule
- * @prm_mod: PRM submodule base (e.g. CORE_MOD)
  * @shift: register bit shift corresponding to the reset line to assert
+ * @part: PRM partition, ignored for OMAP2
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @offset: register offset, ignored for OMAP2
  *
  * Some IPs like dsp or iva contain processors that require an HW
  * reset line to be asserted / deasserted in order to fully enable the
@@ -49,7 +53,7 @@ int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
  * place the submodule into reset.  Returns 0 upon success or -EINVAL
  * upon an argument error.
  */
-int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
+int omap2_prm_assert_hardreset(u8 shift, u8 part, s16 prm_mod, u16 offset)
 {
        u32 mask;
 
@@ -64,6 +68,10 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
  * @prm_mod: PRM submodule base (e.g. CORE_MOD)
  * @rst_shift: register bit shift corresponding to the reset line to deassert
  * @st_shift: register bit shift for the status of the deasserted submodule
+ * @part: PRM partition, not used for OMAP2
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @rst_offset: reset register offset, not used for OMAP2
+ * @st_offset: reset status register offset, not used for OMAP2
  *
  * Some IPs like dsp or iva contain processors that require an HW
  * reset line to be asserted / deasserted in order to fully enable the
@@ -74,7 +82,8 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
  * of reset, or -EBUSY if the submodule did not exit reset promptly.
  */
-int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
+int omap2_prm_deassert_hardreset(u8 rst_shift, u8 st_shift, u8 part,
+                                s16 prm_mod, u16 rst_offset, u16 st_offset)
 {
        u32 rst, st;
        int c;
index 1a3a96392b97be45567ce162d23f26b1433a70e7..f57e29b0e041a1f857f6edadc9b39938c3a118e2 100644 (file)
@@ -100,9 +100,12 @@ static inline u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
 }
 
 /* These omap2_ PRM functions apply to both OMAP2 and 3 */
-extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
-extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
-extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
+int omap2_prm_is_hardreset_asserted(u8 shift, u8 part, s16 prm_mod, u16 offset);
+int omap2_prm_assert_hardreset(u8 shift, u8 part, s16 prm_mod,
+                              u16 offset);
+int omap2_prm_deassert_hardreset(u8 rst_shift, u8 st_shift, u8 part,
+                                s16 prm_mod, u16 reset_offset,
+                                u16 st_offset);
 
 extern int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
 extern int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
index 62709cd2f9c579cb896fc030ebbcc213db0b9263..02f628601b098799e2b73354215ac33a411abe3b 100644 (file)
 #include "prm33xx.h"
 #include "prm-regbits-33xx.h"
 
+#define AM33XX_PRM_RSTCTRL_OFFSET              0x0000
+
+#define AM33XX_RST_GLOBAL_WARM_SW_MASK         (1 << 0)
+
 /* Read a register in a PRM instance */
-u32 am33xx_prm_read_reg(s16 inst, u16 idx)
+static u32 am33xx_prm_read_reg(s16 inst, u16 idx)
 {
        return readl_relaxed(prm_base + inst + idx);
 }
 
 /* Write into a register in a PRM instance */
-void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx)
+static void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx)
 {
        writel_relaxed(val, prm_base + inst + idx);
 }
 
 /* Read-modify-write a register in PRM. Caller must lock */
-u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
+static u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
 {
        u32 v;
 
@@ -52,6 +56,7 @@ u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
  * am33xx_prm_is_hardreset_asserted - read the HW reset line state of
  * submodules contained in the hwmod module
  * @shift: register bit shift corresponding to the reset line to check
+ * @part: PRM partition, ignored for AM33xx
  * @inst: CM instance register offset (*_INST macro)
  * @rstctrl_offs: RM_RSTCTRL register address offset for this module
  *
@@ -59,7 +64,8 @@ u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
  * 0 if the (sub)module hardreset line is not currently asserted, or
  * -EINVAL upon parameter error.
  */
-int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, u16 rstctrl_offs)
+static int am33xx_prm_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
+                                           u16 rstctrl_offs)
 {
        u32 v;
 
@@ -73,6 +79,7 @@ int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, u16 rstctrl_offs)
 /**
  * am33xx_prm_assert_hardreset - assert the HW reset line of a submodule
  * @shift: register bit shift corresponding to the reset line to assert
+ * @part: CM partition, ignored for AM33xx
  * @inst: CM instance register offset (*_INST macro)
  * @rstctrl_reg: RM_RSTCTRL register address for this module
  *
@@ -83,7 +90,8 @@ int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, u16 rstctrl_offs)
  * place the submodule into reset.  Returns 0 upon success or -EINVAL
  * upon an argument error.
  */
-int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs)
+static int am33xx_prm_assert_hardreset(u8 shift, u8 part, s16 inst,
+                                      u16 rstctrl_offs)
 {
        u32 mask = 1 << shift;
 
@@ -96,6 +104,8 @@ int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs)
  * am33xx_prm_deassert_hardreset - deassert a submodule hardreset line and
  * wait
  * @shift: register bit shift corresponding to the reset line to deassert
+ * @st_shift: reset status register bit shift corresponding to the reset line
+ * @part: PRM partition, not used for AM33xx
  * @inst: CM instance register offset (*_INST macro)
  * @rstctrl_reg: RM_RSTCTRL register address for this module
  * @rstst_reg: RM_RSTST register address for this module
@@ -109,14 +119,15 @@ int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs)
  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
  * of reset, or -EBUSY if the submodule did not exit reset promptly.
  */
-int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, s16 inst,
-               u16 rstctrl_offs, u16 rstst_offs)
+static int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, u8 part,
+                                        s16 inst, u16 rstctrl_offs,
+                                        u16 rstst_offs)
 {
        int c;
        u32 mask = 1 << st_shift;
 
        /* Check the current status to avoid  de-asserting the line twice */
-       if (am33xx_prm_is_hardreset_asserted(shift, inst, rstctrl_offs) == 0)
+       if (am33xx_prm_is_hardreset_asserted(shift, 0, inst, rstctrl_offs) == 0)
                return -EEXIST;
 
        /* Clear the reset status by writing 1 to the status bit */
@@ -128,7 +139,7 @@ int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, s16 inst,
        am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs);
 
        /* wait the status to be set */
-       omap_test_timeout(am33xx_prm_is_hardreset_asserted(st_shift, inst,
+       omap_test_timeout(am33xx_prm_is_hardreset_asserted(st_shift, 0, inst,
                                                           rstst_offs),
                          MAX_MODULE_HARDRESET_WAIT, c);
 
@@ -325,6 +336,23 @@ static int am33xx_check_vcvp(void)
        return 0;
 }
 
+/**
+ * am33xx_prm_global_warm_sw_reset - reboot the device via warm reset
+ *
+ * Immediately reboots the device through warm reset.
+ */
+static void am33xx_prm_global_warm_sw_reset(void)
+{
+       am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK,
+                               AM33XX_RST_GLOBAL_WARM_SW_MASK,
+                               AM33XX_PRM_DEVICE_MOD,
+                               AM33XX_PRM_RSTCTRL_OFFSET);
+
+       /* OCP barrier */
+       (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
+                                 AM33XX_PRM_RSTCTRL_OFFSET);
+}
+
 struct pwrdm_ops am33xx_pwrdm_operations = {
        .pwrdm_set_next_pwrst           = am33xx_pwrdm_set_next_pwrst,
        .pwrdm_read_next_pwrst          = am33xx_pwrdm_read_next_pwrst,
@@ -342,3 +370,21 @@ struct pwrdm_ops am33xx_pwrdm_operations = {
        .pwrdm_wait_transition          = am33xx_pwrdm_wait_transition,
        .pwrdm_has_voltdm               = am33xx_check_vcvp,
 };
+
+static struct prm_ll_data am33xx_prm_ll_data = {
+       .assert_hardreset               = am33xx_prm_assert_hardreset,
+       .deassert_hardreset             = am33xx_prm_deassert_hardreset,
+       .is_hardreset_asserted          = am33xx_prm_is_hardreset_asserted,
+       .reset_system                   = am33xx_prm_global_warm_sw_reset,
+};
+
+int __init am33xx_prm_init(void)
+{
+       return prm_register(&am33xx_prm_ll_data);
+}
+
+static void __exit am33xx_prm_exit(void)
+{
+       prm_unregister(&am33xx_prm_ll_data);
+}
+__exitcall(am33xx_prm_exit);
index 9b9918dfb119967e91c3c1ee791bb48e63219b41..98ac41f271da3460378a11a44468504f11ed0f32 100644 (file)
 #define AM33XX_PM_CEFUSE_PWRSTST               AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0004)
 
 #ifndef __ASSEMBLER__
-extern u32 am33xx_prm_read_reg(s16 inst, u16 idx);
-extern void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx);
-extern u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
-extern void am33xx_prm_global_warm_sw_reset(void);
-extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst,
-               u16 rstctrl_offs);
-extern int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs);
-extern int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, s16 inst,
-               u16 rstctrl_offs, u16 rstst_offs);
+int am33xx_prm_init(void);
+
 #endif /* ASSEMBLER */
 #endif
index ff08da385a2dd2facc58784957a55e09571fd33b..c5e00c6714b1d99fc5afaabe3f41985e1fce4bad 100644 (file)
 #include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
 
+static void omap3xxx_prm_read_pending_irqs(unsigned long *events);
+static void omap3xxx_prm_ocp_barrier(void);
+static void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
+static void omap3xxx_prm_restore_irqen(u32 *saved_mask);
+
 static const struct omap_prcm_irq omap3_prcm_irqs[] = {
        OMAP_PRCM_IRQ("wkup",   0,      0),
        OMAP_PRCM_IRQ("io",     9,      1),
@@ -131,7 +136,7 @@ u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
  * recommended way to restart the SoC, considering Errata i520.  No
  * return value.
  */
-void omap3xxx_prm_dpll3_reset(void)
+static void omap3xxx_prm_dpll3_reset(void)
 {
        omap2_prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, OMAP3430_GR_MOD,
                                   OMAP2_RM_RSTCTRL);
@@ -147,7 +152,7 @@ void omap3xxx_prm_dpll3_reset(void)
  * MPU IRQs, and store the result into the u32 pointed to by @events.
  * No return value.
  */
-void omap3xxx_prm_read_pending_irqs(unsigned long *events)
+static void omap3xxx_prm_read_pending_irqs(unsigned long *events)
 {
        u32 mask, st;
 
@@ -166,7 +171,7 @@ void omap3xxx_prm_read_pending_irqs(unsigned long *events)
  * block, to avoid race conditions after acknowledging or clearing IRQ
  * bits.  No return value.
  */
-void omap3xxx_prm_ocp_barrier(void)
+static void omap3xxx_prm_ocp_barrier(void)
 {
        omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
 }
@@ -182,7 +187,7 @@ void omap3xxx_prm_ocp_barrier(void)
  * returning; otherwise, spurious interrupts might occur.  No return
  * value.
  */
-void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
+static void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
 {
        saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD,
                                               OMAP3_PRM_IRQENABLE_MPU_OFFSET);
@@ -202,7 +207,7 @@ void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
  * barrier should be needed here; any pending PRM interrupts will fire
  * once the writes reach the PRM.  No return value.
  */
-void omap3xxx_prm_restore_irqen(u32 *saved_mask)
+static void omap3xxx_prm_restore_irqen(u32 *saved_mask)
 {
        omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD,
                                OMAP3_PRM_IRQENABLE_MPU_OFFSET);
@@ -375,7 +380,7 @@ void __init omap3_prm_init_pm(bool has_uart4, bool has_iva)
  * The ST_IO_CHAIN bit does not exist in 3430 before es3.1. The only
  * thing we can do is toggle EN_IO bit for earlier omaps.
  */
-void omap3430_pre_es3_1_reconfigure_io_chain(void)
+static void omap3430_pre_es3_1_reconfigure_io_chain(void)
 {
        omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
                                     PM_WKEN);
@@ -393,7 +398,7 @@ void omap3430_pre_es3_1_reconfigure_io_chain(void)
  * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit.  No
  * return value. These registers are only available in 3430 es3.1 and later.
  */
-void omap3_prm_reconfigure_io_chain(void)
+static void omap3_prm_reconfigure_io_chain(void)
 {
        int i = 0;
 
@@ -415,15 +420,6 @@ void omap3_prm_reconfigure_io_chain(void)
        omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
 }
 
-/**
- * omap3xxx_prm_reconfigure_io_chain - reconfigure I/O chain
- */
-void omap3xxx_prm_reconfigure_io_chain(void)
-{
-       if (omap3_prcm_irq_setup.reconfigure_io_chain)
-               omap3_prcm_irq_setup.reconfigure_io_chain();
-}
-
 /**
  * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
  *
@@ -664,6 +660,10 @@ static int omap3xxx_prm_late_init(void);
 static struct prm_ll_data omap3xxx_prm_ll_data = {
        .read_reset_sources = &omap3xxx_prm_read_reset_sources,
        .late_init = &omap3xxx_prm_late_init,
+       .assert_hardreset = &omap2_prm_assert_hardreset,
+       .deassert_hardreset = &omap2_prm_deassert_hardreset,
+       .is_hardreset_asserted = &omap2_prm_is_hardreset_asserted,
+       .reset_system = &omap3xxx_prm_dpll3_reset,
 };
 
 int __init omap3xxx_prm_init(void)
index bc37d42a8704ce34f0adfa353441a21b1e16dc55..cfde3f4a03ccda96ce7dabac3630a04963940f21 100644 (file)
@@ -144,22 +144,6 @@ 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);
 
-#ifdef CONFIG_ARCH_OMAP3
-void omap3xxx_prm_reconfigure_io_chain(void);
-#else
-static inline void omap3xxx_prm_reconfigure_io_chain(void)
-{
-}
-#endif
-
-/* PRM interrupt-related functions */
-extern void omap3xxx_prm_read_pending_irqs(unsigned long *events);
-extern void omap3xxx_prm_ocp_barrier(void);
-extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
-extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
-
-extern void omap3xxx_prm_dpll3_reset(void);
-
 extern int __init omap3xxx_prm_init(void);
 extern u32 omap3xxx_prm_get_reset_sources(void);
 int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
index 0958d070d3db66661a3493b1a14286858f19d8f6..cc170fb81ff76dc018ad6eee2c0e9931ab575f08 100644 (file)
 
 /* Static data */
 
+static void omap44xx_prm_read_pending_irqs(unsigned long *events);
+static void omap44xx_prm_ocp_barrier(void);
+static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
+static void omap44xx_prm_restore_irqen(u32 *saved_mask);
+static void omap44xx_prm_reconfigure_io_chain(void);
+
 static const struct omap_prcm_irq omap4_prcm_irqs[] = {
        OMAP_PRCM_IRQ("io",     9,      1),
 };
@@ -80,19 +86,19 @@ static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
 /* PRM low-level functions */
 
 /* Read a register in a CM/PRM instance in the PRM module */
-u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
+static u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
 {
        return readl_relaxed(prm_base + inst + reg);
 }
 
 /* Write into a register in a CM/PRM instance in the PRM module */
-void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
+static void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
 {
        writel_relaxed(val, prm_base + inst + reg);
 }
 
 /* Read-modify-write a register in a PRM module. Caller must lock */
-u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
+static u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 reg)
 {
        u32 v;
 
@@ -207,7 +213,7 @@ static inline u32 _read_pending_irq_reg(u16 irqen_offs, u16 irqst_offs)
  * MPU IRQs, and store the result into the two u32s pointed to by @events.
  * No return value.
  */
-void omap44xx_prm_read_pending_irqs(unsigned long *events)
+static void omap44xx_prm_read_pending_irqs(unsigned long *events)
 {
        events[0] = _read_pending_irq_reg(OMAP4_PRM_IRQENABLE_MPU_OFFSET,
                                          OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
@@ -224,7 +230,7 @@ void omap44xx_prm_read_pending_irqs(unsigned long *events)
  * block, to avoid race conditions after acknowledging or clearing IRQ
  * bits.  No return value.
  */
-void omap44xx_prm_ocp_barrier(void)
+static void omap44xx_prm_ocp_barrier(void)
 {
        omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
                                OMAP4_REVISION_PRM_OFFSET);
@@ -241,7 +247,7 @@ void omap44xx_prm_ocp_barrier(void)
  * interrupts reaches the PRM before returning; otherwise, spurious
  * interrupts might occur.  No return value.
  */
-void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
+static void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
 {
        saved_mask[0] =
                omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
@@ -270,7 +276,7 @@ void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
  * No OCP barrier should be needed here; any pending PRM interrupts will fire
  * once the writes reach the PRM.  No return value.
  */
-void omap44xx_prm_restore_irqen(u32 *saved_mask)
+static void omap44xx_prm_restore_irqen(u32 *saved_mask)
 {
        omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST,
                                 OMAP4_PRM_IRQENABLE_MPU_OFFSET);
@@ -287,7 +293,7 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask)
  * deasserting WUCLKIN and waiting for WUCLKOUT to be deasserted.
  * No return value. XXX Are the final two steps necessary?
  */
-void omap44xx_prm_reconfigure_io_chain(void)
+static void omap44xx_prm_reconfigure_io_chain(void)
 {
        int i = 0;
        s32 inst = omap4_prmst_get_prm_dev_inst();
@@ -652,11 +658,10 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 
 static int omap4_check_vcvp(void)
 {
-       /* No VC/VP on dra7xx devices */
-       if (soc_is_dra7xx())
-               return 0;
+       if (prm_features & PRM_HAS_VOLTAGE)
+               return 1;
 
-       return 1;
+       return 0;
 }
 
 struct pwrdm_ops omap4_pwrdm_operations = {
@@ -689,6 +694,10 @@ static struct prm_ll_data omap44xx_prm_ll_data = {
        .was_any_context_lost_old = &omap44xx_prm_was_any_context_lost_old,
        .clear_context_loss_flags_old = &omap44xx_prm_clear_context_loss_flags_old,
        .late_init = &omap44xx_prm_late_init,
+       .assert_hardreset       = omap4_prminst_assert_hardreset,
+       .deassert_hardreset     = omap4_prminst_deassert_hardreset,
+       .is_hardreset_asserted  = omap4_prminst_is_hardreset_asserted,
+       .reset_system           = omap4_prminst_global_warm_sw_reset,
 };
 
 int __init omap44xx_prm_init(void)
@@ -696,6 +705,9 @@ int __init omap44xx_prm_init(void)
        if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx())
                prm_features |= PRM_HAS_IO_WAKEUP;
 
+       if (!soc_is_dra7xx())
+               prm_features |= PRM_HAS_VOLTAGE;
+
        return prm_register(&omap44xx_prm_ll_data);
 }
 
index 8d95aa543ef562f65fe18e6ed0fd07ed23dbc505..f7512515fde57e7ab5ef1e939e0a25d91f2f9f93 100644 (file)
 /* Function prototypes */
 #ifndef __ASSEMBLER__
 
-extern u32 omap4_prm_read_inst_reg(s16 inst, u16 idx);
-extern void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 idx);
-extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
-
 /* OMAP4/OMAP5-specific VP functions */
 u32 omap4_prm_vp_check_txdone(u8 vp_id);
 void omap4_prm_vp_clear_txdone(u8 vp_id);
@@ -42,21 +38,6 @@ 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);
 
-#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
-       defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM43XX)
-void omap44xx_prm_reconfigure_io_chain(void);
-#else
-static inline void omap44xx_prm_reconfigure_io_chain(void)
-{
-}
-#endif
-
-/* PRM interrupt-related functions */
-extern void omap44xx_prm_read_pending_irqs(unsigned long *events);
-extern void omap44xx_prm_ocp_barrier(void);
-extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
-extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
-
 extern int __init omap44xx_prm_init(void);
 extern u32 omap44xx_prm_get_reset_sources(void);
 
index ee2b5222eac07f279e87a6126d7ed5a864d12d73..779940cb6e5651d4d5c486878b5cbbef060af1dc 100644 (file)
@@ -422,6 +422,105 @@ void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx)
                          __func__);
 }
 
+/**
+ * omap_prm_assert_hardreset - assert hardreset for an IP block
+ * @shift: register bit shift corresponding to the reset line
+ * @part: PRM partition
+ * @prm_mod: PRM submodule base or instance offset
+ * @offset: register offset
+ *
+ * Asserts a hardware reset line for an IP block.
+ */
+int omap_prm_assert_hardreset(u8 shift, u8 part, s16 prm_mod, u16 offset)
+{
+       if (!prm_ll_data->assert_hardreset) {
+               WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+                         __func__);
+               return -EINVAL;
+       }
+
+       return prm_ll_data->assert_hardreset(shift, part, prm_mod, offset);
+}
+
+/**
+ * omap_prm_deassert_hardreset - deassert hardreset for an IP block
+ * @shift: register bit shift corresponding to the reset line
+ * @st_shift: reset status bit shift corresponding to the reset line
+ * @part: PRM partition
+ * @prm_mod: PRM submodule base or instance offset
+ * @offset: register offset
+ * @st_offset: status register offset
+ *
+ * Deasserts a hardware reset line for an IP block.
+ */
+int omap_prm_deassert_hardreset(u8 shift, u8 st_shift, u8 part, s16 prm_mod,
+                               u16 offset, u16 st_offset)
+{
+       if (!prm_ll_data->deassert_hardreset) {
+               WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+                         __func__);
+               return -EINVAL;
+       }
+
+       return prm_ll_data->deassert_hardreset(shift, st_shift, part, prm_mod,
+                                              offset, st_offset);
+}
+
+/**
+ * omap_prm_is_hardreset_asserted - check the hardreset status for an IP block
+ * @shift: register bit shift corresponding to the reset line
+ * @part: PRM partition
+ * @prm_mod: PRM submodule base or instance offset
+ * @offset: register offset
+ *
+ * Checks if a hardware reset line for an IP block is enabled or not.
+ */
+int omap_prm_is_hardreset_asserted(u8 shift, u8 part, s16 prm_mod, u16 offset)
+{
+       if (!prm_ll_data->is_hardreset_asserted) {
+               WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+                         __func__);
+               return -EINVAL;
+       }
+
+       return prm_ll_data->is_hardreset_asserted(shift, part, prm_mod, offset);
+}
+
+/**
+ * omap_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
+ *
+ * Clear any previously-latched I/O wakeup events and ensure that the
+ * I/O wakeup gates are aligned with the current mux settings.
+ * Calls SoC specific I/O chain reconfigure function if available,
+ * otherwise does nothing.
+ */
+void omap_prm_reconfigure_io_chain(void)
+{
+       if (!prcm_irq_setup || !prcm_irq_setup->reconfigure_io_chain)
+               return;
+
+       prcm_irq_setup->reconfigure_io_chain();
+}
+
+/**
+ * omap_prm_reset_system - trigger global SW reset
+ *
+ * Triggers SoC specific global warm reset to reboot the device.
+ */
+void omap_prm_reset_system(void)
+{
+       if (!prm_ll_data->reset_system) {
+               WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+                         __func__);
+               return;
+       }
+
+       prm_ll_data->reset_system();
+
+       while (1)
+               cpu_relax();
+}
+
 /**
  * prm_register - register per-SoC low-level data with the PRM
  * @pld: low-level per-SoC OMAP PRM data & function pointers to register
index 225e0258d76d4e02e49ea6d63f8c1da1e6187479..8adf7b1a1dce68cd9139854e2f4785e1511e8c43 100644 (file)
@@ -148,8 +148,12 @@ int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
 /**
  * omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and
  * wait
- * @rstctrl_reg: RM_RSTCTRL register address for this module
  * @shift: register bit shift corresponding to the reset line to deassert
+ * @st_shift: status bit offset, not used for OMAP4+
+ * @part: PRM partition
+ * @inst: PRM instance offset
+ * @rstctrl_offs: reset register offset
+ * @st_offs: reset status register offset, not used for OMAP4+
  *
  * Some IPs like dsp, ipu or iva contain processors that require an HW
  * reset line to be asserted / deasserted in order to fully enable the
@@ -160,8 +164,8 @@ int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
  * of reset, or -EBUSY if the submodule did not exit reset promptly.
  */
-int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
-                                    u16 rstctrl_offs)
+int omap4_prminst_deassert_hardreset(u8 shift, u8 st_shift, u8 part, s16 inst,
+                                    u16 rstctrl_offs, u16 st_offs)
 {
        int c;
        u32 mask = 1 << shift;
index 583aa3774571391bda936e075fc9051b209624b4..fb1c9d7a2f9defe6b9255cbf193cae32c2eaef14 100644 (file)
@@ -30,8 +30,9 @@ extern int omap4_prminst_is_hardreset_asserted(u8 shift, u8 part, s16 inst,
                                               u16 rstctrl_offs);
 extern int omap4_prminst_assert_hardreset(u8 shift, u8 part, s16 inst,
                                          u16 rstctrl_offs);
-extern int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst,
-                                           u16 rstctrl_offs);
+int omap4_prminst_deassert_hardreset(u8 shift, u8 st_shift, u8 part,
+                                    s16 inst, u16 rstctrl_offs,
+                                    u16 rstst_offs);
 
 extern void omap_prm_base_init(void);
 
index a388f8c1bcb3cb2c69a199613ee3710eeb333c7b..57dee0c7cd2b3d57af4b11b3dcbb9ef156ecfd58 100644 (file)
@@ -263,9 +263,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
        omap_up.dma_rx_timeout = info->dma_rx_timeout;
        omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
        omap_up.autosuspend_timeout = info->autosuspend_timeout;
-       omap_up.DTR_gpio = info->DTR_gpio;
-       omap_up.DTR_inverted = info->DTR_inverted;
-       omap_up.DTR_present = info->DTR_present;
 
        pdata = &omap_up;
        pdata_size = sizeof(struct omap_uart_port_info);
index e6690a44917da7808c7e16a0aeb24d7094a5c9a5..83efe914bf7df4c422f02d7cc6093982093401a2 100644 (file)
@@ -4,6 +4,17 @@ menu "Intel PXA2xx/PXA3xx Implementations"
 
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA27X_DT
+       bool "Support PXA27x platforms from device tree"
+       select CPU_PXA27x
+       select POWER_SUPPLY
+       select PXA27x
+       select USE_OF
+       help
+         Include support for Marvell PXA27x based platforms using
+         the device tree. Needn't select any other machine while
+         MACH_PXA27X_DT is enabled.
+
 config MACH_PXA3XX_DT
        bool "Support PXA3xx platforms from device tree"
        select CPU_PXA300
index 2fe1824c6dcb515fc1eafe78f659d75f1990116a..eb0bf7678a9909fdb473b791eb8f183877c73588 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_CPU_PXA930)      += pxa930.o
 
 # Device Tree support
 obj-$(CONFIG_MACH_PXA3XX_DT)   += pxa-dt.o
+obj-$(CONFIG_MACH_PXA27X_DT)   += pxa-dt.o
 
 # Intel/Marvell Dev Platforms
 obj-$(CONFIG_ARCH_LUBBOCK)     += lubbock.o
index 6915a9f6b3a32b11370841095c81627231ff55c6..51531ecffca85783fa7cbd1ab608f9f52daa3846 100644 (file)
@@ -378,7 +378,7 @@ static void __init em_x270_init_nand(void)
 
        err = gpio_request(GPIO11_NAND_CS, "NAND CS");
        if (err) {
-               pr_warning("EM-X270: failed to request NAND CS gpio\n");
+               pr_warn("EM-X270: failed to request NAND CS gpio\n");
                return;
        }
 
@@ -386,7 +386,7 @@ static void __init em_x270_init_nand(void)
 
        err = gpio_request(nand_rb, "NAND R/B");
        if (err) {
-               pr_warning("EM-X270: failed to request NAND R/B gpio\n");
+               pr_warn("EM-X270: failed to request NAND R/B gpio\n");
                gpio_free(GPIO11_NAND_CS);
                return;
        }
index 8963984d1f43b5e27ea06b6363b0c7b35581a565..7a9fa1aa4e41838d05ae1a72354572e12fb8581c 100644 (file)
 
 struct irq_data;
 
-extern void pxa_timer_init(void);
-
-extern void __init pxa_map_io(void);
-
 extern unsigned int get_clk_frequency_khz(int info);
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *,
+                                            unsigned int));
+extern void __init pxa_map_io(void);
+extern void pxa_timer_init(void);
 
 #define SET_BANK(__nr,__start,__size) \
        mi->bank[__nr].start = (__start), \
@@ -25,6 +25,43 @@ extern unsigned int get_clk_frequency_khz(int info);
 
 #define ARRAY_AND_SIZE(x)      (x), ARRAY_SIZE(x)
 
+#define pxa25x_handle_irq icip_handle_irq
+extern void __init pxa25x_init_irq(void);
+extern void __init pxa25x_map_io(void);
+extern void __init pxa26x_init_irq(void);
+
+#define pxa27x_handle_irq ichp_handle_irq
+extern void __init pxa27x_dt_init_irq(void);
+extern unsigned        pxa27x_get_clk_frequency_khz(int);
+extern void __init pxa27x_init_irq(void);
+extern void __init pxa27x_map_io(void);
+
+#define pxa3xx_handle_irq ichp_handle_irq
+extern void __init pxa3xx_dt_init_irq(void);
+extern void __init pxa3xx_init_irq(void);
+extern void __init pxa3xx_map_io(void);
+
+extern struct syscore_ops pxa_irq_syscore_ops;
+extern struct syscore_ops pxa2xx_mfp_syscore_ops;
+extern struct syscore_ops pxa3xx_mfp_syscore_ops;
+
+void __init pxa_set_ffuart_info(void *info);
+void __init pxa_set_btuart_info(void *info);
+void __init pxa_set_stuart_info(void *info);
+void __init pxa_set_hwuart_info(void *info);
+
+void pxa_restart(enum reboot_mode, const char *);
+
+#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
+extern void pxa2xx_clear_reset_status(unsigned int);
+#else
+static inline void pxa2xx_clear_reset_status(unsigned int mask) {}
+#endif
+
+/*
+ * Once fully converted to the clock framework, all these functions should be
+ * removed, and replaced with a clk_get(NULL, "core").
+ */
 #ifdef CONFIG_PXA25x
 extern unsigned pxa25x_get_clk_frequency_khz(int);
 #else
@@ -32,30 +69,12 @@ extern unsigned pxa25x_get_clk_frequency_khz(int);
 #endif
 
 #ifdef CONFIG_PXA27x
-extern unsigned pxa27x_get_clk_frequency_khz(int);
 #else
 #define pxa27x_get_clk_frequency_khz(x)                (0)
 #endif
 
-#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
-extern void pxa2xx_clear_reset_status(unsigned int);
-#else
-static inline void pxa2xx_clear_reset_status(unsigned int mask) {}
-#endif
-
 #ifdef CONFIG_PXA3xx
-extern unsigned pxa3xx_get_clk_frequency_khz(int);
+extern unsigned        pxa3xx_get_clk_frequency_khz(int);
 #else
 #define pxa3xx_get_clk_frequency_khz(x)                (0)
 #endif
-
-extern struct syscore_ops pxa_irq_syscore_ops;
-extern struct syscore_ops pxa2xx_mfp_syscore_ops;
-extern struct syscore_ops pxa3xx_mfp_syscore_ops;
-
-void __init pxa_set_ffuart_info(void *info);
-void __init pxa_set_btuart_info(void *info);
-void __init pxa_set_stuart_info(void *info);
-void __init pxa_set_hwuart_info(void *info);
-
-void pxa_restart(enum reboot_mode, const char *);
index 00b92dad7b8163b4f0d11203a127ebfb97b97021..f6c76a3ee3b2a4783f5e09979f0096fa4e92ea71 100644 (file)
@@ -140,8 +140,7 @@ static void gumstix_setup_bt_clock(void)
        int timeout = 500;
 
        if (!(OSCC & OSCC_OOK))
-               pr_warning("32kHz clock was not on. Bootloader may need to "
-                               "be updated\n");
+               pr_warn("32kHz clock was not on. Bootloader may need to be updated\n");
        else
                return;
 
index bbf9df37ad4b6cf540166d23c1a3e0690b6b7176..d28fe291233a55ddb0173bcd71e124fc900010e2 100644 (file)
 #define DMEMC_VIRT             IOMEM(0xf6100000)
 #define DMEMC_SIZE             0x00100000
 
+/*
+ * Reserved space for low level debug virtual addresses within
+ * 0xf6200000..0xf6201000
+ */
+
 /*
  * Internal Memory Controller (PXA27x and later)
  */
index 3ac0baac73508bc418fd4493255b51004adff25f..5a341752e32c9948f0c939fbe3e451b1a31c9bf6 100644 (file)
@@ -6,12 +6,4 @@
 #include <mach/mfp-pxa25x.h>
 #include <mach/irqs.h>
 
-extern void __init pxa25x_map_io(void);
-extern void __init pxa25x_init_irq(void);
-#ifdef CONFIG_CPU_PXA26x
-extern void __init pxa26x_init_irq(void);
-#endif
-
-#define pxa25x_handle_irq      icip_handle_irq
-
 #endif /* __MACH_PXA25x_H */
index 7cff640582b8b9cb1daec1c7788264ae2f0735fe..599b925a657c46c5679524006757350b910436a7 100644 (file)
 #define ARB_CORE_PARK          (1<<24)    /* Be parked with core when idle */
 #define ARB_LOCK_FLAG          (1<<23)    /* Only Locking masters gain access to the bus */
 
-extern void __init pxa27x_map_io(void);
-extern void __init pxa27x_init_irq(void);
 extern int __init pxa27x_set_pwrmode(unsigned int mode);
 extern void pxa27x_cpu_pm_enter(suspend_state_t state);
 
-#define pxa27x_handle_irq      ichp_handle_irq
-
 #endif /* __MACH_PXA27x_H */
index 6dd7fa163e292150e743f6d6d30c55ae24a5b93b..b4143fb6631f155b26daa4d14a3c27dfbb4e29e6 100644 (file)
@@ -5,9 +5,4 @@
 #include <mach/pxa3xx-regs.h>
 #include <mach/irqs.h>
 
-extern void __init pxa3xx_map_io(void);
-extern void __init pxa3xx_init_irq(void);
-
-#define pxa3xx_handle_irq      ichp_handle_irq
-
 #endif /* __MACH_PXA3XX_H */
index ef0426a159d4d4e04c681f7097fb8732d7096156..666b78972c40e2434718ed3aef2e2f7852531aad 100644 (file)
@@ -93,8 +93,8 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
                break;
        default:
                /* warning and fall through, treat as MFP_LPM_DEFAULT */
-               pr_warning("%s: GPIO%d: unsupported low power mode\n",
-                               __func__, gpio);
+               pr_warn("%s: GPIO%d: unsupported low power mode\n",
+                       __func__, gpio);
                break;
        }
 
@@ -107,14 +107,12 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c)
         * configurations of those pins not able to wakeup
         */
        if ((c & MFP_LPM_CAN_WAKEUP) && !gpio_desc[gpio].can_wakeup) {
-               pr_warning("%s: GPIO%d unable to wakeup\n",
-                               __func__, gpio);
+               pr_warn("%s: GPIO%d unable to wakeup\n", __func__, gpio);
                return -EINVAL;
        }
 
        if ((c & MFP_LPM_CAN_WAKEUP) && is_out) {
-               pr_warning("%s: output GPIO%d unable to wakeup\n",
-                               __func__, gpio);
+               pr_warn("%s: output GPIO%d unable to wakeup\n", __func__, gpio);
                return -EINVAL;
        }
 
@@ -126,7 +124,7 @@ static inline int __mfp_validate(int mfp)
        int gpio = mfp_to_gpio(mfp);
 
        if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) {
-               pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
+               pr_warn("%s: GPIO%d is invalid pin\n", __func__, gpio);
                return -1;
        }
 
index 1319916291169915b43f31aa9d0028fb3279a612..29019beae591bce9eaff3490c1431028013f4a08 100644 (file)
@@ -446,7 +446,7 @@ static void __init poodle_init(void)
 
        ret = platform_add_devices(devices, ARRAY_SIZE(devices));
        if (ret)
-               pr_warning("poodle: Unable to register LoCoMo device\n");
+               pr_warn("poodle: Unable to register LoCoMo device\n");
 
        pxa_set_fb_info(&poodle_locomo_device.dev, &poodle_fb_info);
        pxa_set_udc_info(&udc_info);
index f6a2c4b1c1dc5ae8580e81f583c304501595027c..7e0e5bd0c9de1431b02414d9295ea5d142098afc 100644 (file)
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/irqs.h>
-#include <mach/pxa3xx.h>
 
 #include "generic.h"
 
 #ifdef CONFIG_PXA3xx
-extern void __init pxa3xx_dt_init_irq(void);
-
 static const struct of_dev_auxdata pxa3xx_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40100000, "pxa2xx-uart.0", NULL),
        OF_DEV_AUXDATA("mrvl,pxa-uart",         0x40200000, "pxa2xx-uart.1", NULL),
@@ -61,3 +58,18 @@ DT_MACHINE_START(PXA_DT, "Marvell PXA3xx (Device Tree Support)")
        .dt_compat      = pxa3xx_dt_board_compat,
 MACHINE_END
 #endif
+
+#ifdef CONFIG_PXA27x
+static const char * const pxa27x_dt_board_compat[] __initconst = {
+       "marvell,pxa270",
+       NULL,
+};
+
+DT_MACHINE_START(PXA27X_DT, "Marvell PXA2xx (Device Tree Support)")
+       .map_io         = pxa27x_map_io,
+       .init_irq       = pxa27x_dt_init_irq,
+       .handle_irq     = pxa27x_handle_irq,
+       .restart        = pxa_restart,
+       .dt_compat      = pxa27x_dt_board_compat,
+MACHINE_END
+#endif
index b040d7d1488839085e5fb5fedf5bee29b0b15803..af423a48c2e3bb13bdb6295fd03ccc2332f61eb0 100644 (file)
@@ -398,6 +398,12 @@ void __init pxa27x_init_irq(void)
        pxa_init_irq(34, pxa27x_set_wake);
 }
 
+void __init pxa27x_dt_init_irq(void)
+{
+       if (IS_ENABLED(CONFIG_OF))
+               pxa_dt_irq_init(pxa27x_set_wake);
+}
+
 static struct map_desc pxa27x_io_desc[] __initdata = {
        {       /* Mem Ctl */
                .virtual        = (unsigned long)SMEMC_VIRT,
index e329ccefd364c47c63b6b3552d773ec8f8fefd8e..614003e8b081d40a6f6de6bf7fb8db3c40523e96 100644 (file)
@@ -74,7 +74,7 @@ static int pxa310_ulpi_poll(void)
                cpu_relax();
        }
 
-       pr_warning("%s: ULPI access timed out!\n", __func__);
+       pr_warn("%s: ULPI access timed out!\n", __func__);
 
        return -ETIMEDOUT;
 }
@@ -84,7 +84,7 @@ static int pxa310_ulpi_read(struct usb_phy *otg, u32 reg)
        int err;
 
        if (pxa310_ulpi_get_phymode() != SYNCH) {
-               pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+               pr_warn("%s: PHY is not in SYNCH mode!\n", __func__);
                return -EBUSY;
        }
 
@@ -101,7 +101,7 @@ static int pxa310_ulpi_read(struct usb_phy *otg, u32 reg)
 static int pxa310_ulpi_write(struct usb_phy *otg, u32 val, u32 reg)
 {
        if (pxa310_ulpi_get_phymode() != SYNCH) {
-               pr_warning("%s: PHY is not in SYNCH mode!\n", __func__);
+               pr_warn("%s: PHY is not in SYNCH mode!\n", __func__);
                return -EBUSY;
        }
 
index 8386dc30b3e40d7c8eefac202411159932553327..a762b23ac830e5a8e90e5e98c2ea66b77c03ac1b 100644 (file)
@@ -521,7 +521,7 @@ static void __init raumfeld_w1_init(void)
                                "W1 external pullup enable");
 
        if (ret < 0)
-               pr_warning("Unable to request GPIO_W1_PULLUP_ENABLE\n");
+               pr_warn("Unable to request GPIO_W1_PULLUP_ENABLE\n");
        else
                gpio_direction_output(GPIO_W1_PULLUP_ENABLE, 0);
 
@@ -600,7 +600,7 @@ static void __init raumfeld_lcd_init(void)
 
        ret = gpio_request(GPIO_TFT_VA_EN, "display VA enable");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_TFT_VA_EN\n");
+               pr_warn("Unable to request GPIO_TFT_VA_EN\n");
        else
                gpio_direction_output(GPIO_TFT_VA_EN, 1);
 
@@ -608,7 +608,7 @@ static void __init raumfeld_lcd_init(void)
 
        ret = gpio_request(GPIO_DISPLAY_ENABLE, "display enable");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_DISPLAY_ENABLE\n");
+               pr_warn("Unable to request GPIO_DISPLAY_ENABLE\n");
        else
                gpio_direction_output(GPIO_DISPLAY_ENABLE, 1);
 
@@ -814,17 +814,17 @@ static void __init raumfeld_power_init(void)
        /* Set PEN2 high to enable maximum charge current */
        ret = gpio_request(GPIO_CHRG_PEN2, "CHRG_PEN2");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_CHRG_PEN2\n");
+               pr_warn("Unable to request GPIO_CHRG_PEN2\n");
        else
                gpio_direction_output(GPIO_CHRG_PEN2, 1);
 
        ret = gpio_request(GPIO_CHARGE_DC_OK, "CABLE_DC_OK");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_CHARGE_DC_OK\n");
+               pr_warn("Unable to request GPIO_CHARGE_DC_OK\n");
 
        ret = gpio_request(GPIO_CHARGE_USB_SUSP, "CHARGE_USB_SUSP");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_CHARGE_USB_SUSP\n");
+               pr_warn("Unable to request GPIO_CHARGE_USB_SUSP\n");
        else
                gpio_direction_output(GPIO_CHARGE_USB_SUSP, 0);
 
@@ -976,19 +976,19 @@ static void __init raumfeld_audio_init(void)
 
        ret = gpio_request(GPIO_CODEC_RESET, "cs4270 reset");
        if (ret < 0)
-               pr_warning("unable to request GPIO_CODEC_RESET\n");
+               pr_warn("unable to request GPIO_CODEC_RESET\n");
        else
                gpio_direction_output(GPIO_CODEC_RESET, 1);
 
        ret = gpio_request(GPIO_SPDIF_RESET, "ak4104 s/pdif reset");
        if (ret < 0)
-               pr_warning("unable to request GPIO_SPDIF_RESET\n");
+               pr_warn("unable to request GPIO_SPDIF_RESET\n");
        else
                gpio_direction_output(GPIO_SPDIF_RESET, 1);
 
        ret = gpio_request(GPIO_MCLK_RESET, "MCLK reset");
        if (ret < 0)
-               pr_warning("unable to request GPIO_MCLK_RESET\n");
+               pr_warn("unable to request GPIO_MCLK_RESET\n");
        else
                gpio_direction_output(GPIO_MCLK_RESET, 1);
 
@@ -1019,20 +1019,20 @@ static void __init raumfeld_common_init(void)
 
        ret = gpio_request(GPIO_W2W_RESET, "Wi2Wi reset");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_W2W_RESET\n");
+               pr_warn("Unable to request GPIO_W2W_RESET\n");
        else
                gpio_direction_output(GPIO_W2W_RESET, 0);
 
        ret = gpio_request(GPIO_W2W_PDN, "Wi2Wi powerup");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_W2W_PDN\n");
+               pr_warn("Unable to request GPIO_W2W_PDN\n");
        else
                gpio_direction_output(GPIO_W2W_PDN, 0);
 
        /* this can be used to switch off the device */
        ret = gpio_request(GPIO_SHUTDOWN_SUPPLY, "supply shutdown");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_SHUTDOWN_SUPPLY\n");
+               pr_warn("Unable to request GPIO_SHUTDOWN_SUPPLY\n");
        else
                gpio_direction_output(GPIO_SHUTDOWN_SUPPLY, 0);
 
@@ -1051,7 +1051,7 @@ static void __init raumfeld_controller_init(void)
 
        ret = gpio_request(GPIO_SHUTDOWN_BATT, "battery shutdown");
        if (ret < 0)
-               pr_warning("Unable to request GPIO_SHUTDOWN_BATT\n");
+               pr_warn("Unable to request GPIO_SHUTDOWN_BATT\n");
        else
                gpio_direction_output(GPIO_SHUTDOWN_BATT, 0);
 
index c158a6e3e0aa82a52458044b24c4444e2a5208ac..7780d1faa06f563057e68e749e7ccc7a9a8006d6 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
-#include <linux/pda_power.h>
+#include <linux/power/gpio-charger.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/input/matrix_keypad.h>
@@ -361,44 +361,17 @@ static struct pxaficp_platform_data tosa_ficp_platform_data = {
 /*
  * Tosa AC IN
  */
-static int tosa_power_init(struct device *dev)
-{
-       int ret = gpio_request(TOSA_GPIO_AC_IN, "ac in");
-       if (ret)
-               goto err_gpio_req;
-
-       ret = gpio_direction_input(TOSA_GPIO_AC_IN);
-       if (ret)
-               goto err_gpio_in;
-
-       return 0;
-
-err_gpio_in:
-       gpio_free(TOSA_GPIO_AC_IN);
-err_gpio_req:
-       return ret;
-}
-
-static void tosa_power_exit(struct device *dev)
-{
-       gpio_free(TOSA_GPIO_AC_IN);
-}
-
-static int tosa_power_ac_online(void)
-{
-       return gpio_get_value(TOSA_GPIO_AC_IN) == 0;
-}
-
 static char *tosa_ac_supplied_to[] = {
        "main-battery",
        "backup-battery",
        "jacket-battery",
 };
 
-static struct pda_power_pdata tosa_power_data = {
-       .init                   = tosa_power_init,
-       .is_ac_online           = tosa_power_ac_online,
-       .exit                   = tosa_power_exit,
+static struct gpio_charger_platform_data tosa_power_data = {
+       .name                   = "charger",
+       .type                   = POWER_SUPPLY_TYPE_MAINS,
+       .gpio                   = TOSA_GPIO_AC_IN,
+       .gpio_active_low        = 1,
        .supplied_to            = tosa_ac_supplied_to,
        .num_supplicants        = ARRAY_SIZE(tosa_ac_supplied_to),
 };
@@ -415,7 +388,7 @@ static struct resource tosa_power_resource[] = {
 };
 
 static struct platform_device tosa_power_device = {
-       .name                   = "pda-power",
+       .name                   = "gpio-charger",
        .id                     = -1,
        .dev.platform_data      = &tosa_power_data,
        .resource               = tosa_power_resource,
index 9db2029aa6321a99fe8948176f41bcf02fdac529..565925f37dc5d4242cc9816479775325e040a387 100644 (file)
@@ -1,6 +1,19 @@
 menu "RealView platform type"
        depends on ARCH_REALVIEW
 
+config REALVIEW_DT
+       bool "Support RealView(R) Device Tree based boot"
+       select ARM_GIC
+       select MFD_SYSCON
+       select POWER_RESET
+       select POWER_RESET_VERSATILE
+       select POWER_SUPPLY
+       select SOC_REALVIEW
+       select USE_OF
+       help
+         Include support for booting the ARM(R) RealView(R) evaluation
+         boards using a device tree machine description.
+
 config MACH_REALVIEW_EB
        bool "Support RealView(R) Emulation Baseboard"
        select ARM_GIC
index 541fa4c109ef0e800869d8640affd82ec7fe0442..e07fdf7ae8a7e61948f268942e4cc5f01238ec81 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 obj-y                                  := core.o
+obj-$(CONFIG_REALVIEW_DT)              += realview-dt.o
 obj-$(CONFIG_MACH_REALVIEW_EB)         += realview_eb.o
 obj-$(CONFIG_MACH_REALVIEW_PB11MP)     += realview_pb11mp.o
 obj-$(CONFIG_MACH_REALVIEW_PB1176)     += realview_pb1176.o
diff --git a/arch/arm/mach-realview/realview-dt.c b/arch/arm/mach-realview/realview-dt.c
new file mode 100644 (file)
index 0000000..cc28b89
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * Author: Linus Walleij <linus.walleij@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.
+ *
+ */
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "core.h"
+
+static const char *realview_dt_platform_compat[] __initconst = {
+       "arm,realview-eb",
+       "arm,realview-pb1176",
+       "arm,realview-pb11mp",
+       "arm,realview-pba8",
+       "arm,realview-pbx",
+       NULL,
+};
+
+DT_MACHINE_START(REALVIEW_DT, "ARM RealView Machine (Device Tree Support)")
+#ifdef CONFIG_ZONE_DMA
+       .dma_zone_size  = SZ_256M,
+#endif
+       .dt_compat      = realview_dt_platform_compat,
+       .l2c_aux_val = 0x0,
+       .l2c_aux_mask = ~0x0,
+MACHINE_END
index 73206e360e312db94dc18575bb117cae84e6e4cc..46c22dedf632abb7375167e93380629f3ac44acf 100644 (file)
 #include <linux/init.h>
 
 ENTRY(rockchip_secondary_startup)
-       bl      v7_invalidate_l1
+       mrc     p15, 0, r0, c0, c0, 0   @ read main ID register
+       ldr     r1, =0x00000c09         @ Cortex-A9 primary part number
+       teq     r0, r1
+       beq     v7_invalidate_l1
        b       secondary_startup
 ENDPROC(rockchip_secondary_startup)
 
index 189684f55927f4c8ce1efa83b20c890adca4d935..f26fcdca2445e96e5cbac6731791485e9f904e7e 100644 (file)
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
 
+#include <linux/reset.h>
+#include <linux/cpu.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
 #include <asm/smp_scu.h>
@@ -37,23 +41,78 @@ static int ncores;
 
 #define PMU_PWRDN_SCU          4
 
-static void __iomem *pmu_base_addr;
+static struct regmap *pmu;
 
-static inline bool pmu_power_domain_is_on(int pd)
+static int pmu_power_domain_is_on(int pd)
 {
-       return !(readl_relaxed(pmu_base_addr + PMU_PWRDN_ST) & BIT(pd));
+       u32 val;
+       int ret;
+
+       ret = regmap_read(pmu, PMU_PWRDN_ST, &val);
+       if (ret < 0)
+               return ret;
+
+       return !(val & BIT(pd));
 }
 
-static void pmu_set_power_domain(int pd, bool on)
+struct reset_control *rockchip_get_core_reset(int cpu)
 {
-       u32 val = readl_relaxed(pmu_base_addr + PMU_PWRDN_CON);
-       if (on)
-               val &= ~BIT(pd);
+       struct device *dev = get_cpu_device(cpu);
+       struct device_node *np;
+
+       /* The cpu device is only available after the initial core bringup */
+       if (dev)
+               np = dev->of_node;
        else
-               val |=  BIT(pd);
-       writel(val, pmu_base_addr + PMU_PWRDN_CON);
+               np = of_get_cpu_node(cpu, 0);
 
-       while (pmu_power_domain_is_on(pd) != on) { }
+       return of_reset_control_get(np, NULL);
+}
+
+static int pmu_set_power_domain(int pd, bool on)
+{
+       u32 val = (on) ? 0 : BIT(pd);
+       int ret;
+
+       /*
+        * We need to soft reset the cpu when we turn off the cpu power domain,
+        * or else the active processors might be stalled when the individual
+        * processor is powered down.
+        */
+       if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
+               struct reset_control *rstc = rockchip_get_core_reset(pd);
+
+               if (IS_ERR(rstc)) {
+                       pr_err("%s: could not get reset control for core %d\n",
+                              __func__, pd);
+                       return PTR_ERR(rstc);
+               }
+
+               if (on)
+                       reset_control_deassert(rstc);
+               else
+                       reset_control_assert(rstc);
+
+               reset_control_put(rstc);
+       }
+
+       ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+       if (ret < 0) {
+               pr_err("%s: could not update power domain\n", __func__);
+               return ret;
+       }
+
+       ret = -1;
+       while (ret != on) {
+               ret = pmu_power_domain_is_on(pd);
+               if (ret < 0) {
+                       pr_err("%s: could not read power domain state\n",
+                                __func__);
+                       return ret;
+               }
+       }
+
+       return 0;
 }
 
 /*
@@ -63,7 +122,9 @@ static void pmu_set_power_domain(int pd, bool on)
 static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
                                             struct task_struct *idle)
 {
-       if (!sram_base_addr || !pmu_base_addr) {
+       int ret;
+
+       if (!sram_base_addr || !pmu) {
                pr_err("%s: sram or pmu missing for cpu boot\n", __func__);
                return -ENXIO;
        }
@@ -75,7 +136,24 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
        }
 
        /* start the core */
-       pmu_set_power_domain(0 + cpu, true);
+       ret = pmu_set_power_domain(0 + cpu, true);
+       if (ret < 0)
+               return ret;
+
+       if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
+               /* We communicate with the bootrom to active the cpus other
+                * than cpu0, after a blob of initialize code, they will
+                * stay at wfe state, once they are actived, they will check
+                * the mailbox:
+                * sram_base_addr + 4: 0xdeadbeaf
+                * sram_base_addr + 8: start address for pc
+                * */
+               udelay(10);
+               writel(virt_to_phys(rockchip_secondary_startup),
+                       sram_base_addr + 8);
+               writel(0xDEADBEAF, sram_base_addr + 4);
+               dsb_sev();
+       }
 
        return 0;
 }
@@ -110,8 +188,6 @@ static int __init rockchip_smp_prepare_sram(struct device_node *node)
                return -EINVAL;
        }
 
-       sram_base_addr = of_iomap(node, 0);
-
        /* set the boot function for the sram code */
        rockchip_boot_fn = virt_to_phys(rockchip_secondary_startup);
 
@@ -125,54 +201,115 @@ static int __init rockchip_smp_prepare_sram(struct device_node *node)
        return 0;
 }
 
-static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
+static struct regmap_config rockchip_pmu_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+};
+
+static int __init rockchip_smp_prepare_pmu(void)
 {
        struct device_node *node;
-       unsigned int i;
+       void __iomem *pmu_base;
 
-       node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+       /*
+        * This function is only called via smp_ops->smp_prepare_cpu().
+        * That only happens if a "/cpus" device tree node exists
+        * and has an "enable-method" property that selects the SMP
+        * operations defined herein.
+        */
+       node = of_find_node_by_path("/cpus");
+
+       pmu = syscon_regmap_lookup_by_phandle(node, "rockchip,pmu");
+       of_node_put(node);
+       if (!IS_ERR(pmu))
+               return 0;
+
+       pmu = syscon_regmap_lookup_by_compatible("rockchip,rk3066-pmu");
+       if (!IS_ERR(pmu))
+               return 0;
+
+       /* fallback, create our own regmap for the pmu area */
+       pmu = NULL;
+       node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu");
        if (!node) {
-               pr_err("%s: missing scu\n", __func__);
-               return;
+               pr_err("%s: could not find pmu dt node\n", __func__);
+               return -ENODEV;
        }
 
-       scu_base_addr = of_iomap(node, 0);
-       if (!scu_base_addr) {
-               pr_err("%s: could not map scu registers\n", __func__);
-               return;
+       pmu_base = of_iomap(node, 0);
+       if (!pmu_base) {
+               pr_err("%s: could not map pmu registers\n", __func__);
+               return -ENOMEM;
        }
 
-       node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-smp-sram");
-       if (!node) {
-               pr_err("%s: could not find sram dt node\n", __func__);
-               return;
+       pmu = regmap_init_mmio(NULL, pmu_base, &rockchip_pmu_regmap_config);
+       if (IS_ERR(pmu)) {
+               int ret = PTR_ERR(pmu);
+
+               iounmap(pmu_base);
+               pmu = NULL;
+               pr_err("%s: regmap init failed\n", __func__);
+               return ret;
        }
 
-       if (rockchip_smp_prepare_sram(node))
-               return;
+       return 0;
+}
 
-       node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-pmu");
+static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
+{
+       struct device_node *node;
+       unsigned int i;
+
+       node = of_find_compatible_node(NULL, NULL, "rockchip,rk3066-smp-sram");
        if (!node) {
-               pr_err("%s: could not find pmu dt node\n", __func__);
+               pr_err("%s: could not find sram dt node\n", __func__);
                return;
        }
 
-       pmu_base_addr = of_iomap(node, 0);
-       if (!pmu_base_addr) {
-               pr_err("%s: could not map pmu registers\n", __func__);
+       sram_base_addr = of_iomap(node, 0);
+       if (!sram_base_addr) {
+               pr_err("%s: could not map sram registers\n", __func__);
                return;
        }
 
-       /* enable the SCU power domain */
-       pmu_set_power_domain(PMU_PWRDN_SCU, true);
-
-       /*
-        * While the number of cpus is gathered from dt, also get the number
-        * of cores from the scu to verify this value when booting the cores.
-        */
-       ncores = scu_get_core_count(scu_base_addr);
+       if (rockchip_smp_prepare_pmu())
+               return;
 
-       scu_enable(scu_base_addr);
+       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
+               if (rockchip_smp_prepare_sram(node))
+                       return;
+
+               /* enable the SCU power domain */
+               pmu_set_power_domain(PMU_PWRDN_SCU, true);
+
+               node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+               if (!node) {
+                       pr_err("%s: missing scu\n", __func__);
+                       return;
+               }
+
+               scu_base_addr = of_iomap(node, 0);
+               if (!scu_base_addr) {
+                       pr_err("%s: could not map scu registers\n", __func__);
+                       return;
+               }
+
+               /*
+                * While the number of cpus is gathered from dt, also get the
+                * number of cores from the scu to verify this value when
+                * booting the cores.
+                */
+               ncores = scu_get_core_count(scu_base_addr);
+               pr_err("%s: ncores %d\n", __func__, ncores);
+
+               scu_enable(scu_base_addr);
+       } else {
+               unsigned int l2ctlr;
+
+               asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr));
+               ncores = ((l2ctlr >> 24) & 0x3) + 1;
+       }
 
        /* Make sure that all cores except the first are really off */
        for (i = 1; i < ncores; i++)
index 8ab9e0e7ff049bed553404ac17f3f063ab5bb601..d226b71d21d5c6c0bdb702af93323f59934b22d4 100644 (file)
 #include <asm/hardware/cache-l2x0.h>
 #include "core.h"
 
+static void __init rockchip_dt_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       platform_device_register_simple("cpufreq-dt", 0, NULL, 0);
+}
+
 static const char * const rockchip_board_dt_compat[] = {
        "rockchip,rk2928",
        "rockchip,rk3066a",
@@ -37,4 +43,5 @@ DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
        .l2c_aux_val    = 0,
        .l2c_aux_mask   = ~0,
        .dt_compat      = rockchip_board_dt_compat,
+       .init_machine   = rockchip_dt_init,
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/include/mach/debug-macro.S b/arch/arm/mach-sa1100/include/mach/debug-macro.S
deleted file mode 100644 (file)
index 530772d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* arch/arm/mach-sa1100/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can 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 <mach/hardware.h>
-
-               .macro  addruart, rp, rv, tmp
-               mrc     p15, 0, \rp, c1, c0
-               tst     \rp, #1                 @ MMU enabled?
-               moveq   \rp, #0x80000000        @ physical base address
-               movne   \rp, #0xf8000000        @ virtual address
-
-               @ We probe for the active serial port here, coherently with
-               @ the comment in arch/arm/mach-sa1100/include/mach/uncompress.h.
-               @ We assume r1 can be clobbered.
-
-               @ see if Ser3 is active
-               add     \rp, \rp, #0x00050000
-               ldr     \rv, [\rp, #UTCR3]
-               tst     \rv, #UTCR3_TXE
-
-               @ if Ser3 is inactive, then try Ser1
-               addeq   \rp, \rp, #(0x00010000 - 0x00050000)
-               ldreq   \rv, [\rp, #UTCR3]
-               tsteq   \rv, #UTCR3_TXE
-
-               @ if Ser1 is inactive, then try Ser2
-               addeq   \rp, \rp, #(0x00030000 - 0x00010000)
-               ldreq   \rv, [\rp, #UTCR3]
-               tsteq   \rv, #UTCR3_TXE
-
-               @ clear top bits, and generate both phys and virt addresses
-               lsl     \rp, \rp, #8
-               lsr     \rp, \rp, #8
-               orr     \rv, \rp, #0xf8000000   @ virtual
-               orr     \rp, \rp, #0x80000000   @ physical
-
-               .endm
-
-               .macro  senduart,rd,rx
-               str     \rd, [\rx, #UTDR]
-               .endm
-
-               .macro  waituart,rd,rx
-1001:          ldr     \rd, [\rx, #UTSR1]
-               tst     \rd, #UTSR1_TNF
-               beq     1001b
-               .endm
-
-               .macro  busyuart,rd,rx
-1001:          ldr     \rd, [\rx, #UTSR1]
-               tst     \rd, #UTSR1_TBY
-               bne     1001b
-               .endm
index ff02e2da99f2f9d92fe8d9fa657e6a5ed419e144..b704433c529c4857e5aee64f2b593ce33106a04e 100644 (file)
 static DEFINE_SPINLOCK(nano_lock);
 
 static int nanoengine_get_pci_address(struct pci_bus *bus,
-       unsigned int devfn, int where, unsigned long *address)
+       unsigned int devfn, int where, void __iomem **address)
 {
        int ret = PCIBIOS_DEVICE_NOT_FOUND;
        unsigned int busnr = bus->number;
 
-       *address = NANO_PCI_CONFIG_SPACE_VIRT +
+       *address = (void __iomem *)NANO_PCI_CONFIG_SPACE_VIRT +
                ((bus->number << 16) | (devfn << 8) | (where & ~3));
 
        ret = (busnr > 255 || devfn > 255 || where > 255) ?
@@ -51,7 +51,7 @@ static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int w
        int size, u32 *val)
 {
        int ret;
-       unsigned long address;
+       void __iomem *address;
        unsigned long flags;
        u32 v;
 
@@ -85,7 +85,7 @@ static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int
        int size, u32 val)
 {
        int ret;
-       unsigned long address;
+       void __iomem *address;
        unsigned long flags;
        unsigned shift;
        u32 v;
index 21f457b56c016a7c67b4a2e73b42048af197e9ca..1b4fafe524ffeb4135d123ed3e0ce9e54be98755 100644 (file)
@@ -1,5 +1,6 @@
 config ARCH_SHMOBILE
        bool
+       select ZONE_DMA if ARM_LPAE
 
 config PM_RCAR
        bool
@@ -18,6 +19,7 @@ config ARCH_RCAR_GEN2
        select PM_RCAR if PM || SMP
        select RENESAS_IRQC
        select SYS_SUPPORTS_SH_CMT
+       select PCI_DOMAINS if PCI
 
 config ARCH_RMOBILE
        bool
@@ -36,7 +38,6 @@ menuconfig ARCH_SHMOBILE_MULTI
        select NO_IOPORT_MAP
        select PINCTRL
        select ARCH_REQUIRE_GPIOLIB
-       select ARCH_HAS_OPP
 
 if ARCH_SHMOBILE_MULTI
 
@@ -73,11 +74,6 @@ config ARCH_R8A7794
 
 comment "Renesas ARM SoCs Board Type"
 
-config MACH_KOELSCH
-       bool "Koelsch board"
-       depends on ARCH_R8A7791
-       select MICREL_PHY if SH_ETH
-
 config MACH_LAGER
        bool "Lager board"
        depends on ARCH_R8A7790
@@ -145,14 +141,6 @@ config ARCH_R8A7790
        select MIGHT_HAVE_PCI
        select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 
-config ARCH_R8A7791
-       bool "R-Car M2-W (R8A77910)"
-       select ARCH_RCAR_GEN2
-       select ARCH_WANT_OPTIONAL_GPIOLIB
-       select ARM_GIC
-       select MIGHT_HAVE_PCI
-       select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
-
 comment "Renesas ARM SoCs Board Type"
 
 config MACH_APE6EVM
@@ -227,12 +215,6 @@ config MACH_LAGER
        select MICREL_PHY if SH_ETH
        select SND_SOC_AK4642 if SND_SIMPLE_CARD
 
-config MACH_KOELSCH
-       bool "Koelsch board"
-       depends on ARCH_R8A7791
-       select USE_OF
-       select MICREL_PHY if SH_ETH
-
 config MACH_KZM9G
        bool "KZM-A9-GT board"
        depends on ARCH_SH73A0
index e20f2786ec72a23056e306c4ad8df1e560579288..b55cac0e5b2b21546f2d467e0d5db1c36ed6dded 100644 (file)
@@ -19,8 +19,8 @@ obj-$(CONFIG_ARCH_EMEV2)      += setup-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)    += setup-r7s72100.o
 
 # Clock objects
-obj-y                          += clock.o
 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
@@ -28,7 +28,6 @@ obj-$(CONFIG_ARCH_R8A7740)    += clock-r8a7740.o
 obj-$(CONFIG_ARCH_R8A7778)     += clock-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)     += clock-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)     += clock-r8a7790.o
-obj-$(CONFIG_ARCH_R8A7791)     += clock-r8a7791.o
 endif
 
 # CPU reset vector handling objects
@@ -36,6 +35,7 @@ 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
 
 # SMP objects
 smp-y                          := $(cpu-y)
@@ -57,7 +57,6 @@ obj-$(CONFIG_ARCH_SH7372)     += entry-intc.o sleep-sh7372.o
 
 # Board objects
 ifdef CONFIG_ARCH_SHMOBILE_MULTI
-obj-$(CONFIG_MACH_KOELSCH)     += board-koelsch-reference.o
 obj-$(CONFIG_MACH_LAGER)       += board-lager-reference.o
 obj-$(CONFIG_MACH_MARZEN)      += board-marzen-reference.o
 else
@@ -69,7 +68,6 @@ obj-$(CONFIG_MACH_BOCKW_REFERENCE)    += board-bockw-reference.o
 obj-$(CONFIG_MACH_MARZEN)      += board-marzen.o
 obj-$(CONFIG_MACH_LAGER)       += board-lager.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA)     += board-armadillo800eva.o
-obj-$(CONFIG_MACH_KOELSCH)     += board-koelsch.o
 obj-$(CONFIG_MACH_KZM9G)       += board-kzm9g.o
 obj-$(CONFIG_MACH_KZM9G_REFERENCE)     += board-kzm9g-reference.o
 endif
index de9a23852fc8caeb8a1173c44339f856deee04e7..57d00ed6ec0c21c1f3a19e40b204a30ad767355e 100644 (file)
@@ -5,7 +5,6 @@ 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_KOELSCH) += 0x40008000
 loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
 loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000
 loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000
index a6503d8c77de07c76288de39d6c4ede94db91090..3b68370b03a09ad1fa64e7aadc1acf7396f17c22 100644 (file)
  * but WITHOUT 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/gpio.h>
@@ -48,7 +44,6 @@ static void __init ape6evm_add_standard_devices(void)
        clk_put(parent);
        clk_put(mp);
 
-       r8a73a4_add_dt_devices();
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
index b222f68d55b7251ef2d8da0e2fcd50005fdfdef4..66f67816a844623977a4595ef23642ed381b3549 100644 (file)
  * but WITHOUT 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/gpio.h>
index e709835344038a5a1fbace09bcf68d554c27aa8b..6d949f1c850bda8bdf25b0ec3cc56e3658e514be 100644 (file)
  * but WITHOUT 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/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/input.h>
-#include <linux/platform_data/st1232_pdata.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
-#include <linux/regulator/driver.h>
+#include <linux/i2c-gpio.h>
+#include <linux/input.h>
+#include <linux/irq.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_data/st1232_pdata.h>
+#include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
+#include <linux/reboot.h>
+#include <linux/regulator/driver.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
-#include <linux/videodev2.h>
 #include <linux/usb/renesas_usbhs.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/i2c-gpio.h>
-#include <linux/reboot.h>
+#include <linux/videodev2.h>
 
-#include <media/mt9t112.h>
-#include <media/sh_mobile_ceu.h>
-#include <media/soc_camera.h>
-#include <asm/page.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <video/sh_mobile_lcdc.h>
-#include <video/sh_mobile_hdmi.h>
+#include <asm/page.h>
+#include <media/mt9t112.h>
+#include <media/sh_mobile_ceu.h>
+#include <media/soc_camera.h>
 #include <sound/sh_fsi.h>
 #include <sound/simple_card.h>
+#include <video/sh_mobile_hdmi.h>
+#include <video/sh_mobile_lcdc.h>
 
 #include "common.h"
 #include "irqs.h"
@@ -1234,8 +1229,15 @@ static void __init eva_init(void)
        static struct pm_domain_device domain_devices[] __initdata = {
                { "A4LC", &lcdc0_device },
                { "A4LC", &hdmi_lcdc_device },
+               { "A4MP", &hdmi_device },
+               { "A4MP", &fsi_device },
+               { "A4R",  &ceu0_device },
+               { "A4S",  &sh_eth_device },
+               { "A3SP", &pwm_device },
+               { "A3SP", &sdhi0_device },
+               { "A3SP", &sh_mmcif_device },
        };
-       struct platform_device *usb = NULL;
+       struct platform_device *usb = NULL, *sdhi1 = NULL;
 
        regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
                                     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
@@ -1304,6 +1306,7 @@ static void __init eva_init(void)
 
                platform_device_register(&vcc_sdhi1);
                platform_device_register(&sdhi1_device);
+               sdhi1 = &sdhi1_device;
        }
 
 
@@ -1324,6 +1327,8 @@ static void __init eva_init(void)
                                       ARRAY_SIZE(domain_devices));
        if (usb)
                rmobile_add_device_to_domain("A3SP", usb);
+       if (sdhi1)
+               rmobile_add_device_to_domain("A3SP", sdhi1);
 
        r8a7740_pm_init();
 }
index 79c47847f2004d5921d3061ff7a73f120a1b4ce3..d649ade4a202a2794abb107fd5b252047b5958c9 100644 (file)
  * but WITHOUT 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/of_platform.h>
index 1cf2c75dacfb49b94c5a26c03d6edb15c064baf1..f27b5a833bf0bb966a7046ae18a64f3f306f3134 100644 (file)
  * but WITHOUT 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/mfd/tmio.h>
diff --git a/arch/arm/mach-shmobile/board-koelsch-reference.c b/arch/arm/mach-shmobile/board-koelsch-reference.c
deleted file mode 100644 (file)
index 46aa540..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Koelsch board support - Reference DT implementation
- *
- * Copyright (C) 2013  Renesas Electronics Corporation
- * Copyright (C) 2013  Renesas Solutions Corp.
- * Copyright (C) 2013  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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/dma-mapping.h>
-#include <linux/kernel.h>
-#include <linux/of_platform.h>
-#include <linux/platform_data/rcar-du.h>
-
-#include <asm/mach/arch.h>
-
-#include "clock.h"
-#include "common.h"
-#include "irqs.h"
-#include "r8a7791.h"
-#include "rcar-gen2.h"
-
-/* DU */
-static struct rcar_du_encoder_data koelsch_du_encoders[] = {
-       {
-               .type = RCAR_DU_ENCODER_NONE,
-               .output = RCAR_DU_OUTPUT_LVDS0,
-               .connector.lvds.panel = {
-                       .width_mm = 210,
-                       .height_mm = 158,
-                       .mode = {
-                               .pixelclock = 65000000,
-                               .hactive = 1024,
-                               .hfront_porch = 20,
-                               .hback_porch = 160,
-                               .hsync_len = 136,
-                               .vactive = 768,
-                               .vfront_porch = 3,
-                               .vback_porch = 29,
-                               .vsync_len = 6,
-                       },
-               },
-       },
-};
-
-static struct rcar_du_platform_data koelsch_du_pdata = {
-       .encoders = koelsch_du_encoders,
-       .num_encoders = ARRAY_SIZE(koelsch_du_encoders),
-};
-
-static const struct resource du_resources[] __initconst = {
-       DEFINE_RES_MEM(0xfeb00000, 0x40000),
-       DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
-       DEFINE_RES_IRQ(gic_spi(256)),
-       DEFINE_RES_IRQ(gic_spi(268)),
-};
-
-static void __init koelsch_add_du_device(void)
-{
-       struct platform_device_info info = {
-               .name = "rcar-du-r8a7791",
-               .id = -1,
-               .res = du_resources,
-               .num_res = ARRAY_SIZE(du_resources),
-               .data = &koelsch_du_pdata,
-               .size_data = sizeof(koelsch_du_pdata),
-               .dma_mask = DMA_BIT_MASK(32),
-       };
-
-       platform_device_register_full(&info);
-}
-
-/*
- * This is a really crude hack to provide clkdev support to platform
- * devices until they get moved to DT.
- */
-static const struct clk_name clk_names[] __initconst = {
-       { "du0", "du.0", "rcar-du-r8a7791" },
-       { "du1", "du.1", "rcar-du-r8a7791" },
-       { "lvds0", "lvds.0", "rcar-du-r8a7791" },
-};
-
-static void __init koelsch_add_standard_devices(void)
-{
-       shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
-       koelsch_add_du_device();
-}
-
-static const char * const koelsch_boards_compat_dt[] __initconst = {
-       "renesas,koelsch",
-       "renesas,koelsch-reference",
-       NULL,
-};
-
-DT_MACHINE_START(KOELSCH_DT, "koelsch")
-       .smp            = smp_ops(r8a7791_smp_ops),
-       .init_early     = shmobile_init_delay,
-       .init_time      = rcar_gen2_timer_init,
-       .init_machine   = koelsch_add_standard_devices,
-       .init_late      = shmobile_init_late,
-       .reserve        = rcar_gen2_reserve,
-       .dt_compat      = koelsch_boards_compat_dt,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
deleted file mode 100644 (file)
index 7111b5c..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Koelsch board support
- *
- * Copyright (C) 2013  Renesas Electronics Corporation
- * Copyright (C) 2013-2014  Renesas Solutions Corp.
- * Copyright (C) 2013  Magnus Damm
- * Copyright (C) 2014  Cogent Embedded, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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/dma-mapping.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/leds.h>
-#include <linux/mfd/tmio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/phy.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/platform_data/gpio-rcar.h>
-#include <linux/platform_data/rcar-du.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/gpio-regulator.h>
-#include <linux/regulator/machine.h>
-#include <linux/sh_eth.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/rspi.h>
-#include <linux/spi/spi.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "irqs.h"
-#include "r8a7791.h"
-#include "rcar-gen2.h"
-
-/* DU */
-static struct rcar_du_encoder_data koelsch_du_encoders[] = {
-       {
-               .type = RCAR_DU_ENCODER_NONE,
-               .output = RCAR_DU_OUTPUT_LVDS0,
-               .connector.lvds.panel = {
-                       .width_mm = 210,
-                       .height_mm = 158,
-                       .mode = {
-                               .pixelclock = 65000000,
-                               .hactive = 1024,
-                               .hfront_porch = 20,
-                               .hback_porch = 160,
-                               .hsync_len = 136,
-                               .vactive = 768,
-                               .vfront_porch = 3,
-                               .vback_porch = 29,
-                               .vsync_len = 6,
-                       },
-               },
-       },
-};
-
-static const struct rcar_du_platform_data koelsch_du_pdata __initconst = {
-       .encoders = koelsch_du_encoders,
-       .num_encoders = ARRAY_SIZE(koelsch_du_encoders),
-};
-
-static const struct resource du_resources[] __initconst = {
-       DEFINE_RES_MEM(0xfeb00000, 0x40000),
-       DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
-       DEFINE_RES_IRQ(gic_spi(256)),
-       DEFINE_RES_IRQ(gic_spi(268)),
-};
-
-static void __init koelsch_add_du_device(void)
-{
-       struct platform_device_info info = {
-               .name = "rcar-du-r8a7791",
-               .id = -1,
-               .res = du_resources,
-               .num_res = ARRAY_SIZE(du_resources),
-               .data = &koelsch_du_pdata,
-               .size_data = sizeof(koelsch_du_pdata),
-               .dma_mask = DMA_BIT_MASK(32),
-       };
-
-       platform_device_register_full(&info);
-}
-
-/* Ether */
-static const struct sh_eth_plat_data ether_pdata __initconst = {
-       .phy                    = 0x1,
-       .phy_irq                = irq_pin(0),
-       .edmac_endian           = EDMAC_LITTLE_ENDIAN,
-       .phy_interface          = PHY_INTERFACE_MODE_RMII,
-       .ether_link_active_low  = 1,
-};
-
-static const struct resource ether_resources[] __initconst = {
-       DEFINE_RES_MEM(0xee700000, 0x400),
-       DEFINE_RES_IRQ(gic_spi(162)),
-};
-
-static const struct platform_device_info ether_info __initconst = {
-       .name           = "r8a7791-ether",
-       .id             = -1,
-       .res            = ether_resources,
-       .num_res        = ARRAY_SIZE(ether_resources),
-       .data           = &ether_pdata,
-       .size_data      = sizeof(ether_pdata),
-       .dma_mask       = DMA_BIT_MASK(32),
-};
-
-/* LEDS */
-static struct gpio_led koelsch_leds[] = {
-       {
-               .name           = "led8",
-               .gpio           = RCAR_GP_PIN(2, 21),
-               .default_state  = LEDS_GPIO_DEFSTATE_ON,
-       }, {
-               .name           = "led7",
-               .gpio           = RCAR_GP_PIN(2, 20),
-               .default_state  = LEDS_GPIO_DEFSTATE_ON,
-       }, {
-               .name           = "led6",
-               .gpio           = RCAR_GP_PIN(2, 19),
-               .default_state  = LEDS_GPIO_DEFSTATE_ON,
-       },
-};
-
-static const struct gpio_led_platform_data koelsch_leds_pdata __initconst = {
-       .leds           = koelsch_leds,
-       .num_leds       = ARRAY_SIZE(koelsch_leds),
-};
-
-/* GPIO KEY */
-#define GPIO_KEY(c, g, d, ...) \
-       { .code = c, .gpio = g, .desc = d, .active_low = 1, \
-         .wakeup = 1, .debounce_interval = 20 }
-
-static struct gpio_keys_button gpio_buttons[] = {
-       GPIO_KEY(KEY_4,         RCAR_GP_PIN(5, 3),      "SW2-pin4"),
-       GPIO_KEY(KEY_3,         RCAR_GP_PIN(5, 2),      "SW2-pin3"),
-       GPIO_KEY(KEY_2,         RCAR_GP_PIN(5, 1),      "SW2-pin2"),
-       GPIO_KEY(KEY_1,         RCAR_GP_PIN(5, 0),      "SW2-pin1"),
-       GPIO_KEY(KEY_G,         RCAR_GP_PIN(7, 6),      "SW36"),
-       GPIO_KEY(KEY_F,         RCAR_GP_PIN(7, 5),      "SW35"),
-       GPIO_KEY(KEY_E,         RCAR_GP_PIN(7, 4),      "SW34"),
-       GPIO_KEY(KEY_D,         RCAR_GP_PIN(7, 3),      "SW33"),
-       GPIO_KEY(KEY_C,         RCAR_GP_PIN(7, 2),      "SW32"),
-       GPIO_KEY(KEY_B,         RCAR_GP_PIN(7, 1),      "SW31"),
-       GPIO_KEY(KEY_A,         RCAR_GP_PIN(7, 0),      "SW30"),
-};
-
-static const struct gpio_keys_platform_data koelsch_keys_pdata __initconst = {
-       .buttons        = gpio_buttons,
-       .nbuttons       = ARRAY_SIZE(gpio_buttons),
-};
-
-/* QSPI */
-static const struct resource qspi_resources[] __initconst = {
-       DEFINE_RES_MEM(0xe6b10000, 0x1000),
-       DEFINE_RES_IRQ_NAMED(gic_spi(184), "mux"),
-};
-
-static const struct rspi_plat_data qspi_pdata __initconst = {
-       .num_chipselect = 1,
-};
-
-/* SPI Flash memory (Spansion S25FL512SAGMFIG11 64 MiB) */
-static struct mtd_partition spi_flash_part[] = {
-       {
-               .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           = "data",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = MTDPART_SIZ_FULL,
-       },
-};
-
-static const struct flash_platform_data spi_flash_data = {
-       .name           = "m25p80",
-       .parts          = spi_flash_part,
-       .nr_parts       = ARRAY_SIZE(spi_flash_part),
-       .type           = "s25fl512s",
-};
-
-static const struct spi_board_info spi_info[] __initconst = {
-       {
-               .modalias       = "m25p80",
-               .platform_data  = &spi_flash_data,
-               .mode           = SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD,
-               .max_speed_hz   = 30000000,
-               .bus_num        = 0,
-               .chip_select    = 0,
-       },
-};
-
-/* SATA0 */
-static const struct resource sata0_resources[] __initconst = {
-       DEFINE_RES_MEM(0xee300000, 0x2000),
-       DEFINE_RES_IRQ(gic_spi(105)),
-};
-
-static const struct platform_device_info sata0_info __initconst = {
-       .name           = "sata-r8a7791",
-       .id             = 0,
-       .res            = sata0_resources,
-       .num_res        = ARRAY_SIZE(sata0_resources),
-       .dma_mask       = DMA_BIT_MASK(32),
-};
-
-/* I2C */
-static const struct resource i2c_resources[] __initconst = {
-       /* I2C0 */
-       DEFINE_RES_MEM(0xE6508000, 0x40),
-       DEFINE_RES_IRQ(gic_spi(287)),
-       /* I2C1 */
-       DEFINE_RES_MEM(0xE6518000, 0x40),
-       DEFINE_RES_IRQ(gic_spi(288)),
-       /* I2C2 */
-       DEFINE_RES_MEM(0xE6530000, 0x40),
-       DEFINE_RES_IRQ(gic_spi(286)),
-       /* I2C3 */
-       DEFINE_RES_MEM(0xE6540000, 0x40),
-       DEFINE_RES_IRQ(gic_spi(290)),
-       /* I2C4 */
-       DEFINE_RES_MEM(0xE6520000, 0x40),
-       DEFINE_RES_IRQ(gic_spi(19)),
-       /* I2C5 */
-       DEFINE_RES_MEM(0xE6528000, 0x40),
-       DEFINE_RES_IRQ(gic_spi(20)),
-};
-
-static void __init koelsch_add_i2c(unsigned idx)
-{
-       unsigned res_idx = idx * 2;
-
-       BUG_ON(res_idx >= ARRAY_SIZE(i2c_resources));
-
-       platform_device_register_simple("i2c-rcar_gen2", idx,
-                                       i2c_resources + res_idx, 2);
-}
-
-#define SDHI_REGULATOR(idx, vdd_pin, vccq_pin)                         \
-static struct regulator_consumer_supply vcc_sdhi##idx##_consumer =     \
-       REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi." #idx);               \
-                                                                       \
-static struct regulator_init_data vcc_sdhi##idx##_init_data = {                \
-       .constraints = {                                                \
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,              \
-       },                                                              \
-       .consumer_supplies      = &vcc_sdhi##idx##_consumer,            \
-       .num_consumer_supplies  = 1,                                    \
-};                                                                     \
-                                                                       \
-static const struct fixed_voltage_config vcc_sdhi##idx##_info __initconst = {\
-       .supply_name    = "SDHI" #idx "Vcc",                            \
-       .microvolts     = 3300000,                                      \
-       .gpio           = vdd_pin,                                      \
-       .enable_high    = 1,                                            \
-       .init_data      = &vcc_sdhi##idx##_init_data,                   \
-};                                                                     \
-                                                                       \
-static struct regulator_consumer_supply vccq_sdhi##idx##_consumer =    \
-       REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi." #idx);              \
-                                                                       \
-static struct regulator_init_data vccq_sdhi##idx##_init_data = {       \
-       .constraints = {                                                \
-               .input_uV       = 3300000,                              \
-               .min_uV         = 1800000,                              \
-               .max_uV         = 3300000,                              \
-               .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |            \
-                                 REGULATOR_CHANGE_STATUS,              \
-       },                                                              \
-       .consumer_supplies      = &vccq_sdhi##idx##_consumer,           \
-       .num_consumer_supplies  = 1,                                    \
-};                                                                     \
-                                                                       \
-static struct gpio vccq_sdhi##idx##_gpio =                             \
-       { vccq_pin, GPIOF_OUT_INIT_HIGH, "vccq-sdhi" #idx };            \
-                                                                       \
-static struct gpio_regulator_state vccq_sdhi##idx##_states[] = {       \
-       { .value = 1800000, .gpios = 0 },                               \
-       { .value = 3300000, .gpios = 1 },                               \
-};                                                                     \
-                                                                       \
-static const struct gpio_regulator_config vccq_sdhi##idx##_info __initconst = {\
-       .supply_name    = "vqmmc",                                      \
-       .gpios          = &vccq_sdhi##idx##_gpio,                       \
-       .nr_gpios       = 1,                                            \
-       .states         = vccq_sdhi##idx##_states,                      \
-       .nr_states      = ARRAY_SIZE(vccq_sdhi##idx##_states),          \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .init_data      = &vccq_sdhi##idx##_init_data,                  \
-};
-
-SDHI_REGULATOR(0, RCAR_GP_PIN(7, 17), RCAR_GP_PIN(2, 12));
-SDHI_REGULATOR(1, RCAR_GP_PIN(7, 18), RCAR_GP_PIN(2, 13));
-SDHI_REGULATOR(2, RCAR_GP_PIN(7, 19), RCAR_GP_PIN(2, 26));
-
-/* SDHI0 */
-static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
-                         MMC_CAP_POWER_OFF_CARD,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
-};
-
-static struct resource sdhi0_resources[] __initdata = {
-       DEFINE_RES_MEM(0xee100000, 0x200),
-       DEFINE_RES_IRQ(gic_spi(165)),
-};
-
-/* SDHI1 */
-static struct sh_mobile_sdhi_info sdhi1_info __initdata = {
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
-                         MMC_CAP_POWER_OFF_CARD,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
-};
-
-static struct resource sdhi1_resources[] __initdata = {
-       DEFINE_RES_MEM(0xee140000, 0x100),
-       DEFINE_RES_IRQ(gic_spi(167)),
-};
-
-/* SDHI2 */
-static struct sh_mobile_sdhi_info sdhi2_info __initdata = {
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
-                         MMC_CAP_POWER_OFF_CARD,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT |
-                         TMIO_MMC_WRPROTECT_DISABLE,
-};
-
-static struct resource sdhi2_resources[] __initdata = {
-       DEFINE_RES_MEM(0xee160000, 0x100),
-       DEFINE_RES_IRQ(gic_spi(168)),
-};
-
-static const struct pinctrl_map koelsch_pinctrl_map[] = {
-       /* DU */
-       PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7791", "pfc-r8a7791",
-                                 "du_rgb666", "du"),
-       PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7791", "pfc-r8a7791",
-                                 "du_sync", "du"),
-       PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7791", "pfc-r8a7791",
-                                 "du_clk_out_0", "du"),
-       /* Ether */
-       PIN_MAP_MUX_GROUP_DEFAULT("r8a7791-ether", "pfc-r8a7791",
-                                 "eth_link", "eth"),
-       PIN_MAP_MUX_GROUP_DEFAULT("r8a7791-ether", "pfc-r8a7791",
-                                 "eth_mdio", "eth"),
-       PIN_MAP_MUX_GROUP_DEFAULT("r8a7791-ether", "pfc-r8a7791",
-                                 "eth_rmii", "eth"),
-       PIN_MAP_MUX_GROUP_DEFAULT("r8a7791-ether", "pfc-r8a7791",
-                                 "intc_irq0", "intc"),
-       /* QSPI */
-       PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7791",
-                                 "qspi_ctrl", "qspi"),
-       PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7791",
-                                 "qspi_data4", "qspi"),
-       /* SCIF0 (CN19: DEBUG SERIAL0) */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7791",
-                                 "scif0_data_d", "scif0"),
-       /* SCIF1 (CN20: DEBUG SERIAL1) */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7791",
-                                 "scif1_data_d", "scif1"),
-       /* I2C1 */
-       PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar_gen2.1", "pfc-r8a7791",
-                                 "i2c1_e", "i2c1"),
-       /* I2C2 */
-       PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar_gen2.2", "pfc-r8a7791",
-                                 "i2c2", "i2c2"),
-       /* I2C4 */
-       PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar_gen2.4", "pfc-r8a7791",
-                                 "i2c4_c", "i2c4"),
-       /* SDHI0 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
-                                 "sdhi0_data4", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
-                                 "sdhi0_ctrl", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
-                                 "sdhi0_cd", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7791",
-                                 "sdhi0_wp", "sdhi0"),
-       /* SDHI2 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
-                                 "sdhi1_data4", "sdhi1"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
-                                 "sdhi1_ctrl", "sdhi1"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
-                                 "sdhi1_cd", "sdhi1"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a7791",
-                                 "sdhi1_wp", "sdhi1"),
-       /* SDHI2 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7791",
-                                 "sdhi2_data4", "sdhi2"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7791",
-                                 "sdhi2_ctrl", "sdhi2"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7791",
-                                 "sdhi2_cd", "sdhi2"),
-};
-
-static void __init koelsch_add_standard_devices(void)
-{
-       r8a7791_clock_init();
-       pinctrl_register_mappings(koelsch_pinctrl_map,
-                                 ARRAY_SIZE(koelsch_pinctrl_map));
-       r8a7791_pinmux_init();
-       r8a7791_add_standard_devices();
-       platform_device_register_full(&ether_info);
-       platform_device_register_data(NULL, "leds-gpio", -1,
-                                     &koelsch_leds_pdata,
-                                     sizeof(koelsch_leds_pdata));
-       platform_device_register_data(NULL, "gpio-keys", -1,
-                                     &koelsch_keys_pdata,
-                                     sizeof(koelsch_keys_pdata));
-       platform_device_register_resndata(NULL, "qspi", 0,
-                                         qspi_resources,
-                                         ARRAY_SIZE(qspi_resources),
-                                         &qspi_pdata, sizeof(qspi_pdata));
-       spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
-
-       koelsch_add_du_device();
-
-       platform_device_register_full(&sata0_info);
-
-       koelsch_add_i2c(1);
-       koelsch_add_i2c(2);
-       koelsch_add_i2c(4);
-       koelsch_add_i2c(5);
-
-       platform_device_register_data(NULL, "reg-fixed-voltage", 0,
-                                     &vcc_sdhi0_info, sizeof(struct fixed_voltage_config));
-       platform_device_register_data(NULL, "reg-fixed-voltage", 1,
-                                     &vcc_sdhi1_info, sizeof(struct fixed_voltage_config));
-       platform_device_register_data(NULL, "reg-fixed-voltage", 2,
-                                     &vcc_sdhi2_info, sizeof(struct fixed_voltage_config));
-       platform_device_register_data(NULL, "gpio-regulator", 0,
-                                     &vccq_sdhi0_info, sizeof(struct gpio_regulator_config));
-       platform_device_register_data(NULL, "gpio-regulator", 1,
-                                     &vccq_sdhi1_info, sizeof(struct gpio_regulator_config));
-       platform_device_register_data(NULL, "gpio-regulator", 2,
-                                     &vccq_sdhi2_info, sizeof(struct gpio_regulator_config));
-
-       platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
-                                         sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
-                                         &sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
-
-       platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
-                                         sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
-                                         &sdhi1_info, sizeof(struct sh_mobile_sdhi_info));
-
-       platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2,
-                                         sdhi2_resources, ARRAY_SIZE(sdhi2_resources),
-                                         &sdhi2_info, sizeof(struct sh_mobile_sdhi_info));
-
-}
-
-/*
- * Ether LEDs on the Koelsch board are named LINK and ACTIVE which corresponds
- * to non-default 01 setting of the Micrel KSZ8041 PHY control register 1 bits
- * 14-15. We have to set them back to 01 from the default 00 value each time
- * the PHY is reset. It's also important because the PHY's LED0 signal is
- * connected to SoC's ETH_LINK signal and in the PHY's default mode it will
- * bounce on and off after each packet, which we apparently want to avoid.
- */
-static int koelsch_ksz8041_fixup(struct phy_device *phydev)
-{
-       u16 phyctrl1 = phy_read(phydev, 0x1e);
-
-       phyctrl1 &= ~0xc000;
-       phyctrl1 |= 0x4000;
-       return phy_write(phydev, 0x1e, phyctrl1);
-}
-
-static void __init koelsch_init(void)
-{
-       koelsch_add_standard_devices();
-
-       irq_set_irq_type(irq_pin(0), IRQ_TYPE_LEVEL_LOW);
-
-       if (IS_ENABLED(CONFIG_PHYLIB))
-               phy_register_fixup_for_id("r8a7791-ether-ff:01",
-                                         koelsch_ksz8041_fixup);
-}
-
-static const char * const koelsch_boards_compat_dt[] __initconst = {
-       "renesas,koelsch",
-       NULL,
-};
-
-DT_MACHINE_START(KOELSCH_DT, "koelsch")
-       .smp            = smp_ops(r8a7791_smp_ops),
-       .init_early     = shmobile_init_delay,
-       .init_time      = rcar_gen2_timer_init,
-       .init_machine   = koelsch_init,
-       .init_late      = shmobile_init_late,
-       .reserve        = rcar_gen2_reserve,
-       .dt_compat      = koelsch_boards_compat_dt,
-MACHINE_END
index d9cdf9a97e2390b4f63cb4b22b11246b2088bea6..2e82e44ab85258b725c3d62c665ceb4e757fc2f9 100644 (file)
  * but WITHOUT 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/delay.h>
@@ -43,6 +39,13 @@ static void __init kzm_init(void)
 #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,
@@ -54,5 +57,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g-reference")
        .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 77e36fa0b14216bb644149b2969267961ae43367..7c9b63bdde9fa458c3ddc7aa751030e0484beaf2 100644 (file)
  * but WITHOUT 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/delay.h>
index bc4b48357ddea891ccb0365ba267325adff374d8..fa06bdba61df19d33fe6990eaa0a867855434c98 100644 (file)
  * but WITHOUT 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/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/of_platform.h>
-#include <linux/platform_data/rcar-du.h>
 
 #include <asm/mach/arch.h>
 
-#include "clock.h"
 #include "common.h"
-#include "irqs.h"
 #include "r8a7790.h"
 #include "rcar-gen2.h"
 
-/* DU */
-static struct rcar_du_encoder_data lager_du_encoders[] = {
-       {
-               .type = RCAR_DU_ENCODER_VGA,
-               .output = RCAR_DU_OUTPUT_DPAD0,
-       }, {
-               .type = RCAR_DU_ENCODER_NONE,
-               .output = RCAR_DU_OUTPUT_LVDS1,
-               .connector.lvds.panel = {
-                       .width_mm = 210,
-                       .height_mm = 158,
-                       .mode = {
-                               .pixelclock = 65000000,
-                               .hactive = 1024,
-                               .hfront_porch = 20,
-                               .hback_porch = 160,
-                               .hsync_len = 136,
-                               .vactive = 768,
-                               .vfront_porch = 3,
-                               .vback_porch = 29,
-                               .vsync_len = 6,
-                       },
-               },
-       },
-};
-
-static struct rcar_du_platform_data lager_du_pdata = {
-       .encoders = lager_du_encoders,
-       .num_encoders = ARRAY_SIZE(lager_du_encoders),
-};
-
-static const struct resource du_resources[] __initconst = {
-       DEFINE_RES_MEM(0xfeb00000, 0x70000),
-       DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
-       DEFINE_RES_MEM_NAMED(0xfeb94000, 0x1c, "lvds.1"),
-       DEFINE_RES_IRQ(gic_spi(256)),
-       DEFINE_RES_IRQ(gic_spi(268)),
-       DEFINE_RES_IRQ(gic_spi(269)),
-};
-
-static void __init lager_add_du_device(void)
-{
-       struct platform_device_info info = {
-               .name = "rcar-du-r8a7790",
-               .id = -1,
-               .res = du_resources,
-               .num_res = ARRAY_SIZE(du_resources),
-               .data = &lager_du_pdata,
-               .size_data = sizeof(lager_du_pdata),
-               .dma_mask = DMA_BIT_MASK(32),
-       };
-
-       platform_device_register_full(&info);
-}
-
-/*
- * This is a really crude hack to provide clkdev support to platform
- * devices until they get moved to DT.
- */
-static const struct clk_name clk_names[] __initconst = {
-       { "du0", "du.0", "rcar-du-r8a7790" },
-       { "du1", "du.1", "rcar-du-r8a7790" },
-       { "du2", "du.2", "rcar-du-r8a7790" },
-       { "lvds0", "lvds.0", "rcar-du-r8a7790" },
-       { "lvds1", "lvds.1", "rcar-du-r8a7790" },
-};
-
-static void __init lager_add_standard_devices(void)
-{
-       shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
-       lager_add_du_device();
-}
-
 static const char *lager_boards_compat_dt[] __initdata = {
        "renesas,lager",
        "renesas,lager-reference",
@@ -116,7 +33,6 @@ DT_MACHINE_START(LAGER_DT, "lager")
        .smp            = smp_ops(r8a7790_smp_ops),
        .init_early     = shmobile_init_delay,
        .init_time      = rcar_gen2_timer_init,
-       .init_machine   = lager_add_standard_devices,
        .init_late      = shmobile_init_late,
        .reserve        = rcar_gen2_reserve,
        .dt_compat      = lager_boards_compat_dt,
index 571327b1c942c138fbba5cfe8e5ea03d7896ccb1..b47262afb2408c45d5ab10ca3ffc512bc2b14af2 100644 (file)
  * but WITHOUT 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/gpio.h>
index ca5d34b92aa7fc8e70d55cf4e6c2cf31aa103e13..ed1087031c5def92376b7acc100ee9dd8234cff2 100644 (file)
  * but WITHOUT 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/delay.h>
 #include <linux/kernel.h>
index 38d9cdd26587ebf3c843ea25d09d26674b9430c4..b15eb923263fb8442ccba621d641ee9a469b58de 100644 (file)
  * but WITHOUT 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/clk/shmobile.h>
@@ -26,7 +22,6 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 
-#include "clock.h"
 #include "common.h"
 #include "irqs.h"
 #include "r8a7779.h"
index ce33d7825c49a818a2bb1927299be684a7196544..994dc7d86ae241fff8ebba14948cefd1f4fff313 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <linux/kernel.h>
index c2330ea1802c6142dc4319836afe1490a7f4d5aa..1cf44dc6d718bcc0da183bc4e19aa595dfc7d08f 100644 (file)
  * but WITHOUT 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>
 #include <linux/io.h>
index 0794f0426e7044810ec46d695c4a9e0c87abd38b..9cac8247c72b6e4565e34523a19519815a19f6c1 100644 (file)
  * but WITHOUT 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/init.h>
 #include <linux/kernel.h>
@@ -455,7 +451,7 @@ enum {
        MSTP128, MSTP127, MSTP125,
        MSTP116, MSTP111, MSTP100, MSTP117,
 
-       MSTP230,
+       MSTP230, MSTP229,
        MSTP222,
        MSTP218, MSTP217, MSTP216, MSTP214,
        MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
@@ -474,11 +470,12 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S],   SMSTPCR1, 27, 0), /* CEU20 */
        [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
        [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B],   SMSTPCR1, 17, 0), /* LCDC1 */
-       [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
+       [MSTP116] = SH_CLK_MSTP32(&div4_clks[DIV4_HPP], SMSTPCR1, 16, 0), /* IIC0 */
        [MSTP111] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 11, 0), /* TMU1 */
        [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_B],   SMSTPCR1,  0, 0), /* LCDC0 */
 
        [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */
+       [MSTP229] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 29, 0), /* INTCA */
        [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */
        [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 18, 0), /* DMAC1 */
        [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 17, 0), /* DMAC2 */
@@ -575,6 +572,10 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh-dma-engine.0",        &mstp_clks[MSTP218]),
        CLKDEV_DEV_ID("sh-sci.7",               &mstp_clks[MSTP222]),
        CLKDEV_DEV_ID("e6cd0000.serial",        &mstp_clks[MSTP222]),
+       CLKDEV_DEV_ID("renesas_intc_irqpin.0",  &mstp_clks[MSTP229]),
+       CLKDEV_DEV_ID("renesas_intc_irqpin.1",  &mstp_clks[MSTP229]),
+       CLKDEV_DEV_ID("renesas_intc_irqpin.2",  &mstp_clks[MSTP229]),
+       CLKDEV_DEV_ID("renesas_intc_irqpin.3",  &mstp_clks[MSTP229]),
        CLKDEV_DEV_ID("sh-sci.6",               &mstp_clks[MSTP230]),
        CLKDEV_DEV_ID("e6cc0000.serial",        &mstp_clks[MSTP230]),
 
index 67980a08a601bfee89430fa48be2141ab3d82bb5..e8510c35558c11637d35e08d78690fbe87eff7c6 100644 (file)
  * but WITHOUT 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
  */
 
 /*
index c51f9db3f66fb2f9408094cc112b52c3d716d534..fa8ab2cc91878af5f568b58521b62d3b9340a96e 100644 (file)
  * but WITHOUT 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/bitops.h>
 #include <linux/init.h>
index 126ddafad5265dc62793fd6e7f25aea16b7c42e1..f9bbc5f0a9a12a8f61510e8d72df280149548c33 100644 (file)
  * but WITHOUT 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>
 #include <linux/io.h>
@@ -68,7 +64,7 @@
 
 #define SDCKCR         0xE6150074
 #define SD2CKCR                0xE6150078
-#define SD3CKCR                0xE615007C
+#define SD3CKCR                0xE615026C
 #define MMC0CKCR       0xE6150240
 #define MMC1CKCR       0xE6150244
 #define SSPCKCR                0xE6150248
diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
deleted file mode 100644 (file)
index 453b231..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * r8a7791 clock framework support
- *
- * Copyright (C) 2013  Renesas Electronics Corporation
- * Copyright (C) 2013  Renesas Solutions Corp.
- * Copyright (C) 2013  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * 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>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sh_clk.h>
-#include <linux/clkdev.h>
-#include "clock.h"
-#include "common.h"
-#include "rcar-gen2.h"
-
-/*
- *   MD                EXTAL           PLL0    PLL1    PLL3
- * 14 13 19    (MHz)           *1      *1
- *---------------------------------------------------
- * 0  0  0     15 x 1          x172/2  x208/2  x106
- * 0  0  1     15 x 1          x172/2  x208/2  x88
- * 0  1  0     20 x 1          x130/2  x156/2  x80
- * 0  1  1     20 x 1          x130/2  x156/2  x66
- * 1  0  0     26 / 2          x200/2  x240/2  x122
- * 1  0  1     26 / 2          x200/2  x240/2  x102
- * 1  1  0     30 / 2          x172/2  x208/2  x106
- * 1  1  1     30 / 2          x172/2  x208/2  x88
- *
- * *1 :        Table 7.6 indicates VCO ouput (PLLx = VCO/2)
- *     see "p1 / 2" on R8A7791_CLOCK_ROOT() below
- */
-
-#define CPG_BASE 0xe6150000
-#define CPG_LEN 0x1000
-
-#define SMSTPCR0       0xE6150130
-#define SMSTPCR1       0xE6150134
-#define SMSTPCR2       0xe6150138
-#define SMSTPCR3       0xE615013C
-#define SMSTPCR5       0xE6150144
-#define SMSTPCR7       0xe615014c
-#define SMSTPCR8       0xE6150990
-#define SMSTPCR9       0xE6150994
-#define SMSTPCR10      0xE6150998
-#define SMSTPCR11      0xE615099C
-
-#define MSTPSR1                IOMEM(0xe6150038)
-#define MSTPSR2                IOMEM(0xe6150040)
-#define MSTPSR3                IOMEM(0xe6150048)
-#define MSTPSR5                IOMEM(0xe615003c)
-#define MSTPSR7                IOMEM(0xe61501c4)
-#define MSTPSR8                IOMEM(0xe61509a0)
-#define MSTPSR9                IOMEM(0xe61509a4)
-#define MSTPSR11       IOMEM(0xe61509ac)
-
-#define SDCKCR         0xE6150074
-#define SD1CKCR                0xE6150078
-#define SD2CKCR                0xE615026c
-#define MMC0CKCR       0xE6150240
-#define MMC1CKCR       0xE6150244
-#define SSPCKCR                0xE6150248
-#define SSPRSCKCR      0xE615024C
-
-static struct clk_mapping cpg_mapping = {
-       .phys   = CPG_BASE,
-       .len    = CPG_LEN,
-};
-
-static struct clk extal_clk = {
-       /* .rate will be updated on r8a7791_clock_init() */
-       .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,
-};
-
-/*
- * clock ratio of these clock will be updated
- * on r8a7791_clock_init()
- */
-SH_FIXED_RATIO_CLK_SET(pll1_clk,               main_clk,       1, 1);
-SH_FIXED_RATIO_CLK_SET(pll3_clk,               main_clk,       1, 1);
-SH_FIXED_RATIO_CLK_SET(qspi_clk,               pll1_clk,       1, 1);
-
-/* fixed ratio clock */
-SH_FIXED_RATIO_CLK_SET(extal_div2_clk,         extal_clk,      1, 2);
-SH_FIXED_RATIO_CLK_SET(cp_clk,                 extal_clk,      1, 2);
-
-SH_FIXED_RATIO_CLK_SET(pll1_div2_clk,          pll1_clk,       1, 2);
-SH_FIXED_RATIO_CLK_SET(hp_clk,                 pll1_clk,       1, 12);
-SH_FIXED_RATIO_CLK_SET(p_clk,                  pll1_clk,       1, 24);
-SH_FIXED_RATIO_CLK_SET(rclk_clk,               pll1_clk,       1, (48 * 1024));
-SH_FIXED_RATIO_CLK_SET(mp_clk,                 pll1_div2_clk,  1, 15);
-SH_FIXED_RATIO_CLK_SET(zg_clk,                 pll1_clk,       1, 3);
-SH_FIXED_RATIO_CLK_SET(zx_clk,                 pll1_clk,       1, 3);
-SH_FIXED_RATIO_CLK_SET(zs_clk,                 pll1_clk,       1, 6);
-
-static struct clk *main_clks[] = {
-       &extal_clk,
-       &extal_div2_clk,
-       &main_clk,
-       &pll1_clk,
-       &pll1_div2_clk,
-       &pll3_clk,
-       &hp_clk,
-       &p_clk,
-       &qspi_clk,
-       &rclk_clk,
-       &mp_clk,
-       &cp_clk,
-       &zg_clk,
-       &zx_clk,
-       &zs_clk,
-};
-
-/* SDHI (DIV4) clock */
-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,
-};
-
-enum {
-       DIV4_SDH, DIV4_SD0,
-       DIV4_NR
-};
-
-static struct clk div4_clks[DIV4_NR] = {
-       [DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
-       [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1df0, CLK_ENABLE_ON_INIT),
-};
-
-/* DIV6 clocks */
-enum {
-       DIV6_SD1, DIV6_SD2,
-       DIV6_NR
-};
-
-static struct clk div6_clks[DIV6_NR] = {
-       [DIV6_SD1]      = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0),
-       [DIV6_SD2]      = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0),
-};
-
-/* MSTP */
-enum {
-       MSTP1108, MSTP1107, MSTP1106,
-       MSTP931, MSTP930, MSTP929, MSTP928, MSTP927, MSTP925,
-       MSTP917,
-       MSTP815, MSTP814,
-       MSTP813,
-       MSTP811, MSTP810, MSTP809,
-       MSTP726, MSTP724, MSTP723, MSTP721, MSTP720,
-       MSTP719, MSTP718, MSTP715, MSTP714,
-       MSTP522,
-       MSTP314, MSTP312, MSTP311,
-       MSTP216, MSTP207, MSTP206,
-       MSTP204, MSTP203, MSTP202,
-       MSTP124,
-       MSTP_NR
-};
-
-static struct clk mstp_clks[MSTP_NR] = {
-       [MSTP1108] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 8, MSTPSR11, 0), /* SCIFA5 */
-       [MSTP1107] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 7, MSTPSR11, 0), /* SCIFA4 */
-       [MSTP1106] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR11, 6, MSTPSR11, 0), /* SCIFA3 */
-       [MSTP931] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */
-       [MSTP930] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */
-       [MSTP929] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */
-       [MSTP928] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */
-       [MSTP927] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 27, MSTPSR9, 0), /* I2C4 */
-       [MSTP925] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 25, MSTPSR9, 0), /* I2C5 */
-       [MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */
-       [MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */
-       [MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */
-       [MSTP813] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR8, 13, MSTPSR8, 0), /* Ether */
-       [MSTP811] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 11, MSTPSR8, 0), /* VIN0 */
-       [MSTP810] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 10, MSTPSR8, 0), /* VIN1 */
-       [MSTP809] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 9, MSTPSR8, 0), /* VIN2 */
-       [MSTP726] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 26, MSTPSR7, 0), /* LVDS0 */
-       [MSTP724] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 24, MSTPSR7, 0), /* DU0 */
-       [MSTP723] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 23, MSTPSR7, 0), /* DU1 */
-       [MSTP721] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 21, MSTPSR7, 0), /* SCIF0 */
-       [MSTP720] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 20, MSTPSR7, 0), /* SCIF1 */
-       [MSTP719] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 19, MSTPSR7, 0), /* SCIF2 */
-       [MSTP718] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 18, MSTPSR7, 0), /* SCIF3 */
-       [MSTP715] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 15, MSTPSR7, 0), /* SCIF4 */
-       [MSTP714] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 14, MSTPSR7, 0), /* SCIF5 */
-       [MSTP522] = SH_CLK_MSTP32_STS(&extal_clk, SMSTPCR5, 22, MSTPSR5, 0), /* Thermal */
-       [MSTP314] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD0], SMSTPCR3, 14, MSTPSR3, 0), /* SDHI0 */
-       [MSTP312] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD1], SMSTPCR3, 12, MSTPSR3, 0), /* SDHI1 */
-       [MSTP311] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD2], SMSTPCR3, 11, MSTPSR3, 0), /* SDHI2 */
-       [MSTP216] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 16, MSTPSR2, 0), /* SCIFB2 */
-       [MSTP207] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 7, MSTPSR2, 0), /* SCIFB1 */
-       [MSTP206] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 6, MSTPSR2, 0), /* SCIFB0 */
-       [MSTP204] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 4, MSTPSR2, 0), /* SCIFA0 */
-       [MSTP203] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 3, MSTPSR2, 0), /* SCIFA1 */
-       [MSTP202] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 2, MSTPSR2, 0), /* SCIFA2 */
-       [MSTP124] = SH_CLK_MSTP32_STS(&rclk_clk, SMSTPCR1, 24, MSTPSR1, 0), /* CMT0 */
-};
-
-static struct clk_lookup lookups[] = {
-
-       /* main clocks */
-       CLKDEV_CON_ID("extal",          &extal_clk),
-       CLKDEV_CON_ID("extal_div2",     &extal_div2_clk),
-       CLKDEV_CON_ID("main",           &main_clk),
-       CLKDEV_CON_ID("pll1",           &pll1_clk),
-       CLKDEV_CON_ID("pll1_div2",      &pll1_div2_clk),
-       CLKDEV_CON_ID("pll3",           &pll3_clk),
-       CLKDEV_CON_ID("zg",             &zg_clk),
-       CLKDEV_CON_ID("zs",             &zs_clk),
-       CLKDEV_CON_ID("hp",             &hp_clk),
-       CLKDEV_CON_ID("p",              &p_clk),
-       CLKDEV_CON_ID("qspi",           &qspi_clk),
-       CLKDEV_CON_ID("rclk",           &rclk_clk),
-       CLKDEV_CON_ID("mp",             &mp_clk),
-       CLKDEV_CON_ID("cp",             &cp_clk),
-       CLKDEV_CON_ID("peripheral_clk", &hp_clk),
-
-       /* MSTP */
-       CLKDEV_ICK_ID("lvds.0", "rcar-du-r8a7791", &mstp_clks[MSTP726]),
-       CLKDEV_ICK_ID("du.0", "rcar-du-r8a7791", &mstp_clks[MSTP724]),
-       CLKDEV_ICK_ID("du.1", "rcar-du-r8a7791", &mstp_clks[MSTP723]),
-       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[MSTP206]), /* SCIFB0 */
-       CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]), /* SCIFB1 */
-       CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]), /* SCIFB2 */
-       CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]), /* SCIFA2 */
-       CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]), /* SCIF0 */
-       CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), /* SCIF1 */
-       CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP719]), /* SCIF2 */
-       CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP718]), /* SCIF3 */
-       CLKDEV_DEV_ID("sh-sci.10", &mstp_clks[MSTP715]), /* SCIF4 */
-       CLKDEV_DEV_ID("sh-sci.11", &mstp_clks[MSTP714]), /* SCIF5 */
-       CLKDEV_DEV_ID("sh-sci.12", &mstp_clks[MSTP1106]), /* SCIFA3 */
-       CLKDEV_DEV_ID("sh-sci.13", &mstp_clks[MSTP1107]), /* SCIFA4 */
-       CLKDEV_DEV_ID("sh-sci.14", &mstp_clks[MSTP1108]), /* SCIFA5 */
-       CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
-       CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP312]),
-       CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]),
-       CLKDEV_ICK_ID("fck", "sh-cmt-48-gen2.0", &mstp_clks[MSTP124]),
-       CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]),
-       CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
-       CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]),
-       CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]),
-       CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]),
-       CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]),
-       CLKDEV_DEV_ID("i2c-rcar_gen2.4", &mstp_clks[MSTP927]),
-       CLKDEV_DEV_ID("i2c-rcar_gen2.5", &mstp_clks[MSTP925]),
-       CLKDEV_DEV_ID("r8a7791-ether", &mstp_clks[MSTP813]), /* Ether */
-       CLKDEV_DEV_ID("r8a7791-vin.0", &mstp_clks[MSTP811]),
-       CLKDEV_DEV_ID("r8a7791-vin.1", &mstp_clks[MSTP810]),
-       CLKDEV_DEV_ID("r8a7791-vin.2", &mstp_clks[MSTP809]),
-       CLKDEV_DEV_ID("sata-r8a7791.0", &mstp_clks[MSTP815]),
-       CLKDEV_DEV_ID("sata-r8a7791.1", &mstp_clks[MSTP814]),
-};
-
-#define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31)             \
-       extal_clk.rate  = e * 1000 * 1000;                      \
-       main_clk.parent = m;                                    \
-       SH_CLK_SET_RATIO(&pll1_clk_ratio, p1 / 2, 1);           \
-       if (mode & MD(19))                                      \
-               SH_CLK_SET_RATIO(&pll3_clk_ratio, p31, 1);      \
-       else                                                    \
-               SH_CLK_SET_RATIO(&pll3_clk_ratio, p30, 1)
-
-
-void __init r8a7791_clock_init(void)
-{
-       u32 mode = rcar_gen2_read_mode_pins();
-       int k, ret = 0;
-
-       switch (mode & (MD(14) | MD(13))) {
-       case 0:
-               R8A7791_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
-               break;
-       case MD(13):
-               R8A7791_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66);
-               break;
-       case MD(14):
-               R8A7791_CLOCK_ROOT(26, &extal_div2_clk, 200, 240, 122, 102);
-               break;
-       case MD(13) | MD(14):
-               R8A7791_CLOCK_ROOT(30, &extal_div2_clk, 172, 208, 106, 88);
-               break;
-       }
-
-       if ((mode & (MD(3) | MD(2) | MD(1))) == MD(2))
-               SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 16);
-       else
-               SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 20);
-
-       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_mstp_register(mstp_clks, MSTP_NR);
-
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-       if (!ret)
-               shmobile_clk_init();
-       else
-               goto epanic;
-
-       return;
-
-epanic:
-       panic("failed to setup r8a7791 clocks\n");
-}
index 7071676145c497ae911fd7199b721692c71c2b8e..3bc92f46060e9ce55c793ea6104b6214d84b8bb7 100644 (file)
  * but WITHOUT 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/init.h>
 #include <linux/kernel.h>
index 02a6f45a0b9e1c832d5c5d6bfcb79395a42363a2..6b4c1f313cc987c15ab0028b0f82ed4cde98a0fb 100644 (file)
  * but WITHOUT 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/init.h>
 #include <linux/kernel.h>
index 806f94038cc49a8421f85d305a018113a59009b8..34f056fc375691c22169b4ee26fb4f049e1396e6 100644 (file)
  * 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/export.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-
-#ifdef CONFIG_COMMON_CLK
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include "clock.h"
-
-void __init shmobile_clk_workaround(const struct clk_name *clks,
-                                   int nr_clks, bool enable)
-{
-       const struct clk_name *clkn;
-       struct clk *clk;
-       unsigned int i;
-
-       for (i = 0; i < nr_clks; ++i) {
-               clkn = clks + i;
-               clk = clk_get(NULL, clkn->clk);
-               if (!IS_ERR(clk)) {
-                       clk_register_clkdev(clk, clkn->con_id, clkn->dev_id);
-                       if (enable)
-                               clk_prepare_enable(clk);
-                       clk_put(clk);
-               }
-       }
-}
-
-#else /* CONFIG_COMMON_CLK */
 #include <linux/sh_clk.h>
-#include <linux/export.h>
+
 #include "clock.h"
 #include "common.h"
 
@@ -84,5 +56,3 @@ void __clk_put(struct clk *clk)
 {
 }
 EXPORT_SYMBOL(__clk_put);
-
-#endif /* CONFIG_COMMON_CLK */
index 31b6417463e651f87ab51ec96a9d36a635a50d7b..cf3552ea10192d2a82502c1b0b9fe0b06704376c 100644 (file)
@@ -1,19 +1,6 @@
 #ifndef CLOCK_H
 #define CLOCK_H
 
-#ifdef CONFIG_COMMON_CLK
-/* temporary clock configuration helper for platform devices */
-
-struct clk_name {
-       const char *clk;
-       const char *con_id;
-       const char *dev_id;
-};
-
-void shmobile_clk_workaround(const struct clk_name *clks, int nr_clks,
-                            bool enable);
-
-#else /* CONFIG_COMMON_CLK */
 /* legacy clock implementation */
 
 struct clk;
@@ -52,5 +39,4 @@ do {                  \
        (p)->div = d;   \
 } while (0)
 
-#endif /* CONFIG_COMMON_CLK */
 #endif
index 72087c79ad7b9087b99acbc6c188ba107ab2a5d1..309025efd4cf29df8fecee49e05ddf883e10be04 100644 (file)
@@ -19,11 +19,6 @@ extern void shmobile_boot_scu(void);
 extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
 extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
 extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
-extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
-extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
-                                           struct task_struct *idle);
-extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
-extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
index f2e79f2376e19f6f0a227af94bf2e4fc3be76409..e329ccbd0a6734f1e1c477f63ec878779cbce3d5 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index f45dde701d7b598c0bc7f2544ea438b0ea19327e..69df8bfac1672202073d5096631e1897857f5a5e 100644 (file)
  * but WITHOUT 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/linkage.h>
index e2af00b1bd9dc465eefec06ad84398b41dda1657..1ccf49cb485fd96ae5f96c5d2f85d06f8dc7d02e 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 44457a94897b28708c83cbb12a394ab857b860f1..9e3618028accea72442a4ca8fc1a09b36f267dd2 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 2c06810d3a70e5af46dc8adc06dea0d66d19114f..f483b560b066a78d5dd99b9dd51c0591ab85cc0b 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * SMP support for SoCs with APMU
  *
+ * Copyright (C) 2014  Renesas Electronics Corporation
  * Copyright (C) 2013  Magnus Damm
  *
  * This program is free software; you can redistribute it and/or modify
@@ -22,6 +23,7 @@
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 #include "common.h"
+#include "platsmp-apmu.h"
 
 static struct {
        void __iomem *iomem;
@@ -83,28 +85,15 @@ static void apmu_init_cpu(struct resource *res, int cpu, int bit)
        pr_debug("apmu ioremap %d %d %pr\n", cpu, bit, res);
 }
 
-static struct {
-       struct resource iomem;
-       int cpus[4];
-} apmu_config[] = {
-       {
-               .iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
-               .cpus = { 0, 1, 2, 3 },
-       },
-       {
-               .iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
-               .cpus = { 0x100, 0x101, 0x102, 0x103 },
-       }
-};
-
-static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit))
+static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit),
+                          struct rcar_apmu_config *apmu_config, int num)
 {
        u32 id;
        int k;
        int bit, index;
        bool is_allowed;
 
-       for (k = 0; k < ARRAY_SIZE(apmu_config); k++) {
+       for (k = 0; k < num; k++) {
                /* only enable the cluster that includes the boot CPU */
                is_allowed = false;
                for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
@@ -128,14 +117,16 @@ static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit))
        }
 }
 
-void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus)
+void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
+                                          struct rcar_apmu_config *apmu_config,
+                                          int num)
 {
        /* install boot code shared by all CPUs */
        shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
        shmobile_boot_arg = MPIDR_HWID_BITMASK;
 
        /* perform per-cpu setup */
-       apmu_parse_cfg(apmu_init_cpu);
+       apmu_parse_cfg(apmu_init_cpu, apmu_config, num);
 }
 
 #ifdef CONFIG_SMP
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.h b/arch/arm/mach-shmobile/platsmp-apmu.h
new file mode 100644 (file)
index 0000000..76512c9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * rmobile apmu definition
+ *
+ * Copyright (C) 2014  Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef PLATSMP_APMU_H
+#define PLATSMP_APMU_H
+
+struct rcar_apmu_config {
+       struct resource iomem;
+       int cpus[4];
+};
+
+extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
+                                          struct rcar_apmu_config *apmu_config,
+                                          int num);
+extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
+                                           struct task_struct *idle);
+extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
+
+#endif /* PLATSMP_APMU_H */
index e3f1464482371bb4dd2c07e7b40ab8f8724eeccc..ac2eecd6f5ea5d9f00abe6a3f3c15334cba0b4ff 100644 (file)
 #include "pm-rmobile.h"
 
 #if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM)
-static int r8a7740_pd_a4s_suspend(void)
+static int r8a7740_pd_a3sm_suspend(void)
 {
        /*
-        * The A4S domain contains the CPU core and therefore it should
+        * The A3SM domain contains the CPU core and therefore it should
         * only be turned off if the CPU is not in use.
         */
        return -EBUSY;
@@ -32,29 +32,65 @@ static int r8a7740_pd_a3sp_suspend(void)
        return console_suspend_enabled ? 0 : -EBUSY;
 }
 
+static int r8a7740_pd_d4_suspend(void)
+{
+       /*
+        * The D4 domain contains the Coresight-ETM hardware block and
+        * therefore it should only be turned off if the debug module is
+        * not in use.
+        */
+       return -EBUSY;
+}
+
 static struct rmobile_pm_domain r8a7740_pm_domains[] = {
        {
                .genpd.name     = "A4LC",
                .bit_shift      = 1,
+       }, {
+               .genpd.name     = "A4MP",
+               .bit_shift      = 2,
+       }, {
+               .genpd.name     = "D4",
+               .bit_shift      = 3,
+               .gov            = &pm_domain_always_on_gov,
+               .suspend        = r8a7740_pd_d4_suspend,
+       }, {
+               .genpd.name     = "A4R",
+               .bit_shift      = 5,
+       }, {
+               .genpd.name     = "A3RV",
+               .bit_shift      = 6,
        }, {
                .genpd.name     = "A4S",
                .bit_shift      = 10,
-               .gov            = &pm_domain_always_on_gov,
                .no_debug       = true,
-               .suspend        = r8a7740_pd_a4s_suspend,
        }, {
                .genpd.name     = "A3SP",
                .bit_shift      = 11,
                .gov            = &pm_domain_always_on_gov,
                .no_debug       = true,
                .suspend        = r8a7740_pd_a3sp_suspend,
+       }, {
+               .genpd.name     = "A3SM",
+               .bit_shift      = 12,
+               .gov            = &pm_domain_always_on_gov,
+               .suspend        = r8a7740_pd_a3sm_suspend,
+       }, {
+               .genpd.name     = "A3SG",
+               .bit_shift      = 13,
+       }, {
+               .genpd.name     = "A4SU",
+               .bit_shift      = 20,
        },
 };
 
 void __init r8a7740_init_pm_domains(void)
 {
        rmobile_init_domains(r8a7740_pm_domains, ARRAY_SIZE(r8a7740_pm_domains));
+       pm_genpd_add_subdomain_names("A4R", "A3RV");
        pm_genpd_add_subdomain_names("A4S", "A3SP");
+       pm_genpd_add_subdomain_names("A4S", "A3SM");
+       pm_genpd_add_subdomain_names("A4S", "A3SG");
 }
 #endif /* CONFIG_PM && !CONFIG_ARCH_MULTIPLATFORM */
 
index 5fafd6fcedf790c45564b0c731f4b317a5dba659..70dcd847a86ea360d5a904d4600c27da3b224d3f 100644 (file)
@@ -11,7 +11,6 @@ enum {
 };
 
 void r8a73a4_add_standard_devices(void);
-void r8a73a4_add_dt_devices(void);
 void r8a73a4_clock_init(void);
 void r8a73a4_pinmux_init(void);
 
index f369b4b0863d0bb38a2705e7c2fc12e83438c340..ca7805ad7ea3d64ea24c487f1ff1c5981e0f6e7f 100644 (file)
  * but WITHOUT 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 __ASM_R8A7740_H__
index f4076a50e970a357c8c9dfbbbc07d4f6d61ada25..f64fedb1f2ccb50db8bd88ec7fb78b18523c01d2 100644 (file)
  * but WITHOUT 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 __ASM_R8A7778_H__
 #define __ASM_R8A7778_H__
@@ -71,7 +67,6 @@ extern void r8a7778_add_standard_devices_dt(void);
 extern void r8a7778_add_dt_devices(void);
 
 extern void r8a7778_init_late(void);
-extern void r8a7778_init_delay(void);
 extern void r8a7778_init_irq_dt(void);
 extern void r8a7778_clock_init(void);
 extern void r8a7778_init_irq_extpin(int irlm);
index c1bf7abefa5a6b0b2a0bdb72999e501afbc42f7e..6cf11eb69d10a4aee5ffea9700a0592fe971b766 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef __ASM_R8A7791_H__
 #define __ASM_R8A7791_H__
 
-void r8a7791_add_standard_devices(void);
-void r8a7791_clock_init(void);
-void r8a7791_pinmux_init(void);
 void r8a7791_pm_init(void);
 extern struct smp_operations r8a7791_smp_ops;
 
index b06a9e8f59a5fb7a232f00a747e1715bc23b5a71..aad97be9cbe1b0fabe069136e2e264cc51de8a24 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 4122104359f98d909ae03a923256b479972ff3e0..171174777b6f8d3fa447cd183eafbf3d3b9ff291 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <linux/kernel.h>
index 53f40b70680de9087fa90c0e61ae2711ac8a0fc7..c27682291cbf032c5d02f88495af7af150575cdd 100644 (file)
  * but WITHOUT 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/irq.h>
 #include <linux/kernel.h>
@@ -180,18 +176,13 @@ static struct resource cmt1_resources[] = {
        DEFINE_RES_IRQ(gic_spi(120)),
 };
 
-#define r8a7790_register_cmt(idx)                                      \
+#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))
 
-void __init r8a73a4_add_dt_devices(void)
-{
-       r8a7790_register_cmt(1);
-}
-
 /* DMA */
 static const struct sh_dmae_slave_config dma_slaves[] = {
        {
@@ -282,7 +273,7 @@ static struct resource dma_resources[] = {
 
 void __init r8a73a4_add_standard_devices(void)
 {
-       r8a73a4_add_dt_devices();
+       r8a73a4_register_cmt(1);
        r8a73a4_register_scif(0);
        r8a73a4_register_scif(1);
        r8a73a4_register_scif(2);
index 8894e1b7ab0e65bbf66975ac36ca9b2b5917604f..79ad93dfdae4ee7083f2c2f1351ee863355d20c4 100644 (file)
  * but WITHOUT 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/delay.h>
 #include <linux/dma-mapping.h>
@@ -71,6 +67,7 @@ static struct map_desc r8a7740_io_desc[] __initdata = {
 
 void __init r8a7740_map_io(void)
 {
+       debug_ll_io_init();
        iotable_init(r8a7740_io_desc, ARRAY_SIZE(r8a7740_io_desc));
 }
 
@@ -746,6 +743,12 @@ static void r8a7740_i2c_workaround(struct platform_device *pdev)
 void __init r8a7740_add_standard_devices(void)
 {
        static struct pm_domain_device domain_devices[] __initdata = {
+               { "A4R",  &tmu0_device },
+               { "A4R",  &i2c0_device },
+               { "A4S",  &irqpin0_device },
+               { "A4S",  &irqpin1_device },
+               { "A4S",  &irqpin2_device },
+               { "A4S",  &irqpin3_device },
                { "A3SP", &scif0_device },
                { "A3SP", &scif1_device },
                { "A3SP", &scif2_device },
@@ -756,6 +759,11 @@ void __init r8a7740_add_standard_devices(void)
                { "A3SP", &scif7_device },
                { "A3SP", &scif8_device },
                { "A3SP", &i2c1_device },
+               { "A3SP", &ipmmu_device },
+               { "A3SP", &dma0_device },
+               { "A3SP", &dma1_device },
+               { "A3SP", &dma2_device },
+               { "A3SP", &usb_dma_device },
        };
 
        /* I2C work-around */
index 85fe016d6a872a6233effacc6118f2195d8cdbc8..170bd146ba1796b801f27e0ca74e2cfd79f0c7e8 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <linux/kernel.h>
@@ -292,8 +288,6 @@ void __init r8a7778_add_dt_devices(void)
                l2x0_init(base, 0x00400000, 0xc20f0fff);
        }
 #endif
-
-       r8a7778_register_tmu(0);
 }
 
 /* HPB-DMA */
@@ -501,6 +495,7 @@ static void __init r8a7778_register_hpb_dmae(void)
 void __init r8a7778_add_standard_devices(void)
 {
        r8a7778_add_dt_devices();
+       r8a7778_register_tmu(0);
        r8a7778_register_scif(0);
        r8a7778_register_scif(1);
        r8a7778_register_scif(2);
@@ -572,11 +567,6 @@ void __init r8a7778_init_irq_extpin(int irlm)
                        &irqpin_platform_data, sizeof(irqpin_platform_data));
 }
 
-void __init r8a7778_init_delay(void)
-{
-       shmobile_init_delay();
-}
-
 #ifdef CONFIG_USE_OF
 #define INT2SMSKCR0    0x82288 /* 0xfe782288 */
 #define INT2SMSKCR1    0x8228c /* 0xfe78228c */
@@ -608,7 +598,7 @@ static const char *r8a7778_compat_dt[] __initdata = {
 };
 
 DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
-       .init_early     = r8a7778_init_delay,
+       .init_early     = shmobile_init_delay,
        .init_irq       = r8a7778_init_irq_dt,
        .init_late      = shmobile_init_late,
        .dt_compat      = r8a7778_compat_dt,
index 136078ab9407cc2d2f31b43b213c105e6bbaaa4e..6156d172cf3108d79c44a397931037a53f1c5266 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include "r8a7779.h"
 
 static struct map_desc r8a7779_io_desc[] __initdata = {
-       /* 2M entity map for 0xf0000000 (MPCORE) */
+       /* 2M identity mapping for 0xf0000000 (MPCORE) */
        {
                .virtual        = 0xf0000000,
                .pfn            = __phys_to_pfn(0xf0000000),
                .length         = SZ_2M,
                .type           = MT_DEVICE_NONSHARED
        },
-       /* 16M entity map for 0xfexxxxxx (DMAC-S/HPBREG/INTC2/LRAM/DBSC) */
+       /* 16M identity mapping for 0xfexxxxxx (DMAC-S/HPBREG/INTC2/LRAM/DBSC) */
        {
                .virtual        = 0xfe000000,
                .pfn            = __phys_to_pfn(0xfe000000),
@@ -70,6 +66,7 @@ static struct map_desc r8a7779_io_desc[] __initdata = {
 
 void __init r8a7779_map_io(void)
 {
+       debug_ll_io_init();
        iotable_init(r8a7779_io_desc, ARRAY_SIZE(r8a7779_io_desc));
 }
 
@@ -683,7 +680,7 @@ void __init r8a7779_add_early_devices(void)
 
        /* Early serial console setup is not included here due to
         * memory map collisions. The SCIF serial ports in r8a7779
-        * are difficult to entity map 1:1 due to collision with the
+        * are difficult to identity map 1:1 due to collision with the
         * virtual memory range used by the coherent DMA code on ARM.
         *
         * Anyone wanting to debug early can remove UPF_IOREMAP from
index 877fdeb985d0c240e52eea158eeb16edd1b2ef68..ec7d97dca4de2108cbb3a7bbb3ee5b52dd0d8f95 100644 (file)
  * but WITHOUT 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/irq.h>
index 35d78639244fd805d08d2f44954a5f889379ff6c..ef8eb3af586dfbd9c6733795e58e48f6f534f5b8 100644 (file)
  * but WITHOUT 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/irq.h>
-#include <linux/kernel.h>
-#include <linux/of_platform.h>
-#include <linux/platform_data/gpio-rcar.h>
-#include <linux/platform_data/irq-renesas-irqc.h>
-#include <linux/serial_sci.h>
-#include <linux/sh_timer.h>
+#include <linux/init.h>
 
 #include <asm/mach/arch.h>
 
 #include "common.h"
-#include "irqs.h"
 #include "r8a7791.h"
 #include "rcar-gen2.h"
 
-static const struct resource pfc_resources[] __initconst = {
-       DEFINE_RES_MEM(0xe6060000, 0x250),
-};
-
-#define r8a7791_register_pfc()                                         \
-       platform_device_register_simple("pfc-r8a7791", -1, pfc_resources, \
-                                       ARRAY_SIZE(pfc_resources))
-
-#define R8A7791_GPIO(idx, base, nr)                                    \
-static const struct resource r8a7791_gpio##idx##_resources[] __initconst = { \
-       DEFINE_RES_MEM((base), 0x50),                                   \
-       DEFINE_RES_IRQ(gic_spi(4 + (idx))),                             \
-};                                                                     \
-                                                                       \
-static const struct gpio_rcar_config                                   \
-r8a7791_gpio##idx##_platform_data __initconst = {                      \
-       .gpio_base      = 32 * (idx),                                   \
-       .irq_base       = 0,                                            \
-       .number_of_pins = (nr),                                         \
-       .pctl_name      = "pfc-r8a7791",                                \
-       .has_both_edge_trigger = 1,                                     \
-};                                                                     \
-
-R8A7791_GPIO(0, 0xe6050000, 32);
-R8A7791_GPIO(1, 0xe6051000, 32);
-R8A7791_GPIO(2, 0xe6052000, 32);
-R8A7791_GPIO(3, 0xe6053000, 32);
-R8A7791_GPIO(4, 0xe6054000, 32);
-R8A7791_GPIO(5, 0xe6055000, 32);
-R8A7791_GPIO(6, 0xe6055400, 32);
-R8A7791_GPIO(7, 0xe6055800, 26);
-
-#define r8a7791_register_gpio(idx)                                     \
-       platform_device_register_resndata(NULL, "gpio_rcar", idx,       \
-               r8a7791_gpio##idx##_resources,                          \
-               ARRAY_SIZE(r8a7791_gpio##idx##_resources),              \
-               &r8a7791_gpio##idx##_platform_data,                     \
-               sizeof(r8a7791_gpio##idx##_platform_data))
-
-void __init r8a7791_pinmux_init(void)
-{
-       r8a7791_register_pfc();
-       r8a7791_register_gpio(0);
-       r8a7791_register_gpio(1);
-       r8a7791_register_gpio(2);
-       r8a7791_register_gpio(3);
-       r8a7791_register_gpio(4);
-       r8a7791_register_gpio(5);
-       r8a7791_register_gpio(6);
-       r8a7791_register_gpio(7);
-}
-
-#define __R8A7791_SCIF(scif_type, index, baseaddr, irq)                        \
-static struct plat_sci_port scif##index##_platform_data = {            \
-       .type           = scif_type,                                    \
-       .flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP,              \
-       .scscr          = SCSCR_RE | SCSCR_TE,                          \
-};                                                                     \
-                                                                       \
-static struct resource scif##index##_resources[] = {                   \
-       DEFINE_RES_MEM(baseaddr, 0x100),                                \
-       DEFINE_RES_IRQ(irq),                                            \
-}
-
-#define R8A7791_SCIF(index, baseaddr, irq)                             \
-       __R8A7791_SCIF(PORT_SCIF, index, baseaddr, irq)
-
-#define R8A7791_SCIFA(index, baseaddr, irq)                            \
-       __R8A7791_SCIF(PORT_SCIFA, index, baseaddr, irq)
-
-#define R8A7791_SCIFB(index, baseaddr, irq)                            \
-       __R8A7791_SCIF(PORT_SCIFB, index, baseaddr, irq)
-
-R8A7791_SCIFA(0,  0xe6c40000, gic_spi(144)); /* SCIFA0 */
-R8A7791_SCIFA(1,  0xe6c50000, gic_spi(145)); /* SCIFA1 */
-R8A7791_SCIFB(2,  0xe6c20000, gic_spi(148)); /* SCIFB0 */
-R8A7791_SCIFB(3,  0xe6c30000, gic_spi(149)); /* SCIFB1 */
-R8A7791_SCIFB(4,  0xe6ce0000, gic_spi(150)); /* SCIFB2 */
-R8A7791_SCIFA(5,  0xe6c60000, gic_spi(151)); /* SCIFA2 */
-R8A7791_SCIF(6,   0xe6e60000, gic_spi(152)); /* SCIF0 */
-R8A7791_SCIF(7,   0xe6e68000, gic_spi(153)); /* SCIF1 */
-R8A7791_SCIF(8,   0xe6e58000, gic_spi(22)); /* SCIF2 */
-R8A7791_SCIF(9,   0xe6ea8000, gic_spi(23)); /* SCIF3 */
-R8A7791_SCIF(10,  0xe6ee0000, gic_spi(24)); /* SCIF4 */
-R8A7791_SCIF(11,  0xe6ee8000, gic_spi(25)); /* SCIF5 */
-R8A7791_SCIFA(12, 0xe6c70000, gic_spi(29)); /* SCIFA3 */
-R8A7791_SCIFA(13, 0xe6c78000, gic_spi(30)); /* SCIFA4 */
-R8A7791_SCIFA(14, 0xe6c80000, gic_spi(31)); /* SCIFA5 */
-
-#define r8a7791_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 struct sh_timer_config cmt0_platform_data = {
-       .channels_mask = 0x60,
-};
-
-static struct resource cmt0_resources[] = {
-       DEFINE_RES_MEM(0xffca0000, 0x1004),
-       DEFINE_RES_IRQ(gic_spi(142)),
-};
-
-#define r8a7791_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))
-
-static struct renesas_irqc_config irqc0_data = {
-       .irq_base = irq_pin(0), /* IRQ0 -> IRQ9 */
-};
-
-static 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(12)), /* IRQ4 */
-       DEFINE_RES_IRQ(gic_spi(13)), /* IRQ5 */
-       DEFINE_RES_IRQ(gic_spi(14)), /* IRQ6 */
-       DEFINE_RES_IRQ(gic_spi(15)), /* IRQ7 */
-       DEFINE_RES_IRQ(gic_spi(16)), /* IRQ8 */
-       DEFINE_RES_IRQ(gic_spi(17)), /* IRQ9 */
-};
-
-#define r8a7791_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))
-
-static const struct resource thermal_resources[] __initconst = {
-       DEFINE_RES_MEM(0xe61f0000, 0x14),
-       DEFINE_RES_MEM(0xe61f0100, 0x38),
-       DEFINE_RES_IRQ(gic_spi(69)),
-};
-
-#define r8a7791_register_thermal()                                     \
-       platform_device_register_simple("rcar_thermal", -1,             \
-                                       thermal_resources,              \
-                                       ARRAY_SIZE(thermal_resources))
-
-void __init r8a7791_add_standard_devices(void)
-{
-       r8a7791_register_scif(0);
-       r8a7791_register_scif(1);
-       r8a7791_register_scif(2);
-       r8a7791_register_scif(3);
-       r8a7791_register_scif(4);
-       r8a7791_register_scif(5);
-       r8a7791_register_scif(6);
-       r8a7791_register_scif(7);
-       r8a7791_register_scif(8);
-       r8a7791_register_scif(9);
-       r8a7791_register_scif(10);
-       r8a7791_register_scif(11);
-       r8a7791_register_scif(12);
-       r8a7791_register_scif(13);
-       r8a7791_register_scif(14);
-       r8a7791_register_cmt(0);
-       r8a7791_register_irqc(0);
-       r8a7791_register_thermal();
-}
-
-#ifdef CONFIG_USE_OF
 static const char *r8a7791_boards_compat_dt[] __initdata = {
        "renesas,r8a7791",
        NULL,
@@ -218,4 +36,3 @@ DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
        .reserve        = rcar_gen2_reserve,
        .dt_compat      = r8a7791_boards_compat_dt,
 MACHINE_END
-#endif /* CONFIG_USE_OF */
index 42d5b43089235375e1a1d75b440a32d8940ac1ed..3dd6edd9bd1d3dfe5b6bb7787e4d672c1a6f63be 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2013  Renesas Solutions Corp.
  * Copyright (C) 2013  Magnus Damm
+ * Copyright (C) 2014  Ulrich Hecht
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * but WITHOUT 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/clk/shmobile.h>
@@ -24,6 +21,7 @@
 #include <linux/dma-contiguous.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <asm/mach/arch.h>
 #include "common.h"
@@ -54,37 +52,61 @@ void __init rcar_gen2_timer_init(void)
 {
 #if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK)
        u32 mode = rcar_gen2_read_mode_pins();
+       bool is_e2 = (bool)of_find_compatible_node(NULL, NULL,
+               "renesas,r8a7794");
 #endif
 #ifdef CONFIG_ARM_ARCH_TIMER
        void __iomem *base;
        int extal_mhz = 0;
        u32 freq;
 
-       /* At Linux boot time the r8a7790 arch timer comes up
-        * with the counter disabled. Moreover, it may also report
-        * a potentially incorrect fixed 13 MHz frequency. To be
-        * correct these registers need to be updated to use the
-        * frequency EXTAL / 2 which can be determined by the MD pins.
-        */
-
-       switch (mode & (MD(14) | MD(13))) {
-       case 0:
-               extal_mhz = 15;
-               break;
-       case MD(13):
-               extal_mhz = 20;
-               break;
-       case MD(14):
-               extal_mhz = 26;
-               break;
-       case MD(13) | MD(14):
-               extal_mhz = 30;
-               break;
+       if (is_e2) {
+               freq = 260000000 / 8;   /* ZS / 8 */
+               /* CNTVOFF has to be initialized either from non-secure
+                * Hypervisor mode or secure Monitor mode with SCR.NS==1.
+                * If TrustZone is enabled then it should be handled by the
+                * secure code.
+                */
+               asm volatile(
+               "       cps     0x16\n"
+               "       mrc     p15, 0, r1, c1, c1, 0\n"
+               "       orr     r0, r1, #1\n"
+               "       mcr     p15, 0, r0, c1, c1, 0\n"
+               "       isb\n"
+               "       mov     r0, #0\n"
+               "       mcrr    p15, 4, r0, r0, c14\n"
+               "       isb\n"
+               "       mcr     p15, 0, r1, c1, c1, 0\n"
+               "       isb\n"
+               "       cps     0x13\n"
+                       : : : "r0", "r1");
+       } else {
+               /* At Linux boot time the r8a7790 arch timer comes up
+                * with the counter disabled. Moreover, it may also report
+                * a potentially incorrect fixed 13 MHz frequency. To be
+                * correct these registers need to be updated to use the
+                * frequency EXTAL / 2 which can be determined by the MD pins.
+                */
+
+               switch (mode & (MD(14) | MD(13))) {
+               case 0:
+                       extal_mhz = 15;
+                       break;
+               case MD(13):
+                       extal_mhz = 20;
+                       break;
+               case MD(14):
+                       extal_mhz = 26;
+                       break;
+               case MD(13) | MD(14):
+                       extal_mhz = 30;
+                       break;
+               }
+
+               /* The arch timer frequency equals EXTAL / 2 */
+               freq = extal_mhz * (1000000 / 2);
        }
 
-       /* The arch timer frequency equals EXTAL / 2 */
-       freq = extal_mhz * (1000000 / 2);
-
        /* Remap "armgcnt address map" space */
        base = ioremap(0xe6080000, PAGE_SIZE);
 
index d646c8d12423a600332f5e5876f75445426fdca3..458a2cfad4173ca74d2226a8037a299cdf9b971f 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -47,7 +43,7 @@
 #include "sh7372.h"
 
 static struct map_desc sh7372_io_desc[] __initdata = {
-       /* create a 1:1 entity map for 0xe6xxxxxx
+       /* create a 1:1 identity mapping for 0xe6xxxxxx
         * used by CPGA, INTC and PFC.
         */
        {
@@ -60,6 +56,7 @@ static struct map_desc sh7372_io_desc[] __initdata = {
 
 void __init sh7372_map_io(void)
 {
+       debug_ll_io_init();
        iotable_init(sh7372_io_desc, ARRAY_SIZE(sh7372_io_desc));
 }
 
@@ -1012,6 +1009,7 @@ DT_MACHINE_START(SH7372_DT, "Generic SH7372 (Flattened Device Tree)")
        .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
 
index b7bd8e50966879608cde0e5c152cefb12185d9f1..93ebe3430bfe707ac234b35f37deb54a1998a531 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -26,6 +22,7 @@
 #include <linux/of_platform.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/i2c/i2c-sh_mobile.h>
 #include <linux/io.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
@@ -45,7 +42,7 @@
 #include "sh73a0.h"
 
 static struct map_desc sh73a0_io_desc[] __initdata = {
-       /* create a 1:1 entity map for 0xe6xxxxxx
+       /* create a 1:1 identity mapping for 0xe6xxxxxx
         * used by CPGA, INTC and PFC.
         */
        {
@@ -58,6 +55,7 @@ static struct map_desc sh73a0_io_desc[] __initdata = {
 
 void __init sh73a0_map_io(void)
 {
+       debug_ll_io_init();
        iotable_init(sh73a0_io_desc, ARRAY_SIZE(sh73a0_io_desc));
 }
 
@@ -192,11 +190,18 @@ static struct resource i2c4_resources[] = {
        },
 };
 
+static struct i2c_sh_mobile_platform_data i2c_platform_data = {
+       .clks_per_count = 2,
+};
+
 static struct platform_device i2c0_device = {
        .name           = "i2c-sh_mobile",
        .id             = 0,
        .resource       = i2c0_resources,
        .num_resources  = ARRAY_SIZE(i2c0_resources),
+       .dev            = {
+               .platform_data  = &i2c_platform_data,
+       },
 };
 
 static struct platform_device i2c1_device = {
@@ -204,6 +209,9 @@ static struct platform_device i2c1_device = {
        .id             = 1,
        .resource       = i2c1_resources,
        .num_resources  = ARRAY_SIZE(i2c1_resources),
+       .dev            = {
+               .platform_data  = &i2c_platform_data,
+       },
 };
 
 static struct platform_device i2c2_device = {
@@ -211,6 +219,9 @@ static struct platform_device i2c2_device = {
        .id             = 2,
        .resource       = i2c2_resources,
        .num_resources  = ARRAY_SIZE(i2c2_resources),
+       .dev            = {
+               .platform_data  = &i2c_platform_data,
+       },
 };
 
 static struct platform_device i2c3_device = {
@@ -218,6 +229,9 @@ static struct platform_device i2c3_device = {
        .id             = 3,
        .resource       = i2c3_resources,
        .num_resources  = ARRAY_SIZE(i2c3_resources),
+       .dev            = {
+               .platform_data  = &i2c_platform_data,
+       },
 };
 
 static struct platform_device i2c4_device = {
@@ -225,6 +239,9 @@ static struct platform_device i2c4_device = {
        .id             = 4,
        .resource       = i2c4_resources,
        .num_resources  = ARRAY_SIZE(i2c4_resources),
+       .dev            = {
+               .platform_data  = &i2c_platform_data,
+       },
 };
 
 static const struct sh_dmae_slave_config sh73a0_dmae_slaves[] = {
@@ -740,17 +757,12 @@ void __init sh73a0_add_standard_devices(void)
                            ARRAY_SIZE(sh73a0_late_devices));
 }
 
-void __init sh73a0_init_delay(void)
-{
-       shmobile_init_delay();
-}
-
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak sh73a0_register_twd(void) { }
 
 void __init sh73a0_earlytimer_init(void)
 {
-       sh73a0_init_delay();
+       shmobile_init_delay();
        sh73a0_clock_init();
        shmobile_earlytimer_init();
        sh73a0_register_twd();
@@ -775,6 +787,13 @@ void __init sh73a0_add_standard_devices_dt(void)
        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,
@@ -783,9 +802,10 @@ static const char *sh73a0_boards_compat_dt[] __initdata = {
 DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
        .smp            = smp_ops(sh73a0_smp_ops),
        .map_io         = sh73a0_map_io,
-       .init_early     = sh73a0_init_delay,
+       .init_early     = shmobile_init_delay,
        .init_machine   = sh73a0_add_standard_devices_dt,
        .init_late      = shmobile_init_late,
+       .restart        = sh73a0_restart,
        .dt_compat      = sh73a0_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
index 359b582dc270d6a96408b145a063f7ebf12b6a3c..f037c64b14fc076749933eb2cef291500e56ee0a 100644 (file)
@@ -71,7 +71,6 @@ enum {
 #define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
 #define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
 
-extern void sh73a0_init_delay(void);
 extern void sh73a0_init_irq(void);
 extern void sh73a0_init_irq_dt(void);
 extern void sh73a0_map_io(void);
index 9782862899e81f1895ae0f1312cdfa5623d58914..146b8de16432fe3ca573243ded57e8dc8208218d 100644 (file)
  * but WITHOUT 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/linkage.h>
index 6ff1df1df9a752c313514284a09a0e747e906c4c..baff3b5efed8c31b5e1c5cd18e21e4348dcc1360 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 3100e355c3fde4e589aa015a50a68e7b1f57da85..3f761f8390430d61fa7753511412d06827eaf284 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 2311694636e123a984fe8f1480d2a9efb7c9a412..9c3da1345b8b7eb45b778eb77e9a81cfed7f8cb4 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/smp_plat.h>
 
 #include "common.h"
+#include "platsmp-apmu.h"
 #include "pm-rcar.h"
 #include "r8a7790.h"
 
@@ -34,10 +35,23 @@ static struct rcar_sysc_ch r8a7790_ca7_scu = {
        .isr_bit = 21, /* CA7-SCU */
 };
 
+static struct rcar_apmu_config r8a7790_apmu_config[] = {
+       {
+               .iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
+               .cpus = { 0, 1, 2, 3 },
+       },
+       {
+               .iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
+               .cpus = { 0x100, 0x0101, 0x102, 0x103 },
+       }
+};
+
 static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
 {
        /* let APMU code install data related to shmobile_boot_vector */
-       shmobile_smp_apmu_prepare_cpus(max_cpus);
+       shmobile_smp_apmu_prepare_cpus(max_cpus,
+                                      r8a7790_apmu_config,
+                                      ARRAY_SIZE(r8a7790_apmu_config));
 
        /* turn on power to SCU */
        r8a7790_pm_init();
index f743386166fb72608e69049610f52c9b96a93103..7e49e0a52e32a168de45abd40bcb174cae04989c 100644 (file)
 #include <asm/smp_plat.h>
 
 #include "common.h"
+#include "platsmp-apmu.h"
 #include "r8a7791.h"
 #include "rcar-gen2.h"
 
+static struct rcar_apmu_config r8a7791_apmu_config[] = {
+       {
+               .iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
+               .cpus = { 0, 1 },
+       }
+};
+
 static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
 {
        /* let APMU code install data related to shmobile_boot_vector */
-       shmobile_smp_apmu_prepare_cpus(max_cpus);
+       shmobile_smp_apmu_prepare_cpus(max_cpus,
+                                      r8a7791_apmu_config,
+                                      ARRAY_SIZE(r8a7791_apmu_config));
 
        r8a7791_pm_init();
 }
index 22d8f87b23e9006b206a3c04fe9720a384926c81..c16dbfe9836c527de5116c5620434ffb1ced2ef6 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
index 87c6be1e79bd989d24c64ccfc4a95342be5ddc4d..f1d027aa7a81ac3361401380553771bdb37d47d2 100644 (file)
  * but WITHOUT 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/platform_device.h>
 #include <linux/clocksource.h>
@@ -45,6 +40,7 @@ void __init shmobile_init_delay(void)
        struct device_node *np, *cpus;
        bool is_a7_a8_a9 = false;
        bool is_a15 = false;
+       bool has_arch_timer = false;
        u32 max_freq = 0;
 
        cpus = of_find_node_by_path("/cpus");
@@ -57,12 +53,16 @@ void __init shmobile_init_delay(void)
                if (!of_property_read_u32(np, "clock-frequency", &freq))
                        max_freq = max(max_freq, freq);
 
-               if (of_device_is_compatible(np, "arm,cortex-a7") ||
-                   of_device_is_compatible(np, "arm,cortex-a8") ||
-                   of_device_is_compatible(np, "arm,cortex-a9"))
+               if (of_device_is_compatible(np, "arm,cortex-a8") ||
+                   of_device_is_compatible(np, "arm,cortex-a9")) {
                        is_a7_a8_a9 = true;
-               else if (of_device_is_compatible(np, "arm,cortex-a15"))
+               } else if (of_device_is_compatible(np, "arm,cortex-a7")) {
+                       is_a7_a8_a9 = true;
+                       has_arch_timer = true;
+               } else if (of_device_is_compatible(np, "arm,cortex-a15")) {
                        is_a15 = true;
+                       has_arch_timer = true;
+               }
        }
 
        of_node_put(cpus);
@@ -70,10 +70,12 @@ void __init shmobile_init_delay(void)
        if (!max_freq)
                return;
 
-       if (is_a7_a8_a9)
-               shmobile_setup_delay_hz(max_freq, 1, 3);
-       else if (is_a15 && !IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
-               shmobile_setup_delay_hz(max_freq, 2, 4);
+       if (!has_arch_timer || !IS_ENABLED(CONFIG_ARM_ARCH_TIMER)) {
+               if (is_a7_a8_a9)
+                       shmobile_setup_delay_hz(max_freq, 1, 3);
+               else if (is_a15)
+                       shmobile_setup_delay_hz(max_freq, 2, 4);
+       }
 }
 
 static void __init shmobile_late_time_init(void)
index 572b8f719ffbf040c6d6e5f4b5274f21e89045db..483cb467bf65a13d1f414a88c0233b5e46e184d1 100644 (file)
@@ -21,6 +21,7 @@
 #define __MACH_CORE_H
 
 #define SOCFPGA_RSTMGR_CTRL    0x04
+#define SOCFPGA_RSTMGR_MODMPURST       0x10
 #define SOCFPGA_RSTMGR_MODPERRST       0x14
 #define SOCFPGA_RSTMGR_BRGMODRST       0x1c
 
@@ -28,6 +29,8 @@
 #define RSTMGR_CTRL_SWCOLDRSTREQ       0x1     /* Cold Reset */
 #define RSTMGR_CTRL_SWWARMRSTREQ       0x2     /* Warm Reset */
 
+#define RSTMGR_MPUMODRST_CPU1          0x2     /* CPU1 Reset */
+
 extern void socfpga_secondary_startup(void);
 extern void __iomem *socfpga_scu_base_addr;
 
@@ -40,7 +43,7 @@ extern void __iomem *rst_manager_base_addr;
 extern struct smp_operations socfpga_smp_ops;
 extern char secondary_trampoline, secondary_trampoline_end;
 
-extern unsigned long cpu1start_addr;
+extern unsigned long socfpga_cpu1start_addr;
 
 #define SOCFPGA_SCU_VIRT_BASE   0xfffec000
 
index 95c115d8b5eee5407feb99ce996f5793ceb34747..f65ea0af4af37dbdce42f9bf1af740b4feeb9e22 100644 (file)
@@ -9,21 +9,26 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <asm/memory.h>
 
        .arch   armv7-a
 
 ENTRY(secondary_trampoline)
-       movw    r2, #:lower16:cpu1start_addr
-       movt  r2, #:upper16:cpu1start_addr
-
-       /* The socfpga VT cannot handle a 0xC0000000 page offset when loading
-               the cpu1start_addr, we bit clear it. Tested on HW and VT. */
-       bic     r2, r2, #0x40000000
-
-       ldr     r0, [r2]
-       ldr     r1, [r0]
-       bx      r1
+       /* CPU1 will always fetch from 0x0 when it is brought out of reset.
+        * Thus, we can just subtract the PAGE_OFFSET to get the physical
+        * address of &cpu1start_addr. This would not work for platforms
+        * where the physical memory does not start at 0x0.
+        */
+       adr     r0, 1f
+       ldmia   r0, {r1, r2}
+       sub     r2, r2, #PAGE_OFFSET
+       ldr     r3, [r2]
+       ldr     r4, [r3]
+       bx      r4
 
+       .align
+1:     .long   .
+       .long   socfpga_cpu1start_addr
 ENTRY(secondary_trampoline_end)
 
 ENTRY(socfpga_secondary_startup)
index 5356a72bc8ce901fdf82d0626f6ca59c9bfa85bf..c64d89b7c0ca80c6a61f3d8e1c7439756bb83ee2 100644 (file)
@@ -33,18 +33,22 @@ static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
 
-       if (cpu1start_addr) {
+       if (socfpga_cpu1start_addr) {
+               /* This will put CPU #1 into reset. */
+               writel(RSTMGR_MPUMODRST_CPU1,
+                      rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
+
                memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
 
-               __raw_writel(virt_to_phys(socfpga_secondary_startup),
-                       (sys_manager_base_addr + (cpu1start_addr & 0x000000ff)));
+               writel(virt_to_phys(socfpga_secondary_startup),
+                      sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff));
 
                flush_cache_all();
                smp_wmb();
                outer_clean_range(0, trampoline_size);
 
-               /* This will release CPU #1 out of reset.*/
-               __raw_writel(0, rst_manager_base_addr + 0x10);
+               /* This will release CPU #1 out of reset. */
+               writel(0, rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
        }
 
        return 0;
@@ -86,10 +90,9 @@ static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
  */
 static void socfpga_cpu_die(unsigned int cpu)
 {
-       cpu_do_idle();
-
-       /* We should have never returned from idle */
-       panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+       /* Do WFI. If we wake up early, go back into WFI */
+       while (1)
+               cpu_do_idle();
 }
 
 struct smp_operations socfpga_smp_ops __initdata = {
index adbf38314ca8c47aac8a52dd70ce68c46a0e9647..383d61e138af1e9dfeee1ccac39b6adb42f74236 100644 (file)
@@ -29,7 +29,7 @@
 void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
 void __iomem *sys_manager_base_addr;
 void __iomem *rst_manager_base_addr;
-unsigned long cpu1start_addr;
+unsigned long socfpga_cpu1start_addr;
 
 static struct map_desc scu_io_desc __initdata = {
        .virtual        = SOCFPGA_SCU_VIRT_BASE,
@@ -70,7 +70,7 @@ void __init socfpga_sysmgr_init(void)
        np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
 
        if (of_property_read_u32(np, "cpu1-start-addr",
-                       (u32 *) &cpu1start_addr))
+                       (u32 *) &socfpga_cpu1start_addr))
                pr_err("SMP: Need cpu1-start-addr in device tree.\n");
 
        sys_manager_base_addr = of_iomap(np, 0);
index 878e9ec97d0fc810249628533c3ff4acc2e11d15..8825bc9e2553057145a9d2839bf4001e71960bd8 100644 (file)
@@ -42,4 +42,14 @@ config SOC_STIH416
          and other digital audio/video applications using Flattened Device
          Trees.
 
+config SOC_STIH407
+       bool "STiH407 STMicroelectronics Consumer Electronics family"
+       default y
+       select STIH407_RESET
+       help
+         This enables support for STMicroelectronics Digital Consumer
+         Electronics family StiH407 parts, targetted at set-top-box
+         and other digital audio/video applications using Flattened Device
+         Trees.
+
 endif
index 1aaa1e15ef70193b93f8afa402980957ad83d3ad..a77604fbaf257acef8e2c546dd267a5e2ef501af 100644 (file)
@@ -42,4 +42,11 @@ config MACH_SUN8I
        select MFD_SUN6I_PRCM
        select RESET_CONTROLLER
 
+config MACH_SUN9I
+       bool "Allwinner (sun9i) SoCs support"
+       default ARCH_SUNXI
+       select ARCH_HAS_RESET_CONTROLLER
+       select ARM_GIC
+       select RESET_CONTROLLER
+
 endif
index c53077bb8c3fb3ff07c79f3c3bfeca781a5c3cb1..e44d028555a4978b134d4ee5c7199c120d5f2d57 100644 (file)
@@ -116,7 +116,7 @@ static int sun6i_smp_boot_secondary(unsigned int cpu,
        return 0;
 }
 
-struct smp_operations sun6i_smp_ops __initdata = {
+static struct smp_operations sun6i_smp_ops __initdata = {
        .smp_prepare_cpus       = sun6i_smp_prepare_cpus,
        .smp_boot_secondary     = sun6i_smp_boot_secondary,
 };
index d7598aeed803c149c9b5a8dda30fc5363e6c7190..1f986758784a1d0673ce2d4206bb1e57b97c75f4 100644 (file)
@@ -63,3 +63,12 @@ static const char * const sun8i_board_dt_compat[] = {
 DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family")
        .dt_compat      = sun8i_board_dt_compat,
 MACHINE_END
+
+static const char * const sun9i_board_dt_compat[] = {
+       "allwinner,sun9i-a80",
+       NULL,
+};
+
+DT_MACHINE_START(SUN9I_DT, "Allwinner sun9i Family")
+       .dt_compat      = sun9i_board_dt_compat,
+MACHINE_END
index 095399618ca53e04011c529698373eb31b55350a..d0be9a1ef6b8c136bd873b19242ed4421df3673e 100644 (file)
@@ -2,6 +2,7 @@ menuconfig ARCH_TEGRA
        bool "NVIDIA Tegra" if ARCH_MULTI_V7
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
+       select ARM_AMBA
        select ARM_GIC
        select CLKSRC_MMIO
        select HAVE_ARM_SCU if SMP
@@ -59,12 +60,4 @@ config ARCH_TEGRA_124_SOC
          Support for NVIDIA Tegra T124 processor family, based on the
          ARM CortexA15MP CPU
 
-config TEGRA_AHB
-       bool "Enable AHB driver for NVIDIA Tegra SoCs"
-       default y
-       help
-         Adds AHB configuration functionality for NVIDIA Tegra SoCs,
-         which controls AHB bus master arbitration and some
-         performance parameters(priority, prefech size).
-
 endif
index e3ebdce3e71f62c48099191bf18cb00892c05aca..425b6c8f0cb03eb7a65c3dda5380f2a0c03ae18c 100644 (file)
@@ -49,7 +49,7 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
        call_firmware_op(prepare_idle);
 
        /* Do suspend by ourselves if the firmware does not implement it */
-       if (call_firmware_op(do_idle) == -ENOSYS)
+       if (call_firmware_op(do_idle, 0) == -ENOSYS)
                cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
index da7be13aecce3cd8d12de9b64c10b6e3facf252b..ab95f5391a2b631e5cace17bbb176766e7d410bf 100644 (file)
@@ -99,42 +99,42 @@ static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
 
 static void tegra_mask(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_CLR);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR);
 }
 
 static void tegra_unmask(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_SET);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET);
 }
 
 static void tegra_ack(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
 }
 
 static void tegra_eoi(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
 }
 
 static int tegra_retrigger(struct irq_data *d)
 {
-       if (d->irq < FIRST_LEGACY_IRQ)
+       if (d->hwirq < FIRST_LEGACY_IRQ)
                return 0;
 
-       tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_SET);
+       tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET);
 
        return 1;
 }
@@ -142,7 +142,7 @@ static int tegra_retrigger(struct irq_data *d)
 #ifdef CONFIG_PM_SLEEP
 static int tegra_set_wake(struct irq_data *d, unsigned int enable)
 {
-       u32 irq = d->irq;
+       u32 irq = d->hwirq;
        u32 index, mask;
 
        if (irq < FIRST_LEGACY_IRQ ||
index 7b2baab0f0bd38751bd4065e67a47b93ac010668..71be4af5e975bec078508d1ea920568edf11b289 100644 (file)
@@ -51,6 +51,7 @@ ENTRY(tegra_resume)
  THUMB(        it      ne )
        bne     cpu_resume                      @ no
 
+       tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
        /* Are we on Tegra20? */
        cmp     r6, #TEGRA20
        beq     1f                              @ Yes
index ec0283cf9a32498617feacce6170a9a3c69c465c..131996805690849a187561ab06014ae9095bd32e 100644 (file)
@@ -80,8 +80,8 @@ static ssize_t dummy_looptest(struct device *dev,
                "in 8bit mode\n");
        status = spi_w8r8(spi, 0xAA);
        if (status < 0)
-               pr_warning("Siple test 1: FAILURE: spi_write_then_read "
-                          "failed with status %d\n", status);
+               pr_warn("Simple test 1: FAILURE: spi_write_then_read failed with status %d\n",
+                       status);
        else
                pr_info("Simple test 1: SUCCESS!\n");
 
@@ -89,8 +89,8 @@ static ssize_t dummy_looptest(struct device *dev,
                "in 8bit mode (full FIFO)\n");
        status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8);
        if (status < 0)
-               pr_warning("Simple test 2: FAILURE: spi_write_then_read() "
-                          "failed with status %d\n", status);
+               pr_warn("Simple test 2: FAILURE: spi_write_then_read() failed with status %d\n",
+                       status);
        else
                pr_info("Simple test 2: SUCCESS!\n");
 
@@ -98,8 +98,8 @@ static ssize_t dummy_looptest(struct device *dev,
                "in 8bit mode (see if we overflow FIFO)\n");
        status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14);
        if (status < 0)
-               pr_warning("Simple test 3: FAILURE: failed with status %d "
-                          "(probably FIFO overrun)\n", status);
+               pr_warn("Simple test 3: FAILURE: failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 3: SUCCESS!\n");
 
@@ -107,14 +107,14 @@ static ssize_t dummy_looptest(struct device *dev,
                "bytes garbage with spi_read() in 8bit mode\n");
        status = spi_write(spi, &txbuf[0], 8);
        if (status < 0)
-               pr_warning("Simple test 4 step 1: FAILURE: spi_write() "
-                          "failed with status %d\n", status);
+               pr_warn("Simple test 4 step 1: FAILURE: spi_write() failed with status %d\n",
+                       status);
        else
                pr_info("Simple test 4 step 1: SUCCESS!\n");
        status = spi_read(spi, &rxbuf[0], 8);
        if (status < 0)
-               pr_warning("Simple test 4 step 2: FAILURE: spi_read() "
-                          "failed with status %d\n", status);
+               pr_warn("Simple test 4 step 2: FAILURE: spi_read() failed with status %d\n",
+                       status);
        else
                pr_info("Simple test 4 step 2: SUCCESS!\n");
 
@@ -122,16 +122,14 @@ static ssize_t dummy_looptest(struct device *dev,
                "14 bytes garbage with spi_read() in 8bit mode\n");
        status = spi_write(spi, &txbuf[0], 14);
        if (status < 0)
-               pr_warning("Simple test 5 step 1: FAILURE: spi_write() "
-                          "failed with status %d (probably FIFO overrun)\n",
-                          status);
+               pr_warn("Simple test 5 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 5 step 1: SUCCESS!\n");
        status = spi_read(spi, &rxbuf[0], 14);
        if (status < 0)
-               pr_warning("Simple test 5 step 2: FAILURE: spi_read() "
-                          "failed with status %d (probably FIFO overrun)\n",
-                          status);
+               pr_warn("Simple test 5 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 5: SUCCESS!\n");
 
@@ -140,16 +138,14 @@ static ssize_t dummy_looptest(struct device *dev,
                DMA_TEST_SIZE, DMA_TEST_SIZE);
        status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE);
        if (status < 0)
-               pr_warning("Simple test 6 step 1: FAILURE: spi_write() "
-                          "failed with status %d (probably FIFO overrun)\n",
-                          status);
+               pr_warn("Simple test 6 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 6 step 1: SUCCESS!\n");
        status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE);
        if (status < 0)
-               pr_warning("Simple test 6 step 2: FAILURE: spi_read() "
-                          "failed with status %d (probably FIFO overrun)\n",
-                          status);
+               pr_warn("Simple test 6 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 6: SUCCESS!\n");
 
@@ -169,18 +165,17 @@ static ssize_t dummy_looptest(struct device *dev,
                pr_info("Simple test 7: SUCCESS! (expected failure with "
                        "status EIO)\n");
        else if (status < 0)
-               pr_warning("Siple test 7: FAILURE: spi_write_then_read "
-                          "failed with status %d\n", status);
+               pr_warn("Simple test 7: FAILURE: spi_write_then_read failed with status %d\n",
+                       status);
        else
-               pr_warning("Siple test 7: FAILURE: spi_write_then_read "
-                          "succeeded but it was expected to fail!\n");
+               pr_warn("Simple test 7: FAILURE: spi_write_then_read succeeded but it was expected to fail!\n");
 
        pr_info("Simple test 8: write 8 bytes, read back 8 bytes garbage "
                "in 16bit mode (full FIFO)\n");
        status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8);
        if (status < 0)
-               pr_warning("Simple test 8: FAILURE: spi_write_then_read() "
-                          "failed with status %d\n", status);
+               pr_warn("Simple test 8: FAILURE: spi_write_then_read() failed with status %d\n",
+                       status);
        else
                pr_info("Simple test 8: SUCCESS!\n");
 
@@ -188,8 +183,8 @@ static ssize_t dummy_looptest(struct device *dev,
                "in 16bit mode (see if we overflow FIFO)\n");
        status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14);
        if (status < 0)
-               pr_warning("Simple test 9: FAILURE: failed with status %d "
-                          "(probably FIFO overrun)\n", status);
+               pr_warn("Simple test 9: FAILURE: failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 9: SUCCESS!\n");
 
@@ -198,17 +193,15 @@ static ssize_t dummy_looptest(struct device *dev,
               DMA_TEST_SIZE, DMA_TEST_SIZE);
        status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE);
        if (status < 0)
-               pr_warning("Simple test 10 step 1: FAILURE: spi_write() "
-                          "failed with status %d (probably FIFO overrun)\n",
-                          status);
+               pr_warn("Simple test 10 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 10 step 1: SUCCESS!\n");
 
        status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE);
        if (status < 0)
-               pr_warning("Simple test 10 step 2: FAILURE: spi_read() "
-                          "failed with status %d (probably FIFO overrun)\n",
-                          status);
+               pr_warn("Simple test 10 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n",
+                       status);
        else
                pr_info("Simple test 10: SUCCESS!\n");
 
index 699e8601dbf0bb935e2edb5887c998a1a1228242..c9ac19b24e5a5da7bbfbf7aa7afcaff34f067e96 100644 (file)
@@ -32,6 +32,7 @@ config UX500_SOC_DB8500
        select PINCTRL_AB8540
        select REGULATOR
        select REGULATOR_DB8500_PRCMU
+       select PM_GENERIC_DOMAINS if PM
 
 config MACH_MOP500
        bool "U8500 Development platform, MOP500 versions"
index 9741de956b3e98e10ec43d5c4cd1bff3f939ff9c..4418a5078833465d26b7bf01d2cd55c33f58bce1 100644 (file)
@@ -9,5 +9,6 @@ obj-$(CONFIG_MACH_MOP500)       += board-mop500-regulators.o \
                                board-mop500-audio.o
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)      += hotplug.o
+obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
 
 CFLAGS_hotplug.o               += -march=armv7-a
index b80a9a2e356eca6a5f76459a8cce58195523d143..2cb587b50905af29edbfb914a61ad4e4c9615035 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/platform_data/arm-ux500-pm.h>
 
 #include "db8500-regs.h"
+#include "pm_domains.h"
 
 /* ARM WFI Standby signal register */
 #define PRCM_ARM_WFI_STANDBY    (prcmu_base + 0x130)
@@ -191,4 +192,7 @@ void __init ux500_pm_init(u32 phy_base, u32 size)
 
        /* Set up ux500 suspend callbacks. */
        suspend_set_ops(UX500_SUSPEND_OPS);
+
+       /* Initialize ux500 power domains */
+       ux500_pm_domains_init();
 }
diff --git a/arch/arm/mach-ux500/pm_domains.c b/arch/arm/mach-ux500/pm_domains.c
new file mode 100644 (file)
index 0000000..0d4b5b4
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Implements PM domains using the generic PM domain for ux500.
+ */
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/pm_domain.h>
+
+#include <dt-bindings/arm/ux500_pm_domains.h>
+#include "pm_domains.h"
+
+static int pd_power_off(struct generic_pm_domain *domain)
+{
+       /*
+        * Handle the gating of the PM domain regulator here.
+        *
+        * Drivers/subsystems handling devices in the PM domain needs to perform
+        * register context save/restore from their respective runtime PM
+        * callbacks, to be able to enable PM domain gating/ungating.
+        */
+       return 0;
+}
+
+static int pd_power_on(struct generic_pm_domain *domain)
+{
+       /*
+        * Handle the ungating of the PM domain regulator here.
+        *
+        * Drivers/subsystems handling devices in the PM domain needs to perform
+        * register context save/restore from their respective runtime PM
+        * callbacks, to be able to enable PM domain gating/ungating.
+        */
+       return 0;
+}
+
+static struct generic_pm_domain ux500_pm_domain_vape = {
+       .name = "VAPE",
+       .power_off = pd_power_off,
+       .power_on = pd_power_on,
+};
+
+static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = {
+       [DOMAIN_VAPE] = &ux500_pm_domain_vape,
+};
+
+static struct of_device_id ux500_pm_domain_matches[] = {
+       { .compatible = "stericsson,ux500-pm-domains", },
+       { },
+};
+
+int __init ux500_pm_domains_init(void)
+{
+       struct device_node *np;
+       struct genpd_onecell_data *genpd_data;
+       int i;
+
+       np = of_find_matching_node(NULL, ux500_pm_domain_matches);
+       if (!np)
+               return -ENODEV;
+
+       genpd_data = kzalloc(sizeof(*genpd_data), GFP_KERNEL);
+       if (!genpd_data)
+               return -ENOMEM;
+
+       genpd_data->domains = ux500_pm_domains;
+       genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains);
+
+       for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i)
+               pm_genpd_init(ux500_pm_domains[i], NULL, false);
+
+       of_genpd_add_provider_onecell(np, genpd_data);
+       return 0;
+}
diff --git a/arch/arm/mach-ux500/pm_domains.h b/arch/arm/mach-ux500/pm_domains.h
new file mode 100644 (file)
index 0000000..263d3ba
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __MACH_UX500_PM_DOMAINS_H
+#define __MACH_UX500_PM_DOMAINS_H
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS
+extern int __init ux500_pm_domains_init(void);
+#else
+static inline int ux500_pm_domains_init(void) { return 0; }
+#endif
+
+#endif
index b2cfba16c4e8ffcdcb1c649fc287fcaaab01573e..d6b16d9a78380e78ff7d33855f1c6caa557d2e83 100644 (file)
@@ -16,6 +16,7 @@ menuconfig ARCH_VEXPRESS
        select POWER_RESET
        select POWER_RESET_VEXPRESS
        select POWER_SUPPLY
+       select REGULATOR if MMC_ARMMMCI
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
        select VEXPRESS_CONFIG
        select VEXPRESS_SYSCFG
@@ -49,9 +50,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
          build a working kernel, you must also enable relevant core
          tile support or Flattened Device Tree based support options.
 
-config ARCH_VEXPRESS_CA9X4
-       bool "Versatile Express Cortex-A9x4 tile"
-
 config ARCH_VEXPRESS_DCSCB
        bool "Dual Cluster System Control Block (DCSCB) support"
        depends on MCPM
index fc649bc09d0c4a04cd60202406b863fe6ebf2bd8..f5c1006dd6a1e31c7e6beb51206706225f1249a7 100644 (file)
@@ -1,11 +1,10 @@
 #
 # Makefile for the linux kernel.
 #
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := \
        -I$(srctree)/arch/arm/plat-versatile/include
 
 obj-y                                  := v2m.o
-obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)      += ct-ca9x4.o
 obj-$(CONFIG_ARCH_VEXPRESS_DCSCB)      += dcscb.o      dcscb_setup.o
 CFLAGS_dcscb.o                         += -march=armv7-a
 CFLAGS_REMOVE_dcscb.o                  = -pg
index 152fad91b3ae1f2c70b97cd7c2d6978aed668908..2a11d3ac8c68b5b74db8da21bca2744a9864f756 100644 (file)
@@ -1,12 +1,5 @@
-/* 2MB large area for motherboard's peripherals static mapping */
-#define V2M_PERIPH 0xf8000000
-
-/* Tile's peripherals static mappings should start here */
-#define V2T_PERIPH 0xf8200000
-
 bool vexpress_smp_init_ops(void);
 
-extern struct smp_operations   vexpress_smp_ops;
 extern struct smp_operations   vexpress_smp_dt_ops;
 
 extern void vexpress_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
deleted file mode 100644 (file)
index 27bea04..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Versatile Express Core Tile Cortex A9x4 Support
- */
-#include <linux/init.h>
-#include <linux/gfp.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-#include <linux/platform_data/video-clcd-versatile.h>
-#include <linux/clkdev.h>
-#include <linux/vexpress.h>
-#include <linux/irqchip/arm-gic.h>
-
-#include <asm/hardware/arm_timer.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/smp_scu.h>
-#include <asm/smp_twd.h>
-
-#include <mach/ct-ca9x4.h>
-
-#include <asm/hardware/timer-sp.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-
-#include "core.h"
-
-#include <mach/motherboard.h>
-#include <mach/irqs.h>
-
-static struct map_desc ct_ca9x4_io_desc[] __initdata = {
-       {
-               .virtual        = V2T_PERIPH,
-               .pfn            = __phys_to_pfn(CT_CA9X4_MPIC),
-               .length         = SZ_8K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static void __init ct_ca9x4_map_io(void)
-{
-       iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
-}
-
-static void __init ca9x4_l2_init(void)
-{
-#ifdef CONFIG_CACHE_L2X0
-       void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
-
-       if (l2x0_base) {
-               /* set RAM latencies to 1 cycle for this core tile. */
-               writel(0, l2x0_base + L310_TAG_LATENCY_CTRL);
-               writel(0, l2x0_base + L310_DATA_LATENCY_CTRL);
-
-               l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
-       } else {
-               pr_err("L2C: unable to map L2 cache controller\n");
-       }
-#endif
-}
-
-#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER);
-
-static void __init ca9x4_twd_init(void)
-{
-       int err = twd_local_timer_register(&twd_local_timer);
-       if (err)
-               pr_err("twd_local_timer_register failed %d\n", err);
-}
-#else
-#define ca9x4_twd_init()       do {} while(0)
-#endif
-
-static void __init ct_ca9x4_init_irq(void)
-{
-       gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K),
-                ioremap(A9_MPCORE_GIC_CPU, SZ_256));
-       ca9x4_twd_init();
-       ca9x4_l2_init();
-}
-
-static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
-{
-       unsigned long framesize = 1024 * 768 * 2;
-
-       fb->panel = versatile_clcd_get_panel("XVGA");
-       if (!fb->panel)
-               return -EINVAL;
-
-       return versatile_clcd_setup_dma(fb, framesize);
-}
-
-static struct clcd_board ct_ca9x4_clcd_data = {
-       .name           = "CT-CA9X4",
-       .caps           = CLCD_CAP_5551 | CLCD_CAP_565,
-       .check          = clcdfb_check,
-       .decode         = clcdfb_decode,
-       .setup          = ct_ca9x4_clcd_setup,
-       .mmap           = versatile_clcd_mmap_dma,
-       .remove         = versatile_clcd_remove_dma,
-};
-
-static AMBA_AHB_DEVICE(clcd, "ct:clcd", 0, CT_CA9X4_CLCDC, IRQ_CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data);
-static AMBA_APB_DEVICE(dmc, "ct:dmc", 0, CT_CA9X4_DMC, IRQ_CT_CA9X4_DMC, NULL);
-static AMBA_APB_DEVICE(smc, "ct:smc", 0, CT_CA9X4_SMC, IRQ_CT_CA9X4_SMC, NULL);
-static AMBA_APB_DEVICE(gpio, "ct:gpio", 0, CT_CA9X4_GPIO, IRQ_CT_CA9X4_GPIO, NULL);
-
-static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
-       &clcd_device,
-       &dmc_device,
-       &smc_device,
-       &gpio_device,
-};
-
-static struct resource pmu_resources[] = {
-       [0] = {
-               .start  = IRQ_CT_CA9X4_PMU_CPU0,
-               .end    = IRQ_CT_CA9X4_PMU_CPU0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [1] = {
-               .start  = IRQ_CT_CA9X4_PMU_CPU1,
-               .end    = IRQ_CT_CA9X4_PMU_CPU1,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               .start  = IRQ_CT_CA9X4_PMU_CPU2,
-               .end    = IRQ_CT_CA9X4_PMU_CPU2,
-               .flags  = IORESOURCE_IRQ,
-       },
-       [3] = {
-               .start  = IRQ_CT_CA9X4_PMU_CPU3,
-               .end    = IRQ_CT_CA9X4_PMU_CPU3,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device pmu_device = {
-       .name           = "arm-pmu",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(pmu_resources),
-       .resource       = pmu_resources,
-};
-
-static struct clk_lookup osc1_lookup = {
-       .dev_id         = "ct:clcd",
-};
-
-static struct platform_device osc1_device = {
-       .name           = "vexpress-osc",
-       .id             = 1,
-       .num_resources  = 1,
-       .resource       = (struct resource []) {
-               VEXPRESS_RES_FUNC(0xf, 1),
-       },
-       .dev.platform_data = &osc1_lookup,
-};
-
-static void __init ct_ca9x4_init(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
-               amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
-
-       platform_device_register(&pmu_device);
-       vexpress_syscfg_device_register(&osc1_device);
-}
-
-#ifdef CONFIG_SMP
-static void *ct_ca9x4_scu_base __initdata;
-
-static void __init ct_ca9x4_init_cpu_map(void)
-{
-       int i, ncores;
-
-       ct_ca9x4_scu_base = ioremap(A9_MPCORE_SCU, SZ_128);
-       if (WARN_ON(!ct_ca9x4_scu_base))
-               return;
-
-       ncores = scu_get_core_count(ct_ca9x4_scu_base);
-
-       if (ncores > nr_cpu_ids) {
-               pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-                       ncores, nr_cpu_ids);
-               ncores = nr_cpu_ids;
-       }
-
-       for (i = 0; i < ncores; ++i)
-               set_cpu_possible(i, true);
-}
-
-static void __init ct_ca9x4_smp_enable(unsigned int max_cpus)
-{
-       scu_enable(ct_ca9x4_scu_base);
-}
-#endif
-
-struct ct_desc ct_ca9x4_desc __initdata = {
-       .id             = V2M_CT_ID_CA9,
-       .name           = "CA9x4",
-       .map_io         = ct_ca9x4_map_io,
-       .init_irq       = ct_ca9x4_init_irq,
-       .init_tile      = ct_ca9x4_init,
-#ifdef CONFIG_SMP
-       .init_cpu_map   = ct_ca9x4_init_cpu_map,
-       .smp_enable     = ct_ca9x4_smp_enable,
-#endif
-};
diff --git a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h
deleted file mode 100644 (file)
index 84acf84..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __MACH_CT_CA9X4_H
-#define __MACH_CT_CA9X4_H
-
-/*
- * Physical base addresses
- */
-#define CT_CA9X4_CLCDC         (0x10020000)
-#define CT_CA9X4_AXIRAM                (0x10060000)
-#define CT_CA9X4_DMC           (0x100e0000)
-#define CT_CA9X4_SMC           (0x100e1000)
-#define CT_CA9X4_SCC           (0x100e2000)
-#define CT_CA9X4_SP804_TIMER   (0x100e4000)
-#define CT_CA9X4_SP805_WDT     (0x100e5000)
-#define CT_CA9X4_TZPC          (0x100e6000)
-#define CT_CA9X4_GPIO          (0x100e8000)
-#define CT_CA9X4_FASTAXI       (0x100e9000)
-#define CT_CA9X4_SLOWAXI       (0x100ea000)
-#define CT_CA9X4_TZASC         (0x100ec000)
-#define CT_CA9X4_CORESIGHT     (0x10200000)
-#define CT_CA9X4_MPIC          (0x1e000000)
-#define CT_CA9X4_SYSTIMER      (0x1e004000)
-#define CT_CA9X4_SYSWDT                (0x1e007000)
-#define CT_CA9X4_L2CC          (0x1e00a000)
-
-#define A9_MPCORE_SCU          (CT_CA9X4_MPIC + 0x0000)
-#define A9_MPCORE_GIC_CPU      (CT_CA9X4_MPIC + 0x0100)
-#define A9_MPCORE_GIT          (CT_CA9X4_MPIC + 0x0200)
-#define A9_MPCORE_TWD          (CT_CA9X4_MPIC + 0x0600)
-#define A9_MPCORE_GIC_DIST     (CT_CA9X4_MPIC + 0x1000)
-
-/*
- * Interrupts.  Those in {} are for AMBA devices
- */
-#define IRQ_CT_CA9X4_CLCDC     { 76 }
-#define IRQ_CT_CA9X4_DMC       { 0 }
-#define IRQ_CT_CA9X4_SMC       { 77, 78 }
-#define IRQ_CT_CA9X4_TIMER0    80
-#define IRQ_CT_CA9X4_TIMER1    81
-#define IRQ_CT_CA9X4_GPIO      { 82 }
-#define IRQ_CT_CA9X4_PMU_CPU0  92
-#define IRQ_CT_CA9X4_PMU_CPU1  93
-#define IRQ_CT_CA9X4_PMU_CPU2  94
-#define IRQ_CT_CA9X4_PMU_CPU3  95
-
-extern struct ct_desc ct_ca9x4_desc;
-
-#endif
diff --git a/arch/arm/mach-vexpress/include/mach/hardware.h b/arch/arm/mach-vexpress/include/mach/hardware.h
deleted file mode 100644 (file)
index 40a8c17..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-vexpress/include/mach/irqs.h b/arch/arm/mach-vexpress/include/mach/irqs.h
deleted file mode 100644 (file)
index f8f7f78..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#define IRQ_LOCALTIMER         29
-#define IRQ_LOCALWDOG          30
-
-#ifndef CONFIG_SPARSE_IRQ
-#define NR_IRQS        256
-#endif
diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
deleted file mode 100644 (file)
index 68abc8b..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef __MACH_MOTHERBOARD_H
-#define __MACH_MOTHERBOARD_H
-
-/*
- * Physical addresses, offset from V2M_PA_CS0-3
- */
-#define V2M_NOR0               (V2M_PA_CS0)
-#define V2M_NOR1               (V2M_PA_CS1)
-#define V2M_SRAM               (V2M_PA_CS2)
-#define V2M_VIDEO_SRAM         (V2M_PA_CS3 + 0x00000000)
-#define V2M_LAN9118            (V2M_PA_CS3 + 0x02000000)
-#define V2M_ISP1761            (V2M_PA_CS3 + 0x03000000)
-
-/*
- * Physical addresses, offset from V2M_PA_CS7
- */
-#define V2M_SYSREGS            (V2M_PA_CS7 + 0x00000000)
-#define V2M_SYSCTL             (V2M_PA_CS7 + 0x00001000)
-#define V2M_SERIAL_BUS_PCI     (V2M_PA_CS7 + 0x00002000)
-
-#define V2M_AACI               (V2M_PA_CS7 + 0x00004000)
-#define V2M_MMCI               (V2M_PA_CS7 + 0x00005000)
-#define V2M_KMI0               (V2M_PA_CS7 + 0x00006000)
-#define V2M_KMI1               (V2M_PA_CS7 + 0x00007000)
-
-#define V2M_UART0              (V2M_PA_CS7 + 0x00009000)
-#define V2M_UART1              (V2M_PA_CS7 + 0x0000a000)
-#define V2M_UART2              (V2M_PA_CS7 + 0x0000b000)
-#define V2M_UART3              (V2M_PA_CS7 + 0x0000c000)
-
-#define V2M_WDT                        (V2M_PA_CS7 + 0x0000f000)
-
-#define V2M_TIMER01            (V2M_PA_CS7 + 0x00011000)
-#define V2M_TIMER23            (V2M_PA_CS7 + 0x00012000)
-
-#define V2M_SERIAL_BUS_DVI     (V2M_PA_CS7 + 0x00016000)
-#define V2M_RTC                        (V2M_PA_CS7 + 0x00017000)
-
-#define V2M_CF                 (V2M_PA_CS7 + 0x0001a000)
-#define V2M_CLCD               (V2M_PA_CS7 + 0x0001f000)
-
-
-/*
- * Interrupts.  Those in {} are for AMBA devices
- */
-#define IRQ_V2M_WDT            { (32 + 0) }
-#define IRQ_V2M_TIMER0         (32 + 2)
-#define IRQ_V2M_TIMER1         (32 + 2)
-#define IRQ_V2M_TIMER2         (32 + 3)
-#define IRQ_V2M_TIMER3         (32 + 3)
-#define IRQ_V2M_RTC            { (32 + 4) }
-#define IRQ_V2M_UART0          { (32 + 5) }
-#define IRQ_V2M_UART1          { (32 + 6) }
-#define IRQ_V2M_UART2          { (32 + 7) }
-#define IRQ_V2M_UART3          { (32 + 8) }
-#define IRQ_V2M_MMCI           { (32 + 9), (32 + 10) }
-#define IRQ_V2M_AACI           { (32 + 11) }
-#define IRQ_V2M_KMI0           { (32 + 12) }
-#define IRQ_V2M_KMI1           { (32 + 13) }
-#define IRQ_V2M_CLCD           { (32 + 14) }
-#define IRQ_V2M_LAN9118                (32 + 15)
-#define IRQ_V2M_ISP1761                (32 + 16)
-#define IRQ_V2M_PCIE           (32 + 17)
-
-
-/*
- * Core tile IDs
- */
-#define V2M_CT_ID_CA9          0x0c000191
-#define V2M_CT_ID_UNSUPPORTED  0xff000191
-#define V2M_CT_ID_MASK         0xff000fff
-
-struct ct_desc {
-       u32                     id;
-       const char              *name;
-       void                    (*map_io)(void);
-       void                    (*init_early)(void);
-       void                    (*init_irq)(void);
-       void                    (*init_tile)(void);
-#ifdef CONFIG_SMP
-       void                    (*init_cpu_map)(void);
-       void                    (*smp_enable)(unsigned int);
-#endif
-};
-
-extern struct ct_desc *ct_desc;
-
-#endif
index a1f3804fd5a549586e18725aecd3089f1c627081..83188cf1875d3e4fb5cfca9f637c75a74da1b2f4 100644 (file)
 #include <asm/smp_scu.h>
 #include <asm/mach/map.h>
 
-#include <mach/motherboard.h>
-
 #include <plat/platsmp.h>
 
 #include "core.h"
 
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-static void __init vexpress_smp_init_cpus(void)
-{
-       ct_desc->init_cpu_map();
-}
-
-static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus)
-{
-       /*
-        * Initialise the present map, which describes the set of CPUs
-        * actually populated at the present time.
-        */
-       ct_desc->smp_enable(max_cpus);
-
-       /*
-        * Write the address of secondary startup into the
-        * system-wide flags register. The boot monitor waits
-        * until it receives a soft interrupt, and then the
-        * secondary CPU branches to this address.
-        */
-       vexpress_flags_set(virt_to_phys(versatile_secondary_startup));
-}
-
-struct smp_operations __initdata vexpress_smp_ops = {
-       .smp_init_cpus          = vexpress_smp_init_cpus,
-       .smp_prepare_cpus       = vexpress_smp_prepare_cpus,
-       .smp_secondary_init     = versatile_secondary_init,
-       .smp_boot_secondary     = versatile_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-       .cpu_die                = vexpress_cpu_die,
-#endif
-};
-
 bool __init vexpress_smp_init_ops(void)
 {
 #ifdef CONFIG_MCPM
@@ -79,8 +41,6 @@ bool __init vexpress_smp_init_ops(void)
        return false;
 }
 
-#if defined(CONFIG_OF)
-
 static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = {
        { .compatible = "arm,cortex-a5-scu", },
        { .compatible = "arm,cortex-a9-scu", },
@@ -112,5 +72,3 @@ struct smp_operations __initdata vexpress_smp_dt_ops = {
        .cpu_die                = vexpress_cpu_die,
 #endif
 };
-
-#endif
index 6ff681a24ba7a7e4c087e34f3966a450aa8577fa..a0400f4cca894f8c83cf99d76514214816b01f14 100644 (file)
@@ -1,380 +1,7 @@
-/*
- * Versatile Express V2M Motherboard Support
- */
-#include <linux/device.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/mmci.h>
-#include <linux/io.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/of_address.h>
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/ata_platform.h>
-#include <linux/smsc911x.h>
-#include <linux/spinlock.h>
-#include <linux/usb/isp1760.h>
-#include <linux/mtd/physmap.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/vexpress.h>
-#include <linux/clkdev.h>
-
-#include <asm/mach-types.h>
-#include <asm/sizes.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-#include <asm/hardware/arm_timer.h>
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/timer-sp.h>
-
-#include <mach/ct-ca9x4.h>
-#include <mach/motherboard.h>
-
-#include <plat/sched_clock.h>
-#include <plat/platsmp.h>
 
 #include "core.h"
 
-#define V2M_PA_CS0     0x40000000
-#define V2M_PA_CS1     0x44000000
-#define V2M_PA_CS2     0x48000000
-#define V2M_PA_CS3     0x4c000000
-#define V2M_PA_CS7     0x10000000
-
-static struct map_desc v2m_io_desc[] __initdata = {
-       {
-               .virtual        = V2M_PERIPH,
-               .pfn            = __phys_to_pfn(V2M_PA_CS7),
-               .length         = SZ_128K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
-{
-       if (WARN_ON(!base || irq == NO_IRQ))
-               return;
-
-       sp804_clocksource_init(base + TIMER_2_BASE, "v2m-timer1");
-       sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
-}
-
-
-static struct resource v2m_pcie_i2c_resource = {
-       .start  = V2M_SERIAL_BUS_PCI,
-       .end    = V2M_SERIAL_BUS_PCI + SZ_4K - 1,
-       .flags  = IORESOURCE_MEM,
-};
-
-static struct platform_device v2m_pcie_i2c_device = {
-       .name           = "versatile-i2c",
-       .id             = 0,
-       .num_resources  = 1,
-       .resource       = &v2m_pcie_i2c_resource,
-};
-
-static struct resource v2m_ddc_i2c_resource = {
-       .start  = V2M_SERIAL_BUS_DVI,
-       .end    = V2M_SERIAL_BUS_DVI + SZ_4K - 1,
-       .flags  = IORESOURCE_MEM,
-};
-
-static struct platform_device v2m_ddc_i2c_device = {
-       .name           = "versatile-i2c",
-       .id             = 1,
-       .num_resources  = 1,
-       .resource       = &v2m_ddc_i2c_resource,
-};
-
-static struct resource v2m_eth_resources[] = {
-       {
-               .start  = V2M_LAN9118,
-               .end    = V2M_LAN9118 + SZ_64K - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_V2M_LAN9118,
-               .end    = IRQ_V2M_LAN9118,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct smsc911x_platform_config v2m_eth_config = {
-       .flags          = SMSC911X_USE_32BIT,
-       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-       .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
-       .phy_interface  = PHY_INTERFACE_MODE_MII,
-};
-
-static struct platform_device v2m_eth_device = {
-       .name           = "smsc911x",
-       .id             = -1,
-       .resource       = v2m_eth_resources,
-       .num_resources  = ARRAY_SIZE(v2m_eth_resources),
-       .dev.platform_data = &v2m_eth_config,
-};
-
-static struct regulator_consumer_supply v2m_eth_supplies[] = {
-       REGULATOR_SUPPLY("vddvario", "smsc911x"),
-       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-};
-
-static struct resource v2m_usb_resources[] = {
-       {
-               .start  = V2M_ISP1761,
-               .end    = V2M_ISP1761 + SZ_128K - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = IRQ_V2M_ISP1761,
-               .end    = IRQ_V2M_ISP1761,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct isp1760_platform_data v2m_usb_config = {
-       .is_isp1761             = true,
-       .bus_width_16           = false,
-       .port1_otg              = true,
-       .analog_oc              = false,
-       .dack_polarity_high     = false,
-       .dreq_polarity_high     = false,
-};
-
-static struct platform_device v2m_usb_device = {
-       .name           = "isp1760",
-       .id             = -1,
-       .resource       = v2m_usb_resources,
-       .num_resources  = ARRAY_SIZE(v2m_usb_resources),
-       .dev.platform_data = &v2m_usb_config,
-};
-
-static struct physmap_flash_data v2m_flash_data = {
-       .width          = 4,
-};
-
-static struct resource v2m_flash_resources[] = {
-       {
-               .start  = V2M_NOR0,
-               .end    = V2M_NOR0 + SZ_64M - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = V2M_NOR1,
-               .end    = V2M_NOR1 + SZ_64M - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device v2m_flash_device = {
-       .name           = "physmap-flash",
-       .id             = -1,
-       .resource       = v2m_flash_resources,
-       .num_resources  = ARRAY_SIZE(v2m_flash_resources),
-       .dev.platform_data = &v2m_flash_data,
-};
-
-static struct pata_platform_info v2m_pata_data = {
-       .ioport_shift   = 2,
-};
-
-static struct resource v2m_pata_resources[] = {
-       {
-               .start  = V2M_CF,
-               .end    = V2M_CF + 0xff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = V2M_CF + 0x100,
-               .end    = V2M_CF + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device v2m_cf_device = {
-       .name           = "pata_platform",
-       .id             = -1,
-       .resource       = v2m_pata_resources,
-       .num_resources  = ARRAY_SIZE(v2m_pata_resources),
-       .dev.platform_data = &v2m_pata_data,
-};
-
-static struct mmci_platform_data v2m_mmci_data = {
-       .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
-       .status         = vexpress_get_mci_cardin,
-       .gpio_cd        = -1,
-       .gpio_wp        = -1,
-};
-
-static struct resource v2m_sysreg_resources[] = {
-       {
-               .start  = V2M_SYSREGS,
-               .end    = V2M_SYSREGS + 0xfff,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device v2m_sysreg_device = {
-       .name           = "vexpress-sysreg",
-       .id             = -1,
-       .resource       = v2m_sysreg_resources,
-       .num_resources  = ARRAY_SIZE(v2m_sysreg_resources),
-};
-
-static struct platform_device v2m_muxfpga_device = {
-       .name           = "vexpress-muxfpga",
-       .id             = 0,
-       .num_resources  = 1,
-       .resource       = (struct resource []) {
-               VEXPRESS_RES_FUNC(0, 7),
-       }
-};
-
-static struct platform_device v2m_shutdown_device = {
-       .name           = "vexpress-shutdown",
-       .id             = 0,
-       .num_resources  = 1,
-       .resource       = (struct resource []) {
-               VEXPRESS_RES_FUNC(0, 8),
-       }
-};
-
-static struct platform_device v2m_reboot_device = {
-       .name           = "vexpress-reboot",
-       .id             = 0,
-       .num_resources  = 1,
-       .resource       = (struct resource []) {
-               VEXPRESS_RES_FUNC(0, 9),
-       }
-};
-
-static struct platform_device v2m_dvimode_device = {
-       .name           = "vexpress-dvimode",
-       .id             = 0,
-       .num_resources  = 1,
-       .resource       = (struct resource []) {
-               VEXPRESS_RES_FUNC(0, 11),
-       }
-};
-
-static AMBA_APB_DEVICE(aaci,  "mb:aaci",  0, V2M_AACI, IRQ_V2M_AACI, NULL);
-static AMBA_APB_DEVICE(mmci,  "mb:mmci",  0, V2M_MMCI, IRQ_V2M_MMCI, &v2m_mmci_data);
-static AMBA_APB_DEVICE(kmi0,  "mb:kmi0",  0, V2M_KMI0, IRQ_V2M_KMI0, NULL);
-static AMBA_APB_DEVICE(kmi1,  "mb:kmi1",  0, V2M_KMI1, IRQ_V2M_KMI1, NULL);
-static AMBA_APB_DEVICE(uart0, "mb:uart0", 0, V2M_UART0, IRQ_V2M_UART0, NULL);
-static AMBA_APB_DEVICE(uart1, "mb:uart1", 0, V2M_UART1, IRQ_V2M_UART1, NULL);
-static AMBA_APB_DEVICE(uart2, "mb:uart2", 0, V2M_UART2, IRQ_V2M_UART2, NULL);
-static AMBA_APB_DEVICE(uart3, "mb:uart3", 0, V2M_UART3, IRQ_V2M_UART3, NULL);
-static AMBA_APB_DEVICE(wdt,   "mb:wdt",   0, V2M_WDT, IRQ_V2M_WDT, NULL);
-static AMBA_APB_DEVICE(rtc,   "mb:rtc",   0, V2M_RTC, IRQ_V2M_RTC, NULL);
-
-static struct amba_device *v2m_amba_devs[] __initdata = {
-       &aaci_device,
-       &mmci_device,
-       &kmi0_device,
-       &kmi1_device,
-       &uart0_device,
-       &uart1_device,
-       &uart2_device,
-       &uart3_device,
-       &wdt_device,
-       &rtc_device,
-};
-
-static void __init v2m_timer_init(void)
-{
-       vexpress_clk_init(ioremap(V2M_SYSCTL, SZ_4K));
-       v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
-}
-
-static void __init v2m_init_early(void)
-{
-       if (ct_desc->init_early)
-               ct_desc->init_early();
-       versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
-}
-
-struct ct_desc *ct_desc;
-
-static struct ct_desc *ct_descs[] __initdata = {
-#ifdef CONFIG_ARCH_VEXPRESS_CA9X4
-       &ct_ca9x4_desc,
-#endif
-};
-
-static void __init v2m_populate_ct_desc(void)
-{
-       int i;
-       u32 current_tile_id;
-
-       ct_desc = NULL;
-       current_tile_id = vexpress_get_procid(VEXPRESS_SITE_MASTER)
-                               & V2M_CT_ID_MASK;
-
-       for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
-               if (ct_descs[i]->id == current_tile_id)
-                       ct_desc = ct_descs[i];
-
-       if (!ct_desc)
-               panic("vexpress: this kernel does not support core tile ID 0x%08x when booting via ATAGs.\n"
-                     "You may need a device tree blob or a different kernel to boot on this board.\n",
-                     current_tile_id);
-}
-
-static void __init v2m_map_io(void)
-{
-       iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
-       vexpress_sysreg_early_init(ioremap(V2M_SYSREGS, SZ_4K));
-       v2m_populate_ct_desc();
-       ct_desc->map_io();
-}
-
-static void __init v2m_init_irq(void)
-{
-       ct_desc->init_irq();
-}
-
-static void __init v2m_init(void)
-{
-       int i;
-
-       regulator_register_fixed(0, v2m_eth_supplies,
-                       ARRAY_SIZE(v2m_eth_supplies));
-
-       platform_device_register(&v2m_sysreg_device);
-       platform_device_register(&v2m_pcie_i2c_device);
-       platform_device_register(&v2m_ddc_i2c_device);
-       platform_device_register(&v2m_flash_device);
-       platform_device_register(&v2m_cf_device);
-       platform_device_register(&v2m_eth_device);
-       platform_device_register(&v2m_usb_device);
-
-       for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
-               amba_device_register(v2m_amba_devs[i], &iomem_resource);
-
-       vexpress_syscfg_device_register(&v2m_muxfpga_device);
-       vexpress_syscfg_device_register(&v2m_shutdown_device);
-       vexpress_syscfg_device_register(&v2m_reboot_device);
-       vexpress_syscfg_device_register(&v2m_dvimode_device);
-
-       ct_desc->init_tile();
-}
-
-MACHINE_START(VEXPRESS, "ARM-Versatile Express")
-       .atag_offset    = 0x100,
-       .smp            = smp_ops(vexpress_smp_ops),
-       .map_io         = v2m_map_io,
-       .init_early     = v2m_init_early,
-       .init_irq       = v2m_init_irq,
-       .init_time      = v2m_timer_init,
-       .init_machine   = v2m_init,
-MACHINE_END
-
-static void __init v2m_dt_init(void)
-{
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char * const v2m_dt_match[] __initconst = {
        "arm,vexpress",
        NULL,
@@ -386,5 +13,4 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
        .l2c_aux_mask   = 0xfe0fffff,
        .smp            = smp_ops(vexpress_smp_dt_ops),
        .smp_init       = smp_init_ops(vexpress_smp_init_ops),
-       .init_machine   = v2m_dt_init,
 MACHINE_END
index c85fb3f7d5cdf55d683eea83ca7a4a0e15125fb5..b03a97eb75012fcc2769a6ab89355610c86ad4a3 100644 (file)
@@ -4,6 +4,4 @@
 
 # Common support
 obj-y                          := common.o slcr.o pm.o
-CFLAGS_REMOVE_hotplug.o                =-march=armv6k
-CFLAGS_hotplug.o               =-Wa,-march=armv7-a -mcpu=cortex-a9
 obj-$(CONFIG_SMP)              += headsmp.o platsmp.o
index 2bc71273c73c6c324b4c8d869389d8bd535a3a64..382c60e9aa1606fa980fb6c88e1aadd286e8210f 100644 (file)
@@ -29,7 +29,6 @@ extern void zynq_slcr_cpu_state_write(int cpu, bool die);
 extern u32 zynq_slcr_get_device_id(void);
 
 #ifdef CONFIG_SMP
-extern void secondary_startup(void);
 extern char zynq_secondary_trampoline;
 extern char zynq_secondary_trampoline_jump;
 extern char zynq_secondary_trampoline_end;
diff --git a/arch/arm/mach-zynq/hotplug.c b/arch/arm/mach-zynq/hotplug.c
deleted file mode 100644 (file)
index b685c89..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Xilinx
- *
- * based on linux/arch/arm/mach-realview/hotplug.c
- *
- * Copyright (C) 2002 ARM Ltd.
- * 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.
- */
-#include <asm/proc-fns.h>
-
index ae69809a9e479bef7617e41627b082452c93d09e..ab906b8010470ad514081bc6901923a2c76f2f5d 100644 (file)
@@ -21,7 +21,7 @@ config CPU_ARM7TDMI
 
 # ARM720T
 config CPU_ARM720T
-       bool "Support ARM720T processor" if ARCH_INTEGRATOR
+       bool "Support ARM720T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        select CPU_32v4T
        select CPU_ABRT_LV4T
        select CPU_CACHE_V4
@@ -39,7 +39,7 @@ config CPU_ARM720T
 
 # ARM740T
 config CPU_ARM740T
-       bool "Support ARM740T processor" if ARCH_INTEGRATOR
+       bool "Support ARM740T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_LV4T
@@ -71,7 +71,7 @@ config CPU_ARM9TDMI
 
 # ARM920T
 config CPU_ARM920T
-       bool "Support ARM920T processor" if ARCH_INTEGRATOR
+       bool "Support ARM920T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        select CPU_32v4T
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
@@ -89,7 +89,7 @@ config CPU_ARM920T
 
 # ARM922T
 config CPU_ARM922T
-       bool "Support ARM922T processor" if ARCH_INTEGRATOR
+       bool "Support ARM922T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        select CPU_32v4T
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
@@ -127,7 +127,7 @@ config CPU_ARM925T
 
 # ARM926T
 config CPU_ARM926T
-       bool "Support ARM926T processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB
+       bool "Support ARM926T processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V5) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB)
        select CPU_32v5
        select CPU_ABRT_EV5TJ
        select CPU_CACHE_VIVT
@@ -163,7 +163,7 @@ config CPU_FA526
 
 # ARM940T
 config CPU_ARM940T
-       bool "Support ARM940T processor" if ARCH_INTEGRATOR
+       bool "Support ARM940T processor" if (ARCH_MULTI_V4T && ARCH_INTEGRATOR)
        depends on !MMU
        select CPU_32v4T
        select CPU_ABRT_NOMMU
@@ -181,7 +181,7 @@ config CPU_ARM940T
 
 # ARM946E-S
 config CPU_ARM946E
-       bool "Support ARM946E-S processor" if ARCH_INTEGRATOR
+       bool "Support ARM946E-S processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        depends on !MMU
        select CPU_32v5
        select CPU_ABRT_NOMMU
@@ -198,7 +198,7 @@ config CPU_ARM946E
 
 # ARM1020 - needs validating
 config CPU_ARM1020
-       bool "Support ARM1020T (rev 0) processor" if ARCH_INTEGRATOR
+       bool "Support ARM1020T (rev 0) processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        select CPU_32v5
        select CPU_ABRT_EV4T
        select CPU_CACHE_V4WT
@@ -216,7 +216,7 @@ config CPU_ARM1020
 
 # ARM1020E - needs validating
 config CPU_ARM1020E
-       bool "Support ARM1020E processor" if ARCH_INTEGRATOR
+       bool "Support ARM1020E processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        depends on n
        select CPU_32v5
        select CPU_ABRT_EV4T
@@ -229,7 +229,7 @@ config CPU_ARM1020E
 
 # ARM1022E
 config CPU_ARM1022
-       bool "Support ARM1022E processor" if ARCH_INTEGRATOR
+       bool "Support ARM1022E processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        select CPU_32v5
        select CPU_ABRT_EV4T
        select CPU_CACHE_VIVT
@@ -247,7 +247,7 @@ config CPU_ARM1022
 
 # ARM1026EJ-S
 config CPU_ARM1026
-       bool "Support ARM1026EJ-S processor" if ARCH_INTEGRATOR
+       bool "Support ARM1026EJ-S processor" if (ARCH_MULTI_V5 && ARCH_INTEGRATOR)
        select CPU_32v5
        select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10
        select CPU_CACHE_VIVT
@@ -358,7 +358,7 @@ config CPU_PJ4B
 
 # ARMv6
 config CPU_V6
-       bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+       bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX)
        select CPU_32v6
        select CPU_ABRT_EV6
        select CPU_CACHE_V6
@@ -371,7 +371,7 @@ config CPU_V6
 
 # ARMv6k
 config CPU_V6K
-       bool "Support ARM V6K processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+       bool "Support ARM V6K processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX)
        select CPU_32v6
        select CPU_32v6K
        select CPU_ABRT_EV6
@@ -385,7 +385,7 @@ config CPU_V6K
 
 # ARMv7
 config CPU_V7
-       bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+       bool "Support ARM V7 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V7) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX)
        select CPU_32v6K
        select CPU_32v7
        select CPU_ABRT_EV7
@@ -798,6 +798,7 @@ config NEED_KUSER_HELPERS
 
 config KUSER_HELPERS
        bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS
+       depends on MMU
        default y
        help
          Warning: disabling this option may break user programs.
index 55f9d6e0cc88b87feaa41d443f521ce9bb1aef52..5e65ca8dea62cf3f38d48f2ad8a25425ab0ce6de 100644 (file)
@@ -956,7 +956,7 @@ static u32 cache_id_part_number_from_dt;
  * @associativity: variable to return the calculated associativity in
  * @max_way_size: the maximum size in bytes for the cache ways
  */
-static void __init l2x0_cache_size_of_parse(const struct device_node *np,
+static int __init l2x0_cache_size_of_parse(const struct device_node *np,
                                            u32 *aux_val, u32 *aux_mask,
                                            u32 *associativity,
                                            u32 max_way_size)
@@ -974,7 +974,7 @@ static void __init l2x0_cache_size_of_parse(const struct device_node *np,
        of_property_read_u32(np, "cache-line-size", &line_size);
 
        if (!cache_size || !sets)
-               return;
+               return -ENODEV;
 
        /* All these l2 caches have the same line = block size actually */
        if (!line_size) {
@@ -1009,7 +1009,7 @@ static void __init l2x0_cache_size_of_parse(const struct device_node *np,
 
        if (way_size > max_way_size) {
                pr_err("L2C OF: set size %dKB is too large\n", way_size);
-               return;
+               return -EINVAL;
        }
 
        pr_info("L2C OF: override cache size: %d bytes (%dKB)\n",
@@ -1027,7 +1027,7 @@ static void __init l2x0_cache_size_of_parse(const struct device_node *np,
        if (way_size_bits < 1 || way_size_bits > 6) {
                pr_err("L2C OF: cache way size illegal: %dKB is not mapped\n",
                       way_size);
-               return;
+               return -EINVAL;
        }
 
        mask |= L2C_AUX_CTRL_WAY_SIZE_MASK;
@@ -1036,6 +1036,8 @@ static void __init l2x0_cache_size_of_parse(const struct device_node *np,
        *aux_val &= ~mask;
        *aux_val |= val;
        *aux_mask &= ~mask;
+
+       return 0;
 }
 
 static void __init l2x0_of_parse(const struct device_node *np,
@@ -1046,6 +1048,7 @@ static void __init l2x0_of_parse(const struct device_node *np,
        u32 dirty = 0;
        u32 val = 0, mask = 0;
        u32 assoc;
+       int ret;
 
        of_property_read_u32(np, "arm,tag-latency", &tag);
        if (tag) {
@@ -1068,7 +1071,10 @@ static void __init l2x0_of_parse(const struct device_node *np,
                val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
        }
 
-       l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_256K);
+       ret = l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_256K);
+       if (ret)
+               return;
+
        if (assoc > 8) {
                pr_err("l2x0 of: cache setting yield too high associativity\n");
                pr_err("l2x0 of: %d calculated, max 8\n", assoc);
@@ -1125,6 +1131,7 @@ static void __init l2c310_of_parse(const struct device_node *np,
        u32 tag[3] = { 0, 0, 0 };
        u32 filter[2] = { 0, 0 };
        u32 assoc;
+       int ret;
 
        of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
        if (tag[0] && tag[1] && tag[2])
@@ -1152,7 +1159,10 @@ static void __init l2c310_of_parse(const struct device_node *np,
                               l2x0_base + L310_ADDR_FILTER_START);
        }
 
-       l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K);
+       ret = l2x0_cache_size_of_parse(np, aux_val, aux_mask, &assoc, SZ_512K);
+       if (ret)
+               return;
+
        switch (assoc) {
        case 16:
                *aux_val &= ~L2X0_AUX_CTRL_ASSOC_MASK;
@@ -1164,8 +1174,8 @@ static void __init l2c310_of_parse(const struct device_node *np,
                *aux_mask &= ~L2X0_AUX_CTRL_ASSOC_MASK;
                break;
        default:
-               pr_err("PL310 OF: cache setting yield illegal associativity\n");
-               pr_err("PL310 OF: %d calculated, only 8 and 16 legal\n", assoc);
+               pr_err("L2C-310 OF cache associativity %d invalid, only 8 or 16 permitted\n",
+                      assoc);
                break;
        }
 }
index c245d903927fadfdee177b4d94b876ae2473618e..e8907117861ef81a79938df32b1889a80e7cdc5a 100644 (file)
@@ -1198,7 +1198,6 @@ __iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot,
 {
        return dma_common_pages_remap(pages, size,
                        VM_ARM_DMA_CONSISTENT | VM_USERMAP, prot, caller);
-       return NULL;
 }
 
 /*
index 45aeaaca9052f237322cf91a247a69fdb2d1571e..e17ed00828d722cad66a756695311ad691ae68cf 100644 (file)
@@ -127,8 +127,11 @@ void *kmap_atomic_pfn(unsigned long pfn)
 {
        unsigned long vaddr;
        int idx, type;
+       struct page *page = pfn_to_page(pfn);
 
        pagefault_disable();
+       if (!PageHighMem(page))
+               return page_address(page);
 
        type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR * smp_processor_id();
index 92bba32d92304c4383d43bee8ef95f7d988602c6..9481f85c56e6fd0ed263401a3e71d0cfa541606c 100644 (file)
@@ -559,10 +559,10 @@ void __init mem_init(void)
 #ifdef CONFIG_MODULES
                        "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #endif
-                       "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
-                       "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
-                       "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
-                       "       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n",
+                       "      .text : 0x%p" " - 0x%p" "   (%4td kB)\n"
+                       "      .init : 0x%p" " - 0x%p" "   (%4td kB)\n"
+                       "      .data : 0x%p" " - 0x%p" "   (%4td kB)\n"
+                       "       .bss : 0x%p" " - 0x%p" "   (%4td kB)\n",
 
                        MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
                                (PAGE_SIZE)),
index b3a947863ac7bb7e38d47b7a640d698b55a34bbc..22ac2a6fbfe373b432f43b1041ca9cf42e189837 100644 (file)
@@ -270,7 +270,6 @@ __v7_pj4b_setup:
 /* Auxiliary Debug Modes Control 1 Register */
 #define PJ4B_STATIC_BP (1 << 2) /* Enable Static BP */
 #define PJ4B_INTER_PARITY (1 << 8) /* Disable Internal Parity Handling */
-#define PJ4B_BCK_OFF_STREX (1 << 5) /* Enable the back off of STREX instr */
 #define PJ4B_CLEAN_LINE (1 << 16) /* Disable data transfer for clean line */
 
 /* Auxiliary Debug Modes Control 2 Register */
@@ -293,7 +292,6 @@ __v7_pj4b_setup:
        /* Auxiliary Debug Modes Control 1 Register */
        mrc     p15, 1, r0, c15, c1, 1
        orr     r0, r0, #PJ4B_CLEAN_LINE
-       orr     r0, r0, #PJ4B_BCK_OFF_STREX
        orr     r0, r0, #PJ4B_INTER_PARITY
        bic     r0, r0, #PJ4B_STATIC_BP
        mcr     p15, 1, r0, c15, c1, 1
index 23259f104c66fd367d4663cbd4adafd240ffa50d..afa2b3c4df4a267e5a609c13e6e7d6461be85616 100644 (file)
@@ -535,7 +535,7 @@ ENTRY(cpu_xscale_do_suspend)
        mrc     p15, 0, r5, c15, c1, 0  @ CP access reg
        mrc     p15, 0, r6, c13, c0, 0  @ PID
        mrc     p15, 0, r7, c3, c0, 0   @ domain ID
-       mrc     p15, 0, r8, c1, c1, 0   @ auxiliary control reg
+       mrc     p15, 0, r8, c1, c0, 1   @ auxiliary control reg
        mrc     p15, 0, r9, c1, c0, 0   @ control reg
        bic     r4, r4, #2              @ clear frequency change bit
        stmia   r0, {r4 - r9}           @ store cp regs
@@ -552,7 +552,7 @@ ENTRY(cpu_xscale_do_resume)
        mcr     p15, 0, r6, c13, c0, 0  @ PID
        mcr     p15, 0, r7, c3, c0, 0   @ domain ID
        mcr     p15, 0, r1, c2, c0, 0   @ translation table base addr
-       mcr     p15, 0, r8, c1, c1, 0   @ auxiliary control reg
+       mcr     p15, 0, r8, c1, c0, 1   @ auxiliary control reg
        mov     r0, r9                  @ control register
        b       cpu_resume_mmu
 ENDPROC(cpu_xscale_do_resume)
index f0a008496993ec1a5fc1625068ffb69aa510a3f1..87746c37f0309d19d1b9be932bb3784c937fb712 100644 (file)
@@ -35,6 +35,7 @@ obj-$(CONFIG_SAMSUNG_DMADEV)  += dma-ops.o
 # PM support
 
 obj-$(CONFIG_PM_SLEEP)         += pm-common.o
+obj-$(CONFIG_EXYNOS_CPU_SUSPEND) += pm-common.o
 obj-$(CONFIG_SAMSUNG_PM)       += pm.o
 obj-$(CONFIG_SAMSUNG_PM_GPIO)  += pm-gpio.o
 obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o
index f5b9d3ff9cd4bed7fe4573df30f1adb4d0476990..f5cf2bd208e0c1b21179c68d0ff2bab1b39eb531 100644 (file)
 
 #define S5P_VA_CHIPID          S3C_ADDR(0x02000000)
 #define S5P_VA_CMU             S3C_ADDR(0x02100000)
-#define S5P_VA_GPIO            S3C_ADDR(0x02200000)
-#define S5P_VA_GPIO1           S5P_VA_GPIO
-#define S5P_VA_GPIO2           S3C_ADDR(0x02240000)
-#define S5P_VA_GPIO3           S3C_ADDR(0x02280000)
 
-#define S5P_VA_SYSRAM          S3C_ADDR(0x02400000)
-#define S5P_VA_SYSRAM_NS       S3C_ADDR(0x02410000)
 #define S5P_VA_DMC0            S3C_ADDR(0x02440000)
 #define S5P_VA_DMC1            S3C_ADDR(0x02480000)
 #define S5P_VA_SROMC           S3C_ADDR(0x024C0000)
 
-#define S5P_VA_SYSTIMER                S3C_ADDR(0x02500000)
-#define S5P_VA_L2CC            S3C_ADDR(0x02600000)
-
-#define S5P_VA_COMBINER_BASE   S3C_ADDR(0x02700000)
-#define S5P_VA_COMBINER(x)     (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10)
-
 #define S5P_VA_COREPERI_BASE   S3C_ADDR(0x02800000)
 #define S5P_VA_COREPERI(x)     (S5P_VA_COREPERI_BASE + (x))
 #define S5P_VA_SCU             S5P_VA_COREPERI(0x0)
 #define S5P_VA_TWD             S5P_VA_COREPERI(0x600)
 
-#define S5P_VA_GIC_CPU         S3C_ADDR(0x02810000)
-#define S5P_VA_GIC_DIST                S3C_ADDR(0x02820000)
-
 #define VA_VIC(x)              (S3C_VA_IRQ + ((x) * 0x10000))
 #define VA_VIC0                        VA_VIC(0)
 #define VA_VIC1                        VA_VIC(1)
 #define VA_VIC2                        VA_VIC(2)
 #define VA_VIC3                        VA_VIC(3)
 
-#define S5P_VA_UART(x)         (S3C_VA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_VA_UART0           S5P_VA_UART(0)
-#define S5P_VA_UART1           S5P_VA_UART(1)
-#define S5P_VA_UART2           S5P_VA_UART(2)
-#define S5P_VA_UART3           S5P_VA_UART(3)
-
 #ifndef S3C_UART_OFFSET
 #define S3C_UART_OFFSET                (0x400)
 #endif
index a301ca2c7d00e4b47b7e9b6316f9fa57a8f738be..49b8ef91584af2945d37121d4238167b5e1cb4a8 100644 (file)
@@ -4,6 +4,6 @@ config PLAT_VERSATILE_CLOCK
        bool
 
 config PLAT_VERSATILE_SCHED_CLOCK
-       def_bool y
+       bool
 
 endif
index ac9afde76dead843ed4a53b2e0da97e4a7a0bd72..6b1ebd964c108429f7feff86f74b17b124229f88 100644 (file)
@@ -1,5 +1,6 @@
 config ARM64
        def_bool y
+       select ARCH_BINFMT_ELF_RANDOMIZE_PIE
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select ARCH_HAS_SG_CHAIN
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
@@ -23,9 +24,9 @@ config ARM64
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
        select GENERIC_CPU_AUTOPROBE
        select GENERIC_EARLY_IOREMAP
-       select GENERIC_IOMAP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
+       select GENERIC_PCI_IOMAP
        select GENERIC_SCHED_CLOCK
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_STRNCPY_FROM_USER
@@ -33,13 +34,16 @@ config ARM64
        select GENERIC_TIME_VSYSCALL
        select HANDLE_DOMAIN_IRQ
        select HARDIRQS_SW_RESEND
+       select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_ARCH_AUDITSYSCALL
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_KGDB
+       select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
        select HAVE_BPF_JIT
        select HAVE_C_RECORDMCOUNT
        select HAVE_CC_STACKPROTECTOR
+       select HAVE_CMPXCHG_DOUBLE
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_API_DEBUG
@@ -141,6 +145,11 @@ source "kernel/Kconfig.freezer"
 
 menu "Platform selection"
 
+config ARCH_SEATTLE
+       bool "AMD Seattle SoC Family"
+       help
+         This enables support for AMD Seattle SOC Family
+
 config ARCH_THUNDER
        bool "Cavium Inc. Thunder SoC Family"
        help
@@ -165,9 +174,6 @@ endmenu
 
 menu "Bus support"
 
-config ARM_AMBA
-       bool
-
 config PCI
        bool "PCI support"
        help
@@ -192,6 +198,114 @@ endmenu
 
 menu "Kernel Features"
 
+menu "ARM errata workarounds via the alternatives framework"
+
+config ARM64_ERRATUM_826319
+       bool "Cortex-A53: 826319: System might deadlock if a write cannot complete until read data is accepted"
+       default y
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 826319 on Cortex-A53 parts up to r0p2 with an AMBA 4 ACE or
+         AXI master interface and an L2 cache.
+
+         If a Cortex-A53 uses an AMBA AXI4 ACE interface to other processors
+         and is unable to accept a certain write via this interface, it will
+         not progress on read data presented on the read data channel and the
+         system can deadlock.
+
+         The workaround promotes data cache clean instructions to
+         data cache clean-and-invalidate.
+         Please note that this does not necessarily enable the workaround,
+         as it depends on the alternative framework, which will only patch
+         the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
+config ARM64_ERRATUM_827319
+       bool "Cortex-A53: 827319: Data cache clean instructions might cause overlapping transactions to the interconnect"
+       default y
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 827319 on Cortex-A53 parts up to r0p2 with an AMBA 5 CHI
+         master interface and an L2 cache.
+
+         Under certain conditions this erratum can cause a clean line eviction
+         to occur at the same time as another transaction to the same address
+         on the AMBA 5 CHI interface, which can cause data corruption if the
+         interconnect reorders the two transactions.
+
+         The workaround promotes data cache clean instructions to
+         data cache clean-and-invalidate.
+         Please note that this does not necessarily enable the workaround,
+         as it depends on the alternative framework, which will only patch
+         the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
+config ARM64_ERRATUM_824069
+       bool "Cortex-A53: 824069: Cache line might not be marked as clean after a CleanShared snoop"
+       default y
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 824069 on Cortex-A53 parts up to r0p2 when it is connected
+         to a coherent interconnect.
+
+         If a Cortex-A53 processor is executing a store or prefetch for
+         write instruction at the same time as a processor in another
+         cluster is executing a cache maintenance operation to the same
+         address, then this erratum might cause a clean cache line to be
+         incorrectly marked as dirty.
+
+         The workaround promotes data cache clean instructions to
+         data cache clean-and-invalidate.
+         Please note that this option does not necessarily enable the
+         workaround, as it depends on the alternative framework, which will
+         only patch the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
+config ARM64_ERRATUM_819472
+       bool "Cortex-A53: 819472: Store exclusive instructions might cause data corruption"
+       default y
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 819472 on Cortex-A53 parts up to r0p1 with an L2 cache
+         present when it is connected to a coherent interconnect.
+
+         If the processor is executing a load and store exclusive sequence at
+         the same time as a processor in another cluster is executing a cache
+         maintenance operation to the same address, then this erratum might
+         cause data corruption.
+
+         The workaround promotes data cache clean instructions to
+         data cache clean-and-invalidate.
+         Please note that this does not necessarily enable the workaround,
+         as it depends on the alternative framework, which will only patch
+         the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
+config ARM64_ERRATUM_832075
+       bool "Cortex-A57: 832075: possible deadlock on mixing exclusive memory accesses with device loads"
+       default y
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 832075 on Cortex-A57 parts up to r1p2.
+
+         Affected Cortex-A57 parts might deadlock when exclusive load/store
+         instructions to Write-Back memory are mixed with Device loads.
+
+         The workaround is to promote device loads to use Load-Acquire
+         semantics.
+         Please note that this does not necessarily enable the workaround,
+         as it depends on the alternative framework, which will only patch
+         the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
+endmenu
+
+
 choice
        prompt "Page size"
        default ARM64_4K_PAGES
@@ -232,7 +346,7 @@ config ARM64_VA_BITS_42
 
 config ARM64_VA_BITS_48
        bool "48-bit"
-       depends on BROKEN
+       depends on !ARM_SMMU
 
 endchoice
 
@@ -344,6 +458,19 @@ config ARCH_HAS_CACHE_LINE_SIZE
 
 source "mm/Kconfig"
 
+config SECCOMP
+       bool "Enable seccomp to safely compute untrusted bytecode"
+       ---help---
+         This kernel feature is useful for number crunching applications
+         that may need to compute untrusted bytecode during their
+         execution. By using pipes or other transports made available to
+         the process as file descriptors supporting the read/write
+         syscalls, it's possible to isolate those applications in
+         their own address space using seccomp. Once seccomp is
+         enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+         and the task is only allowed to execute a few safe syscalls
+         defined by each seccomp mode.
+
 config XEN_DOM0
        def_bool y
        depends on XEN
@@ -360,6 +487,58 @@ config FORCE_MAX_ZONEORDER
        default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
        default "11"
 
+menuconfig ARMV8_DEPRECATED
+       bool "Emulate deprecated/obsolete ARMv8 instructions"
+       depends on COMPAT
+       help
+         Legacy software support may require certain instructions
+         that have been deprecated or obsoleted in the architecture.
+
+         Enable this config to enable selective emulation of these
+         features.
+
+         If unsure, say Y
+
+if ARMV8_DEPRECATED
+
+config SWP_EMULATION
+       bool "Emulate SWP/SWPB instructions"
+       help
+         ARMv8 obsoletes the use of A32 SWP/SWPB instructions such that
+         they are always undefined. Say Y here to enable software
+         emulation of these instructions for userspace using LDXR/STXR.
+
+         In some older versions of glibc [<=2.8] SWP is used during futex
+         trylock() operations with the assumption that the code will not
+         be preempted. This invalid assumption may be more likely to fail
+         with SWP emulation enabled, leading to deadlock of the user
+         application.
+
+         NOTE: when accessing uncached shared regions, LDXR/STXR rely
+         on an external transaction monitoring block called a global
+         monitor to maintain update atomicity. If your system does not
+         implement a global monitor, this option can cause programs that
+         perform SWP operations to uncached memory to deadlock.
+
+         If unsure, say Y
+
+config CP15_BARRIER_EMULATION
+       bool "Emulate CP15 Barrier instructions"
+       help
+         The CP15 barrier instructions - CP15ISB, CP15DSB, and
+         CP15DMB - are deprecated in ARMv8 (and ARMv7). It is
+         strongly recommended to use the ISB, DSB, and DMB
+         instructions instead.
+
+         Say Y here to enable software emulation of these
+         instructions for AArch32 userspace code. When this option is
+         enabled, CP15 barrier usage is traced which can help
+         identify software that needs updating.
+
+         If unsure, say Y
+
+endif
+
 endmenu
 
 menu "Boot options"
@@ -400,6 +579,17 @@ config EFI
          allow the kernel to be booted as an EFI application. This
          is only useful on systems that have UEFI firmware.
 
+config DMI
+       bool "Enable support for SMBIOS (DMI) tables"
+       depends on EFI
+       default y
+       help
+         This enables SMBIOS/DMI feature for systems.
+
+         This option is only useful on systems that have UEFI firmware.
+         However, even with this option, the resultant kernel should
+         continue to boot on existing non-UEFI platforms.
+
 endmenu
 
 menu "Userspace binary formats"
index 0a12933e50edaef727d67e5f678f779418ea24b4..5fdd6dce806125d1035a9e32fef8711de7ec4373 100644 (file)
@@ -6,6 +6,18 @@ config FRAME_POINTER
        bool
        default y
 
+config ARM64_PTDUMP
+       bool "Export kernel pagetable layout to userspace via debugfs"
+       depends on DEBUG_KERNEL
+       select DEBUG_FS
+        help
+         Say Y here if you want to show the kernel pagetable layout in a
+         debugfs file. This information is only useful for kernel developers
+         who are working in architecture specific areas of the kernel.
+         It is probably not a good idea to enable this feature in a production
+         kernel.
+         If in doubt, say "N"
+
 config STRICT_DEVMEM
        bool "Filter access to /dev/mem"
        depends on MMU
index 20901ffed182a6d1b1f41c08f91109e1ac2047ef..1c43cec971b5cd7196b367d1917baa25a10078bd 100644 (file)
@@ -70,8 +70,13 @@ zinstall install: vmlinux
 %.dtb: scripts
        $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
 
-dtbs: scripts
-       $(Q)$(MAKE) $(build)=$(boot)/dts dtbs
+PHONY += dtbs dtbs_install
+
+dtbs: prepare scripts
+       $(Q)$(MAKE) $(build)=$(boot)/dts
+
+dtbs_install:
+       $(Q)$(MAKE) $(dtbinst)=$(boot)/dts
 
 PHONY += vdso_install
 vdso_install:
@@ -85,6 +90,7 @@ define archhelp
   echo  '* Image.gz      - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
   echo  '* dtbs          - Build device tree blobs for enabled boards'
+  echo  '  dtbs_install  - Install dtbs to $(INSTALL_DTBS_PATH)'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
   echo  '                  Install using (your) ~/bin/installkernel or'
index f8001a62029c8f4e1e2acdf6dc5431f1b8239e96..3b8d427c398599c85c8d12e3f67f20095ec43bac 100644 (file)
@@ -1,10 +1,8 @@
-dtb-$(CONFIG_ARCH_THUNDER) += thunder-88xx.dtb
-dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb
-dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb
+dts-dirs += amd
+dts-dirs += apm
+dts-dirs += arm
+dts-dirs += cavium
 
-targets += dtbs
-targets += $(dtb-y)
-
-dtbs: $(addprefix $(obj)/, $(dtb-y))
-
-clean-files := *.dtb
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/amd/Makefile b/arch/arm64/boot/dts/amd/Makefile
new file mode 100644 (file)
index 0000000..cfdf701
--- /dev/null
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_SEATTLE) += amd-overdrive.dtb
+
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/amd/amd-overdrive.dts b/arch/arm64/boot/dts/amd/amd-overdrive.dts
new file mode 100644 (file)
index 0000000..564a3f7
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * DTS file for AMD Seattle Overdrive Development Board
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ */
+
+/dts-v1/;
+
+/include/ "amd-seattle-soc.dtsi"
+
+/ {
+       model = "AMD Seattle Development Board (Overdrive)";
+       compatible = "amd,seattle-overdrive", "amd,seattle";
+
+       chosen {
+               stdout-path = &serial0;
+               linux,pci-probe-only;
+       };
+};
+
+&ccp0 {
+       status = "ok";
+};
+
+&gpio0 {
+       status = "ok";
+};
+
+&gpio1 {
+       status = "ok";
+};
+
+&i2c0 {
+       status = "ok";
+};
+
+&pcie0 {
+       status = "ok";
+};
+
+&spi0 {
+       status = "ok";
+};
+
+&spi1 {
+       status = "ok";
+       sdcard0: sdcard@0 {
+               compatible = "mmc-spi-slot";
+               reg = <0>;
+               spi-max-frequency = <20000000>;
+               voltage-ranges = <3200 3400>;
+               gpios = <&gpio0 7 0>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <7 3>;
+               pl022,hierarchy = <0>;
+               pl022,interface = <0>;
+               pl022,com-mode = <0x0>;
+               pl022,rx-level-trig = <0>;
+               pl022,tx-level-trig = <0>;
+       };
+};
+
+&v2m0 {
+       arm,msi-base-spi = <64>;
+       arm,msi-num-spis = <256>;
+};
diff --git a/arch/arm64/boot/dts/amd/amd-seattle-clks.dtsi b/arch/arm64/boot/dts/amd/amd-seattle-clks.dtsi
new file mode 100644 (file)
index 0000000..f623c46
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * DTS file for AMD Seattle Clocks
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ */
+
+       adl3clk_100mhz: clk100mhz_0 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+               clock-output-names = "adl3clk_100mhz";
+       };
+
+       ccpclk_375mhz: clk375mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <375000000>;
+               clock-output-names = "ccpclk_375mhz";
+       };
+
+       sataclk_333mhz: clk333mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <333000000>;
+               clock-output-names = "sataclk_333mhz";
+       };
+
+       pcieclk_500mhz: clk500mhz_0 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <500000000>;
+               clock-output-names = "pcieclk_500mhz";
+       };
+
+       dmaclk_500mhz: clk500mhz_1 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <500000000>;
+               clock-output-names = "dmaclk_500mhz";
+       };
+
+       miscclk_250mhz: clk250mhz_4 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <250000000>;
+               clock-output-names = "miscclk_250mhz";
+       };
+
+       uartspiclk_100mhz: clk100mhz_1 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+               clock-output-names = "uartspiclk_100mhz";
+       };
diff --git a/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi b/arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi
new file mode 100644 (file)
index 0000000..2874d92
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * DTS file for AMD Seattle SoC
+ *
+ * Copyright (C) 2014 Advanced Micro Devices, Inc.
+ */
+
+/ {
+       compatible = "amd,seattle";
+       interrupt-parent = <&gic0>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       gic0: interrupt-controller@e1101000 {
+               compatible = "arm,gic-400", "arm,cortex-a15-gic";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               reg = <0x0 0xe1110000 0 0x1000>,
+                     <0x0 0xe112f000 0 0x2000>,
+                     <0x0 0xe1140000 0 0x10000>,
+                     <0x0 0xe1160000 0 0x10000>;
+               interrupts = <1 9 0xf04>;
+               ranges = <0 0 0 0xe1100000 0 0x100000>;
+               v2m0: v2m@e0080000 {
+                       compatible = "arm,gic-v2m-frame";
+                       msi-controller;
+                       reg = <0x0 0x00080000 0 0x1000>;
+               };
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff04>,
+                            <1 14 0xff04>,
+                            <1 11 0xff04>,
+                            <1 10 0xff04>;
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 7 4>,
+                            <0 8 4>,
+                            <0 9 4>,
+                            <0 10 4>,
+                            <0 11 4>,
+                            <0 12 4>,
+                            <0 13 4>,
+                            <0 14 4>;
+       };
+
+       smb0: smb {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               /* DDR range is 40-bit addressing */
+               dma-ranges = <0x80 0x0 0x80 0x0 0x7f 0xffffffff>;
+
+               /include/ "amd-seattle-clks.dtsi"
+
+               sata0: sata@e0300000 {
+                       compatible = "snps,dwc-ahci";
+                       reg = <0 0xe0300000 0 0x800>;
+                       interrupts = <0 355 4>;
+                       clocks = <&sataclk_333mhz>;
+                       dma-coherent;
+               };
+
+               i2c0: i2c@e1000000 {
+                       status = "disabled";
+                       compatible = "snps,designware-i2c";
+                       reg = <0 0xe1000000 0 0x1000>;
+                       interrupts = <0 357 4>;
+                       clocks = <&uartspiclk_100mhz>;
+               };
+
+               serial0: serial@e1010000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0 0xe1010000 0 0x1000>;
+                       interrupts = <0 328 4>;
+                       clocks = <&uartspiclk_100mhz>, <&uartspiclk_100mhz>;
+                       clock-names = "uartclk", "apb_pclk";
+               };
+
+               spi0: ssp@e1020000 {
+                       status = "disabled";
+                       compatible = "arm,pl022", "arm,primecell";
+                       #gpio-cells = <2>;
+                       reg = <0 0xe1020000 0 0x1000>;
+                       spi-controller;
+                       interrupts = <0 330 4>;
+                       clocks = <&uartspiclk_100mhz>;
+                       clock-names = "apb_pclk";
+               };
+
+               spi1: ssp@e1030000 {
+                       status = "disabled";
+                       compatible = "arm,pl022", "arm,primecell";
+                       #gpio-cells = <2>;
+                       reg = <0 0xe1030000 0 0x1000>;
+                       spi-controller;
+                       interrupts = <0 329 4>;
+                       clocks = <&uartspiclk_100mhz>;
+                       clock-names = "apb_pclk";
+                       num-cs = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               gpio0: gpio@e1040000 {
+                       status = "disabled";
+                       compatible = "arm,pl061", "arm,primecell";
+                       #gpio-cells = <2>;
+                       reg = <0 0xe1040000 0 0x1000>;
+                       gpio-controller;
+                       interrupts = <0 359 4>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&uartspiclk_100mhz>;
+                       clock-names = "apb_pclk";
+               };
+
+               gpio1: gpio@e1050000 {
+                       status = "disabled";
+                       compatible = "arm,pl061", "arm,primecell";
+                       #gpio-cells = <2>;
+                       reg = <0 0xe1050000 0 0x1000>;
+                       gpio-controller;
+                       interrupts = <0 358 4>;
+                       clocks = <&uartspiclk_100mhz>;
+                       clock-names = "apb_pclk";
+               };
+
+               ccp0: ccp@e0100000 {
+                       status = "disabled";
+                       compatible = "amd,ccp-seattle-v1a";
+                       reg = <0 0xe0100000 0 0x10000>;
+                       interrupts = <0 3 4>;
+                       dma-coherent;
+               };
+
+               pcie0: pcie@f0000000 {
+                       compatible = "pci-host-ecam-generic";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       #interrupt-cells = <1>;
+                       device_type = "pci";
+                       bus-range = <0 0x7f>;
+                       msi-parent = <&v2m0>;
+                       reg = <0 0xf0000000 0 0x10000000>;
+
+                       interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+                       interrupt-map =
+                               <0x1000 0x0 0x0 0x1 &gic0 0x0 0x0 0x0 0x120 0x1>,
+                               <0x1000 0x0 0x0 0x2 &gic0 0x0 0x0 0x0 0x121 0x1>,
+                               <0x1000 0x0 0x0 0x3 &gic0 0x0 0x0 0x0 0x122 0x1>,
+                               <0x1000 0x0 0x0 0x4 &gic0 0x0 0x0 0x0 0x123 0x1>;
+
+                       dma-coherent;
+                       dma-ranges = <0x43000000 0x80 0x0 0x80 0x0 0x7f 0xffffffff>;
+                       ranges =
+                               /* I/O Memory (size=64K) */
+                               <0x01000000 0x00 0x00000000 0x00 0xefff0000 0x00 0x00010000>,
+                               /* 32-bit MMIO (size=2G) */
+                               <0x02000000 0x00 0x40000000 0x00 0x40000000 0x00 0x80000000>,
+                               /* 64-bit MMIO (size= 124G) */
+                               <0x03000000 0x01 0x00000000 0x01 0x00000000 0x7f 0x00000000>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts
deleted file mode 100644 (file)
index 2e25de0..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * dts file for AppliedMicro (APM) Mustang Board
- *
- * Copyright (C) 2013, Applied Micro Circuits Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- */
-
-/dts-v1/;
-
-/include/ "apm-storm.dtsi"
-
-/ {
-       model = "APM X-Gene Mustang board";
-       compatible = "apm,mustang", "apm,xgene-storm";
-
-       chosen { };
-
-       memory {
-               device_type = "memory";
-               reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */
-       };
-};
-
-&pcie0clk {
-       status = "ok";
-};
-
-&pcie0 {
-       status = "ok";
-};
-
-&serial0 {
-       status = "ok";
-};
-
-&menet {
-       status = "ok";
-};
-
-&sgenet0 {
-       status = "ok";
-};
-
-&xgenet {
-       status = "ok";
-};
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
deleted file mode 100644 (file)
index 295c72d..0000000
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * dts file for AppliedMicro (APM) X-Gene Storm SOC
- *
- * Copyright (C) 2013, Applied Micro Circuits Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- */
-
-/ {
-       compatible = "apm,xgene-storm";
-       interrupt-parent = <&gic>;
-       #address-cells = <2>;
-       #size-cells = <2>;
-
-       cpus {
-               #address-cells = <2>;
-               #size-cells = <0>;
-
-               cpu@000 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x000>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-               cpu@001 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x001>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-               cpu@100 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x100>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-               cpu@101 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x101>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-               cpu@200 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x200>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-               cpu@201 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x201>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-               cpu@300 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x300>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-               cpu@301 {
-                       device_type = "cpu";
-                       compatible = "apm,potenza", "arm,armv8";
-                       reg = <0x0 0x301>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x1 0x0000fff8>;
-               };
-       };
-
-       gic: interrupt-controller@78010000 {
-               compatible = "arm,cortex-a15-gic";
-               #interrupt-cells = <3>;
-               interrupt-controller;
-               reg = <0x0 0x78010000 0x0 0x1000>,      /* GIC Dist */
-                     <0x0 0x78020000 0x0 0x1000>,      /* GIC CPU */
-                     <0x0 0x78040000 0x0 0x2000>,      /* GIC VCPU Control */
-                     <0x0 0x78060000 0x0 0x2000>;      /* GIC VCPU */
-               interrupts = <1 9 0xf04>;       /* GIC Maintenence IRQ */
-       };
-
-       timer {
-               compatible = "arm,armv8-timer";
-               interrupts = <1 0 0xff01>,      /* Secure Phys IRQ */
-                            <1 13 0xff01>,     /* Non-secure Phys IRQ */
-                            <1 14 0xff01>,     /* Virt IRQ */
-                            <1 15 0xff01>;     /* Hyp IRQ */
-               clock-frequency = <50000000>;
-       };
-
-       soc {
-               compatible = "simple-bus";
-               #address-cells = <2>;
-               #size-cells = <2>;
-               ranges;
-
-               clocks {
-                       #address-cells = <2>;
-                       #size-cells = <2>;
-                       ranges;
-                       refclk: refclk {
-                               compatible = "fixed-clock";
-                               #clock-cells = <1>;
-                               clock-frequency = <100000000>;
-                               clock-output-names = "refclk";
-                       };
-
-                       pcppll: pcppll@17000100 {
-                               compatible = "apm,xgene-pcppll-clock";
-                               #clock-cells = <1>;
-                               clocks = <&refclk 0>;
-                               clock-names = "pcppll";
-                               reg = <0x0 0x17000100 0x0 0x1000>;
-                               clock-output-names = "pcppll";
-                               type = <0>;
-                       };
-
-                       socpll: socpll@17000120 {
-                               compatible = "apm,xgene-socpll-clock";
-                               #clock-cells = <1>;
-                               clocks = <&refclk 0>;
-                               clock-names = "socpll";
-                               reg = <0x0 0x17000120 0x0 0x1000>;
-                               clock-output-names = "socpll";
-                               type = <1>;
-                       };
-
-                       socplldiv2: socplldiv2  {
-                               compatible = "fixed-factor-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socpll 0>;
-                               clock-names = "socplldiv2";
-                               clock-mult = <1>;
-                               clock-div = <2>;
-                               clock-output-names = "socplldiv2";
-                       };
-
-                       qmlclk: qmlclk {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               clock-names = "qmlclk";
-                               reg = <0x0 0x1703C000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "qmlclk";
-                       };
-
-                       ethclk: ethclk {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               clock-names = "ethclk";
-                               reg = <0x0 0x17000000 0x0 0x1000>;
-                               reg-names = "div-reg";
-                               divider-offset = <0x238>;
-                               divider-width = <0x9>;
-                               divider-shift = <0x0>;
-                               clock-output-names = "ethclk";
-                       };
-
-                       menetclk: menetclk {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&ethclk 0>;
-                               reg = <0x0 0x1702C000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "menetclk";
-                       };
-
-                       sge0clk: sge0clk@1f21c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f21c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               csr-mask = <0x3>;
-                               clock-output-names = "sge0clk";
-                       };
-
-                       xge0clk: xge0clk@1f61c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f61c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               csr-mask = <0x3>;
-                               clock-output-names = "xge0clk";
-                       };
-
-                       sataphy1clk: sataphy1clk@1f21c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f21c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "sataphy1clk";
-                               status = "disabled";
-                               csr-offset = <0x4>;
-                               csr-mask = <0x00>;
-                               enable-offset = <0x0>;
-                               enable-mask = <0x06>;
-                       };
-
-                       sataphy2clk: sataphy1clk@1f22c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f22c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "sataphy2clk";
-                               status = "ok";
-                               csr-offset = <0x4>;
-                               csr-mask = <0x3a>;
-                               enable-offset = <0x0>;
-                               enable-mask = <0x06>;
-                       };
-
-                       sataphy3clk: sataphy1clk@1f23c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f23c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "sataphy3clk";
-                               status = "ok";
-                               csr-offset = <0x4>;
-                               csr-mask = <0x3a>;
-                               enable-offset = <0x0>;
-                               enable-mask = <0x06>;
-                       };
-
-                       sata01clk: sata01clk@1f21c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f21c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "sata01clk";
-                               csr-offset = <0x4>;
-                               csr-mask = <0x05>;
-                               enable-offset = <0x0>;
-                               enable-mask = <0x39>;
-                       };
-
-                       sata23clk: sata23clk@1f22c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f22c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "sata23clk";
-                               csr-offset = <0x4>;
-                               csr-mask = <0x05>;
-                               enable-offset = <0x0>;
-                               enable-mask = <0x39>;
-                       };
-
-                       sata45clk: sata45clk@1f23c000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f23c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "sata45clk";
-                               csr-offset = <0x4>;
-                               csr-mask = <0x05>;
-                               enable-offset = <0x0>;
-                               enable-mask = <0x39>;
-                       };
-
-                       rtcclk: rtcclk@17000000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x17000000 0x0 0x2000>;
-                               reg-names = "csr-reg";
-                               csr-offset = <0xc>;
-                               csr-mask = <0x2>;
-                               enable-offset = <0x10>;
-                               enable-mask = <0x2>;
-                               clock-output-names = "rtcclk";
-                       };
-
-                       rngpkaclk: rngpkaclk@17000000 {
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x17000000 0x0 0x2000>;
-                               reg-names = "csr-reg";
-                               csr-offset = <0xc>;
-                               csr-mask = <0x10>;
-                               enable-offset = <0x10>;
-                               enable-mask = <0x10>;
-                               clock-output-names = "rngpkaclk";
-                       };
-
-                       pcie0clk: pcie0clk@1f2bc000 {
-                               status = "disabled";
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f2bc000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "pcie0clk";
-                       };
-
-                       pcie1clk: pcie1clk@1f2cc000 {
-                               status = "disabled";
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f2cc000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "pcie1clk";
-                       };
-
-                       pcie2clk: pcie2clk@1f2dc000 {
-                               status = "disabled";
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f2dc000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "pcie2clk";
-                       };
-
-                       pcie3clk: pcie3clk@1f50c000 {
-                               status = "disabled";
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f50c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "pcie3clk";
-                       };
-
-                       pcie4clk: pcie4clk@1f51c000 {
-                               status = "disabled";
-                               compatible = "apm,xgene-device-clock";
-                               #clock-cells = <1>;
-                               clocks = <&socplldiv2 0>;
-                               reg = <0x0 0x1f51c000 0x0 0x1000>;
-                               reg-names = "csr-reg";
-                               clock-output-names = "pcie4clk";
-                       };
-               };
-
-               pcie0: pcie@1f2b0000 {
-                       status = "disabled";
-                       device_type = "pci";
-                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       reg = < 0x00 0x1f2b0000 0x0 0x00010000   /* Controller registers */
-                               0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */
-                       reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000   /* io */
-                                 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */
-                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
-                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
-                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1
-                                        0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1
-                                        0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1
-                                        0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>;
-                       dma-coherent;
-                       clocks = <&pcie0clk 0>;
-               };
-
-               pcie1: pcie@1f2c0000 {
-                       status = "disabled";
-                       device_type = "pci";
-                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       reg = < 0x00 0x1f2c0000 0x0 0x00010000   /* Controller registers */
-                               0xd0 0xd0000000 0x0 0x00040000>; /* PCI config space */
-                       reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */
-                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
-                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
-                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x1
-                                        0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x1
-                                        0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x1
-                                        0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x1>;
-                       dma-coherent;
-                       clocks = <&pcie1clk 0>;
-               };
-
-               pcie2: pcie@1f2d0000 {
-                       status = "disabled";
-                       device_type = "pci";
-                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       reg =  < 0x00 0x1f2d0000 0x0 0x00010000   /* Controller registers */
-                                0x90 0xd0000000 0x0 0x00040000>; /* PCI config space */
-                       reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */
-                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
-                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
-                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x1
-                                        0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x1
-                                        0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x1
-                                        0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x1>;
-                       dma-coherent;
-                       clocks = <&pcie2clk 0>;
-               };
-
-               pcie3: pcie@1f500000 {
-                       status = "disabled";
-                       device_type = "pci";
-                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       reg = < 0x00 0x1f500000 0x0 0x00010000   /* Controller registers */
-                               0xa0 0xd0000000 0x0 0x00040000>; /* PCI config space */
-                       reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000   /* io   */
-                                 0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem  */
-                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
-                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
-                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x1
-                                        0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x1
-                                        0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x1
-                                        0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x1>;
-                       dma-coherent;
-                       clocks = <&pcie3clk 0>;
-               };
-
-               pcie4: pcie@1f510000 {
-                       status = "disabled";
-                       device_type = "pci";
-                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
-                       #interrupt-cells = <1>;
-                       #size-cells = <2>;
-                       #address-cells = <3>;
-                       reg = < 0x00 0x1f510000 0x0 0x00010000   /* Controller registers */
-                               0xc0 0xd0000000 0x0 0x00200000>; /* PCI config space */
-                       reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xc0 0x10000000 0x0 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */
-                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
-                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
-                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x1
-                                        0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x1
-                                        0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x1
-                                        0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x1>;
-                       dma-coherent;
-                       clocks = <&pcie4clk 0>;
-               };
-
-               serial0: serial@1c020000 {
-                       status = "disabled";
-                       device_type = "serial";
-                       compatible = "ns16550a";
-                       reg = <0 0x1c020000 0x0 0x1000>;
-                       reg-shift = <2>;
-                       clock-frequency = <10000000>; /* Updated by bootloader */
-                       interrupt-parent = <&gic>;
-                       interrupts = <0x0 0x4c 0x4>;
-               };
-
-               serial1: serial@1c021000 {
-                       status = "disabled";
-                       device_type = "serial";
-                       compatible = "ns16550a";
-                       reg = <0 0x1c021000 0x0 0x1000>;
-                       reg-shift = <2>;
-                       clock-frequency = <10000000>; /* Updated by bootloader */
-                       interrupt-parent = <&gic>;
-                       interrupts = <0x0 0x4d 0x4>;
-               };
-
-               serial2: serial@1c022000 {
-                       status = "disabled";
-                       device_type = "serial";
-                       compatible = "ns16550a";
-                       reg = <0 0x1c022000 0x0 0x1000>;
-                       reg-shift = <2>;
-                       clock-frequency = <10000000>; /* Updated by bootloader */
-                       interrupt-parent = <&gic>;
-                       interrupts = <0x0 0x4e 0x4>;
-               };
-
-               serial3: serial@1c023000 {
-                       status = "disabled";
-                       device_type = "serial";
-                       compatible = "ns16550a";
-                       reg = <0 0x1c023000 0x0 0x1000>;
-                       reg-shift = <2>;
-                       clock-frequency = <10000000>; /* Updated by bootloader */
-                       interrupt-parent = <&gic>;
-                       interrupts = <0x0 0x4f 0x4>;
-               };
-
-               phy1: phy@1f21a000 {
-                       compatible = "apm,xgene-phy";
-                       reg = <0x0 0x1f21a000 0x0 0x100>;
-                       #phy-cells = <1>;
-                       clocks = <&sataphy1clk 0>;
-                       status = "disabled";
-                       apm,tx-boost-gain = <30 30 30 30 30 30>;
-                       apm,tx-eye-tuning = <2 10 10 2 10 10>;
-               };
-
-               phy2: phy@1f22a000 {
-                       compatible = "apm,xgene-phy";
-                       reg = <0x0 0x1f22a000 0x0 0x100>;
-                       #phy-cells = <1>;
-                       clocks = <&sataphy2clk 0>;
-                       status = "ok";
-                       apm,tx-boost-gain = <30 30 30 30 30 30>;
-                       apm,tx-eye-tuning = <1 10 10 2 10 10>;
-               };
-
-               phy3: phy@1f23a000 {
-                       compatible = "apm,xgene-phy";
-                       reg = <0x0 0x1f23a000 0x0 0x100>;
-                       #phy-cells = <1>;
-                       clocks = <&sataphy3clk 0>;
-                       status = "ok";
-                       apm,tx-boost-gain = <31 31 31 31 31 31>;
-                       apm,tx-eye-tuning = <2 10 10 2 10 10>;
-               };
-
-               sata1: sata@1a000000 {
-                       compatible = "apm,xgene-ahci";
-                       reg = <0x0 0x1a000000 0x0 0x1000>,
-                             <0x0 0x1f210000 0x0 0x1000>,
-                             <0x0 0x1f21d000 0x0 0x1000>,
-                             <0x0 0x1f21e000 0x0 0x1000>,
-                             <0x0 0x1f217000 0x0 0x1000>;
-                       interrupts = <0x0 0x86 0x4>;
-                       dma-coherent;
-                       status = "disabled";
-                       clocks = <&sata01clk 0>;
-                       phys = <&phy1 0>;
-                       phy-names = "sata-phy";
-               };
-
-               sata2: sata@1a400000 {
-                       compatible = "apm,xgene-ahci";
-                       reg = <0x0 0x1a400000 0x0 0x1000>,
-                             <0x0 0x1f220000 0x0 0x1000>,
-                             <0x0 0x1f22d000 0x0 0x1000>,
-                             <0x0 0x1f22e000 0x0 0x1000>,
-                             <0x0 0x1f227000 0x0 0x1000>;
-                       interrupts = <0x0 0x87 0x4>;
-                       dma-coherent;
-                       status = "ok";
-                       clocks = <&sata23clk 0>;
-                       phys = <&phy2 0>;
-                       phy-names = "sata-phy";
-               };
-
-               sata3: sata@1a800000 {
-                       compatible = "apm,xgene-ahci";
-                       reg = <0x0 0x1a800000 0x0 0x1000>,
-                             <0x0 0x1f230000 0x0 0x1000>,
-                             <0x0 0x1f23d000 0x0 0x1000>,
-                             <0x0 0x1f23e000 0x0 0x1000>;
-                       interrupts = <0x0 0x88 0x4>;
-                       dma-coherent;
-                       status = "ok";
-                       clocks = <&sata45clk 0>;
-                       phys = <&phy3 0>;
-                       phy-names = "sata-phy";
-               };
-
-               rtc: rtc@10510000 {
-                       compatible = "apm,xgene-rtc";
-                       reg = <0x0 0x10510000 0x0 0x400>;
-                       interrupts = <0x0 0x46 0x4>;
-                       #clock-cells = <1>;
-                       clocks = <&rtcclk 0>;
-               };
-
-               menet: ethernet@17020000 {
-                       compatible = "apm,xgene-enet";
-                       status = "disabled";
-                       reg = <0x0 0x17020000 0x0 0xd100>,
-                             <0x0 0X17030000 0x0 0X400>,
-                             <0x0 0X10000000 0x0 0X200>;
-                       reg-names = "enet_csr", "ring_csr", "ring_cmd";
-                       interrupts = <0x0 0x3c 0x4>;
-                       dma-coherent;
-                       clocks = <&menetclk 0>;
-                       /* mac address will be overwritten by the bootloader */
-                       local-mac-address = [00 00 00 00 00 00];
-                       phy-connection-type = "rgmii";
-                       phy-handle = <&menetphy>;
-                       mdio {
-                               compatible = "apm,xgene-mdio";
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               menetphy: menetphy@3 {
-                                       compatible = "ethernet-phy-id001c.c915";
-                                       reg = <0x3>;
-                               };
-
-                       };
-               };
-
-               sgenet0: ethernet@1f210000 {
-                       compatible = "apm,xgene-enet";
-                       status = "disabled";
-                       reg = <0x0 0x1f210000 0x0 0x10000>,
-                             <0x0 0x1f200000 0x0 0X10000>,
-                             <0x0 0x1B000000 0x0 0X20000>;
-                       reg-names = "enet_csr", "ring_csr", "ring_cmd";
-                       interrupts = <0x0 0xA0 0x4>;
-                       dma-coherent;
-                       clocks = <&sge0clk 0>;
-                       local-mac-address = [00 00 00 00 00 00];
-                       phy-connection-type = "sgmii";
-               };
-
-               xgenet: ethernet@1f610000 {
-                       compatible = "apm,xgene-enet";
-                       status = "disabled";
-                       reg = <0x0 0x1f610000 0x0 0xd100>,
-                             <0x0 0x1f600000 0x0 0X400>,
-                             <0x0 0x18000000 0x0 0X200>;
-                       reg-names = "enet_csr", "ring_csr", "ring_cmd";
-                       interrupts = <0x0 0x60 0x4>;
-                       dma-coherent;
-                       clocks = <&xge0clk 0>;
-                       /* mac address will be overwritten by the bootloader */
-                       local-mac-address = [00 00 00 00 00 00];
-                       phy-connection-type = "xgmii";
-               };
-
-               rng: rng@10520000 {
-                       compatible = "apm,xgene-rng";
-                       reg = <0x0 0x10520000 0x0 0x100>;
-                       interrupts = <0x0 0x41 0x4>;
-                       clocks = <&rngpkaclk 0>;
-               };
-       };
-};
diff --git a/arch/arm64/boot/dts/apm/Makefile b/arch/arm64/boot/dts/apm/Makefile
new file mode 100644 (file)
index 0000000..a2afabb
--- /dev/null
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb
+
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/apm/apm-mustang.dts b/arch/arm64/boot/dts/apm/apm-mustang.dts
new file mode 100644 (file)
index 0000000..2e25de0
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * dts file for AppliedMicro (APM) Mustang Board
+ *
+ * Copyright (C) 2013, Applied Micro Circuits Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+/dts-v1/;
+
+/include/ "apm-storm.dtsi"
+
+/ {
+       model = "APM X-Gene Mustang board";
+       compatible = "apm,mustang", "apm,xgene-storm";
+
+       chosen { };
+
+       memory {
+               device_type = "memory";
+               reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */
+       };
+};
+
+&pcie0clk {
+       status = "ok";
+};
+
+&pcie0 {
+       status = "ok";
+};
+
+&serial0 {
+       status = "ok";
+};
+
+&menet {
+       status = "ok";
+};
+
+&sgenet0 {
+       status = "ok";
+};
+
+&xgenet {
+       status = "ok";
+};
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
new file mode 100644 (file)
index 0000000..f1ad9c2
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * dts file for AppliedMicro (APM) X-Gene Storm SOC
+ *
+ * Copyright (C) 2013, Applied Micro Circuits Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+/ {
+       compatible = "apm,xgene-storm";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu@000 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x000>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+               cpu@001 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x001>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+               cpu@100 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x100>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+               cpu@101 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x101>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+               cpu@200 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x200>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+               cpu@201 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x201>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+               cpu@300 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x300>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+               cpu@301 {
+                       device_type = "cpu";
+                       compatible = "apm,potenza", "arm,armv8";
+                       reg = <0x0 0x301>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x1 0x0000fff8>;
+               };
+       };
+
+       gic: interrupt-controller@78010000 {
+               compatible = "arm,cortex-a15-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x0 0x78010000 0x0 0x1000>,      /* GIC Dist */
+                     <0x0 0x78020000 0x0 0x1000>,      /* GIC CPU */
+                     <0x0 0x78040000 0x0 0x2000>,      /* GIC VCPU Control */
+                     <0x0 0x78060000 0x0 0x2000>;      /* GIC VCPU */
+               interrupts = <1 9 0xf04>;       /* GIC Maintenence IRQ */
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 0 0xff01>,      /* Secure Phys IRQ */
+                            <1 13 0xff01>,     /* Non-secure Phys IRQ */
+                            <1 14 0xff01>,     /* Virt IRQ */
+                            <1 15 0xff01>;     /* Hyp IRQ */
+               clock-frequency = <50000000>;
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               clocks {
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+                       refclk: refclk {
+                               compatible = "fixed-clock";
+                               #clock-cells = <1>;
+                               clock-frequency = <100000000>;
+                               clock-output-names = "refclk";
+                       };
+
+                       pcppll: pcppll@17000100 {
+                               compatible = "apm,xgene-pcppll-clock";
+                               #clock-cells = <1>;
+                               clocks = <&refclk 0>;
+                               clock-names = "pcppll";
+                               reg = <0x0 0x17000100 0x0 0x1000>;
+                               clock-output-names = "pcppll";
+                               type = <0>;
+                       };
+
+                       socpll: socpll@17000120 {
+                               compatible = "apm,xgene-socpll-clock";
+                               #clock-cells = <1>;
+                               clocks = <&refclk 0>;
+                               clock-names = "socpll";
+                               reg = <0x0 0x17000120 0x0 0x1000>;
+                               clock-output-names = "socpll";
+                               type = <1>;
+                       };
+
+                       socplldiv2: socplldiv2  {
+                               compatible = "fixed-factor-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socpll 0>;
+                               clock-names = "socplldiv2";
+                               clock-mult = <1>;
+                               clock-div = <2>;
+                               clock-output-names = "socplldiv2";
+                       };
+
+                       qmlclk: qmlclk {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               clock-names = "qmlclk";
+                               reg = <0x0 0x1703C000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "qmlclk";
+                       };
+
+                       ethclk: ethclk {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               clock-names = "ethclk";
+                               reg = <0x0 0x17000000 0x0 0x1000>;
+                               reg-names = "div-reg";
+                               divider-offset = <0x238>;
+                               divider-width = <0x9>;
+                               divider-shift = <0x0>;
+                               clock-output-names = "ethclk";
+                       };
+
+                       menetclk: menetclk {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&ethclk 0>;
+                               reg = <0x0 0x1702C000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "menetclk";
+                       };
+
+                       sge0clk: sge0clk@1f21c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f21c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               csr-mask = <0x3>;
+                               clock-output-names = "sge0clk";
+                       };
+
+                       xge0clk: xge0clk@1f61c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f61c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               csr-mask = <0x3>;
+                               clock-output-names = "xge0clk";
+                       };
+
+                       sataphy1clk: sataphy1clk@1f21c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f21c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sataphy1clk";
+                               status = "disabled";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x00>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x06>;
+                       };
+
+                       sataphy2clk: sataphy1clk@1f22c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f22c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sataphy2clk";
+                               status = "ok";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x3a>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x06>;
+                       };
+
+                       sataphy3clk: sataphy1clk@1f23c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f23c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sataphy3clk";
+                               status = "ok";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x3a>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x06>;
+                       };
+
+                       sata01clk: sata01clk@1f21c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f21c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sata01clk";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x05>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x39>;
+                       };
+
+                       sata23clk: sata23clk@1f22c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f22c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sata23clk";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x05>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x39>;
+                       };
+
+                       sata45clk: sata45clk@1f23c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f23c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "sata45clk";
+                               csr-offset = <0x4>;
+                               csr-mask = <0x05>;
+                               enable-offset = <0x0>;
+                               enable-mask = <0x39>;
+                       };
+
+                       rtcclk: rtcclk@17000000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x17000000 0x0 0x2000>;
+                               reg-names = "csr-reg";
+                               csr-offset = <0xc>;
+                               csr-mask = <0x2>;
+                               enable-offset = <0x10>;
+                               enable-mask = <0x2>;
+                               clock-output-names = "rtcclk";
+                       };
+
+                       rngpkaclk: rngpkaclk@17000000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x17000000 0x0 0x2000>;
+                               reg-names = "csr-reg";
+                               csr-offset = <0xc>;
+                               csr-mask = <0x10>;
+                               enable-offset = <0x10>;
+                               enable-mask = <0x10>;
+                               clock-output-names = "rngpkaclk";
+                       };
+
+                       pcie0clk: pcie0clk@1f2bc000 {
+                               status = "disabled";
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f2bc000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "pcie0clk";
+                       };
+
+                       pcie1clk: pcie1clk@1f2cc000 {
+                               status = "disabled";
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f2cc000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "pcie1clk";
+                       };
+
+                       pcie2clk: pcie2clk@1f2dc000 {
+                               status = "disabled";
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f2dc000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "pcie2clk";
+                       };
+
+                       pcie3clk: pcie3clk@1f50c000 {
+                               status = "disabled";
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f50c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "pcie3clk";
+                       };
+
+                       pcie4clk: pcie4clk@1f51c000 {
+                               status = "disabled";
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f51c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "pcie4clk";
+                       };
+               };
+
+               pcie0: pcie@1f2b0000 {
+                       status = "disabled";
+                       device_type = "pci";
+                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = < 0x00 0x1f2b0000 0x0 0x00010000   /* Controller registers */
+                               0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */
+                       reg-names = "csr", "cfg";
+                       ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000   /* io */
+                                 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */
+                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
+                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc2 0x1
+                                        0x0 0x0 0x0 0x2 &gic 0x0 0xc3 0x1
+                                        0x0 0x0 0x0 0x3 &gic 0x0 0xc4 0x1
+                                        0x0 0x0 0x0 0x4 &gic 0x0 0xc5 0x1>;
+                       dma-coherent;
+                       clocks = <&pcie0clk 0>;
+               };
+
+               pcie1: pcie@1f2c0000 {
+                       status = "disabled";
+                       device_type = "pci";
+                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = < 0x00 0x1f2c0000 0x0 0x00010000   /* Controller registers */
+                               0xd0 0xd0000000 0x0 0x00040000>; /* PCI config space */
+                       reg-names = "csr", "cfg";
+                       ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */
+                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
+                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xc8 0x1
+                                        0x0 0x0 0x0 0x2 &gic 0x0 0xc9 0x1
+                                        0x0 0x0 0x0 0x3 &gic 0x0 0xca 0x1
+                                        0x0 0x0 0x0 0x4 &gic 0x0 0xcb 0x1>;
+                       dma-coherent;
+                       clocks = <&pcie1clk 0>;
+               };
+
+               pcie2: pcie@1f2d0000 {
+                       status = "disabled";
+                       device_type = "pci";
+                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg =  < 0x00 0x1f2d0000 0x0 0x00010000   /* Controller registers */
+                                0x90 0xd0000000 0x0 0x00040000>; /* PCI config space */
+                       reg-names = "csr", "cfg";
+                       ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000   /* io  */
+                                 0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */
+                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
+                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xce 0x1
+                                        0x0 0x0 0x0 0x2 &gic 0x0 0xcf 0x1
+                                        0x0 0x0 0x0 0x3 &gic 0x0 0xd0 0x1
+                                        0x0 0x0 0x0 0x4 &gic 0x0 0xd1 0x1>;
+                       dma-coherent;
+                       clocks = <&pcie2clk 0>;
+               };
+
+               pcie3: pcie@1f500000 {
+                       status = "disabled";
+                       device_type = "pci";
+                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = < 0x00 0x1f500000 0x0 0x00010000   /* Controller registers */
+                               0xa0 0xd0000000 0x0 0x00040000>; /* PCI config space */
+                       reg-names = "csr", "cfg";
+                       ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000   /* io   */
+                                 0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem  */
+                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
+                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xd4 0x1
+                                        0x0 0x0 0x0 0x2 &gic 0x0 0xd5 0x1
+                                        0x0 0x0 0x0 0x3 &gic 0x0 0xd6 0x1
+                                        0x0 0x0 0x0 0x4 &gic 0x0 0xd7 0x1>;
+                       dma-coherent;
+                       clocks = <&pcie3clk 0>;
+               };
+
+               pcie4: pcie@1f510000 {
+                       status = "disabled";
+                       device_type = "pci";
+                       compatible = "apm,xgene-storm-pcie", "apm,xgene-pcie";
+                       #interrupt-cells = <1>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       reg = < 0x00 0x1f510000 0x0 0x00010000   /* Controller registers */
+                               0xc0 0xd0000000 0x0 0x00200000>; /* PCI config space */
+                       reg-names = "csr", "cfg";
+                       ranges = <0x01000000 0x0 0x00000000 0xc0 0x10000000 0x0 0x00010000   /* io  */
+                                 0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */
+                       dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
+                                     0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
+                       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+                       interrupt-map = <0x0 0x0 0x0 0x1 &gic 0x0 0xda 0x1
+                                        0x0 0x0 0x0 0x2 &gic 0x0 0xdb 0x1
+                                        0x0 0x0 0x0 0x3 &gic 0x0 0xdc 0x1
+                                        0x0 0x0 0x0 0x4 &gic 0x0 0xdd 0x1>;
+                       dma-coherent;
+                       clocks = <&pcie4clk 0>;
+               };
+
+               serial0: serial@1c020000 {
+                       status = "disabled";
+                       device_type = "serial";
+                       compatible = "ns16550a";
+                       reg = <0 0x1c020000 0x0 0x1000>;
+                       reg-shift = <2>;
+                       clock-frequency = <10000000>; /* Updated by bootloader */
+                       interrupt-parent = <&gic>;
+                       interrupts = <0x0 0x4c 0x4>;
+               };
+
+               serial1: serial@1c021000 {
+                       status = "disabled";
+                       device_type = "serial";
+                       compatible = "ns16550a";
+                       reg = <0 0x1c021000 0x0 0x1000>;
+                       reg-shift = <2>;
+                       clock-frequency = <10000000>; /* Updated by bootloader */
+                       interrupt-parent = <&gic>;
+                       interrupts = <0x0 0x4d 0x4>;
+               };
+
+               serial2: serial@1c022000 {
+                       status = "disabled";
+                       device_type = "serial";
+                       compatible = "ns16550a";
+                       reg = <0 0x1c022000 0x0 0x1000>;
+                       reg-shift = <2>;
+                       clock-frequency = <10000000>; /* Updated by bootloader */
+                       interrupt-parent = <&gic>;
+                       interrupts = <0x0 0x4e 0x4>;
+               };
+
+               serial3: serial@1c023000 {
+                       status = "disabled";
+                       device_type = "serial";
+                       compatible = "ns16550a";
+                       reg = <0 0x1c023000 0x0 0x1000>;
+                       reg-shift = <2>;
+                       clock-frequency = <10000000>; /* Updated by bootloader */
+                       interrupt-parent = <&gic>;
+                       interrupts = <0x0 0x4f 0x4>;
+               };
+
+               phy1: phy@1f21a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f21a000 0x0 0x100>;
+                       #phy-cells = <1>;
+                       clocks = <&sataphy1clk 0>;
+                       status = "disabled";
+                       apm,tx-boost-gain = <30 30 30 30 30 30>;
+                       apm,tx-eye-tuning = <2 10 10 2 10 10>;
+               };
+
+               phy2: phy@1f22a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f22a000 0x0 0x100>;
+                       #phy-cells = <1>;
+                       clocks = <&sataphy2clk 0>;
+                       status = "ok";
+                       apm,tx-boost-gain = <30 30 30 30 30 30>;
+                       apm,tx-eye-tuning = <1 10 10 2 10 10>;
+               };
+
+               phy3: phy@1f23a000 {
+                       compatible = "apm,xgene-phy";
+                       reg = <0x0 0x1f23a000 0x0 0x100>;
+                       #phy-cells = <1>;
+                       clocks = <&sataphy3clk 0>;
+                       status = "ok";
+                       apm,tx-boost-gain = <31 31 31 31 31 31>;
+                       apm,tx-eye-tuning = <2 10 10 2 10 10>;
+               };
+
+               sata1: sata@1a000000 {
+                       compatible = "apm,xgene-ahci";
+                       reg = <0x0 0x1a000000 0x0 0x1000>,
+                             <0x0 0x1f210000 0x0 0x1000>,
+                             <0x0 0x1f21d000 0x0 0x1000>,
+                             <0x0 0x1f21e000 0x0 0x1000>,
+                             <0x0 0x1f217000 0x0 0x1000>;
+                       interrupts = <0x0 0x86 0x4>;
+                       dma-coherent;
+                       status = "disabled";
+                       clocks = <&sata01clk 0>;
+                       phys = <&phy1 0>;
+                       phy-names = "sata-phy";
+               };
+
+               sata2: sata@1a400000 {
+                       compatible = "apm,xgene-ahci";
+                       reg = <0x0 0x1a400000 0x0 0x1000>,
+                             <0x0 0x1f220000 0x0 0x1000>,
+                             <0x0 0x1f22d000 0x0 0x1000>,
+                             <0x0 0x1f22e000 0x0 0x1000>,
+                             <0x0 0x1f227000 0x0 0x1000>;
+                       interrupts = <0x0 0x87 0x4>;
+                       dma-coherent;
+                       status = "ok";
+                       clocks = <&sata23clk 0>;
+                       phys = <&phy2 0>;
+                       phy-names = "sata-phy";
+               };
+
+               sata3: sata@1a800000 {
+                       compatible = "apm,xgene-ahci";
+                       reg = <0x0 0x1a800000 0x0 0x1000>,
+                             <0x0 0x1f230000 0x0 0x1000>,
+                             <0x0 0x1f23d000 0x0 0x1000>,
+                             <0x0 0x1f23e000 0x0 0x1000>;
+                       interrupts = <0x0 0x88 0x4>;
+                       dma-coherent;
+                       status = "ok";
+                       clocks = <&sata45clk 0>;
+                       phys = <&phy3 0>;
+                       phy-names = "sata-phy";
+               };
+
+               rtc: rtc@10510000 {
+                       compatible = "apm,xgene-rtc";
+                       reg = <0x0 0x10510000 0x0 0x400>;
+                       interrupts = <0x0 0x46 0x4>;
+                       #clock-cells = <1>;
+                       clocks = <&rtcclk 0>;
+               };
+
+               menet: ethernet@17020000 {
+                       compatible = "apm,xgene-enet";
+                       status = "disabled";
+                       reg = <0x0 0x17020000 0x0 0xd100>,
+                             <0x0 0X17030000 0x0 0Xc300>,
+                             <0x0 0X10000000 0x0 0X200>;
+                       reg-names = "enet_csr", "ring_csr", "ring_cmd";
+                       interrupts = <0x0 0x3c 0x4>;
+                       dma-coherent;
+                       clocks = <&menetclk 0>;
+                       /* mac address will be overwritten by the bootloader */
+                       local-mac-address = [00 00 00 00 00 00];
+                       phy-connection-type = "rgmii";
+                       phy-handle = <&menetphy>;
+                       mdio {
+                               compatible = "apm,xgene-mdio";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               menetphy: menetphy@3 {
+                                       compatible = "ethernet-phy-id001c.c915";
+                                       reg = <0x3>;
+                               };
+
+                       };
+               };
+
+               sgenet0: ethernet@1f210000 {
+                       compatible = "apm,xgene-enet";
+                       status = "disabled";
+                       reg = <0x0 0x1f210000 0x0 0xd100>,
+                             <0x0 0x1f200000 0x0 0Xc300>,
+                             <0x0 0x1B000000 0x0 0X200>;
+                       reg-names = "enet_csr", "ring_csr", "ring_cmd";
+                       interrupts = <0x0 0xA0 0x4>;
+                       dma-coherent;
+                       clocks = <&sge0clk 0>;
+                       local-mac-address = [00 00 00 00 00 00];
+                       phy-connection-type = "sgmii";
+               };
+
+               xgenet: ethernet@1f610000 {
+                       compatible = "apm,xgene-enet";
+                       status = "disabled";
+                       reg = <0x0 0x1f610000 0x0 0xd100>,
+                             <0x0 0x1f600000 0x0 0Xc300>,
+                             <0x0 0x18000000 0x0 0X200>;
+                       reg-names = "enet_csr", "ring_csr", "ring_cmd";
+                       interrupts = <0x0 0x60 0x4>;
+                       dma-coherent;
+                       clocks = <&xge0clk 0>;
+                       /* mac address will be overwritten by the bootloader */
+                       local-mac-address = [00 00 00 00 00 00];
+                       phy-connection-type = "xgmii";
+               };
+
+               rng: rng@10520000 {
+                       compatible = "apm,xgene-rng";
+                       reg = <0x0 0x10520000 0x0 0x100>;
+                       interrupts = <0x0 0x41 0x4>;
+                       clocks = <&rngpkaclk 0>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/arm/Makefile b/arch/arm64/boot/dts/arm/Makefile
new file mode 100644 (file)
index 0000000..301a0da
--- /dev/null
@@ -0,0 +1,7 @@
+dtb-$(CONFIG_ARCH_VEXPRESS) += foundation-v8.dtb
+dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb
+dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb
+
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dts b/arch/arm64/boot/dts/arm/foundation-v8.dts
new file mode 100644 (file)
index 0000000..27f3296
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * ARM Ltd.
+ *
+ * ARMv8 Foundation model DTS
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+       model = "Foundation-v8A";
+       compatible = "arm,foundation-aarch64", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x80000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x0 0x2c001000 0 0x1000>,
+                     <0x0 0x2c002000 0 0x1000>,
+                     <0x0 0x2c004000 0 0x2000>,
+                     <0x0 0x2c006000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xf08>,
+                            <1 14 0xf08>,
+                            <1 11 0xf08>,
+                            <1 10 0xf08>;
+               clock-frequency = <100000000>;
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
+               arm,v2m-memory-map = "rs1";
+               #address-cells = <2>; /* SMB chipselect number and offset */
+               #size-cells = <1>;
+
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0  0 4>,
+                               <0 0  1 &gic 0  1 4>,
+                               <0 0  2 &gic 0  2 4>,
+                               <0 0  3 &gic 0  3 4>,
+                               <0 0  4 &gic 0  4 4>,
+                               <0 0  5 &gic 0  5 4>,
+                               <0 0  6 &gic 0  6 4>,
+                               <0 0  7 &gic 0  7 4>,
+                               <0 0  8 &gic 0  8 4>,
+                               <0 0  9 &gic 0  9 4>,
+                               <0 0 10 &gic 0 10 4>,
+                               <0 0 11 &gic 0 11 4>,
+                               <0 0 12 &gic 0 12 4>,
+                               <0 0 13 &gic 0 13 4>,
+                               <0 0 14 &gic 0 14 4>,
+                               <0 0 15 &gic 0 15 4>,
+                               <0 0 16 &gic 0 16 4>,
+                               <0 0 17 &gic 0 17 4>,
+                               <0 0 18 &gic 0 18 4>,
+                               <0 0 19 &gic 0 19 4>,
+                               <0 0 20 &gic 0 20 4>,
+                               <0 0 21 &gic 0 21 4>,
+                               <0 0 22 &gic 0 22 4>,
+                               <0 0 23 &gic 0 23 4>,
+                               <0 0 24 &gic 0 24 4>,
+                               <0 0 25 &gic 0 25 4>,
+                               <0 0 26 &gic 0 26 4>,
+                               <0 0 27 &gic 0 27 4>,
+                               <0 0 28 &gic 0 28 4>,
+                               <0 0 29 &gic 0 29 4>,
+                               <0 0 30 &gic 0 30 4>,
+                               <0 0 31 &gic 0 31 4>,
+                               <0 0 32 &gic 0 32 4>,
+                               <0 0 33 &gic 0 33 4>,
+                               <0 0 34 &gic 0 34 4>,
+                               <0 0 35 &gic 0 35 4>,
+                               <0 0 36 &gic 0 36 4>,
+                               <0 0 37 &gic 0 37 4>,
+                               <0 0 38 &gic 0 38 4>,
+                               <0 0 39 &gic 0 39 4>,
+                               <0 0 40 &gic 0 40 4>,
+                               <0 0 41 &gic 0 41 4>,
+                               <0 0 42 &gic 0 42 4>;
+
+               ethernet@2,02000000 {
+                       compatible = "smsc,lan91c111";
+                       reg = <2 0x02000000 0x10000>;
+                       interrupts = <15>;
+               };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               iofpga@3,00000000 {
+                       compatible = "arm,amba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 3 0 0x200000>;
+
+                       v2m_sysreg: sysreg@010000 {
+                               compatible = "arm,vexpress-sysreg";
+                               reg = <0x010000 0x1000>;
+                       };
+
+                       v2m_serial0: uart@090000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x090000 0x1000>;
+                               interrupts = <5>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial1: uart@0a0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0a0000 0x1000>;
+                               interrupts = <6>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial2: uart@0b0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0b0000 0x1000>;
+                               interrupts = <7>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial3: uart@0c0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0c0000 0x1000>;
+                               interrupts = <8>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       virtio_block@0130000 {
+                               compatible = "virtio,mmio";
+                               reg = <0x130000 0x200>;
+                               interrupts = <42>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/arm/juno-clocks.dtsi b/arch/arm64/boot/dts/arm/juno-clocks.dtsi
new file mode 100644 (file)
index 0000000..ea2b566
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * ARM Juno Platform clocks
+ *
+ * Copyright (c) 2013-2014 ARM Ltd
+ *
+ * This file is licensed under a dual GPLv2 or BSD license.
+ *
+ */
+
+       /* SoC fixed clocks */
+       soc_uartclk: refclk72738khz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <7273800>;
+               clock-output-names = "juno:uartclk";
+       };
+
+       soc_usb48mhz: clk48mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <48000000>;
+               clock-output-names = "clk48mhz";
+       };
+
+       soc_smc50mhz: clk50mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <50000000>;
+               clock-output-names = "smc_clk";
+       };
+
+       soc_refclk100mhz: refclk100mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+               clock-output-names = "apb_pclk";
+       };
+
+       soc_faxiclk: refclk533mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <533000000>;
+               clock-output-names = "faxi_clk";
+       };
diff --git a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
new file mode 100644 (file)
index 0000000..c138b95
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * ARM Juno Platform motherboard peripherals
+ *
+ * Copyright (c) 2013-2014 ARM Ltd
+ *
+ * This file is licensed under a dual GPLv2 or BSD license.
+ *
+ */
+
+               mb_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "juno_mb:clk24mhz";
+               };
+
+               mb_clk25mhz: clk25mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <25000000>;
+                       clock-output-names = "juno_mb:clk25mhz";
+               };
+
+               motherboard {
+                       compatible = "arm,vexpress,v2p-p1", "simple-bus";
+                       #address-cells = <2>;  /* SMB chipselect number and offset */
+                       #size-cells = <1>;
+                       #interrupt-cells = <1>;
+                       ranges;
+                       model = "V2M-Juno";
+                       arm,hbi = <0x252>;
+                       arm,vexpress,site = <0>;
+                       arm,v2m-memory-map = "rs1";
+
+                       mb_fixed_3v3: fixedregulator@0 {
+                               compatible = "regulator-fixed";
+                               regulator-name = "MCC_SB_3V3";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       ethernet@2,00000000 {
+                               compatible = "smsc,lan9118", "smsc,lan9115";
+                               reg = <2 0x00000000 0x10000>;
+                               interrupts = <3>;
+                               phy-mode = "mii";
+                               reg-io-width = <4>;
+                               smsc,irq-active-high;
+                               smsc,irq-push-pull;
+                               clocks = <&mb_clk25mhz>;
+                               vdd33a-supply = <&mb_fixed_3v3>;
+                               vddvario-supply = <&mb_fixed_3v3>;
+                       };
+
+                       usb@5,00000000 {
+                               compatible = "nxp,usb-isp1763";
+                               reg = <5 0x00000000 0x20000>;
+                               bus-width = <16>;
+                               interrupts = <4>;
+                       };
+
+                       iofpga@3,00000000 {
+                               compatible = "arm,amba-bus", "simple-bus";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 3 0 0x200000>;
+
+                               mmci@050000 {
+                                       compatible = "arm,pl180", "arm,primecell";
+                                       reg = <0x050000 0x1000>;
+                                       interrupts = <5>;
+                                       /* cd-gpios = <&v2m_mmc_gpios 0 0>;
+                                       wp-gpios = <&v2m_mmc_gpios 1 0>; */
+                                       max-frequency = <12000000>;
+                                       vmmc-supply = <&mb_fixed_3v3>;
+                                       clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
+                                       clock-names = "mclk", "apb_pclk";
+                               };
+
+                               kmi@060000 {
+                                       compatible = "arm,pl050", "arm,primecell";
+                                       reg = <0x060000 0x1000>;
+                                       interrupts = <8>;
+                                       clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
+                                       clock-names = "KMIREFCLK", "apb_pclk";
+                               };
+
+                               kmi@070000 {
+                                       compatible = "arm,pl050", "arm,primecell";
+                                       reg = <0x070000 0x1000>;
+                                       interrupts = <8>;
+                                       clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
+                                       clock-names = "KMIREFCLK", "apb_pclk";
+                               };
+
+                               wdt@0f0000 {
+                                       compatible = "arm,sp805", "arm,primecell";
+                                       reg = <0x0f0000 0x10000>;
+                                       interrupts = <7>;
+                                       clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
+                                       clock-names = "wdogclk", "apb_pclk";
+                               };
+
+                               v2m_timer01: timer@110000 {
+                                       compatible = "arm,sp804", "arm,primecell";
+                                       reg = <0x110000 0x10000>;
+                                       interrupts = <9>;
+                                       clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
+                                       clock-names = "timclken1", "apb_pclk";
+                               };
+
+                               v2m_timer23: timer@120000 {
+                                       compatible = "arm,sp804", "arm,primecell";
+                                       reg = <0x120000 0x10000>;
+                                       interrupts = <9>;
+                                       clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
+                                       clock-names = "timclken1", "apb_pclk";
+                               };
+
+                               rtc@170000 {
+                                       compatible = "arm,pl031", "arm,primecell";
+                                       reg = <0x170000 0x10000>;
+                                       interrupts = <0>;
+                                       clocks = <&soc_smc50mhz>;
+                                       clock-names = "apb_pclk";
+                               };
+                       };
+               };
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
new file mode 100644 (file)
index 0000000..cb3073e
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * ARM Ltd. Juno Platform
+ *
+ * Copyright (c) 2013-2014 ARM Ltd.
+ *
+ * This file is licensed under a dual GPLv2 or BSD license.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       model = "ARM Juno development board (r0)";
+       compatible = "arm,juno", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       aliases {
+               serial0 = &soc_uart0;
+       };
+
+       chosen {
+               stdout-path = &soc_uart0;
+       };
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               A57_0: cpu@0 {
+                       compatible = "arm,cortex-a57","arm,armv8";
+                       reg = <0x0 0x0>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+               };
+
+               A57_1: cpu@1 {
+                       compatible = "arm,cortex-a57","arm,armv8";
+                       reg = <0x0 0x1>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+               };
+
+               A53_0: cpu@100 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x0 0x100>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+               };
+
+               A53_1: cpu@101 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x0 0x101>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+               };
+
+               A53_2: cpu@102 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x0 0x102>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+               };
+
+               A53_3: cpu@103 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x0 0x103>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               /* last 16MB of the first memory area is reserved for secure world use by firmware */
+               reg = <0x00000000 0x80000000 0x0 0x7f000000>,
+                     <0x00000008 0x80000000 0x1 0x80000000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,gic-400", "arm,cortex-a15-gic";
+               reg = <0x0 0x2c010000 0 0x1000>,
+                     <0x0 0x2c02f000 0 0x2000>,
+                     <0x0 0x2c04f000 0 0x2000>,
+                     <0x0 0x2c06f000 0 0x2000>;
+               #address-cells = <0>;
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <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>;
+       };
+
+       /include/ "juno-clocks.dtsi"
+
+       dma@7ff00000 {
+               compatible = "arm,pl330", "arm,primecell";
+               reg = <0x0 0x7ff00000 0 0x1000>;
+               #dma-cells = <1>;
+               #dma-channels = <8>;
+               #dma-requests = <32>;
+               interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&soc_faxiclk>;
+               clock-names = "apb_pclk";
+       };
+
+       soc_uart0: uart@7ff80000 {
+               compatible = "arm,pl011", "arm,primecell";
+               reg = <0x0 0x7ff80000 0x0 0x1000>;
+               interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+               clock-names = "uartclk", "apb_pclk";
+       };
+
+       i2c@7ffa0000 {
+               compatible = "snps,designware-i2c";
+               reg = <0x0 0x7ffa0000 0x0 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+               clock-frequency = <400000>;
+               i2c-sda-hold-time-ns = <500>;
+               clocks = <&soc_smc50mhz>;
+
+               dvi0: dvi-transmitter@70 {
+                       compatible = "nxp,tda998x";
+                       reg = <0x70>;
+               };
+
+               dvi1: dvi-transmitter@71 {
+                       compatible = "nxp,tda998x";
+                       reg = <0x71>;
+               };
+       };
+
+       ohci@7ffb0000 {
+               compatible = "generic-ohci";
+               reg = <0x0 0x7ffb0000 0x0 0x10000>;
+               interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&soc_usb48mhz>;
+       };
+
+       ehci@7ffc0000 {
+               compatible = "generic-ehci";
+               reg = <0x0 0x7ffc0000 0x0 0x10000>;
+               interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&soc_usb48mhz>;
+       };
+
+       memory-controller@7ffd0000 {
+               compatible = "arm,pl354", "arm,primecell";
+               reg = <0 0x7ffd0000 0 0x1000>;
+               interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&soc_smc50mhz>;
+               clock-names = "apb_pclk";
+       };
+
+       smb {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 15>;
+               interrupt-map = <0 0  0 &gic 0  68 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  1 &gic 0  69 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  2 &gic 0  70 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  3 &gic 0 160 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  4 &gic 0 161 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  5 &gic 0 162 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  6 &gic 0 163 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  7 &gic 0 164 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  8 &gic 0 165 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0  9 &gic 0 166 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0 10 &gic 0 167 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0 11 &gic 0 168 IRQ_TYPE_LEVEL_HIGH>,
+                               <0 0 12 &gic 0 169 IRQ_TYPE_LEVEL_HIGH>;
+
+               /include/ "juno-motherboard.dtsi"
+       };
+};
diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
new file mode 100644 (file)
index 0000000..efc59b3
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * ARM Ltd. Fast Models
+ *
+ * Architecture Envelope Model (AEM) ARMv8-A
+ * ARMAEMv8AMPCT
+ *
+ * RTSM_VE_AEMv8A.lisa
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x80000000 0x00010000;
+
+/ {
+       model = "RTSM_VE_AEMv8A";
+       compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "spin-table";
+                       cpu-release-addr = <0x0 0x8000fff8>;
+               };
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x80000000>,
+                     <0x00000008 0x80000000 0 0x80000000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x0 0x2c001000 0 0x1000>,
+                     <0x0 0x2c002000 0 0x1000>,
+                     <0x0 0x2c004000 0 0x2000>,
+                     <0x0 0x2c006000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xf08>,
+                            <1 14 0xf08>,
+                            <1 11 0xf08>,
+                            <1 10 0xf08>;
+               clock-frequency = <100000000>;
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 60 4>,
+                            <0 61 4>,
+                            <0 62 4>,
+                            <0 63 4>;
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0  0 4>,
+                               <0 0  1 &gic 0  1 4>,
+                               <0 0  2 &gic 0  2 4>,
+                               <0 0  3 &gic 0  3 4>,
+                               <0 0  4 &gic 0  4 4>,
+                               <0 0  5 &gic 0  5 4>,
+                               <0 0  6 &gic 0  6 4>,
+                               <0 0  7 &gic 0  7 4>,
+                               <0 0  8 &gic 0  8 4>,
+                               <0 0  9 &gic 0  9 4>,
+                               <0 0 10 &gic 0 10 4>,
+                               <0 0 11 &gic 0 11 4>,
+                               <0 0 12 &gic 0 12 4>,
+                               <0 0 13 &gic 0 13 4>,
+                               <0 0 14 &gic 0 14 4>,
+                               <0 0 15 &gic 0 15 4>,
+                               <0 0 16 &gic 0 16 4>,
+                               <0 0 17 &gic 0 17 4>,
+                               <0 0 18 &gic 0 18 4>,
+                               <0 0 19 &gic 0 19 4>,
+                               <0 0 20 &gic 0 20 4>,
+                               <0 0 21 &gic 0 21 4>,
+                               <0 0 22 &gic 0 22 4>,
+                               <0 0 23 &gic 0 23 4>,
+                               <0 0 24 &gic 0 24 4>,
+                               <0 0 25 &gic 0 25 4>,
+                               <0 0 26 &gic 0 26 4>,
+                               <0 0 27 &gic 0 27 4>,
+                               <0 0 28 &gic 0 28 4>,
+                               <0 0 29 &gic 0 29 4>,
+                               <0 0 30 &gic 0 30 4>,
+                               <0 0 31 &gic 0 31 4>,
+                               <0 0 32 &gic 0 32 4>,
+                               <0 0 33 &gic 0 33 4>,
+                               <0 0 34 &gic 0 34 4>,
+                               <0 0 35 &gic 0 35 4>,
+                               <0 0 36 &gic 0 36 4>,
+                               <0 0 37 &gic 0 37 4>,
+                               <0 0 38 &gic 0 38 4>,
+                               <0 0 39 &gic 0 39 4>,
+                               <0 0 40 &gic 0 40 4>,
+                               <0 0 41 &gic 0 41 4>,
+                               <0 0 42 &gic 0 42 4>;
+
+               /include/ "rtsm_ve-motherboard.dtsi"
+       };
+};
diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
new file mode 100644 (file)
index 0000000..c46cbb2
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * ARM Ltd. Fast Models
+ *
+ * Versatile Express (VE) system model
+ * Motherboard component
+ *
+ * VEMotherBoard.lisa
+ */
+
+       motherboard {
+               arm,v2m-memory-map = "rs1";
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
+               #address-cells = <2>; /* SMB chipselect number and offset */
+               #size-cells = <1>;
+               #interrupt-cells = <1>;
+               ranges;
+
+               flash@0,00000000 {
+                       compatible = "arm,vexpress-flash", "cfi-flash";
+                       reg = <0 0x00000000 0x04000000>,
+                             <4 0x00000000 0x04000000>;
+                       bank-width = <4>;
+               };
+
+               v2m_video_ram: vram@2,00000000 {
+                       compatible = "arm,vexpress-vram";
+                       reg = <2 0x00000000 0x00800000>;
+               };
+
+               ethernet@2,02000000 {
+                       compatible = "smsc,lan91c111";
+                       reg = <2 0x02000000 0x10000>;
+                       interrupts = <15>;
+               };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               iofpga@3,00000000 {
+                       compatible = "arm,amba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 3 0 0x200000>;
+
+                       v2m_sysreg: sysreg@010000 {
+                               compatible = "arm,vexpress-sysreg";
+                               reg = <0x010000 0x1000>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+
+                       v2m_sysctl: sysctl@020000 {
+                               compatible = "arm,sp810", "arm,primecell";
+                               reg = <0x020000 0x1000>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
+                               clock-names = "refclk", "timclk", "apb_pclk";
+                               #clock-cells = <1>;
+                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+                       };
+
+                       aaci@040000 {
+                               compatible = "arm,pl041", "arm,primecell";
+                               reg = <0x040000 0x1000>;
+                               interrupts = <11>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       mmci@050000 {
+                               compatible = "arm,pl180", "arm,primecell";
+                               reg = <0x050000 0x1000>;
+                               interrupts = <9 10>;
+                               cd-gpios = <&v2m_sysreg 0 0>;
+                               wp-gpios = <&v2m_sysreg 1 0>;
+                               max-frequency = <12000000>;
+                               vmmc-supply = <&v2m_fixed_3v3>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "mclk", "apb_pclk";
+                       };
+
+                       kmi@060000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x060000 0x1000>;
+                               interrupts = <12>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
+                       };
+
+                       kmi@070000 {
+                               compatible = "arm,pl050", "arm,primecell";
+                               reg = <0x070000 0x1000>;
+                               interrupts = <13>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
+                       };
+
+                       v2m_serial0: uart@090000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x090000 0x1000>;
+                               interrupts = <5>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial1: uart@0a0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0a0000 0x1000>;
+                               interrupts = <6>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial2: uart@0b0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0b0000 0x1000>;
+                               interrupts = <7>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       v2m_serial3: uart@0c0000 {
+                               compatible = "arm,pl011", "arm,primecell";
+                               reg = <0x0c0000 0x1000>;
+                               interrupts = <8>;
+                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+                               clock-names = "uartclk", "apb_pclk";
+                       };
+
+                       wdt@0f0000 {
+                               compatible = "arm,sp805", "arm,primecell";
+                               reg = <0x0f0000 0x1000>;
+                               interrupts = <0>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
+                               clock-names = "wdogclk", "apb_pclk";
+                       };
+
+                       v2m_timer01: timer@110000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x110000 0x1000>;
+                               interrupts = <2>;
+                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       v2m_timer23: timer@120000 {
+                               compatible = "arm,sp804", "arm,primecell";
+                               reg = <0x120000 0x1000>;
+                               interrupts = <3>;
+                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
+                       };
+
+                       rtc@170000 {
+                               compatible = "arm,pl031", "arm,primecell";
+                               reg = <0x170000 0x1000>;
+                               interrupts = <4>;
+                               clocks = <&v2m_clk24mhz>;
+                               clock-names = "apb_pclk";
+                       };
+
+                       clcd@1f0000 {
+                               compatible = "arm,pl111", "arm,primecell";
+                               reg = <0x1f0000 0x1000>;
+                               interrupt-names = "combined";
+                               interrupts = <14>;
+                               clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
+                               clock-names = "clcdclk", "apb_pclk";
+                               arm,pl11x,framebuffer = <0x18000000 0x00180000>;
+                               memory-region = <&v2m_video_ram>;
+                               max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
+
+                               port {
+                                       v2m_clcd_pads: endpoint {
+                                               remote-endpoint = <&v2m_clcd_panel>;
+                                               arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+                                       };
+                               };
+
+                               panel {
+                                       compatible = "panel-dpi";
+
+                                       port {
+                                               v2m_clcd_panel: endpoint {
+                                                       remote-endpoint = <&v2m_clcd_pads>;
+                                               };
+                                       };
+
+                                       panel-timing {
+                                               clock-frequency = <63500127>;
+                                               hactive = <1024>;
+                                               hback-porch = <152>;
+                                               hfront-porch = <48>;
+                                               hsync-len = <104>;
+                                               vactive = <768>;
+                                               vback-porch = <23>;
+                                               vfront-porch = <3>;
+                                               vsync-len = <4>;
+                                       };
+                               };
+                       };
+
+                       virtio_block@0130000 {
+                               compatible = "virtio,mmio";
+                               reg = <0x130000 0x200>;
+                               interrupts = <42>;
+                       };
+               };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+
+               mcc {
+                       compatible = "arm,vexpress,config-bus";
+                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                       v2m_oscclk1: osc@1 {
+                               /* CLCD clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 1>;
+                               freq-range = <23750000 63500000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk1";
+                       };
+
+                       reset@0 {
+                               compatible = "arm,vexpress-reset";
+                               arm,vexpress-sysreg,func = <5 0>;
+                       };
+
+                       muxfpga@0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                       };
+
+                       shutdown@0 {
+                               compatible = "arm,vexpress-shutdown";
+                               arm,vexpress-sysreg,func = <8 0>;
+                       };
+
+                       reboot@0 {
+                               compatible = "arm,vexpress-reboot";
+                               arm,vexpress-sysreg,func = <9 0>;
+                       };
+
+                       dvimode@0 {
+                               compatible = "arm,vexpress-dvimode";
+                               arm,vexpress-sysreg,func = <11 0>;
+                       };
+               };
+       };
diff --git a/arch/arm64/boot/dts/cavium/Makefile b/arch/arm64/boot/dts/cavium/Makefile
new file mode 100644 (file)
index 0000000..e34f89d
--- /dev/null
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_THUNDER) += thunder-88xx.dtb
+
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dts b/arch/arm64/boot/dts/cavium/thunder-88xx.dts
new file mode 100644 (file)
index 0000000..800ba65
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Cavium Thunder DTS file - Thunder board description
+ *
+ * Copyright (C) 2014, Cavium Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This 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.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 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/ "thunder-88xx.dtsi"
+
+/ {
+       model = "Cavium ThunderX CN88XX board";
+       compatible = "cavium,thunder-88xx";
+
+       aliases {
+               serial0 = &uaa0;
+               serial1 = &uaa1;
+       };
+
+       memory@00000000 {
+               device_type = "memory";
+               reg = <0x0 0x00000000 0x0 0x80000000>;
+       };
+};
diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
new file mode 100644 (file)
index 0000000..d8c0bdc
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * Cavium Thunder DTS file - Thunder SoC description
+ *
+ * Copyright (C) 2014, Cavium Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This 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.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 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.
+ */
+
+/ {
+       compatible = "cavium,thunder-88xx";
+       interrupt-parent = <&gic0>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu@000 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x000>;
+                       enable-method = "psci";
+               };
+               cpu@001 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x001>;
+                       enable-method = "psci";
+               };
+               cpu@002 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x002>;
+                       enable-method = "psci";
+               };
+               cpu@003 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x003>;
+                       enable-method = "psci";
+               };
+               cpu@004 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x004>;
+                       enable-method = "psci";
+               };
+               cpu@005 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x005>;
+                       enable-method = "psci";
+               };
+               cpu@006 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x006>;
+                       enable-method = "psci";
+               };
+               cpu@007 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x007>;
+                       enable-method = "psci";
+               };
+               cpu@008 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x008>;
+                       enable-method = "psci";
+               };
+               cpu@009 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x009>;
+                       enable-method = "psci";
+               };
+               cpu@00a {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x00a>;
+                       enable-method = "psci";
+               };
+               cpu@00b {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x00b>;
+                       enable-method = "psci";
+               };
+               cpu@00c {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x00c>;
+                       enable-method = "psci";
+               };
+               cpu@00d {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x00d>;
+                       enable-method = "psci";
+               };
+               cpu@00e {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x00e>;
+                       enable-method = "psci";
+               };
+               cpu@00f {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x00f>;
+                       enable-method = "psci";
+               };
+               cpu@100 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x100>;
+                       enable-method = "psci";
+               };
+               cpu@101 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x101>;
+                       enable-method = "psci";
+               };
+               cpu@102 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x102>;
+                       enable-method = "psci";
+               };
+               cpu@103 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x103>;
+                       enable-method = "psci";
+               };
+               cpu@104 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x104>;
+                       enable-method = "psci";
+               };
+               cpu@105 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x105>;
+                       enable-method = "psci";
+               };
+               cpu@106 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x106>;
+                       enable-method = "psci";
+               };
+               cpu@107 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x107>;
+                       enable-method = "psci";
+               };
+               cpu@108 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x108>;
+                       enable-method = "psci";
+               };
+               cpu@109 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x109>;
+                       enable-method = "psci";
+               };
+               cpu@10a {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x10a>;
+                       enable-method = "psci";
+               };
+               cpu@10b {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x10b>;
+                       enable-method = "psci";
+               };
+               cpu@10c {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x10c>;
+                       enable-method = "psci";
+               };
+               cpu@10d {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x10d>;
+                       enable-method = "psci";
+               };
+               cpu@10e {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x10e>;
+                       enable-method = "psci";
+               };
+               cpu@10f {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x10f>;
+                       enable-method = "psci";
+               };
+               cpu@200 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x200>;
+                       enable-method = "psci";
+               };
+               cpu@201 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x201>;
+                       enable-method = "psci";
+               };
+               cpu@202 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x202>;
+                       enable-method = "psci";
+               };
+               cpu@203 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x203>;
+                       enable-method = "psci";
+               };
+               cpu@204 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x204>;
+                       enable-method = "psci";
+               };
+               cpu@205 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x205>;
+                       enable-method = "psci";
+               };
+               cpu@206 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x206>;
+                       enable-method = "psci";
+               };
+               cpu@207 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x207>;
+                       enable-method = "psci";
+               };
+               cpu@208 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x208>;
+                       enable-method = "psci";
+               };
+               cpu@209 {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x209>;
+                       enable-method = "psci";
+               };
+               cpu@20a {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x20a>;
+                       enable-method = "psci";
+               };
+               cpu@20b {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x20b>;
+                       enable-method = "psci";
+               };
+               cpu@20c {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x20c>;
+                       enable-method = "psci";
+               };
+               cpu@20d {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x20d>;
+                       enable-method = "psci";
+               };
+               cpu@20e {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x20e>;
+                       enable-method = "psci";
+               };
+               cpu@20f {
+                       device_type = "cpu";
+                       compatible = "cavium,thunder", "arm,armv8";
+                       reg = <0x0 0x20f>;
+                       enable-method = "psci";
+               };
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 0xff01>,
+                            <1 14 0xff01>,
+                            <1 11 0xff01>,
+                            <1 10 0xff01>;
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               refclk50mhz: refclk50mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <50000000>;
+                       clock-output-names = "refclk50mhz";
+               };
+
+               gic0: interrupt-controller@8010,00000000 {
+                       compatible = "arm,gic-v3";
+                       #interrupt-cells = <3>;
+                       interrupt-controller;
+                       reg = <0x8010 0x00000000 0x0 0x010000>, /* GICD */
+                             <0x8010 0x80000000 0x0 0x600000>; /* GICR */
+                       interrupts = <1 9 0xf04>;
+               };
+
+               uaa0: serial@87e0,24000000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x87e0 0x24000000 0x0 0x1000>;
+                       interrupts = <1 21 4>;
+                       clocks = <&refclk50mhz>;
+                       clock-names = "apb_pclk";
+               };
+
+               uaa1: serial@87e0,25000000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x87e0 0x25000000 0x0 0x1000>;
+                       interrupts = <1 22 4>;
+                       clocks = <&refclk50mhz>;
+                       clock-names = "apb_pclk";
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/foundation-v8.dts b/arch/arm64/boot/dts/foundation-v8.dts
deleted file mode 100644 (file)
index 4a06090..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * ARM Ltd.
- *
- * ARMv8 Foundation model DTS
- */
-
-/dts-v1/;
-
-/memreserve/ 0x80000000 0x00010000;
-
-/ {
-       model = "Foundation-v8A";
-       compatible = "arm,foundation-aarch64", "arm,vexpress";
-       interrupt-parent = <&gic>;
-       #address-cells = <2>;
-       #size-cells = <2>;
-
-       chosen { };
-
-       aliases {
-               serial0 = &v2m_serial0;
-               serial1 = &v2m_serial1;
-               serial2 = &v2m_serial2;
-               serial3 = &v2m_serial3;
-       };
-
-       cpus {
-               #address-cells = <2>;
-               #size-cells = <0>;
-
-               cpu@0 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x0>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-               cpu@1 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x1>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-               cpu@2 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x2>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-               cpu@3 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x3>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-       };
-
-       memory@80000000 {
-               device_type = "memory";
-               reg = <0x00000000 0x80000000 0 0x80000000>,
-                     <0x00000008 0x80000000 0 0x80000000>;
-       };
-
-       gic: interrupt-controller@2c001000 {
-               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
-               #interrupt-cells = <3>;
-               #address-cells = <0>;
-               interrupt-controller;
-               reg = <0x0 0x2c001000 0 0x1000>,
-                     <0x0 0x2c002000 0 0x1000>,
-                     <0x0 0x2c004000 0 0x2000>,
-                     <0x0 0x2c006000 0 0x2000>;
-               interrupts = <1 9 0xf04>;
-       };
-
-       timer {
-               compatible = "arm,armv8-timer";
-               interrupts = <1 13 0xff01>,
-                            <1 14 0xff01>,
-                            <1 11 0xff01>,
-                            <1 10 0xff01>;
-               clock-frequency = <100000000>;
-       };
-
-       pmu {
-               compatible = "arm,armv8-pmuv3";
-               interrupts = <0 60 4>,
-                            <0 61 4>,
-                            <0 62 4>,
-                            <0 63 4>;
-       };
-
-       smb {
-               compatible = "arm,vexpress,v2m-p1", "simple-bus";
-               arm,v2m-memory-map = "rs1";
-               #address-cells = <2>; /* SMB chipselect number and offset */
-               #size-cells = <1>;
-
-               ranges = <0 0 0 0x08000000 0x04000000>,
-                        <1 0 0 0x14000000 0x04000000>,
-                        <2 0 0 0x18000000 0x04000000>,
-                        <3 0 0 0x1c000000 0x04000000>,
-                        <4 0 0 0x0c000000 0x04000000>,
-                        <5 0 0 0x10000000 0x04000000>;
-
-               #interrupt-cells = <1>;
-               interrupt-map-mask = <0 0 63>;
-               interrupt-map = <0 0  0 &gic 0  0 4>,
-                               <0 0  1 &gic 0  1 4>,
-                               <0 0  2 &gic 0  2 4>,
-                               <0 0  3 &gic 0  3 4>,
-                               <0 0  4 &gic 0  4 4>,
-                               <0 0  5 &gic 0  5 4>,
-                               <0 0  6 &gic 0  6 4>,
-                               <0 0  7 &gic 0  7 4>,
-                               <0 0  8 &gic 0  8 4>,
-                               <0 0  9 &gic 0  9 4>,
-                               <0 0 10 &gic 0 10 4>,
-                               <0 0 11 &gic 0 11 4>,
-                               <0 0 12 &gic 0 12 4>,
-                               <0 0 13 &gic 0 13 4>,
-                               <0 0 14 &gic 0 14 4>,
-                               <0 0 15 &gic 0 15 4>,
-                               <0 0 16 &gic 0 16 4>,
-                               <0 0 17 &gic 0 17 4>,
-                               <0 0 18 &gic 0 18 4>,
-                               <0 0 19 &gic 0 19 4>,
-                               <0 0 20 &gic 0 20 4>,
-                               <0 0 21 &gic 0 21 4>,
-                               <0 0 22 &gic 0 22 4>,
-                               <0 0 23 &gic 0 23 4>,
-                               <0 0 24 &gic 0 24 4>,
-                               <0 0 25 &gic 0 25 4>,
-                               <0 0 26 &gic 0 26 4>,
-                               <0 0 27 &gic 0 27 4>,
-                               <0 0 28 &gic 0 28 4>,
-                               <0 0 29 &gic 0 29 4>,
-                               <0 0 30 &gic 0 30 4>,
-                               <0 0 31 &gic 0 31 4>,
-                               <0 0 32 &gic 0 32 4>,
-                               <0 0 33 &gic 0 33 4>,
-                               <0 0 34 &gic 0 34 4>,
-                               <0 0 35 &gic 0 35 4>,
-                               <0 0 36 &gic 0 36 4>,
-                               <0 0 37 &gic 0 37 4>,
-                               <0 0 38 &gic 0 38 4>,
-                               <0 0 39 &gic 0 39 4>,
-                               <0 0 40 &gic 0 40 4>,
-                               <0 0 41 &gic 0 41 4>,
-                               <0 0 42 &gic 0 42 4>;
-
-               ethernet@2,02000000 {
-                       compatible = "smsc,lan91c111";
-                       reg = <2 0x02000000 0x10000>;
-                       interrupts = <15>;
-               };
-
-               v2m_clk24mhz: clk24mhz {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <24000000>;
-                       clock-output-names = "v2m:clk24mhz";
-               };
-
-               v2m_refclk1mhz: refclk1mhz {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <1000000>;
-                       clock-output-names = "v2m:refclk1mhz";
-               };
-
-               v2m_refclk32khz: refclk32khz {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <32768>;
-                       clock-output-names = "v2m:refclk32khz";
-               };
-
-               iofpga@3,00000000 {
-                       compatible = "arm,amba-bus", "simple-bus";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 3 0 0x200000>;
-
-                       v2m_sysreg: sysreg@010000 {
-                               compatible = "arm,vexpress-sysreg";
-                               reg = <0x010000 0x1000>;
-                       };
-
-                       v2m_serial0: uart@090000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x090000 0x1000>;
-                               interrupts = <5>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       v2m_serial1: uart@0a0000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x0a0000 0x1000>;
-                               interrupts = <6>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       v2m_serial2: uart@0b0000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x0b0000 0x1000>;
-                               interrupts = <7>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       v2m_serial3: uart@0c0000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x0c0000 0x1000>;
-                               interrupts = <8>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       virtio_block@0130000 {
-                               compatible = "virtio,mmio";
-                               reg = <0x130000 0x200>;
-                               interrupts = <42>;
-                       };
-               };
-       };
-};
diff --git a/arch/arm64/boot/dts/include/dt-bindings b/arch/arm64/boot/dts/include/dt-bindings
new file mode 120000 (symlink)
index 0000000..08c00e4
--- /dev/null
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts
deleted file mode 100644 (file)
index 572005e..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * ARM Ltd. Fast Models
- *
- * Architecture Envelope Model (AEM) ARMv8-A
- * ARMAEMv8AMPCT
- *
- * RTSM_VE_AEMv8A.lisa
- */
-
-/dts-v1/;
-
-/memreserve/ 0x80000000 0x00010000;
-
-/ {
-       model = "RTSM_VE_AEMv8A";
-       compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress";
-       interrupt-parent = <&gic>;
-       #address-cells = <2>;
-       #size-cells = <2>;
-
-       chosen { };
-
-       aliases {
-               serial0 = &v2m_serial0;
-               serial1 = &v2m_serial1;
-               serial2 = &v2m_serial2;
-               serial3 = &v2m_serial3;
-       };
-
-       cpus {
-               #address-cells = <2>;
-               #size-cells = <0>;
-
-               cpu@0 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x0>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-               cpu@1 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x1>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-               cpu@2 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x2>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-               cpu@3 {
-                       device_type = "cpu";
-                       compatible = "arm,armv8";
-                       reg = <0x0 0x3>;
-                       enable-method = "spin-table";
-                       cpu-release-addr = <0x0 0x8000fff8>;
-               };
-       };
-
-       memory@80000000 {
-               device_type = "memory";
-               reg = <0x00000000 0x80000000 0 0x80000000>,
-                     <0x00000008 0x80000000 0 0x80000000>;
-       };
-
-       gic: interrupt-controller@2c001000 {
-               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
-               #interrupt-cells = <3>;
-               #address-cells = <0>;
-               interrupt-controller;
-               reg = <0x0 0x2c001000 0 0x1000>,
-                     <0x0 0x2c002000 0 0x1000>,
-                     <0x0 0x2c004000 0 0x2000>,
-                     <0x0 0x2c006000 0 0x2000>;
-               interrupts = <1 9 0xf04>;
-       };
-
-       timer {
-               compatible = "arm,armv8-timer";
-               interrupts = <1 13 0xff01>,
-                            <1 14 0xff01>,
-                            <1 11 0xff01>,
-                            <1 10 0xff01>;
-               clock-frequency = <100000000>;
-       };
-
-       pmu {
-               compatible = "arm,armv8-pmuv3";
-               interrupts = <0 60 4>,
-                            <0 61 4>,
-                            <0 62 4>,
-                            <0 63 4>;
-       };
-
-       smb {
-               compatible = "simple-bus";
-
-               #address-cells = <2>;
-               #size-cells = <1>;
-               ranges = <0 0 0 0x08000000 0x04000000>,
-                        <1 0 0 0x14000000 0x04000000>,
-                        <2 0 0 0x18000000 0x04000000>,
-                        <3 0 0 0x1c000000 0x04000000>,
-                        <4 0 0 0x0c000000 0x04000000>,
-                        <5 0 0 0x10000000 0x04000000>;
-
-               #interrupt-cells = <1>;
-               interrupt-map-mask = <0 0 63>;
-               interrupt-map = <0 0  0 &gic 0  0 4>,
-                               <0 0  1 &gic 0  1 4>,
-                               <0 0  2 &gic 0  2 4>,
-                               <0 0  3 &gic 0  3 4>,
-                               <0 0  4 &gic 0  4 4>,
-                               <0 0  5 &gic 0  5 4>,
-                               <0 0  6 &gic 0  6 4>,
-                               <0 0  7 &gic 0  7 4>,
-                               <0 0  8 &gic 0  8 4>,
-                               <0 0  9 &gic 0  9 4>,
-                               <0 0 10 &gic 0 10 4>,
-                               <0 0 11 &gic 0 11 4>,
-                               <0 0 12 &gic 0 12 4>,
-                               <0 0 13 &gic 0 13 4>,
-                               <0 0 14 &gic 0 14 4>,
-                               <0 0 15 &gic 0 15 4>,
-                               <0 0 16 &gic 0 16 4>,
-                               <0 0 17 &gic 0 17 4>,
-                               <0 0 18 &gic 0 18 4>,
-                               <0 0 19 &gic 0 19 4>,
-                               <0 0 20 &gic 0 20 4>,
-                               <0 0 21 &gic 0 21 4>,
-                               <0 0 22 &gic 0 22 4>,
-                               <0 0 23 &gic 0 23 4>,
-                               <0 0 24 &gic 0 24 4>,
-                               <0 0 25 &gic 0 25 4>,
-                               <0 0 26 &gic 0 26 4>,
-                               <0 0 27 &gic 0 27 4>,
-                               <0 0 28 &gic 0 28 4>,
-                               <0 0 29 &gic 0 29 4>,
-                               <0 0 30 &gic 0 30 4>,
-                               <0 0 31 &gic 0 31 4>,
-                               <0 0 32 &gic 0 32 4>,
-                               <0 0 33 &gic 0 33 4>,
-                               <0 0 34 &gic 0 34 4>,
-                               <0 0 35 &gic 0 35 4>,
-                               <0 0 36 &gic 0 36 4>,
-                               <0 0 37 &gic 0 37 4>,
-                               <0 0 38 &gic 0 38 4>,
-                               <0 0 39 &gic 0 39 4>,
-                               <0 0 40 &gic 0 40 4>,
-                               <0 0 41 &gic 0 41 4>,
-                               <0 0 42 &gic 0 42 4>;
-
-               /include/ "rtsm_ve-motherboard.dtsi"
-       };
-};
diff --git a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi
deleted file mode 100644 (file)
index ac2cb24..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * ARM Ltd. Fast Models
- *
- * Versatile Express (VE) system model
- * Motherboard component
- *
- * VEMotherBoard.lisa
- */
-
-       motherboard {
-               arm,v2m-memory-map = "rs1";
-               compatible = "arm,vexpress,v2m-p1", "simple-bus";
-               #address-cells = <2>; /* SMB chipselect number and offset */
-               #size-cells = <1>;
-               #interrupt-cells = <1>;
-               ranges;
-
-               flash@0,00000000 {
-                       compatible = "arm,vexpress-flash", "cfi-flash";
-                       reg = <0 0x00000000 0x04000000>,
-                             <4 0x00000000 0x04000000>;
-                       bank-width = <4>;
-               };
-
-               vram@2,00000000 {
-                       compatible = "arm,vexpress-vram";
-                       reg = <2 0x00000000 0x00800000>;
-               };
-
-               ethernet@2,02000000 {
-                       compatible = "smsc,lan91c111";
-                       reg = <2 0x02000000 0x10000>;
-                       interrupts = <15>;
-               };
-
-               v2m_clk24mhz: clk24mhz {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <24000000>;
-                       clock-output-names = "v2m:clk24mhz";
-               };
-
-               v2m_refclk1mhz: refclk1mhz {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <1000000>;
-                       clock-output-names = "v2m:refclk1mhz";
-               };
-
-               v2m_refclk32khz: refclk32khz {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <32768>;
-                       clock-output-names = "v2m:refclk32khz";
-               };
-
-               iofpga@3,00000000 {
-                       compatible = "arm,amba-bus", "simple-bus";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 3 0 0x200000>;
-
-                       v2m_sysreg: sysreg@010000 {
-                               compatible = "arm,vexpress-sysreg";
-                               reg = <0x010000 0x1000>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                       };
-
-                       v2m_sysctl: sysctl@020000 {
-                               compatible = "arm,sp810", "arm,primecell";
-                               reg = <0x020000 0x1000>;
-                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
-                               clock-names = "refclk", "timclk", "apb_pclk";
-                               #clock-cells = <1>;
-                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
-                       };
-
-                       aaci@040000 {
-                               compatible = "arm,pl041", "arm,primecell";
-                               reg = <0x040000 0x1000>;
-                               interrupts = <11>;
-                               clocks = <&v2m_clk24mhz>;
-                               clock-names = "apb_pclk";
-                       };
-
-                       mmci@050000 {
-                               compatible = "arm,pl180", "arm,primecell";
-                               reg = <0x050000 0x1000>;
-                               interrupts = <9 10>;
-                               cd-gpios = <&v2m_sysreg 0 0>;
-                               wp-gpios = <&v2m_sysreg 1 0>;
-                               max-frequency = <12000000>;
-                               vmmc-supply = <&v2m_fixed_3v3>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "mclk", "apb_pclk";
-                       };
-
-                       kmi@060000 {
-                               compatible = "arm,pl050", "arm,primecell";
-                               reg = <0x060000 0x1000>;
-                               interrupts = <12>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "KMIREFCLK", "apb_pclk";
-                       };
-
-                       kmi@070000 {
-                               compatible = "arm,pl050", "arm,primecell";
-                               reg = <0x070000 0x1000>;
-                               interrupts = <13>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "KMIREFCLK", "apb_pclk";
-                       };
-
-                       v2m_serial0: uart@090000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x090000 0x1000>;
-                               interrupts = <5>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       v2m_serial1: uart@0a0000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x0a0000 0x1000>;
-                               interrupts = <6>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       v2m_serial2: uart@0b0000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x0b0000 0x1000>;
-                               interrupts = <7>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       v2m_serial3: uart@0c0000 {
-                               compatible = "arm,pl011", "arm,primecell";
-                               reg = <0x0c0000 0x1000>;
-                               interrupts = <8>;
-                               clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
-                               clock-names = "uartclk", "apb_pclk";
-                       };
-
-                       wdt@0f0000 {
-                               compatible = "arm,sp805", "arm,primecell";
-                               reg = <0x0f0000 0x1000>;
-                               interrupts = <0>;
-                               clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
-                               clock-names = "wdogclk", "apb_pclk";
-                       };
-
-                       v2m_timer01: timer@110000 {
-                               compatible = "arm,sp804", "arm,primecell";
-                               reg = <0x110000 0x1000>;
-                               interrupts = <2>;
-                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
-                               clock-names = "timclken1", "timclken2", "apb_pclk";
-                       };
-
-                       v2m_timer23: timer@120000 {
-                               compatible = "arm,sp804", "arm,primecell";
-                               reg = <0x120000 0x1000>;
-                               interrupts = <3>;
-                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
-                               clock-names = "timclken1", "timclken2", "apb_pclk";
-                       };
-
-                       rtc@170000 {
-                               compatible = "arm,pl031", "arm,primecell";
-                               reg = <0x170000 0x1000>;
-                               interrupts = <4>;
-                               clocks = <&v2m_clk24mhz>;
-                               clock-names = "apb_pclk";
-                       };
-
-                       clcd@1f0000 {
-                               compatible = "arm,pl111", "arm,primecell";
-                               reg = <0x1f0000 0x1000>;
-                               interrupts = <14>;
-                               clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
-                               clock-names = "clcdclk", "apb_pclk";
-                       };
-
-                       virtio_block@0130000 {
-                               compatible = "virtio,mmio";
-                               reg = <0x130000 0x200>;
-                               interrupts = <42>;
-                       };
-               };
-
-               v2m_fixed_3v3: fixedregulator@0 {
-                       compatible = "regulator-fixed";
-                       regulator-name = "3V3";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       regulator-always-on;
-               };
-
-               mcc {
-                       compatible = "arm,vexpress,config-bus";
-                       arm,vexpress,config-bridge = <&v2m_sysreg>;
-
-                       v2m_oscclk1: osc@1 {
-                               /* CLCD clock */
-                               compatible = "arm,vexpress-osc";
-                               arm,vexpress-sysreg,func = <1 1>;
-                               freq-range = <23750000 63500000>;
-                               #clock-cells = <0>;
-                               clock-output-names = "v2m:oscclk1";
-                       };
-
-                       reset@0 {
-                               compatible = "arm,vexpress-reset";
-                               arm,vexpress-sysreg,func = <5 0>;
-                       };
-
-                       muxfpga@0 {
-                               compatible = "arm,vexpress-muxfpga";
-                               arm,vexpress-sysreg,func = <7 0>;
-                       };
-
-                       shutdown@0 {
-                               compatible = "arm,vexpress-shutdown";
-                               arm,vexpress-sysreg,func = <8 0>;
-                       };
-
-                       reboot@0 {
-                               compatible = "arm,vexpress-reboot";
-                               arm,vexpress-sysreg,func = <9 0>;
-                       };
-
-                       dvimode@0 {
-                               compatible = "arm,vexpress-dvimode";
-                               arm,vexpress-sysreg,func = <11 0>;
-                       };
-               };
-       };
diff --git a/arch/arm64/boot/dts/thunder-88xx.dts b/arch/arm64/boot/dts/thunder-88xx.dts
deleted file mode 100644 (file)
index 800ba65..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Cavium Thunder DTS file - Thunder board description
- *
- * Copyright (C) 2014, Cavium Inc.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This 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.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 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/ "thunder-88xx.dtsi"
-
-/ {
-       model = "Cavium ThunderX CN88XX board";
-       compatible = "cavium,thunder-88xx";
-
-       aliases {
-               serial0 = &uaa0;
-               serial1 = &uaa1;
-       };
-
-       memory@00000000 {
-               device_type = "memory";
-               reg = <0x0 0x00000000 0x0 0x80000000>;
-       };
-};
diff --git a/arch/arm64/boot/dts/thunder-88xx.dtsi b/arch/arm64/boot/dts/thunder-88xx.dtsi
deleted file mode 100644 (file)
index d8c0bdc..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Cavium Thunder DTS file - Thunder SoC description
- *
- * Copyright (C) 2014, Cavium Inc.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This 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.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 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.
- */
-
-/ {
-       compatible = "cavium,thunder-88xx";
-       interrupt-parent = <&gic0>;
-       #address-cells = <2>;
-       #size-cells = <2>;
-
-       psci {
-               compatible = "arm,psci-0.2";
-               method = "smc";
-       };
-
-       cpus {
-               #address-cells = <2>;
-               #size-cells = <0>;
-
-               cpu@000 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x000>;
-                       enable-method = "psci";
-               };
-               cpu@001 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x001>;
-                       enable-method = "psci";
-               };
-               cpu@002 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x002>;
-                       enable-method = "psci";
-               };
-               cpu@003 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x003>;
-                       enable-method = "psci";
-               };
-               cpu@004 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x004>;
-                       enable-method = "psci";
-               };
-               cpu@005 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x005>;
-                       enable-method = "psci";
-               };
-               cpu@006 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x006>;
-                       enable-method = "psci";
-               };
-               cpu@007 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x007>;
-                       enable-method = "psci";
-               };
-               cpu@008 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x008>;
-                       enable-method = "psci";
-               };
-               cpu@009 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x009>;
-                       enable-method = "psci";
-               };
-               cpu@00a {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x00a>;
-                       enable-method = "psci";
-               };
-               cpu@00b {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x00b>;
-                       enable-method = "psci";
-               };
-               cpu@00c {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x00c>;
-                       enable-method = "psci";
-               };
-               cpu@00d {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x00d>;
-                       enable-method = "psci";
-               };
-               cpu@00e {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x00e>;
-                       enable-method = "psci";
-               };
-               cpu@00f {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x00f>;
-                       enable-method = "psci";
-               };
-               cpu@100 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x100>;
-                       enable-method = "psci";
-               };
-               cpu@101 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x101>;
-                       enable-method = "psci";
-               };
-               cpu@102 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x102>;
-                       enable-method = "psci";
-               };
-               cpu@103 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x103>;
-                       enable-method = "psci";
-               };
-               cpu@104 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x104>;
-                       enable-method = "psci";
-               };
-               cpu@105 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x105>;
-                       enable-method = "psci";
-               };
-               cpu@106 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x106>;
-                       enable-method = "psci";
-               };
-               cpu@107 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x107>;
-                       enable-method = "psci";
-               };
-               cpu@108 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x108>;
-                       enable-method = "psci";
-               };
-               cpu@109 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x109>;
-                       enable-method = "psci";
-               };
-               cpu@10a {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x10a>;
-                       enable-method = "psci";
-               };
-               cpu@10b {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x10b>;
-                       enable-method = "psci";
-               };
-               cpu@10c {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x10c>;
-                       enable-method = "psci";
-               };
-               cpu@10d {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x10d>;
-                       enable-method = "psci";
-               };
-               cpu@10e {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x10e>;
-                       enable-method = "psci";
-               };
-               cpu@10f {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x10f>;
-                       enable-method = "psci";
-               };
-               cpu@200 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x200>;
-                       enable-method = "psci";
-               };
-               cpu@201 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x201>;
-                       enable-method = "psci";
-               };
-               cpu@202 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x202>;
-                       enable-method = "psci";
-               };
-               cpu@203 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x203>;
-                       enable-method = "psci";
-               };
-               cpu@204 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x204>;
-                       enable-method = "psci";
-               };
-               cpu@205 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x205>;
-                       enable-method = "psci";
-               };
-               cpu@206 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x206>;
-                       enable-method = "psci";
-               };
-               cpu@207 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x207>;
-                       enable-method = "psci";
-               };
-               cpu@208 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x208>;
-                       enable-method = "psci";
-               };
-               cpu@209 {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x209>;
-                       enable-method = "psci";
-               };
-               cpu@20a {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x20a>;
-                       enable-method = "psci";
-               };
-               cpu@20b {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x20b>;
-                       enable-method = "psci";
-               };
-               cpu@20c {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x20c>;
-                       enable-method = "psci";
-               };
-               cpu@20d {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x20d>;
-                       enable-method = "psci";
-               };
-               cpu@20e {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x20e>;
-                       enable-method = "psci";
-               };
-               cpu@20f {
-                       device_type = "cpu";
-                       compatible = "cavium,thunder", "arm,armv8";
-                       reg = <0x0 0x20f>;
-                       enable-method = "psci";
-               };
-       };
-
-       timer {
-               compatible = "arm,armv8-timer";
-               interrupts = <1 13 0xff01>,
-                            <1 14 0xff01>,
-                            <1 11 0xff01>,
-                            <1 10 0xff01>;
-       };
-
-       soc {
-               compatible = "simple-bus";
-               #address-cells = <2>;
-               #size-cells = <2>;
-               ranges;
-
-               refclk50mhz: refclk50mhz {
-                       compatible = "fixed-clock";
-                       #clock-cells = <0>;
-                       clock-frequency = <50000000>;
-                       clock-output-names = "refclk50mhz";
-               };
-
-               gic0: interrupt-controller@8010,00000000 {
-                       compatible = "arm,gic-v3";
-                       #interrupt-cells = <3>;
-                       interrupt-controller;
-                       reg = <0x8010 0x00000000 0x0 0x010000>, /* GICD */
-                             <0x8010 0x80000000 0x0 0x600000>; /* GICR */
-                       interrupts = <1 9 0xf04>;
-               };
-
-               uaa0: serial@87e0,24000000 {
-                       compatible = "arm,pl011", "arm,primecell";
-                       reg = <0x87e0 0x24000000 0x0 0x1000>;
-                       interrupts = <1 21 4>;
-                       clocks = <&refclk50mhz>;
-                       clock-names = "apb_pclk";
-               };
-
-               uaa1: serial@87e0,25000000 {
-                       compatible = "arm,pl011", "arm,primecell";
-                       reg = <0x87e0 0x25000000 0x0 0x1000>;
-                       interrupts = <1 22 4>;
-                       clocks = <&refclk50mhz>;
-                       clock-names = "apb_pclk";
-               };
-       };
-};
index 9cd37de9aa8d93e253eccf6c6c4b44f71b91241f..dd301be89ecccfb6fe9f1d7c02a69bafcfea1559 100644 (file)
@@ -35,6 +35,9 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_THUNDER=y
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_XGENE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_KSM=y
@@ -52,6 +55,7 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+CONFIG_BPF_JIT=y
 # CONFIG_WIRELESS is not set
 CONFIG_NET_9P=y
 CONFIG_NET_9P_VIRTIO=y
@@ -65,19 +69,21 @@ CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_AHCI_XGENE=y
-CONFIG_PHY_XGENE=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_TUN=y
 CONFIG_VIRTIO_NET=y
+CONFIG_NET_XGENE=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
-CONFIG_NET_XGENE=y
 # CONFIG_WLAN is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -86,22 +92,40 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_VIRTIO_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
+# CONFIG_HMC_DRV is not set
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_GPIO_PL061=y
+CONFIG_GPIO_XGENE=y
 # CONFIG_HWMON is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
+CONFIG_USB_ULPI=y
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SPI=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_EFI=y
+CONFIG_RTC_DRV_XGENE=y
 CONFIG_VIRTIO_BALLOON=y
 CONFIG_VIRTIO_MMIO=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PHY_XGENE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
index 5562652c5316629089fbbecdabd24f03a1f302c6..a38b02ce5f9a9c68af825cfc462382e2f2a9c836 100644 (file)
@@ -27,20 +27,19 @@ config CRYPTO_AES_ARM64_CE
        tristate "AES core cipher using ARMv8 Crypto Extensions"
        depends on ARM64 && KERNEL_MODE_NEON
        select CRYPTO_ALGAPI
-       select CRYPTO_AES
 
 config CRYPTO_AES_ARM64_CE_CCM
        tristate "AES in CCM mode using ARMv8 Crypto Extensions"
        depends on ARM64 && KERNEL_MODE_NEON
        select CRYPTO_ALGAPI
-       select CRYPTO_AES
+       select CRYPTO_AES_ARM64_CE
        select CRYPTO_AEAD
 
 config CRYPTO_AES_ARM64_CE_BLK
        tristate "AES in ECB/CBC/CTR/XTS modes using ARMv8 Crypto Extensions"
        depends on ARM64 && KERNEL_MODE_NEON
        select CRYPTO_BLKCIPHER
-       select CRYPTO_AES
+       select CRYPTO_AES_ARM64_CE
        select CRYPTO_ABLK_HELPER
 
 config CRYPTO_AES_ARM64_NEON_BLK
index 9e6cdde9b43d9032a074fdfb0c726b62fd74c1b4..0ac73b838fa32ca58561b6b9c7f73d10d824daa9 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/crypto.h>
 #include <linux/module.h>
 
+#include "aes-ce-setkey.h"
+
 static int num_rounds(struct crypto_aes_ctx *ctx)
 {
        /*
@@ -48,7 +50,7 @@ static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key,
        struct crypto_aes_ctx *ctx = crypto_aead_ctx(tfm);
        int ret;
 
-       ret = crypto_aes_expand_key(ctx, in_key, key_len);
+       ret = ce_aes_expandkey(ctx, in_key, key_len);
        if (!ret)
                return 0;
 
index 2075e1acae6b745ed9b8de2a828f449cfb8f08fa..ce47792a983dda8b2909609502ef80d54c1215f8 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/crypto.h>
 #include <linux/module.h>
 
+#include "aes-ce-setkey.h"
+
 MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
 MODULE_LICENSE("GPL v2");
@@ -124,6 +126,114 @@ static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
        kernel_neon_end();
 }
 
+/*
+ * aes_sub() - use the aese instruction to perform the AES sbox substitution
+ *             on each byte in 'input'
+ */
+static u32 aes_sub(u32 input)
+{
+       u32 ret;
+
+       __asm__("dup    v1.4s, %w[in]           ;"
+               "movi   v0.16b, #0              ;"
+               "aese   v0.16b, v1.16b          ;"
+               "umov   %w[out], v0.4s[0]       ;"
+
+       :       [out]   "=r"(ret)
+       :       [in]    "r"(input)
+       :               "v0","v1");
+
+       return ret;
+}
+
+int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
+                    unsigned int key_len)
+{
+       /*
+        * The AES key schedule round constants
+        */
+       static u8 const rcon[] = {
+               0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
+       };
+
+       u32 kwords = key_len / sizeof(u32);
+       struct aes_block *key_enc, *key_dec;
+       int i, j;
+
+       if (key_len != AES_KEYSIZE_128 &&
+           key_len != AES_KEYSIZE_192 &&
+           key_len != AES_KEYSIZE_256)
+               return -EINVAL;
+
+       memcpy(ctx->key_enc, in_key, key_len);
+       ctx->key_length = key_len;
+
+       kernel_neon_begin_partial(2);
+       for (i = 0; i < sizeof(rcon); i++) {
+               u32 *rki = ctx->key_enc + (i * kwords);
+               u32 *rko = rki + kwords;
+
+               rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0];
+               rko[1] = rko[0] ^ rki[1];
+               rko[2] = rko[1] ^ rki[2];
+               rko[3] = rko[2] ^ rki[3];
+
+               if (key_len == AES_KEYSIZE_192) {
+                       if (i >= 7)
+                               break;
+                       rko[4] = rko[3] ^ rki[4];
+                       rko[5] = rko[4] ^ rki[5];
+               } else if (key_len == AES_KEYSIZE_256) {
+                       if (i >= 6)
+                               break;
+                       rko[4] = aes_sub(rko[3]) ^ rki[4];
+                       rko[5] = rko[4] ^ rki[5];
+                       rko[6] = rko[5] ^ rki[6];
+                       rko[7] = rko[6] ^ rki[7];
+               }
+       }
+
+       /*
+        * Generate the decryption keys for the Equivalent Inverse Cipher.
+        * This involves reversing the order of the round keys, and applying
+        * the Inverse Mix Columns transformation on all but the first and
+        * the last one.
+        */
+       key_enc = (struct aes_block *)ctx->key_enc;
+       key_dec = (struct aes_block *)ctx->key_dec;
+       j = num_rounds(ctx);
+
+       key_dec[0] = key_enc[j];
+       for (i = 1, j--; j > 0; i++, j--)
+               __asm__("ld1    {v0.16b}, %[in]         ;"
+                       "aesimc v1.16b, v0.16b          ;"
+                       "st1    {v1.16b}, %[out]        ;"
+
+               :       [out]   "=Q"(key_dec[i])
+               :       [in]    "Q"(key_enc[j])
+               :               "v0","v1");
+       key_dec[i] = key_enc[0];
+
+       kernel_neon_end();
+       return 0;
+}
+EXPORT_SYMBOL(ce_aes_expandkey);
+
+int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+                 unsigned int key_len)
+{
+       struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+       int ret;
+
+       ret = ce_aes_expandkey(ctx, in_key, key_len);
+       if (!ret)
+               return 0;
+
+       tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+       return -EINVAL;
+}
+EXPORT_SYMBOL(ce_aes_setkey);
+
 static struct crypto_alg aes_alg = {
        .cra_name               = "aes",
        .cra_driver_name        = "aes-ce",
@@ -135,7 +245,7 @@ static struct crypto_alg aes_alg = {
        .cra_cipher = {
                .cia_min_keysize        = AES_MIN_KEY_SIZE,
                .cia_max_keysize        = AES_MAX_KEY_SIZE,
-               .cia_setkey             = crypto_aes_set_key,
+               .cia_setkey             = ce_aes_setkey,
                .cia_encrypt            = aes_cipher_encrypt,
                .cia_decrypt            = aes_cipher_decrypt
        }
diff --git a/arch/arm64/crypto/aes-ce-setkey.h b/arch/arm64/crypto/aes-ce-setkey.h
new file mode 100644 (file)
index 0000000..f08a647
--- /dev/null
@@ -0,0 +1,5 @@
+
+int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+                 unsigned int key_len);
+int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
+                    unsigned int key_len);
index 79cd911ef88c3e95806db16f55bffc904ff961e2..801aae32841f2513ba665034ae4817945debb781 100644 (file)
 #include <linux/module.h>
 #include <linux/cpufeature.h>
 
+#include "aes-ce-setkey.h"
+
 #ifdef USE_V8_CRYPTO_EXTENSIONS
 #define MODE                   "ce"
 #define PRIO                   300
+#define aes_setkey             ce_aes_setkey
+#define aes_expandkey          ce_aes_expandkey
 #define aes_ecb_encrypt                ce_aes_ecb_encrypt
 #define aes_ecb_decrypt                ce_aes_ecb_decrypt
 #define aes_cbc_encrypt                ce_aes_cbc_encrypt
@@ -30,6 +34,8 @@ MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions");
 #else
 #define MODE                   "neon"
 #define PRIO                   200
+#define aes_setkey             crypto_aes_set_key
+#define aes_expandkey          crypto_aes_expand_key
 #define aes_ecb_encrypt                neon_aes_ecb_encrypt
 #define aes_ecb_decrypt                neon_aes_ecb_decrypt
 #define aes_cbc_encrypt                neon_aes_cbc_encrypt
@@ -79,10 +85,10 @@ static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
        struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
        int ret;
 
-       ret = crypto_aes_expand_key(&ctx->key1, in_key, key_len / 2);
+       ret = aes_expandkey(&ctx->key1, in_key, key_len / 2);
        if (!ret)
-               ret = crypto_aes_expand_key(&ctx->key2, &in_key[key_len / 2],
-                                           key_len / 2);
+               ret = aes_expandkey(&ctx->key2, &in_key[key_len / 2],
+                                   key_len / 2);
        if (!ret)
                return 0;
 
@@ -288,7 +294,7 @@ static struct crypto_alg aes_algs[] = { {
                .min_keysize    = AES_MIN_KEY_SIZE,
                .max_keysize    = AES_MAX_KEY_SIZE,
                .ivsize         = AES_BLOCK_SIZE,
-               .setkey         = crypto_aes_set_key,
+               .setkey         = aes_setkey,
                .encrypt        = ecb_encrypt,
                .decrypt        = ecb_decrypt,
        },
@@ -306,7 +312,7 @@ static struct crypto_alg aes_algs[] = { {
                .min_keysize    = AES_MIN_KEY_SIZE,
                .max_keysize    = AES_MAX_KEY_SIZE,
                .ivsize         = AES_BLOCK_SIZE,
-               .setkey         = crypto_aes_set_key,
+               .setkey         = aes_setkey,
                .encrypt        = cbc_encrypt,
                .decrypt        = cbc_decrypt,
        },
@@ -324,7 +330,7 @@ static struct crypto_alg aes_algs[] = { {
                .min_keysize    = AES_MIN_KEY_SIZE,
                .max_keysize    = AES_MAX_KEY_SIZE,
                .ivsize         = AES_BLOCK_SIZE,
-               .setkey         = crypto_aes_set_key,
+               .setkey         = aes_setkey,
                .encrypt        = ctr_encrypt,
                .decrypt        = ctr_encrypt,
        },
diff --git a/arch/arm64/include/asm/alternative-asm.h b/arch/arm64/include/asm/alternative-asm.h
new file mode 100644 (file)
index 0000000..919a678
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ASM_ALTERNATIVE_ASM_H
+#define __ASM_ALTERNATIVE_ASM_H
+
+#ifdef __ASSEMBLY__
+
+.macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len
+       .word \orig_offset - .
+       .word \alt_offset - .
+       .hword \feature
+       .byte \orig_len
+       .byte \alt_len
+.endm
+
+.macro alternative_insn insn1 insn2 cap
+661:   \insn1
+662:   .pushsection .altinstructions, "a"
+       altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
+       .popsection
+       .pushsection .altinstr_replacement, "ax"
+663:   \insn2
+664:   .popsection
+       .if ((664b-663b) != (662b-661b))
+               .error "Alternatives instruction length mismatch"
+       .endif
+.endm
+
+#endif  /*  __ASSEMBLY__  */
+
+#endif /* __ASM_ALTERNATIVE_ASM_H */
diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
new file mode 100644 (file)
index 0000000..d261f01
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __ASM_ALTERNATIVE_H
+#define __ASM_ALTERNATIVE_H
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/stringify.h>
+
+struct alt_instr {
+       s32 orig_offset;        /* offset to original instruction */
+       s32 alt_offset;         /* offset to replacement instruction */
+       u16 cpufeature;         /* cpufeature bit set for replacement */
+       u8  orig_len;           /* size of original instruction(s) */
+       u8  alt_len;            /* size of new instruction(s), <= orig_len */
+};
+
+void apply_alternatives_all(void);
+void apply_alternatives(void *start, size_t length);
+void free_alternatives_memory(void);
+
+#define ALTINSTR_ENTRY(feature)                                                      \
+       " .word 661b - .\n"                             /* label           */ \
+       " .word 663f - .\n"                             /* new instruction */ \
+       " .hword " __stringify(feature) "\n"            /* feature bit     */ \
+       " .byte 662b-661b\n"                            /* source len      */ \
+       " .byte 664f-663f\n"                            /* replacement len */
+
+/* alternative assembly primitive: */
+#define ALTERNATIVE(oldinstr, newinstr, feature)                       \
+       "661:\n\t"                                                      \
+       oldinstr "\n"                                                   \
+       "662:\n"                                                        \
+       ".pushsection .altinstructions,\"a\"\n"                         \
+       ALTINSTR_ENTRY(feature)                                         \
+       ".popsection\n"                                                 \
+       ".pushsection .altinstr_replacement, \"a\"\n"                   \
+       "663:\n\t"                                                      \
+       newinstr "\n"                                                   \
+       "664:\n\t"                                                      \
+       ".popsection\n\t"                                               \
+       ".if ((664b-663b) != (662b-661b))\n\t"                          \
+       "       .error \"Alternatives instruction length mismatch\"\n\t"\
+       ".endif\n"
+
+#endif /* __ASM_ALTERNATIVE_H */
index f19097134b02d6cc14f4a4f3fe4deb5a6225d6c0..b1fa4e61471814f78e4c5f99ed349afc98541121 100644 (file)
@@ -104,6 +104,15 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
        asm volatile("msr       cntkctl_el1, %0" : : "r" (cntkctl));
 }
 
+static inline u64 arch_counter_get_cntpct(void)
+{
+       /*
+        * AArch64 kernel and user space mandate the use of CNTVCT.
+        */
+       BUG();
+       return 0;
+}
+
 static inline u64 arch_counter_get_cntvct(void)
 {
        u64 cval;
index 88cc05b5f3aca1ae9d799c4d82880a6bd23c9b3e..bde449936e2f07fda4abf1e3c840fe9401620708 100644 (file)
@@ -32,6 +32,8 @@
 
 #ifndef __ASSEMBLY__
 
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
 static inline int cache_line_size(void)
 {
        u32 cwg = cache_type_cwg();
index 689b6379188c112ac2441833e165dcb63b0b4515..7ae31a2cc6c0ba97780200bef8a0fe96c7a3127e 100644 (file)
@@ -73,7 +73,7 @@ extern void flush_cache_all(void);
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void __flush_dcache_area(void *addr, size_t len);
-extern void __flush_cache_user_range(unsigned long start, unsigned long end);
+extern long __flush_cache_user_range(unsigned long start, unsigned long end);
 
 static inline void flush_cache_mm(struct mm_struct *mm)
 {
index ddb9d7830558f0840bf7b71fac33a20388c4a1f6..cb9593079f29763c34f7e68fa89737355ac03adb 100644 (file)
@@ -19,6 +19,7 @@
 #define __ASM_CMPXCHG_H
 
 #include <linux/bug.h>
+#include <linux/mmdebug.h>
 
 #include <asm/barrier.h>
 
@@ -152,6 +153,51 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
        return oldval;
 }
 
+#define system_has_cmpxchg_double()     1
+
+static inline int __cmpxchg_double(volatile void *ptr1, volatile void *ptr2,
+               unsigned long old1, unsigned long old2,
+               unsigned long new1, unsigned long new2, int size)
+{
+       unsigned long loop, lost;
+
+       switch (size) {
+       case 8:
+               VM_BUG_ON((unsigned long *)ptr2 - (unsigned long *)ptr1 != 1);
+               do {
+                       asm volatile("// __cmpxchg_double8\n"
+                       "       ldxp    %0, %1, %2\n"
+                       "       eor     %0, %0, %3\n"
+                       "       eor     %1, %1, %4\n"
+                       "       orr     %1, %0, %1\n"
+                       "       mov     %w0, #0\n"
+                       "       cbnz    %1, 1f\n"
+                       "       stxp    %w0, %5, %6, %2\n"
+                       "1:\n"
+                               : "=&r"(loop), "=&r"(lost), "+Q" (*(u64 *)ptr1)
+                               : "r" (old1), "r"(old2), "r"(new1), "r"(new2));
+               } while (loop);
+               break;
+       default:
+               BUILD_BUG();
+       }
+
+       return !lost;
+}
+
+static inline int __cmpxchg_double_mb(volatile void *ptr1, volatile void *ptr2,
+                       unsigned long old1, unsigned long old2,
+                       unsigned long new1, unsigned long new2, int size)
+{
+       int ret;
+
+       smp_mb();
+       ret = __cmpxchg_double(ptr1, ptr2, old1, old2, new1, new2, size);
+       smp_mb();
+
+       return ret;
+}
+
 static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
                                         unsigned long new, int size)
 {
@@ -182,6 +228,33 @@ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
        __ret; \
 })
 
+#define cmpxchg_double(ptr1, ptr2, o1, o2, n1, n2) \
+({\
+       int __ret;\
+       __ret = __cmpxchg_double_mb((ptr1), (ptr2), (unsigned long)(o1), \
+                       (unsigned long)(o2), (unsigned long)(n1), \
+                       (unsigned long)(n2), sizeof(*(ptr1)));\
+       __ret; \
+})
+
+#define cmpxchg_double_local(ptr1, ptr2, o1, o2, n1, n2) \
+({\
+       int __ret;\
+       __ret = __cmpxchg_double((ptr1), (ptr2), (unsigned long)(o1), \
+                       (unsigned long)(o2), (unsigned long)(n1), \
+                       (unsigned long)(n2), sizeof(*(ptr1)));\
+       __ret; \
+})
+
+#define this_cpu_cmpxchg_1(ptr, o, n) cmpxchg_local(raw_cpu_ptr(&(ptr)), o, n)
+#define this_cpu_cmpxchg_2(ptr, o, n) cmpxchg_local(raw_cpu_ptr(&(ptr)), o, n)
+#define this_cpu_cmpxchg_4(ptr, o, n) cmpxchg_local(raw_cpu_ptr(&(ptr)), o, n)
+#define this_cpu_cmpxchg_8(ptr, o, n) cmpxchg_local(raw_cpu_ptr(&(ptr)), o, n)
+
+#define this_cpu_cmpxchg_double_8(ptr1, ptr2, o1, o2, n1, n2) \
+       cmpxchg_double_local(raw_cpu_ptr(&(ptr1)), raw_cpu_ptr(&(ptr2)), \
+                               o1, o2, n1, n2)
+
 #define cmpxchg64(ptr,o,n)             cmpxchg((ptr),(o),(n))
 #define cmpxchg64_local(ptr,o,n)       cmpxchg_local((ptr),(o),(n))
 
index 253e33bc94fb5e4e4a33b39be0151070cda825db..3fb053fa6e981b40accf4180187dd0789edeb1f0 100644 (file)
@@ -37,8 +37,8 @@ typedef s32           compat_ssize_t;
 typedef s32            compat_time_t;
 typedef s32            compat_clock_t;
 typedef s32            compat_pid_t;
-typedef u32            __compat_uid_t;
-typedef u32            __compat_gid_t;
+typedef u16            __compat_uid_t;
+typedef u16            __compat_gid_t;
 typedef u16            __compat_uid16_t;
 typedef u16            __compat_gid16_t;
 typedef u32            __compat_uid32_t;
@@ -205,6 +205,13 @@ typedef struct compat_siginfo {
                        compat_long_t _band;    /* POLL_IN, POLL_OUT, POLL_MSG */
                        int _fd;
                } _sigpoll;
+
+               /* SIGSYS */
+               struct {
+                       compat_uptr_t _call_addr; /* calling user insn */
+                       int _syscall;   /* triggering system call number */
+                       compat_uint_t _arch;    /* AUDIT_ARCH_* of syscall */
+               } _sigsys;
        } _sifields;
 } compat_siginfo_t;
 
index 05644308601984d2bd78cb46de8ee96303823568..ace70682499b69b3e23e36215bb8760c6ea67cb3 100644 (file)
@@ -30,6 +30,8 @@ struct cpuinfo_arm64 {
        u32             reg_dczid;
        u32             reg_midr;
 
+       u64             reg_id_aa64dfr0;
+       u64             reg_id_aa64dfr1;
        u64             reg_id_aa64isar0;
        u64             reg_id_aa64isar1;
        u64             reg_id_aa64mmfr0;
index cd4ac0516488fe1f0d2357310a121f67855ce38c..07547ccc1f2bd2945edd53a037915c0368ab2400 100644 (file)
 #define MAX_CPU_FEATURES       (8 * sizeof(elf_hwcap))
 #define cpu_feature(x)         ilog2(HWCAP_ ## x)
 
+#define ARM64_WORKAROUND_CLEAN_CACHE           0
+#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE   1
+
+#define ARM64_NCAPS                            2
+
+#ifndef __ASSEMBLY__
+
+extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
+
 static inline bool cpu_have_feature(unsigned int num)
 {
        return elf_hwcap & (1UL << num);
 }
 
+static inline bool cpus_have_cap(unsigned int num)
+{
+       if (num >= ARM64_NCAPS)
+               return false;
+       return test_bit(num, cpu_hwcaps);
+}
+
+static inline void cpus_set_cap(unsigned int num)
+{
+       if (num >= ARM64_NCAPS)
+               pr_warn("Attempt to set an illegal CPU capability (%d >= %d)\n",
+                       num, ARM64_NCAPS);
+       else
+               __set_bit(num, cpu_hwcaps);
+}
+
+void check_local_cpu_errata(void);
+
+#endif /* __ASSEMBLY__ */
+
 #endif
index 379d0b874328caa7f59dae03f7f08659b81eebdf..8adb986a3086a3ee75e83aa165fe7273cf3575f0 100644 (file)
 #define MIDR_IMPLEMENTOR(midr) \
        (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
 
+#define MIDR_CPU_PART(imp, partnum) \
+       (((imp)                 << MIDR_IMPLEMENTOR_SHIFT) | \
+       (0xf                    << MIDR_ARCHITECTURE_SHIFT) | \
+       ((partnum)              << MIDR_PARTNUM_SHIFT))
+
 #define ARM_CPU_IMP_ARM                0x41
 #define ARM_CPU_IMP_APM                0x50
 
diff --git a/arch/arm64/include/asm/dmi.h b/arch/arm64/include/asm/dmi.h
new file mode 100644 (file)
index 0000000..69d37d8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * arch/arm64/include/asm/dmi.h
+ *
+ * Copyright (C) 2013 Linaro Limited.
+ * Written by: Yi Li (yi.li@linaro.org)
+ *
+ * based on arch/ia64/include/asm/dmi.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef __ASM_DMI_H
+#define __ASM_DMI_H
+
+#include <linux/io.h>
+#include <linux/slab.h>
+
+/*
+ * According to section 2.3.6 of the UEFI spec, the firmware should not
+ * request a virtual mapping for configuration tables such as SMBIOS.
+ * This means we have to map them before use.
+ */
+#define dmi_early_remap(x, l)          ioremap_cache(x, l)
+#define dmi_early_unmap(x, l)          iounmap(x)
+#define dmi_remap(x, l)                        ioremap_cache(x, l)
+#define dmi_unmap(x)                   iounmap(x)
+#define dmi_alloc(l)                   kzalloc(l, GFP_KERNEL)
+
+#endif
index 01d3aab64b79f3c13fdd602b9e8a16bf14a8fda8..1f65be3931392c24352763bb9365430d48670b41 100644 (file)
@@ -126,7 +126,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;
  * that it will "exec", and that there is sufficient room for the brk.
  */
 extern unsigned long randomize_et_dyn(unsigned long base);
-#define ELF_ET_DYN_BASE        (randomize_et_dyn(2 * TASK_SIZE_64 / 3))
+#define ELF_ET_DYN_BASE        (2 * TASK_SIZE_64 / 3)
 
 /*
  * When the program starts, a1 contains a pointer to a function to be
@@ -169,7 +169,7 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define COMPAT_ELF_PLATFORM            ("v8l")
 #endif
 
-#define COMPAT_ELF_ET_DYN_BASE         (randomize_et_dyn(2 * TASK_SIZE_32 / 3))
+#define COMPAT_ELF_ET_DYN_BASE         (2 * TASK_SIZE_32 / 3)
 
 /* AArch32 registers. */
 #define COMPAT_ELF_NGREG               18
index 5f7bfe6df723bb08ef5d20cc9deb196dab8a3811..9ef6eca905cae91aef5e86d8b7417d1c906f6917 100644 (file)
@@ -31,6 +31,7 @@
  *
  */
 enum fixed_addresses {
+       FIX_HOLE,
        FIX_EARLYCON_MEM_BASE,
        __end_of_permanent_fixed_addresses,
 
@@ -56,10 +57,11 @@ enum fixed_addresses {
 
 #define FIXMAP_PAGE_IO     __pgprot(PROT_DEVICE_nGnRE)
 
-extern void __early_set_fixmap(enum fixed_addresses idx,
-                              phys_addr_t phys, pgprot_t flags);
+void __init early_fixmap_init(void);
 
-#define __set_fixmap __early_set_fixmap
+#define __early_set_fixmap __set_fixmap
+
+extern void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
 
 #include <asm-generic/fixmap.h>
 
index 024c46183c3cc4bac07977ffcdade60c2567ea98..0ad735166d9fa7303eaa961d6f07d833c95b84ff 100644 (file)
@@ -30,6 +30,7 @@
 #define COMPAT_HWCAP_IDIVA     (1 << 17)
 #define COMPAT_HWCAP_IDIVT     (1 << 18)
 #define COMPAT_HWCAP_IDIV      (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
+#define COMPAT_HWCAP_LPAE      (1 << 20)
 #define COMPAT_HWCAP_EVTSTRM   (1 << 21)
 
 #define COMPAT_HWCAP2_AES      (1 << 0)
index 56a9e63b6c33ef45dc37741a7a842df05d1667f6..e2ff32a93b5cefc2c6fc2866d4d7befed27259fc 100644 (file)
@@ -354,6 +354,16 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+
+bool aarch32_insn_is_wide(u32 insn);
+
+#define A32_RN_OFFSET  16
+#define A32_RT_OFFSET  12
+#define A32_RT2_OFFSET  0
+
+u32 aarch32_insn_extract_reg_num(u32 insn, int offset);
+u32 aarch32_insn_mcr_extract_opc2(u32 insn);
+u32 aarch32_insn_mcr_extract_crm(u32 insn);
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_INSN_H */
index 79f1d519221f839eb8e6488d14e7978ce6a3cd22..949c406d4df431902f02d493c0cb133ca4c1728b 100644 (file)
 #include <asm/barrier.h>
 #include <asm/pgtable.h>
 #include <asm/early_ioremap.h>
+#include <asm/alternative.h>
+#include <asm/cpufeature.h>
 
 #include <xen/xen.h>
 
 /*
  * Generic IO read/write.  These perform native-endian accesses.
  */
+#define __raw_writeb __raw_writeb
 static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
 {
        asm volatile("strb %w0, [%1]" : : "r" (val), "r" (addr));
 }
 
+#define __raw_writew __raw_writew
 static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 {
        asm volatile("strh %w0, [%1]" : : "r" (val), "r" (addr));
 }
 
+#define __raw_writel __raw_writel
 static inline void __raw_writel(u32 val, volatile void __iomem *addr)
 {
        asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr));
 }
 
+#define __raw_writeq __raw_writeq
 static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
 {
        asm volatile("str %0, [%1]" : : "r" (val), "r" (addr));
 }
 
+#define __raw_readb __raw_readb
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
        u8 val;
-       asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr));
+       asm volatile(ALTERNATIVE("ldrb %w0, [%1]",
+                                "ldarb %w0, [%1]",
+                                ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                    : "=r" (val) : "r" (addr));
        return val;
 }
 
+#define __raw_readw __raw_readw
 static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
        u16 val;
-       asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr));
+
+       asm volatile(ALTERNATIVE("ldrh %w0, [%1]",
+                                "ldarh %w0, [%1]",
+                                ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                    : "=r" (val) : "r" (addr));
        return val;
 }
 
+#define __raw_readl __raw_readl
 static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
        u32 val;
-       asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
+       asm volatile(ALTERNATIVE("ldr %w0, [%1]",
+                                "ldar %w0, [%1]",
+                                ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                    : "=r" (val) : "r" (addr));
        return val;
 }
 
+#define __raw_readq __raw_readq
 static inline u64 __raw_readq(const volatile void __iomem *addr)
 {
        u64 val;
-       asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr));
+       asm volatile(ALTERNATIVE("ldr %0, [%1]",
+                                "ldar %0, [%1]",
+                                ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                    : "=r" (val) : "r" (addr));
        return val;
 }
 
@@ -125,94 +148,6 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
 #define IO_SPACE_LIMIT         (SZ_32M - 1)
 #define PCI_IOBASE             ((void __iomem *)(MODULES_VADDR - SZ_32M))
 
-static inline u8 inb(unsigned long addr)
-{
-       return readb(addr + PCI_IOBASE);
-}
-
-static inline u16 inw(unsigned long addr)
-{
-       return readw(addr + PCI_IOBASE);
-}
-
-static inline u32 inl(unsigned long addr)
-{
-       return readl(addr + PCI_IOBASE);
-}
-
-static inline void outb(u8 b, unsigned long addr)
-{
-       writeb(b, addr + PCI_IOBASE);
-}
-
-static inline void outw(u16 b, unsigned long addr)
-{
-       writew(b, addr + PCI_IOBASE);
-}
-
-static inline void outl(u32 b, unsigned long addr)
-{
-       writel(b, addr + PCI_IOBASE);
-}
-
-#define inb_p(addr)    inb(addr)
-#define inw_p(addr)    inw(addr)
-#define inl_p(addr)    inl(addr)
-
-#define outb_p(x, addr)        outb((x), (addr))
-#define outw_p(x, addr)        outw((x), (addr))
-#define outl_p(x, addr)        outl((x), (addr))
-
-static inline void insb(unsigned long addr, void *buffer, int count)
-{
-       u8 *buf = buffer;
-       while (count--)
-               *buf++ = __raw_readb(addr + PCI_IOBASE);
-}
-
-static inline void insw(unsigned long addr, void *buffer, int count)
-{
-       u16 *buf = buffer;
-       while (count--)
-               *buf++ = __raw_readw(addr + PCI_IOBASE);
-}
-
-static inline void insl(unsigned long addr, void *buffer, int count)
-{
-       u32 *buf = buffer;
-       while (count--)
-               *buf++ = __raw_readl(addr + PCI_IOBASE);
-}
-
-static inline void outsb(unsigned long addr, const void *buffer, int count)
-{
-       const u8 *buf = buffer;
-       while (count--)
-               __raw_writeb(*buf++, addr + PCI_IOBASE);
-}
-
-static inline void outsw(unsigned long addr, const void *buffer, int count)
-{
-       const u16 *buf = buffer;
-       while (count--)
-               __raw_writew(*buf++, addr + PCI_IOBASE);
-}
-
-static inline void outsl(unsigned long addr, const void *buffer, int count)
-{
-       const u32 *buf = buffer;
-       while (count--)
-               __raw_writel(*buf++, addr + PCI_IOBASE);
-}
-
-#define insb_p(port,to,len)    insb(port,to,len)
-#define insw_p(port,to,len)    insw(port,to,len)
-#define insl_p(port,to,len)    insl(port,to,len)
-
-#define outsb_p(port,from,len) outsb(port,from,len)
-#define outsw_p(port,from,len) outsw(port,from,len)
-#define outsl_p(port,from,len) outsl(port,from,len)
-
 /*
  * String version of I/O memory access operations.
  */
@@ -236,18 +171,14 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 #define ioremap_wc(addr, size)         __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
 #define iounmap                                __iounmap
 
-#define ARCH_HAS_IOREMAP_WC
-#include <asm-generic/iomap.h>
-
 /*
- * More restrictive address range checking than the default implementation
- * (PHYS_OFFSET and PHYS_MASK taken into account).
+ * io{read,write}{16,32}be() macros
  */
-#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
-extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+#define ioread16be(p)          ({ __u16 __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; })
+#define ioread32be(p)          ({ __u32 __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; })
 
-extern int devmem_is_allowed(unsigned long pfn);
+#define iowrite16be(v,p)       ({ __iowmb(); __raw_writew((__force __u16)cpu_to_be16(v), p); })
+#define iowrite32be(v,p)       ({ __iowmb(); __raw_writel((__force __u32)cpu_to_be32(v), p); })
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
@@ -260,6 +191,18 @@ extern int devmem_is_allowed(unsigned long pfn);
  */
 #define xlate_dev_kmem_ptr(p)  p
 
+#include <asm-generic/io.h>
+
+/*
+ * More restrictive address range checking than the default implementation
+ * (PHYS_OFFSET and PHYS_MASK taken into account).
+ */
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
+extern int devmem_is_allowed(unsigned long pfn);
+
 struct bio_vec;
 extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
                                      const struct bio_vec *vec2);
index e1f7ecdde11ffd6103bd41ab19e625a9c76c2f85..94c53674a31d24f45b6b392d90ac840c6bde7589 100644 (file)
@@ -3,7 +3,8 @@
 
 #include <asm-generic/irq.h>
 
-extern void (*handle_arch_irq)(struct pt_regs *);
+struct pt_regs;
+
 extern void migrate_irqs(void);
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
index 8e24ef3f7c82c7c9dc7af7ea9b07c34ed27a7631..b4f6b19a8a685d0adba9b35534b6782b79b81043 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_IRQ_WORK_H
 #define __ASM_IRQ_WORK_H
 
+#ifdef CONFIG_SMP
+
 #include <asm/smp.h>
 
 static inline bool arch_irq_work_has_interrupt(void)
@@ -8,4 +10,13 @@ static inline bool arch_irq_work_has_interrupt(void)
        return !!__smp_cross_call;
 }
 
+#else
+
+static inline bool arch_irq_work_has_interrupt(void)
+{
+       return false;
+}
+
+#endif
+
 #endif /* __ASM_IRQ_WORK_H */
index 7fd3e27e3ccc80f1b4d27f7980f7d187af125d3c..8afb863f5a9e3a7651a415c80057e1a5c4b592c6 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef __ARM64_KVM_ARM_H__
 #define __ARM64_KVM_ARM_H__
 
+#include <asm/memory.h>
 #include <asm/types.h>
 
 /* Hyp Configuration Register (HCR) bits */
 #endif
 
 #define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
-#define VTTBR_BADDR_MASK  (((1LLU << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
-#define VTTBR_VMID_SHIFT  (48LLU)
-#define VTTBR_VMID_MASK          (0xffLLU << VTTBR_VMID_SHIFT)
+#define VTTBR_BADDR_MASK  (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
+#define VTTBR_VMID_SHIFT  (UL(48))
+#define VTTBR_VMID_MASK          (UL(0xFF) << VTTBR_VMID_SHIFT)
 
 /* Hyp System Trap Register */
 #define HSTR_EL2_TTEE  (1 << 16)
 
 /* Exception Syndrome Register (ESR) bits */
 #define ESR_EL2_EC_SHIFT       (26)
-#define ESR_EL2_EC             (0x3fU << ESR_EL2_EC_SHIFT)
-#define ESR_EL2_IL             (1U << 25)
+#define ESR_EL2_EC             (UL(0x3f) << ESR_EL2_EC_SHIFT)
+#define ESR_EL2_IL             (UL(1) << 25)
 #define ESR_EL2_ISS            (ESR_EL2_IL - 1)
 #define ESR_EL2_ISV_SHIFT      (24)
-#define ESR_EL2_ISV            (1U << ESR_EL2_ISV_SHIFT)
+#define ESR_EL2_ISV            (UL(1) << ESR_EL2_ISV_SHIFT)
 #define ESR_EL2_SAS_SHIFT      (22)
-#define ESR_EL2_SAS            (3U << ESR_EL2_SAS_SHIFT)
+#define ESR_EL2_SAS            (UL(3) << ESR_EL2_SAS_SHIFT)
 #define ESR_EL2_SSE            (1 << 21)
 #define ESR_EL2_SRT_SHIFT      (16)
 #define ESR_EL2_SRT_MASK       (0x1f << ESR_EL2_SRT_SHIFT)
 #define ESR_EL2_FSC_TYPE       (0x3c)
 
 #define ESR_EL2_CV_SHIFT       (24)
-#define ESR_EL2_CV             (1U << ESR_EL2_CV_SHIFT)
+#define ESR_EL2_CV             (UL(1) << ESR_EL2_CV_SHIFT)
 #define ESR_EL2_COND_SHIFT     (20)
-#define ESR_EL2_COND           (0xfU << ESR_EL2_COND_SHIFT)
+#define ESR_EL2_COND           (UL(0xf) << ESR_EL2_COND_SHIFT)
 
 
 #define FSC_FAULT      (0x04)
 #define FSC_PERM       (0x0c)
 
 /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
-#define HPFAR_MASK     (~0xFUL)
+#define HPFAR_MASK     (~UL(0xf))
 
 #define ESR_EL2_EC_UNKNOWN     (0x00)
 #define ESR_EL2_EC_WFI         (0x01)
index ccc7087d3c4ea7451ac3734a395b6d6607bbdd2b..6486b2bfd56263c920cd28d840d9583212391d01 100644 (file)
@@ -120,11 +120,13 @@ extern phys_addr_t                memstart_addr;
  * translation for translating DMA addresses.  Use the driver
  * DMA support - see dma-mapping.h.
  */
+#define virt_to_phys virt_to_phys
 static inline phys_addr_t virt_to_phys(const volatile void *x)
 {
        return __virt_to_phys((unsigned long)(x));
 }
 
+#define phys_to_virt phys_to_virt
 static inline void *phys_to_virt(phys_addr_t x)
 {
        return (void *)(__phys_to_virt(x));
@@ -142,7 +144,7 @@ static inline void *phys_to_virt(phys_addr_t x)
  *  virt_to_page(k)    convert a _valid_ virtual address to struct page *
  *  virt_addr_valid(k) indicates whether a virtual address is valid
  */
-#define ARCH_PFN_OFFSET                PHYS_PFN_OFFSET
+#define ARCH_PFN_OFFSET                ((unsigned long)PHYS_PFN_OFFSET)
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define        virt_addr_valid(kaddr)  pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
diff --git a/arch/arm64/include/asm/opcodes.h b/arch/arm64/include/asm/opcodes.h
new file mode 100644 (file)
index 0000000..4e603ea
--- /dev/null
@@ -0,0 +1 @@
+#include <../../arm/include/asm/opcodes.h>
index 5279e573338690afbee3c7e593858baa9f7b9e42..09da25bc596fd0bdccdf03e94b37a4c81e0cc633 100644 (file)
@@ -44,6 +44,221 @@ static inline unsigned long __my_cpu_offset(void)
 
 #endif /* CONFIG_SMP */
 
+#define PERCPU_OP(op, asm_op)                                          \
+static inline unsigned long __percpu_##op(void *ptr,                   \
+                       unsigned long val, int size)                    \
+{                                                                      \
+       unsigned long loop, ret;                                        \
+                                                                       \
+       switch (size) {                                                 \
+       case 1:                                                         \
+               do {                                                    \
+                       asm ("//__per_cpu_" #op "_1\n"                  \
+                       "ldxrb    %w[ret], %[ptr]\n"                    \
+                       #asm_op " %w[ret], %w[ret], %w[val]\n"          \
+                       "stxrb    %w[loop], %w[ret], %[ptr]\n"          \
+                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
+                         [ptr] "+Q"(*(u8 *)ptr)                        \
+                       : [val] "Ir" (val));                            \
+               } while (loop);                                         \
+               break;                                                  \
+       case 2:                                                         \
+               do {                                                    \
+                       asm ("//__per_cpu_" #op "_2\n"                  \
+                       "ldxrh    %w[ret], %[ptr]\n"                    \
+                       #asm_op " %w[ret], %w[ret], %w[val]\n"          \
+                       "stxrh    %w[loop], %w[ret], %[ptr]\n"          \
+                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
+                         [ptr]  "+Q"(*(u16 *)ptr)                      \
+                       : [val] "Ir" (val));                            \
+               } while (loop);                                         \
+               break;                                                  \
+       case 4:                                                         \
+               do {                                                    \
+                       asm ("//__per_cpu_" #op "_4\n"                  \
+                       "ldxr     %w[ret], %[ptr]\n"                    \
+                       #asm_op " %w[ret], %w[ret], %w[val]\n"          \
+                       "stxr     %w[loop], %w[ret], %[ptr]\n"          \
+                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
+                         [ptr] "+Q"(*(u32 *)ptr)                       \
+                       : [val] "Ir" (val));                            \
+               } while (loop);                                         \
+               break;                                                  \
+       case 8:                                                         \
+               do {                                                    \
+                       asm ("//__per_cpu_" #op "_8\n"                  \
+                       "ldxr     %[ret], %[ptr]\n"                     \
+                       #asm_op " %[ret], %[ret], %[val]\n"             \
+                       "stxr     %w[loop], %[ret], %[ptr]\n"           \
+                       : [loop] "=&r" (loop), [ret] "=&r" (ret),       \
+                         [ptr] "+Q"(*(u64 *)ptr)                       \
+                       : [val] "Ir" (val));                            \
+               } while (loop);                                         \
+               break;                                                  \
+       default:                                                        \
+               BUILD_BUG();                                            \
+       }                                                               \
+                                                                       \
+       return ret;                                                     \
+}
+
+PERCPU_OP(add, add)
+PERCPU_OP(and, and)
+PERCPU_OP(or, orr)
+#undef PERCPU_OP
+
+static inline unsigned long __percpu_read(void *ptr, int size)
+{
+       unsigned long ret;
+
+       switch (size) {
+       case 1:
+               ret = ACCESS_ONCE(*(u8 *)ptr);
+               break;
+       case 2:
+               ret = ACCESS_ONCE(*(u16 *)ptr);
+               break;
+       case 4:
+               ret = ACCESS_ONCE(*(u32 *)ptr);
+               break;
+       case 8:
+               ret = ACCESS_ONCE(*(u64 *)ptr);
+               break;
+       default:
+               BUILD_BUG();
+       }
+
+       return ret;
+}
+
+static inline void __percpu_write(void *ptr, unsigned long val, int size)
+{
+       switch (size) {
+       case 1:
+               ACCESS_ONCE(*(u8 *)ptr) = (u8)val;
+               break;
+       case 2:
+               ACCESS_ONCE(*(u16 *)ptr) = (u16)val;
+               break;
+       case 4:
+               ACCESS_ONCE(*(u32 *)ptr) = (u32)val;
+               break;
+       case 8:
+               ACCESS_ONCE(*(u64 *)ptr) = (u64)val;
+               break;
+       default:
+               BUILD_BUG();
+       }
+}
+
+static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
+                                               int size)
+{
+       unsigned long ret, loop;
+
+       switch (size) {
+       case 1:
+               do {
+                       asm ("//__percpu_xchg_1\n"
+                       "ldxrb %w[ret], %[ptr]\n"
+                       "stxrb %w[loop], %w[val], %[ptr]\n"
+                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                         [ptr] "+Q"(*(u8 *)ptr)
+                       : [val] "r" (val));
+               } while (loop);
+               break;
+       case 2:
+               do {
+                       asm ("//__percpu_xchg_2\n"
+                       "ldxrh %w[ret], %[ptr]\n"
+                       "stxrh %w[loop], %w[val], %[ptr]\n"
+                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                         [ptr] "+Q"(*(u16 *)ptr)
+                       : [val] "r" (val));
+               } while (loop);
+               break;
+       case 4:
+               do {
+                       asm ("//__percpu_xchg_4\n"
+                       "ldxr %w[ret], %[ptr]\n"
+                       "stxr %w[loop], %w[val], %[ptr]\n"
+                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                         [ptr] "+Q"(*(u32 *)ptr)
+                       : [val] "r" (val));
+               } while (loop);
+               break;
+       case 8:
+               do {
+                       asm ("//__percpu_xchg_8\n"
+                       "ldxr %[ret], %[ptr]\n"
+                       "stxr %w[loop], %[val], %[ptr]\n"
+                       : [loop] "=&r"(loop), [ret] "=&r"(ret),
+                         [ptr] "+Q"(*(u64 *)ptr)
+                       : [val] "r" (val));
+               } while (loop);
+               break;
+       default:
+               BUILD_BUG();
+       }
+
+       return ret;
+}
+
+#define _percpu_add(pcp, val) \
+       __percpu_add(raw_cpu_ptr(&(pcp)), val, sizeof(pcp))
+
+#define _percpu_add_return(pcp, val) (typeof(pcp)) (_percpu_add(pcp, val))
+
+#define _percpu_and(pcp, val) \
+       __percpu_and(raw_cpu_ptr(&(pcp)), val, sizeof(pcp))
+
+#define _percpu_or(pcp, val) \
+       __percpu_or(raw_cpu_ptr(&(pcp)), val, sizeof(pcp))
+
+#define _percpu_read(pcp) (typeof(pcp))        \
+       (__percpu_read(raw_cpu_ptr(&(pcp)), sizeof(pcp)))
+
+#define _percpu_write(pcp, val) \
+       __percpu_write(raw_cpu_ptr(&(pcp)), (unsigned long)(val), sizeof(pcp))
+
+#define _percpu_xchg(pcp, val) (typeof(pcp)) \
+       (__percpu_xchg(raw_cpu_ptr(&(pcp)), (unsigned long)(val), sizeof(pcp)))
+
+#define this_cpu_add_1(pcp, val) _percpu_add(pcp, val)
+#define this_cpu_add_2(pcp, val) _percpu_add(pcp, val)
+#define this_cpu_add_4(pcp, val) _percpu_add(pcp, val)
+#define this_cpu_add_8(pcp, val) _percpu_add(pcp, val)
+
+#define this_cpu_add_return_1(pcp, val) _percpu_add_return(pcp, val)
+#define this_cpu_add_return_2(pcp, val) _percpu_add_return(pcp, val)
+#define this_cpu_add_return_4(pcp, val) _percpu_add_return(pcp, val)
+#define this_cpu_add_return_8(pcp, val) _percpu_add_return(pcp, val)
+
+#define this_cpu_and_1(pcp, val) _percpu_and(pcp, val)
+#define this_cpu_and_2(pcp, val) _percpu_and(pcp, val)
+#define this_cpu_and_4(pcp, val) _percpu_and(pcp, val)
+#define this_cpu_and_8(pcp, val) _percpu_and(pcp, val)
+
+#define this_cpu_or_1(pcp, val) _percpu_or(pcp, val)
+#define this_cpu_or_2(pcp, val) _percpu_or(pcp, val)
+#define this_cpu_or_4(pcp, val) _percpu_or(pcp, val)
+#define this_cpu_or_8(pcp, val) _percpu_or(pcp, val)
+
+#define this_cpu_read_1(pcp) _percpu_read(pcp)
+#define this_cpu_read_2(pcp) _percpu_read(pcp)
+#define this_cpu_read_4(pcp) _percpu_read(pcp)
+#define this_cpu_read_8(pcp) _percpu_read(pcp)
+
+#define this_cpu_write_1(pcp, val) _percpu_write(pcp, val)
+#define this_cpu_write_2(pcp, val) _percpu_write(pcp, val)
+#define this_cpu_write_4(pcp, val) _percpu_write(pcp, val)
+#define this_cpu_write_8(pcp, val) _percpu_write(pcp, val)
+
+#define this_cpu_xchg_1(pcp, val) _percpu_xchg(pcp, val)
+#define this_cpu_xchg_2(pcp, val) _percpu_xchg(pcp, val)
+#define this_cpu_xchg_4(pcp, val) _percpu_xchg(pcp, val)
+#define this_cpu_xchg_8(pcp, val) _percpu_xchg(pcp, val)
+
 #include <asm-generic/percpu.h>
 
 #endif /* __ASM_PERCPU_H */
index d5bed02073d69832fcd11a12d3cc548f70e50c24..e20df38a8ff3885409291b8c2f7b7edfeb4b6cb7 100644 (file)
 
 #define check_pgt_cache()              do { } while (0)
 
+#define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+
 #if CONFIG_ARM64_PGTABLE_LEVELS > 2
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+       return (pmd_t *)__get_free_page(PGALLOC_GFP);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
@@ -50,7 +52,7 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+       return (pud_t *)__get_free_page(PGALLOC_GFP);
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@@ -69,8 +71,6 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 extern pgd_t *pgd_alloc(struct mm_struct *mm);
 extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
 
-#define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
-
 static inline pte_t *
 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
 {
diff --git a/arch/arm64/include/asm/seccomp.h b/arch/arm64/include/asm/seccomp.h
new file mode 100644 (file)
index 0000000..c76fac9
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * arch/arm64/include/asm/seccomp.h
+ *
+ * Copyright (C) 2014 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@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_SECCOMP_H
+#define _ASM_SECCOMP_H
+
+#include <asm/unistd.h>
+
+#ifdef CONFIG_COMPAT
+#define __NR_seccomp_read_32           __NR_compat_read
+#define __NR_seccomp_write_32          __NR_compat_write
+#define __NR_seccomp_exit_32           __NR_compat_exit
+#define __NR_seccomp_sigreturn_32      __NR_compat_rt_sigreturn
+#endif /* CONFIG_COMPAT */
+
+#include <asm-generic/seccomp.h>
+
+#endif /* _ASM_SECCOMP_H */
index a82c0c5c8b521dc652fe9c4ca92de19f07018543..c028fe37456feade18c0c5737cf974899a8b6ee4 100644 (file)
 #ifndef __ASM_TLB_H
 #define __ASM_TLB_H
 
-#define  __tlb_remove_pmd_tlb_entry __tlb_remove_pmd_tlb_entry
-
-#include <asm-generic/tlb.h>
-
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
@@ -37,71 +33,22 @@ static inline void __tlb_remove_table(void *_table)
 #define tlb_remove_entry(tlb, entry)   tlb_remove_page(tlb, entry)
 #endif /* CONFIG_HAVE_RCU_TABLE_FREE */
 
-/*
- * There's three ways the TLB shootdown code is used:
- *  1. Unmapping a range of vmas.  See zap_page_range(), unmap_region().
- *     tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called.
- *  2. Unmapping all vmas.  See exit_mmap().
- *     tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called.
- *     Page tables will be freed.
- *  3. Unmapping argument pages.  See shift_arg_pages().
- *     tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called.
- */
+#include <asm-generic/tlb.h>
+
 static inline void tlb_flush(struct mmu_gather *tlb)
 {
        if (tlb->fullmm) {
                flush_tlb_mm(tlb->mm);
-       } else if (tlb->end > 0) {
+       } else {
                struct vm_area_struct vma = { .vm_mm = tlb->mm, };
                flush_tlb_range(&vma, tlb->start, tlb->end);
-               tlb->start = TASK_SIZE;
-               tlb->end = 0;
-       }
-}
-
-static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr)
-{
-       if (!tlb->fullmm) {
-               tlb->start = min(tlb->start, addr);
-               tlb->end = max(tlb->end, addr + PAGE_SIZE);
-       }
-}
-
-/*
- * Memorize the range for the TLB flush.
- */
-static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
-                                         unsigned long addr)
-{
-       tlb_add_flush(tlb, addr);
-}
-
-/*
- * In the case of tlb vma handling, we can optimise these away in the
- * case where we're doing a full MM flush.  When we're doing a munmap,
- * the vmas are adjusted to only cover the region to be torn down.
- */
-static inline void tlb_start_vma(struct mmu_gather *tlb,
-                                struct vm_area_struct *vma)
-{
-       if (!tlb->fullmm) {
-               tlb->start = TASK_SIZE;
-               tlb->end = 0;
        }
 }
 
-static inline void tlb_end_vma(struct mmu_gather *tlb,
-                              struct vm_area_struct *vma)
-{
-       if (!tlb->fullmm)
-               tlb_flush(tlb);
-}
-
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
                                  unsigned long addr)
 {
        pgtable_page_dtor(pte);
-       tlb_add_flush(tlb, addr);
        tlb_remove_entry(tlb, pte);
 }
 
@@ -109,7 +56,6 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
 static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
                                  unsigned long addr)
 {
-       tlb_add_flush(tlb, addr);
        tlb_remove_entry(tlb, virt_to_page(pmdp));
 }
 #endif
@@ -118,15 +64,8 @@ static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
 static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pudp,
                                  unsigned long addr)
 {
-       tlb_add_flush(tlb, addr);
        tlb_remove_entry(tlb, virt_to_page(pudp));
 }
 #endif
 
-static inline void __tlb_remove_pmd_tlb_entry(struct mmu_gather *tlb, pmd_t *pmdp,
-                                               unsigned long address)
-{
-       tlb_add_flush(tlb, address);
-}
-
 #endif
index 10ca8ff93cc25ca99a00b0bd3ed6993daea633a1..232e4ba5d314ca10f15290214ab2f3d5ef550c48 100644 (file)
 #ifndef __ASM_TRAP_H
 #define __ASM_TRAP_H
 
+#include <linux/list.h>
+
+struct pt_regs;
+
+struct undef_hook {
+       struct list_head node;
+       u32 instr_mask;
+       u32 instr_val;
+       u64 pstate_mask;
+       u64 pstate_val;
+       int (*fn)(struct pt_regs *regs, u32 instr);
+};
+
+void register_undef_hook(struct undef_hook *hook);
+void unregister_undef_hook(struct undef_hook *hook);
+
 static inline int in_exception_text(unsigned long ptr)
 {
        extern char __exception_text_start[];
index 6d2bf419431d86aece4a3aa0650091f120d3efcd..49c9aefd24a50e1892c4df018e784fc44be4617e 100644 (file)
@@ -31,6 +31,9 @@
  * Compat syscall numbers used by the AArch64 kernel.
  */
 #define __NR_compat_restart_syscall    0
+#define __NR_compat_exit               1
+#define __NR_compat_read               3
+#define __NR_compat_write              4
 #define __NR_compat_sigreturn          119
 #define __NR_compat_rt_sigreturn       173
 
index da1f06b535e38a97bbd981ade5c414d1131ef4e8..8893cebcea5b8d903fed25db1a6dcb6effa14cef 100644 (file)
@@ -787,8 +787,11 @@ __SYSCALL(__NR_sched_setattr, sys_sched_setattr)
 __SYSCALL(__NR_sched_getattr, sys_sched_getattr)
 #define __NR_renameat2 382
 __SYSCALL(__NR_renameat2, sys_renameat2)
-                       /* 383 for seccomp */
+#define __NR_seccomp 383
+__SYSCALL(__NR_seccomp, sys_seccomp)
 #define __NR_getrandom 384
 __SYSCALL(__NR_getrandom, sys_getrandom)
 #define __NR_memfd_create 385
 __SYSCALL(__NR_memfd_create, sys_memfd_create)
+#define __NR_bpf 386
+__SYSCALL(__NR_bpf, sys_bpf)
index 5bd029b436444f79719f714a9af92ffe27a911d5..eaa77ed7766a3bde911e370404098f11626fe39a 100644 (file)
@@ -5,6 +5,7 @@
 CPPFLAGS_vmlinux.lds   := -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o          := -DTEXT_OFFSET=$(TEXT_OFFSET)
 CFLAGS_efi-stub.o      := -DTEXT_OFFSET=$(TEXT_OFFSET)
+CFLAGS_armv8_deprecated.o := -I$(src)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
@@ -15,10 +16,11 @@ arm64-obj-y         := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
                           entry-fpsimd.o process.o ptrace.o setup.o signal.o   \
                           sys.o stacktrace.o time.o traps.o io.o vdso.o        \
                           hyp-stub.o psci.o cpu_ops.o insn.o return_address.o  \
-                          cpuinfo.o
+                          cpuinfo.o cpu_errata.o alternative.o
 
 arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o         \
-                                          sys_compat.o
+                                          sys_compat.o                         \
+                                          ../../arm/kernel/opcodes.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)                        += smp.o smp_spin_table.o topology.o
@@ -31,6 +33,7 @@ arm64-obj-$(CONFIG_JUMP_LABEL)                += jump_label.o
 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
 
 obj-y                                  += $(arm64-obj-y) vdso/
 obj-m                                  += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
new file mode 100644 (file)
index 0000000..ad7821d
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * alternative runtime patching
+ * inspired by the x86 version
+ *
+ * Copyright (C) 2014 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/>.
+ */
+
+#define pr_fmt(fmt) "alternatives: " fmt
+
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <asm/cacheflush.h>
+#include <asm/alternative.h>
+#include <asm/cpufeature.h>
+#include <linux/stop_machine.h>
+
+extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+
+struct alt_region {
+       struct alt_instr *begin;
+       struct alt_instr *end;
+};
+
+static int __apply_alternatives(void *alt_region)
+{
+       struct alt_instr *alt;
+       struct alt_region *region = alt_region;
+       u8 *origptr, *replptr;
+
+       for (alt = region->begin; alt < region->end; alt++) {
+               if (!cpus_have_cap(alt->cpufeature))
+                       continue;
+
+               BUG_ON(alt->alt_len > alt->orig_len);
+
+               pr_info_once("patching kernel code\n");
+
+               origptr = (u8 *)&alt->orig_offset + alt->orig_offset;
+               replptr = (u8 *)&alt->alt_offset + alt->alt_offset;
+               memcpy(origptr, replptr, alt->alt_len);
+               flush_icache_range((uintptr_t)origptr,
+                                  (uintptr_t)(origptr + alt->alt_len));
+       }
+
+       return 0;
+}
+
+void apply_alternatives_all(void)
+{
+       struct alt_region region = {
+               .begin  = __alt_instructions,
+               .end    = __alt_instructions_end,
+       };
+
+       /* better not try code patching on a live SMP system */
+       stop_machine(__apply_alternatives, &region, NULL);
+}
+
+void apply_alternatives(void *start, size_t length)
+{
+       struct alt_region region = {
+               .begin  = start,
+               .end    = start + length,
+       };
+
+       __apply_alternatives(&region);
+}
+
+void free_alternatives_memory(void)
+{
+       free_reserved_area(__alt_instructions, __alt_instructions_end,
+                          0, "alternatives");
+}
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
new file mode 100644 (file)
index 0000000..c363671
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ *  Copyright (C) 2014 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/perf_event.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+
+#include <asm/insn.h>
+#include <asm/opcodes.h>
+#include <asm/system_misc.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+
+#define CREATE_TRACE_POINTS
+#include "trace-events-emulation.h"
+
+/*
+ * The runtime support for deprecated instruction support can be in one of
+ * following three states -
+ *
+ * 0 = undef
+ * 1 = emulate (software emulation)
+ * 2 = hw (supported in hardware)
+ */
+enum insn_emulation_mode {
+       INSN_UNDEF,
+       INSN_EMULATE,
+       INSN_HW,
+};
+
+enum legacy_insn_status {
+       INSN_DEPRECATED,
+       INSN_OBSOLETE,
+};
+
+struct insn_emulation_ops {
+       const char              *name;
+       enum legacy_insn_status status;
+       struct undef_hook       *hooks;
+       int                     (*set_hw_mode)(bool enable);
+};
+
+struct insn_emulation {
+       struct list_head node;
+       struct insn_emulation_ops *ops;
+       int current_mode;
+       int min;
+       int max;
+};
+
+static LIST_HEAD(insn_emulation);
+static int nr_insn_emulated;
+static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
+
+static void register_emulation_hooks(struct insn_emulation_ops *ops)
+{
+       struct undef_hook *hook;
+
+       BUG_ON(!ops->hooks);
+
+       for (hook = ops->hooks; hook->instr_mask; hook++)
+               register_undef_hook(hook);
+
+       pr_notice("Registered %s emulation handler\n", ops->name);
+}
+
+static void remove_emulation_hooks(struct insn_emulation_ops *ops)
+{
+       struct undef_hook *hook;
+
+       BUG_ON(!ops->hooks);
+
+       for (hook = ops->hooks; hook->instr_mask; hook++)
+               unregister_undef_hook(hook);
+
+       pr_notice("Removed %s emulation handler\n", ops->name);
+}
+
+static int update_insn_emulation_mode(struct insn_emulation *insn,
+                                      enum insn_emulation_mode prev)
+{
+       int ret = 0;
+
+       switch (prev) {
+       case INSN_UNDEF: /* Nothing to be done */
+               break;
+       case INSN_EMULATE:
+               remove_emulation_hooks(insn->ops);
+               break;
+       case INSN_HW:
+               if (insn->ops->set_hw_mode) {
+                       insn->ops->set_hw_mode(false);
+                       pr_notice("Disabled %s support\n", insn->ops->name);
+               }
+               break;
+       }
+
+       switch (insn->current_mode) {
+       case INSN_UNDEF:
+               break;
+       case INSN_EMULATE:
+               register_emulation_hooks(insn->ops);
+               break;
+       case INSN_HW:
+               if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(true))
+                       pr_notice("Enabled %s support\n", insn->ops->name);
+               else
+                       ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static void register_insn_emulation(struct insn_emulation_ops *ops)
+{
+       unsigned long flags;
+       struct insn_emulation *insn;
+
+       insn = kzalloc(sizeof(*insn), GFP_KERNEL);
+       insn->ops = ops;
+       insn->min = INSN_UNDEF;
+
+       switch (ops->status) {
+       case INSN_DEPRECATED:
+               insn->current_mode = INSN_EMULATE;
+               insn->max = INSN_HW;
+               break;
+       case INSN_OBSOLETE:
+               insn->current_mode = INSN_UNDEF;
+               insn->max = INSN_EMULATE;
+               break;
+       }
+
+       raw_spin_lock_irqsave(&insn_emulation_lock, flags);
+       list_add(&insn->node, &insn_emulation);
+       nr_insn_emulated++;
+       raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
+
+       /* Register any handlers if required */
+       update_insn_emulation_mode(insn, INSN_UNDEF);
+}
+
+static int emulation_proc_handler(struct ctl_table *table, int write,
+                                 void __user *buffer, size_t *lenp,
+                                 loff_t *ppos)
+{
+       int ret = 0;
+       struct insn_emulation *insn = (struct insn_emulation *) table->data;
+       enum insn_emulation_mode prev_mode = insn->current_mode;
+
+       table->data = &insn->current_mode;
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+       if (ret || !write || prev_mode == insn->current_mode)
+               goto ret;
+
+       ret = update_insn_emulation_mode(insn, prev_mode);
+       if (ret) {
+               /* Mode change failed, revert to previous mode. */
+               insn->current_mode = prev_mode;
+               update_insn_emulation_mode(insn, INSN_UNDEF);
+       }
+ret:
+       table->data = insn;
+       return ret;
+}
+
+static struct ctl_table ctl_abi[] = {
+       {
+               .procname = "abi",
+               .mode = 0555,
+       },
+       { }
+};
+
+static void register_insn_emulation_sysctl(struct ctl_table *table)
+{
+       unsigned long flags;
+       int i = 0;
+       struct insn_emulation *insn;
+       struct ctl_table *insns_sysctl, *sysctl;
+
+       insns_sysctl = kzalloc(sizeof(*sysctl) * (nr_insn_emulated + 1),
+                             GFP_KERNEL);
+
+       raw_spin_lock_irqsave(&insn_emulation_lock, flags);
+       list_for_each_entry(insn, &insn_emulation, node) {
+               sysctl = &insns_sysctl[i];
+
+               sysctl->mode = 0644;
+               sysctl->maxlen = sizeof(int);
+
+               sysctl->procname = insn->ops->name;
+               sysctl->data = insn;
+               sysctl->extra1 = &insn->min;
+               sysctl->extra2 = &insn->max;
+               sysctl->proc_handler = emulation_proc_handler;
+               i++;
+       }
+       raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
+
+       table->child = insns_sysctl;
+       register_sysctl_table(table);
+}
+
+/*
+ *  Implement emulation of the SWP/SWPB instructions using load-exclusive and
+ *  store-exclusive.
+ *
+ *  Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>]
+ *  Where: Rt  = destination
+ *        Rt2 = source
+ *        Rn  = address
+ */
+
+/*
+ * Error-checking SWP macros implemented using ldxr{b}/stxr{b}
+ */
+#define __user_swpX_asm(data, addr, res, temp, B)              \
+       __asm__ __volatile__(                                   \
+       "       mov             %w2, %w1\n"                     \
+       "0:     ldxr"B"         %w1, [%3]\n"                    \
+       "1:     stxr"B"         %w0, %w2, [%3]\n"               \
+       "       cbz             %w0, 2f\n"                      \
+       "       mov             %w0, %w4\n"                     \
+       "2:\n"                                                  \
+       "       .pushsection     .fixup,\"ax\"\n"               \
+       "       .align          2\n"                            \
+       "3:     mov             %w0, %w5\n"                     \
+       "       b               2b\n"                           \
+       "       .popsection"                                    \
+       "       .pushsection     __ex_table,\"a\"\n"            \
+       "       .align          3\n"                            \
+       "       .quad           0b, 3b\n"                       \
+       "       .quad           1b, 3b\n"                       \
+       "       .popsection"                                    \
+       : "=&r" (res), "+r" (data), "=&r" (temp)                \
+       : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)              \
+       : "memory")
+
+#define __user_swp_asm(data, addr, res, temp) \
+       __user_swpX_asm(data, addr, res, temp, "")
+#define __user_swpb_asm(data, addr, res, temp) \
+       __user_swpX_asm(data, addr, res, temp, "b")
+
+/*
+ * Bit 22 of the instruction encoding distinguishes between
+ * the SWP and SWPB variants (bit set means SWPB).
+ */
+#define TYPE_SWPB (1 << 22)
+
+/*
+ * Set up process info to signal segmentation fault - called on access error.
+ */
+static void set_segfault(struct pt_regs *regs, unsigned long addr)
+{
+       siginfo_t info;
+
+       down_read(&current->mm->mmap_sem);
+       if (find_vma(current->mm, addr) == NULL)
+               info.si_code = SEGV_MAPERR;
+       else
+               info.si_code = SEGV_ACCERR;
+       up_read(&current->mm->mmap_sem);
+
+       info.si_signo = SIGSEGV;
+       info.si_errno = 0;
+       info.si_addr  = (void *) instruction_pointer(regs);
+
+       pr_debug("SWP{B} emulation: access caused memory abort!\n");
+       arm64_notify_die("Illegal memory access", regs, &info, 0);
+}
+
+static int emulate_swpX(unsigned int address, unsigned int *data,
+                       unsigned int type)
+{
+       unsigned int res = 0;
+
+       if ((type != TYPE_SWPB) && (address & 0x3)) {
+               /* SWP to unaligned address not permitted */
+               pr_debug("SWP instruction on unaligned pointer!\n");
+               return -EFAULT;
+       }
+
+       while (1) {
+               unsigned long temp;
+
+               if (type == TYPE_SWPB)
+                       __user_swpb_asm(*data, address, res, temp);
+               else
+                       __user_swp_asm(*data, address, res, temp);
+
+               if (likely(res != -EAGAIN) || signal_pending(current))
+                       break;
+
+               cond_resched();
+       }
+
+       return res;
+}
+
+/*
+ * swp_handler logs the id of calling process, dissects the instruction, sanity
+ * checks the memory location, calls emulate_swpX for the actual operation and
+ * deals with fixup/error handling before returning
+ */
+static int swp_handler(struct pt_regs *regs, u32 instr)
+{
+       u32 destreg, data, type, address = 0;
+       int rn, rt2, res = 0;
+
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
+
+       type = instr & TYPE_SWPB;
+
+       switch (arm_check_condition(instr, regs->pstate)) {
+       case ARM_OPCODE_CONDTEST_PASS:
+               break;
+       case ARM_OPCODE_CONDTEST_FAIL:
+               /* Condition failed - return to next instruction */
+               goto ret;
+       case ARM_OPCODE_CONDTEST_UNCOND:
+               /* If unconditional encoding - not a SWP, undef */
+               return -EFAULT;
+       default:
+               return -EINVAL;
+       }
+
+       rn = aarch32_insn_extract_reg_num(instr, A32_RN_OFFSET);
+       rt2 = aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET);
+
+       address = (u32)regs->user_regs.regs[rn];
+       data    = (u32)regs->user_regs.regs[rt2];
+       destreg = aarch32_insn_extract_reg_num(instr, A32_RT_OFFSET);
+
+       pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
+               rn, address, destreg,
+               aarch32_insn_extract_reg_num(instr, A32_RT2_OFFSET), data);
+
+       /* Check access in reasonable access range for both SWP and SWPB */
+       if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) {
+               pr_debug("SWP{B} emulation: access to 0x%08x not allowed!\n",
+                       address);
+               goto fault;
+       }
+
+       res = emulate_swpX(address, &data, type);
+       if (res == -EFAULT)
+               goto fault;
+       else if (res == 0)
+               regs->user_regs.regs[destreg] = data;
+
+ret:
+       if (type == TYPE_SWPB)
+               trace_instruction_emulation("swpb", regs->pc);
+       else
+               trace_instruction_emulation("swp", regs->pc);
+
+       pr_warn_ratelimited("\"%s\" (%ld) uses obsolete SWP{B} instruction at 0x%llx\n",
+                       current->comm, (unsigned long)current->pid, regs->pc);
+
+       regs->pc += 4;
+       return 0;
+
+fault:
+       set_segfault(regs, address);
+
+       return 0;
+}
+
+/*
+ * Only emulate SWP/SWPB executed in ARM state/User mode.
+ * The kernel must be SWP free and SWP{B} does not exist in Thumb.
+ */
+static struct undef_hook swp_hooks[] = {
+       {
+               .instr_mask     = 0x0fb00ff0,
+               .instr_val      = 0x01000090,
+               .pstate_mask    = COMPAT_PSR_MODE_MASK,
+               .pstate_val     = COMPAT_PSR_MODE_USR,
+               .fn             = swp_handler
+       },
+       { }
+};
+
+static struct insn_emulation_ops swp_ops = {
+       .name = "swp",
+       .status = INSN_OBSOLETE,
+       .hooks = swp_hooks,
+       .set_hw_mode = NULL,
+};
+
+static int cp15barrier_handler(struct pt_regs *regs, u32 instr)
+{
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
+
+       switch (arm_check_condition(instr, regs->pstate)) {
+       case ARM_OPCODE_CONDTEST_PASS:
+               break;
+       case ARM_OPCODE_CONDTEST_FAIL:
+               /* Condition failed - return to next instruction */
+               goto ret;
+       case ARM_OPCODE_CONDTEST_UNCOND:
+               /* If unconditional encoding - not a barrier instruction */
+               return -EFAULT;
+       default:
+               return -EINVAL;
+       }
+
+       switch (aarch32_insn_mcr_extract_crm(instr)) {
+       case 10:
+               /*
+                * dmb - mcr p15, 0, Rt, c7, c10, 5
+                * dsb - mcr p15, 0, Rt, c7, c10, 4
+                */
+               if (aarch32_insn_mcr_extract_opc2(instr) == 5) {
+                       dmb(sy);
+                       trace_instruction_emulation(
+                               "mcr p15, 0, Rt, c7, c10, 5 ; dmb", regs->pc);
+               } else {
+                       dsb(sy);
+                       trace_instruction_emulation(
+                               "mcr p15, 0, Rt, c7, c10, 4 ; dsb", regs->pc);
+               }
+               break;
+       case 5:
+               /*
+                * isb - mcr p15, 0, Rt, c7, c5, 4
+                *
+                * Taking an exception or returning from one acts as an
+                * instruction barrier. So no explicit barrier needed here.
+                */
+               trace_instruction_emulation(
+                       "mcr p15, 0, Rt, c7, c5, 4 ; isb", regs->pc);
+               break;
+       }
+
+ret:
+       pr_warn_ratelimited("\"%s\" (%ld) uses deprecated CP15 Barrier instruction at 0x%llx\n",
+                       current->comm, (unsigned long)current->pid, regs->pc);
+
+       regs->pc += 4;
+       return 0;
+}
+
+#define SCTLR_EL1_CP15BEN (1 << 5)
+
+static inline void config_sctlr_el1(u32 clear, u32 set)
+{
+       u32 val;
+
+       asm volatile("mrs %0, sctlr_el1" : "=r" (val));
+       val &= ~clear;
+       val |= set;
+       asm volatile("msr sctlr_el1, %0" : : "r" (val));
+}
+
+static void enable_cp15_ben(void *info)
+{
+       config_sctlr_el1(0, SCTLR_EL1_CP15BEN);
+}
+
+static void disable_cp15_ben(void *info)
+{
+       config_sctlr_el1(SCTLR_EL1_CP15BEN, 0);
+}
+
+static int cpu_hotplug_notify(struct notifier_block *b,
+                             unsigned long action, void *hcpu)
+{
+       switch (action) {
+       case CPU_STARTING:
+       case CPU_STARTING_FROZEN:
+               enable_cp15_ben(NULL);
+               return NOTIFY_DONE;
+       case CPU_DYING:
+       case CPU_DYING_FROZEN:
+               disable_cp15_ben(NULL);
+               return NOTIFY_DONE;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block cpu_hotplug_notifier = {
+       .notifier_call = cpu_hotplug_notify,
+};
+
+static int cp15_barrier_set_hw_mode(bool enable)
+{
+       if (enable) {
+               register_cpu_notifier(&cpu_hotplug_notifier);
+               on_each_cpu(enable_cp15_ben, NULL, true);
+       } else {
+               unregister_cpu_notifier(&cpu_hotplug_notifier);
+               on_each_cpu(disable_cp15_ben, NULL, true);
+       }
+
+       return true;
+}
+
+static struct undef_hook cp15_barrier_hooks[] = {
+       {
+               .instr_mask     = 0x0fff0fdf,
+               .instr_val      = 0x0e070f9a,
+               .pstate_mask    = COMPAT_PSR_MODE_MASK,
+               .pstate_val     = COMPAT_PSR_MODE_USR,
+               .fn             = cp15barrier_handler,
+       },
+       {
+               .instr_mask     = 0x0fff0fff,
+               .instr_val      = 0x0e070f95,
+               .pstate_mask    = COMPAT_PSR_MODE_MASK,
+               .pstate_val     = COMPAT_PSR_MODE_USR,
+               .fn             = cp15barrier_handler,
+       },
+       { }
+};
+
+static struct insn_emulation_ops cp15_barrier_ops = {
+       .name = "cp15_barrier",
+       .status = INSN_DEPRECATED,
+       .hooks = cp15_barrier_hooks,
+       .set_hw_mode = cp15_barrier_set_hw_mode,
+};
+
+/*
+ * Invoked as late_initcall, since not needed before init spawned.
+ */
+static int __init armv8_deprecated_init(void)
+{
+       if (IS_ENABLED(CONFIG_SWP_EMULATION))
+               register_insn_emulation(&swp_ops);
+
+       if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION))
+               register_insn_emulation(&cp15_barrier_ops);
+
+       register_insn_emulation_sysctl(ctl_abi);
+
+       return 0;
+}
+
+late_initcall(armv8_deprecated_init);
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
new file mode 100644 (file)
index 0000000..fa62637
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Contains CPU specific errata definitions
+ *
+ * Copyright (C) 2014 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/>.
+ */
+
+#define pr_fmt(fmt) "alternatives: " fmt
+
+#include <linux/types.h>
+#include <asm/cpu.h>
+#include <asm/cputype.h>
+#include <asm/cpufeature.h>
+
+#define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
+#define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
+
+/*
+ * Add a struct or another datatype to the union below if you need
+ * different means to detect an affected CPU.
+ */
+struct arm64_cpu_capabilities {
+       const char *desc;
+       u16 capability;
+       bool (*is_affected)(struct arm64_cpu_capabilities *);
+       union {
+               struct {
+                       u32 midr_model;
+                       u32 midr_range_min, midr_range_max;
+               };
+       };
+};
+
+#define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
+                       MIDR_ARCHITECTURE_MASK)
+
+static bool __maybe_unused
+is_affected_midr_range(struct arm64_cpu_capabilities *entry)
+{
+       u32 midr = read_cpuid_id();
+
+       if ((midr & CPU_MODEL_MASK) != entry->midr_model)
+               return false;
+
+       midr &= MIDR_REVISION_MASK | MIDR_VARIANT_MASK;
+
+       return (midr >= entry->midr_range_min && midr <= entry->midr_range_max);
+}
+
+#define MIDR_RANGE(model, min, max) \
+       .is_affected = is_affected_midr_range, \
+       .midr_model = model, \
+       .midr_range_min = min, \
+       .midr_range_max = max
+
+struct arm64_cpu_capabilities arm64_errata[] = {
+#if    defined(CONFIG_ARM64_ERRATUM_826319) || \
+       defined(CONFIG_ARM64_ERRATUM_827319) || \
+       defined(CONFIG_ARM64_ERRATUM_824069)
+       {
+       /* Cortex-A53 r0p[012] */
+               .desc = "ARM errata 826319, 827319, 824069",
+               .capability = ARM64_WORKAROUND_CLEAN_CACHE,
+               MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
+       },
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_819472
+       {
+       /* Cortex-A53 r0p[01] */
+               .desc = "ARM errata 819472",
+               .capability = ARM64_WORKAROUND_CLEAN_CACHE,
+               MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
+       },
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_832075
+       {
+       /* Cortex-A57 r0p0 - r1p2 */
+               .desc = "ARM erratum 832075",
+               .capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
+               MIDR_RANGE(MIDR_CORTEX_A57, 0x00, 0x12),
+       },
+#endif
+       {
+       }
+};
+
+void check_local_cpu_errata(void)
+{
+       struct arm64_cpu_capabilities *cpus = arm64_errata;
+       int i;
+
+       for (i = 0; cpus[i].desc; i++) {
+               if (!cpus[i].is_affected(&cpus[i]))
+                       continue;
+
+               if (!cpus_have_cap(cpus[i].capability))
+                       pr_info("enabling workaround for %s\n", cpus[i].desc);
+               cpus_set_cap(cpus[i].capability);
+       }
+}
index 504fdaa8367e49c8ca1ff3178ebdf83ecb8d4f2b..57b641747534a4bb7a8e0901b685d092b89fbfdc 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/cachetype.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
+#include <asm/cpufeature.h>
 
 #include <linux/bitops.h>
 #include <linux/bug.h>
@@ -110,6 +111,15 @@ static void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur)
        /* If different, timekeeping will be broken (especially with KVM) */
        diff |= CHECK(cntfrq, boot, cur, cpu);
 
+       /*
+        * The kernel uses self-hosted debug features and expects CPUs to
+        * support identical debug features. We presently need CTX_CMPs, WRPs,
+        * and BRPs to be identical.
+        * ID_AA64DFR1 is currently RES0.
+        */
+       diff |= CHECK(id_aa64dfr0, boot, cur, cpu);
+       diff |= CHECK(id_aa64dfr1, boot, cur, cpu);
+
        /*
         * Even in big.LITTLE, processors should be identical instruction-set
         * wise.
@@ -143,7 +153,12 @@ static void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur)
        diff |= CHECK(id_isar3, boot, cur, cpu);
        diff |= CHECK(id_isar4, boot, cur, cpu);
        diff |= CHECK(id_isar5, boot, cur, cpu);
-       diff |= CHECK(id_mmfr0, boot, cur, cpu);
+       /*
+        * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and
+        * ACTLR formats could differ across CPUs and therefore would have to
+        * be trapped for virtualization anyway.
+        */
+       diff |= CHECK_MASK(id_mmfr0, 0xff0fffff, boot, cur, cpu);
        diff |= CHECK(id_mmfr1, boot, cur, cpu);
        diff |= CHECK(id_mmfr2, boot, cur, cpu);
        diff |= CHECK(id_mmfr3, boot, cur, cpu);
@@ -155,7 +170,7 @@ static void cpuinfo_sanity_check(struct cpuinfo_arm64 *cur)
         * pretend to support them.
         */
        WARN_TAINT_ONCE(diff, TAINT_CPU_OUT_OF_SPEC,
-                       "Unsupported CPU feature variation.");
+                       "Unsupported CPU feature variation.\n");
 }
 
 static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
@@ -165,6 +180,8 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
        info->reg_dczid = read_cpuid(DCZID_EL0);
        info->reg_midr = read_cpuid_id();
 
+       info->reg_id_aa64dfr0 = read_cpuid(ID_AA64DFR0_EL1);
+       info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1);
        info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
        info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
        info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
@@ -186,6 +203,8 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
        info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
 
        cpuinfo_detect_icache_policy(info);
+
+       check_local_cpu_errata();
 }
 
 void cpuinfo_store_cpu(void)
index 619b1dd7bcdea70e184daacbfb5dd7797c8460c0..8ce9b0577442395df912ca934f0fca338948b4a8 100644 (file)
@@ -54,18 +54,18 @@ ENTRY(efi_stub_entry)
        b.eq    efi_load_fail
 
        /*
-        * efi_entry() will have relocated the kernel image if necessary
-        * and we return here with device tree address in x0 and the kernel
-        * entry point stored at *image_addr. Save those values in registers
-        * which are callee preserved.
+        * efi_entry() will have copied the kernel image if necessary and we
+        * return here with device tree address in x0 and the kernel entry
+        * point stored at *image_addr. Save those values in registers which
+        * are callee preserved.
         */
        mov     x20, x0         // DTB address
        ldr     x0, [sp, #16]   // relocated _text address
-       mov     x21, x0
+       ldr     x21, =stext_offset
+       add     x21, x0, x21
 
        /*
-        * Flush dcache covering current runtime addresses
-        * of kernel text/data. Then flush all of icache.
+        * Calculate size of the kernel Image (same for original and copy).
         */
        adrp    x1, _text
        add     x1, x1, #:lo12:_text
@@ -73,9 +73,24 @@ ENTRY(efi_stub_entry)
        add     x2, x2, #:lo12:_edata
        sub     x1, x2, x1
 
+       /*
+        * Flush the copied Image to the PoC, and ensure it is not shadowed by
+        * stale icache entries from before relocation.
+        */
        bl      __flush_dcache_area
        ic      ialluis
 
+       /*
+        * Ensure that the rest of this function (in the original Image) is
+        * visible when the caches are disabled. The I-cache can't have stale
+        * entries for the VA range of the current image, so no maintenance is
+        * necessary.
+        */
+       adr     x0, efi_stub_entry
+       adr     x1, efi_stub_entry_end
+       sub     x1, x1, x0
+       bl      __flush_dcache_area
+
        /* Turn off Dcache and MMU */
        mrs     x0, CurrentEL
        cmp     x0, #CurrentEL_EL2
@@ -105,4 +120,5 @@ efi_load_fail:
        ldp     x29, x30, [sp], #32
        ret
 
+efi_stub_entry_end:
 ENDPROC(efi_stub_entry)
index 03aaa99e1ea00a3d4caf79d27cea669d857a9090..6fac253bc783a44066630643c0b57153825d0be9 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/dmi.h>
 #include <linux/efi.h>
 #include <linux/export.h>
 #include <linux/memblock.h>
@@ -89,7 +90,8 @@ static int __init uefi_init(void)
         */
        if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
                pr_err("System table signature incorrect\n");
-               return -EINVAL;
+               retval = -EINVAL;
+               goto out;
        }
        if ((efi.systab->hdr.revision >> 16) < 2)
                pr_warn("Warning: EFI system table version %d.%02d, expected 2.00 or greater\n",
@@ -103,6 +105,7 @@ static int __init uefi_init(void)
                for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
                        vendor[i] = c16[i];
                vendor[i] = '\0';
+               early_memunmap(c16, sizeof(vendor));
        }
 
        pr_info("EFI v%u.%.02u by %s\n",
@@ -110,48 +113,28 @@ static int __init uefi_init(void)
                efi.systab->hdr.revision & 0xffff, vendor);
 
        retval = efi_config_init(NULL);
-       if (retval == 0)
-               set_bit(EFI_CONFIG_TABLES, &efi.flags);
 
-       early_memunmap(c16, sizeof(vendor));
+out:
        early_memunmap(efi.systab,  sizeof(efi_system_table_t));
-
        return retval;
 }
 
-static __initdata char memory_type_name[][32] = {
-       {"Reserved"},
-       {"Loader Code"},
-       {"Loader Data"},
-       {"Boot Code"},
-       {"Boot Data"},
-       {"Runtime Code"},
-       {"Runtime Data"},
-       {"Conventional Memory"},
-       {"Unusable Memory"},
-       {"ACPI Reclaim Memory"},
-       {"ACPI Memory NVS"},
-       {"Memory Mapped I/O"},
-       {"MMIO Port Space"},
-       {"PAL Code"},
-};
-
 /*
  * Return true for RAM regions we want to permanently reserve.
  */
 static __init int is_reserve_region(efi_memory_desc_t *md)
 {
-       if (!is_normal_ram(md))
+       switch (md->type) {
+       case EFI_LOADER_CODE:
+       case EFI_LOADER_DATA:
+       case EFI_BOOT_SERVICES_CODE:
+       case EFI_BOOT_SERVICES_DATA:
+       case EFI_CONVENTIONAL_MEMORY:
                return 0;
-
-       if (md->attribute & EFI_MEMORY_RUNTIME)
-               return 1;
-
-       if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
-           md->type == EFI_RESERVED_TYPE)
-               return 1;
-
-       return 0;
+       default:
+               break;
+       }
+       return is_normal_ram(md);
 }
 
 static __init void reserve_regions(void)
@@ -166,10 +149,13 @@ static __init void reserve_regions(void)
                paddr = md->phys_addr;
                npages = md->num_pages;
 
-               if (uefi_debug)
-                       pr_info("  0x%012llx-0x%012llx [%s]",
+               if (uefi_debug) {
+                       char buf[64];
+
+                       pr_info("  0x%012llx-0x%012llx %s",
                                paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-                               memory_type_name[md->type]);
+                               efi_md_typeattr_format(buf, sizeof(buf), md));
+               }
 
                memrange_efi_to_native(&paddr, &npages);
                size = npages << PAGE_SHIFT;
@@ -393,11 +379,16 @@ static int __init arm64_enter_virtual_mode(void)
                return -1;
        }
 
-       pr_info("Remapping and enabling EFI services.\n");
-
-       /* replace early memmap mapping with permanent mapping */
        mapsize = memmap.map_end - memmap.map;
        early_memunmap(memmap.map, mapsize);
+
+       if (efi_runtime_disabled()) {
+               pr_info("EFI runtime services will be disabled.\n");
+               return -1;
+       }
+
+       pr_info("Remapping and enabling EFI services.\n");
+       /* replace early memmap mapping with permanent mapping */
        memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
                                                   mapsize);
        memmap.map_end = memmap.map + mapsize;
@@ -479,3 +470,17 @@ err_unmap:
        return -1;
 }
 early_initcall(arm64_enter_virtual_mode);
+
+static int __init arm64_dmi_init(void)
+{
+       /*
+        * On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to
+        * be called early because dmi_id_init(), which is an arch_initcall
+        * itself, depends on dmi_scan_machine() having been called already.
+        */
+       dmi_scan_machine();
+       if (dmi_available)
+               dmi_set_dump_stack_arch_desc();
+       return 0;
+}
+core_initcall(arm64_dmi_init);
index 38e704e597f71bc25e677849162716a307640921..08cafc518b9a57ad724530b9dbb144d50683c13f 100644 (file)
@@ -98,8 +98,8 @@
 ENTRY(_mcount)
        mcount_enter
 
-       ldr     x0, =ftrace_trace_function
-       ldr     x2, [x0]
+       adrp    x0, ftrace_trace_function
+       ldr     x2, [x0, #:lo12:ftrace_trace_function]
        adr     x0, ftrace_stub
        cmp     x0, x2                  // if (ftrace_trace_function
        b.eq    skip_ftrace_call        //     != ftrace_stub) {
@@ -115,14 +115,15 @@ skip_ftrace_call:                 //   return;
        mcount_exit                     //   return;
                                        // }
 skip_ftrace_call:
-       ldr     x1, =ftrace_graph_return
-       ldr     x2, [x1]                //   if ((ftrace_graph_return
-       cmp     x0, x2                  //        != ftrace_stub)
-       b.ne    ftrace_graph_caller
-
-       ldr     x1, =ftrace_graph_entry //     || (ftrace_graph_entry
-       ldr     x2, [x1]                //        != ftrace_graph_entry_stub))
-       ldr     x0, =ftrace_graph_entry_stub
+       adrp    x1, ftrace_graph_return
+       ldr     x2, [x1, #:lo12:ftrace_graph_return]
+       cmp     x0, x2                  //   if ((ftrace_graph_return
+       b.ne    ftrace_graph_caller     //        != ftrace_stub)
+
+       adrp    x1, ftrace_graph_entry  //     || (ftrace_graph_entry
+       adrp    x0, ftrace_graph_entry_stub //     != ftrace_graph_entry_stub))
+       ldr     x2, [x1, #:lo12:ftrace_graph_entry]
+       add     x0, x0, #:lo12:ftrace_graph_entry_stub
        cmp     x0, x2
        b.ne    ftrace_graph_caller     //     ftrace_graph_caller();
 
index 726b910fe6ec1a4516e216a35031eb1d99d31664..fd4fa374e5d2b276821e324eb6066f86bdb514c7 100644 (file)
 #define BAD_ERROR      3
 
        .macro  kernel_entry, el, regsize = 64
-       sub     sp, sp, #S_FRAME_SIZE - S_LR    // room for LR, SP, SPSR, ELR
+       sub     sp, sp, #S_FRAME_SIZE
        .if     \regsize == 32
        mov     w0, w0                          // zero upper 32 bits of x0
        .endif
-       push    x28, x29
-       push    x26, x27
-       push    x24, x25
-       push    x22, x23
-       push    x20, x21
-       push    x18, x19
-       push    x16, x17
-       push    x14, x15
-       push    x12, x13
-       push    x10, x11
-       push    x8, x9
-       push    x6, x7
-       push    x4, x5
-       push    x2, x3
-       push    x0, x1
+       stp     x0, x1, [sp, #16 * 0]
+       stp     x2, x3, [sp, #16 * 1]
+       stp     x4, x5, [sp, #16 * 2]
+       stp     x6, x7, [sp, #16 * 3]
+       stp     x8, x9, [sp, #16 * 4]
+       stp     x10, x11, [sp, #16 * 5]
+       stp     x12, x13, [sp, #16 * 6]
+       stp     x14, x15, [sp, #16 * 7]
+       stp     x16, x17, [sp, #16 * 8]
+       stp     x18, x19, [sp, #16 * 9]
+       stp     x20, x21, [sp, #16 * 10]
+       stp     x22, x23, [sp, #16 * 11]
+       stp     x24, x25, [sp, #16 * 12]
+       stp     x26, x27, [sp, #16 * 13]
+       stp     x28, x29, [sp, #16 * 14]
+
        .if     \el == 0
        mrs     x21, sp_el0
        get_thread_info tsk                     // Ensure MDSCR_EL1.SS is clear,
        .if     \el == 0
        ct_user_enter
        ldr     x23, [sp, #S_SP]                // load return stack pointer
+       msr     sp_el0, x23
        .endif
+       msr     elr_el1, x21                    // set up the return data
+       msr     spsr_el1, x22
        .if     \ret
        ldr     x1, [sp, #S_X1]                 // preserve x0 (syscall return)
-       add     sp, sp, S_X2
        .else
-       pop     x0, x1
+       ldp     x0, x1, [sp, #16 * 0]
        .endif
-       pop     x2, x3                          // load the rest of the registers
-       pop     x4, x5
-       pop     x6, x7
-       pop     x8, x9
-       msr     elr_el1, x21                    // set up the return data
-       msr     spsr_el1, x22
-       .if     \el == 0
-       msr     sp_el0, x23
-       .endif
-       pop     x10, x11
-       pop     x12, x13
-       pop     x14, x15
-       pop     x16, x17
-       pop     x18, x19
-       pop     x20, x21
-       pop     x22, x23
-       pop     x24, x25
-       pop     x26, x27
-       pop     x28, x29
-       ldr     lr, [sp], #S_FRAME_SIZE - S_LR  // load LR and restore SP
+       ldp     x2, x3, [sp, #16 * 1]
+       ldp     x4, x5, [sp, #16 * 2]
+       ldp     x6, x7, [sp, #16 * 3]
+       ldp     x8, x9, [sp, #16 * 4]
+       ldp     x10, x11, [sp, #16 * 5]
+       ldp     x12, x13, [sp, #16 * 6]
+       ldp     x14, x15, [sp, #16 * 7]
+       ldp     x16, x17, [sp, #16 * 8]
+       ldp     x18, x19, [sp, #16 * 9]
+       ldp     x20, x21, [sp, #16 * 10]
+       ldp     x22, x23, [sp, #16 * 11]
+       ldp     x24, x25, [sp, #16 * 12]
+       ldp     x26, x27, [sp, #16 * 13]
+       ldp     x28, x29, [sp, #16 * 14]
+       ldr     lr, [sp, #S_LR]
+       add     sp, sp, #S_FRAME_SIZE           // restore sp
        eret                                    // return to kernel
        .endm
 
@@ -168,7 +167,8 @@ tsk .req    x28             // current thread_info
  * Interrupt handling.
  */
        .macro  irq_handler
-       ldr     x1, handle_arch_irq
+       adrp    x1, handle_arch_irq
+       ldr     x1, [x1, #:lo12:handle_arch_irq]
        mov     x0, sp
        blr     x1
        .endm
@@ -455,8 +455,8 @@ el0_da:
        bic     x0, x26, #(0xff << 56)
        mov     x1, x25
        mov     x2, sp
-       adr     lr, ret_to_user
-       b       do_mem_abort
+       bl      do_mem_abort
+       b       ret_to_user
 el0_ia:
        /*
         * Instruction abort handling
@@ -468,8 +468,8 @@ el0_ia:
        mov     x0, x26
        orr     x1, x25, #1 << 24               // use reserved ISS bit for instruction aborts
        mov     x2, sp
-       adr     lr, ret_to_user
-       b       do_mem_abort
+       bl      do_mem_abort
+       b       ret_to_user
 el0_fpsimd_acc:
        /*
         * Floating Point or Advanced SIMD access
@@ -478,8 +478,8 @@ el0_fpsimd_acc:
        ct_user_exit
        mov     x0, x25
        mov     x1, sp
-       adr     lr, ret_to_user
-       b       do_fpsimd_acc
+       bl      do_fpsimd_acc
+       b       ret_to_user
 el0_fpsimd_exc:
        /*
         * Floating Point or Advanced SIMD exception
@@ -488,8 +488,8 @@ el0_fpsimd_exc:
        ct_user_exit
        mov     x0, x25
        mov     x1, sp
-       adr     lr, ret_to_user
-       b       do_fpsimd_exc
+       bl      do_fpsimd_exc
+       b       ret_to_user
 el0_sp_pc:
        /*
         * Stack or PC alignment exception handling
@@ -500,8 +500,8 @@ el0_sp_pc:
        mov     x0, x26
        mov     x1, x25
        mov     x2, sp
-       adr     lr, ret_to_user
-       b       do_sp_pc_abort
+       bl      do_sp_pc_abort
+       b       ret_to_user
 el0_undef:
        /*
         * Undefined instruction
@@ -510,8 +510,8 @@ el0_undef:
        enable_dbg_and_irq
        ct_user_exit
        mov     x0, sp
-       adr     lr, ret_to_user
-       b       do_undefinstr
+       bl      do_undefinstr
+       b       ret_to_user
 el0_dbg:
        /*
         * Debug exception handling
@@ -530,8 +530,8 @@ el0_inv:
        mov     x0, sp
        mov     x1, #BAD_SYNC
        mrs     x2, esr_el1
-       adr     lr, ret_to_user
-       b       bad_mode
+       bl      bad_mode
+       b       ret_to_user
 ENDPROC(el0_sync)
 
        .align  6
@@ -653,14 +653,15 @@ el0_svc_naked:                                    // compat entry point
        ldr     x16, [tsk, #TI_FLAGS]           // check for syscall hooks
        tst     x16, #_TIF_SYSCALL_WORK
        b.ne    __sys_trace
-       adr     lr, ret_fast_syscall            // return address
        cmp     scno, sc_nr                     // check upper syscall limit
        b.hs    ni_sys
        ldr     x16, [stbl, scno, lsl #3]       // address in the syscall table
-       br      x16                             // call sys_* routine
+       blr     x16                             // call sys_* routine
+       b       ret_fast_syscall
 ni_sys:
        mov     x0, sp
-       b       do_ni_syscall
+       bl      do_ni_syscall
+       b       ret_fast_syscall
 ENDPROC(el0_svc)
 
        /*
@@ -668,26 +669,38 @@ ENDPROC(el0_svc)
         * switches, and waiting for our parent to respond.
         */
 __sys_trace:
-       mov     x0, sp
+       mov     w0, #-1                         // set default errno for
+       cmp     scno, x0                        // user-issued syscall(-1)
+       b.ne    1f
+       mov     x0, #-ENOSYS
+       str     x0, [sp, #S_X0]
+1:     mov     x0, sp
        bl      syscall_trace_enter
-       adr     lr, __sys_trace_return          // return address
+       cmp     w0, #-1                         // skip the syscall?
+       b.eq    __sys_trace_return_skipped
        uxtw    scno, w0                        // syscall number (possibly new)
        mov     x1, sp                          // pointer to regs
        cmp     scno, sc_nr                     // check upper syscall limit
-       b.hs    ni_sys
+       b.hs    __ni_sys_trace
        ldp     x0, x1, [sp]                    // restore the syscall args
        ldp     x2, x3, [sp, #S_X2]
        ldp     x4, x5, [sp, #S_X4]
        ldp     x6, x7, [sp, #S_X6]
        ldr     x16, [stbl, scno, lsl #3]       // address in the syscall table
-       b     x16                             // call sys_* routine
+       blr     x16                             // call sys_* routine
 
 __sys_trace_return:
-       str     x0, [sp]                        // save returned x0
+       str     x0, [sp, #S_X0]                 // save returned x0
+__sys_trace_return_skipped:
        mov     x0, sp
        bl      syscall_trace_exit
        b       ret_to_user
 
+__ni_sys_trace:
+       mov     x0, sp
+       bl      do_ni_syscall
+       b       __sys_trace_return
+
 /*
  * Special system call wrappers.
  */
@@ -695,6 +708,3 @@ ENTRY(sys_rt_sigreturn_wrapper)
        mov     x0, sp
        b       sys_rt_sigreturn
 ENDPROC(sys_rt_sigreturn_wrapper)
-
-ENTRY(handle_arch_irq)
-       .quad   0
index 0a6e4f924df87fa2a595b2774ac752f119d4e7e5..8ce88e08c030e16b90d2772d377160a12465fce2 100644 (file)
@@ -132,6 +132,8 @@ efi_head:
 #endif
 
 #ifdef CONFIG_EFI
+       .globl  stext_offset
+       .set    stext_offset, stext - efi_head
        .align 3
 pe_header:
        .ascii  "PE"
@@ -155,12 +157,12 @@ optional_header:
        .long   0                               // SizeOfInitializedData
        .long   0                               // SizeOfUninitializedData
        .long   efi_stub_entry - efi_head       // AddressOfEntryPoint
-       .long   stext - efi_head                // BaseOfCode
+       .long   stext_offset                    // BaseOfCode
 
 extra_header_fields:
        .quad   0                               // ImageBase
-       .long   0x20                            // SectionAlignment
-       .long   0x8                             // FileAlignment
+       .long   0x1000                          // SectionAlignment
+       .long   PECOFF_FILE_ALIGNMENT           // FileAlignment
        .short  0                               // MajorOperatingSystemVersion
        .short  0                               // MinorOperatingSystemVersion
        .short  0                               // MajorImageVersion
@@ -172,7 +174,7 @@ extra_header_fields:
        .long   _end - efi_head                 // SizeOfImage
 
        // Everything before the kernel image is considered part of the header
-       .long   stext - efi_head                // SizeOfHeaders
+       .long   stext_offset                    // SizeOfHeaders
        .long   0                               // CheckSum
        .short  0xa                             // Subsystem (EFI application)
        .short  0                               // DllCharacteristics
@@ -217,16 +219,24 @@ section_table:
        .byte   0
        .byte   0                       // end of 0 padding of section name
        .long   _end - stext            // VirtualSize
-       .long   stext - efi_head        // VirtualAddress
+       .long   stext_offset            // VirtualAddress
        .long   _edata - stext          // SizeOfRawData
-       .long   stext - efi_head        // PointerToRawData
+       .long   stext_offset            // PointerToRawData
 
        .long   0               // PointerToRelocations (0 for executables)
        .long   0               // PointerToLineNumbers (0 for executables)
        .short  0               // NumberOfRelocations  (0 for executables)
        .short  0               // NumberOfLineNumbers  (0 for executables)
        .long   0xe0500020      // Characteristics (section flags)
-       .align 5
+
+       /*
+        * EFI will load stext onwards at the 4k section alignment
+        * described in the PE/COFF header. To ensure that instruction
+        * sequences using an adrp and a :lo12: immediate will function
+        * correctly at this alignment, we must ensure that stext is
+        * placed at a 4k boundary in the Image to begin with.
+        */
+       .align 12
 #endif
 
 ENTRY(stext)
@@ -238,7 +248,13 @@ ENTRY(stext)
        mov     x0, x22
        bl      lookup_processor_type
        mov     x23, x0                         // x23=current cpu_table
-       cbz     x23, __error_p                  // invalid processor (x23=0)?
+       /*
+        * __error_p may end up out of range for cbz if text areas are
+        * aligned up to section sizes.
+        */
+       cbnz    x23, 1f                         // invalid processor (x23=0)?
+       b       __error_p
+1:
        bl      __vet_fdt
        bl      __create_page_tables            // x25=TTBR0, x26=TTBR1
        /*
@@ -250,12 +266,213 @@ ENTRY(stext)
         */
        ldr     x27, __switch_data              // address to jump to after
                                                // MMU has been enabled
-       adr     lr, __enable_mmu                // return (PIC) address
+       adrp    lr, __enable_mmu                // return (PIC) address
+       add     lr, lr, #:lo12:__enable_mmu
        ldr     x12, [x23, #CPU_INFO_SETUP]
        add     x12, x12, x28                   // __virt_to_phys
        br      x12                             // initialise processor
 ENDPROC(stext)
 
+/*
+ * Determine validity of the x21 FDT pointer.
+ * The dtb must be 8-byte aligned and live in the first 512M of memory.
+ */
+__vet_fdt:
+       tst     x21, #0x7
+       b.ne    1f
+       cmp     x21, x24
+       b.lt    1f
+       mov     x0, #(1 << 29)
+       add     x0, x0, x24
+       cmp     x21, x0
+       b.ge    1f
+       ret
+1:
+       mov     x21, #0
+       ret
+ENDPROC(__vet_fdt)
+/*
+ * Macro to create a table entry to the next page.
+ *
+ *     tbl:    page table address
+ *     virt:   virtual address
+ *     shift:  #imm page table shift
+ *     ptrs:   #imm pointers per table page
+ *
+ * Preserves:  virt
+ * Corrupts:   tmp1, tmp2
+ * Returns:    tbl -> next level table page address
+ */
+       .macro  create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2
+       lsr     \tmp1, \virt, #\shift
+       and     \tmp1, \tmp1, #\ptrs - 1        // table index
+       add     \tmp2, \tbl, #PAGE_SIZE
+       orr     \tmp2, \tmp2, #PMD_TYPE_TABLE   // address of next table and entry type
+       str     \tmp2, [\tbl, \tmp1, lsl #3]
+       add     \tbl, \tbl, #PAGE_SIZE          // next level table page
+       .endm
+
+/*
+ * Macro to populate the PGD (and possibily PUD) for the corresponding
+ * block entry in the next level (tbl) for the given virtual address.
+ *
+ * Preserves:  tbl, next, virt
+ * Corrupts:   tmp1, tmp2
+ */
+       .macro  create_pgd_entry, tbl, virt, tmp1, tmp2
+       create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2
+#if SWAPPER_PGTABLE_LEVELS == 3
+       create_table_entry \tbl, \virt, TABLE_SHIFT, PTRS_PER_PTE, \tmp1, \tmp2
+#endif
+       .endm
+
+/*
+ * Macro to populate block entries in the page table for the start..end
+ * virtual range (inclusive).
+ *
+ * Preserves:  tbl, flags
+ * Corrupts:   phys, start, end, pstate
+ */
+       .macro  create_block_map, tbl, flags, phys, start, end
+       lsr     \phys, \phys, #BLOCK_SHIFT
+       lsr     \start, \start, #BLOCK_SHIFT
+       and     \start, \start, #PTRS_PER_PTE - 1       // table index
+       orr     \phys, \flags, \phys, lsl #BLOCK_SHIFT  // table entry
+       lsr     \end, \end, #BLOCK_SHIFT
+       and     \end, \end, #PTRS_PER_PTE - 1           // table end index
+9999:  str     \phys, [\tbl, \start, lsl #3]           // store the entry
+       add     \start, \start, #1                      // next entry
+       add     \phys, \phys, #BLOCK_SIZE               // next block
+       cmp     \start, \end
+       b.ls    9999b
+       .endm
+
+/*
+ * Setup the initial page tables. We only setup the barest amount which is
+ * required to get the kernel running. The following sections are required:
+ *   - identity mapping to enable the MMU (low address, TTBR0)
+ *   - first few MB of the kernel linear mapping to jump to once the MMU has
+ *     been enabled, including the FDT blob (TTBR1)
+ *   - pgd entry for fixed mappings (TTBR1)
+ */
+__create_page_tables:
+       pgtbl   x25, x26, x28                   // idmap_pg_dir and swapper_pg_dir addresses
+       mov     x27, lr
+
+       /*
+        * Invalidate the idmap and swapper page tables to avoid potential
+        * dirty cache lines being evicted.
+        */
+       mov     x0, x25
+       add     x1, x26, #SWAPPER_DIR_SIZE
+       bl      __inval_cache_range
+
+       /*
+        * Clear the idmap and swapper page tables.
+        */
+       mov     x0, x25
+       add     x6, x26, #SWAPPER_DIR_SIZE
+1:     stp     xzr, xzr, [x0], #16
+       stp     xzr, xzr, [x0], #16
+       stp     xzr, xzr, [x0], #16
+       stp     xzr, xzr, [x0], #16
+       cmp     x0, x6
+       b.lo    1b
+
+       ldr     x7, =MM_MMUFLAGS
+
+       /*
+        * Create the identity mapping.
+        */
+       mov     x0, x25                         // idmap_pg_dir
+       ldr     x3, =KERNEL_START
+       add     x3, x3, x28                     // __pa(KERNEL_START)
+       create_pgd_entry x0, x3, x5, x6
+       ldr     x6, =KERNEL_END
+       mov     x5, x3                          // __pa(KERNEL_START)
+       add     x6, x6, x28                     // __pa(KERNEL_END)
+       create_block_map x0, x7, x3, x5, x6
+
+       /*
+        * Map the kernel image (starting with PHYS_OFFSET).
+        */
+       mov     x0, x26                         // swapper_pg_dir
+       mov     x5, #PAGE_OFFSET
+       create_pgd_entry x0, x5, x3, x6
+       ldr     x6, =KERNEL_END
+       mov     x3, x24                         // phys offset
+       create_block_map x0, x7, x3, x5, x6
+
+       /*
+        * Map the FDT blob (maximum 2MB; must be within 512MB of
+        * PHYS_OFFSET).
+        */
+       mov     x3, x21                         // FDT phys address
+       and     x3, x3, #~((1 << 21) - 1)       // 2MB aligned
+       mov     x6, #PAGE_OFFSET
+       sub     x5, x3, x24                     // subtract PHYS_OFFSET
+       tst     x5, #~((1 << 29) - 1)           // within 512MB?
+       csel    x21, xzr, x21, ne               // zero the FDT pointer
+       b.ne    1f
+       add     x5, x5, x6                      // __va(FDT blob)
+       add     x6, x5, #1 << 21                // 2MB for the FDT blob
+       sub     x6, x6, #1                      // inclusive range
+       create_block_map x0, x7, x3, x5, x6
+1:
+       /*
+        * Since the page tables have been populated with non-cacheable
+        * accesses (MMU disabled), invalidate the idmap and swapper page
+        * tables again to remove any speculatively loaded cache lines.
+        */
+       mov     x0, x25
+       add     x1, x26, #SWAPPER_DIR_SIZE
+       bl      __inval_cache_range
+
+       mov     lr, x27
+       ret
+ENDPROC(__create_page_tables)
+       .ltorg
+
+       .align  3
+       .type   __switch_data, %object
+__switch_data:
+       .quad   __mmap_switched
+       .quad   __bss_start                     // x6
+       .quad   __bss_stop                      // x7
+       .quad   processor_id                    // x4
+       .quad   __fdt_pointer                   // x5
+       .quad   memstart_addr                   // x6
+       .quad   init_thread_union + THREAD_START_SP // sp
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode, and
+ * uses absolute addresses; this is not position independent.
+ */
+__mmap_switched:
+       adr     x3, __switch_data + 8
+
+       ldp     x6, x7, [x3], #16
+1:     cmp     x6, x7
+       b.hs    2f
+       str     xzr, [x6], #8                   // Clear BSS
+       b       1b
+2:
+       ldp     x4, x5, [x3], #16
+       ldr     x6, [x3], #8
+       ldr     x16, [x3]
+       mov     sp, x16
+       str     x22, [x4]                       // Save processor ID
+       str     x21, [x5]                       // Save FDT pointer
+       str     x24, [x6]                       // Save PHYS_OFFSET
+       mov     x29, #0
+       b       start_kernel
+ENDPROC(__mmap_switched)
+
+/*
+ * end early head section, begin head code that is also used for
+ * hotplug and needs to have the same protections as the text region
+ */
+       .section ".text","ax"
 /*
  * If we're fortunate enough to boot at EL2, ensure that the world is
  * sane before dropping to EL1.
@@ -331,7 +548,8 @@ CPU_LE(     movk    x0, #0x30d0, lsl #16    )       // Clear EE and E0E on LE systems
        msr     vttbr_el2, xzr
 
        /* Hypervisor stub */
-       adr     x0, __hyp_stub_vectors
+       adrp    x0, __hyp_stub_vectors
+       add     x0, x0, #:lo12:__hyp_stub_vectors
        msr     vbar_el2, x0
 
        /* spsr */
@@ -491,183 +709,6 @@ ENDPROC(__calc_phys_offset)
 1:     .quad   .
        .quad   PAGE_OFFSET
 
-/*
- * Macro to create a table entry to the next page.
- *
- *     tbl:    page table address
- *     virt:   virtual address
- *     shift:  #imm page table shift
- *     ptrs:   #imm pointers per table page
- *
- * Preserves:  virt
- * Corrupts:   tmp1, tmp2
- * Returns:    tbl -> next level table page address
- */
-       .macro  create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2
-       lsr     \tmp1, \virt, #\shift
-       and     \tmp1, \tmp1, #\ptrs - 1        // table index
-       add     \tmp2, \tbl, #PAGE_SIZE
-       orr     \tmp2, \tmp2, #PMD_TYPE_TABLE   // address of next table and entry type
-       str     \tmp2, [\tbl, \tmp1, lsl #3]
-       add     \tbl, \tbl, #PAGE_SIZE          // next level table page
-       .endm
-
-/*
- * Macro to populate the PGD (and possibily PUD) for the corresponding
- * block entry in the next level (tbl) for the given virtual address.
- *
- * Preserves:  tbl, next, virt
- * Corrupts:   tmp1, tmp2
- */
-       .macro  create_pgd_entry, tbl, virt, tmp1, tmp2
-       create_table_entry \tbl, \virt, PGDIR_SHIFT, PTRS_PER_PGD, \tmp1, \tmp2
-#if SWAPPER_PGTABLE_LEVELS == 3
-       create_table_entry \tbl, \virt, TABLE_SHIFT, PTRS_PER_PTE, \tmp1, \tmp2
-#endif
-       .endm
-
-/*
- * Macro to populate block entries in the page table for the start..end
- * virtual range (inclusive).
- *
- * Preserves:  tbl, flags
- * Corrupts:   phys, start, end, pstate
- */
-       .macro  create_block_map, tbl, flags, phys, start, end
-       lsr     \phys, \phys, #BLOCK_SHIFT
-       lsr     \start, \start, #BLOCK_SHIFT
-       and     \start, \start, #PTRS_PER_PTE - 1       // table index
-       orr     \phys, \flags, \phys, lsl #BLOCK_SHIFT  // table entry
-       lsr     \end, \end, #BLOCK_SHIFT
-       and     \end, \end, #PTRS_PER_PTE - 1           // table end index
-9999:  str     \phys, [\tbl, \start, lsl #3]           // store the entry
-       add     \start, \start, #1                      // next entry
-       add     \phys, \phys, #BLOCK_SIZE               // next block
-       cmp     \start, \end
-       b.ls    9999b
-       .endm
-
-/*
- * Setup the initial page tables. We only setup the barest amount which is
- * required to get the kernel running. The following sections are required:
- *   - identity mapping to enable the MMU (low address, TTBR0)
- *   - first few MB of the kernel linear mapping to jump to once the MMU has
- *     been enabled, including the FDT blob (TTBR1)
- *   - pgd entry for fixed mappings (TTBR1)
- */
-__create_page_tables:
-       pgtbl   x25, x26, x28                   // idmap_pg_dir and swapper_pg_dir addresses
-       mov     x27, lr
-
-       /*
-        * Invalidate the idmap and swapper page tables to avoid potential
-        * dirty cache lines being evicted.
-        */
-       mov     x0, x25
-       add     x1, x26, #SWAPPER_DIR_SIZE
-       bl      __inval_cache_range
-
-       /*
-        * Clear the idmap and swapper page tables.
-        */
-       mov     x0, x25
-       add     x6, x26, #SWAPPER_DIR_SIZE
-1:     stp     xzr, xzr, [x0], #16
-       stp     xzr, xzr, [x0], #16
-       stp     xzr, xzr, [x0], #16
-       stp     xzr, xzr, [x0], #16
-       cmp     x0, x6
-       b.lo    1b
-
-       ldr     x7, =MM_MMUFLAGS
-
-       /*
-        * Create the identity mapping.
-        */
-       mov     x0, x25                         // idmap_pg_dir
-       ldr     x3, =KERNEL_START
-       add     x3, x3, x28                     // __pa(KERNEL_START)
-       create_pgd_entry x0, x3, x5, x6
-       ldr     x6, =KERNEL_END
-       mov     x5, x3                          // __pa(KERNEL_START)
-       add     x6, x6, x28                     // __pa(KERNEL_END)
-       create_block_map x0, x7, x3, x5, x6
-
-       /*
-        * Map the kernel image (starting with PHYS_OFFSET).
-        */
-       mov     x0, x26                         // swapper_pg_dir
-       mov     x5, #PAGE_OFFSET
-       create_pgd_entry x0, x5, x3, x6
-       ldr     x6, =KERNEL_END
-       mov     x3, x24                         // phys offset
-       create_block_map x0, x7, x3, x5, x6
-
-       /*
-        * Map the FDT blob (maximum 2MB; must be within 512MB of
-        * PHYS_OFFSET).
-        */
-       mov     x3, x21                         // FDT phys address
-       and     x3, x3, #~((1 << 21) - 1)       // 2MB aligned
-       mov     x6, #PAGE_OFFSET
-       sub     x5, x3, x24                     // subtract PHYS_OFFSET
-       tst     x5, #~((1 << 29) - 1)           // within 512MB?
-       csel    x21, xzr, x21, ne               // zero the FDT pointer
-       b.ne    1f
-       add     x5, x5, x6                      // __va(FDT blob)
-       add     x6, x5, #1 << 21                // 2MB for the FDT blob
-       sub     x6, x6, #1                      // inclusive range
-       create_block_map x0, x7, x3, x5, x6
-1:
-       /*
-        * Since the page tables have been populated with non-cacheable
-        * accesses (MMU disabled), invalidate the idmap and swapper page
-        * tables again to remove any speculatively loaded cache lines.
-        */
-       mov     x0, x25
-       add     x1, x26, #SWAPPER_DIR_SIZE
-       bl      __inval_cache_range
-
-       mov     lr, x27
-       ret
-ENDPROC(__create_page_tables)
-       .ltorg
-
-       .align  3
-       .type   __switch_data, %object
-__switch_data:
-       .quad   __mmap_switched
-       .quad   __bss_start                     // x6
-       .quad   __bss_stop                      // x7
-       .quad   processor_id                    // x4
-       .quad   __fdt_pointer                   // x5
-       .quad   memstart_addr                   // x6
-       .quad   init_thread_union + THREAD_START_SP // sp
-
-/*
- * The following fragment of code is executed with the MMU on in MMU mode, and
- * uses absolute addresses; this is not position independent.
- */
-__mmap_switched:
-       adr     x3, __switch_data + 8
-
-       ldp     x6, x7, [x3], #16
-1:     cmp     x6, x7
-       b.hs    2f
-       str     xzr, [x6], #8                   // Clear BSS
-       b       1b
-2:
-       ldp     x4, x5, [x3], #16
-       ldr     x6, [x3], #8
-       ldr     x16, [x3]
-       mov     sp, x16
-       str     x22, [x4]                       // Save processor ID
-       str     x21, [x5]                       // Save FDT pointer
-       str     x24, [x6]                       // Save PHYS_OFFSET
-       mov     x29, #0
-       b       start_kernel
-ENDPROC(__mmap_switched)
-
 /*
  * Exception handling. Something went wrong and we can't proceed. We ought to
  * tell the user, but since we don't have any guarantee that we're even
@@ -715,22 +756,3 @@ __lookup_processor_type_data:
        .quad   .
        .quad   cpu_table
        .size   __lookup_processor_type_data, . - __lookup_processor_type_data
-
-/*
- * Determine validity of the x21 FDT pointer.
- * The dtb must be 8-byte aligned and live in the first 512M of memory.
- */
-__vet_fdt:
-       tst     x21, #0x7
-       b.ne    1f
-       cmp     x21, x24
-       b.lt    1f
-       mov     x0, #(1 << 29)
-       add     x0, x0, x24
-       cmp     x21, x0
-       b.ge    1f
-       ret
-1:
-       mov     x21, #0
-       ret
-ENDPROC(__vet_fdt)
index e007714ded04e6a0854657b0cc39f244e06de18c..7e9327a0986dc5305f74f5e9bdfb224eccec21c6 100644 (file)
@@ -163,9 +163,10 @@ static int __kprobes aarch64_insn_patch_text_cb(void *arg)
                 * which ends with "dsb; isb" pair guaranteeing global
                 * visibility.
                 */
-               atomic_set(&pp->cpu_count, -1);
+               /* Notify other processors with an additional increment. */
+               atomic_inc(&pp->cpu_count);
        } else {
-               while (atomic_read(&pp->cpu_count) != -1)
+               while (atomic_read(&pp->cpu_count) <= num_online_cpus())
                        cpu_relax();
                isb();
        }
@@ -959,3 +960,29 @@ u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst,
 
        return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift);
 }
+
+bool aarch32_insn_is_wide(u32 insn)
+{
+       return insn >= 0xe800;
+}
+
+/*
+ * Macros/defines for extracting register numbers from instruction.
+ */
+u32 aarch32_insn_extract_reg_num(u32 insn, int offset)
+{
+       return (insn & (0xf << offset)) >> offset;
+}
+
+#define OPC2_MASK      0x7
+#define OPC2_OFFSET    5
+u32 aarch32_insn_mcr_extract_opc2(u32 insn)
+{
+       return (insn & (OPC2_MASK << OPC2_OFFSET)) >> OPC2_OFFSET;
+}
+
+#define CRM_MASK       0xf
+u32 aarch32_insn_mcr_extract_crm(u32 insn)
+{
+       return insn & CRM_MASK;
+}
index 7d37ead4d1994fa877dcf798148875775b25ded9..354be2a872ae81bd58db3506cd0c7f77a62cd402 100644 (file)
  */
 void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
 {
-       unsigned char *t = to;
-       while (count) {
+       while (count && (!IS_ALIGNED((unsigned long)from, 8) ||
+                        !IS_ALIGNED((unsigned long)to, 8))) {
+               *(u8 *)to = __raw_readb(from);
+               from++;
+               to++;
                count--;
-               *t = readb(from);
-               t++;
+       }
+
+       while (count >= 8) {
+               *(u64 *)to = __raw_readq(from);
+               from += 8;
+               to += 8;
+               count -= 8;
+       }
+
+       while (count) {
+               *(u8 *)to = __raw_readb(from);
                from++;
+               to++;
+               count--;
        }
 }
 EXPORT_SYMBOL(__memcpy_fromio);
@@ -40,12 +54,26 @@ EXPORT_SYMBOL(__memcpy_fromio);
  */
 void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
 {
-       const unsigned char *f = from;
-       while (count) {
+       while (count && (!IS_ALIGNED((unsigned long)to, 8) ||
+                        !IS_ALIGNED((unsigned long)from, 8))) {
+               __raw_writeb(*(volatile u8 *)from, to);
+               from++;
+               to++;
                count--;
-               writeb(*f, to);
-               f++;
+       }
+
+       while (count >= 8) {
+               __raw_writeq(*(volatile u64 *)from, to);
+               from += 8;
+               to += 8;
+               count -= 8;
+       }
+
+       while (count) {
+               __raw_writeb(*(volatile u8 *)from, to);
+               from++;
                to++;
+               count--;
        }
 }
 EXPORT_SYMBOL(__memcpy_toio);
@@ -55,10 +83,28 @@ EXPORT_SYMBOL(__memcpy_toio);
  */
 void __memset_io(volatile void __iomem *dst, int c, size_t count)
 {
-       while (count) {
+       u64 qc = (u8)c;
+
+       qc |= qc << 8;
+       qc |= qc << 16;
+       qc |= qc << 32;
+
+       while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
+               __raw_writeb(c, dst);
+               dst++;
                count--;
-               writeb(c, dst);
+       }
+
+       while (count >= 8) {
+               __raw_writeq(qc, dst);
+               dst += 8;
+               count -= 8;
+       }
+
+       while (count) {
+               __raw_writeb(c, dst);
                dst++;
+               count--;
        }
 }
 EXPORT_SYMBOL(__memset_io);
index 071a6ec13bd8e8beb8324c1ae8557dc20a085cd1..240b75c0e94fdc435a672b740b08d4a848915295 100644 (file)
@@ -40,6 +40,8 @@ int arch_show_interrupts(struct seq_file *p, int prec)
        return 0;
 }
 
+void (*handle_arch_irq)(struct pt_regs *) = NULL;
+
 void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
 {
        if (handle_arch_irq)
index 263a166291fbd96691c01f5d81554b4471d13d79..4f1fec7a46dbb1687046a2d7645edfc27bcce665 100644 (file)
@@ -22,9 +22,8 @@
 
 #ifdef HAVE_JUMP_LABEL
 
-static void __arch_jump_label_transform(struct jump_entry *entry,
-                                       enum jump_label_type type,
-                                       bool is_static)
+void arch_jump_label_transform(struct jump_entry *entry,
+                              enum jump_label_type type)
 {
        void *addr = (void *)entry->code;
        u32 insn;
@@ -37,22 +36,18 @@ static void __arch_jump_label_transform(struct jump_entry *entry,
                insn = aarch64_insn_gen_nop();
        }
 
-       if (is_static)
-               aarch64_insn_patch_text_nosync(addr, insn);
-       else
-               aarch64_insn_patch_text(&addr, &insn, 1);
-}
-
-void arch_jump_label_transform(struct jump_entry *entry,
-                              enum jump_label_type type)
-{
-       __arch_jump_label_transform(entry, type, false);
+       aarch64_insn_patch_text(&addr, &insn, 1);
 }
 
 void arch_jump_label_transform_static(struct jump_entry *entry,
                                      enum jump_label_type type)
 {
-       __arch_jump_label_transform(entry, type, true);
+       /*
+        * We use the architected A64 NOP in arch_static_branch, so there's no
+        * need to patch an identical A64 NOP over the top of it here. The core
+        * will call arch_jump_label_transform from a module notifier if the
+        * NOP needs to be replaced by a branch.
+        */
 }
 
 #endif /* HAVE_JUMP_LABEL */
index 1eb1cc955139537e1b66cbdc78accd5830f0ca06..fd027b101de59fd350ed45d2ec928693e4b9be41 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/moduleloader.h>
 #include <linux/vmalloc.h>
 #include <asm/insn.h>
+#include <asm/sections.h>
 
 #define        AARCH64_INSN_IMM_MOVNZ          AARCH64_INSN_IMM_MAX
 #define        AARCH64_INSN_IMM_MOVK           AARCH64_INSN_IMM_16
@@ -394,3 +395,20 @@ overflow:
               me->name, (int)ELF64_R_TYPE(rel[i].r_info), val);
        return -ENOEXEC;
 }
+
+int module_finalize(const Elf_Ehdr *hdr,
+                   const Elf_Shdr *sechdrs,
+                   struct module *me)
+{
+       const Elf_Shdr *s, *se;
+       const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+       for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) {
+               if (strcmp(".altinstructions", secstrs + s->sh_name) == 0) {
+                       apply_alternatives((void *)s->sh_addr, s->sh_size);
+                       return 0;
+               }
+       }
+
+       return 0;
+}
index aa29ecb4f80044a4f3491cdcdcfce491642bb008..25a5308744b1ce17e8299502be30cca1b3cca628 100644 (file)
@@ -169,8 +169,14 @@ armpmu_event_set_period(struct perf_event *event,
                ret = 1;
        }
 
-       if (left > (s64)armpmu->max_period)
-               left = armpmu->max_period;
+       /*
+        * Limit the maximum period to prevent the counter value
+        * from overtaking the one we are about to program. In
+        * effect we are reducing max_period to account for
+        * interrupt latency (and we are being very conservative).
+        */
+       if (left > (armpmu->max_period >> 1))
+               left = armpmu->max_period >> 1;
 
        local64_set(&hwc->prev_count, (u64)-left);
 
index c3065dbc4fa269bafbb0b93f5a458d0534ae2bc5..fde9923af859c5764110b1accf7a9da567559dd4 100644 (file)
@@ -378,8 +378,3 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
        return randomize_base(mm->brk);
 }
-
-unsigned long randomize_et_dyn(unsigned long base)
-{
-       return randomize_base(base);
-}
index 866c1c821860d9689dc363b73001529ee3b5bec5..663da771580ac21a82faae5f5062fa6361e1f794 100644 (file)
@@ -528,7 +528,7 @@ static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
        if (WARN_ON_ONCE(!index))
                return -EINVAL;
 
-       if (state->type == PSCI_POWER_STATE_TYPE_STANDBY)
+       if (state[index - 1].type == PSCI_POWER_STATE_TYPE_STANDBY)
                ret = psci_ops.cpu_suspend(state[index - 1], 0);
        else
                ret = __cpu_suspend(index, psci_suspend_finisher);
index 8a4ae8e73213a26add3da24f8a0ea2a8f17ff4ed..d882b833dbdb59095b29b3e9212a7e73508f0f1d 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/smp.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/seccomp.h>
 #include <linux/security.h>
 #include <linux/init.h>
 #include <linux/signal.h>
@@ -551,6 +552,32 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset,
        return ret;
 }
 
+static int system_call_get(struct task_struct *target,
+                          const struct user_regset *regset,
+                          unsigned int pos, unsigned int count,
+                          void *kbuf, void __user *ubuf)
+{
+       int syscallno = task_pt_regs(target)->syscallno;
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  &syscallno, 0, -1);
+}
+
+static int system_call_set(struct task_struct *target,
+                          const struct user_regset *regset,
+                          unsigned int pos, unsigned int count,
+                          const void *kbuf, const void __user *ubuf)
+{
+       int syscallno, ret;
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);
+       if (ret)
+               return ret;
+
+       task_pt_regs(target)->syscallno = syscallno;
+       return ret;
+}
+
 enum aarch64_regset {
        REGSET_GPR,
        REGSET_FPR,
@@ -559,6 +586,7 @@ enum aarch64_regset {
        REGSET_HW_BREAK,
        REGSET_HW_WATCH,
 #endif
+       REGSET_SYSTEM_CALL,
 };
 
 static const struct user_regset aarch64_regsets[] = {
@@ -608,6 +636,14 @@ static const struct user_regset aarch64_regsets[] = {
                .set = hw_break_set,
        },
 #endif
+       [REGSET_SYSTEM_CALL] = {
+               .core_note_type = NT_ARM_SYSTEM_CALL,
+               .n = 1,
+               .size = sizeof(int),
+               .align = sizeof(int),
+               .get = system_call_get,
+               .set = system_call_set,
+       },
 };
 
 static const struct user_regset_view user_aarch64_view = {
@@ -1114,6 +1150,10 @@ static void tracehook_report_syscall(struct pt_regs *regs,
 
 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 {
+       /* Do the secure computing check first; failures should be fast. */
+       if (secure_computing() == -1)
+               return -1;
+
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
 
index 2437196cc5d402b5d3b501d1699ff21fb7257e32..b8099116675459b933b290fd3fda5fd3cd3ecdb3 100644 (file)
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/efi.h>
+#include <linux/personality.h>
 
 #include <asm/fixmap.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/cputable.h>
+#include <asm/cpufeature.h>
 #include <asm/cpu_ops.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
@@ -72,13 +74,15 @@ EXPORT_SYMBOL_GPL(elf_hwcap);
                                 COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
                                 COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
                                 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
-                                COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)
+                                COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\
+                                COMPAT_HWCAP_LPAE)
 unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
 unsigned int compat_elf_hwcap2 __read_mostly;
 #endif
 
+DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
+
 static const char *cpu_name;
-static const char *machine_name;
 phys_addr_t __fdt_pointer __initdata;
 
 /*
@@ -116,12 +120,16 @@ void __init early_print(const char *str, ...)
 
 void __init smp_setup_processor_id(void)
 {
+       u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
+       cpu_logical_map(0) = mpidr;
+
        /*
         * clear __my_cpu_offset on boot CPU to avoid hang caused by
         * using percpu variable early, for example, lockdep will
         * access percpu variable inside lock_release
         */
        set_my_cpu_offset(0);
+       pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr);
 }
 
 bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
@@ -311,7 +319,7 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
                        cpu_relax();
        }
 
-       machine_name = of_flat_dt_get_machine_name();
+       dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name());
 }
 
 /*
@@ -376,6 +384,7 @@ void __init setup_arch(char **cmdline_p)
 
        *cmdline_p = boot_command_line;
 
+       early_fixmap_init();
        early_ioremap_init();
 
        parse_early_param();
@@ -398,7 +407,6 @@ void __init setup_arch(char **cmdline_p)
 
        psci_init();
 
-       cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
        cpu_read_bootcpu_ops();
 #ifdef CONFIG_SMP
        smp_init_cpus();
@@ -447,14 +455,50 @@ static const char *hwcap_str[] = {
        NULL
 };
 
+#ifdef CONFIG_COMPAT
+static const char *compat_hwcap_str[] = {
+       "swp",
+       "half",
+       "thumb",
+       "26bit",
+       "fastmult",
+       "fpa",
+       "vfp",
+       "edsp",
+       "java",
+       "iwmmxt",
+       "crunch",
+       "thumbee",
+       "neon",
+       "vfpv3",
+       "vfpv3d16",
+       "tls",
+       "vfpv4",
+       "idiva",
+       "idivt",
+       "vfpd32",
+       "lpae",
+       "evtstrm"
+};
+
+static const char *compat_hwcap2_str[] = {
+       "aes",
+       "pmull",
+       "sha1",
+       "sha2",
+       "crc32",
+       NULL
+};
+#endif /* CONFIG_COMPAT */
+
 static int c_show(struct seq_file *m, void *v)
 {
-       int i;
-
-       seq_printf(m, "Processor\t: %s rev %d (%s)\n",
-                  cpu_name, read_cpuid_id() & 15, ELF_PLATFORM);
+       int i, j;
 
        for_each_online_cpu(i) {
+               struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
+               u32 midr = cpuinfo->reg_midr;
+
                /*
                 * glibc reads /proc/cpuinfo to determine the number of
                 * online processors, looking for lines beginning with
@@ -463,24 +507,38 @@ static int c_show(struct seq_file *m, void *v)
 #ifdef CONFIG_SMP
                seq_printf(m, "processor\t: %d\n", i);
 #endif
-       }
-
-       /* dump out the processor features */
-       seq_puts(m, "Features\t: ");
-
-       for (i = 0; hwcap_str[i]; i++)
-               if (elf_hwcap & (1 << i))
-                       seq_printf(m, "%s ", hwcap_str[i]);
-
-       seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
-       seq_printf(m, "CPU architecture: AArch64\n");
-       seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15);
-       seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff);
-       seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
 
-       seq_puts(m, "\n");
-
-       seq_printf(m, "Hardware\t: %s\n", machine_name);
+               /*
+                * Dump out the common processor features in a single line.
+                * Userspace should read the hwcaps with getauxval(AT_HWCAP)
+                * rather than attempting to parse this, but there's a body of
+                * software which does already (at least for 32-bit).
+                */
+               seq_puts(m, "Features\t:");
+               if (personality(current->personality) == PER_LINUX32) {
+#ifdef CONFIG_COMPAT
+                       for (j = 0; compat_hwcap_str[j]; j++)
+                               if (compat_elf_hwcap & (1 << j))
+                                       seq_printf(m, " %s", compat_hwcap_str[j]);
+
+                       for (j = 0; compat_hwcap2_str[j]; j++)
+                               if (compat_elf_hwcap2 & (1 << j))
+                                       seq_printf(m, " %s", compat_hwcap2_str[j]);
+#endif /* CONFIG_COMPAT */
+               } else {
+                       for (j = 0; hwcap_str[j]; j++)
+                               if (elf_hwcap & (1 << j))
+                                       seq_printf(m, " %s", hwcap_str[j]);
+               }
+               seq_puts(m, "\n");
+
+               seq_printf(m, "CPU implementer\t: 0x%02x\n",
+                          MIDR_IMPLEMENTOR(midr));
+               seq_printf(m, "CPU architecture: 8\n");
+               seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
+               seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
+               seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
+       }
 
        return 0;
 }
index 1b9ad02837cfcafd4ecbc87f3e10aafe504ac0de..5a1ba6e80d4e20b6d95b0152d99e2ebca53e7424 100644 (file)
@@ -186,6 +186,12 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
                err |= __put_user(from->si_uid, &to->si_uid);
                err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, &to->si_ptr);
                break;
+       case __SI_SYS:
+               err |= __put_user((compat_uptr_t)(unsigned long)
+                               from->si_call_addr, &to->si_call_addr);
+               err |= __put_user(from->si_syscall, &to->si_syscall);
+               err |= __put_user(from->si_arch, &to->si_arch);
+               break;
        default: /* this is just in case for now ... */
                err |= __put_user(from->si_pid, &to->si_pid);
                err |= __put_user(from->si_uid, &to->si_uid);
index a564b440416a8cde66ed8a31ade2a30d4a04e391..ede186cdd4520169fd2ea9259d4738b8796bf45d 100644 (file)
@@ -147,14 +147,12 @@ cpu_resume_after_mmu:
        ret
 ENDPROC(cpu_resume_after_mmu)
 
-       .data
 ENTRY(cpu_resume)
        bl      el2_setup               // if in EL2 drop to EL1 cleanly
 #ifdef CONFIG_SMP
        mrs     x1, mpidr_el1
-       adr     x4, mpidr_hash_ptr
-       ldr     x5, [x4]
-       add     x8, x4, x5              // x8 = struct mpidr_hash phys address
+       adrp    x8, mpidr_hash
+       add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address
         /* retrieve mpidr_hash members to compute the hash */
        ldr     x2, [x8, #MPIDR_HASH_MASK]
        ldp     w3, w4, [x8, #MPIDR_HASH_SHIFTS]
@@ -164,14 +162,15 @@ ENTRY(cpu_resume)
 #else
        mov     x7, xzr
 #endif
-       adr     x0, sleep_save_sp
+       adrp    x0, sleep_save_sp
+       add     x0, x0, #:lo12:sleep_save_sp
        ldr     x0, [x0, #SLEEP_SAVE_SP_PHYS]
        ldr     x0, [x0, x7, lsl #3]
        /* load sp from context */
        ldr     x2, [x0, #CPU_CTX_SP]
-       adr     x1, sleep_idmap_phys
+       adrp    x1, sleep_idmap_phys
        /* load physical address of identity map page table in x1 */
-       ldr     x1, [x1]
+       ldr     x1, [x1, #:lo12:sleep_idmap_phys]
        mov     sp, x2
        /*
         * cpu_do_resume expects x0 to contain context physical address
@@ -180,26 +179,3 @@ ENTRY(cpu_resume)
        bl      cpu_do_resume           // PC relative jump, MMU off
        b       cpu_resume_mmu          // Resume MMU, never returns
 ENDPROC(cpu_resume)
-
-       .align 3
-mpidr_hash_ptr:
-       /*
-        * offset of mpidr_hash symbol from current location
-        * used to obtain run-time mpidr_hash address with MMU off
-         */
-       .quad   mpidr_hash - .
-/*
- * physical address of identity mapped page tables
- */
-       .type   sleep_idmap_phys, #object
-ENTRY(sleep_idmap_phys)
-       .quad   0
-/*
- * struct sleep_save_sp {
- *     phys_addr_t *save_ptr_stash;
- *     phys_addr_t save_ptr_stash_phys;
- * };
- */
-       .type   sleep_save_sp, #object
-ENTRY(sleep_save_sp)
-       .space  SLEEP_SAVE_SP_SZ        // struct sleep_save_sp
index b06d1d90ee8cb223c70612515a0bed75048cc806..7ae6ee0852618e7c383dfd8d06626297788ac59a 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/of.h>
 #include <linux/irq_work.h>
 
+#include <asm/alternative.h>
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
@@ -309,6 +310,7 @@ void cpu_die(void)
 void __init smp_cpus_done(unsigned int max_cpus)
 {
        pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
+       apply_alternatives_all();
 }
 
 void __init smp_prepare_boot_cpu(void)
index 13ad4dbb1615fc9ad5419393f75907fb41560cc9..3771b72b6569fbf87acefb6de0741a5af8ec6548 100644 (file)
@@ -126,8 +126,8 @@ int __cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
        return ret;
 }
 
-extern struct sleep_save_sp sleep_save_sp;
-extern phys_addr_t sleep_idmap_phys;
+struct sleep_save_sp sleep_save_sp;
+phys_addr_t sleep_idmap_phys;
 
 static int __init cpu_suspend_init(void)
 {
index dc47e53e9e28c15da99e62976a9ca29f71da8bc4..28c511b06edfc05d9ac95e8c4ddf7bf11d62df05 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/unistd.h>
 
-static inline void
-do_compat_cache_op(unsigned long start, unsigned long end, int flags)
+static long
+__do_compat_cache_op(unsigned long start, unsigned long end)
 {
-       struct mm_struct *mm = current->active_mm;
-       struct vm_area_struct *vma;
+       long ret;
 
-       if (end < start || flags)
-               return;
+       do {
+               unsigned long chunk = min(PAGE_SIZE, end - start);
 
-       down_read(&mm->mmap_sem);
-       vma = find_vma(mm, start);
-       if (vma && vma->vm_start < end) {
-               if (start < vma->vm_start)
-                       start = vma->vm_start;
-               if (end > vma->vm_end)
-                       end = vma->vm_end;
-               up_read(&mm->mmap_sem);
-               __flush_cache_user_range(start & PAGE_MASK, PAGE_ALIGN(end));
-               return;
-       }
-       up_read(&mm->mmap_sem);
+               if (fatal_signal_pending(current))
+                       return 0;
+
+               ret = __flush_cache_user_range(start, start + chunk);
+               if (ret)
+                       return ret;
+
+               cond_resched();
+               start += chunk;
+       } while (start < end);
+
+       return 0;
 }
 
+static inline long
+do_compat_cache_op(unsigned long start, unsigned long end, int flags)
+{
+       if (end < start || flags)
+               return -EINVAL;
+
+       if (!access_ok(VERIFY_READ, start, end - start))
+               return -EFAULT;
+
+       return __do_compat_cache_op(start, end);
+}
 /*
  * Handle all unrecognised system calls.
  */
@@ -74,8 +84,7 @@ long compat_arm_syscall(struct pt_regs *regs)
         * the specified region).
         */
        case __ARM_NR_compat_cacheflush:
-               do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);
-               return 0;
+               return do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);
 
        case __ARM_NR_compat_set_tls:
                current->thread.tp_value = regs->regs[0];
index b6ee26b0939a8ac60f188ba2d5e67c738584aaf1..fcb8f7b42271c81b970732bd5bda9b50e5b89b1d 100644 (file)
@@ -255,12 +255,15 @@ void store_cpu_topology(unsigned int cpuid)
                /* Multiprocessor system : Multi-threads per core */
                cpuid_topo->thread_id  = MPIDR_AFFINITY_LEVEL(mpidr, 0);
                cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-               cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
+               cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 2) |
+                                        MPIDR_AFFINITY_LEVEL(mpidr, 3) << 8;
        } else {
                /* Multiprocessor system : Single-thread per core */
                cpuid_topo->thread_id  = -1;
                cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-               cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+               cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1) |
+                                        MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8 |
+                                        MPIDR_AFFINITY_LEVEL(mpidr, 3) << 16;
        }
 
        pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
diff --git a/arch/arm64/kernel/trace-events-emulation.h b/arch/arm64/kernel/trace-events-emulation.h
new file mode 100644 (file)
index 0000000..ae1dd59
--- /dev/null
@@ -0,0 +1,35 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM emulation
+
+#if !defined(_TRACE_EMULATION_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EMULATION_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(instruction_emulation,
+
+       TP_PROTO(const char *instr, u64 addr),
+       TP_ARGS(instr, addr),
+
+       TP_STRUCT__entry(
+               __string(instr, instr)
+               __field(u64, addr)
+       ),
+
+       TP_fast_assign(
+               __assign_str(instr, instr);
+               __entry->addr = addr;
+       ),
+
+       TP_printk("instr=\"%s\" addr=0x%llx", __get_str(instr), __entry->addr)
+);
+
+#endif /* _TRACE_EMULATION_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+
+#define TRACE_INCLUDE_FILE trace-events-emulation
+#include <trace/define_trace.h>
index de1b085e796396be5f6ce6c5932a3e418ade432e..0a801e3743d5df0e793954d0077b0865fb15c290 100644 (file)
@@ -259,6 +259,69 @@ void arm64_notify_die(const char *str, struct pt_regs *regs,
        }
 }
 
+static LIST_HEAD(undef_hook);
+static DEFINE_RAW_SPINLOCK(undef_lock);
+
+void register_undef_hook(struct undef_hook *hook)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&undef_lock, flags);
+       list_add(&hook->node, &undef_hook);
+       raw_spin_unlock_irqrestore(&undef_lock, flags);
+}
+
+void unregister_undef_hook(struct undef_hook *hook)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&undef_lock, flags);
+       list_del(&hook->node);
+       raw_spin_unlock_irqrestore(&undef_lock, flags);
+}
+
+static int call_undef_hook(struct pt_regs *regs)
+{
+       struct undef_hook *hook;
+       unsigned long flags;
+       u32 instr;
+       int (*fn)(struct pt_regs *regs, u32 instr) = NULL;
+       void __user *pc = (void __user *)instruction_pointer(regs);
+
+       if (!user_mode(regs))
+               return 1;
+
+       if (compat_thumb_mode(regs)) {
+               /* 16-bit Thumb instruction */
+               if (get_user(instr, (u16 __user *)pc))
+                       goto exit;
+               instr = le16_to_cpu(instr);
+               if (aarch32_insn_is_wide(instr)) {
+                       u32 instr2;
+
+                       if (get_user(instr2, (u16 __user *)(pc + 2)))
+                               goto exit;
+                       instr2 = le16_to_cpu(instr2);
+                       instr = (instr << 16) | instr2;
+               }
+       } else {
+               /* 32-bit ARM instruction */
+               if (get_user(instr, (u32 __user *)pc))
+                       goto exit;
+               instr = le32_to_cpu(instr);
+       }
+
+       raw_spin_lock_irqsave(&undef_lock, flags);
+       list_for_each_entry(hook, &undef_hook, node)
+               if ((instr & hook->instr_mask) == hook->instr_val &&
+                       (regs->pstate & hook->pstate_mask) == hook->pstate_val)
+                       fn = hook->fn;
+
+       raw_spin_unlock_irqrestore(&undef_lock, flags);
+exit:
+       return fn ? fn(regs, instr) : 1;
+}
+
 asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 {
        siginfo_t info;
@@ -268,6 +331,9 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
        if (!aarch32_break_handler(regs))
                return;
 
+       if (call_undef_hook(regs) == 0)
+               return;
+
        if (show_unhandled_signals && unhandled_signal(current, SIGILL) &&
            printk_ratelimit()) {
                pr_info("%s[%d]: undefined instruction: pc=%p\n",
index edf8715ba39b5b3486776afd1cdccd90666a8702..9965ec87cbecfcac284eddc4459bda6adab0c368 100644 (file)
@@ -11,8 +11,9 @@
 
 #include "image.h"
 
-#define ARM_EXIT_KEEP(x)
-#define ARM_EXIT_DISCARD(x)    x
+/* .exit.text needed in case of alternative patching */
+#define ARM_EXIT_KEEP(x)       x
+#define ARM_EXIT_DISCARD(x)
 
 OUTPUT_ARCH(aarch64)
 ENTRY(_text)
@@ -32,6 +33,22 @@ jiffies = jiffies_64;
        *(.hyp.text)                                    \
        VMLINUX_SYMBOL(__hyp_text_end) = .;
 
+/*
+ * The size of the PE/COFF section that covers the kernel image, which
+ * runs from stext to _edata, must be a round multiple of the PE/COFF
+ * FileAlignment, which we set to its minimum value of 0x200. 'stext'
+ * itself is 4 KB aligned, so padding out _edata to a 0x200 aligned
+ * boundary should be sufficient.
+ */
+PECOFF_FILE_ALIGNMENT = 0x200;
+
+#ifdef CONFIG_EFI
+#define PECOFF_EDATA_PADDING   \
+       .pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
+#else
+#define PECOFF_EDATA_PADDING
+#endif
+
 SECTIONS
 {
        /*
@@ -100,9 +117,21 @@ SECTIONS
        . = ALIGN(PAGE_SIZE);
        __init_end = .;
 
+       . = ALIGN(4);
+       .altinstructions : {
+               __alt_instructions = .;
+               *(.altinstructions)
+               __alt_instructions_end = .;
+       }
+       .altinstr_replacement : {
+               *(.altinstr_replacement)
+       }
+
+       . = ALIGN(PAGE_SIZE);
        _data = .;
        _sdata = .;
        RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
+       PECOFF_EDATA_PADDING
        _edata = .;
 
        BSS_SECTION(0, 0, 0)
index b72aa9f9215ca7d658390e3a368d5be39415b834..fbe909fb0a1a8b95ab4f6e3ade19daaa21c70436 100644 (file)
 .macro activate_traps
        ldr     x2, [x0, #VCPU_HCR_EL2]
        msr     hcr_el2, x2
-       ldr     x2, =(CPTR_EL2_TTA)
+       mov     x2, #CPTR_EL2_TTA
        msr     cptr_el2, x2
 
-       ldr     x2, =(1 << 15)  // Trap CP15 Cr=15
+       mov     x2, #(1 << 15)  // Trap CP15 Cr=15
        msr     hstr_el2, x2
 
        mrs     x2, mdcr_el2
index 4cc3b719208e0a8238930d44b409b2f7c2beb9f5..3d7c2df89946cc1d1606a4b3401115f10e44ab71 100644 (file)
@@ -424,6 +424,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        /* VBAR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b0000), Op2(0b000),
          NULL, reset_val, VBAR_EL1, 0 },
+
+       /* ICC_SRE_EL1 */
+       { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
+         trap_raz_wi },
+
        /* CONTEXTIDR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
          access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
@@ -690,6 +695,10 @@ static const struct sys_reg_desc cp15_regs[] = {
        { Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR },
        { Op1( 0), CRn(10), CRm( 3), Op2( 0), access_vm_reg, NULL, c10_AMAIR0 },
        { Op1( 0), CRn(10), CRm( 3), Op2( 1), access_vm_reg, NULL, c10_AMAIR1 },
+
+       /* ICC_SRE */
+       { Op1( 0), CRn(12), CRm(12), Op2( 5), trap_raz_wi },
+
        { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
 };
 
index 6e0ed93d51fe1850ee27176fc9222dac5416b74d..c17967fdf5f6007330ba65beb7a05bd347600764 100644 (file)
@@ -46,7 +46,7 @@ USER(9f, strh wzr, [x0], #2   )
        sub     x1, x1, #2
 4:     adds    x1, x1, #1
        b.mi    5f
-       strb    wzr, [x0]
+USER(9f, strb  wzr, [x0]       )
 5:     mov     x0, #0
        ret
 ENDPROC(__clear_user)
index c56179ed2c09af1d96b4f8df1b42d2ce6a67ab27..773d37a14039d9bb456f0896e022c4a3e1415773 100644 (file)
@@ -3,3 +3,4 @@ obj-y                           := dma-mapping.o extable.o fault.o init.o \
                                   ioremap.o mmap.o pgd.o mmu.o \
                                   context.o proc.o pageattr.o
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
+obj-$(CONFIG_ARM64_PTDUMP)     += dump.o
index 23663837acff5e61c15cb9a3342c414c3fb710b1..2560e1e1562e764f03fe8fa9925466f18653199d 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/errno.h>
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative-asm.h>
 
 #include "proc-macros.S"
 
@@ -138,9 +141,12 @@ USER(9f, ic        ivau, x4        )               // invalidate I line PoU
        add     x4, x4, x2
        cmp     x4, x1
        b.lo    1b
-9:                                             // ignore any faulting cache operation
        dsb     ish
        isb
+       mov     x0, #0
+       ret
+9:
+       mov     x0, #-EFAULT
        ret
 ENDPROC(flush_icache_range)
 ENDPROC(__flush_cache_user_range)
@@ -210,7 +216,7 @@ __dma_clean_range:
        dcache_line_size x2, x3
        sub     x3, x2, #1
        bic     x0, x0, x3
-1:     dc      cvac, x0                        // clean D / U line
+1:     alternative_insn "dc cvac, x0", "dc civac, x0", ARM64_WORKAROUND_CLEAN_CACHE
        add     x0, x0, x2
        cmp     x0, x1
        b.lo    1b
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
new file mode 100644 (file)
index 0000000..bf69601
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Debug helper to dump the current kernel pagetables of the system
+ * so that we can see what the various memory ranges are set to.
+ *
+ * Derived from x86 and arm implementation:
+ * (C) Copyright 2008 Intel Corporation
+ *
+ * Author: Arjan van de Ven <arjan@linux.intel.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.
+ */
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+
+#define LOWEST_ADDR    (UL(0xffffffffffffffff) << VA_BITS)
+
+struct addr_marker {
+       unsigned long start_address;
+       const char *name;
+};
+
+enum address_markers_idx {
+       VMALLOC_START_NR = 0,
+       VMALLOC_END_NR,
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+       VMEMMAP_START_NR,
+       VMEMMAP_END_NR,
+#endif
+       PCI_START_NR,
+       PCI_END_NR,
+       FIXADDR_START_NR,
+       FIXADDR_END_NR,
+       MODULES_START_NR,
+       MODUELS_END_NR,
+       KERNEL_SPACE_NR,
+};
+
+static struct addr_marker address_markers[] = {
+       { VMALLOC_START,        "vmalloc() Area" },
+       { VMALLOC_END,          "vmalloc() End" },
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+       { 0,                    "vmemmap start" },
+       { 0,                    "vmemmap end" },
+#endif
+       { (unsigned long) PCI_IOBASE,           "PCI I/O start" },
+       { (unsigned long) PCI_IOBASE + SZ_16M,  "PCI I/O end" },
+       { FIXADDR_START,        "Fixmap start" },
+       { FIXADDR_TOP,          "Fixmap end" },
+       { MODULES_VADDR,        "Modules start" },
+       { MODULES_END,          "Modules end" },
+       { PAGE_OFFSET,          "Kernel Mapping" },
+       { -1,                   NULL },
+};
+
+struct pg_state {
+       struct seq_file *seq;
+       const struct addr_marker *marker;
+       unsigned long start_address;
+       unsigned level;
+       u64 current_prot;
+};
+
+struct prot_bits {
+       u64             mask;
+       u64             val;
+       const char      *set;
+       const char      *clear;
+};
+
+static const struct prot_bits pte_bits[] = {
+       {
+               .mask   = PTE_USER,
+               .val    = PTE_USER,
+               .set    = "USR",
+               .clear  = "   ",
+       }, {
+               .mask   = PTE_RDONLY,
+               .val    = PTE_RDONLY,
+               .set    = "ro",
+               .clear  = "RW",
+       }, {
+               .mask   = PTE_PXN,
+               .val    = PTE_PXN,
+               .set    = "NX",
+               .clear  = "x ",
+       }, {
+               .mask   = PTE_SHARED,
+               .val    = PTE_SHARED,
+               .set    = "SHD",
+               .clear  = "   ",
+       }, {
+               .mask   = PTE_AF,
+               .val    = PTE_AF,
+               .set    = "AF",
+               .clear  = "  ",
+       }, {
+               .mask   = PTE_NG,
+               .val    = PTE_NG,
+               .set    = "NG",
+               .clear  = "  ",
+       }, {
+               .mask   = PTE_UXN,
+               .val    = PTE_UXN,
+               .set    = "UXN",
+       }, {
+               .mask   = PTE_ATTRINDX_MASK,
+               .val    = PTE_ATTRINDX(MT_DEVICE_nGnRnE),
+               .set    = "DEVICE/nGnRnE",
+       }, {
+               .mask   = PTE_ATTRINDX_MASK,
+               .val    = PTE_ATTRINDX(MT_DEVICE_nGnRE),
+               .set    = "DEVICE/nGnRE",
+       }, {
+               .mask   = PTE_ATTRINDX_MASK,
+               .val    = PTE_ATTRINDX(MT_DEVICE_GRE),
+               .set    = "DEVICE/GRE",
+       }, {
+               .mask   = PTE_ATTRINDX_MASK,
+               .val    = PTE_ATTRINDX(MT_NORMAL_NC),
+               .set    = "MEM/NORMAL-NC",
+       }, {
+               .mask   = PTE_ATTRINDX_MASK,
+               .val    = PTE_ATTRINDX(MT_NORMAL),
+               .set    = "MEM/NORMAL",
+       }
+};
+
+struct pg_level {
+       const struct prot_bits *bits;
+       size_t num;
+       u64 mask;
+};
+
+static struct pg_level pg_level[] = {
+       {
+       }, { /* pgd */
+               .bits   = pte_bits,
+               .num    = ARRAY_SIZE(pte_bits),
+       }, { /* pud */
+               .bits   = pte_bits,
+               .num    = ARRAY_SIZE(pte_bits),
+       }, { /* pmd */
+               .bits   = pte_bits,
+               .num    = ARRAY_SIZE(pte_bits),
+       }, { /* pte */
+               .bits   = pte_bits,
+               .num    = ARRAY_SIZE(pte_bits),
+       },
+};
+
+static void dump_prot(struct pg_state *st, const struct prot_bits *bits,
+                       size_t num)
+{
+       unsigned i;
+
+       for (i = 0; i < num; i++, bits++) {
+               const char *s;
+
+               if ((st->current_prot & bits->mask) == bits->val)
+                       s = bits->set;
+               else
+                       s = bits->clear;
+
+               if (s)
+                       seq_printf(st->seq, " %s", s);
+       }
+}
+
+static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
+                               u64 val)
+{
+       static const char units[] = "KMGTPE";
+       u64 prot = val & pg_level[level].mask;
+
+       if (addr < LOWEST_ADDR)
+               return;
+
+       if (!st->level) {
+               st->level = level;
+               st->current_prot = prot;
+               st->start_address = addr;
+               seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+       } else if (prot != st->current_prot || level != st->level ||
+                  addr >= st->marker[1].start_address) {
+               const char *unit = units;
+               unsigned long delta;
+
+               if (st->current_prot) {
+                       seq_printf(st->seq, "0x%16lx-0x%16lx   ",
+                                  st->start_address, addr);
+
+                       delta = (addr - st->start_address) >> 10;
+                       while (!(delta & 1023) && unit[1]) {
+                               delta >>= 10;
+                               unit++;
+                       }
+                       seq_printf(st->seq, "%9lu%c", delta, *unit);
+                       if (pg_level[st->level].bits)
+                               dump_prot(st, pg_level[st->level].bits,
+                                         pg_level[st->level].num);
+                       seq_puts(st->seq, "\n");
+               }
+
+               if (addr >= st->marker[1].start_address) {
+                       st->marker++;
+                       seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+               }
+
+               st->start_address = addr;
+               st->current_prot = prot;
+               st->level = level;
+       }
+
+       if (addr >= st->marker[1].start_address) {
+               st->marker++;
+               seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+       }
+
+}
+
+static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
+{
+       pte_t *pte = pte_offset_kernel(pmd, 0);
+       unsigned long addr;
+       unsigned i;
+
+       for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
+               addr = start + i * PAGE_SIZE;
+               note_page(st, addr, 4, pte_val(*pte));
+       }
+}
+
+static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
+{
+       pmd_t *pmd = pmd_offset(pud, 0);
+       unsigned long addr;
+       unsigned i;
+
+       for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
+               addr = start + i * PMD_SIZE;
+               if (pmd_none(*pmd) || pmd_sect(*pmd) || pmd_bad(*pmd))
+                       note_page(st, addr, 3, pmd_val(*pmd));
+               else
+                       walk_pte(st, pmd, addr);
+       }
+}
+
+static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
+{
+       pud_t *pud = pud_offset(pgd, 0);
+       unsigned long addr;
+       unsigned i;
+
+       for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
+               addr = start + i * PUD_SIZE;
+               if (pud_none(*pud) || pud_sect(*pud) || pud_bad(*pud))
+                       note_page(st, addr, 2, pud_val(*pud));
+               else
+                       walk_pmd(st, pud, addr);
+       }
+}
+
+static void walk_pgd(struct pg_state *st, struct mm_struct *mm, unsigned long start)
+{
+       pgd_t *pgd = pgd_offset(mm, 0);
+       unsigned i;
+       unsigned long addr;
+
+       for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
+               addr = start + i * PGDIR_SIZE;
+               if (pgd_none(*pgd) || pgd_bad(*pgd))
+                       note_page(st, addr, 1, pgd_val(*pgd));
+               else
+                       walk_pud(st, pgd, addr);
+       }
+}
+
+static int ptdump_show(struct seq_file *m, void *v)
+{
+       struct pg_state st = {
+               .seq = m,
+               .marker = address_markers,
+       };
+
+       walk_pgd(&st, &init_mm, LOWEST_ADDR);
+
+       note_page(&st, 0, 0, 0);
+       return 0;
+}
+
+static int ptdump_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ptdump_show, NULL);
+}
+
+static const struct file_operations ptdump_fops = {
+       .open           = ptdump_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int ptdump_init(void)
+{
+       struct dentry *pe;
+       unsigned i, j;
+
+       for (i = 0; i < ARRAY_SIZE(pg_level); i++)
+               if (pg_level[i].bits)
+                       for (j = 0; j < pg_level[i].num; j++)
+                               pg_level[i].mask |= pg_level[i].bits[j].mask;
+
+       address_markers[VMEMMAP_START_NR].start_address =
+                               (unsigned long)virt_to_page(PAGE_OFFSET);
+       address_markers[VMEMMAP_END_NR].start_address =
+                               (unsigned long)virt_to_page(high_memory);
+
+       pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
+                                &ptdump_fops);
+       return pe ? 0 : -ENOMEM;
+}
+device_initcall(ptdump_init);
index 41cb6d3d607582043fa3a0a6caf6469d8e73b159..c11cd27ca8f580c1ab5cb6482e79c6d36f75af22 100644 (file)
@@ -380,7 +380,7 @@ static struct fault_info {
        { do_bad,               SIGBUS,  0,             "level 1 address size fault"    },
        { do_bad,               SIGBUS,  0,             "level 2 address size fault"    },
        { do_bad,               SIGBUS,  0,             "level 3 address size fault"    },
-       { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "input address range fault"     },
+       { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 0 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 1 translation fault"     },
        { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "level 2 translation fault"     },
        { do_page_fault,        SIGSEGV, SEGV_MAPERR,   "level 3 translation fault"     },
index 494297c698ca3966b3b1e94f747652e3e493476b..bac492c12fcc4bd054e09f8db8022b64dcaa8f74 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/setup.h>
 #include <asm/sizes.h>
 #include <asm/tlb.h>
+#include <asm/alternative.h>
 
 #include "mm.h"
 
@@ -325,6 +326,7 @@ void __init mem_init(void)
 void free_initmem(void)
 {
        free_initmem_default(0);
+       free_alternatives_memory();
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
index fa324bd5a5c42b4feb616a321a61c599c903488f..cbb99c8f1e04368f0da27e11868df06b5cfdea70 100644 (file)
@@ -103,97 +103,10 @@ void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
 }
 EXPORT_SYMBOL(ioremap_cache);
 
-static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
-#if CONFIG_ARM64_PGTABLE_LEVELS > 2
-static pte_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
-#endif
-#if CONFIG_ARM64_PGTABLE_LEVELS > 3
-static pte_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
-#endif
-
-static inline pud_t * __init early_ioremap_pud(unsigned long addr)
-{
-       pgd_t *pgd;
-
-       pgd = pgd_offset_k(addr);
-       BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
-
-       return pud_offset(pgd, addr);
-}
-
-static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
-{
-       pud_t *pud = early_ioremap_pud(addr);
-
-       BUG_ON(pud_none(*pud) || pud_bad(*pud));
-
-       return pmd_offset(pud, addr);
-}
-
-static inline pte_t * __init early_ioremap_pte(unsigned long addr)
-{
-       pmd_t *pmd = early_ioremap_pmd(addr);
-
-       BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd));
-
-       return pte_offset_kernel(pmd, addr);
-}
-
+/*
+ * Must be called after early_fixmap_init
+ */
 void __init early_ioremap_init(void)
 {
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       unsigned long addr = fix_to_virt(FIX_BTMAP_BEGIN);
-
-       pgd = pgd_offset_k(addr);
-       pgd_populate(&init_mm, pgd, bm_pud);
-       pud = pud_offset(pgd, addr);
-       pud_populate(&init_mm, pud, bm_pmd);
-       pmd = pmd_offset(pud, addr);
-       pmd_populate_kernel(&init_mm, pmd, bm_pte);
-
-       /*
-        * The boot-ioremap range spans multiple pmds, for which
-        * we are not prepared:
-        */
-       BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
-                    != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
-
-       if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
-               WARN_ON(1);
-               pr_warn("pmd %p != %p\n",
-                       pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
-               pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
-                       fix_to_virt(FIX_BTMAP_BEGIN));
-               pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
-                       fix_to_virt(FIX_BTMAP_END));
-
-               pr_warn("FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
-               pr_warn("FIX_BTMAP_BEGIN:     %d\n",
-                       FIX_BTMAP_BEGIN);
-       }
-
        early_ioremap_setup();
 }
-
-void __init __early_set_fixmap(enum fixed_addresses idx,
-                              phys_addr_t phys, pgprot_t flags)
-{
-       unsigned long addr = __fix_to_virt(idx);
-       pte_t *pte;
-
-       if (idx >= __end_of_fixed_addresses) {
-               BUG();
-               return;
-       }
-
-       pte = early_ioremap_pte(addr);
-
-       if (pgprot_val(flags))
-               set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
-       else {
-               pte_clear(&init_mm, addr, pte);
-               flush_tlb_kernel_range(addr, addr+PAGE_SIZE);
-       }
-}
index d519f4f50c8c6f5431281ee5e15346e860e9f741..50c3351df9c7ea8b1cd6dc6901bdbad6c04b9c4a 100644 (file)
@@ -1,2 +1 @@
 extern void __init bootmem_init(void);
-extern void __init arm64_swiotlb_init(void);
index 1d73662f00ff60c68db5335bce754d8c8dad34de..54922d1275b8d1db8dbc05a1dfa482146366862b 100644 (file)
@@ -47,22 +47,14 @@ static int mmap_is_legacy(void)
        return sysctl_legacy_va_layout;
 }
 
-/*
- * Since get_random_int() returns the same value within a 1 jiffy window, we
- * will almost always get the same randomisation for the stack and mmap
- * region. This will mean the relative distance between stack and mmap will be
- * the same.
- *
- * To avoid this we can shift the randomness by 1 bit.
- */
 static unsigned long mmap_rnd(void)
 {
        unsigned long rnd = 0;
 
        if (current->flags & PF_RANDOMIZE)
-               rnd = (long)get_random_int() & (STACK_RND_MASK >> 1);
+               rnd = (long)get_random_int() & STACK_RND_MASK;
 
-       return rnd << (PAGE_SHIFT + 1);
+       return rnd << PAGE_SHIFT;
 }
 
 static unsigned long mmap_base(void)
index 6894ef3e62342bb7e0f35252c03cb29faabaddc3..6032f3e3056a6c69899b06ee4c86cc22aa985893 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/io.h>
 
 #include <asm/cputype.h>
+#include <asm/fixmap.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/sizes.h>
@@ -202,7 +203,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
 }
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
-                                 unsigned long end, unsigned long phys,
+                                 unsigned long end, phys_addr_t phys,
                                  int map_io)
 {
        pud_t *pud;
@@ -297,11 +298,15 @@ static void __init map_mem(void)
         * create_mapping requires puds, pmds and ptes to be allocated from
         * memory addressable from the initial direct kernel mapping.
         *
-        * The initial direct kernel mapping, located at swapper_pg_dir,
-        * gives us PUD_SIZE memory starting from PHYS_OFFSET (which must be
-        * aligned to 2MB as per Documentation/arm64/booting.txt).
+        * The initial direct kernel mapping, located at swapper_pg_dir, gives
+        * us PUD_SIZE (4K pages) or PMD_SIZE (64K pages) memory starting from
+        * PHYS_OFFSET (which must be aligned to 2MB as per
+        * Documentation/arm64/booting.txt).
         */
-       limit = PHYS_OFFSET + PUD_SIZE;
+       if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+               limit = PHYS_OFFSET + PMD_SIZE;
+       else
+               limit = PHYS_OFFSET + PUD_SIZE;
        memblock_set_current_limit(limit);
 
        /* map all the memory banks */
@@ -459,3 +464,96 @@ void vmemmap_free(unsigned long start, unsigned long end)
 {
 }
 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
+static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
+#if CONFIG_ARM64_PGTABLE_LEVELS > 2
+static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss;
+#endif
+#if CONFIG_ARM64_PGTABLE_LEVELS > 3
+static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss;
+#endif
+
+static inline pud_t * fixmap_pud(unsigned long addr)
+{
+       pgd_t *pgd = pgd_offset_k(addr);
+
+       BUG_ON(pgd_none(*pgd) || pgd_bad(*pgd));
+
+       return pud_offset(pgd, addr);
+}
+
+static inline pmd_t * fixmap_pmd(unsigned long addr)
+{
+       pud_t *pud = fixmap_pud(addr);
+
+       BUG_ON(pud_none(*pud) || pud_bad(*pud));
+
+       return pmd_offset(pud, addr);
+}
+
+static inline pte_t * fixmap_pte(unsigned long addr)
+{
+       pmd_t *pmd = fixmap_pmd(addr);
+
+       BUG_ON(pmd_none(*pmd) || pmd_bad(*pmd));
+
+       return pte_offset_kernel(pmd, addr);
+}
+
+void __init early_fixmap_init(void)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       unsigned long addr = FIXADDR_START;
+
+       pgd = pgd_offset_k(addr);
+       pgd_populate(&init_mm, pgd, bm_pud);
+       pud = pud_offset(pgd, addr);
+       pud_populate(&init_mm, pud, bm_pmd);
+       pmd = pmd_offset(pud, addr);
+       pmd_populate_kernel(&init_mm, pmd, bm_pte);
+
+       /*
+        * The boot-ioremap range spans multiple pmds, for which
+        * we are not preparted:
+        */
+       BUILD_BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
+                    != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
+
+       if ((pmd != fixmap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)))
+            || pmd != fixmap_pmd(fix_to_virt(FIX_BTMAP_END))) {
+               WARN_ON(1);
+               pr_warn("pmd %p != %p, %p\n",
+                       pmd, fixmap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)),
+                       fixmap_pmd(fix_to_virt(FIX_BTMAP_END)));
+               pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
+                       fix_to_virt(FIX_BTMAP_BEGIN));
+               pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
+                       fix_to_virt(FIX_BTMAP_END));
+
+               pr_warn("FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
+               pr_warn("FIX_BTMAP_BEGIN:     %d\n", FIX_BTMAP_BEGIN);
+       }
+}
+
+void __set_fixmap(enum fixed_addresses idx,
+                              phys_addr_t phys, pgprot_t flags)
+{
+       unsigned long addr = __fix_to_virt(idx);
+       pte_t *pte;
+
+       if (idx >= __end_of_fixed_addresses) {
+               BUG();
+               return;
+       }
+
+       pte = fixmap_pte(addr);
+
+       if (pgprot_val(flags)) {
+               set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
+       } else {
+               pte_clear(&init_mm, addr, pte);
+               flush_tlb_kernel_range(addr, addr+PAGE_SIZE);
+       }
+}
index 62c6101df260e60ddd1084804383d2831de67ba4..71ca104f97bde3a7b9f11e2aa4e443357e2e29b9 100644 (file)
 
 #define PGD_SIZE       (PTRS_PER_PGD * sizeof(pgd_t))
 
+static struct kmem_cache *pgd_cache;
+
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        if (PGD_SIZE == PAGE_SIZE)
-               return (pgd_t *)get_zeroed_page(GFP_KERNEL);
+               return (pgd_t *)__get_free_page(PGALLOC_GFP);
        else
-               return kzalloc(PGD_SIZE, GFP_KERNEL);
+               return kmem_cache_alloc(pgd_cache, PGALLOC_GFP);
 }
 
 void pgd_free(struct mm_struct *mm, pgd_t *pgd)
@@ -43,5 +45,17 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
        if (PGD_SIZE == PAGE_SIZE)
                free_page((unsigned long)pgd);
        else
-               kfree(pgd);
+               kmem_cache_free(pgd_cache, pgd);
+}
+
+static int __init pgd_cache_init(void)
+{
+       /*
+        * Naturally aligned pgds required by the architecture.
+        */
+       if (PGD_SIZE != PAGE_SIZE)
+               pgd_cache = kmem_cache_create("pgd_cache", PGD_SIZE, PGD_SIZE,
+                                             SLAB_PANIC, NULL);
+       return 0;
 }
+core_initcall(pgd_cache_init);
index 2134f7e6c28809e5f8b68e673dcd4b1998c89d09..de0a81a539a01ca450eb53e7919216c2a1e907c2 100644 (file)
 
 /* Data-processing (2 source) */
 /* Rd = Rn OP Rm */
-#define A64_UDIV(sf, Rd, Rn, Rm) aarch64_insn_gen_data2(Rd, Rn, Rm, \
-       A64_VARIANT(sf), AARCH64_INSN_DATA2_UDIV)
+#define A64_DATA2(sf, Rd, Rn, Rm, type) aarch64_insn_gen_data2(Rd, Rn, Rm, \
+       A64_VARIANT(sf), AARCH64_INSN_DATA2_##type)
+#define A64_UDIV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, UDIV)
+#define A64_LSLV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, LSLV)
+#define A64_LSRV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, LSRV)
+#define A64_ASRV(sf, Rd, Rn, Rm) A64_DATA2(sf, Rd, Rn, Rm, ASRV)
 
 /* Data-processing (3 source) */
 /* Rd = Ra + Rn * Rm */
index 7ae33545535b96fd363d08ede9634d8ff0a30ad3..edba042b23259c6f4b642a842fc1a2eb740c59b3 100644 (file)
 #define pr_fmt(fmt) "bpf_jit: " fmt
 
 #include <linux/filter.h>
-#include <linux/moduleloader.h>
 #include <linux/printk.h>
 #include <linux/skbuff.h>
 #include <linux/slab.h>
+
 #include <asm/byteorder.h>
 #include <asm/cacheflush.h>
+#include <asm/debug-monitors.h>
 
 #include "bpf_jit.h"
 
@@ -59,7 +60,7 @@ struct jit_ctx {
        const struct bpf_prog *prog;
        int idx;
        int tmp_used;
-       int body_offset;
+       int epilogue_offset;
        int *offset;
        u32 *image;
 };
@@ -119,10 +120,18 @@ static inline int bpf2a64_offset(int bpf_to, int bpf_from,
        return to - from;
 }
 
+static void jit_fill_hole(void *area, unsigned int size)
+{
+       u32 *ptr;
+       /* We are guaranteed to have aligned memory. */
+       for (ptr = area; size >= sizeof(u32); size -= sizeof(u32))
+               *ptr++ = cpu_to_le32(AARCH64_BREAK_FAULT);
+}
+
 static inline int epilogue_offset(const struct jit_ctx *ctx)
 {
-       int to = ctx->offset[ctx->prog->len - 1];
-       int from = ctx->idx - ctx->body_offset;
+       int to = ctx->epilogue_offset;
+       int from = ctx->idx;
 
        return to - from;
 }
@@ -196,6 +205,12 @@ static void build_epilogue(struct jit_ctx *ctx)
        emit(A64_RET(A64_LR), ctx);
 }
 
+/* JITs an eBPF instruction.
+ * Returns:
+ * 0  - successfully JITed an 8-byte eBPF instruction.
+ * >0 - successfully JITed a 16-byte eBPF instruction.
+ * <0 - failed to JIT.
+ */
 static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
 {
        const u8 code = insn->code;
@@ -252,6 +267,18 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                emit(A64_MUL(is64, tmp, tmp, src), ctx);
                emit(A64_SUB(is64, dst, dst, tmp), ctx);
                break;
+       case BPF_ALU | BPF_LSH | BPF_X:
+       case BPF_ALU64 | BPF_LSH | BPF_X:
+               emit(A64_LSLV(is64, dst, dst, src), ctx);
+               break;
+       case BPF_ALU | BPF_RSH | BPF_X:
+       case BPF_ALU64 | BPF_RSH | BPF_X:
+               emit(A64_LSRV(is64, dst, dst, src), ctx);
+               break;
+       case BPF_ALU | BPF_ARSH | BPF_X:
+       case BPF_ALU64 | BPF_ARSH | BPF_X:
+               emit(A64_ASRV(is64, dst, dst, src), ctx);
+               break;
        /* dst = -dst */
        case BPF_ALU | BPF_NEG:
        case BPF_ALU64 | BPF_NEG:
@@ -436,6 +463,8 @@ emit_cond_jmp:
        }
        /* function return */
        case BPF_JMP | BPF_EXIT:
+               /* Optimization: when last instruction is EXIT,
+                  simply fallthrough to epilogue. */
                if (i == ctx->prog->len - 1)
                        break;
                jmp_offset = epilogue_offset(ctx);
@@ -443,6 +472,27 @@ emit_cond_jmp:
                emit(A64_B(jmp_offset), ctx);
                break;
 
+       /* dst = imm64 */
+       case BPF_LD | BPF_IMM | BPF_DW:
+       {
+               const struct bpf_insn insn1 = insn[1];
+               u64 imm64;
+
+               if (insn1.code != 0 || insn1.src_reg != 0 ||
+                   insn1.dst_reg != 0 || insn1.off != 0) {
+                       /* Note: verifier in BPF core must catch invalid
+                        * instructions.
+                        */
+                       pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
+                       return -EINVAL;
+               }
+
+               imm64 = (u64)insn1.imm << 32 | imm;
+               emit_a64_mov_i64(dst, imm64, ctx);
+
+               return 1;
+       }
+
        /* LDX: dst = *(size *)(src + off) */
        case BPF_LDX | BPF_MEM | BPF_W:
        case BPF_LDX | BPF_MEM | BPF_H:
@@ -594,6 +644,10 @@ static int build_body(struct jit_ctx *ctx)
                        ctx->offset[i] = ctx->idx;
 
                ret = build_insn(insn, ctx);
+               if (ret > 0) {
+                       i++;
+                       continue;
+               }
                if (ret)
                        return ret;
        }
@@ -613,8 +667,10 @@ void bpf_jit_compile(struct bpf_prog *prog)
 
 void bpf_int_jit_compile(struct bpf_prog *prog)
 {
+       struct bpf_binary_header *header;
        struct jit_ctx ctx;
        int image_size;
+       u8 *image_ptr;
 
        if (!bpf_jit_enable)
                return;
@@ -631,28 +687,31 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
 
        /* 1. Initial fake pass to compute ctx->idx. */
 
-       /* Fake pass to fill in ctx->offset. */
+       /* Fake pass to fill in ctx->offset and ctx->tmp_used. */
        if (build_body(&ctx))
                goto out;
 
        build_prologue(&ctx);
 
+       ctx.epilogue_offset = ctx.idx;
        build_epilogue(&ctx);
 
        /* Now we know the actual image size. */
        image_size = sizeof(u32) * ctx.idx;
-       ctx.image = module_alloc(image_size);
-       if (unlikely(ctx.image == NULL))
+       header = bpf_jit_binary_alloc(image_size, &image_ptr,
+                                     sizeof(u32), jit_fill_hole);
+       if (header == NULL)
                goto out;
 
        /* 2. Now, the actual pass. */
 
+       ctx.image = (u32 *)image_ptr;
        ctx.idx = 0;
+
        build_prologue(&ctx);
 
-       ctx.body_offset = ctx.idx;
        if (build_body(&ctx)) {
-               module_free(NULL, ctx.image);
+               bpf_jit_binary_free(header);
                goto out;
        }
 
@@ -663,17 +722,25 @@ void bpf_int_jit_compile(struct bpf_prog *prog)
                bpf_jit_dump(prog->len, image_size, 2, ctx.image);
 
        bpf_flush_icache(ctx.image, ctx.image + ctx.idx);
-       prog->bpf_func = (void *)ctx.image;
-       prog->jited = 1;
 
+       set_memory_ro((unsigned long)header, header->pages);
+       prog->bpf_func = (void *)ctx.image;
+       prog->jited = true;
 out:
        kfree(ctx.offset);
 }
 
 void bpf_jit_free(struct bpf_prog *prog)
 {
-       if (prog->jited)
-               module_free(NULL, prog->bpf_func);
+       unsigned long addr = (unsigned long)prog->bpf_func & PAGE_MASK;
+       struct bpf_binary_header *header = (void *)addr;
+
+       if (!prog->jited)
+               goto free_filter;
+
+       set_memory_rw(addr, header->pages);
+       bpf_jit_binary_free(header);
 
-       kfree(prog);
+free_filter:
+       bpf_prog_unlock_free(prog);
 }
index 37b75602adf60e382587dd3b118eaae5ad03d02e..cc92cdb9994c8850f36c146d2a77f68b60d1e8a5 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/spi/spi.h>
 #include <linux/usb/atmel_usba_udc.h>
 
-#include <mach/atmel-mci.h>
+#include <linux/platform_data/mmc-atmel-mci.h>
 #include <linux/atmel-mci.h>
 
 #include <asm/io.h>
diff --git a/arch/avr32/mach-at32ap/include/mach/atmel-mci.h b/arch/avr32/mach-at32ap/include/mach/atmel-mci.h
deleted file mode 100644 (file)
index 11d7f4b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __MACH_ATMEL_MCI_H
-#define __MACH_ATMEL_MCI_H
-
-#include <linux/platform_data/dma-dw.h>
-
-/**
- * struct mci_dma_data - DMA data for MCI interface
- */
-struct mci_dma_data {
-       struct dw_dma_slave     sdata;
-};
-
-/* accessor macros */
-#define        slave_data_ptr(s)       (&(s)->sdata)
-#define find_slave_dev(s)      ((s)->sdata.dma_dev)
-
-#endif /* __MACH_ATMEL_MCI_H */
index e59dba12ce9476d0888e3150137274c23ea0ab0f..752a3f45df60cd475b51b21bb567b9bd48f90581 100644 (file)
@@ -112,6 +112,9 @@ static inline void writel(unsigned int b, volatile void __iomem *addr)
        else
                *(volatile unsigned int __force *) addr = b;
 }
+#define writeb_relaxed(b, addr) writeb(b, addr)
+#define writew_relaxed(b, addr) writew(b, addr)
+#define writel_relaxed(b, addr) writel(b, addr)
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
index 8cb50a2fbcb2d9b34b6bad36323cb49513f64ceb..99bb7efaf9b7ec458762cd3f5016a92949a44987 100644 (file)
@@ -243,6 +243,9 @@ static inline void writel(uint32_t datum, volatile void __iomem *addr)
                __flush_PCI_writes();
 }
 
+#define writeb_relaxed writeb
+#define writew_relaxed writew
+#define writel_relaxed writel
 
 /* Values for nocacheflag and cmode */
 #define IOMAP_FULL_CACHING             0
index bee0acd52f7e3d603ec87ce87ec3843b1efe55bd..80a7e34be00984a104923d933eafa7faa0d937fc 100644 (file)
@@ -393,6 +393,10 @@ __writeq (unsigned long val, volatile void __iomem *addr)
 #define writew(v,a)    __writew((v), (a))
 #define writel(v,a)    __writel((v), (a))
 #define writeq(v,a)    __writeq((v), (a))
+#define writeb_relaxed(v,a)    __writeb((v), (a))
+#define writew_relaxed(v,a)    __writew((v), (a))
+#define writel_relaxed(v,a)    __writel((v), (a))
+#define writeq_relaxed(v,a)    __writeq((v), (a))
 #define __raw_writeb   writeb
 #define __raw_writew   writew
 #define __raw_writel   writel
index 449c8c0fa2bdc65165ff62248fdb4dbf8cba129e..103bedc59644a65a90d76d51b85c586478ef0e01 100644 (file)
@@ -365,15 +365,15 @@ ia64_done_with_exception (struct pt_regs *regs)
 }
 
 #define ARCH_HAS_TRANSLATE_MEM_PTR     1
-static __inline__ char *
-xlate_dev_mem_ptr (unsigned long p)
+static __inline__ void *
+xlate_dev_mem_ptr(phys_addr_t p)
 {
        struct page *page;
-       char * ptr;
+       void *ptr;
 
        page = pfn_to_page(p >> PAGE_SHIFT);
        if (PageUncached(page))
-               ptr = (char *)p + __IA64_UNCACHED_OFFSET;
+               ptr = (void *)p + __IA64_UNCACHED_OFFSET;
        else
                ptr = __va(p);
 
@@ -383,15 +383,15 @@ xlate_dev_mem_ptr (unsigned long p)
 /*
  * Convert a virtual cached kernel memory pointer to an uncached pointer
  */
-static __inline__ char *
-xlate_dev_kmem_ptr (char * p)
+static __inline__ void *
+xlate_dev_kmem_ptr(void *p)
 {
        struct page *page;
-       char * ptr;
+       void *ptr;
 
        page = virt_to_page((unsigned long)p);
        if (PageUncached(page))
-               ptr = (char *)__pa(p) + __IA64_UNCACHED_OFFSET;
+               ptr = (void *)__pa(p) + __IA64_UNCACHED_OFFSET;
        else
                ptr = p;
 
index 741b99c1a0b1483b153be8823ae681a141d71bf5..c52d7540dc05f4c8ca324e0f6f9ce118f9570d71 100644 (file)
@@ -568,6 +568,7 @@ efi_init (void)
                {
                        const char *unit;
                        unsigned long size;
+                       char buf[64];
 
                        md = p;
                        size = md->num_pages << EFI_PAGE_SHIFT;
@@ -586,9 +587,10 @@ efi_init (void)
                                unit = "KB";
                        }
 
-                       printk("mem%02d: type=%2u, attr=0x%016lx, "
+                       printk("mem%02d: %s "
                               "range=[0x%016lx-0x%016lx) (%4lu%s)\n",
-                              i, md->type, md->attribute, md->phys_addr,
+                              i, efi_md_typeattr_format(buf, sizeof(buf), md),
+                              md->phys_addr,
                               md->phys_addr + efi_md_size(md), size, unit);
                }
        }
index ec6b9acb6bea8733a5f17bd7afe4a0a249ff4de9..dbe46f43884df183a69a2da387a941f55dbb371d 100644 (file)
@@ -1563,7 +1563,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 
        for (i = 0; i < npages; i++) {
                pfn = gfn_to_pfn(kvm, base_gfn + i);
-               if (!kvm_is_mmio_pfn(pfn)) {
+               if (!kvm_is_reserved_pfn(pfn)) {
                        kvm_set_pmt_entry(kvm, base_gfn + i,
                                        pfn << PAGE_SHIFT,
                                _PAGE_AR_RWX | _PAGE_MA_WB);
index 4010f1fc5b65ba1fc01217f071d897af5a33c125..6e7787f3dac7bb52f87ec33378193b14f65bf70c 100644 (file)
@@ -161,6 +161,9 @@ static inline void _writel(unsigned long l, unsigned long addr)
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
+#define writeb_relaxed writeb
+#define writew_relaxed writew
+#define writel_relaxed writel
 
 #define ioread8 read
 #define ioread16 readw
index 01a62161b08a1a69a74635de7004e4e65c73bf20..192b00f098f4367c74bdbcec5717077d22d32589 100644 (file)
@@ -858,6 +858,24 @@ static struct platform_device *atari_netusbee_devices[] __initdata = {
 };
 #endif /* CONFIG_ATARI_ETHERNEC */
 
+#ifdef CONFIG_ATARI_SCSI
+static const struct resource atari_scsi_st_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = IRQ_MFP_FSCSI,
+               .end   = IRQ_MFP_FSCSI,
+       },
+};
+
+static const struct resource atari_scsi_tt_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = IRQ_TT_MFP_SCSI,
+               .end   = IRQ_TT_MFP_SCSI,
+       },
+};
+#endif
+
 int __init atari_platform_init(void)
 {
        int rv = 0;
@@ -892,6 +910,15 @@ int __init atari_platform_init(void)
        }
 #endif
 
+#ifdef CONFIG_ATARI_SCSI
+       if (ATARIHW_PRESENT(ST_SCSI))
+               platform_device_register_simple("atari_scsi", -1,
+                       atari_scsi_st_rsrc, ARRAY_SIZE(atari_scsi_st_rsrc));
+       else if (ATARIHW_PRESENT(TT_SCSI))
+               platform_device_register_simple("atari_scsi", -1,
+                       atari_scsi_tt_rsrc, ARRAY_SIZE(atari_scsi_tt_rsrc));
+#endif
+
        return rv;
 }
 
index ddbf43ca8858012470d7f20665e89e85f5a045f3..e5a66596b116dc7642700aa62638318c73cca135 100644 (file)
@@ -59,6 +59,31 @@ static irqreturn_t stdma_int (int irq, void *dummy);
 /************************* End of Prototypes **************************/
 
 
+/**
+ * stdma_try_lock - attempt to acquire ST DMA interrupt "lock"
+ * @handler: interrupt handler to use after acquisition
+ *
+ * Returns !0 if lock was acquired; otherwise 0.
+ */
+
+int stdma_try_lock(irq_handler_t handler, void *data)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (stdma_locked) {
+               local_irq_restore(flags);
+               return 0;
+       }
+
+       stdma_locked   = 1;
+       stdma_isr      = handler;
+       stdma_isr_data = data;
+       local_irq_restore(flags);
+       return 1;
+}
+EXPORT_SYMBOL(stdma_try_lock);
+
 
 /*
  * Function: void stdma_lock( isrfunc isr, void *data )
@@ -78,19 +103,10 @@ static irqreturn_t stdma_int (int irq, void *dummy);
 
 void stdma_lock(irq_handler_t handler, void *data)
 {
-       unsigned long flags;
-
-       local_irq_save(flags);          /* protect lock */
-
        /* Since the DMA is used for file system purposes, we
         have to sleep uninterruptible (there may be locked
         buffers) */
-       wait_event(stdma_wait, !stdma_locked);
-
-       stdma_locked   = 1;
-       stdma_isr      = handler;
-       stdma_isr_data = data;
-       local_irq_restore(flags);
+       wait_event(stdma_wait, stdma_try_lock(handler, data));
 }
 EXPORT_SYMBOL(stdma_lock);
 
@@ -122,22 +138,25 @@ void stdma_release(void)
 EXPORT_SYMBOL(stdma_release);
 
 
-/*
- * Function: int stdma_others_waiting( void )
- *
- * Purpose: Check if someone waits for the ST-DMA lock.
- *
- * Inputs: none
- *
- * Returns: 0 if no one is waiting, != 0 otherwise
+/**
+ * stdma_is_locked_by - allow lock holder to check whether it needs to release.
+ * @handler: interrupt handler previously used to acquire lock.
  *
+ * Returns !0 if locked for the given handler; 0 otherwise.
  */
 
-int stdma_others_waiting(void)
+int stdma_is_locked_by(irq_handler_t handler)
 {
-       return waitqueue_active(&stdma_wait);
+       unsigned long flags;
+       int result;
+
+       local_irq_save(flags);
+       result = stdma_locked && (stdma_isr == handler);
+       local_irq_restore(flags);
+
+       return result;
 }
-EXPORT_SYMBOL(stdma_others_waiting);
+EXPORT_SYMBOL(stdma_is_locked_by);
 
 
 /*
index 8e389b7fa70c88ff3db422de4bfa7c2306d098ce..d24e34d870dc4c4a25bc450e3b218c298ce6cbed 100644 (file)
@@ -8,11 +8,11 @@
 
 /***************************** Prototypes *****************************/
 
+int stdma_try_lock(irq_handler_t, void *);
 void stdma_lock(irq_handler_t handler, void *data);
 void stdma_release( void );
-int stdma_others_waiting( void );
 int stdma_islocked( void );
-void *stdma_locked_by( void );
+int stdma_is_locked_by(irq_handler_t);
 void stdma_init( void );
 
 /************************* End of Prototypes **************************/
index c70cc91550037c4e5e9317bd79e2d40056913b1e..bccd5a914eb6fc6c733990141f8e78f60391efda 100644 (file)
@@ -3,3 +3,11 @@
 #else
 #include <asm/io_mm.h>
 #endif
+
+#define readb_relaxed(addr)    readb(addr)
+#define readw_relaxed(addr)    readw(addr)
+#define readl_relaxed(addr)    readl(addr)
+
+#define writeb_relaxed(b, addr)        writeb(b, addr)
+#define writew_relaxed(b, addr)        writew(b, addr)
+#define writel_relaxed(b, addr)        writel(b, addr)
index be4b5a813ad401972624886802f5f69aa047e7dc..a93c8cde4d382fc171798affe7090cc59a60f46d 100644 (file)
@@ -40,10 +40,6 @@ static inline unsigned int _swapl(volatile unsigned long v)
 #define readl(addr) \
     ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
 
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-
 #define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
 #define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
 #define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
index d323b2c2d07d4e9a574da7e7f97d7a21bca08b6f..29c7c6c3a5f2055423f91911dba42049e6a1e876 100644 (file)
@@ -53,6 +53,10 @@ struct mac_model
 #define MAC_SCSI_QUADRA                2
 #define MAC_SCSI_QUADRA2       3
 #define MAC_SCSI_QUADRA3       4
+#define MAC_SCSI_IIFX          5
+#define MAC_SCSI_DUO           6
+#define MAC_SCSI_CCL           7
+#define MAC_SCSI_LATE          8
 
 #define MAC_IDE_NONE           0
 #define MAC_IDE_QUADRA         1
index 4ef7a54813e6b72d88a0d40109a26347b91aa7c6..75e75d7b1702fb6434c59e9155dbba1d71623b17 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            354
+#define NR_syscalls            355
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index b419c6b7ac3739b150000dfd13aff28d3dcc372a..2c1bec9a14b67da42a8ed09b644373d0cf35b5ef 100644 (file)
 #define __NR_renameat2         351
 #define __NR_getrandom         352
 #define __NR_memfd_create      353
+#define __NR_bpf               354
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index 05b46c2b08b8d8d4be26c56e8be4d245cef3dab6..2ca219e184cd16e6ebad1bd9123061695691c843 100644 (file)
@@ -374,4 +374,5 @@ ENTRY(sys_call_table)
        .long sys_renameat2
        .long sys_getrandom
        .long sys_memfd_create
+       .long sys_bpf
 
index a471eab1a4dda8d65214df570da554b9be44e378..e9c3756139fc0e4130a4570d22148383f6344f61 100644 (file)
@@ -278,7 +278,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "IIfx",
                .adb_type       = MAC_ADB_IOP,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_IIFX,
                .scc_type       = MAC_SCC_IOP,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_IOP,
@@ -329,7 +329,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "Color Classic",
                .adb_type       = MAC_ADB_CUDA,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_CCL,
                .scc_type       = MAC_SCC_II,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -338,7 +338,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "Color Classic II",
                .adb_type       = MAC_ADB_CUDA,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_CCL,
                .scc_type       = MAC_SCC_II,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -526,7 +526,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "Performa 520",
                .adb_type       = MAC_ADB_CUDA,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_CCL,
                .scc_type       = MAC_SCC_II,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -535,7 +535,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "Performa 550",
                .adb_type       = MAC_ADB_CUDA,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_CCL,
                .scc_type       = MAC_SCC_II,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -567,7 +567,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "TV",
                .adb_type       = MAC_ADB_CUDA,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_CCL,
                .scc_type       = MAC_SCC_II,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -712,7 +712,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook 190",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_QUADRA,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_LATE,
                .ide_type       = MAC_IDE_BABOON,
                .scc_type       = MAC_SCC_QUADRA,
                .nubus_type     = MAC_NUBUS,
@@ -722,7 +722,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook 520",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_QUADRA,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_LATE,
                .scc_type       = MAC_SCC_QUADRA,
                .ether_type     = MAC_ETHER_SONIC,
                .nubus_type     = MAC_NUBUS,
@@ -740,7 +740,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook Duo 210",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_DUO,
                .scc_type       = MAC_SCC_QUADRA,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -749,7 +749,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook Duo 230",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_DUO,
                .scc_type       = MAC_SCC_QUADRA,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -758,7 +758,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook Duo 250",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_DUO,
                .scc_type       = MAC_SCC_QUADRA,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -767,7 +767,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook Duo 270c",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_DUO,
                .scc_type       = MAC_SCC_QUADRA,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -776,7 +776,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook Duo 280",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_DUO,
                .scc_type       = MAC_SCC_QUADRA,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -785,7 +785,7 @@ static struct mac_model mac_data_table[] = {
                .name           = "PowerBook Duo 280c",
                .adb_type       = MAC_ADB_PB2,
                .via_type       = MAC_VIA_IICI,
-               .scsi_type      = MAC_SCSI_OLD,
+               .scsi_type      = MAC_SCSI_DUO,
                .scc_type       = MAC_SCC_QUADRA,
                .nubus_type     = MAC_NUBUS,
                .floppy_type    = MAC_FLOPPY_SWIM_ADDR2,
@@ -929,6 +929,70 @@ static struct platform_device swim_pdev = {
        .resource       = &swim_rsrc,
 };
 
+static const struct resource mac_scsi_iifx_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = IRQ_MAC_SCSI,
+               .end   = IRQ_MAC_SCSI,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0x50008000,
+               .end   = 0x50009FFF,
+       },
+};
+
+static const struct resource mac_scsi_duo_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_MEM,
+               .start = 0xFEE02000,
+               .end   = 0xFEE03FFF,
+       },
+};
+
+static const struct resource mac_scsi_old_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = IRQ_MAC_SCSI,
+               .end   = IRQ_MAC_SCSI,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0x50010000,
+               .end   = 0x50011FFF,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0x50006000,
+               .end   = 0x50007FFF,
+       },
+};
+
+static const struct resource mac_scsi_late_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = IRQ_MAC_SCSI,
+               .end   = IRQ_MAC_SCSI,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0x50010000,
+               .end   = 0x50011FFF,
+       },
+};
+
+static const struct resource mac_scsi_ccl_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = IRQ_MAC_SCSI,
+               .end   = IRQ_MAC_SCSI,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0x50F10000,
+               .end   = 0x50F11FFF,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0x50F06000,
+               .end   = 0x50F07FFF,
+       },
+};
+
 static struct platform_device esp_0_pdev = {
        .name           = "mac_esp",
        .id             = 0,
@@ -1000,6 +1064,60 @@ int __init mac_platform_init(void)
                    (macintosh_config->ident == MAC_MODEL_Q950))
                        platform_device_register(&esp_1_pdev);
                break;
+       case MAC_SCSI_IIFX:
+               /* Addresses from The Guide to Mac Family Hardware.
+                * $5000 8000 - $5000 9FFF: SCSI DMA
+                * $5000 C000 - $5000 DFFF: Alternate SCSI (DMA)
+                * $5000 E000 - $5000 FFFF: Alternate SCSI (Hsk)
+                * The SCSI DMA custom IC embeds the 53C80 core. mac_scsi does
+                * not make use of its DMA or hardware handshaking logic.
+                */
+               platform_device_register_simple("mac_scsi", 0,
+                       mac_scsi_iifx_rsrc, ARRAY_SIZE(mac_scsi_iifx_rsrc));
+               break;
+       case MAC_SCSI_DUO:
+               /* Addresses from the Duo Dock II Developer Note.
+                * $FEE0 2000 - $FEE0 3FFF: normal mode
+                * $FEE0 4000 - $FEE0 5FFF: pseudo DMA without /DRQ
+                * $FEE0 6000 - $FEE0 7FFF: pseudo DMA with /DRQ
+                * The NetBSD code indicates that both 5380 chips share
+                * an IRQ (?) which would need careful handling (see mac_esp).
+                */
+               platform_device_register_simple("mac_scsi", 1,
+                       mac_scsi_duo_rsrc, ARRAY_SIZE(mac_scsi_duo_rsrc));
+               /* fall through */
+       case MAC_SCSI_OLD:
+               /* Addresses from Developer Notes for Duo System,
+                * PowerBook 180 & 160, 140 & 170, Macintosh IIsi
+                * and also from The Guide to Mac Family Hardware for
+                * SE/30, II, IIx, IIcx, IIci.
+                * $5000 6000 - $5000 7FFF: pseudo-DMA with /DRQ
+                * $5001 0000 - $5001 1FFF: normal mode
+                * $5001 2000 - $5001 3FFF: pseudo-DMA without /DRQ
+                * GMFH says that $5000 0000 - $50FF FFFF "wraps
+                * $5000 0000 - $5001 FFFF eight times" (!)
+                * mess.org says IIci and Color Classic do not alias
+                * I/O address space.
+                */
+               platform_device_register_simple("mac_scsi", 0,
+                       mac_scsi_old_rsrc, ARRAY_SIZE(mac_scsi_old_rsrc));
+               break;
+       case MAC_SCSI_LATE:
+               /* PDMA logic in 68040 PowerBooks is somehow different to
+                * '030 models. It's probably more like Quadras (see mac_esp).
+                */
+               platform_device_register_simple("mac_scsi", 0,
+                       mac_scsi_late_rsrc, ARRAY_SIZE(mac_scsi_late_rsrc));
+               break;
+       case MAC_SCSI_CCL:
+               /* Addresses from the Color Classic Developer Note.
+                * $50F0 6000 - $50F0 7FFF: SCSI handshake
+                * $50F1 0000 - $50F1 1FFF: SCSI
+                * $50F1 2000 - $50F1 3FFF: SCSI DMA
+                */
+               platform_device_register_simple("mac_scsi", 0,
+                       mac_scsi_ccl_rsrc, ARRAY_SIZE(mac_scsi_ccl_rsrc));
+               break;
        }
 
        /*
index acaff6a49e357e89154651f6ec57db9ab53f0459..b09a3cb29b68fda44ba224fda84743bdfaaeded2 100644 (file)
@@ -94,7 +94,6 @@ void __init paging_init(void)
        high_memory = (void *) end_mem;
 
        empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
-       memset(empty_zero_page, 0, PAGE_SIZE);
 
        /*
         * Set up SFC/DFC registers (user data space).
index f59ec58083f8b41545665a0dfab1492bfd1d3007..a8b942bf71638c9778dd8fff05c63797202edd61 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/platform_device.h>
 
 #include <asm/oplib.h>
 #include <asm/setup.h>
@@ -27,6 +28,7 @@
 #include <asm/sun3mmu.h>
 #include <asm/rtc.h>
 #include <asm/machdep.h>
+#include <asm/machines.h>
 #include <asm/idprom.h>
 #include <asm/intersil.h>
 #include <asm/irq.h>
@@ -169,3 +171,61 @@ static void __init sun3_sched_init(irq_handler_t timer_routine)
         intersil_clear();
 }
 
+#ifdef CONFIG_SUN3_SCSI
+
+static const struct resource sun3_scsi_vme_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = SUN3_VEC_VMESCSI0,
+               .end   = SUN3_VEC_VMESCSI0,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0xff200000,
+               .end   = 0xff200021,
+       }, {
+               .flags = IORESOURCE_IRQ,
+               .start = SUN3_VEC_VMESCSI1,
+               .end   = SUN3_VEC_VMESCSI1,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0xff204000,
+               .end   = 0xff204021,
+       },
+};
+
+/*
+ * Int: level 2 autovector
+ * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0>
+ */
+static const struct resource sun3_scsi_rsrc[] __initconst = {
+       {
+               .flags = IORESOURCE_IRQ,
+               .start = 2,
+               .end   = 2,
+       }, {
+               .flags = IORESOURCE_MEM,
+               .start = 0x00140000,
+               .end   = 0x0014001f,
+       },
+};
+
+int __init sun3_platform_init(void)
+{
+       switch (idprom->id_machtype) {
+       case SM_SUN3 | SM_3_160:
+       case SM_SUN3 | SM_3_260:
+               platform_device_register_simple("sun3_scsi_vme", -1,
+                       sun3_scsi_vme_rsrc, ARRAY_SIZE(sun3_scsi_vme_rsrc));
+               break;
+       case SM_SUN3 | SM_3_50:
+       case SM_SUN3 | SM_3_60:
+               platform_device_register_simple("sun3_scsi", -1,
+                       sun3_scsi_rsrc, ARRAY_SIZE(sun3_scsi_rsrc));
+               break;
+       }
+       return 0;
+}
+
+arch_initcall(sun3_platform_init);
+
+#endif
index 6feded3b0c4c1eb6d1414082a9f9318041129a39..a7736fa0580cc2e000cf1613d7b21dbe7aba4dcc 100644 (file)
@@ -129,6 +129,10 @@ endmenu
 
 menu "Kernel features"
 
+config NR_CPUS
+       int
+       default "1"
+
 config ADVANCED_OPTIONS
        bool "Prompt for advanced kernel configuration options"
        help
index 433751b2a003309bb2a449888ac5b48f6f747d3c..940f5fc1d1da13f3988fe99fd69a7d02e0825c8d 100644 (file)
@@ -69,12 +69,4 @@ extern void __iomem *ioremap(phys_addr_t address, unsigned long size);
 
 #include <asm-generic/io.h>
 
-#define readb_relaxed  readb
-#define readw_relaxed  readw
-#define readl_relaxed  readl
-
-#define writeb_relaxed writeb
-#define writew_relaxed writew
-#define writel_relaxed writel
-
 #endif /* _ASM_MICROBLAZE_IO_H */
index 8aa97817cc8c6aabecc6e313a5db7d72d1aa9e99..99b6ded54849e2327e7593592c14aa73adee1429 100644 (file)
@@ -14,7 +14,6 @@
 #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
 
 #include <linux/pagemap.h>
-#include <asm-generic/tlb.h>
 
 #ifdef CONFIG_MMU
 #define tlb_start_vma(tlb, vma)                do { } while (0)
@@ -22,4 +21,6 @@
 #define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
 #endif
 
+#include <asm-generic/tlb.h>
+
 #endif /* _ASM_MICROBLAZE_TLB_H */
index ea4b233647c1aa32d23562e7abba7dab72d404db..0a53362d55486187ea3aada0ff999b04de97d7ec 100644 (file)
@@ -38,6 +38,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#define __NR_syscalls         387
+#define __NR_syscalls         388
 
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
index 1c2380bf8fe60850274dce0bdbc9e9bb16cc531f..c712677f8a2a6d7460e245d8e703adaa53372070 100644 (file)
 #define __NR_seccomp           384
 #define __NR_getrandom         385
 #define __NR_memfd_create      386
+#define __NR_bpf               387
 
 #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
index de59ee1d7010a788cf916b4ade098375af6214d6..0166e890486c72d9b9263b6d46553dc8b50d6b4a 100644 (file)
@@ -387,3 +387,4 @@ ENTRY(sys_call_table)
        .long sys_seccomp
        .long sys_getrandom             /* 385 */
        .long sys_memfd_create
+       .long sys_bpf
index 9037914f6985df1dfd8227bbc6f7e943aa15a3ea..b30e41c0c0335cf2ab79e716c9c41c0ebced18e8 100644 (file)
@@ -660,8 +660,13 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
                        res = &hose->mem_resources[memno++];
                        break;
                }
-               if (res != NULL)
-                       of_pci_range_to_resource(&range, dev, res);
+               if (res != NULL) {
+                       res->name = dev->full_name;
+                       res->flags = range.flags;
+                       res->start = range.cpu_addr;
+                       res->end = range.cpu_addr + range.size - 1;
+                       res->parent = res->child = res->sibling = NULL;
+               }
        }
 
        /* If there's an ISA hole and the pci_mem_offset is -not- matching
index ad6badb6be715735715e25ad3198b19e9f54191b..9536ef912f594651be7e403264f3eb30c3355384 100644 (file)
@@ -2066,6 +2066,7 @@ config MIPS_CPS
          support is unavailable.
 
 config MIPS_CPS_PM
+       depends on MIPS_CPS
        select MIPS_CPC
        bool
 
@@ -2100,9 +2101,17 @@ config 64BIT_PHYS_ADDR
 config ARCH_PHYS_ADDR_T_64BIT
        def_bool 64BIT_PHYS_ADDR
 
+choice
+       prompt "SmartMIPS or microMIPS ASE support"
+
+config CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS
+       bool "None"
+       help
+         Select this if you want neither microMIPS nor SmartMIPS support
+
 config CPU_HAS_SMARTMIPS
        depends on SYS_SUPPORTS_SMARTMIPS
-       bool "Support for the SmartMIPS ASE"
+       bool "SmartMIPS"
        help
          SmartMIPS is a extension of the MIPS32 architecture aimed at
          increased security at both hardware and software level for
@@ -2114,11 +2123,13 @@ config CPU_HAS_SMARTMIPS
 
 config CPU_MICROMIPS
        depends on SYS_SUPPORTS_MICROMIPS
-       bool "Build kernel using microMIPS ISA"
+       bool "microMIPS"
        help
          When this option is enabled the kernel will be built using the
          microMIPS ISA
 
+endchoice
+
 config CPU_HAS_MSA
        bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
        depends on CPU_SUPPORTS_MSA
index 23cb94806fbc5d0f370110cc0da8936f54b80719..58076472bdd8e85eb8eaba14e8e3c21b6c4dfdc1 100644 (file)
@@ -93,6 +93,15 @@ LDFLAGS_vmlinux                      += -G 0 -static -n -nostdlib
 KBUILD_AFLAGS_MODULE           += -mlong-calls
 KBUILD_CFLAGS_MODULE           += -mlong-calls
 
+#
+# pass -msoft-float to GAS if it supports it.  However on newer binutils
+# (specifically newer than 2.24.51.20140728) we then also need to explicitly
+# set ".set hardfloat" in all files which manipulate floating point registers.
+#
+ifneq ($(call as-option,-Wa$(comma)-msoft-float,),)
+       cflags-y                += -DGAS_HAS_SET_HARDFLOAT -Wa,-msoft-float
+endif
+
 cflags-y += -ffreestanding
 
 #
index 4d661a1d2dae90d5308d63699be7287037657aa9..9423f5aed287802a6b52c368c80233c1fd9d9973 100644 (file)
@@ -113,7 +113,7 @@ static void __init db120_pci_init(u8 *eeprom)
        ath79_register_pci();
 }
 #else
-static inline void db120_pci_init(void) {}
+static inline void db120_pci_init(u8 *eeprom) {}
 #endif /* CONFIG_PCI */
 
 static void __init db120_setup(void)
index 7417340496756d30d159aae9b48e4af0f8edf531..2bc4aa95944e462d84673bb974e2dde119fb6bdf 100644 (file)
@@ -809,6 +809,7 @@ static struct irq_chip octeon_irq_chip_ciu_gpio_v2 = {
        .irq_set_type = octeon_irq_ciu_gpio_set_type,
 #ifdef CONFIG_SMP
        .irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
+       .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
 #endif
        .flags = IRQCHIP_SET_TYPE_MASKED,
 };
@@ -823,6 +824,7 @@ static struct irq_chip octeon_irq_chip_ciu_gpio = {
        .irq_set_type = octeon_irq_ciu_gpio_set_type,
 #ifdef CONFIG_SMP
        .irq_set_affinity = octeon_irq_ciu_set_affinity,
+       .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
 #endif
        .flags = IRQCHIP_SET_TYPE_MASKED,
 };
index 38f4c32e28165543d99bbd391ad3df993789ea06..5ebdb32d9a2b8586c1a39539951756ee5adc2ea3 100644 (file)
@@ -806,15 +806,6 @@ void __init prom_init(void)
 #endif
        }
 
-       if (octeon_is_simulation()) {
-               /*
-                * The simulator uses a mtdram device pre filled with
-                * the filesystem. Also specify the calibration delay
-                * to avoid calculating it every time.
-                */
-               strcat(arcs_cmdline, " rw root=1f00 slram=root,0x40000000,+1073741824");
-       }
-
        mips_hpt_frequency = octeon_get_clock_rate();
 
        octeon_init_cvmcount();
index e38c2811d4e23645e962df3b2f27fee3cdfb9804..cdac7b3eeaf7fa6524b8f6ffb92edc7209eef4c5 100644 (file)
@@ -13,6 +13,8 @@
 #include <asm/mipsregs.h>
 
        .macro  fpu_save_single thread tmp=t0
+       .set push
+       SET_HARDFLOAT
        cfc1    \tmp,  fcr31
        swc1    $f0,  THREAD_FPR0_LS64(\thread)
        swc1    $f1,  THREAD_FPR1_LS64(\thread)
        swc1    $f30, THREAD_FPR30_LS64(\thread)
        swc1    $f31, THREAD_FPR31_LS64(\thread)
        sw      \tmp, THREAD_FCR31(\thread)
+       .set pop
        .endm
 
        .macro  fpu_restore_single thread tmp=t0
+       .set push
+       SET_HARDFLOAT
        lw      \tmp, THREAD_FCR31(\thread)
        lwc1    $f0,  THREAD_FPR0_LS64(\thread)
        lwc1    $f1,  THREAD_FPR1_LS64(\thread)
@@ -84,6 +89,7 @@
        lwc1    $f30, THREAD_FPR30_LS64(\thread)
        lwc1    $f31, THREAD_FPR31_LS64(\thread)
        ctc1    \tmp, fcr31
+       .set pop
        .endm
 
        .macro  cpu_save_nonscratch thread
index cd9a98bc8f606197a15b70d729aa66a0431f3e0e..6caf8766b80f161ea7a620ecc33cca7768e1d4b0 100644 (file)
@@ -57,6 +57,8 @@
 #endif /* CONFIG_CPU_MIPSR2 */
 
        .macro  fpu_save_16even thread tmp=t0
+       .set    push
+       SET_HARDFLOAT
        cfc1    \tmp, fcr31
        sdc1    $f0,  THREAD_FPR0_LS64(\thread)
        sdc1    $f2,  THREAD_FPR2_LS64(\thread)
        sdc1    $f28, THREAD_FPR28_LS64(\thread)
        sdc1    $f30, THREAD_FPR30_LS64(\thread)
        sw      \tmp, THREAD_FCR31(\thread)
+       .set    pop
        .endm
 
        .macro  fpu_save_16odd thread
        .set    push
        .set    mips64r2
+       SET_HARDFLOAT
        sdc1    $f1,  THREAD_FPR1_LS64(\thread)
        sdc1    $f3,  THREAD_FPR3_LS64(\thread)
        sdc1    $f5,  THREAD_FPR5_LS64(\thread)
        .endm
 
        .macro  fpu_restore_16even thread tmp=t0
+       .set    push
+       SET_HARDFLOAT
        lw      \tmp, THREAD_FCR31(\thread)
        ldc1    $f0,  THREAD_FPR0_LS64(\thread)
        ldc1    $f2,  THREAD_FPR2_LS64(\thread)
        .macro  fpu_restore_16odd thread
        .set    push
        .set    mips64r2
+       SET_HARDFLOAT
        ldc1    $f1,  THREAD_FPR1_LS64(\thread)
        ldc1    $f3,  THREAD_FPR3_LS64(\thread)
        ldc1    $f5,  THREAD_FPR5_LS64(\thread)
        .macro  cfcmsa  rd, cs
        .set    push
        .set    noat
+       SET_HARDFLOAT
        .insn
        .word   CFC_MSA_INSN | (\cs << 11)
        move    \rd, $1
        .macro  ctcmsa  cd, rs
        .set    push
        .set    noat
+       SET_HARDFLOAT
        move    $1, \rs
        .word   CTC_MSA_INSN | (\cd << 6)
        .set    pop
        .macro  ld_d    wd, off, base
        .set    push
        .set    noat
+       SET_HARDFLOAT
        add     $1, \base, \off
        .word   LDD_MSA_INSN | (\wd << 6)
        .set    pop
        .macro  st_d    wd, off, base
        .set    push
        .set    noat
+       SET_HARDFLOAT
        add     $1, \base, \off
        .word   STD_MSA_INSN | (\wd << 6)
        .set    pop
        .macro  copy_u_w        rd, ws, n
        .set    push
        .set    noat
+       SET_HARDFLOAT
        .insn
        .word   COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
        /* move triggers an assembler bug... */
        .macro  copy_u_d        rd, ws, n
        .set    push
        .set    noat
+       SET_HARDFLOAT
        .insn
        .word   COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
        /* move triggers an assembler bug... */
        .macro  insert_w        wd, n, rs
        .set    push
        .set    noat
+       SET_HARDFLOAT
        /* move triggers an assembler bug... */
        or      $1, \rs, zero
        .word   INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
        .macro  insert_d        wd, n, rs
        .set    push
        .set    noat
+       SET_HARDFLOAT
        /* move triggers an assembler bug... */
        or      $1, \rs, zero
        .word   INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
        st_d    31, THREAD_FPR31, \thread
        .set    push
        .set    noat
+       SET_HARDFLOAT
        cfcmsa  $1, MSA_CSR
        sw      $1, THREAD_MSA_CSR(\thread)
        .set    pop
        .macro  msa_restore_all thread
        .set    push
        .set    noat
+       SET_HARDFLOAT
        lw      $1, THREAD_MSA_CSR(\thread)
        ctcmsa  MSA_CSR, $1
        .set    pop
        .macro  msa_init_all_upper
        .set    push
        .set    noat
+       SET_HARDFLOAT
        not     $1, zero
        msa_init_upper  0
        .set    pop
index 51f80bd36fcc457a46782bc4266241d4de34ee2c..63b3468ede4cb0e1a6de5ee85e3f50271df6f3ec 100644 (file)
@@ -37,15 +37,15 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *);
 
 #define cop2_present           1
 #define cop2_lazy_restore      1
-#define cop2_save(r)           do { (r); } while (0)
-#define cop2_restore(r)                do { (r); } while (0)
+#define cop2_save(r)           do { (void)(r); } while (0)
+#define cop2_restore(r)                do { (void)(r); } while (0)
 
 #else
 
 #define cop2_present           0
 #define cop2_lazy_restore      0
-#define cop2_save(r)           do { (r); } while (0)
-#define cop2_restore(r)                do { (r); } while (0)
+#define cop2_save(r)           do { (void)(r); } while (0)
+#define cop2_restore(r)                do { (void)(r); } while (0)
 #endif
 
 enum cu2_ops {
index 429481f9028dd08119e9961ab8669c04181a6ad3..f184ba088532635068f1944f858c249675dbd991 100644 (file)
 
 #include <asm/sgidefs.h>
 
+/*
+ * starting with binutils 2.24.51.20140729, MIPS binutils warn about mixing
+ * hardfloat and softfloat object files.  The kernel build uses soft-float by
+ * default, so we also need to pass -msoft-float along to GAS if it supports it.
+ * But this in turn causes assembler errors in files which access hardfloat
+ * registers.  We detect if GAS supports "-msoft-float" in the Makefile and
+ * explicitly put ".set hardfloat" where floating point registers are touched.
+ */
+#ifdef GAS_HAS_SET_HARDFLOAT
+#define SET_HARDFLOAT .set hardfloat
+#else
+#define SET_HARDFLOAT
+#endif
+
 #if _MIPS_SIM == _MIPS_SIM_ABI32
 
 /*
index 4d0aeda6839741ea27f956e9049958cdab297b56..dd562414cd5effc97f834da299c052d2922e325a 100644 (file)
@@ -145,8 +145,8 @@ static inline void lose_fpu(int save)
        if (is_msa_enabled()) {
                if (save) {
                        save_msa(current);
-                       asm volatile("cfc1 %0, $31"
-                               : "=r"(current->thread.fpu.fcr31));
+                       current->thread.fpu.fcr31 =
+                                       read_32bit_cp1_register(CP1_STATUS);
                }
                disable_msa();
                clear_thread_flag(TIF_USEDMSA);
index 992aaba603b5ca24da6242c5aebef4ea80aeb0e2..b463f2aa5a613caf29b13adb43b7a8097fb98bf2 100644 (file)
@@ -24,7 +24,7 @@ do {                                                  \
        asm volatile (                                  \
                "1: " load " %[tmp_dst], 0(%[tmp_src])\n"       \
                "   li %[tmp_err], 0\n"                 \
-               "2:\n"                                  \
+               "2: .insn\n"                            \
                                                        \
                ".section .fixup, \"ax\"\n"             \
                "3: li %[tmp_err], 1\n"                 \
@@ -46,7 +46,7 @@ do {                                          \
        asm volatile (                          \
                "1: " store " %[tmp_src], 0(%[tmp_dst])\n"\
                "   li %[tmp_err], 0\n"         \
-               "2:\n"                          \
+               "2: .insn\n"                    \
                                                \
                ".section .fixup, \"ax\"\n"     \
                "3: li %[tmp_err], 1\n"         \
index d9f932de80e926f3701e4a63166e48f37ac89f8f..1c967abd545c688c806367762db0ea34618ae955 100644 (file)
@@ -8,19 +8,12 @@ extern void (*cpu_wait)(void);
 extern void r4k_wait(void);
 extern asmlinkage void __r4k_wait(void);
 extern void r4k_wait_irqoff(void);
-extern void __pastwait(void);
 
 static inline int using_rollback_handler(void)
 {
        return cpu_wait == r4k_wait;
 }
 
-static inline int address_is_in_r4k_wait_irqoff(unsigned long addr)
-{
-       return addr >= (unsigned long)r4k_wait_irqoff &&
-              addr < (unsigned long)__pastwait;
-}
-
 extern int mips_cpuidle_wait_enter(struct cpuidle_device *dev,
                                   struct cpuidle_driver *drv, int index);
 
index e194f957ca8c42a0af82f0621c425308a25e4d53..fdbff44e5482cd20acc5efc798091894a3292c4f 100644 (file)
 #define WORD_INSN ".word"
 #endif
 
+#ifdef CONFIG_CPU_MICROMIPS
+#define NOP_INSN "nop32"
+#else
+#define NOP_INSN "nop"
+#endif
+
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-       asm_volatile_goto("1:\tnop\n\t"
+       asm_volatile_goto("1:\t" NOP_INSN "\n\t"
                "nop\n\t"
                ".pushsection __jump_table,  \"aw\"\n\t"
                WORD_INSN " 1b, %l[l_yes], %0\n\t"
index 7d28f95b0512ea27e1aeb7fac6f22ecc561a45fd..6d69332f21ecd53e09eebfba0de74f1c9fc1daa6 100644 (file)
 #define cpu_has_mcheck         0
 #define cpu_has_mdmx           0
 #define cpu_has_mips16         0
-#define cpu_has_mips32r1       0
 #define cpu_has_mips32r2       0
 #define cpu_has_mips3d         0
-#define cpu_has_mips64r1       0
 #define cpu_has_mips64r2       0
 #define cpu_has_mipsmt         0
 #define cpu_has_prefetch       0
index cf3b580c3df6de0c09e6a47f05f670ae79b94666..22a135ac91de3830e885342b834feb47ab109eff 100644 (file)
 #define MIPS_CONF6_SYND                (_ULCAST_(1) << 13)
 /* proAptiv FTLB on/off bit */
 #define MIPS_CONF6_FTLBEN      (_ULCAST_(1) << 15)
+/* FTLB probability bits */
+#define MIPS_CONF6_FTLBP_SHIFT (16)
 
 #define MIPS_CONF7_WII         (_ULCAST_(1) << 31)
 
@@ -1324,7 +1326,7 @@ do {                                                                      \
 /*
  * Macros to access the floating point coprocessor control registers
  */
-#define read_32bit_cp1_register(source)                                        \
+#define _read_32bit_cp1_register(source, gas_hardfloat)                        \
 ({                                                                     \
        int __res;                                                      \
                                                                        \
@@ -1334,12 +1336,21 @@ do {                                                                    \
        "       # gas fails to assemble cfc1 for some archs,    \n"     \
        "       # like Octeon.                                  \n"     \
        "       .set    mips1                                   \n"     \
+       "       "STR(gas_hardfloat)"                            \n"     \
        "       cfc1    %0,"STR(source)"                        \n"     \
        "       .set    pop                                     \n"     \
        : "=r" (__res));                                                \
        __res;                                                          \
 })
 
+#ifdef GAS_HAS_SET_HARDFLOAT
+#define read_32bit_cp1_register(source)                                        \
+       _read_32bit_cp1_register(source, .set hardfloat)
+#else
+#define read_32bit_cp1_register(source)                                        \
+       _read_32bit_cp1_register(source, )
+#endif
+
 #ifdef HAVE_AS_DSP
 #define rddsp(mask)                                                    \
 ({                                                                     \
index 4520adc8699b9c00835a4340c8da217e90dcc305..cd6e0afc683366e598eadbaf8c572e0434fdb9bf 100644 (file)
@@ -257,7 +257,11 @@ static inline void protected_flush_icache_line(unsigned long addr)
  */
 static inline void protected_writeback_dcache_line(unsigned long addr)
 {
+#ifdef CONFIG_EVA
+       protected_cachee_op(Hit_Writeback_Inv_D, addr);
+#else
        protected_cache_op(Hit_Writeback_Inv_D, addr);
+#endif
 }
 
 static inline void protected_writeback_scache_line(unsigned long addr)
index a10951090234073cae8aa6ea9d8b5542faef6a22..22a5624e2fd2dcecf4b5592097e0c18620012426 100644 (file)
@@ -301,7 +301,8 @@ do {                                                                        \
                        __get_kernel_common((x), size, __gu_ptr);       \
                else                                                    \
                        __get_user_common((x), size, __gu_ptr);         \
-       }                                                               \
+       } else                                                          \
+               (x) = 0;                                                \
                                                                        \
        __gu_err;                                                       \
 })
@@ -316,6 +317,7 @@ do {                                                                        \
        "       .insn                                           \n"     \
        "       .section .fixup,\"ax\"                          \n"     \
        "3:     li      %0, %4                                  \n"     \
+       "       move    %1, $0                                  \n"     \
        "       j       2b                                      \n"     \
        "       .previous                                       \n"     \
        "       .section __ex_table,\"a\"                       \n"     \
@@ -630,6 +632,7 @@ do {                                                                        \
        "       .insn                                           \n"     \
        "       .section .fixup,\"ax\"                          \n"     \
        "3:     li      %0, %4                                  \n"     \
+       "       move    %1, $0                                  \n"     \
        "       j       2b                                      \n"     \
        "       .previous                                       \n"     \
        "       .section __ex_table,\"a\"                       \n"     \
@@ -773,10 +776,11 @@ extern void __put_user_unaligned_unknown(void);
        "jal\t" #destination "\n\t"
 #endif
 
-#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
-#define DADDI_SCRATCH "$0"
-#else
+#if defined(CONFIG_CPU_DADDI_WORKAROUNDS) || (defined(CONFIG_EVA) &&   \
+                                             defined(CONFIG_CPU_HAS_PREFETCH))
 #define DADDI_SCRATCH "$3"
+#else
+#define DADDI_SCRATCH "$0"
 #endif
 
 extern size_t __copy_user(void *__to, const void *__from, size_t __n);
@@ -1418,7 +1422,7 @@ static inline long __strnlen_user(const char __user *s, long n)
 }
 
 /*
- * strlen_user: - Get the size of a string in user space.
+ * strnlen_user: - Get the size of a string in user space.
  * @str: The string to measure.
  *
  * Context: User context only. This function may sleep.
@@ -1427,9 +1431,7 @@ static inline long __strnlen_user(const char __user *s, long n)
  *
  * Returns the size of the string INCLUDING the terminating NUL.
  * On exception, returns 0.
- *
- * If there is a limit on the length of a valid string, you may wish to
- * consider using strnlen_user() instead.
+ * If the string is too long, returns a value greater than @n.
  */
 static inline long strnlen_user(const char __user *s, long n)
 {
index bbcfb8ba8106a4be5c4247de03a120264c87614f..91a3d197ede365437ba468e5dff97e4358a6f314 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _UAPI_ASM_PTRACE_H
 #define _UAPI_ASM_PTRACE_H
 
+#include <linux/types.h>
+
 /* 0 - 31 are integer registers, 32 - 63 are fp registers.  */
 #define FPR_BASE       32
 #define PC             64
index fdb4923777d1347822517b9671b80f378c74d16b..d001bb1ad177e7b6e2df2fbb7e42e894784b2e91 100644 (file)
 #define __NR_seccomp                   (__NR_Linux + 352)
 #define __NR_getrandom                 (__NR_Linux + 353)
 #define __NR_memfd_create              (__NR_Linux + 354)
+#define __NR_bpf                       (__NR_Linux + 355)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            354
+#define __NR_Linux_syscalls            355
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                354
+#define __NR_O32_Linux_syscalls                355
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_seccomp                   (__NR_Linux + 312)
 #define __NR_getrandom                 (__NR_Linux + 313)
 #define __NR_memfd_create              (__NR_Linux + 314)
+#define __NR_bpf                       (__NR_Linux + 315)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            314
+#define __NR_Linux_syscalls            315
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         314
+#define __NR_64_Linux_syscalls         315
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_seccomp                   (__NR_Linux + 316)
 #define __NR_getrandom                 (__NR_Linux + 317)
 #define __NR_memfd_create              (__NR_Linux + 318)
+#define __NR_bpf                       (__NR_Linux + 319)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            318
+#define __NR_Linux_syscalls            319
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                318
+#define __NR_N32_Linux_syscalls                319
 
 #endif /* _UAPI_ASM_UNISTD_H */
index 290c23b516789ba16193f7b72fa61eafbf7907b2..86495072a922f31e0214cad3b6ac71c10aaf5fa8 100644 (file)
@@ -208,7 +208,6 @@ bmips_reset_nmi_vec_end:
 END(bmips_reset_nmi_vec)
 
        .set    pop
-       .previous
 
 /***********************************************************************
  * CPU1 warm restart vector (used for second and subsequent boots).
@@ -281,5 +280,3 @@ LEAF(bmips_enable_xks01)
        jr      ra
 
 END(bmips_enable_xks01)
-
-       .previous
index 7b2df224f0414805d8260e4fad30b1d0050f65b5..4d7d99d601cc13219e9d8f9631da6002b3d9df9d 100644 (file)
@@ -144,7 +144,7 @@ int __mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                case mm_bc1t_op:
                        preempt_disable();
                        if (is_fpu_owner())
-                               asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+                               fcr31 = read_32bit_cp1_register(CP1_STATUS);
                        else
                                fcr31 = current->thread.fpu.fcr31;
                        preempt_enable();
@@ -562,11 +562,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
        case cop1_op:
                preempt_disable();
                if (is_fpu_owner())
-                       asm volatile(
-                               ".set push\n"
-                               "\t.set mips1\n"
-                               "\tcfc1\t%0,$31\n"
-                               "\t.set pop" : "=r" (fcr31));
+                       fcr31 = read_32bit_cp1_register(CP1_STATUS);
                else
                        fcr31 = current->thread.fpu.fcr31;
                preempt_enable();
index e6e97d2a5c9e68cccde81ab0f181184d1e27fd13..0384b05ab5a02413cbcb11a163375029f285255f 100644 (file)
@@ -229,6 +229,7 @@ LEAF(mips_cps_core_init)
         nop
 
        .set    push
+       .set    mips32r2
        .set    mt
 
        /* Only allow 1 TC per VPE to execute... */
@@ -345,6 +346,7 @@ LEAF(mips_cps_boot_vpes)
         nop
 
        .set    push
+       .set    mips32r2
        .set    mt
 
 1:     /* Enter VPE configuration state */
index 94c4a0c0a577909849326dd38999d30ef017ab99..dc49cf30c2db46f9e0f2caef74548459c71f6714 100644 (file)
@@ -193,6 +193,32 @@ static void set_isa(struct cpuinfo_mips *c, unsigned int isa)
 static char unknown_isa[] = KERN_ERR \
        "Unsupported ISA type, c0.config0: %d.";
 
+static unsigned int calculate_ftlb_probability(struct cpuinfo_mips *c)
+{
+
+       unsigned int probability = c->tlbsize / c->tlbsizevtlb;
+
+       /*
+        * 0 = All TLBWR instructions go to FTLB
+        * 1 = 15:1: For every 16 TBLWR instructions, 15 go to the
+        * FTLB and 1 goes to the VTLB.
+        * 2 = 7:1: As above with 7:1 ratio.
+        * 3 = 3:1: As above with 3:1 ratio.
+        *
+        * Use the linear midpoint as the probability threshold.
+        */
+       if (probability >= 12)
+               return 1;
+       else if (probability >= 6)
+               return 2;
+       else
+               /*
+                * So FTLB is less than 4 times bigger than VTLB.
+                * A 3:1 ratio can still be useful though.
+                */
+               return 3;
+}
+
 static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 {
        unsigned int config6;
@@ -203,9 +229,14 @@ static void set_ftlb_enable(struct cpuinfo_mips *c, int enable)
        case CPU_P5600:
                /* proAptiv & related cores use Config6 to enable the FTLB */
                config6 = read_c0_config6();
+               /* Clear the old probability value */
+               config6 &= ~(3 << MIPS_CONF6_FTLBP_SHIFT);
                if (enable)
                        /* Enable FTLB */
-                       write_c0_config6(config6 | MIPS_CONF6_FTLBEN);
+                       write_c0_config6(config6 |
+                                        (calculate_ftlb_probability(c)
+                                         << MIPS_CONF6_FTLBP_SHIFT)
+                                        | MIPS_CONF6_FTLBEN);
                else
                        /* Disable FTLB */
                        write_c0_config6(config6 &  ~MIPS_CONF6_FTLBEN);
@@ -757,31 +788,34 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                        c->cputype = CPU_LOONGSON2;
                        __cpu_name[cpu] = "ICT Loongson-2";
                        set_elf_platform(cpu, "loongson2e");
+                       set_isa(c, MIPS_CPU_ISA_III);
                        break;
                case PRID_REV_LOONGSON2F:
                        c->cputype = CPU_LOONGSON2;
                        __cpu_name[cpu] = "ICT Loongson-2";
                        set_elf_platform(cpu, "loongson2f");
+                       set_isa(c, MIPS_CPU_ISA_III);
                        break;
                case PRID_REV_LOONGSON3A:
                        c->cputype = CPU_LOONGSON3;
-                       c->writecombine = _CACHE_UNCACHED_ACCELERATED;
                        __cpu_name[cpu] = "ICT Loongson-3";
                        set_elf_platform(cpu, "loongson3a");
+                       set_isa(c, MIPS_CPU_ISA_M64R1);
                        break;
                case PRID_REV_LOONGSON3B_R1:
                case PRID_REV_LOONGSON3B_R2:
                        c->cputype = CPU_LOONGSON3;
                        __cpu_name[cpu] = "ICT Loongson-3";
                        set_elf_platform(cpu, "loongson3b");
+                       set_isa(c, MIPS_CPU_ISA_M64R1);
                        break;
                }
 
-               set_isa(c, MIPS_CPU_ISA_III);
                c->options = R4K_OPTS |
                             MIPS_CPU_FPU | MIPS_CPU_LLSC |
                             MIPS_CPU_32FPR;
                c->tlbsize = 64;
+               c->writecombine = _CACHE_UNCACHED_ACCELERATED;
                break;
        case PRID_IMP_LOONGSON_32:  /* Loongson-1 */
                decode_configs(c);
index ac35e12cb1f3585d05f4f336489c161b4b17a950..a5e26dd9059256ed7c2a2033210bcd1bbc99b6e3 100644 (file)
@@ -358,6 +358,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    push
        /* gas fails to assemble cfc1 for some archs (octeon).*/ \
        .set    mips1
+       SET_HARDFLOAT
        cfc1    a1, fcr31
        li      a2, ~(0x3f << 12)
        and     a2, a1
index 09ce45980758d91f51d7966cfc2d49549789771c..0b9082b6b6832d104a7994c0a6d44f13f61912cb 100644 (file)
@@ -68,9 +68,6 @@ void r4k_wait_irqoff(void)
                "       wait                    \n"
                "       .set    pop             \n");
        local_irq_enable();
-       __asm__(
-       "       .globl __pastwait       \n"
-       "__pastwait:                    \n");
 }
 
 /*
index 6001610cfe55f846a403633a13cfa8973a23e07a..dda800e9e73167d3637f972516743b12e25a9ddc 100644 (file)
 
 #ifdef HAVE_JUMP_LABEL
 
-#define J_RANGE_MASK ((1ul << 28) - 1)
+/*
+ * Define parameters for the standard MIPS and the microMIPS jump
+ * instruction encoding respectively:
+ *
+ * - the ISA bit of the target, either 0 or 1 respectively,
+ *
+ * - the amount the jump target address is shifted right to fit in the
+ *   immediate field of the machine instruction, either 2 or 1,
+ *
+ * - the mask determining the size of the jump region relative to the
+ *   delay-slot instruction, either 256MB or 128MB,
+ *
+ * - the jump target alignment, either 4 or 2 bytes.
+ */
+#define J_ISA_BIT      IS_ENABLED(CONFIG_CPU_MICROMIPS)
+#define J_RANGE_SHIFT  (2 - J_ISA_BIT)
+#define J_RANGE_MASK   ((1ul << (26 + J_RANGE_SHIFT)) - 1)
+#define J_ALIGN_MASK   ((1ul << J_RANGE_SHIFT) - 1)
 
 void arch_jump_label_transform(struct jump_entry *e,
                               enum jump_label_type type)
 {
+       union mips_instruction *insn_p;
        union mips_instruction insn;
-       union mips_instruction *insn_p =
-               (union mips_instruction *)(unsigned long)e->code;
 
-       /* Jump only works within a 256MB aligned region. */
-       BUG_ON((e->target & ~J_RANGE_MASK) != (e->code & ~J_RANGE_MASK));
+       insn_p = (union mips_instruction *)msk_isa16_mode(e->code);
+
+       /* Jump only works within an aligned region its delay slot is in. */
+       BUG_ON((e->target & ~J_RANGE_MASK) != ((e->code + 4) & ~J_RANGE_MASK));
 
-       /* Target must have 4 byte alignment. */
-       BUG_ON((e->target & 3) != 0);
+       /* Target must have the right alignment and ISA must be preserved. */
+       BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT);
 
        if (type == JUMP_LABEL_ENABLE) {
-               insn.j_format.opcode = j_op;
-               insn.j_format.target = (e->target & J_RANGE_MASK) >> 2;
+               insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op;
+               insn.j_format.target = e->target >> J_RANGE_SHIFT;
        } else {
                insn.word = 0; /* nop */
        }
 
        get_online_cpus();
        mutex_lock(&text_mutex);
-       *insn_p = insn;
+       if (IS_ENABLED(CONFIG_CPU_MICROMIPS)) {
+               insn_p->halfword[0] = insn.word >> 16;
+               insn_p->halfword[1] = insn.word;
+       } else
+               *insn_p = insn;
 
        flush_icache_range((unsigned long)insn_p,
                           (unsigned long)insn_p + sizeof(*insn_p));
index f31063dbdaebcffe4521be0d04d045c726ba85aa..5ce3b746cedc0bdea6e305cc72ef2121f0026053 100644 (file)
@@ -28,6 +28,8 @@
        .set    mips1
        /* Save floating point context */
 LEAF(_save_fp_context)
+       .set    push
+       SET_HARDFLOAT
        li      v0, 0                                   # assume success
        cfc1    t1,fcr31
        EX(swc1 $f0,(SC_FPREGS+0)(a0))
@@ -65,6 +67,7 @@ LEAF(_save_fp_context)
        EX(sw   t1,(SC_FPC_CSR)(a0))
        cfc1    t0,$0                           # implementation/version
        jr      ra
+       .set    pop
        .set    nomacro
         EX(sw  t0,(SC_FPC_EIR)(a0))
        .set    macro
@@ -80,6 +83,8 @@ LEAF(_save_fp_context)
  * stack frame which might have been changed by the user.
  */
 LEAF(_restore_fp_context)
+       .set    push
+       SET_HARDFLOAT
        li      v0, 0                                   # assume success
        EX(lw t0,(SC_FPC_CSR)(a0))
        EX(lwc1 $f0,(SC_FPREGS+0)(a0))
@@ -116,6 +121,7 @@ LEAF(_restore_fp_context)
        EX(lwc1 $f31,(SC_FPREGS+248)(a0))
        jr      ra
         ctc1   t0,fcr31
+       .set    pop
        END(_restore_fp_context)
        .set    reorder
 
index 20b7b040e76f1c4e8d9a019edae6014f3ee3fea5..435ea652f5fae7af10c392b884faecdc8ea430cf 100644 (file)
@@ -120,6 +120,9 @@ LEAF(_restore_fp)
 
 #define FPU_DEFAULT  0x00000000
 
+       .set push
+       SET_HARDFLOAT
+
 LEAF(_init_fpu)
        mfc0    t0, CP0_STATUS
        li      t1, ST0_CU1
@@ -165,3 +168,5 @@ LEAF(_init_fpu)
        mtc1    t0, $f31
        jr      ra
        END(_init_fpu)
+
+       .set pop
index 8352523568e6d7c993a5f42e52d5121c57ad81b8..6c160c67984c014e53a3a068698fdef58a9b9345 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
+/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
+#undef fp
+
        .macro  EX insn, reg, src
        .set    push
+       SET_HARDFLOAT
        .set    nomacro
 .ex\@: \insn   \reg, \src
        .set    pop
        .set    arch=r4000
 
 LEAF(_save_fp_context)
+       .set    push
+       SET_HARDFLOAT
        cfc1    t1, fcr31
+       .set    pop
 
 #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
        .set    push
+       SET_HARDFLOAT
 #ifdef CONFIG_CPU_MIPS32_R2
-       .set    mips64r2
+       .set    mips32r2
+       .set    fp=64
        mfc0    t0, CP0_STATUS
        sll     t0, t0, 5
        bgez    t0, 1f                  # skip storing odd if FR=0
@@ -64,6 +73,8 @@ LEAF(_save_fp_context)
 1:     .set    pop
 #endif
 
+       .set push
+       SET_HARDFLOAT
        /* Store the 16 even double precision registers */
        EX      sdc1 $f0, SC_FPREGS+0(a0)
        EX      sdc1 $f2, SC_FPREGS+16(a0)
@@ -84,11 +95,14 @@ LEAF(_save_fp_context)
        EX      sw t1, SC_FPC_CSR(a0)
        jr      ra
         li     v0, 0                                   # success
+       .set pop
        END(_save_fp_context)
 
 #ifdef CONFIG_MIPS32_COMPAT
        /* Save 32-bit process floating point context */
 LEAF(_save_fp_context32)
+       .set push
+       SET_HARDFLOAT
        cfc1    t1, fcr31
 
        mfc0    t0, CP0_STATUS
@@ -134,6 +148,7 @@ LEAF(_save_fp_context32)
        EX      sw t1, SC32_FPC_CSR(a0)
        cfc1    t0, $0                          # implementation/version
        EX      sw t0, SC32_FPC_EIR(a0)
+       .set pop
 
        jr      ra
         li     v0, 0                                   # success
@@ -150,8 +165,10 @@ LEAF(_restore_fp_context)
 
 #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
        .set    push
+       SET_HARDFLOAT
 #ifdef CONFIG_CPU_MIPS32_R2
-       .set    mips64r2
+       .set    mips32r2
+       .set    fp=64
        mfc0    t0, CP0_STATUS
        sll     t0, t0, 5
        bgez    t0, 1f                  # skip loading odd if FR=0
@@ -175,6 +192,8 @@ LEAF(_restore_fp_context)
        EX      ldc1 $f31, SC_FPREGS+248(a0)
 1:     .set pop
 #endif
+       .set push
+       SET_HARDFLOAT
        EX      ldc1 $f0, SC_FPREGS+0(a0)
        EX      ldc1 $f2, SC_FPREGS+16(a0)
        EX      ldc1 $f4, SC_FPREGS+32(a0)
@@ -192,6 +211,7 @@ LEAF(_restore_fp_context)
        EX      ldc1 $f28, SC_FPREGS+224(a0)
        EX      ldc1 $f30, SC_FPREGS+240(a0)
        ctc1    t1, fcr31
+       .set pop
        jr      ra
         li     v0, 0                                   # success
        END(_restore_fp_context)
@@ -199,6 +219,8 @@ LEAF(_restore_fp_context)
 #ifdef CONFIG_MIPS32_COMPAT
 LEAF(_restore_fp_context32)
        /* Restore an o32 sigcontext.  */
+       .set push
+       SET_HARDFLOAT
        EX      lw t1, SC32_FPC_CSR(a0)
 
        mfc0    t0, CP0_STATUS
@@ -242,6 +264,7 @@ LEAF(_restore_fp_context32)
        ctc1    t1, fcr31
        jr      ra
         li     v0, 0                                   # success
+       .set pop
        END(_restore_fp_context32)
 #endif
 
index 4c4ec1812420b873663d682d706860f394d7db00..64591e671878f41d9c4d0551806783b65578eb23 100644 (file)
@@ -22,6 +22,9 @@
 
 #include <asm/asmmacro.h>
 
+/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
+#undef fp
+
 /*
  * Offset to the current process status flags, the first 32 bytes of the
  * stack are not used.
        bgtz    a3, 1f
 
        /* Save 128b MSA vector context + scalar FP control & status. */
+       .set push
+       SET_HARDFLOAT
        cfc1    t1, fcr31
        msa_save_all    a0
+       .set pop        /* SET_HARDFLOAT */
+
        sw      t1, THREAD_FCR31(a0)
        b       2f
 
@@ -161,6 +168,9 @@ LEAF(_init_msa_upper)
 
 #define FPU_DEFAULT  0x00000000
 
+       .set push
+       SET_HARDFLOAT
+
 LEAF(_init_fpu)
        mfc0    t0, CP0_STATUS
        li      t1, ST0_CU1
@@ -232,7 +242,8 @@ LEAF(_init_fpu)
 
 #ifdef CONFIG_CPU_MIPS32_R2
        .set    push
-       .set    mips64r2
+       .set    mips32r2
+       .set    fp=64
        sll     t0, t0, 5                       # is Status.FR set?
        bgez    t0, 1f                          # no: skip setting upper 32b
 
@@ -291,3 +302,5 @@ LEAF(_init_fpu)
 #endif
        jr      ra
        END(_init_fpu)
+
+       .set pop        /* SET_HARDFLOAT */
index da0fbe46d83b040dc54a300d7be5324ce51f1ab3..47077380c15c43aca685a3aacbea837f8cc42a65 100644 (file)
@@ -18,6 +18,9 @@
 
        .set    noreorder
        .set    mips2
+       .set    push
+       SET_HARDFLOAT
+
        /* Save floating point context */
        LEAF(_save_fp_context)
        mfc0    t0,CP0_STATUS
@@ -85,3 +88,5 @@
 1:     jr      ra
         nop
        END(_restore_fp_context)
+
+       .set pop        /* SET_HARDFLOAT */
index 31b1b763cb298841eee156c61752687c4056809d..c5c4fd54d797221256e147a8a0be5278a8806df5 100644 (file)
@@ -94,12 +94,12 @@ int rtlx_open(int index, int can_sleep)
        int ret = 0;
 
        if (index >= RTLX_CHANNELS) {
-               pr_debug(KERN_DEBUG "rtlx_open index out of range\n");
+               pr_debug("rtlx_open index out of range\n");
                return -ENOSYS;
        }
 
        if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
-               pr_debug(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
+               pr_debug("rtlx_open channel %d already opened\n", index);
                ret = -EBUSY;
                goto out_fail;
        }
index 744cd10ba599e260b97e0a53da6d872792f7bd54..00cad1005a16d1fc1925166ec5746e5ac9890154 100644 (file)
@@ -579,3 +579,4 @@ EXPORT(sys_call_table)
        PTR     sys_seccomp
        PTR     sys_getrandom
        PTR     sys_memfd_create
+       PTR     sys_bpf                         /* 4355 */
index 002b1bc09c387c44dcd5ac4157a97ef8223344cb..5251565e344b48f1931f500f52494eadd4e51a04 100644 (file)
@@ -434,4 +434,5 @@ EXPORT(sys_call_table)
        PTR     sys_seccomp
        PTR     sys_getrandom
        PTR     sys_memfd_create
+       PTR     sys_bpf                         /* 5315 */
        .size   sys_call_table,.-sys_call_table
index ca6cbbe9805bf8cdc28657468e93390c1ff117eb..77e74398b828770fa8814ed831c2efd6cb412b40 100644 (file)
@@ -427,4 +427,5 @@ EXPORT(sysn32_call_table)
        PTR     sys_seccomp
        PTR     sys_getrandom
        PTR     sys_memfd_create
+       PTR     sys_bpf
        .size   sysn32_call_table,.-sysn32_call_table
index 9e10d11fbb84799840f48ca08143bf44aeddc644..6f8db9f728e8d7d3f22c0518434ebb844e544953 100644 (file)
@@ -564,4 +564,5 @@ EXPORT(sys32_call_table)
        PTR     sys_seccomp
        PTR     sys_getrandom
        PTR     sys_memfd_create
+       PTR     sys_bpf                         /* 4355 */
        .size   sys32_call_table,.-sys32_call_table
index b3b8f0d9d4a77b9ee4d2f02e0a2761a281ee87b1..f3b635f86c39c085ac67126929d4a7cec89e9702 100644 (file)
@@ -485,7 +485,7 @@ static void __init bootmem_init(void)
  * NOTE: historically plat_mem_setup did the entire platform initialization.
  *      This was rather impractical because it meant plat_mem_setup had to
  * get away without any kind of memory allocator.  To keep old code from
- * breaking plat_setup was just renamed to plat_setup and a second platform
+ * breaking plat_setup was just renamed to plat_mem_setup and a second platform
  * initialization hook for anything else was introduced.
  */
 
@@ -493,7 +493,7 @@ static int usermem __initdata;
 
 static int __init early_parse_mem(char *p)
 {
-       unsigned long start, size;
+       phys_t start, size;
 
        /*
         * If a user specifies memory size, we
@@ -683,7 +683,8 @@ static void __init arch_mem_init(char **cmdline_p)
        dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
        /* Tell bootmem about cma reserved memblock section */
        for_each_memblock(reserved, reg)
-               reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+               if (reg->size != 0)
+                       reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
 }
 
 static void __init resource_init(void)
index 1d57605e4615288a604403de1a7071d7112b20c0..16f1e4f2bf3c3c08896161106529b4a0c551dd9e 100644 (file)
@@ -658,13 +658,13 @@ static int signal_setup(void)
                save_fp_context = _save_fp_context;
                restore_fp_context = _restore_fp_context;
        } else {
-               save_fp_context = copy_fp_from_sigcontext;
-               restore_fp_context = copy_fp_to_sigcontext;
+               save_fp_context = copy_fp_to_sigcontext;
+               restore_fp_context = copy_fp_from_sigcontext;
        }
 #endif /* CONFIG_SMP */
 #else
-       save_fp_context = copy_fp_from_sigcontext;;
-       restore_fp_context = copy_fp_to_sigcontext;
+       save_fp_context = copy_fp_to_sigcontext;
+       restore_fp_context = copy_fp_from_sigcontext;
 #endif
 
        return 0;
index 1d2ee8a9be137d33293a402cc23eea35bb77c459..8776d0a34274f295c3c611ae33bceb00e25e1a8d 100644 (file)
@@ -4,7 +4,7 @@ config PICVUE
 
 config PICVUE_PROC
        tristate "PICVUE LCD display driver /proc interface"
-       depends on PICVUE
+       depends on PICVUE && PROC_FS
 
 config DS1603
        bool "DS1603 RTC driver"
index c17ef80cf65ab0f67946b515c24dab351f684acc..5d3238af9b5cc551ecb0ca9670b242b62f181a73 100644 (file)
        STOREB(t0, NBYTES-2(dst), .Ls_exc_p1\@)
 .Ldone\@:
        jr      ra
+        nop
        .if __memcpy == 1
        END(memcpy)
        .set __memcpy, 0
index 91615c2ef0cf969baeff215ca3d8a627e3851d2f..1ef365ab3cd3bfd93cafe61d6cef6fa919644d22 100644 (file)
@@ -34,7 +34,7 @@ static void dump_tlb(int first, int last)
                entrylo0 = read_c0_entrylo0();
 
                /* Unused entries have a virtual address of KSEG0.  */
-               if ((entryhi & 0xffffe000) != 0x80000000
+               if ((entryhi & 0xfffff000) != 0x80000000
                    && (entryhi & 0xfc0) == asid) {
                        /*
                         * Only print entries in use
@@ -43,7 +43,7 @@ static void dump_tlb(int first, int last)
 
                        printk("va=%08lx asid=%08lx"
                               "  [pa=%06lx n=%d d=%d v=%d g=%d]",
-                              (entryhi & 0xffffe000),
+                              (entryhi & 0xfffff000),
                               entryhi & 0xfc0,
                               entrylo0 & PAGE_MASK,
                               (entrylo0 & (1 << 11)) ? 1 : 0,
index f3af6995e2a6e9546175add0d38d0b555ecd1b61..7d12c0dded3ded2009f85ffd7ed7d6e52f645c0c 100644 (file)
@@ -40,9 +40,11 @@ FEXPORT(__strnlen_\func\()_nocheck_asm)
 .else
        EX(lbe, t0, (v0), .Lfault\@)
 .endif
-       PTR_ADDIU       v0, 1
+       .set            noreorder
        bnez            t0, 1b
-1:     PTR_SUBU        v0, a0
+1:      PTR_ADDIU      v0, 1
+       .set            reorder
+       PTR_SUBU        v0, a0
        jr              ra
        END(__strnlen_\func\()_asm)
 
index 0bb9cc9dc621f705dd77b139b0985c01213f9c8e..d87e03330b29ae0dd5e27e9e84536dcc96af6f5c 100644 (file)
@@ -11,7 +11,8 @@ obj-$(CONFIG_PCI) += pci.o
 # Serial port support
 #
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-obj-$(CONFIG_SERIAL_8250) += serial.o
+loongson-serial-$(CONFIG_SERIAL_8250) := serial.o
+obj-y += $(loongson-serial-m) $(loongson-serial-y)
 obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
 obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
 
index a217061beee3fe0b6b57a1b06a663d0de5d4850f..462e34d46b4a9fa2265532474ecda20d249e3f79 100644 (file)
@@ -91,6 +91,7 @@ EXPORT_SYMBOL(clk_put);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
+       unsigned int rate_khz = rate / 1000;
        struct cpufreq_frequency_table *pos;
        int ret = 0;
        int regval;
@@ -107,9 +108,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
                propagate_rate(clk);
 
        cpufreq_for_each_valid_entry(pos, loongson2_clockmod_table)
-               if (rate == pos->frequency)
+               if (rate_khz == pos->frequency)
                        break;
-       if (rate != pos->frequency)
+       if (rate_khz != pos->frequency)
                return -ENOTSUPP;
 
        clk->rate = rate;
index 37ed184398c6bbf8d017f130c73317ed2e548518..42323bcc5d28baf7279aacc50d15a4107c2c71b7 100644 (file)
@@ -33,6 +33,7 @@
 
 static struct node_data prealloc__node_data[MAX_NUMNODES];
 unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+EXPORT_SYMBOL(__node_distances);
 struct node_data *__node_data[MAX_NUMNODES];
 EXPORT_SYMBOL(__node_data);
 
index 7a4727795a707764fda6014bf5db92d06e63052d..cac529a405b881aaf6a0d46cd749a0789bb2c414 100644 (file)
@@ -584,11 +584,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                if (insn.i_format.rs == bc_op) {
                        preempt_disable();
                        if (is_fpu_owner())
-                               asm volatile(
-                                       ".set push\n"
-                                       "\t.set mips1\n"
-                                       "\tcfc1\t%0,$31\n"
-                                       "\t.set pop" : "=r" (fcr31));
+                               fcr31 = read_32bit_cp1_register(CP1_STATUS);
                        else
                                fcr31 = current->thread.fpu.fcr31;
                        preempt_enable();
@@ -1023,7 +1019,7 @@ emul:
                                        goto emul;
 
                                case cop1x_op:
-                                       if (cpu_has_mips_4_5 || cpu_has_mips64)
+                                       if (cpu_has_mips_4_5 || cpu_has_mips64 || cpu_has_mips32r2)
                                                /* its one of ours */
                                                goto emul;
 
@@ -1068,7 +1064,7 @@ emul:
                break;
 
        case cop1x_op:
-               if (!cpu_has_mips_4_5 && !cpu_has_mips64)
+               if (!cpu_has_mips_4_5 && !cpu_has_mips64 && !cpu_has_mips32r2)
                        return SIGILL;
 
                sig = fpux_emu(xcp, ctx, ir, fault_addr);
index fa6ebd4bc9e9ae9b28a058650d0f9f87011e4c2e..c3917e251f59393a5138b3d4c557886e4fa45286 100644 (file)
@@ -299,6 +299,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 
        local_irq_save(flags);
 
+       htw_stop();
        pid = read_c0_entryhi() & ASID_MASK;
        address &= (PAGE_MASK << 1);
        write_c0_entryhi(address | pid);
@@ -346,6 +347,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
                        tlb_write_indexed();
        }
        tlbw_use_hazard();
+       htw_start();
        flush_itlb_vm(vma);
        local_irq_restore(flags);
 }
@@ -422,6 +424,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
 
        local_irq_save(flags);
        /* Save old context and create impossible VPN2 value */
+       htw_stop();
        old_ctx = read_c0_entryhi();
        old_pagemask = read_c0_pagemask();
        wired = read_c0_wired();
@@ -443,6 +446,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
 
        write_c0_entryhi(old_ctx);
        write_c0_pagemask(old_pagemask);
+       htw_start();
 out:
        local_irq_restore(flags);
        return ret;
index a08dd53a1cc51a976d4608444d2a1307ce0865ed..e3328a96e80909b758a8d619b6a0f8398399d2da 100644 (file)
@@ -1062,6 +1062,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
 struct mips_huge_tlb_info {
        int huge_pte;
        int restore_scratch;
+       bool need_reload_pte;
 };
 
 static struct mips_huge_tlb_info
@@ -1076,6 +1077,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
 
        rv.huge_pte = scratch;
        rv.restore_scratch = 0;
+       rv.need_reload_pte = false;
 
        if (check_for_high_segbits) {
                UASM_i_MFC0(p, tmp, C0_BADVADDR);
@@ -1264,6 +1266,7 @@ static void build_r4000_tlb_refill_handler(void)
        } else {
                htlb_info.huge_pte = K0;
                htlb_info.restore_scratch = 0;
+               htlb_info.need_reload_pte = true;
                vmalloc_mode = refill_noscratch;
                /*
                 * create the plain linear handler
@@ -1300,7 +1303,8 @@ static void build_r4000_tlb_refill_handler(void)
        }
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
        uasm_l_tlb_huge_update(&l, p);
-       UASM_i_LW(&p, K0, 0, K1);
+       if (htlb_info.need_reload_pte)
+               UASM_i_LW(&p, htlb_info.huge_pte, 0, K1);
        build_huge_update_entries(&p, htlb_info.huge_pte, K1);
        build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
                                   htlb_info.restore_scratch);
@@ -1868,8 +1872,16 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l,
        uasm_l_smp_pgtable_change(l, *p);
 #endif
        iPTE_LW(p, wr.r1, wr.r2); /* get even pte */
-       if (!m4kc_tlbp_war())
+       if (!m4kc_tlbp_war()) {
                build_tlb_probe_entry(p);
+               if (cpu_has_htw) {
+                       /* race condition happens, leaving */
+                       uasm_i_ehb(p);
+                       uasm_i_mfc0(p, wr.r3, C0_INDEX);
+                       uasm_il_bltz(p, r, wr.r3, label_leave);
+                       uasm_i_nop(p);
+               }
+       }
        return wr;
 }
 
index b9510ea8db565d39761043b8e083926c48dc1b2b..6510ace272d43141b4d52d0a90f2cfd810b264d5 100644 (file)
@@ -5,8 +5,9 @@
 # Copyright (C) 2008 Wind River Systems, Inc.
 #   written by Ralf Baechle <ralf@linux-mips.org>
 #
-obj-y                          := malta-amon.o malta-display.o malta-init.o \
+obj-y                          := malta-display.o malta-init.o \
                                   malta-int.o malta-memory.o malta-platform.o \
                                   malta-reset.o malta-setup.o malta-time.o
 
+obj-$(CONFIG_MIPS_CMP)         += malta-amon.o
 obj-$(CONFIG_MIPS_MALTA_PM)    += malta-pm.o
index febf4334545e5dc21cae2baae586e3067b064c4f..2ae49e99eb6797b9e1466bd8487c763c7c19d837 100644 (file)
@@ -14,7 +14,6 @@ obj-y                         := sead3-lcd.o sead3-display.o sead3-init.o \
                                   sead3-setup.o sead3-time.o
 
 obj-y                          += sead3-i2c-dev.o sead3-i2c.o \
-                                  sead3-pic32-i2c-drv.o sead3-pic32-bus.o \
                                   leds-sead3.o sead3-leds.o
 
 obj-$(CONFIG_EARLY_PRINTK)     += sead3-console.o
index f70d5fc58ef51fe0bc81160e060c1a48ab4f0cec..795ae83894e0326b1ea75aeee762f52057c5ec70 100644 (file)
@@ -5,10 +5,8 @@
  *
  * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
  */
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <irq.h>
 
 struct resource sead3_i2c_resources[] = {
        {
@@ -30,8 +28,4 @@ static int __init sead3_i2c_init(void)
        return platform_device_register(&sead3_i2c_device);
 }
 
-module_init(sead3_i2c_init);
-
-MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("I2C probe driver for SEAD3");
+device_initcall(sead3_i2c_init);
index 20102a6d41410fbba6854edab6ee1199d50cc7fa..c427c57781865e13d52dc75ea2bb2f8db5db9ad7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
  */
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 
@@ -76,8 +76,4 @@ static int __init led_init(void)
        return platform_device_register(&fled_device);
 }
 
-module_init(led_init);
-
-MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("LED probe driver for SEAD-3");
+device_initcall(led_init);
diff --git a/arch/mips/mti-sead3/sead3-pic32-bus.c b/arch/mips/mti-sead3/sead3-pic32-bus.c
deleted file mode 100644 (file)
index 3b12aa5..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
- */
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/errno.h>
-
-#define PIC32_NULL     0x00
-#define PIC32_RD       0x01
-#define PIC32_SYSRD    0x02
-#define PIC32_WR       0x10
-#define PIC32_SYSWR    0x20
-#define PIC32_IRQ_CLR  0x40
-#define PIC32_STATUS   0x80
-
-#define DELAY() udelay(100)    /* FIXME: needed? */
-
-/* spinlock to ensure atomic access to PIC32 */
-static DEFINE_SPINLOCK(pic32_bus_lock);
-
-/* FIXME: io_remap these */
-static void __iomem *bus_xfer  = (void __iomem *)0xbf000600;
-static void __iomem *bus_status = (void __iomem *)0xbf000060;
-
-static inline unsigned int ioready(void)
-{
-       return readl(bus_status) & 1;
-}
-
-static inline void wait_ioready(void)
-{
-       do { } while (!ioready());
-}
-
-static inline void wait_ioclear(void)
-{
-       do { } while (ioready());
-}
-
-static inline void check_ioclear(void)
-{
-       if (ioready()) {
-               pr_debug("ioclear: initially busy\n");
-               do {
-                       (void) readl(bus_xfer);
-                       DELAY();
-               } while (ioready());
-               pr_debug("ioclear: cleared busy\n");
-       }
-}
-
-u32 pic32_bus_readl(u32 reg)
-{
-       unsigned long flags;
-       u32 status, val;
-
-       spin_lock_irqsave(&pic32_bus_lock, flags);
-
-       check_ioclear();
-
-       writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer);
-       DELAY();
-       wait_ioready();
-       status = readl(bus_xfer);
-       DELAY();
-       val = readl(bus_xfer);
-       wait_ioclear();
-
-       pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status);
-
-       spin_unlock_irqrestore(&pic32_bus_lock, flags);
-
-       return val;
-}
-
-void pic32_bus_writel(u32 val, u32 reg)
-{
-       unsigned long flags;
-       u32 status;
-
-       spin_lock_irqsave(&pic32_bus_lock, flags);
-
-       check_ioclear();
-
-       writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer);
-       DELAY();
-       writel(val, bus_xfer);
-       DELAY();
-       wait_ioready();
-       status = readl(bus_xfer);
-       wait_ioclear();
-
-       pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status);
-
-       spin_unlock_irqrestore(&pic32_bus_lock, flags);
-}
diff --git a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
deleted file mode 100644 (file)
index 80fe194..0000000
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
- */
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-
-#define PIC32_I2CxCON          0x0000
-#define PIC32_I2CxCONCLR       0x0004
-#define PIC32_I2CxCONSET       0x0008
-#define PIC32_I2CxCONINV       0x000C
-#define         I2CCON_ON              (1<<15)
-#define         I2CCON_FRZ             (1<<14)
-#define         I2CCON_SIDL            (1<<13)
-#define         I2CCON_SCLREL          (1<<12)
-#define         I2CCON_STRICT          (1<<11)
-#define         I2CCON_A10M            (1<<10)
-#define         I2CCON_DISSLW          (1<<9)
-#define         I2CCON_SMEN            (1<<8)
-#define         I2CCON_GCEN            (1<<7)
-#define         I2CCON_STREN           (1<<6)
-#define         I2CCON_ACKDT           (1<<5)
-#define         I2CCON_ACKEN           (1<<4)
-#define         I2CCON_RCEN            (1<<3)
-#define         I2CCON_PEN             (1<<2)
-#define         I2CCON_RSEN            (1<<1)
-#define         I2CCON_SEN             (1<<0)
-
-#define PIC32_I2CxSTAT         0x0010
-#define PIC32_I2CxSTATCLR      0x0014
-#define PIC32_I2CxSTATSET      0x0018
-#define PIC32_I2CxSTATINV      0x001C
-#define         I2CSTAT_ACKSTAT        (1<<15)
-#define         I2CSTAT_TRSTAT         (1<<14)
-#define         I2CSTAT_BCL            (1<<10)
-#define         I2CSTAT_GCSTAT         (1<<9)
-#define         I2CSTAT_ADD10          (1<<8)
-#define         I2CSTAT_IWCOL          (1<<7)
-#define         I2CSTAT_I2COV          (1<<6)
-#define         I2CSTAT_DA             (1<<5)
-#define         I2CSTAT_P              (1<<4)
-#define         I2CSTAT_S              (1<<3)
-#define         I2CSTAT_RW             (1<<2)
-#define         I2CSTAT_RBF            (1<<1)
-#define         I2CSTAT_TBF            (1<<0)
-
-#define PIC32_I2CxADD          0x0020
-#define PIC32_I2CxADDCLR       0x0024
-#define PIC32_I2CxADDSET       0x0028
-#define PIC32_I2CxADDINV       0x002C
-#define PIC32_I2CxMSK          0x0030
-#define PIC32_I2CxMSKCLR       0x0034
-#define PIC32_I2CxMSKSET       0x0038
-#define PIC32_I2CxMSKINV       0x003C
-#define PIC32_I2CxBRG          0x0040
-#define PIC32_I2CxBRGCLR       0x0044
-#define PIC32_I2CxBRGSET       0x0048
-#define PIC32_I2CxBRGINV       0x004C
-#define PIC32_I2CxTRN          0x0050
-#define PIC32_I2CxTRNCLR       0x0054
-#define PIC32_I2CxTRNSET       0x0058
-#define PIC32_I2CxTRNINV       0x005C
-#define PIC32_I2CxRCV          0x0060
-
-struct i2c_platform_data {
-       u32     base;
-       struct i2c_adapter adap;
-       u32     xfer_timeout;
-       u32     ack_timeout;
-       u32     ctl_timeout;
-};
-
-extern u32 pic32_bus_readl(u32 reg);
-extern void pic32_bus_writel(u32 val, u32 reg);
-
-static inline void
-StartI2C(struct i2c_platform_data *adap)
-{
-       pr_debug("StartI2C\n");
-       pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
-}
-
-static inline void
-StopI2C(struct i2c_platform_data *adap)
-{
-       pr_debug("StopI2C\n");
-       pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
-}
-
-static inline void
-AckI2C(struct i2c_platform_data *adap)
-{
-       pr_debug("AckI2C\n");
-       pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
-       pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
-}
-
-static inline void
-NotAckI2C(struct i2c_platform_data *adap)
-{
-       pr_debug("NakI2C\n");
-       pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
-       pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
-}
-
-static inline int
-IdleI2C(struct i2c_platform_data *adap)
-{
-       int i;
-
-       pr_debug("IdleI2C\n");
-       for (i = 0; i < adap->ctl_timeout; i++) {
-               if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
-                    (I2CCON_ACKEN | I2CCON_RCEN | I2CCON_PEN | I2CCON_RSEN |
-                     I2CCON_SEN)) == 0) &&
-                   ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
-                    (I2CSTAT_TRSTAT)) == 0))
-                       return 0;
-               udelay(1);
-       }
-       return -ETIMEDOUT;
-}
-
-static inline u32
-MasterWriteI2C(struct i2c_platform_data *adap, u32 byte)
-{
-       pr_debug("MasterWriteI2C\n");
-
-       pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
-
-       return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_IWCOL;
-}
-
-static inline u32
-MasterReadI2C(struct i2c_platform_data *adap)
-{
-       pr_debug("MasterReadI2C\n");
-
-       pic32_bus_writel(I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
-
-       while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & I2CCON_RCEN)
-               ;
-
-       pic32_bus_writel(I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
-
-       return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
-}
-
-static int
-do_address(struct i2c_platform_data *adap, unsigned int addr, int rd)
-{
-       pr_debug("doaddress\n");
-
-       IdleI2C(adap);
-       StartI2C(adap);
-       IdleI2C(adap);
-
-       addr <<= 1;
-       if (rd)
-               addr |= 1;
-
-       if (MasterWriteI2C(adap, addr))
-               return -EIO;
-       IdleI2C(adap);
-       if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_ACKSTAT)
-               return -EIO;
-       return 0;
-}
-
-static int
-i2c_read(struct i2c_platform_data *adap, unsigned char *buf,
-                   unsigned int len)
-{
-       int     i;
-       u32     data;
-
-       pr_debug("i2c_read\n");
-
-       i = 0;
-       while (i < len) {
-               data = MasterReadI2C(adap);
-               buf[i++] = data;
-               if (i < len)
-                       AckI2C(adap);
-               else
-                       NotAckI2C(adap);
-       }
-
-       StopI2C(adap);
-       IdleI2C(adap);
-       return 0;
-}
-
-static int
-i2c_write(struct i2c_platform_data *adap, unsigned char *buf,
-                    unsigned int len)
-{
-       int     i;
-       u32     data;
-
-       pr_debug("i2c_write\n");
-
-       i = 0;
-       while (i < len) {
-               data = buf[i];
-               if (MasterWriteI2C(adap, data))
-                       return -EIO;
-               IdleI2C(adap);
-               if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
-                   I2CSTAT_ACKSTAT)
-                       return -EIO;
-               i++;
-       }
-
-       StopI2C(adap);
-       IdleI2C(adap);
-       return 0;
-}
-
-static int
-platform_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
-{
-       struct i2c_platform_data *adap = i2c_adap->algo_data;
-       struct i2c_msg *p;
-       int i, err = 0;
-
-       pr_debug("platform_xfer\n");
-       for (i = 0; i < num; i++) {
-#define __BUFSIZE 80
-               int ii;
-               static char buf[__BUFSIZE];
-               char *b = buf;
-
-               p = &msgs[i];
-               b += sprintf(buf, " [%d bytes]", p->len);
-               if ((p->flags & I2C_M_RD) == 0) {
-                       for (ii = 0; ii < p->len; ii++) {
-                               if (b < &buf[__BUFSIZE-4]) {
-                                       b += sprintf(b, " %02x", p->buf[ii]);
-                               } else {
-                                       strcat(b, "...");
-                                       break;
-                               }
-                       }
-               }
-               pr_debug("xfer%d: DevAddr: %04x Op:%s Data:%s\n", i, p->addr,
-                        (p->flags & I2C_M_RD) ? "Rd" : "Wr", buf);
-       }
-
-
-       for (i = 0; !err && i < num; i++) {
-               p = &msgs[i];
-               err = do_address(adap, p->addr, p->flags & I2C_M_RD);
-               if (err || !p->len)
-                       continue;
-               if (p->flags & I2C_M_RD)
-                       err = i2c_read(adap, p->buf, p->len);
-               else
-                       err = i2c_write(adap, p->buf, p->len);
-       }
-
-       /* Return the number of messages processed, or the error code. */
-       if (err == 0)
-               err = num;
-
-       return err;
-}
-
-static u32
-platform_func(struct i2c_adapter *adap)
-{
-       pr_debug("platform_algo\n");
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static const struct i2c_algorithm platform_algo = {
-       .master_xfer    = platform_xfer,
-       .functionality  = platform_func,
-};
-
-static void i2c_platform_setup(struct i2c_platform_data *priv)
-{
-       pr_debug("i2c_platform_setup\n");
-
-       pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
-       pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
-       pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONSET);
-       pic32_bus_writel((I2CSTAT_BCL | I2CSTAT_IWCOL),
-               (priv->base + PIC32_I2CxSTATCLR));
-}
-
-static void i2c_platform_disable(struct i2c_platform_data *priv)
-{
-       pr_debug("i2c_platform_disable\n");
-}
-
-static int i2c_platform_probe(struct platform_device *pdev)
-{
-       struct i2c_platform_data *priv;
-       struct resource *r;
-       int ret;
-
-       pr_debug("i2c_platform_probe\n");
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!r)
-               return -ENODEV;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_platform_data),
-                           GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       /* FIXME: need to allocate resource in PIC32 space */
-#if 0
-       priv->base = bus_request_region(r->start, resource_size(r),
-                                         pdev->name);
-#else
-       priv->base = r->start;
-#endif
-       if (!priv->base)
-               return -EBUSY;
-
-       priv->xfer_timeout = 200;
-       priv->ack_timeout = 200;
-       priv->ctl_timeout = 200;
-
-       priv->adap.nr = pdev->id;
-       priv->adap.algo = &platform_algo;
-       priv->adap.algo_data = priv;
-       priv->adap.dev.parent = &pdev->dev;
-       strlcpy(priv->adap.name, "PIC32 I2C", sizeof(priv->adap.name));
-
-       i2c_platform_setup(priv);
-
-       ret = i2c_add_numbered_adapter(&priv->adap);
-       if (ret) {
-               i2c_platform_disable(priv);
-               return ret;
-       }
-
-       platform_set_drvdata(pdev, priv);
-       return 0;
-}
-
-static int i2c_platform_remove(struct platform_device *pdev)
-{
-       struct i2c_platform_data *priv = platform_get_drvdata(pdev);
-
-       pr_debug("i2c_platform_remove\n");
-       platform_set_drvdata(pdev, NULL);
-       i2c_del_adapter(&priv->adap);
-       i2c_platform_disable(priv);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-i2c_platform_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct i2c_platform_data *priv = platform_get_drvdata(pdev);
-
-       dev_dbg(&pdev->dev, "i2c_platform_disable\n");
-       i2c_platform_disable(priv);
-
-       return 0;
-}
-
-static int
-i2c_platform_resume(struct platform_device *pdev)
-{
-       struct i2c_platform_data *priv = platform_get_drvdata(pdev);
-
-       dev_dbg(&pdev->dev, "i2c_platform_setup\n");
-       i2c_platform_setup(priv);
-
-       return 0;
-}
-#else
-#define i2c_platform_suspend   NULL
-#define i2c_platform_resume    NULL
-#endif
-
-static struct platform_driver i2c_platform_driver = {
-       .driver = {
-               .name   = "i2c_pic32",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = i2c_platform_probe,
-       .remove         = i2c_platform_remove,
-       .suspend        = i2c_platform_suspend,
-       .resume         = i2c_platform_resume,
-};
-
-static int __init
-i2c_platform_init(void)
-{
-       pr_debug("i2c_platform_init\n");
-       return platform_driver_register(&i2c_platform_driver);
-}
-
-static void __exit
-i2c_platform_exit(void)
-{
-       pr_debug("i2c_platform_exit\n");
-       platform_driver_unregister(&i2c_platform_driver);
-}
-
-MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
-MODULE_DESCRIPTION("PIC32 I2C driver");
-MODULE_LICENSE("GPL");
-
-module_init(i2c_platform_init);
-module_exit(i2c_platform_exit);
index be358a8050c57c14377c1bcc44cd45b332b622b1..6b43af0a34d9dd39c4afd08526342bbdd514b068 100644 (file)
@@ -1,6 +1,10 @@
 obj-y                          += setup.o nlm_hal.o cop2-ex.o dt.o
 obj-$(CONFIG_SMP)              += wakeup.o
-obj-$(CONFIG_USB)              += usb-init.o
-obj-$(CONFIG_USB)              += usb-init-xlp2.o
-obj-$(CONFIG_SATA_AHCI)                += ahci-init.o
-obj-$(CONFIG_SATA_AHCI)                += ahci-init-xlp2.o
+ifdef CONFIG_USB
+obj-y                          += usb-init.o
+obj-y                          += usb-init-xlp2.o
+endif
+ifdef CONFIG_SATA_AHCI
+obj-y                          += ahci-init.o
+obj-y                          += ahci-init-xlp2.o
+endif
index 6854ed5097d2e61bb3f7f3e2937612a5d1058b07..83a1dfd8f0e3c34d02cbe24448f5c5407852f942 100644 (file)
@@ -92,7 +92,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame,
                                /* This marks the end of the previous function,
                                   which means we overran. */
                                break;
-                       stack_size = (unsigned) stack_adjustment;
+                       stack_size = (unsigned long) stack_adjustment;
                } else if (is_ra_save_ins(&ip)) {
                        int ra_slot = ip.i_format.simmediate;
                        if (ra_slot < 0)
index fa374fe3746ba344f30e2b14b8ff6c3669bc5c88..f7ac3edda1b211a512ae0afe6e633a421cda7664 100644 (file)
@@ -443,10 +443,8 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
        msg.data = 0xc00 | msixvec;
 
        ret = irq_set_msi_desc(xirq, desc);
-       if (ret < 0) {
-               destroy_irq(xirq);
+       if (ret < 0)
                return ret;
-       }
 
        write_msi_msg(xirq, &msg);
        return 0;
index 37fe8e7887e22ea417fc49ecf2eb96a324e425a8..d3ed15b2b2d1ff60d5ace5eafdebe073501eb6d9 100644 (file)
@@ -215,17 +215,12 @@ static int ltq_pci_probe(struct platform_device *pdev)
 
        pci_clear_flags(PCI_PROBE_ONLY);
 
-       res_cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        res_bridge = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res_cfg || !res_bridge) {
-               dev_err(&pdev->dev, "missing memory resources\n");
-               return -EINVAL;
-       }
-
        ltq_pci_membase = devm_ioremap_resource(&pdev->dev, res_bridge);
        if (IS_ERR(ltq_pci_membase))
                return PTR_ERR(ltq_pci_membase);
 
+       res_cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ltq_pci_mapped_cfg = devm_ioremap_resource(&pdev->dev, res_cfg);
        if (IS_ERR(ltq_pci_mapped_cfg))
                return PTR_ERR(ltq_pci_mapped_cfg);
index f914c753de21dcc9982a3f13ec007db9069d42a4..8d53d7a2ed45ca87e973a4db00ef8e2d330f96e6 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/time.h>
 
 #include <asm/irq_cpu.h>
+#include <asm/setup.h>
 
 #include <msp_int.h>
 
index b8df2f7b3328e61f8fc7d9da9f78b777bf829632..1207ec4dfb77021a6a114d776684ccfbe696ea00 100644 (file)
@@ -131,11 +131,11 @@ static int msp_cic_irq_set_affinity(struct irq_data *d,
        int cpu;
        unsigned long flags;
        unsigned int  mtflags;
-       unsigned long imask = (1 << (irq - MSP_CIC_INTBASE));
+       unsigned long imask = (1 << (d->irq - MSP_CIC_INTBASE));
        volatile u32 *cic_mask = (volatile u32 *)CIC_VPE0_MSK_REG;
 
        /* timer balancing should be disabled in kernel code */
-       BUG_ON(irq == MSP_INT_VPE0_TIMER || irq == MSP_INT_VPE1_TIMER);
+       BUG_ON(d->irq == MSP_INT_VPE0_TIMER || d->irq == MSP_INT_VPE1_TIMER);
 
        LOCK_CORE(flags, mtflags);
        /* enable if any of each VPE's TCs require this IRQ */
index a95c00f5fb9697ed90fa79d44ec887b498f680fc..a304bcc37e4fba137a5a1ee8bc792a50d7258e01 100644 (file)
@@ -107,6 +107,7 @@ static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
 }
 
 unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
+EXPORT_SYMBOL(__node_distances);
 
 static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b)
 {
index c8ed2c807e69cee3fa89f2a0e1a15d3edec70155..455c40d6d6251f84b856b116d4c0e036e4037bc1 100644 (file)
@@ -25,3 +25,4 @@ obj-$(CONFIG_SIBYTE_RHONE)    += swarm/
 obj-$(CONFIG_SIBYTE_SENTOSA)   += swarm/
 obj-$(CONFIG_SIBYTE_SWARM)     += swarm/
 obj-$(CONFIG_SIBYTE_BIGSUR)    += swarm/
+obj-$(CONFIG_SIBYTE_LITTLESUR) += swarm/
index e6ed0d897ccc7c8b4f08b2f12fc97edee223de1b..897ba3c12b3276b9071a56e70e67e7e39d28850e 100644 (file)
@@ -67,6 +67,10 @@ static inline void writel(u32 b, volatile void __iomem *addr)
 #define __raw_writew writew
 #define __raw_writel writel
 
+#define writeb_relaxed writeb
+#define writew_relaxed writew
+#define writel_relaxed writel
+
 /*****************************************************************************/
 /*
  * traditional input/output functions
diff --git a/arch/nios2/Kconfig b/arch/nios2/Kconfig
new file mode 100644 (file)
index 0000000..2361acf
--- /dev/null
@@ -0,0 +1,206 @@
+config NIOS2
+       def_bool y
+       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select CLKSRC_OF
+       select GENERIC_ATOMIC64
+       select GENERIC_CLOCKEVENTS
+       select GENERIC_CPU_DEVICES
+       select GENERIC_IRQ_PROBE
+       select GENERIC_IRQ_SHOW
+       select HAVE_ARCH_TRACEHOOK
+       select IRQ_DOMAIN
+       select MODULES_USE_ELF_RELA
+       select OF
+       select OF_EARLY_FLATTREE
+       select SOC_BUS
+       select SPARSE_IRQ
+       select USB_ARCH_HAS_HCD if USB_SUPPORT
+
+config GENERIC_CSUM
+       def_bool y
+
+config GENERIC_HWEIGHT
+       def_bool y
+
+config GENERIC_CALIBRATE_DELAY
+       def_bool y
+
+config NO_IOPORT_MAP
+       def_bool y
+
+config HAS_DMA
+       def_bool y
+
+config FPU
+       def_bool n
+
+config SWAP
+       def_bool n
+
+config RWSEM_GENERIC_SPINLOCK
+       def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+       def_bool n
+
+source "init/Kconfig"
+
+menu "Kernel features"
+
+source "kernel/Kconfig.preempt"
+
+source "kernel/Kconfig.freezer"
+
+source "kernel/Kconfig.hz"
+
+source "mm/Kconfig"
+
+config FORCE_MAX_ZONEORDER
+       int "Maximum zone order"
+       range 9 20
+       default "11"
+       help
+         The kernel memory allocator divides physically contiguous memory
+         blocks into "zones", where each zone is a power of two number of
+         pages.  This option selects the largest power of two that the kernel
+         keeps in the memory allocator.  If you need to allocate very large
+         blocks of physically contiguous memory, then you may need to
+         increase this value.
+
+         This config option is actually maximum order plus one. For example,
+         a value of 11 means that the largest free memory block is 2^10 pages.
+
+endmenu
+
+source "arch/nios2/platform/Kconfig.platform"
+
+menu "Processor type and features"
+
+config MMU
+       def_bool y
+
+config NR_CPUS
+       int
+       default "1"
+
+config NIOS2_ALIGNMENT_TRAP
+       bool "Catch alignment trap"
+       default y
+       help
+         Nios II CPUs cannot fetch/store data which is not bus aligned,
+         i.e., a 2 or 4 byte fetch must start at an address divisible by
+         2 or 4. Any non-aligned load/store instructions will be trapped and
+         emulated in software if you say Y here, which has a performance
+         impact.
+
+comment "Boot options"
+
+config CMDLINE_BOOL
+       bool "Default bootloader kernel arguments"
+       default y
+
+config CMDLINE
+       string "Default kernel command string"
+       default ""
+       depends on CMDLINE_BOOL
+       help
+         On some platforms, there is currently no way for the boot loader to
+         pass arguments to the kernel. For these platforms, you can supply
+         some command-line options at build time by entering them here.  In
+         other cases you can specify kernel args so that you don't have
+         to set them up in board prom initialization routines.
+
+config CMDLINE_FORCE
+       bool "Force default kernel command string"
+       depends on CMDLINE_BOOL
+       help
+         Set this to have arguments from the default kernel command string
+         override those passed by the boot loader.
+
+config NIOS2_CMDLINE_IGNORE_DTB
+       bool "Ignore kernel command string from DTB"
+       depends on CMDLINE_BOOL
+       depends on !CMDLINE_FORCE
+       default y
+       help
+         Set this to ignore the bootargs property from the devicetree's
+         chosen node and fall back to CMDLINE if nothing is passed.
+
+config NIOS2_PASS_CMDLINE
+       bool "Passed kernel command line from u-boot"
+       default n
+       help
+         Use bootargs env variable from u-boot for kernel command line.
+         will override "Default kernel command string".
+         Say N if you are unsure.
+
+endmenu
+
+menu "Advanced setup"
+
+config ADVANCED_OPTIONS
+       bool "Prompt for advanced kernel configuration options"
+       help
+
+comment "Default settings for advanced configuration options are used"
+       depends on !ADVANCED_OPTIONS
+
+config NIOS2_KERNEL_MMU_REGION_BASE_BOOL
+       bool "Set custom kernel MMU region base address"
+       depends on ADVANCED_OPTIONS
+       help
+         This option allows you to set the virtual address of the kernel MMU region.
+
+         Say N here unless you know what you are doing.
+
+config NIOS2_KERNEL_MMU_REGION_BASE
+       hex "Virtual base address of the kernel MMU region " if NIOS2_KERNEL_MMU_REGION_BASE_BOOL
+       default "0x80000000"
+       help
+         This option allows you to set the virtual base address of the kernel MMU region.
+
+config NIOS2_KERNEL_REGION_BASE_BOOL
+       bool "Set custom kernel region base address"
+       depends on ADVANCED_OPTIONS
+       help
+         This option allows you to set the virtual address of the kernel region.
+
+         Say N here unless you know what you are doing.
+
+config NIOS2_KERNEL_REGION_BASE
+       hex "Virtual base address of the kernel region " if NIOS2_KERNEL_REGION_BASE_BOOL
+       default "0xc0000000"
+
+config NIOS2_IO_REGION_BASE_BOOL
+       bool "Set custom I/O region base address"
+       depends on ADVANCED_OPTIONS
+       help
+         This option allows you to set the virtual address of the I/O region.
+
+         Say N here unless you know what you are doing.
+
+config NIOS2_IO_REGION_BASE
+       hex "Virtual base address of the I/O region" if NIOS2_IO_REGION_BASE_BOOL
+       default "0xe0000000"
+
+endmenu
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/nios2/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/nios2/Kconfig.debug b/arch/nios2/Kconfig.debug
new file mode 100644 (file)
index 0000000..8d4e6ba
--- /dev/null
@@ -0,0 +1,17 @@
+menu "Kernel hacking"
+
+config TRACE_IRQFLAGS_SUPPORT
+       def_bool y
+
+source "lib/Kconfig.debug"
+
+config DEBUG_STACK_USAGE
+       bool "Enable stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+endmenu
diff --git a/arch/nios2/Makefile b/arch/nios2/Makefile
new file mode 100644 (file)
index 0000000..e142c9e
--- /dev/null
@@ -0,0 +1,73 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2013 Altera Corporation
+# Copyright (C) 1994, 95, 96, 2003 by Wind River Systems
+# Written by Fredrik Markstrom
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" cleaning up for this architecture.
+#
+# Nios2 port by Wind River Systems Inc trough:
+#   fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+
+UTS_SYSNAME = Linux
+
+export MMU
+
+LIBGCC         := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+
+KBUILD_CFLAGS += -pipe -D__linux__ -D__ELF__
+KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MUL_SUPPORT),-mhw-mul,-mno-hw-mul)
+KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MULX_SUPPORT),-mhw-mulx,-mno-hw-mulx)
+KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_DIV_SUPPORT),-mhw-div,-mno-hw-div)
+KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_FPU_SUPPORT),-mcustom-fpu-cfg=60-1,)
+
+KBUILD_CFLAGS += -fno-optimize-sibling-calls
+KBUILD_CFLAGS += -DUTS_SYSNAME=\"$(UTS_SYSNAME)\"
+KBUILD_CFLAGS += -fno-builtin
+KBUILD_CFLAGS += -G 0
+
+head-y         := arch/nios2/kernel/head.o
+libs-y         += arch/nios2/lib/ $(LIBGCC)
+core-y         += arch/nios2/kernel/ arch/nios2/mm/
+core-y         += arch/nios2/platform/
+
+INSTALL_PATH ?= /tftpboot
+nios2-boot := arch/$(ARCH)/boot
+BOOT_TARGETS = vmImage zImage
+PHONY += $(BOOT_TARGETS) install
+KBUILD_IMAGE := $(nios2-boot)/vmImage
+
+ifneq ($(CONFIG_NIOS2_DTB_SOURCE),"")
+       core-y  += $(nios2-boot)/
+endif
+
+all: vmImage
+
+archclean:
+       $(Q)$(MAKE) $(clean)=$(nios2-boot)
+
+%.dtb:
+       $(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@
+
+dtbs:
+       $(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@
+
+$(BOOT_TARGETS): vmlinux
+       $(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@
+
+install:
+       $(Q)$(MAKE) $(build)=$(nios2-boot) BOOTIMAGE=$(KBUILD_IMAGE) install
+
+define archhelp
+  echo  '* vmImage         - Kernel-only image for U-Boot ($(KBUILD_IMAGE))'
+  echo  '  install         - Install kernel using'
+  echo  '                     (your) ~/bin/$(INSTALLKERNEL) or'
+  echo  '                     (distribution) /sbin/$(INSTALLKERNEL) or'
+  echo  '                     install to $$(INSTALL_PATH)'
+  echo  '  dtbs            - Build device tree blobs for enabled boards'
+endef
diff --git a/arch/nios2/boot/Makefile b/arch/nios2/boot/Makefile
new file mode 100644 (file)
index 0000000..59392dc
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# arch/nios2/boot/Makefile
+#
+# 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.
+#
+
+UIMAGE_LOADADDR = $(shell $(NM) vmlinux | awk '$$NF == "_stext" {print $$1}')
+UIMAGE_ENTRYADDR = $(shell $(NM) vmlinux | awk '$$NF == "_start" {print $$1}')
+UIMAGE_COMPRESSION = gzip
+
+OBJCOPYFLAGS_vmlinux.bin := -O binary
+
+targets += vmlinux.bin vmlinux.gz vmImage
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+       $(call if_changed,objcopy)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,gzip)
+
+$(obj)/vmImage: $(obj)/vmlinux.gz
+       $(call if_changed,uimage)
+       @$(kecho) 'Kernel: $@ is ready'
+
+# Rule to build device tree blobs
+DTB_SRC := $(patsubst "%",%,$(CONFIG_NIOS2_DTB_SOURCE))
+
+# Make sure the generated dtb gets removed during clean
+extra-$(CONFIG_NIOS2_DTB_SOURCE_BOOL) += system.dtb
+
+$(obj)/system.dtb: $(DTB_SRC) FORCE
+       $(call cmd,dtc)
+
+# Ensure system.dtb exists
+$(obj)/linked_dtb.o: $(obj)/system.dtb
+
+obj-$(CONFIG_NIOS2_DTB_SOURCE_BOOL) += linked_dtb.o
+
+targets += $(dtb-y)
+
+# Rule to build device tree blobs with make command
+$(obj)/%.dtb: $(src)/dts/%.dts FORCE
+       $(call if_changed_dep,dtc)
+
+$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
+
+clean-files := *.dtb
+
+install:
+       sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff --git a/arch/nios2/boot/dts/3c120_devboard.dts b/arch/nios2/boot/dts/3c120_devboard.dts
new file mode 100644 (file)
index 0000000..31c51f9
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *  Copyright (C) 2013 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file is generated by sopc2dts.
+ */
+
+/dts-v1/;
+
+/ {
+       model = "altr,qsys_ghrd_3c120";
+       compatible = "altr,qsys_ghrd_3c120";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu: cpu@0x0 {
+                       device_type = "cpu";
+                       compatible = "altr,nios2-1.0";
+                       reg = <0x00000000>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       clock-frequency = <125000000>;
+                       dcache-line-size = <32>;
+                       icache-line-size = <32>;
+                       dcache-size = <32768>;
+                       icache-size = <32768>;
+                       altr,implementation = "fast";
+                       altr,pid-num-bits = <8>;
+                       altr,tlb-num-ways = <16>;
+                       altr,tlb-num-entries = <128>;
+                       altr,tlb-ptr-sz = <7>;
+                       altr,has-div = <1>;
+                       altr,has-mul = <1>;
+                       altr,reset-addr = <0xc2800000>;
+                       altr,fast-tlb-miss-addr = <0xc7fff400>;
+                       altr,exception-addr = <0xd0000020>;
+                       altr,has-initda = <1>;
+                       altr,has-mmu = <1>;
+               };
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x10000000 0x08000000>,
+                       <0x07fff400 0x00000400>;
+       };
+
+       sopc@0 {
+               device_type = "soc";
+               ranges;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "altr,avalon", "simple-bus";
+               bus-frequency = <125000000>;
+
+               pb_cpu_to_io: bridge@0x8000000 {
+                       compatible = "simple-bus";
+                       reg = <0x08000000 0x00800000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x00002000 0x08002000 0x00002000>,
+                               <0x00004000 0x08004000 0x00000400>,
+                               <0x00004400 0x08004400 0x00000040>,
+                               <0x00004800 0x08004800 0x00000040>,
+                               <0x00004c80 0x08004c80 0x00000020>,
+                               <0x00004d50 0x08004d50 0x00000008>,
+                               <0x00008000 0x08008000 0x00000020>,
+                               <0x00400000 0x08400000 0x00000020>;
+
+                       timer_1ms: timer@0x400000 {
+                               compatible = "altr,timer-1.0";
+                               reg = <0x00400000 0x00000020>;
+                               interrupt-parent = <&cpu>;
+                               interrupts = <11>;
+                               clock-frequency = <125000000>;
+                       };
+
+                       timer_0: timer@0x8000 {
+                               compatible = "altr,timer-1.0";
+                               reg = < 0x00008000 0x00000020 >;
+                               interrupt-parent = < &cpu >;
+                               interrupts = < 5 >;
+                               clock-frequency = < 125000000 >;
+                       };
+
+                       jtag_uart: serial@0x4d50 {
+                               compatible = "altr,juart-1.0";
+                               reg = <0x00004d50 0x00000008>;
+                               interrupt-parent = <&cpu>;
+                               interrupts = <1>;
+                       };
+
+                       tse_mac: ethernet@0x4000 {
+                               compatible = "altr,tse-1.0";
+                               reg = <0x00004000 0x00000400>,
+                                       <0x00004400 0x00000040>,
+                                       <0x00004800 0x00000040>,
+                                       <0x00002000 0x00002000>;
+                               reg-names = "control_port", "rx_csr", "tx_csr", "s1";
+                               interrupt-parent = <&cpu>;
+                               interrupts = <2 3>;
+                               interrupt-names = "rx_irq", "tx_irq";
+                               rx-fifo-depth = <8192>;
+                               tx-fifo-depth = <8192>;
+                               max-frame-size = <1518>;
+                               local-mac-address = [ 00 00 00 00 00 00 ];
+                               phy-mode = "rgmii-id";
+                               phy-handle = <&phy0>;
+                               tse_mac_mdio: mdio {
+                                       compatible = "altr,tse-mdio";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       phy0: ethernet-phy@18 {
+                                               reg = <18>;
+                                               device_type = "ethernet-phy";
+                                       };
+                               };
+                       };
+
+                       uart: serial@0x4c80 {
+                               compatible = "altr,uart-1.0";
+                               reg = <0x00004c80 0x00000020>;
+                               interrupt-parent = <&cpu>;
+                               interrupts = <10>;
+                               current-speed = <115200>;
+                               clock-frequency = <62500000>;
+                       };
+               };
+
+               cfi_flash_64m: flash@0x0 {
+                       compatible = "cfi-flash";
+                       reg = <0x00000000 0x04000000>;
+                       bank-width = <2>;
+                       device-width = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       partition@800000 {
+                               reg = <0x00800000 0x01e00000>;
+                               label = "JFFS2 Filesystem";
+                       };
+               };
+       };
+
+       chosen {
+               bootargs = "debug console=ttyJ0,115200";
+       };
+};
diff --git a/arch/nios2/boot/install.sh b/arch/nios2/boot/install.sh
new file mode 100644 (file)
index 0000000..3cb3f46
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install" script for nios2 architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+verify () {
+       if [ ! -f "$1" ]; then
+               echo ""                                                   1>&2
+               echo " *** Missing file: $1"                              1>&2
+               echo ' *** You need to run "make" before "make install".' 1>&2
+               echo ""                                                   1>&2
+               exit 1
+       fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
+# User may have a custom install script
+
+if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
+if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+
+# Default install - same as make zlilo
+
+if [ -f $4/vmlinuz ]; then
+       mv $4/vmlinuz $4/vmlinuz.old
+fi
+
+if [ -f $4/System.map ]; then
+       mv $4/System.map $4/System.old
+fi
+
+cat $2 > $4/vmlinuz
+cp $3 $4/System.map
+
+sync
diff --git a/arch/nios2/boot/linked_dtb.S b/arch/nios2/boot/linked_dtb.S
new file mode 100644 (file)
index 0000000..071f922
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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/>.
+ *
+ */
+.section .dtb.init.rodata,"a"
+.incbin "arch/nios2/boot/system.dtb"
diff --git a/arch/nios2/configs/3c120_defconfig b/arch/nios2/configs/3c120_defconfig
new file mode 100644 (file)
index 0000000..87541f0
--- /dev/null
@@ -0,0 +1,77 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_SHMEM is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_NIOS2_MEM_BASE=0x10000000
+CONFIG_NIOS2_HW_MUL_SUPPORT=y
+CONFIG_NIOS2_HW_DIV_SUPPORT=y
+CONFIG_CUSTOM_CACHE_SETTINGS=y
+CONFIG_NIOS2_DCACHE_SIZE=0x8000
+CONFIG_NIOS2_ICACHE_SIZE=0x8000
+# CONFIG_NIOS2_CMDLINE_IGNORE_DTB is not set
+CONFIG_NIOS2_PASS_CMDLINE=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_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=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_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_NETDEVICES=y
+CONFIG_ALTERA_TSE=y
+CONFIG_MARVELL_PHY=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_ALTERA_JTAGUART=y
+CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE=y
+CONFIG_SERIAL_ALTERA_UART=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_ROOT_NFS=y
+CONFIG_SUNRPC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
new file mode 100644 (file)
index 0000000..bb160be
--- /dev/null
@@ -0,0 +1,66 @@
+generic-y += atomic.h
+generic-y += auxvec.h
+generic-y += barrier.h
+generic-y += bitops.h
+generic-y += bitsperlong.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += exec.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += hash.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.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 += local.h
+generic-y += mcs_spinlock.h
+generic-y += mman.h
+generic-y += module.h
+generic-y += msgbuf.h
+generic-y += param.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += preempt.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+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
+generic-y += sockios.h
+generic-y += spinlock.h
+generic-y += stat.h
+generic-y += statfs.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += types.h
+generic-y += unaligned.h
+generic-y += user.h
+generic-y += vga.h
+generic-y += xor.h
diff --git a/arch/nios2/include/asm/asm-macros.h b/arch/nios2/include/asm/asm-macros.h
new file mode 100644 (file)
index 0000000..29fa2e4
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Macro used to simplify coding multi-line assembler.
+ * Some of the bit test macro can simplify down to one line
+ * depending on the mask value.
+ *
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+#ifndef _ASM_NIOS2_ASMMACROS_H
+#define _ASM_NIOS2_ASMMACROS_H
+/*
+ * ANDs reg2 with mask and places the result in reg1.
+ *
+ * You cannnot use the same register for reg1 & reg2.
+ */
+
+.macro ANDI32  reg1, reg2, mask
+.if \mask & 0xffff
+       .if \mask & 0xffff0000
+               movhi   \reg1, %hi(\mask)
+               movui   \reg1, %lo(\mask)
+               and     \reg1, \reg1, \reg2
+       .else
+               andi    \reg1, \reg2, %lo(\mask)
+       .endif
+.else
+       andhi   \reg1, \reg2, %hi(\mask)
+.endif
+.endm
+
+/*
+ * ORs reg2 with mask and places the result in reg1.
+ *
+ * It is safe to use the same register for reg1 & reg2.
+ */
+
+.macro ORI32   reg1, reg2, mask
+.if \mask & 0xffff
+       .if \mask & 0xffff0000
+               orhi    \reg1, \reg2, %hi(\mask)
+               ori     \reg1, \reg2, %lo(\mask)
+       .else
+               ori     \reg1, \reg2, %lo(\mask)
+       .endif
+.else
+       orhi    \reg1, \reg2, %hi(\mask)
+.endif
+.endm
+
+/*
+ * XORs reg2 with mask and places the result in reg1.
+ *
+ * It is safe to use the same register for reg1 & reg2.
+ */
+
+.macro XORI32  reg1, reg2, mask
+.if \mask & 0xffff
+       .if \mask & 0xffff0000
+               xorhi   \reg1, \reg2, %hi(\mask)
+               xori    \reg1, \reg1, %lo(\mask)
+       .else
+               xori    \reg1, \reg2, %lo(\mask)
+       .endif
+.else
+       xorhi   \reg1, \reg2, %hi(\mask)
+.endif
+.endm
+
+/*
+ * This is a support macro for BTBZ & BTBNZ.  It checks
+ * the bit to make sure it is valid 32 value.
+ *
+ * It is safe to use the same register for reg1 & reg2.
+ */
+
+.macro BT      reg1, reg2, bit
+.if \bit > 31
+       .err
+.else
+       .if \bit < 16
+               andi    \reg1, \reg2, (1 << \bit)
+       .else
+               andhi   \reg1, \reg2, (1 << (\bit - 16))
+       .endif
+.endif
+.endm
+
+/*
+ * Tests the bit in reg2 and branches to label if the
+ * bit is zero.  The result of the bit test is stored in reg1.
+ *
+ * It is safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTBZ    reg1, reg2, bit, label
+       BT      \reg1, \reg2, \bit
+       beq     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bit in reg2 and branches to label if the
+ * bit is non-zero.  The result of the bit test is stored in reg1.
+ *
+ * It is safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTBNZ   reg1, reg2, bit, label
+       BT      \reg1, \reg2, \bit
+       bne     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bit in reg2 and then compliments the bit in reg2.
+ * The result of the bit test is stored in reg1.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTC     reg1, reg2, bit
+.if \bit > 31
+       .err
+.else
+       .if \bit < 16
+               andi    \reg1, \reg2, (1 << \bit)
+               xori    \reg2, \reg2, (1 << \bit)
+       .else
+               andhi   \reg1, \reg2, (1 << (\bit - 16))
+               xorhi   \reg2, \reg2, (1 << (\bit - 16))
+       .endif
+.endif
+.endm
+
+/*
+ * Tests the bit in reg2 and then sets the bit in reg2.
+ * The result of the bit test is stored in reg1.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTS     reg1, reg2, bit
+.if \bit > 31
+       .err
+.else
+       .if \bit < 16
+               andi    \reg1, \reg2, (1 << \bit)
+               ori     \reg2, \reg2, (1 << \bit)
+       .else
+               andhi   \reg1, \reg2, (1 << (\bit - 16))
+               orhi    \reg2, \reg2, (1 << (\bit - 16))
+       .endif
+.endif
+.endm
+
+/*
+ * Tests the bit in reg2 and then resets the bit in reg2.
+ * The result of the bit test is stored in reg1.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTR     reg1, reg2, bit
+.if \bit > 31
+       .err
+.else
+       .if \bit < 16
+               andi    \reg1, \reg2, (1 << \bit)
+               andi    \reg2, \reg2, %lo(~(1 << \bit))
+       .else
+               andhi   \reg1, \reg2, (1 << (\bit - 16))
+               andhi   \reg2, \reg2, %lo(~(1 << (\bit - 16)))
+       .endif
+.endif
+.endm
+
+/*
+ * Tests the bit in reg2 and then compliments the bit in reg2.
+ * The result of the bit test is stored in reg1.  If the
+ * original bit was zero it branches to label.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTCBZ   reg1, reg2, bit, label
+       BTC     \reg1, \reg2, \bit
+       beq     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bit in reg2 and then compliments the bit in reg2.
+ * The result of the bit test is stored in reg1.  If the
+ * original bit was non-zero it branches to label.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTCBNZ  reg1, reg2, bit, label
+       BTC     \reg1, \reg2, \bit
+       bne     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bit in reg2 and then sets the bit in reg2.
+ * The result of the bit test is stored in reg1.  If the
+ * original bit was zero it branches to label.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTSBZ   reg1, reg2, bit, label
+       BTS     \reg1, \reg2, \bit
+       beq     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bit in reg2 and then sets the bit in reg2.
+ * The result of the bit test is stored in reg1.  If the
+ * original bit was non-zero it branches to label.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTSBNZ  reg1, reg2, bit, label
+       BTS     \reg1, \reg2, \bit
+       bne     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bit in reg2 and then resets the bit in reg2.
+ * The result of the bit test is stored in reg1.  If the
+ * original bit was zero it branches to label.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTRBZ   reg1, reg2, bit, label
+       BTR     \reg1, \reg2, \bit
+       bne     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bit in reg2 and then resets the bit in reg2.
+ * The result of the bit test is stored in reg1.  If the
+ * original bit was non-zero it branches to label.
+ *
+ * It is NOT safe to use the same register for reg1 & reg2.
+ */
+
+.macro BTRBNZ  reg1, reg2, bit, label
+       BTR     \reg1, \reg2, \bit
+       bne     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bits in mask against reg2 stores the result in reg1.
+ * If the all the bits in the mask are zero it branches to label.
+ *
+ * It is safe to use the same register for reg1 & reg2.
+ */
+
+.macro TSTBZ   reg1, reg2, mask, label
+       ANDI32  \reg1, \reg2, \mask
+       beq     \reg1, r0, \label
+.endm
+
+/*
+ * Tests the bits in mask against reg2 stores the result in reg1.
+ * If the any of the bits in the mask are 1 it branches to label.
+ *
+ * It is safe to use the same register for reg1 & reg2.
+ */
+
+.macro TSTBNZ  reg1, reg2, mask, label
+       ANDI32  \reg1, \reg2, \mask
+       bne     \reg1, r0, \label
+.endm
+
+/*
+ * Pushes reg onto the stack.
+ */
+
+.macro PUSH    reg
+       addi    sp, sp, -4
+       stw     \reg, 0(sp)
+.endm
+
+/*
+ * Pops the top of the stack into reg.
+ */
+
+.macro POP     reg
+       ldw     \reg, 0(sp)
+       addi    sp, sp, 4
+.endm
+
+
+#endif /* _ASM_NIOS2_ASMMACROS_H */
diff --git a/arch/nios2/include/asm/asm-offsets.h b/arch/nios2/include/asm/asm-offsets.h
new file mode 100644 (file)
index 0000000..5b9f5e0
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ *  Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ *  Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 <generated/asm-offsets.h>
diff --git a/arch/nios2/include/asm/cache.h b/arch/nios2/include/asm/cache.h
new file mode 100644 (file)
index 0000000..2293cf5
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef _ASM_NIOS2_CACHE_H
+#define _ASM_NIOS2_CACHE_H
+
+#define NIOS2_DCACHE_SIZE      CONFIG_NIOS2_DCACHE_SIZE
+#define NIOS2_ICACHE_SIZE      CONFIG_NIOS2_ICACHE_SIZE
+#define NIOS2_DCACHE_LINE_SIZE CONFIG_NIOS2_DCACHE_LINE_SIZE
+#define NIOS2_ICACHE_LINE_SHIFT        5
+#define NIOS2_ICACHE_LINE_SIZE (1 << NIOS2_ICACHE_LINE_SHIFT)
+
+/* bytes per L1 cache line */
+#define L1_CACHE_SHIFT         NIOS2_ICACHE_LINE_SHIFT
+#define L1_CACHE_BYTES         NIOS2_ICACHE_LINE_SIZE
+
+#define ARCH_DMA_MINALIGN      L1_CACHE_BYTES
+
+#define __cacheline_aligned
+#define ____cacheline_aligned
+
+#endif
diff --git a/arch/nios2/include/asm/cacheflush.h b/arch/nios2/include/asm/cacheflush.h
new file mode 100644 (file)
index 0000000..52abba9
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2003 Microtronix Datacom Ltd.
+ * Copyright (C) 2000-2002 Greg Ungerer <gerg@snapgear.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_NIOS2_CACHEFLUSH_H
+#define _ASM_NIOS2_CACHEFLUSH_H
+
+#include <linux/mm_types.h>
+
+/*
+ * This flag is used to indicate that the page pointed to by a pte is clean
+ * and does not require cleaning before returning it to the user.
+ */
+#define PG_dcache_clean PG_arch_1
+
+struct mm_struct;
+
+extern void flush_cache_all(void);
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_dup_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+       unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
+       unsigned long pfn);
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+extern void flush_dcache_page(struct page *page);
+
+extern void flush_icache_range(unsigned long start, unsigned long end);
+extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+
+#define flush_cache_vmap(start, end)           flush_dcache_range(start, end)
+#define flush_cache_vunmap(start, end)         flush_dcache_range(start, end)
+
+extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+                               unsigned long user_vaddr,
+                               void *dst, void *src, int len);
+extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
+                               unsigned long user_vaddr,
+                               void *dst, void *src, int len);
+
+extern void flush_dcache_range(unsigned long start, unsigned long end);
+extern void invalidate_dcache_range(unsigned long start, unsigned long end);
+
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+
+#endif /* _ASM_NIOS2_CACHEFLUSH_H */
diff --git a/arch/nios2/include/asm/checksum.h b/arch/nios2/include/asm/checksum.h
new file mode 100644 (file)
index 0000000..6bc1f0d
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS_CHECKSUM_H
+#define _ASM_NIOS_CHECKSUM_H
+
+/* Take these from lib/checksum.c */
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+extern __wsum csum_partial_copy(const void *src, void *dst, int len,
+                               __wsum sum);
+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
+                                       int len, __wsum sum, int *csum_err);
+#define csum_partial_copy_nocheck(src, dst, len, sum)  \
+       csum_partial_copy((src), (dst), (len), (sum))
+
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+extern __sum16 ip_compute_csum(const void *buff, int len);
+
+/*
+ * Fold a partial checksum
+ */
+static inline __sum16 csum_fold(__wsum sum)
+{
+       __asm__ __volatile__(
+               "add    %0, %1, %0\n"
+               "cmpltu r8, %0, %1\n"
+               "srli   %0, %0, 16\n"
+               "add    %0, %0, r8\n"
+               "nor    %0, %0, %0\n"
+               : "=r" (sum)
+               : "r" (sum << 16), "0" (sum)
+               : "r8");
+       return (__force __sum16) sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+#define csum_tcpudp_nofold csum_tcpudp_nofold
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+                                       unsigned short len,
+                                       unsigned short proto,
+                                       __wsum sum)
+{
+       __asm__ __volatile__(
+               "add    %0, %1, %0\n"
+               "cmpltu r8, %0, %1\n"
+               "add    %0, %0, r8\n"   /* add carry */
+               "add    %0, %2, %0\n"
+               "cmpltu r8, %0, %2\n"
+               "add    %0, %0, r8\n"   /* add carry */
+               "add    %0, %3, %0\n"
+               "cmpltu r8, %0, %3\n"
+               "add    %0, %0, r8\n"   /* add carry */
+               : "=r" (sum), "=r" (saddr)
+               : "r" (daddr), "r" ((ntohs(len) << 16) + (proto * 256)),
+                 "0" (sum),
+                 "1" (saddr)
+               : "r8");
+
+       return sum;
+}
+
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+                                       unsigned short len,
+                                       unsigned short proto, __wsum sum)
+{
+       return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+}
+
+#endif /* _ASM_NIOS_CHECKSUM_H */
diff --git a/arch/nios2/include/asm/cmpxchg.h b/arch/nios2/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..8593871
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS2_CMPXCHG_H
+#define _ASM_NIOS2_CMPXCHG_H
+
+#include <linux/irqflags.h>
+
+#define xchg(ptr, x)   \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x)                ((volatile struct __xchg_dummy *)(x))
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+                                       int size)
+{
+       unsigned long tmp, flags;
+
+       local_irq_save(flags);
+
+       switch (size) {
+       case 1:
+               __asm__ __volatile__(
+                       "ldb    %0, %2\n"
+                       "stb    %1, %2\n"
+                       : "=&r" (tmp)
+                       : "r" (x), "m" (*__xg(ptr))
+                       : "memory");
+               break;
+       case 2:
+               __asm__ __volatile__(
+                       "ldh    %0, %2\n"
+                       "sth    %1, %2\n"
+                       : "=&r" (tmp)
+                       : "r" (x), "m" (*__xg(ptr))
+                       : "memory");
+               break;
+       case 4:
+               __asm__ __volatile__(
+                       "ldw    %0, %2\n"
+                       "stw    %1, %2\n"
+                       : "=&r" (tmp)
+                       : "r" (x), "m" (*__xg(ptr))
+                       : "memory");
+               break;
+       }
+
+       local_irq_restore(flags);
+       return tmp;
+}
+
+#include <asm-generic/cmpxchg.h>
+#include <asm-generic/cmpxchg-local.h>
+
+#endif /* _ASM_NIOS2_CMPXCHG_H */
diff --git a/arch/nios2/include/asm/cpuinfo.h b/arch/nios2/include/asm/cpuinfo.h
new file mode 100644 (file)
index 0000000..e88fcae
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _ASM_NIOS2_CPUINFO_H
+#define _ASM_NIOS2_CPUINFO_H
+
+#include <linux/types.h>
+
+struct cpuinfo {
+       /* Core CPU configuration */
+       char cpu_impl[12];
+       u32 cpu_clock_freq;
+       u32 mmu;
+       u32 has_div;
+       u32 has_mul;
+       u32 has_mulx;
+
+       /* CPU caches */
+       u32 icache_line_size;
+       u32 icache_size;
+       u32 dcache_line_size;
+       u32 dcache_size;
+
+       /* TLB */
+       u32 tlb_pid_num_bits;   /* number of bits used for the PID in TLBMISC */
+       u32 tlb_num_ways;
+       u32 tlb_num_ways_log2;
+       u32 tlb_num_entries;
+       u32 tlb_num_lines;
+       u32 tlb_ptr_sz;
+
+       /* Addresses */
+       u32 reset_addr;
+       u32 exception_addr;
+       u32 fast_tlb_miss_exc_addr;
+};
+
+extern struct cpuinfo cpuinfo;
+
+extern void setup_cpuinfo(void);
+
+#endif /* _ASM_NIOS2_CPUINFO_H */
diff --git a/arch/nios2/include/asm/delay.h b/arch/nios2/include/asm/delay.h
new file mode 100644 (file)
index 0000000..098e49b
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2014 Altera Corporation
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * 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_NIOS2_DELAY_H
+#define _ASM_NIOS2_DELAY_H
+
+#include <asm-generic/delay.h>
+
+/* Undefined functions to get compile-time errors */
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
+
+extern unsigned long loops_per_jiffy;
+
+#endif /* _ASM_NIOS2_DELAY_H */
diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h
new file mode 100644 (file)
index 0000000..b556723
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *
+ * 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_NIOS2_DMA_MAPPING_H
+#define _ASM_NIOS2_DMA_MAPPING_H
+
+#include <linux/scatterlist.h>
+#include <linux/cache.h>
+#include <asm/cacheflush.h>
+
+static inline void __dma_sync_for_device(void *vaddr, size_t size,
+                             enum dma_data_direction direction)
+{
+       switch (direction) {
+       case DMA_FROM_DEVICE:
+               invalidate_dcache_range((unsigned long)vaddr,
+                       (unsigned long)(vaddr + size));
+               break;
+       case DMA_TO_DEVICE:
+               /*
+                * We just need to flush the caches here , but Nios2 flush
+                * instruction will do both writeback and invalidate.
+                */
+       case DMA_BIDIRECTIONAL: /* flush and invalidate */
+               flush_dcache_range((unsigned long)vaddr,
+                       (unsigned long)(vaddr + size));
+               break;
+       default:
+               BUG();
+       }
+}
+
+static inline void __dma_sync_for_cpu(void *vaddr, size_t size,
+                             enum dma_data_direction direction)
+{
+       switch (direction) {
+       case DMA_BIDIRECTIONAL:
+       case DMA_FROM_DEVICE:
+               invalidate_dcache_range((unsigned long)vaddr,
+                       (unsigned long)(vaddr + size));
+               break;
+       case DMA_TO_DEVICE:
+               break;
+       default:
+               BUG();
+       }
+}
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+                          dma_addr_t *dma_handle, gfp_t flag);
+
+void dma_free_coherent(struct device *dev, size_t size,
+                        void *vaddr, dma_addr_t dma_handle);
+
+static inline dma_addr_t dma_map_single(struct device *dev, void *ptr,
+                                       size_t size,
+                                       enum dma_data_direction direction)
+{
+       BUG_ON(!valid_dma_direction(direction));
+       __dma_sync_for_device(ptr, size, direction);
+       return virt_to_phys(ptr);
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+                               size_t size, enum dma_data_direction direction)
+{
+}
+
+extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+       enum dma_data_direction direction);
+extern dma_addr_t dma_map_page(struct device *dev, struct page *page,
+       unsigned long offset, size_t size, enum dma_data_direction direction);
+extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+       size_t size, enum dma_data_direction direction);
+extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+       int nhwentries, enum dma_data_direction direction);
+extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+       size_t size, enum dma_data_direction direction);
+extern void dma_sync_single_for_device(struct device *dev,
+       dma_addr_t dma_handle, size_t size, enum dma_data_direction direction);
+extern void dma_sync_single_range_for_cpu(struct device *dev,
+       dma_addr_t dma_handle, unsigned long offset, size_t size,
+       enum dma_data_direction direction);
+extern void dma_sync_single_range_for_device(struct device *dev,
+       dma_addr_t dma_handle, unsigned long offset, size_t size,
+       enum dma_data_direction direction);
+extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+       int nelems, enum dma_data_direction direction);
+extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+       int nelems, enum dma_data_direction direction);
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+       return 1;
+}
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+       if (!dev->dma_mask || !dma_supported(dev, mask))
+               return -EIO;
+
+       *dev->dma_mask = mask;
+
+       return 0;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       return 0;
+}
+
+/*
+* dma_alloc_noncoherent() returns non-cacheable memory, so there's no need to
+* do any flushing here.
+*/
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+                                 enum dma_data_direction direction)
+{
+}
+
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+               void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+               void *cpu_addr, dma_addr_t dma_addr,
+               size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
+#endif /* _ASM_NIOS2_DMA_MAPPING_H */
diff --git a/arch/nios2/include/asm/elf.h b/arch/nios2/include/asm/elf.h
new file mode 100644 (file)
index 0000000..b7d655d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _ASM_NIOS2_ELF_H
+#define _ASM_NIOS2_ELF_H
+
+#include <uapi/asm/elf.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_ALTERA_NIOS2)
+
+#define ELF_PLAT_INIT(_r, load_addr)
+
+#define CORE_DUMP_USE_REGSET
+#define ELF_EXEC_PAGESIZE      4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   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                0xD0000000UL
+
+/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+   now struct_user_regs, they are different) */
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES        1
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+       int uses_interp);
+#define ELF_CORE_COPY_REGS(pr_reg, regs)                               \
+{ do {                                                                 \
+       /* Bleech. */                                                   \
+       pr_reg[0]  = regs->r8;                                          \
+       pr_reg[1]  = regs->r9;                                          \
+       pr_reg[2]  = regs->r10;                                         \
+       pr_reg[3]  = regs->r11;                                         \
+       pr_reg[4]  = regs->r12;                                         \
+       pr_reg[5]  = regs->r13;                                         \
+       pr_reg[6]  = regs->r14;                                         \
+       pr_reg[7]  = regs->r15;                                         \
+       pr_reg[8]  = regs->r1;                                          \
+       pr_reg[9]  = regs->r2;                                          \
+       pr_reg[10] = regs->r3;                                          \
+       pr_reg[11] = regs->r4;                                          \
+       pr_reg[12] = regs->r5;                                          \
+       pr_reg[13] = regs->r6;                                          \
+       pr_reg[14] = regs->r7;                                          \
+       pr_reg[15] = regs->orig_r2;                                     \
+       pr_reg[16] = regs->ra;                                          \
+       pr_reg[17] = regs->fp;                                          \
+       pr_reg[18] = regs->sp;                                          \
+       pr_reg[19] = regs->gp;                                          \
+       pr_reg[20] = regs->estatus;                                     \
+       pr_reg[21] = regs->ea;                                          \
+       pr_reg[22] = regs->orig_r7;                                     \
+       {                                                               \
+               struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \
+               pr_reg[23] = sw->r16;                                   \
+               pr_reg[24] = sw->r17;                                   \
+               pr_reg[25] = sw->r18;                                   \
+               pr_reg[26] = sw->r19;                                   \
+               pr_reg[27] = sw->r20;                                   \
+               pr_reg[28] = sw->r21;                                   \
+               pr_reg[29] = sw->r22;                                   \
+               pr_reg[30] = sw->r23;                                   \
+               pr_reg[31] = sw->fp;                                    \
+               pr_reg[32] = sw->gp;                                    \
+               pr_reg[33] = sw->ra;                                    \
+       }                                                               \
+} while (0); }
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this cpu supports.  */
+
+#define ELF_HWCAP      (0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.  */
+
+#define ELF_PLATFORM  (NULL)
+
+#endif /* _ASM_NIOS2_ELF_H */
diff --git a/arch/nios2/include/asm/entry.h b/arch/nios2/include/asm/entry.h
new file mode 100644 (file)
index 0000000..cf37f55
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS2_ENTRY_H
+#define _ASM_NIOS2_ENTRY_H
+
+#ifdef __ASSEMBLY__
+
+#include <asm/processor.h>
+#include <asm/registers.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * Standard Nios2 interrupt entry and exit macros.
+ * Must be called with interrupts disabled.
+ */
+.macro SAVE_ALL
+       rdctl   r24, estatus
+       andi    r24, r24, ESTATUS_EU
+       beq     r24, r0, 1f /* In supervisor mode, already on kernel stack */
+
+       movia   r24, _current_thread    /* Switch to current kernel stack */
+       ldw     r24, 0(r24)             /* using the thread_info */
+       addi    r24, r24, THREAD_SIZE-PT_REGS_SIZE
+       stw     sp, PT_SP(r24)          /* Save user stack before changing */
+       mov     sp, r24
+       br      2f
+
+1 :    mov     r24, sp
+       addi    sp, sp, -PT_REGS_SIZE   /* Backup the kernel stack pointer */
+       stw     r24, PT_SP(sp)
+2 :    stw     r1, PT_R1(sp)
+       stw     r2, PT_R2(sp)
+       stw     r3, PT_R3(sp)
+       stw     r4, PT_R4(sp)
+       stw     r5, PT_R5(sp)
+       stw     r6, PT_R6(sp)
+       stw     r7, PT_R7(sp)
+       stw     r8, PT_R8(sp)
+       stw     r9, PT_R9(sp)
+       stw     r10, PT_R10(sp)
+       stw     r11, PT_R11(sp)
+       stw     r12, PT_R12(sp)
+       stw     r13, PT_R13(sp)
+       stw     r14, PT_R14(sp)
+       stw     r15, PT_R15(sp)
+       stw     r2, PT_ORIG_R2(sp)
+       stw     r7, PT_ORIG_R7(sp)
+
+       stw     ra, PT_RA(sp)
+       stw     fp, PT_FP(sp)
+       stw     gp, PT_GP(sp)
+       rdctl   r24, estatus
+       stw     r24, PT_ESTATUS(sp)
+       stw     ea, PT_EA(sp)
+.endm
+
+.macro RESTORE_ALL
+       ldw     r1, PT_R1(sp)           /* Restore registers */
+       ldw     r2, PT_R2(sp)
+       ldw     r3, PT_R3(sp)
+       ldw     r4, PT_R4(sp)
+       ldw     r5, PT_R5(sp)
+       ldw     r6, PT_R6(sp)
+       ldw     r7, PT_R7(sp)
+       ldw     r8, PT_R8(sp)
+       ldw     r9, PT_R9(sp)
+       ldw     r10, PT_R10(sp)
+       ldw     r11, PT_R11(sp)
+       ldw     r12, PT_R12(sp)
+       ldw     r13, PT_R13(sp)
+       ldw     r14, PT_R14(sp)
+       ldw     r15, PT_R15(sp)
+       ldw     ra, PT_RA(sp)
+       ldw     fp, PT_FP(sp)
+       ldw     gp, PT_GP(sp)
+       ldw     r24, PT_ESTATUS(sp)
+       wrctl   estatus, r24
+       ldw     ea, PT_EA(sp)
+       ldw     sp, PT_SP(sp)           /* Restore sp last */
+.endm
+
+.macro SAVE_SWITCH_STACK
+       addi    sp, sp, -SWITCH_STACK_SIZE
+       stw     r16, SW_R16(sp)
+       stw     r17, SW_R17(sp)
+       stw     r18, SW_R18(sp)
+       stw     r19, SW_R19(sp)
+       stw     r20, SW_R20(sp)
+       stw     r21, SW_R21(sp)
+       stw     r22, SW_R22(sp)
+       stw     r23, SW_R23(sp)
+       stw     fp, SW_FP(sp)
+       stw     gp, SW_GP(sp)
+       stw     ra, SW_RA(sp)
+.endm
+
+.macro RESTORE_SWITCH_STACK
+       ldw     r16, SW_R16(sp)
+       ldw     r17, SW_R17(sp)
+       ldw     r18, SW_R18(sp)
+       ldw     r19, SW_R19(sp)
+       ldw     r20, SW_R20(sp)
+       ldw     r21, SW_R21(sp)
+       ldw     r22, SW_R22(sp)
+       ldw     r23, SW_R23(sp)
+       ldw     fp, SW_FP(sp)
+       ldw     gp, SW_GP(sp)
+       ldw     ra, SW_RA(sp)
+       addi    sp, sp, SWITCH_STACK_SIZE
+.endm
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_NIOS2_ENTRY_H */
diff --git a/arch/nios2/include/asm/io.h b/arch/nios2/include/asm/io.h
new file mode 100644 (file)
index 0000000..9102bfd
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 Altera Corporation
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS2_IO_H
+#define _ASM_NIOS2_IO_H
+
+#include <linux/types.h>
+#include <asm/pgtable-bits.h>
+
+/* PCI is not supported in nios2, set this to 0. */
+#define IO_SPACE_LIMIT 0
+
+#define readb_relaxed(addr)    readb(addr)
+#define readw_relaxed(addr)    readw(addr)
+#define readl_relaxed(addr)    readl(addr)
+
+#define writeb_relaxed(x, addr)        writeb(x, addr)
+#define writew_relaxed(x, addr)        writew(x, addr)
+#define writel_relaxed(x, addr)        writel(x, addr)
+
+extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size,
+                       unsigned long cacheflag);
+extern void __iounmap(void __iomem *addr);
+
+static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
+{
+       return __ioremap(physaddr, size, 0);
+}
+
+static inline void __iomem *ioremap_nocache(unsigned long physaddr,
+                                               unsigned long size)
+{
+       return __ioremap(physaddr, size, 0);
+}
+
+static inline void iounmap(void __iomem *addr)
+{
+       __iounmap(addr);
+}
+
+/* Pages to physical address... */
+#define page_to_phys(page)     virt_to_phys(page_to_virt(page))
+#define page_to_bus(page)      page_to_virt(page)
+
+/* Macros used for converting between virtual and physical mappings. */
+#define phys_to_virt(vaddr)    \
+       ((void *)((unsigned long)(vaddr) | CONFIG_NIOS2_KERNEL_REGION_BASE))
+/* Clear top 3 bits */
+#define virt_to_phys(vaddr)    \
+       ((unsigned long)((unsigned long)(vaddr) & ~0xE0000000))
+
+#include <asm-generic/io.h>
+
+#endif /* _ASM_NIOS2_IO_H */
diff --git a/arch/nios2/include/asm/irq.h b/arch/nios2/include/asm/irq.h
new file mode 100644 (file)
index 0000000..8e40fd9
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _ASM_NIOS2_IRQ_H
+#define _ASM_NIOS2_IRQ_H
+
+#define NIOS2_CPU_NR_IRQS      32
+
+#include <asm-generic/irq.h>
+#include <linux/irqdomain.h>
+
+#endif
diff --git a/arch/nios2/include/asm/irqflags.h b/arch/nios2/include/asm/irqflags.h
new file mode 100644 (file)
index 0000000..75ab92e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/registers.h>
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       return RDCTL(CTL_STATUS);
+}
+
+/*
+ * This will restore ALL status register flags, not only the interrupt
+ * mask flag.
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       WRCTL(CTL_STATUS, flags);
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       unsigned long flags;
+
+       flags = arch_local_save_flags();
+       arch_local_irq_restore(flags & ~STATUS_PIE);
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       unsigned long flags;
+
+       flags = arch_local_save_flags();
+       arch_local_irq_restore(flags | STATUS_PIE);
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags & STATUS_PIE) == 0;
+}
+
+static inline int arch_irqs_disabled(void)
+{
+       return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+
+       flags = arch_local_save_flags();
+       arch_local_irq_restore(flags & ~STATUS_PIE);
+       return flags;
+}
+
+#endif /* _ASM_IRQFLAGS_H */
diff --git a/arch/nios2/include/asm/linkage.h b/arch/nios2/include/asm/linkage.h
new file mode 100644 (file)
index 0000000..e0c6dec
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef _ASM_NIOS2_LINKAGE_H
+#define _ASM_NIOS2_LINKAGE_H
+
+/* This file is required by include/linux/linkage.h */
+#define __ALIGN .align 4
+#define __ALIGN_STR ".align 4"
+
+#endif
diff --git a/arch/nios2/include/asm/mmu.h b/arch/nios2/include/asm/mmu.h
new file mode 100644 (file)
index 0000000..d9c0b10
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS2_MMU_H
+#define _ASM_NIOS2_MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+#endif /* _ASM_NIOS2_MMU_H */
diff --git a/arch/nios2/include/asm/mmu_context.h b/arch/nios2/include/asm/mmu_context.h
new file mode 100644 (file)
index 0000000..294b4b1
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * based on MIPS asm/mmu_context.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_NIOS2_MMU_CONTEXT_H
+#define _ASM_NIOS2_MMU_CONTEXT_H
+
+#include <asm-generic/mm_hooks.h>
+
+extern void mmu_context_init(void);
+extern unsigned long get_pid_from_context(mm_context_t *ctx);
+
+/*
+ * For the fast tlb miss handlers, we keep a pointer to the current pgd.
+ * processor.
+ */
+extern pgd_t *pgd_current;
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/*
+ * Initialize the context related info for a new mm_struct instance.
+ *
+ * Set all new contexts to 0, that way the generation will never match
+ * the currently running generation when this context is switched in.
+ */
+static inline int init_new_context(struct task_struct *tsk,
+                                       struct mm_struct *mm)
+{
+       mm->context = 0;
+       return 0;
+}
+
+/*
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+static inline void destroy_context(struct mm_struct *mm)
+{
+}
+
+void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+               struct task_struct *tsk);
+
+static inline void deactivate_mm(struct task_struct *tsk,
+                               struct mm_struct *mm)
+{
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+void activate_mm(struct mm_struct *prev, struct mm_struct *next);
+
+#endif /* _ASM_NIOS2_MMU_CONTEXT_H */
diff --git a/arch/nios2/include/asm/mutex.h b/arch/nios2/include/asm/mutex.h
new file mode 100644 (file)
index 0000000..ff6101a
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/mutex-dec.h>
diff --git a/arch/nios2/include/asm/page.h b/arch/nios2/include/asm/page.h
new file mode 100644 (file)
index 0000000..4b32d6f
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * MMU support based on asm/page.h from mips which is:
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ *
+ * 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_NIOS2_PAGE_H
+#define _ASM_NIOS2_PAGE_H
+
+#include <linux/pfn.h>
+#include <linux/const.h>
+
+/*
+ * PAGE_SHIFT determines the page size
+ */
+#define PAGE_SHIFT     12
+#define PAGE_SIZE      (_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK      (~(PAGE_SIZE - 1))
+
+/*
+ * PAGE_OFFSET -- the first address of the first page of memory.
+ */
+#define PAGE_OFFSET    \
+       (CONFIG_NIOS2_MEM_BASE + CONFIG_NIOS2_KERNEL_REGION_BASE)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This gives the physical RAM offset.
+ */
+#define PHYS_OFFSET            CONFIG_NIOS2_MEM_BASE
+
+/*
+ * It's normally defined only for FLATMEM config but it's
+ * used in our early mem init code for all memory models.
+ * So always define it.
+ */
+#define ARCH_PFN_OFFSET                PFN_UP(PHYS_OFFSET)
+
+#define clear_page(page)       memset((page), 0, PAGE_SIZE)
+#define copy_page(to, from)    memcpy((to), (from), PAGE_SIZE)
+
+struct page;
+
+extern void clear_user_page(void *addr, unsigned long vaddr, struct page *page);
+extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+                               struct page *to);
+
+/*
+ * These are used to make use of C type-checking.
+ */
+typedef struct page *pgtable_t;
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)     ((x).pte)
+#define pgd_val(x)     ((x).pgd)
+#define pgprot_val(x)  ((x).pgprot)
+
+#define __pte(x)       ((pte_t) { (x) })
+#define __pgd(x)       ((pgd_t) { (x) })
+#define __pgprot(x)    ((pgprot_t) { (x) })
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+extern unsigned long memory_size;
+
+extern struct page *mem_map;
+
+#endif /* !__ASSEMBLY__ */
+
+# define __pa(x)               \
+       ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
+# define __va(x)               \
+       ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+
+#define page_to_virt(page)     \
+       ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
+
+# define pfn_to_kaddr(pfn)     __va((pfn) << PAGE_SHIFT)
+# define pfn_valid(pfn)                ((pfn) >= ARCH_PFN_OFFSET &&    \
+                                       (pfn) < max_mapnr)
+
+# define virt_to_page(vaddr)   pfn_to_page(PFN_DOWN(virt_to_phys(vaddr)))
+# define virt_addr_valid(vaddr)        pfn_valid(PFN_DOWN(virt_to_phys(vaddr)))
+
+# define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \
+                                VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+# define UNCAC_ADDR(addr)      \
+       ((void *)((unsigned)(addr) | CONFIG_NIOS2_IO_REGION_BASE))
+# define CAC_ADDR(addr)                \
+       ((void *)(((unsigned)(addr) & ~CONFIG_NIOS2_IO_REGION_BASE) |   \
+               CONFIG_NIOS2_KERNEL_REGION_BASE))
+
+#include <asm-generic/memory_model.h>
+
+#include <asm-generic/getorder.h>
+
+#endif /* _ASM_NIOS2_PAGE_H */
diff --git a/arch/nios2/include/asm/pgalloc.h b/arch/nios2/include/asm/pgalloc.h
new file mode 100644 (file)
index 0000000..6e2985e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 2001, 2003 by Ralf Baechle
+ * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc.
+ */
+
+#ifndef _ASM_NIOS2_PGALLOC_H
+#define _ASM_NIOS2_PGALLOC_H
+
+#include <linux/mm.h>
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+       pte_t *pte)
+{
+       set_pmd(pmd, __pmd((unsigned long)pte));
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+       pgtable_t pte)
+{
+       set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
+}
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+/*
+ * Initialize a new pmd table with invalid pointers.
+ */
+extern void pmd_init(unsigned long page, unsigned long pagetable);
+
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+       free_pages((unsigned long)pgd, PGD_ORDER);
+}
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+       unsigned long address)
+{
+       pte_t *pte;
+
+       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO,
+                                       PTE_ORDER);
+
+       return pte;
+}
+
+static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
+       unsigned long address)
+{
+       struct page *pte;
+
+       pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+       if (pte) {
+               if (!pgtable_page_ctor(pte)) {
+                       __free_page(pte);
+                       return NULL;
+               }
+               clear_highpage(pte);
+       }
+       return pte;
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+       free_pages((unsigned long)pte, PTE_ORDER);
+}
+
+static inline void pte_free(struct mm_struct *mm, struct page *pte)
+{
+       pgtable_page_dtor(pte);
+       __free_pages(pte, PTE_ORDER);
+}
+
+#define __pte_free_tlb(tlb, pte, addr)                         \
+       do {                                                    \
+               pgtable_page_dtor(pte);                         \
+               tlb_remove_page((tlb), (pte));                  \
+       } while (0)
+
+#define check_pgt_cache()      do { } while (0)
+
+#endif /* _ASM_NIOS2_PGALLOC_H */
diff --git a/arch/nios2/include/asm/pgtable-bits.h b/arch/nios2/include/asm/pgtable-bits.h
new file mode 100644 (file)
index 0000000..ce9e706
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *
+ * 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_NIOS2_PGTABLE_BITS_H
+#define _ASM_NIOS2_PGTABLE_BITS_H
+
+/*
+ * These are actual hardware defined protection bits in the tlbacc register
+ * which looks like this:
+ *
+ * 31 30 ... 26 25 24 23 22 21 20 19 18 ...  1  0
+ * ignored........  C  R  W  X  G PFN............
+ */
+#define _PAGE_GLOBAL   (1<<20)
+#define _PAGE_EXEC     (1<<21)
+#define _PAGE_WRITE    (1<<22)
+#define _PAGE_READ     (1<<23)
+#define _PAGE_CACHED   (1<<24) /* C: data access cacheable */
+
+/*
+ * Software defined bits. They are ignored by the hardware and always read back
+ * as zero, but can be written as non-zero.
+ */
+#define _PAGE_PRESENT  (1<<25) /* PTE contains a translation */
+#define _PAGE_ACCESSED (1<<26) /* page referenced */
+#define _PAGE_DIRTY    (1<<27) /* dirty page */
+#define _PAGE_FILE     (1<<28) /* PTE used for file mapping or swap */
+
+#endif /* _ASM_NIOS2_PGTABLE_BITS_H */
diff --git a/arch/nios2/include/asm/pgtable.h b/arch/nios2/include/asm/pgtable.h
new file mode 100644 (file)
index 0000000..ccbaffd
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *
+ * Based on asm/pgtable-32.h from mips which is:
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc.
+ *
+ * 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_NIOS2_PGTABLE_H
+#define _ASM_NIOS2_PGTABLE_H
+
+#include <linux/io.h>
+#include <linux/bug.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+#include <asm/pgtable-bits.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+#define FIRST_USER_ADDRESS     0
+
+#define VMALLOC_START          CONFIG_NIOS2_KERNEL_MMU_REGION_BASE
+#define VMALLOC_END            (CONFIG_NIOS2_KERNEL_REGION_BASE - 1)
+
+struct mm_struct;
+
+/* Helper macro */
+#define MKP(x, w, r) __pgprot(_PAGE_PRESENT | _PAGE_CACHED |           \
+                               ((x) ? _PAGE_EXEC : 0) |                \
+                               ((r) ? _PAGE_READ : 0) |                \
+                               ((w) ? _PAGE_WRITE : 0))
+/*
+ * These are the macros that generic kernel code needs
+ * (to populate protection_map[])
+ */
+
+/* Remove W bit on private pages for COW support */
+#define __P000 MKP(0, 0, 0)
+#define __P001 MKP(0, 0, 1)
+#define __P010 MKP(0, 0, 0)    /* COW */
+#define __P011 MKP(0, 0, 1)    /* COW */
+#define __P100 MKP(1, 0, 0)
+#define __P101 MKP(1, 0, 1)
+#define __P110 MKP(1, 0, 0)    /* COW */
+#define __P111 MKP(1, 0, 1)    /* COW */
+
+/* Shared pages can have exact HW mapping */
+#define __S000 MKP(0, 0, 0)
+#define __S001 MKP(0, 0, 1)
+#define __S010 MKP(0, 1, 0)
+#define __S011 MKP(0, 1, 1)
+#define __S100 MKP(1, 0, 0)
+#define __S101 MKP(1, 0, 1)
+#define __S110 MKP(1, 1, 0)
+#define __S111 MKP(1, 1, 1)
+
+/* Used all over the kernel */
+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_CACHED | _PAGE_READ | \
+                            _PAGE_WRITE | _PAGE_EXEC | _PAGE_GLOBAL)
+
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_CACHED | _PAGE_READ | \
+                            _PAGE_WRITE | _PAGE_ACCESSED)
+
+#define PAGE_COPY MKP(0, 0, 1)
+
+#define PGD_ORDER      0
+#define PTE_ORDER      0
+
+#define PTRS_PER_PGD   ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
+#define PTRS_PER_PTE   ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
+
+#define USER_PTRS_PER_PGD      \
+       (CONFIG_NIOS2_KERNEL_MMU_REGION_BASE / PGDIR_SIZE)
+
+#define PGDIR_SHIFT    22
+#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK     (~(PGDIR_SIZE-1))
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+#define ZERO_PAGE(vaddr)       (virt_to_page(empty_zero_page))
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)];
+
+/*
+ * (pmds are folded into puds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+static inline void set_pmd(pmd_t *pmdptr, pmd_t pmdval)
+{
+       pmdptr->pud.pgd.pgd = pmdval.pud.pgd.pgd;
+}
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(addr)                (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+#define pgd_offset(mm, addr)   ((mm)->pgd + pgd_index(addr))
+
+static inline int pte_write(pte_t pte)         \
+       { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte)         \
+       { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte)         \
+       { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)          \
+       { return pte_val(pte) & _PAGE_FILE; }
+static inline int pte_special(pte_t pte)       { return 0; }
+
+#define pgprot_noncached pgprot_noncached
+
+static inline pgprot_t pgprot_noncached(pgprot_t _prot)
+{
+       unsigned long prot = pgprot_val(_prot);
+
+       prot &= ~_PAGE_CACHED;
+
+       return __pgprot(prot);
+}
+
+static inline int pte_none(pte_t pte)
+{
+       return !(pte_val(pte) & ~(_PAGE_GLOBAL|0xf));
+}
+
+static inline int pte_present(pte_t pte)       \
+       { return pte_val(pte) & _PAGE_PRESENT; }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_WRITE;
+       return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_DIRTY;
+       return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+       pte_val(pte) &= ~_PAGE_ACCESSED;
+       return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_WRITE;
+       return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_DIRTY;
+       return pte;
+}
+
+static inline pte_t pte_mkspecial(pte_t pte)   { return pte; }
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+       pte_val(pte) |= _PAGE_ACCESSED;
+       return pte;
+}
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+       const unsigned long mask = _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC;
+
+       pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+       return pte;
+}
+
+static inline int pmd_present(pmd_t pmd)
+{
+       return (pmd_val(pmd) != (unsigned long) invalid_pte_table)
+                       && (pmd_val(pmd) != 0UL);
+}
+
+static inline void pmd_clear(pmd_t *pmdp)
+{
+       pmd_val(*pmdp) = (unsigned long) invalid_pte_table;
+}
+
+#define pte_pfn(pte)           (pte_val(pte) & 0xfffff)
+#define pfn_pte(pfn, prot)     (__pte(pfn | pgprot_val(prot)))
+#define pte_page(pte)          (pfn_to_page(pte_pfn(pte)))
+
+/*
+ * Store a linux PTE into the linux page table.
+ */
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+       *ptep = pteval;
+}
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t pteval)
+{
+       unsigned long paddr = page_to_virt(pte_page(pteval));
+
+       flush_dcache_range(paddr, paddr + PAGE_SIZE);
+       set_pte(ptep, pteval);
+}
+
+static inline int pmd_none(pmd_t pmd)
+{
+       return (pmd_val(pmd) ==
+               (unsigned long) invalid_pte_table) || (pmd_val(pmd) == 0UL);
+}
+
+#define pmd_bad(pmd)   (pmd_val(pmd) & ~PAGE_MASK)
+
+static inline void pte_clear(struct mm_struct *mm,
+                               unsigned long addr, pte_t *ptep)
+{
+       pte_t null;
+
+       pte_val(null) = (addr >> PAGE_SHIFT) & 0xf;
+
+       set_pte_at(mm, addr, ptep, null);
+       flush_tlb_one(addr);
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page, prot)     (pfn_pte(page_to_pfn(page), prot))
+
+#define pte_unmap(pte) do { } while (0)
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define pmd_phys(pmd)          virt_to_phys((void *)pmd_val(pmd))
+#define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+#define pmd_page_vaddr(pmd)    pmd_val(pmd)
+
+#define pte_offset_map(dir, addr)                      \
+       ((pte_t *) page_address(pmd_page(*dir)) +       \
+        (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)     pgd_offset(&init_mm, addr)
+
+/* Get the address to the PTE for a vaddr in specific directory */
+#define pte_offset_kernel(dir, addr)                   \
+       ((pte_t *) pmd_page_vaddr(*(dir)) +             \
+        (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+
+#define pte_ERROR(e) \
+       pr_err("%s:%d: bad pte %08lx.\n", \
+               __FILE__, __LINE__, pte_val(e))
+#define pgd_ERROR(e) \
+       pr_err("%s:%d: bad pgd %08lx.\n", \
+               __FILE__, __LINE__, pgd_val(e))
+
+/*
+ * Encode and decode a swap entry (must be !pte_none(pte) && !pte_present(pte)
+ * && !pte_file(pte)):
+ *
+ * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 ...  1  0
+ *  0  0  0  0 type.  0  0  0  0  0  0 offset.........
+ *
+ * This gives us up to 2**2 = 4 swap files and 2**20 * 4K = 4G per swap file.
+ *
+ * Note that the offset field is always non-zero, thus !pte_none(pte) is always
+ * true.
+ */
+#define __swp_type(swp)                (((swp).val >> 26) & 0x3)
+#define __swp_offset(swp)      ((swp).val & 0xfffff)
+#define __swp_entry(type, off) ((swp_entry_t) { (((type) & 0x3) << 26) \
+                                                | ((off) & 0xfffff) })
+#define __swp_entry_to_pte(swp)        ((pte_t) { (swp).val })
+#define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
+
+/* Encode and decode a nonlinear file mapping entry */
+#define PTE_FILE_MAX_BITS      25
+#define pte_to_pgoff(pte)      (pte_val(pte) & 0x1ffffff)
+#define pgoff_to_pte(off)      __pte(((off) & 0x1ffffff) | _PAGE_FILE)
+
+#define kern_addr_valid(addr)          (1)
+
+#include <asm-generic/pgtable.h>
+
+#define pgtable_cache_init()           do { } while (0)
+
+extern void __init paging_init(void);
+extern void __init mmu_init(void);
+
+extern void update_mmu_cache(struct vm_area_struct *vma,
+                            unsigned long address, pte_t *pte);
+
+#endif /* _ASM_NIOS2_PGTABLE_H */
diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h
new file mode 100644 (file)
index 0000000..3bd3494
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ * Copyright (C) 2001 Ken Hill (khill@microtronix.com)
+ *                    Vic Phillips (vic@microtronix.com)
+ *
+ * based on SPARC asm/processor_32.h which is:
+ *
+ * Copyright (C) 1994 David S. Miller
+ *
+ * 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_NIOS2_PROCESSOR_H
+#define _ASM_NIOS2_PROCESSOR_H
+
+#include <asm/ptrace.h>
+#include <asm/registers.h>
+#include <asm/page.h>
+
+#define NIOS2_FLAG_KTHREAD     0x00000001      /* task is a kernel thread */
+
+#define NIOS2_OP_NOP           0x1883a
+#define NIOS2_OP_BREAK         0x3da03a
+
+#ifdef __KERNEL__
+
+#define STACK_TOP      TASK_SIZE
+#define STACK_TOP_MAX  STACK_TOP
+
+#endif /* __KERNEL__ */
+
+/* Kuser helpers is mapped to this user space address */
+#define KUSER_BASE             0x1000
+#define KUSER_SIZE             (PAGE_SIZE)
+#ifndef __ASSEMBLY__
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+# define TASK_SIZE             0x7FFF0000UL
+# define TASK_UNMAPPED_BASE    (PAGE_ALIGN(TASK_SIZE / 3))
+
+/* The Nios processor specific thread struct. */
+struct thread_struct {
+       struct pt_regs *kregs;
+
+       /* Context switch saved kernel state. */
+       unsigned long ksp;
+       unsigned long kpsr;
+};
+
+#define INIT_MMAP \
+       { &init_mm, (0), (0), __pgprot(0x0), VM_READ | VM_WRITE | VM_EXEC }
+
+# define INIT_THREAD {                 \
+       .kregs  = NULL,                 \
+       .ksp    = 0,                    \
+       .kpsr   = 0,                    \
+}
+
+extern void start_thread(struct pt_regs *regs, unsigned long pc,
+                       unsigned long sp);
+
+struct task_struct;
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+/* Free current thread data structures etc.. */
+static inline void exit_thread(void)
+{
+}
+
+/* Return saved PC of a blocked thread. */
+#define thread_saved_pc(tsk)   ((tsk)->thread.kregs->ea)
+
+extern unsigned long get_wchan(struct task_struct *p);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)   do { } while (0)
+
+#define task_pt_regs(p) \
+       ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1)
+
+/* Used by procfs */
+#define KSTK_EIP(tsk)  ((tsk)->thread.kregs->ea)
+#define KSTK_ESP(tsk)  ((tsk)->thread.kregs->sp)
+
+#define cpu_relax()    barrier()
+#define cpu_relax_lowlatency()  cpu_relax()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_NIOS2_PROCESSOR_H */
diff --git a/arch/nios2/include/asm/ptrace.h b/arch/nios2/include/asm/ptrace.h
new file mode 100644 (file)
index 0000000..20fb1cf
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * based on m68k asm/processor.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_NIOS2_PTRACE_H
+#define _ASM_NIOS2_PTRACE_H
+
+#include <uapi/asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+#define user_mode(regs)        (((regs)->estatus & ESTATUS_EU))
+
+#define instruction_pointer(regs)      ((regs)->ra)
+#define profile_pc(regs)               instruction_pointer(regs)
+#define user_stack_pointer(regs)       ((regs)->sp)
+extern void show_regs(struct pt_regs *);
+
+#define current_pt_regs() \
+       ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE)\
+               - 1)
+
+int do_syscall_trace_enter(void);
+void do_syscall_trace_exit(void);
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_NIOS2_PTRACE_H */
diff --git a/arch/nios2/include/asm/registers.h b/arch/nios2/include/asm/registers.h
new file mode 100644 (file)
index 0000000..615bce1
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _ASM_NIOS2_REGISTERS_H
+#define _ASM_NIOS2_REGISTERS_H
+
+#ifndef __ASSEMBLY__
+#include <asm/cpuinfo.h>
+#endif
+
+/* control register numbers */
+#define CTL_STATUS     0
+#define CTL_ESTATUS    1
+#define CTL_BSTATUS    2
+#define CTL_IENABLE    3
+#define CTL_IPENDING   4
+#define CTL_CPUID      5
+#define CTL_RSV1       6
+#define CTL_EXCEPTION  7
+#define CTL_PTEADDR    8
+#define CTL_TLBACC     9
+#define CTL_TLBMISC    10
+#define CTL_RSV2       11
+#define CTL_BADADDR    12
+#define CTL_CONFIG     13
+#define CTL_MPUBASE    14
+#define CTL_MPUACC     15
+
+/* access control registers using GCC builtins */
+#define RDCTL(r)       __builtin_rdctl(r)
+#define WRCTL(r, v)    __builtin_wrctl(r, v)
+
+/* status register bits */
+#define STATUS_PIE     (1 << 0)        /* processor interrupt enable */
+#define STATUS_U       (1 << 1)        /* user mode */
+#define STATUS_EH      (1 << 2)        /* Exception mode */
+
+/* estatus register bits */
+#define ESTATUS_EPIE   (1 << 0)        /* processor interrupt enable */
+#define ESTATUS_EU     (1 << 1)        /* user mode */
+#define ESTATUS_EH     (1 << 2)        /* Exception mode */
+
+/* tlbmisc register bits */
+#define TLBMISC_PID_SHIFT      4
+#ifndef __ASSEMBLY__
+#define TLBMISC_PID_MASK       ((1UL << cpuinfo.tlb_pid_num_bits) - 1)
+#endif
+#define TLBMISC_WAY_MASK       0xf
+#define TLBMISC_WAY_SHIFT      20
+
+#define TLBMISC_PID    (TLBMISC_PID_MASK << TLBMISC_PID_SHIFT) /* TLB PID */
+#define TLBMISC_WE     (1 << 18)       /* TLB write enable */
+#define TLBMISC_RD     (1 << 19)       /* TLB read */
+#define TLBMISC_WAY    (TLBMISC_WAY_MASK << TLBMISC_WAY_SHIFT) /* TLB way */
+
+#endif /* _ASM_NIOS2_REGISTERS_H */
diff --git a/arch/nios2/include/asm/setup.h b/arch/nios2/include/asm/setup.h
new file mode 100644 (file)
index 0000000..dcbf8cf
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _ASM_NIOS2_SETUP_H
+#define _ASM_NIOS2_SETUP_H
+
+#include <asm-generic/setup.h>
+
+#ifndef __ASSEMBLY__
+#ifdef __KERNEL__
+
+extern char exception_handler_hook[];
+extern char fast_handler[];
+extern char fast_handler_end[];
+
+extern void pagetable_init(void);
+
+extern void setup_early_printk(void);
+
+#endif/* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_NIOS2_SETUP_H */
diff --git a/arch/nios2/include/asm/signal.h b/arch/nios2/include/asm/signal.h
new file mode 100644 (file)
index 0000000..bbcf11e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright Altera Corporation (C) 2013. 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 _NIOS2_SIGNAL_H
+#define _NIOS2_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+
+#endif /* _NIOS2_SIGNAL_H */
diff --git a/arch/nios2/include/asm/string.h b/arch/nios2/include/asm/string.h
new file mode 100644 (file)
index 0000000..14dd570
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * 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_NIOS2_STRING_H
+#define _ASM_NIOS2_STRING_H
+
+#ifdef __KERNEL__
+
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
+
+extern void *memset(void *s, int c, size_t count);
+extern void *memcpy(void *d, const void *s, size_t count);
+extern void *memmove(void *d, const void *s, size_t count);
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_NIOS2_STRING_H */
diff --git a/arch/nios2/include/asm/switch_to.h b/arch/nios2/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..c47b3f4
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS2_SWITCH_TO_H
+#define _ASM_NIOS2_SWITCH_TO_H
+
+/*
+ * switch_to(n) should switch tasks to task ptr, first checking that
+ * ptr isn't the current task, in which case it does nothing.  This
+ * also clears the TS-flag if the task we switched to has used the
+ * math co-processor latest.
+ */
+#define switch_to(prev, next, last)                    \
+{                                                      \
+       void *_last;                                    \
+       __asm__ __volatile__ (                          \
+               "mov    r4, %1\n"                       \
+               "mov    r5, %2\n"                       \
+               "call   resume\n"                       \
+               "mov    %0,r4\n"                        \
+               : "=r" (_last)                          \
+               : "r" (prev), "r" (next)                \
+               : "r4", "r5", "r7", "r8", "ra");        \
+       (last) = _last;                                 \
+}
+
+#endif /* _ASM_NIOS2_SWITCH_TO_H */
diff --git a/arch/nios2/include/asm/syscall.h b/arch/nios2/include/asm/syscall.h
new file mode 100644 (file)
index 0000000..9de2208
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright Altera Corporation (C) <2014>. 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_SYSCALL_H__
+#define __ASM_NIOS2_SYSCALL_H__
+
+#include <linux/err.h>
+#include <linux/sched.h>
+
+static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+       return regs->r2;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+                               struct pt_regs *regs)
+{
+       regs->r2 = regs->orig_r2;
+       regs->r7 = regs->orig_r7;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+                               struct pt_regs *regs)
+{
+       return regs->r7 ? regs->r2 : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+       struct pt_regs *regs)
+{
+       return regs->r2;
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+       struct pt_regs *regs, int error, long val)
+{
+       if (error) {
+               /* error < 0, but nios2 uses > 0 return value */
+               regs->r2 = -error;
+               regs->r7 = 1;
+       } else {
+               regs->r2 = val;
+               regs->r7 = 0;
+       }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+       struct pt_regs *regs, unsigned int i, unsigned int n,
+       unsigned long *args)
+{
+       BUG_ON(i + n > 6);
+
+       switch (i) {
+       case 0:
+               if (!n--)
+                       break;
+               *args++ = regs->r4;
+       case 1:
+               if (!n--)
+                       break;
+               *args++ = regs->r5;
+       case 2:
+               if (!n--)
+                       break;
+               *args++ = regs->r6;
+       case 3:
+               if (!n--)
+                       break;
+               *args++ = regs->r7;
+       case 4:
+               if (!n--)
+                       break;
+               *args++ = regs->r8;
+       case 5:
+               if (!n--)
+                       break;
+               *args++ = regs->r9;
+       case 6:
+               if (!n--)
+                       break;
+       default:
+               BUG();
+       }
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+       struct pt_regs *regs, unsigned int i, unsigned int n,
+       const unsigned long *args)
+{
+       BUG_ON(i + n > 6);
+
+       switch (i) {
+       case 0:
+               if (!n--)
+                       break;
+               regs->r4 = *args++;
+       case 1:
+               if (!n--)
+                       break;
+               regs->r5 = *args++;
+       case 2:
+               if (!n--)
+                       break;
+               regs->r6 = *args++;
+       case 3:
+               if (!n--)
+                       break;
+               regs->r7 = *args++;
+       case 4:
+               if (!n--)
+                       break;
+               regs->r8 = *args++;
+       case 5:
+               if (!n--)
+                       break;
+               regs->r9 = *args++;
+       case 6:
+               if (!n)
+                       break;
+       default:
+               BUG();
+       }
+}
+
+#endif
diff --git a/arch/nios2/include/asm/syscalls.h b/arch/nios2/include/asm/syscalls.h
new file mode 100644 (file)
index 0000000..0245d78
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright Altera Corporation (C) 2013. 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_SYSCALLS_H
+#define __ASM_NIOS2_SYSCALLS_H
+
+int sys_cacheflush(unsigned long addr, unsigned long len,
+                               unsigned int op);
+
+#include <asm-generic/syscalls.h>
+
+#endif /* __ASM_NIOS2_SYSCALLS_H */
diff --git a/arch/nios2/include/asm/thread_info.h b/arch/nios2/include/asm/thread_info.h
new file mode 100644 (file)
index 0000000..1f26657
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * NiosII low-level thread information
+ *
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * Based on asm/thread_info_no.h from m68k which is:
+ *
+ * Copyright (C) 2002 David Howells <dhowells@redhat.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_NIOS2_THREAD_INFO_H
+#define _ASM_NIOS2_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+/*
+ * Size of the kernel stack for each process.
+ */
+#define THREAD_SIZE_ORDER      1
+#define THREAD_SIZE            8192 /* 2 * PAGE_SIZE */
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+       unsigned long seg;
+} mm_segment_t;
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ *   must also be changed
+ */
+struct thread_info {
+       struct task_struct      *task;          /* main task structure */
+       struct exec_domain      *exec_domain;   /* execution domain */
+       unsigned long           flags;          /* low level flags */
+       __u32                   cpu;            /* current CPU */
+       int                     preempt_count;  /* 0 => preemptable,<0 => BUG */
+       mm_segment_t            addr_limit;     /* thread address space:
+                                                 0-0x7FFFFFFF for user-thead
+                                                 0-0xFFFFFFFF for kernel-thread
+                                               */
+       struct restart_block    restart_block;
+       struct pt_regs          *regs;
+};
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#define INIT_THREAD_INFO(tsk)                  \
+{                                              \
+       .task           = &tsk,                 \
+       .exec_domain    = &default_exec_domain, \
+       .flags          = 0,                    \
+       .cpu            = 0,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
+       .addr_limit     = KERNEL_DS,            \
+       .restart_block  = {                     \
+               .fn = do_no_restart_syscall,    \
+       },                                      \
+}
+
+#define init_thread_info       (init_thread_union.thread_info)
+#define init_stack             (init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+       register unsigned long sp asm("sp");
+
+       return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
+}
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to
+ *   access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE      0       /* syscall trace active */
+#define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
+#define TIF_SIGPENDING         2       /* signal pending */
+#define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+#define TIF_MEMDIE             4       /* is terminating due to OOM killer */
+#define TIF_SECCOMP            5       /* secure computing */
+#define TIF_SYSCALL_AUDIT      6       /* syscall auditing active */
+#define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal() */
+
+#define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling
+                                          TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
+#define _TIF_SECCOMP           (1 << TIF_SECCOMP)
+#define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
+#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
+
+/* work to do on interrupt/exception return */
+#define _TIF_WORK_MASK         0x0000FFFE
+
+/* work to do on any return to u-space */
+# define _TIF_ALLWORK_MASK     0x0000FFFF
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_NIOS2_THREAD_INFO_H */
diff --git a/arch/nios2/include/asm/timex.h b/arch/nios2/include/asm/timex.h
new file mode 100644 (file)
index 0000000..2f2abb2
--- /dev/null
@@ -0,0 +1,24 @@
+/* Copyright Altera Corporation (C) 2014. 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_TIMEX_H
+#define _ASM_NIOS2_TIMEX_H
+
+typedef unsigned long cycles_t;
+
+extern cycles_t get_cycles(void);
+
+#endif
diff --git a/arch/nios2/include/asm/tlb.h b/arch/nios2/include/asm/tlb.h
new file mode 100644 (file)
index 0000000..d3bc648
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS2_TLB_H
+#define _ASM_NIOS2_TLB_H
+
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+extern void set_mmu_pid(unsigned long pid);
+
+/*
+ * NiosII doesn't need any special per-pte or per-vma handling, except
+ * we need to flush cache for the area to be unmapped.
+ */
+#define tlb_start_vma(tlb, vma)                                        \
+       do {                                                    \
+               if (!tlb->fullmm)                               \
+                       flush_cache_range(vma, vma->vm_start, vma->vm_end); \
+       }  while (0)
+
+#define tlb_end_vma(tlb, vma)  do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)     do { } while (0)
+
+#include <linux/pagemap.h>
+#include <asm-generic/tlb.h>
+
+#endif /* _ASM_NIOS2_TLB_H */
diff --git a/arch/nios2/include/asm/tlbflush.h b/arch/nios2/include/asm/tlbflush.h
new file mode 100644 (file)
index 0000000..e19652f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _ASM_NIOS2_TLBFLUSH_H
+#define _ASM_NIOS2_TLBFLUSH_H
+
+struct mm_struct;
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb_all() flushes all processes TLB entries
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB entries
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ */
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+                           unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_one(unsigned long vaddr);
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+                               unsigned long addr)
+{
+       flush_tlb_one(addr);
+}
+
+#endif /* _ASM_NIOS2_TLBFLUSH_H */
diff --git a/arch/nios2/include/asm/traps.h b/arch/nios2/include/asm/traps.h
new file mode 100644 (file)
index 0000000..82a4847
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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_NIOS2_TRAPS_H
+#define _ASM_NIOS2_TRAPS_H
+
+#define TRAP_ID_SYSCALL                0
+
+#ifndef __ASSEMBLY__
+void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr);
+#endif
+
+#endif /* _ASM_NIOS2_TRAPS_H */
diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h
new file mode 100644 (file)
index 0000000..acedc0a
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * User space memory access functions for Nios II
+ *
+ * Copyright (C) 2010-2011, Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009, Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.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_NIOS2_UACCESS_H
+#define _ASM_NIOS2_UACCESS_H
+
+#include <linux/errno.h>
+#include <linux/thread_info.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+struct exception_table_entry {
+       unsigned long insn;
+       unsigned long fixup;
+};
+
+extern int fixup_exception(struct pt_regs *regs);
+
+/*
+ * Segment stuff
+ */
+#define MAKE_MM_SEG(s)         ((mm_segment_t) { (s) })
+#define USER_DS                        MAKE_MM_SEG(0x80000000UL)
+#define KERNEL_DS              MAKE_MM_SEG(0)
+
+#define get_ds()               (KERNEL_DS)
+
+#define get_fs()               (current_thread_info()->addr_limit)
+#define set_fs(seg)            (current_thread_info()->addr_limit = (seg))
+
+#define segment_eq(a, b)       ((a).seg == (b).seg)
+
+#define __access_ok(addr, len)                 \
+       (((signed long)(((long)get_fs().seg) &  \
+               ((long)(addr) | (((long)(addr)) + (len)) | (len)))) == 0)
+
+#define access_ok(type, addr, len)             \
+       likely(__access_ok((unsigned long)(addr), (unsigned long)(len)))
+
+# define __EX_TABLE_SECTION    ".section __ex_table,\"a\"\n"
+
+/*
+ * Zero Userspace
+ */
+
+static inline unsigned long __must_check __clear_user(void __user *to,
+                                                     unsigned long n)
+{
+       __asm__ __volatile__ (
+               "1:     stb     zero, 0(%1)\n"
+               "       addi    %0, %0, -1\n"
+               "       addi    %1, %1, 1\n"
+               "       bne     %0, zero, 1b\n"
+               "2:\n"
+               __EX_TABLE_SECTION
+               ".word  1b, 2b\n"
+               ".previous\n"
+               : "=r" (n), "=r" (to)
+               : "0" (n), "1" (to)
+       );
+
+       return n;
+}
+
+static inline unsigned long __must_check clear_user(void __user *to,
+                                                   unsigned long n)
+{
+       if (!access_ok(VERIFY_WRITE, to, n))
+               return n;
+       return __clear_user(to, n);
+}
+
+extern long __copy_from_user(void *to, const void __user *from,
+                               unsigned long n);
+extern long __copy_to_user(void __user *to, const void *from, unsigned long n);
+
+static inline long copy_from_user(void *to, const void __user *from,
+                               unsigned long n)
+{
+       if (!access_ok(VERIFY_READ, from, n))
+               return n;
+       return __copy_from_user(to, from, n);
+}
+
+static inline long copy_to_user(void __user *to, const void *from,
+                               unsigned long n)
+{
+       if (!access_ok(VERIFY_WRITE, to, n))
+               return n;
+       return __copy_to_user(to, from, n);
+}
+
+extern long strncpy_from_user(char *__to, const char __user *__from,
+                               long __len);
+extern long strnlen_user(const char __user *s, long n);
+
+#define __copy_from_user_inatomic      __copy_from_user
+#define __copy_to_user_inatomic                __copy_to_user
+
+/* Optimized macros */
+#define __get_user_asm(val, insn, addr, err)                           \
+{                                                                      \
+       __asm__ __volatile__(                                           \
+       "       movi    %0, %3\n"                                       \
+       "1:   " insn " %1, 0(%2)\n"                                     \
+       "       movi     %0, 0\n"                                       \
+       "2:\n"                                                          \
+       "       .section __ex_table,\"a\"\n"                            \
+       "       .word 1b, 2b\n"                                         \
+       "       .previous"                                              \
+       : "=&r" (err), "=r" (val)                                       \
+       : "r" (addr), "i" (-EFAULT));                                   \
+}
+
+#define __get_user_unknown(val, size, ptr, err) do {                   \
+       err = 0;                                                        \
+       if (copy_from_user(&(val), ptr, size)) {                        \
+               err = -EFAULT;                                          \
+       }                                                               \
+       } while (0)
+
+#define __get_user_common(val, size, ptr, err)                         \
+do {                                                                   \
+       switch (size) {                                                 \
+       case 1:                                                         \
+               __get_user_asm(val, "ldbu", ptr, err);                  \
+               break;                                                  \
+       case 2:                                                         \
+               __get_user_asm(val, "ldhu", ptr, err);                  \
+               break;                                                  \
+       case 4:                                                         \
+               __get_user_asm(val, "ldw", ptr, err);                   \
+               break;                                                  \
+       default:                                                        \
+               __get_user_unknown(val, size, ptr, err);                \
+               break;                                                  \
+       }                                                               \
+} while (0)
+
+#define __get_user(x, ptr)                                             \
+       ({                                                              \
+       long __gu_err = -EFAULT;                                        \
+       const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);              \
+       unsigned long __gu_val;                                         \
+       __get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\
+       (x) = (__typeof__(x))__gu_val;                                  \
+       __gu_err;                                                       \
+       })
+
+#define get_user(x, ptr)                                               \
+({                                                                     \
+       long __gu_err = -EFAULT;                                        \
+       const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);              \
+       unsigned long __gu_val = 0;                                     \
+       if (access_ok(VERIFY_READ,  __gu_ptr, sizeof(*__gu_ptr)))       \
+               __get_user_common(__gu_val, sizeof(*__gu_ptr),          \
+                       __gu_ptr, __gu_err);                            \
+       (x) = (__typeof__(x))__gu_val;                                  \
+       __gu_err;                                                       \
+})
+
+#define __put_user_asm(val, insn, ptr, err)                            \
+{                                                                      \
+       __asm__ __volatile__(                                           \
+       "       movi    %0, %3\n"                                       \
+       "1:   " insn " %1, 0(%2)\n"                                     \
+       "       movi     %0, 0\n"                                       \
+       "2:\n"                                                          \
+       "       .section __ex_table,\"a\"\n"                            \
+       "       .word 1b, 2b\n"                                         \
+       "       .previous\n"                                            \
+       : "=&r" (err)                                                   \
+       : "r" (val), "r" (ptr), "i" (-EFAULT));                         \
+}
+
+#define put_user(x, ptr)                                               \
+({                                                                     \
+       long __pu_err = -EFAULT;                                        \
+       __typeof__(*(ptr)) __user *__pu_ptr = (ptr);                    \
+       __typeof__(*(ptr)) __pu_val = (__typeof(*ptr))(x);              \
+       if (access_ok(VERIFY_WRITE, __pu_ptr, sizeof(*__pu_ptr))) {     \
+               switch (sizeof(*__pu_ptr)) {                            \
+               case 1:                                                 \
+                       __put_user_asm(__pu_val, "stb", __pu_ptr, __pu_err); \
+                       break;                                          \
+               case 2:                                                 \
+                       __put_user_asm(__pu_val, "sth", __pu_ptr, __pu_err); \
+                       break;                                          \
+               case 4:                                                 \
+                       __put_user_asm(__pu_val, "stw", __pu_ptr, __pu_err); \
+                       break;                                          \
+               default:                                                \
+                       /* XXX: This looks wrong... */                  \
+                       __pu_err = 0;                                   \
+                       if (copy_to_user(__pu_ptr, &(__pu_val),         \
+                               sizeof(*__pu_ptr)))                     \
+                               __pu_err = -EFAULT;                     \
+                       break;                                          \
+               }                                                       \
+       }                                                               \
+       __pu_err;                                                       \
+})
+
+#define __put_user(x, ptr) put_user(x, ptr)
+
+#endif /* _ASM_NIOS2_UACCESS_H */
diff --git a/arch/nios2/include/asm/ucontext.h b/arch/nios2/include/asm/ucontext.h
new file mode 100644 (file)
index 0000000..2c87614
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * 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_NIOS2_UCONTEXT_H
+#define _ASM_NIOS2_UCONTEXT_H
+
+typedef int greg_t;
+#define NGREG 32
+typedef greg_t gregset_t[NGREG];
+
+struct mcontext {
+       int version;
+       gregset_t gregs;
+};
+
+#define MCONTEXT_VERSION 2
+
+struct ucontext {
+       unsigned long     uc_flags;
+       struct ucontext  *uc_link;
+       stack_t           uc_stack;
+       struct mcontext   uc_mcontext;
+       sigset_t          uc_sigmask;   /* mask last for extensibility */
+};
+
+#endif
diff --git a/arch/nios2/include/uapi/asm/Kbuild b/arch/nios2/include/uapi/asm/Kbuild
new file mode 100644 (file)
index 0000000..4f07ca3
--- /dev/null
@@ -0,0 +1,4 @@
+include include/uapi/asm-generic/Kbuild.asm
+
+header-y += elf.h
+header-y += ucontext.h
diff --git a/arch/nios2/include/uapi/asm/byteorder.h b/arch/nios2/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..3ab5dc2
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2009   Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (C) 2004   Microtronix Datacom 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 _ASM_NIOS2_BYTEORDER_H
+#define _ASM_NIOS2_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif
diff --git a/arch/nios2/include/uapi/asm/elf.h b/arch/nios2/include/uapi/asm/elf.h
new file mode 100644 (file)
index 0000000..a5b91ae
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 _UAPI_ASM_NIOS2_ELF_H
+#define _UAPI_ASM_NIOS2_ELF_H
+
+#include <linux/ptrace.h>
+
+/* Relocation types */
+#define R_NIOS2_NONE           0
+#define R_NIOS2_S16            1
+#define R_NIOS2_U16            2
+#define R_NIOS2_PCREL16                3
+#define R_NIOS2_CALL26         4
+#define R_NIOS2_IMM5           5
+#define R_NIOS2_CACHE_OPX      6
+#define R_NIOS2_IMM6           7
+#define R_NIOS2_IMM8           8
+#define R_NIOS2_HI16           9
+#define R_NIOS2_LO16           10
+#define R_NIOS2_HIADJ16                11
+#define R_NIOS2_BFD_RELOC_32   12
+#define R_NIOS2_BFD_RELOC_16   13
+#define R_NIOS2_BFD_RELOC_8    14
+#define R_NIOS2_GPREL          15
+#define R_NIOS2_GNU_VTINHERIT  16
+#define R_NIOS2_GNU_VTENTRY    17
+#define R_NIOS2_UJMP           18
+#define R_NIOS2_CJMP           19
+#define R_NIOS2_CALLR          20
+#define R_NIOS2_ALIGN          21
+/* Keep this the last entry.  */
+#define R_NIOS2_NUM            22
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG      \
+       ((sizeof(struct pt_regs) + sizeof(struct switch_stack)) /       \
+               sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef unsigned long elf_fpregset_t;
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS32
+#define ELF_DATA       ELFDATA2LSB
+#define ELF_ARCH       EM_ALTERA_NIOS2
+
+#endif /* _UAPI_ASM_NIOS2_ELF_H */
diff --git a/arch/nios2/include/uapi/asm/ptrace.h b/arch/nios2/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..e83a7c9
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * based on m68k asm/processor.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _UAPI_ASM_NIOS2_PTRACE_H
+#define _UAPI_ASM_NIOS2_PTRACE_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Register numbers used by 'ptrace' system call interface.
+ */
+
+/* GP registers */
+#define PTR_R0         0
+#define PTR_R1         1
+#define PTR_R2         2
+#define PTR_R3         3
+#define PTR_R4         4
+#define PTR_R5         5
+#define PTR_R6         6
+#define PTR_R7         7
+#define PTR_R8         8
+#define PTR_R9         9
+#define PTR_R10                10
+#define PTR_R11                11
+#define PTR_R12                12
+#define PTR_R13                13
+#define PTR_R14                14
+#define PTR_R15                15
+#define PTR_R16                16
+#define PTR_R17                17
+#define PTR_R18                18
+#define PTR_R19                19
+#define PTR_R20                20
+#define PTR_R21                21
+#define PTR_R22                22
+#define PTR_R23                23
+#define PTR_R24                24
+#define PTR_R25                25
+#define PTR_GP         26
+#define PTR_SP         27
+#define PTR_FP         28
+#define PTR_EA         29
+#define PTR_BA         30
+#define PTR_RA         31
+/* Control registers */
+#define PTR_PC         32
+#define PTR_STATUS     33
+#define PTR_ESTATUS    34
+#define PTR_BSTATUS    35
+#define PTR_IENABLE    36
+#define PTR_IPENDING   37
+#define PTR_CPUID      38
+#define PTR_CTL6       39
+#define PTR_CTL7       40
+#define PTR_PTEADDR    41
+#define PTR_TLBACC     42
+#define PTR_TLBMISC    43
+
+#define NUM_PTRACE_REG (PTR_TLBMISC + 1)
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call.
+
+   There is a fake_regs in setup.c that has to match pt_regs.*/
+
+struct pt_regs {
+       unsigned long  r8;              /* r8-r15 Caller-saved GP registers */
+       unsigned long  r9;
+       unsigned long  r10;
+       unsigned long  r11;
+       unsigned long  r12;
+       unsigned long  r13;
+       unsigned long  r14;
+       unsigned long  r15;
+       unsigned long  r1;              /* Assembler temporary */
+       unsigned long  r2;              /* Retval LS 32bits */
+       unsigned long  r3;              /* Retval MS 32bits */
+       unsigned long  r4;              /* r4-r7 Register arguments */
+       unsigned long  r5;
+       unsigned long  r6;
+       unsigned long  r7;
+       unsigned long  orig_r2;         /* Copy of r2 ?? */
+       unsigned long  ra;              /* Return address */
+       unsigned long  fp;              /* Frame pointer */
+       unsigned long  sp;              /* Stack pointer */
+       unsigned long  gp;              /* Global pointer */
+       unsigned long  estatus;
+       unsigned long  ea;              /* Exception return address (pc) */
+       unsigned long  orig_r7;
+};
+
+/*
+ * This is the extended stack used by signal handlers and the context
+ * switcher: it's pushed after the normal "struct pt_regs".
+ */
+struct switch_stack {
+       unsigned long  r16;             /* r16-r23 Callee-saved GP registers */
+       unsigned long  r17;
+       unsigned long  r18;
+       unsigned long  r19;
+       unsigned long  r20;
+       unsigned long  r21;
+       unsigned long  r22;
+       unsigned long  r23;
+       unsigned long  fp;
+       unsigned long  gp;
+       unsigned long  ra;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_ASM_NIOS2_PTRACE_H */
diff --git a/arch/nios2/include/uapi/asm/sigcontext.h b/arch/nios2/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..7b8bb41
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, Microtronix Datacom Ltd.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef _ASM_NIOS2_SIGCONTEXT_H
+#define _ASM_NIOS2_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+struct sigcontext {
+       struct pt_regs regs;
+       unsigned long  sc_mask; /* old sigmask */
+};
+
+#endif
diff --git a/arch/nios2/include/uapi/asm/signal.h b/arch/nios2/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..f29ee63
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright Altera Corporation (C) 2013. 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_SIGNAL_H
+#define _ASM_NIOS2_SIGNAL_H
+
+#define SA_RESTORER 0x04000000
+#include <asm-generic/signal.h>
+
+#endif /* _ASM_NIOS2_SIGNAL_H */
diff --git a/arch/nios2/include/uapi/asm/swab.h b/arch/nios2/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..b4e22eb
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2011 Pyramid Technical Consultants, Inc.
+ *
+ * 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_NIOS2_SWAB_H
+#define _ASM_NIOS2_SWAB_H
+
+#include <linux/types.h>
+#include <asm-generic/swab.h>
+
+#ifdef CONFIG_NIOS2_CI_SWAB_SUPPORT
+#ifdef __GNUC__
+
+#define __nios2_swab(x)                \
+       __builtin_custom_ini(CONFIG_NIOS2_CI_SWAB_NO, (x))
+
+static inline __attribute__((const)) __u16 __arch_swab16(__u16 x)
+{
+       return (__u16) __nios2_swab(((__u32) x) << 16);
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __attribute__((const)) __u32 __arch_swab32(__u32 x)
+{
+       return (__u32) __nios2_swab(x);
+}
+#define __arch_swab32 __arch_swab32
+
+#endif /* __GNUC__ */
+#endif /* CONFIG_NIOS2_CI_SWAB_SUPPORT */
+
+#endif /* _ASM_NIOS2_SWAB_H */
diff --git a/arch/nios2/include/uapi/asm/unistd.h b/arch/nios2/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..c4bf795
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Altera 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.
+ *
+ * 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 sys_mmap2 sys_mmap_pgoff
+
+/* Use the standard ABI for syscalls */
+#include <asm-generic/unistd.h>
+
+/* Additional Nios II specific syscalls. */
+#define __NR_cacheflush (__NR_arch_specific_syscall)
+__SYSCALL(__NR_cacheflush, sys_cacheflush)
diff --git a/arch/nios2/kernel/Makefile b/arch/nios2/kernel/Makefile
new file mode 100644 (file)
index 0000000..8ae7682
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Makefile for the nios2 linux kernel.
+#
+
+extra-y        += head.o
+extra-y        += vmlinux.lds
+
+obj-y  += cpuinfo.o
+obj-y  += entry.o
+obj-y  += insnemu.o
+obj-y  += irq.o
+obj-y  += nios2_ksyms.o
+obj-y  += process.o
+obj-y  += prom.o
+obj-y  += ptrace.o
+obj-y  += setup.o
+obj-y  += signal.o
+obj-y  += sys_nios2.o
+obj-y  += syscall_table.o
+obj-y  += time.o
+obj-y  += traps.o
+
+obj-$(CONFIG_MODULES)                  += module.o
+obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP)     += misaligned.o
diff --git a/arch/nios2/kernel/asm-offsets.c b/arch/nios2/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..c3ee73c
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <linux/thread_info.h>
+#include <linux/kbuild.h>
+
+int main(void)
+{
+       /* struct task_struct */
+       OFFSET(TASK_THREAD, task_struct, thread);
+       BLANK();
+
+       /* struct thread_struct */
+       OFFSET(THREAD_KSP, thread_struct, ksp);
+       OFFSET(THREAD_KPSR, thread_struct, kpsr);
+       BLANK();
+
+       /* struct pt_regs */
+       OFFSET(PT_ORIG_R2, pt_regs, orig_r2);
+       OFFSET(PT_ORIG_R7, pt_regs, orig_r7);
+
+       OFFSET(PT_R1, pt_regs, r1);
+       OFFSET(PT_R2, pt_regs, r2);
+       OFFSET(PT_R3, pt_regs, r3);
+       OFFSET(PT_R4, pt_regs, r4);
+       OFFSET(PT_R5, pt_regs, r5);
+       OFFSET(PT_R6, pt_regs, r6);
+       OFFSET(PT_R7, pt_regs, r7);
+       OFFSET(PT_R8, pt_regs, r8);
+       OFFSET(PT_R9, pt_regs, r9);
+       OFFSET(PT_R10, pt_regs, r10);
+       OFFSET(PT_R11, pt_regs, r11);
+       OFFSET(PT_R12, pt_regs, r12);
+       OFFSET(PT_R13, pt_regs, r13);
+       OFFSET(PT_R14, pt_regs, r14);
+       OFFSET(PT_R15, pt_regs, r15);
+       OFFSET(PT_EA, pt_regs, ea);
+       OFFSET(PT_RA, pt_regs, ra);
+       OFFSET(PT_FP, pt_regs, fp);
+       OFFSET(PT_SP, pt_regs, sp);
+       OFFSET(PT_GP, pt_regs, gp);
+       OFFSET(PT_ESTATUS, pt_regs, estatus);
+       DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
+       BLANK();
+
+       /* struct switch_stack */
+       OFFSET(SW_R16, switch_stack, r16);
+       OFFSET(SW_R17, switch_stack, r17);
+       OFFSET(SW_R18, switch_stack, r18);
+       OFFSET(SW_R19, switch_stack, r19);
+       OFFSET(SW_R20, switch_stack, r20);
+       OFFSET(SW_R21, switch_stack, r21);
+       OFFSET(SW_R22, switch_stack, r22);
+       OFFSET(SW_R23, switch_stack, r23);
+       OFFSET(SW_FP, switch_stack, fp);
+       OFFSET(SW_GP, switch_stack, gp);
+       OFFSET(SW_RA, switch_stack, ra);
+       DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack));
+       BLANK();
+
+       /* struct thread_info */
+       OFFSET(TI_FLAGS, thread_info, flags);
+       OFFSET(TI_PREEMPT_COUNT, thread_info, preempt_count);
+       BLANK();
+
+       return 0;
+}
diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c
new file mode 100644 (file)
index 0000000..51d5bb9
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * Based on cpuinfo.c from microblaze
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/of.h>
+#include <asm/cpuinfo.h>
+
+struct cpuinfo cpuinfo;
+
+#define err_cpu(x) \
+       pr_err("ERROR: Nios II " x " different for kernel and DTS\n")
+
+static inline u32 fcpu(struct device_node *cpu, const char *n)
+{
+       u32 val = 0;
+
+       of_property_read_u32(cpu, n, &val);
+
+       return val;
+}
+
+static inline u32 fcpu_has(struct device_node *cpu, const char *n)
+{
+       return of_get_property(cpu, n, NULL) ? 1 : 0;
+}
+
+void __init setup_cpuinfo(void)
+{
+       struct device_node *cpu;
+       const char *str;
+       int len;
+
+       cpu = of_find_node_by_type(NULL, "cpu");
+       if (!cpu)
+               panic("%s: No CPU found in devicetree!\n", __func__);
+
+       if (!fcpu_has(cpu, "altr,has-initda"))
+               panic("initda instruction is unimplemented. Please update your "
+                       "hardware system to have more than 4-byte line data "
+                       "cache\n");
+
+       cpuinfo.cpu_clock_freq = fcpu(cpu, "clock-frequency");
+
+       str = of_get_property(cpu, "altr,implementation", &len);
+       if (str)
+               strlcpy(cpuinfo.cpu_impl, str, sizeof(cpuinfo.cpu_impl));
+       else
+               strcpy(cpuinfo.cpu_impl, "<unknown>");
+
+       cpuinfo.has_div = fcpu_has(cpu, "altr,has-div");
+       cpuinfo.has_mul = fcpu_has(cpu, "altr,has-mul");
+       cpuinfo.has_mulx = fcpu_has(cpu, "altr,has-mulx");
+
+       if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div)
+               err_cpu("DIV");
+
+       if (IS_ENABLED(CONFIG_NIOS2_HW_MUL_SUPPORT) && !cpuinfo.has_mul)
+               err_cpu("MUL");
+
+       if (IS_ENABLED(CONFIG_NIOS2_HW_MULX_SUPPORT) && !cpuinfo.has_mulx)
+               err_cpu("MULX");
+
+       cpuinfo.tlb_num_ways = fcpu(cpu, "altr,tlb-num-ways");
+       if (!cpuinfo.tlb_num_ways)
+               panic("altr,tlb-num-ways can't be 0. Please check your hardware "
+                       "system\n");
+       cpuinfo.icache_line_size = fcpu(cpu, "icache-line-size");
+       cpuinfo.icache_size = fcpu(cpu, "icache-size");
+       if (CONFIG_NIOS2_ICACHE_SIZE != cpuinfo.icache_size)
+               pr_warn("Warning: icache size configuration mismatch "
+               "(0x%x vs 0x%x) of CONFIG_NIOS2_ICACHE_SIZE vs "
+               "device tree icache-size\n",
+               CONFIG_NIOS2_ICACHE_SIZE, cpuinfo.icache_size);
+
+       cpuinfo.dcache_line_size = fcpu(cpu, "dcache-line-size");
+       if (CONFIG_NIOS2_DCACHE_LINE_SIZE != cpuinfo.dcache_line_size)
+               pr_warn("Warning: dcache line size configuration mismatch "
+               "(0x%x vs 0x%x) of CONFIG_NIOS2_DCACHE_LINE_SIZE vs "
+               "device tree dcache-line-size\n",
+               CONFIG_NIOS2_DCACHE_LINE_SIZE, cpuinfo.dcache_line_size);
+       cpuinfo.dcache_size = fcpu(cpu, "dcache-size");
+       if (CONFIG_NIOS2_DCACHE_SIZE != cpuinfo.dcache_size)
+               pr_warn("Warning: dcache size configuration mismatch "
+                       "(0x%x vs 0x%x) of CONFIG_NIOS2_DCACHE_SIZE vs "
+                       "device tree dcache-size\n",
+                       CONFIG_NIOS2_DCACHE_SIZE, cpuinfo.dcache_size);
+
+       cpuinfo.tlb_pid_num_bits = fcpu(cpu, "altr,pid-num-bits");
+       cpuinfo.tlb_num_ways_log2 = ilog2(cpuinfo.tlb_num_ways);
+       cpuinfo.tlb_num_entries = fcpu(cpu, "altr,tlb-num-entries");
+       cpuinfo.tlb_num_lines = cpuinfo.tlb_num_entries / cpuinfo.tlb_num_ways;
+       cpuinfo.tlb_ptr_sz = fcpu(cpu, "altr,tlb-ptr-sz");
+
+       cpuinfo.reset_addr = fcpu(cpu, "altr,reset-addr");
+       cpuinfo.exception_addr = fcpu(cpu, "altr,exception-addr");
+       cpuinfo.fast_tlb_miss_exc_addr = fcpu(cpu, "altr,fast-tlb-miss-addr");
+}
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+       int count = 0;
+       const u32 clockfreq = cpuinfo.cpu_clock_freq;
+
+       count = seq_printf(m,
+                       "CPU:\t\tNios II/%s\n"
+                       "MMU:\t\t%s\n"
+                       "FPU:\t\tnone\n"
+                       "Clocking:\t%u.%02u MHz\n"
+                       "BogoMips:\t%lu.%02lu\n"
+                       "Calibration:\t%lu loops\n",
+                       cpuinfo.cpu_impl,
+                       cpuinfo.mmu ? "present" : "none",
+                       clockfreq / 1000000, (clockfreq / 100000) % 10,
+                       (loops_per_jiffy * HZ) / 500000,
+                       ((loops_per_jiffy * HZ) / 5000) % 100,
+                       (loops_per_jiffy * HZ));
+
+       count += seq_printf(m,
+                       "HW:\n"
+                       " MUL:\t\t%s\n"
+                       " MULX:\t\t%s\n"
+                       " DIV:\t\t%s\n",
+                       cpuinfo.has_mul ? "yes" : "no",
+                       cpuinfo.has_mulx ? "yes" : "no",
+                       cpuinfo.has_div ? "yes" : "no");
+
+       count += seq_printf(m,
+                       "Icache:\t\t%ukB, line length: %u\n",
+                       cpuinfo.icache_size >> 10,
+                       cpuinfo.icache_line_size);
+
+       count += seq_printf(m,
+                       "Dcache:\t\t%ukB, line length: %u\n",
+                       cpuinfo.dcache_size >> 10,
+                       cpuinfo.dcache_line_size);
+
+       count += seq_printf(m,
+                       "TLB:\t\t%u ways, %u entries, %u PID bits\n",
+                       cpuinfo.tlb_num_ways,
+                       cpuinfo.tlb_num_entries,
+                       cpuinfo.tlb_pid_num_bits);
+
+       return 0;
+}
+
+static void *cpuinfo_start(struct seq_file *m, loff_t *pos)
+{
+       unsigned long i = *pos;
+
+       return i < num_possible_cpus() ? (void *) (i + 1) : NULL;
+}
+
+static void *cpuinfo_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return cpuinfo_start(m, pos);
+}
+
+static void cpuinfo_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+       .start  = cpuinfo_start,
+       .next   = cpuinfo_next,
+       .stop   = cpuinfo_stop,
+       .show   = show_cpuinfo
+};
+
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S
new file mode 100644 (file)
index 0000000..83bca17
--- /dev/null
@@ -0,0 +1,555 @@
+/*
+ * linux/arch/nios2/kernel/entry.S
+ *
+ * Copyright (C) 2013-2014  Altera Corporation
+ * Copyright (C) 2009, Wind River Systems Inc
+ *
+ * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ *
+ *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
+ *                      Kenneth Albanowski <kjahds@kjahds.com>,
+ *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)
+ *  Copyright (C) 2004  Microtronix Datacom Ltd.
+ *
+ * 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.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ * ColdFire support by Greg Ungerer (gerg@snapgear.com)
+ * 5307 fixes by David W. Miller
+ * linux 2.4 support David McCullough <davidm@snapgear.com>
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/asm-macros.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/entry.h>
+#include <asm/unistd.h>
+#include <asm/processor.h>
+
+.macro GET_THREAD_INFO reg
+.if THREAD_SIZE & 0xffff0000
+       andhi   \reg, sp, %hi(~(THREAD_SIZE-1))
+.else
+       addi    \reg, r0, %lo(~(THREAD_SIZE-1))
+       and     \reg, \reg, sp
+.endif
+.endm
+
+.macro kuser_cmpxchg_check
+       /*
+        * Make sure our user space atomic helper is restarted if it was
+        * interrupted in a critical region.
+        * ea-4 = address of interrupted insn (ea must be preserved).
+        * sp = saved regs.
+        * cmpxchg_ldw = first critical insn, cmpxchg_stw = last critical insn.
+        * If ea <= cmpxchg_stw and ea > cmpxchg_ldw then saved EA is set to
+        * cmpxchg_ldw + 4.
+       */
+       /* et = cmpxchg_stw + 4 */
+       movui   et, (KUSER_BASE + 4 + (cmpxchg_stw - __kuser_helper_start))
+       bgtu    ea, et, 1f
+
+       subi    et, et, (cmpxchg_stw - cmpxchg_ldw) /* et = cmpxchg_ldw + 4 */
+       bltu    ea, et, 1f
+       stw     et, PT_EA(sp)   /* fix up EA */
+       mov     ea, et
+1:
+.endm
+
+.section .rodata
+.align 4
+exception_table:
+       .word unhandled_exception       /* 0 - Reset */
+       .word unhandled_exception       /* 1 - Processor-only Reset */
+       .word external_interrupt        /* 2 - Interrupt */
+       .word handle_trap               /* 3 - Trap Instruction */
+
+       .word instruction_trap          /* 4 - Unimplemented instruction */
+       .word handle_illegal            /* 5 - Illegal instruction */
+       .word handle_unaligned          /* 6 - Misaligned data access */
+       .word handle_unaligned          /* 7 - Misaligned destination address */
+
+       .word handle_diverror           /* 8 - Division error */
+       .word protection_exception_ba   /* 9 - Supervisor-only instr. address */
+       .word protection_exception_instr /* 10 - Supervisor only instruction */
+       .word protection_exception_ba   /* 11 - Supervisor only data address */
+
+       .word unhandled_exception       /* 12 - Double TLB miss (data) */
+       .word protection_exception_pte  /* 13 - TLB permission violation (x) */
+       .word protection_exception_pte  /* 14 - TLB permission violation (r) */
+       .word protection_exception_pte  /* 15 - TLB permission violation (w) */
+
+       .word unhandled_exception       /* 16 - MPU region violation */
+
+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   instruction_trap        /* 30 */
+       .word   handle_breakpoint       /* 31 */
+
+.text
+.set noat
+.set nobreak
+
+ENTRY(inthandler)
+       SAVE_ALL
+
+       kuser_cmpxchg_check
+
+       /* Clear EH bit before we get a new excpetion in the kernel
+        * and after we have saved it to the exception frame. This is done
+        * whether it's trap, tlb-miss or interrupt. If we don't do this
+        * estatus is not updated the next exception.
+        */
+       rdctl   r24, status
+       movi    r9, %lo(~STATUS_EH)
+       and     r24, r24, r9
+       wrctl   status, r24
+
+       /* Read cause and vector and branch to the associated handler */
+       mov     r4, sp
+       rdctl   r5, exception
+       movia   r9, exception_table
+       add     r24, r9, r5
+       ldw     r24, 0(r24)
+       jmp     r24
+
+
+/***********************************************************************
+ * Handle traps
+ ***********************************************************************
+ */
+ENTRY(handle_trap)
+       ldw     r24, -4(ea)     /* instruction that caused the exception */
+       srli    r24, r24, 4
+       andi    r24, r24, 0x7c
+       movia   r9,trap_table
+       add     r24, r24, r9
+       ldw     r24, 0(r24)
+       jmp     r24
+
+
+/***********************************************************************
+ * Handle system calls
+ ***********************************************************************
+ */
+ENTRY(handle_system_call)
+       /* Enable interrupts */
+       rdctl   r10, status
+       ori     r10, r10, STATUS_PIE
+       wrctl   status, r10
+
+       /* Reload registers destroyed by common code. */
+       ldw     r4, PT_R4(sp)
+       ldw     r5, PT_R5(sp)
+
+local_restart:
+       /* Check that the requested system call is within limits */
+       movui   r1, __NR_syscalls
+       bgeu    r2, r1, ret_invsyscall
+       slli    r1, r2, 2
+       movhi   r11, %hiadj(sys_call_table)
+       add     r1, r1, r11
+       ldw     r1, %lo(sys_call_table)(r1)
+       beq     r1, r0, ret_invsyscall
+
+       /* Check if we are being traced */
+       GET_THREAD_INFO r11
+       ldw     r11,TI_FLAGS(r11)
+       BTBNZ   r11,r11,TIF_SYSCALL_TRACE,traced_system_call
+
+       /* Execute the system call */
+       callr   r1
+
+       /* If the syscall returns a negative result:
+        *   Set r7 to 1 to indicate error,
+        *   Negate r2 to get a positive error code
+        * If the syscall returns zero or a positive value:
+        *   Set r7 to 0.
+        * The sigreturn system calls will skip the code below by
+        * adding to register ra. To avoid destroying registers
+        */
+translate_rc_and_ret:
+       movi    r1, 0
+       bge     r2, zero, 3f
+       sub     r2, zero, r2
+       movi    r1, 1
+3:
+       stw     r2, PT_R2(sp)
+       stw     r1, PT_R7(sp)
+end_translate_rc_and_ret:
+
+ret_from_exception:
+       ldw     r1, PT_ESTATUS(sp)
+       /* if so, skip resched, signals */
+       TSTBNZ  r1, r1, ESTATUS_EU, Luser_return
+
+restore_all:
+       rdctl   r10, status                     /* disable intrs */
+       andi    r10, r10, %lo(~STATUS_PIE)
+       wrctl   status, r10
+       RESTORE_ALL
+       eret
+
+       /* If the syscall number was invalid return ENOSYS */
+ret_invsyscall:
+       movi    r2, -ENOSYS
+       br      translate_rc_and_ret
+
+       /* This implements the same as above, except it calls
+        * do_syscall_trace_enter and do_syscall_trace_exit before and after the
+        * syscall in order for utilities like strace and gdb to work.
+        */
+traced_system_call:
+       SAVE_SWITCH_STACK
+       call    do_syscall_trace_enter
+       RESTORE_SWITCH_STACK
+
+       /* Create system call register arguments. The 5th and 6th
+          arguments on stack are already in place at the beginning
+          of pt_regs. */
+       ldw     r2, PT_R2(sp)
+       ldw     r4, PT_R4(sp)
+       ldw     r5, PT_R5(sp)
+       ldw     r6, PT_R6(sp)
+       ldw     r7, PT_R7(sp)
+
+       /* Fetch the syscall function, we don't need to check the boundaries
+        * since this is already done.
+        */
+       slli    r1, r2, 2
+       movhi   r11,%hiadj(sys_call_table)
+       add     r1, r1, r11
+       ldw     r1, %lo(sys_call_table)(r1)
+
+       callr   r1
+
+       /* If the syscall returns a negative result:
+        *   Set r7 to 1 to indicate error,
+        *   Negate r2 to get a positive error code
+        * If the syscall returns zero or a positive value:
+        *   Set r7 to 0.
+        * The sigreturn system calls will skip the code below by
+        * adding to register ra. To avoid destroying registers
+        */
+translate_rc_and_ret2:
+       movi    r1, 0
+       bge     r2, zero, 4f
+       sub     r2, zero, r2
+       movi    r1, 1
+4:
+       stw     r2, PT_R2(sp)
+       stw     r1, PT_R7(sp)
+end_translate_rc_and_ret2:
+       SAVE_SWITCH_STACK
+       call    do_syscall_trace_exit
+       RESTORE_SWITCH_STACK
+       br      ret_from_exception
+
+Luser_return:
+       GET_THREAD_INFO r11                     /* get thread_info pointer */
+       ldw     r10, TI_FLAGS(r11)              /* get thread_info->flags */
+       ANDI32  r11, r10, _TIF_WORK_MASK
+       beq     r11, r0, restore_all            /* Nothing to do */
+       BTBZ    r1, r10, TIF_NEED_RESCHED, Lsignal_return
+
+       /* Reschedule work */
+       call    schedule
+       br      ret_from_exception
+
+Lsignal_return:
+       ANDI32  r1, r10, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
+       beq     r1, r0, restore_all
+       mov     r4, sp                  /* pt_regs */
+       SAVE_SWITCH_STACK
+       call    do_notify_resume
+       beq     r2, r0, no_work_pending
+       RESTORE_SWITCH_STACK
+       /* prepare restart syscall here without leaving kernel */
+       ldw     r2, PT_R2(sp)   /* reload syscall number in r2 */
+       ldw     r4, PT_R4(sp)   /* reload syscall arguments r4-r9 */
+       ldw     r5, PT_R5(sp)
+       ldw     r6, PT_R6(sp)
+       ldw     r7, PT_R7(sp)
+       ldw     r8, PT_R8(sp)
+       ldw     r9, PT_R9(sp)
+       br      local_restart   /* restart syscall */
+
+no_work_pending:
+       RESTORE_SWITCH_STACK
+       br      ret_from_exception
+
+/***********************************************************************
+ * Handle external interrupts.
+ ***********************************************************************
+ */
+/*
+ * This is the generic interrupt handler (for all hardware interrupt
+ * sources). It figures out the vector number and calls the appropriate
+ * interrupt service routine directly.
+ */
+external_interrupt:
+       rdctl   r12, ipending
+       rdctl   r9, ienable
+       and     r12, r12, r9
+       /* skip if no interrupt is pending */
+       beq     r12, r0, ret_from_interrupt
+
+       movi    r24, -1
+       stw     r24, PT_ORIG_R2(sp)
+
+       /*
+        * Process an external hardware interrupt.
+        */
+
+       addi    ea, ea, -4      /* re-issue the interrupted instruction */
+       stw     ea, PT_EA(sp)
+2:     movi    r4, %lo(-1)     /* Start from bit position 0,
+                                       highest priority */
+                               /* This is the IRQ # for handler call */
+1:     andi    r10, r12, 1     /* Isolate bit we are interested in */
+       srli    r12, r12, 1     /* shift count is costly without hardware
+                                       multiplier */
+       addi    r4, r4, 1
+       beq     r10, r0, 1b
+       mov     r5, sp          /* Setup pt_regs pointer for handler call */
+       call    do_IRQ
+       rdctl   r12, ipending   /* check again if irq still pending */
+       rdctl   r9, ienable     /* Isolate possible interrupts */
+       and     r12, r12, r9
+       bne     r12, r0, 2b
+       /* br   ret_from_interrupt */ /* fall through to ret_from_interrupt */
+
+ENTRY(ret_from_interrupt)
+       ldw     r1, PT_ESTATUS(sp)      /* check if returning to kernel */
+       TSTBNZ  r1, r1, ESTATUS_EU, Luser_return
+
+#ifdef CONFIG_PREEMPT
+       GET_THREAD_INFO r1
+       ldw     r4, TI_PREEMPT_COUNT(r1)
+       bne     r4, r0, restore_all
+
+need_resched:
+       ldw     r4, TI_FLAGS(r1)                /* ? Need resched set */
+       BTBZ    r10, r4, TIF_NEED_RESCHED, restore_all
+       ldw     r4, PT_ESTATUS(sp)      /* ? Interrupts off */
+       andi    r10, r4, ESTATUS_EPIE
+       beq     r10, r0, restore_all
+       movia   r4, PREEMPT_ACTIVE
+       stw     r4, TI_PREEMPT_COUNT(r1)
+       rdctl   r10, status             /* enable intrs again */
+       ori     r10, r10 ,STATUS_PIE
+       wrctl   status, r10
+       PUSH    r1
+       call    schedule
+       POP     r1
+       mov     r4, r0
+       stw     r4, TI_PREEMPT_COUNT(r1)
+       rdctl   r10, status             /* disable intrs */
+       andi    r10, r10, %lo(~STATUS_PIE)
+       wrctl   status, r10
+       br      need_resched
+#else
+       br      restore_all
+#endif
+
+/***********************************************************************
+ * A few syscall wrappers
+ ***********************************************************************
+ */
+/*
+ * int clone(unsigned long clone_flags, unsigned long newsp,
+ *             int __user * parent_tidptr, int __user * child_tidptr,
+ *             int tls_val)
+ */
+ENTRY(sys_clone)
+       SAVE_SWITCH_STACK
+       addi    sp, sp, -4
+       stw     r7, 0(sp)       /* Pass 5th arg thru stack */
+       mov     r7, r6          /* 4th arg is 3rd of clone() */
+       mov     r6, zero        /* 3rd arg always 0 */
+       call    do_fork
+       addi    sp, sp, 4
+       RESTORE_SWITCH_STACK
+       ret
+
+ENTRY(sys_rt_sigreturn)
+       SAVE_SWITCH_STACK
+       mov     r4, sp
+       call    do_rt_sigreturn
+       RESTORE_SWITCH_STACK
+       addi    ra, ra, (end_translate_rc_and_ret - translate_rc_and_ret)
+       ret
+
+/***********************************************************************
+ * A few other wrappers and stubs
+ ***********************************************************************
+ */
+protection_exception_pte:
+       rdctl   r6, pteaddr
+       slli    r6, r6, 10
+       call    do_page_fault
+       br      ret_from_exception
+
+protection_exception_ba:
+       rdctl   r6, badaddr
+       call    do_page_fault
+       br      ret_from_exception
+
+protection_exception_instr:
+       call    handle_supervisor_instr
+       br      ret_from_exception
+
+handle_breakpoint:
+       call    breakpoint_c
+       br      ret_from_exception
+
+#ifdef CONFIG_NIOS2_ALIGNMENT_TRAP
+handle_unaligned:
+       SAVE_SWITCH_STACK
+       call    handle_unaligned_c
+       RESTORE_SWITCH_STACK
+       br      ret_from_exception
+#else
+handle_unaligned:
+       call    handle_unaligned_c
+       br      ret_from_exception
+#endif
+
+handle_illegal:
+       call    handle_illegal_c
+       br      ret_from_exception
+
+handle_diverror:
+       call    handle_diverror_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
+ * registers.
+ */
+ENTRY(resume)
+
+       rdctl   r7, status                      /* save thread status reg */
+       stw     r7, TASK_THREAD + THREAD_KPSR(r4)
+
+       andi    r7, r7, %lo(~STATUS_PIE)        /* disable interrupts */
+       wrctl   status, r7
+
+       SAVE_SWITCH_STACK
+       stw     sp, TASK_THREAD + THREAD_KSP(r4)/* save kernel stack pointer */
+       ldw     sp, TASK_THREAD + THREAD_KSP(r5)/* restore new thread stack */
+       movia   r24, _current_thread            /* save thread */
+       GET_THREAD_INFO r1
+       stw     r1, 0(r24)
+       RESTORE_SWITCH_STACK
+
+       ldw     r7, TASK_THREAD + THREAD_KPSR(r5)/* restore thread status reg */
+       wrctl   status, r7
+       ret
+
+ENTRY(ret_from_fork)
+       call    schedule_tail
+       br      ret_from_exception
+
+ENTRY(ret_from_kernel_thread)
+       call    schedule_tail
+       mov     r4,r17  /* arg */
+       callr   r16     /* function */
+       br      ret_from_exception
+
+/*
+ * Kernel user helpers.
+ *
+ * Each segment is 64-byte aligned and will be mapped to the <User space>.
+ * New segments (if ever needed) must be added after the existing ones.
+ * This mechanism should be used only for things that are really small and
+ * justified, and not be abused freely.
+ *
+ */
+
+ /* Filling pads with undefined instructions. */
+.macro kuser_pad sym size
+       .if     ((. - \sym) & 3)
+       .rept   (4 - (. - \sym) & 3)
+       .byte   0
+       .endr
+       .endif
+       .rept   ((\size - (. - \sym)) / 4)
+       .word   0xdeadbeef
+       .endr
+.endm
+
+       .align  6
+       .globl  __kuser_helper_start
+__kuser_helper_start:
+
+__kuser_helper_version:                                /* @ 0x1000 */
+       .word   ((__kuser_helper_end - __kuser_helper_start) >> 6)
+
+__kuser_cmpxchg:                               /* @ 0x1004 */
+       /*
+        * r4 pointer to exchange variable
+        * r5 old value
+        * r6 new value
+        */
+cmpxchg_ldw:
+       ldw     r2, 0(r4)                       /* load current value */
+       sub     r2, r2, r5                      /* compare with old value */
+       bne     r2, zero, cmpxchg_ret
+
+       /* We had a match, store the new value */
+cmpxchg_stw:
+       stw     r6, 0(r4)
+cmpxchg_ret:
+       ret
+
+       kuser_pad __kuser_cmpxchg, 64
+
+       .globl  __kuser_sigtramp
+__kuser_sigtramp:
+       movi    r2, __NR_rt_sigreturn
+       trap
+
+       kuser_pad __kuser_sigtramp, 64
+
+       .globl  __kuser_helper_end
+__kuser_helper_end:
diff --git a/arch/nios2/kernel/head.S b/arch/nios2/kernel/head.S
new file mode 100644 (file)
index 0000000..372ce4a
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2009 Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd.
+ *
+ * Based on head.S for Altera's Excalibur development board with nios processor
+ *
+ * Based on the following from the Excalibur sdk distribution:
+ *     NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s
+ *
+ * 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/init.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/page.h>
+#include <asm/asm-offsets.h>
+#include <asm/asm-macros.h>
+
+/*
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+.data
+.global empty_zero_page
+.align 12
+empty_zero_page:
+       .space  PAGE_SIZE
+
+/*
+ * This global variable is used as an extension to the nios'
+ * STATUS register to emulate a user/supervisor mode.
+ */
+       .data
+       .align  2
+       .set noat
+
+       .global _current_thread
+_current_thread:
+       .long   0
+/*
+ * Input(s): passed from u-boot
+ *   r4 - Optional pointer to a board information structure.
+ *   r5 - Optional pointer to the physical starting address of the init RAM
+ *        disk.
+ *   r6 - Optional pointer to the physical ending address of the init RAM
+ *        disk.
+ *   r7 - Optional pointer to the physical starting address of any kernel
+ *        command-line parameters.
+ */
+
+/*
+ * First executable code - detected and jumped to by the ROM bootstrap
+ * if the code resides in flash (looks for "Nios" at offset 0x0c from
+ * the potential executable image).
+ */
+       __HEAD
+ENTRY(_start)
+       wrctl   status, r0              /* Disable interrupts */
+
+       /* Initialize all cache lines within the instruction cache */
+       movia   r1, NIOS2_ICACHE_SIZE
+       movui   r2, NIOS2_ICACHE_LINE_SIZE
+
+icache_init:
+       initi   r1
+       sub     r1, r1, r2
+       bgt     r1, r0, icache_init
+       br      1f
+
+       /*
+        * This is the default location for the exception handler. Code in jump
+        * to our handler
+        */
+ENTRY(exception_handler_hook)
+       movia   r24, inthandler
+       jmp     r24
+
+ENTRY(fast_handler)
+       nextpc et
+helper:
+       stw     r3, r3save - helper(et)
+
+       rdctl   r3 , pteaddr
+       srli    r3, r3, 12
+       slli    r3, r3, 2
+       movia   et, pgd_current
+
+       ldw     et, 0(et)
+       add     r3, et, r3
+       ldw     et, 0(r3)
+
+       rdctl   r3, pteaddr
+       andi    r3, r3, 0xfff
+       add     et, r3, et
+       ldw     et, 0(et)
+       wrctl   tlbacc, et
+       nextpc  et
+helper2:
+       ldw     r3, r3save - helper2(et)
+       subi    ea, ea, 4
+       eret
+r3save:
+       .word 0x0
+ENTRY(fast_handler_end)
+
+1:
+       /*
+        * After the instruction cache is initialized, the data cache must
+        * also be initialized.
+        */
+       movia   r1, NIOS2_DCACHE_SIZE
+       movui   r2, NIOS2_DCACHE_LINE_SIZE
+
+dcache_init:
+       initd   0(r1)
+       sub     r1, r1, r2
+       bgt     r1, r0, dcache_init
+
+       nextpc  r1                      /* Find out where we are */
+chkadr:
+       movia   r2, chkadr
+       beq     r1, r2,finish_move      /* We are running in RAM done */
+       addi    r1, r1,(_start - chkadr)        /* Source */
+       movia   r2, _start              /* Destination */
+       movia   r3, __bss_start         /* End of copy */
+
+loop_move:                             /* r1: src, r2: dest, r3: last dest */
+       ldw     r8, 0(r1)               /* load a word from [r1] */
+       stw     r8, 0(r2)               /* store a word to dest [r2] */
+       flushd  0(r2)                   /* Flush cache for safety */
+       addi    r1, r1, 4               /* inc the src addr */
+       addi    r2, r2, 4               /* inc the dest addr */
+       blt     r2, r3, loop_move
+
+       movia   r1, finish_move         /* VMA(_start)->l1 */
+       jmp     r1                      /* jmp to _start */
+
+finish_move:
+
+       /* Mask off all possible interrupts */
+       wrctl   ienable, r0
+
+       /* Clear .bss */
+       movia   r2, __bss_start
+       movia   r1, __bss_stop
+1:
+       stb     r0, 0(r2)
+       addi    r2, r2, 1
+       bne     r1, r2, 1b
+
+       movia   r1, init_thread_union   /* set stack at top of the task union */
+       addi    sp, r1, THREAD_SIZE
+       movia   r2, _current_thread     /* Remember current thread */
+       stw     r1, 0(r2)
+
+       movia   r1, nios2_boot_init     /* save args r4-r7 passed from u-boot */
+       callr   r1
+
+       movia   r1, start_kernel        /* call start_kernel as a subroutine */
+       callr   r1
+
+       /* If we return from start_kernel, break to the oci debugger and
+        * buggered we are.
+        */
+       break
+
+       /* End of startup code */
+.set at
diff --git a/arch/nios2/kernel/insnemu.S b/arch/nios2/kernel/insnemu.S
new file mode 100644 (file)
index 0000000..1c6b651
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ *  Copyright (C) 2003-2013 Altera Corporation
+ *  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <linux/linkage.h>
+#include <asm/entry.h>
+
+.set noat
+.set nobreak
+
+/*
+* Explicitly allow the use of r1 (the assembler temporary register)
+* within this code. This register is normally reserved for the use of
+* the compiler.
+*/
+
+ENTRY(instruction_trap)
+       ldw     r1, PT_R1(sp)           // Restore registers
+       ldw     r2, PT_R2(sp)
+       ldw     r3, PT_R3(sp)
+       ldw     r4, PT_R4(sp)
+       ldw     r5, PT_R5(sp)
+       ldw     r6, PT_R6(sp)
+       ldw     r7, PT_R7(sp)
+       ldw     r8, PT_R8(sp)
+       ldw     r9, PT_R9(sp)
+       ldw     r10, PT_R10(sp)
+       ldw     r11, PT_R11(sp)
+       ldw     r12, PT_R12(sp)
+       ldw     r13, PT_R13(sp)
+       ldw     r14, PT_R14(sp)
+       ldw     r15, PT_R15(sp)
+       ldw     ra, PT_RA(sp)
+       ldw     fp, PT_FP(sp)
+       ldw     gp, PT_GP(sp)
+       ldw     et, PT_ESTATUS(sp)
+       wrctl   estatus, et
+       ldw     ea, PT_EA(sp)
+       ldw     et, PT_SP(sp)           /* backup sp in et */
+
+       addi    sp, sp, PT_REGS_SIZE
+
+       /* INSTRUCTION EMULATION
+       *  ---------------------
+       *
+       * Nios II processors generate exceptions for unimplemented instructions.
+       * The routines below emulate these instructions.  Depending on the
+       * processor core, the only instructions that might need to be emulated
+       * are div, divu, mul, muli, mulxss, mulxsu, and mulxuu.
+       *
+       * The emulations match the instructions, except for the following
+       * limitations:
+       *
+       * 1) The emulation routines do not emulate the use of the exception
+       *    temporary register (et) as a source operand because the exception
+       *    handler already has modified it.
+       *
+       * 2) The routines do not emulate the use of the stack pointer (sp) or
+       *    the exception return address register (ea) as a destination because
+       *    modifying these registers crashes the exception handler or the
+       *    interrupted routine.
+       *
+       * Detailed Design
+       * ---------------
+       *
+       * The emulation routines expect the contents of integer registers r0-r31
+       * to be on the stack at addresses sp, 4(sp), 8(sp), ... 124(sp).  The
+       * routines retrieve source operands from the stack and modify the
+       * destination register's value on the stack prior to the end of the
+       * exception handler.  Then all registers except the destination register
+       * are restored to their previous values.
+       *
+       * The instruction that causes the exception is found at address -4(ea).
+       * The instruction's OP and OPX fields identify the operation to be
+       * performed.
+       *
+       * One instruction, muli, is an I-type instruction that is identified by
+       * an OP field of 0x24.
+       *
+       * muli   AAAAA,BBBBB,IIIIIIIIIIIIIIII,-0x24-
+       *           27    22                6      0    <-- LSB of field
+       *
+       * The remaining emulated instructions are R-type and have an OP field
+       * of 0x3a.  Their OPX fields identify them.
+       *
+       * R-type AAAAA,BBBBB,CCCCC,XXXXXX,NNNNN,-0x3a-
+       *           27    22    17     11     6      0  <-- LSB of field
+       *
+       *
+       * Opcode Encoding.  muli is identified by its OP value.  Then OPX & 0x02
+       * is used to differentiate between the division opcodes and the
+       * remaining multiplication opcodes.
+       *
+       * Instruction   OP      OPX    OPX & 0x02
+       * -----------   ----    ----   ----------
+       * muli          0x24
+       * divu          0x3a    0x24         0
+       * div           0x3a    0x25         0
+       * mul           0x3a    0x27      != 0
+       * mulxuu        0x3a    0x07      != 0
+       * mulxsu        0x3a    0x17      != 0
+       * mulxss        0x3a    0x1f      != 0
+       */
+
+
+       /*
+       * Save everything on the stack to make it easy for the emulation
+       * routines to retrieve the source register operands.
+       */
+
+       addi sp, sp, -128
+       stw zero, 0(sp) /* Save zero on stack to avoid special case for r0. */
+       stw r1, 4(sp)
+       stw r2,  8(sp)
+       stw r3, 12(sp)
+       stw r4, 16(sp)
+       stw r5, 20(sp)
+       stw r6, 24(sp)
+       stw r7, 28(sp)
+       stw r8, 32(sp)
+       stw r9, 36(sp)
+       stw r10, 40(sp)
+       stw r11, 44(sp)
+       stw r12, 48(sp)
+       stw r13, 52(sp)
+       stw r14, 56(sp)
+       stw r15, 60(sp)
+       stw r16, 64(sp)
+       stw r17, 68(sp)
+       stw r18, 72(sp)
+       stw r19, 76(sp)
+       stw r20, 80(sp)
+       stw r21, 84(sp)
+       stw r22, 88(sp)
+       stw r23, 92(sp)
+               /* Don't bother to save et.  It's already been changed. */
+       rdctl r5, estatus
+       stw r5,  100(sp)
+
+       stw gp, 104(sp)
+       stw et, 108(sp) /* et contains previous sp value. */
+       stw fp, 112(sp)
+       stw ea, 116(sp)
+       stw ra, 120(sp)
+
+
+       /*
+       * Split the instruction into its fields.  We need 4*A, 4*B, and 4*C as
+       * offsets to the stack pointer for access to the stored register values.
+       */
+       ldw r2,-4(ea)   /* r2 = AAAAA,BBBBB,IIIIIIIIIIIIIIII,PPPPPP */
+       roli r3, r2, 7  /* r3 = BBB,IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BB */
+       roli r4, r3, 3  /* r4 = IIIIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB */
+       roli r5, r4, 2  /* r5 = IIIIIIIIIIIIII,PPPPPP,AAAAA,BBBBB,II */
+       srai r4, r4, 16 /* r4 = (sign-extended) IMM16 */
+       roli r6, r5, 5  /* r6 = XXXX,NNNNN,PPPPPP,AAAAA,BBBBB,CCCCC,XX */
+       andi r2, r2, 0x3f       /* r2 = 00000000000000000000000000,PPPPPP */
+       andi r3, r3, 0x7c       /* r3 = 0000000000000000000000000,AAAAA,00 */
+       andi r5, r5, 0x7c       /* r5 = 0000000000000000000000000,BBBBB,00 */
+       andi r6, r6, 0x7c       /* r6 = 0000000000000000000000000,CCCCC,00 */
+
+       /* Now
+       * r2 = OP
+       * r3 = 4*A
+       * r4 = IMM16 (sign extended)
+       * r5 = 4*B
+       * r6 = 4*C
+       */
+
+       /*
+       * Get the operands.
+       *
+       * It is necessary to check for muli because it uses an I-type
+       * instruction format, while the other instructions are have an R-type
+       * format.
+       *
+       *  Prepare for either multiplication or division loop.
+       *  They both loop 32 times.
+       */
+       movi r14, 32
+
+       add  r3, r3, sp         /* r3 = address of A-operand. */
+       ldw  r3, 0(r3)          /* r3 = A-operand. */
+       movi r7, 0x24           /* muli opcode (I-type instruction format) */
+       beq r2, r7, mul_immed /* muli doesn't use the B register as a source */
+
+       add  r5, r5, sp         /* r5 = address of B-operand. */
+       ldw  r5, 0(r5)          /* r5 = B-operand. */
+                               /* r4 = SSSSSSSSSSSSSSSS,-----IMM16------ */
+                               /* IMM16 not needed, align OPX portion */
+                               /* r4 = SSSSSSSSSSSSSSSS,CCCCC,-OPX--,00000 */
+       srli r4, r4, 5          /* r4 = 00000,SSSSSSSSSSSSSSSS,CCCCC,-OPX-- */
+       andi r4, r4, 0x3f       /* r4 = 00000000000000000000000000,-OPX-- */
+
+       /* Now
+       * r2 = OP
+       * r3 = src1
+       * r5 = src2
+       * r4 = OPX (no longer can be muli)
+       * r6 = 4*C
+       */
+
+
+       /*
+       *  Multiply or Divide?
+       */
+       andi r7, r4, 0x02       /* For R-type multiply instructions,
+                                  OPX & 0x02 != 0 */
+       bne r7, zero, multiply
+
+
+       /* DIVISION
+       *
+       * Divide an unsigned dividend by an unsigned divisor using
+       * a shift-and-subtract algorithm.  The example below shows
+       * 43 div 7 = 6 for 8-bit integers.  This classic algorithm uses a
+       * single register to store both the dividend and the quotient,
+       * allowing both values to be shifted with a single instruction.
+       *
+       *                               remainder dividend:quotient
+       *                               --------- -----------------
+       *   initialize                   00000000     00101011:
+       *   shift                        00000000     0101011:_
+       *   remainder >= divisor? no     00000000     0101011:0
+       *   shift                        00000000     101011:0_
+       *   remainder >= divisor? no     00000000     101011:00
+       *   shift                        00000001     01011:00_
+       *   remainder >= divisor? no     00000001     01011:000
+       *   shift                        00000010     1011:000_
+       *   remainder >= divisor? no     00000010     1011:0000
+       *   shift                        00000101     011:0000_
+       *   remainder >= divisor? no     00000101     011:00000
+       *   shift                        00001010     11:00000_
+       *   remainder >= divisor? yes    00001010     11:000001
+       *       remainder -= divisor   - 00000111
+       *                              ----------
+       *                                00000011     11:000001
+       *   shift                        00000111     1:000001_
+       *   remainder >= divisor? yes    00000111     1:0000011
+       *       remainder -= divisor   - 00000111
+       *                              ----------
+       *                                00000000     1:0000011
+       *   shift                        00000001     :0000011_
+       *   remainder >= divisor? no     00000001     :00000110
+       *
+       * The quotient is 00000110.
+       */
+
+divide:
+       /*
+       *  Prepare for division by assuming the result
+       *  is unsigned, and storing its "sign" as 0.
+       */
+       movi r17, 0
+
+
+       /* Which division opcode? */
+       xori r7, r4, 0x25               /* OPX of div */
+       bne r7, zero, unsigned_division
+
+
+       /*
+       *  OPX is div.  Determine and store the sign of the quotient.
+       *  Then take the absolute value of both operands.
+       */
+       xor r17, r3, r5         /* MSB contains sign of quotient */
+       bge r3,zero,dividend_is_nonnegative
+       sub r3, zero, r3        /* -r3 */
+dividend_is_nonnegative:
+       bge r5, zero, divisor_is_nonnegative
+       sub r5, zero, r5        /* -r5 */
+divisor_is_nonnegative:
+
+
+unsigned_division:
+       /* Initialize the unsigned-division loop. */
+       movi r13, 0     /* remainder = 0 */
+
+       /* Now
+       * r3 = dividend : quotient
+       * r4 = 0x25 for div, 0x24 for divu
+       * r5 = divisor
+       * r13 = remainder
+       * r14 = loop counter (already initialized to 32)
+       * r17 = MSB contains sign of quotient
+       */
+
+
+       /*
+       *   for (count = 32; count > 0; --count)
+       *   {
+       */
+divide_loop:
+
+       /*
+       *       Division:
+       *
+       *       (remainder:dividend:quotient) <<= 1;
+       */
+       slli r13, r13, 1
+       cmplt r7, r3, zero      /* r7 = MSB of r3 */
+       or r13, r13, r7
+       slli r3, r3, 1
+
+
+       /*
+       *       if (remainder >= divisor)
+       *       {
+       *           set LSB of quotient
+       *           remainder -= divisor;
+       *       }
+       */
+       bltu r13, r5, div_skip
+       ori r3, r3, 1
+       sub r13, r13, r5
+div_skip:
+
+       /*
+       *   }
+       */
+       subi r14, r14, 1
+       bne r14, zero, divide_loop
+
+
+       /* Now
+       * r3 = quotient
+       * r4 = 0x25 for div, 0x24 for divu
+       * r6 = 4*C
+       * r17 = MSB contains sign of quotient
+       */
+
+
+       /*
+       *  Conditionally negate signed quotient.  If quotient is unsigned,
+       *  the sign already is initialized to 0.
+       */
+       bge r17, zero, quotient_is_nonnegative
+       sub r3, zero, r3                /* -r3 */
+       quotient_is_nonnegative:
+
+
+       /*
+       *  Final quotient is in r3.
+       */
+       add r6, r6, sp
+       stw r3, 0(r6)   /* write quotient to stack */
+       br restore_registers
+
+
+
+
+       /* MULTIPLICATION
+       *
+       * A "product" is the number that one gets by summing a "multiplicand"
+       * several times.  The "multiplier" specifies the number of copies of the
+       * multiplicand that are summed.
+       *
+       * Actual multiplication algorithms don't use repeated addition, however.
+       * Shift-and-add algorithms get the same answer as repeated addition, and
+       * they are faster.  To compute the lower half of a product (pppp below)
+       * one shifts the product left before adding in each of the partial
+       * products (a * mmmm) through (d * mmmm).
+       *
+       * To compute the upper half of a product (PPPP below), one adds in the
+       * partial products (d * mmmm) through (a * mmmm), each time following
+       * the add by a right shift of the product.
+       *
+       *     mmmm
+       *   * abcd
+       *   ------
+       *     ####  = d * mmmm
+       *    ####   = c * mmmm
+       *   ####    = b * mmmm
+       *  ####     = a * mmmm
+       * --------
+       * PPPPpppp
+       *
+       * The example above shows 4 partial products.  Computing actual Nios II
+       * products requires 32 partials.
+       *
+       * It is possible to compute the result of mulxsu from the result of
+       * mulxuu because the only difference between the results of these two
+       * opcodes is the value of the partial product associated with the sign
+       * bit of rA.
+       *
+       *   mulxsu = mulxuu - (rA < 0) ? rB : 0;
+       *
+       * It is possible to compute the result of mulxss from the result of
+       * mulxsu because the only difference between the results of these two
+       * opcodes is the value of the partial product associated with the sign
+       * bit of rB.
+       *
+       *   mulxss = mulxsu - (rB < 0) ? rA : 0;
+       *
+       */
+
+mul_immed:
+       /* Opcode is muli.  Change it into mul for remainder of algorithm. */
+       mov r6, r5              /* Field B is dest register, not field C. */
+       mov r5, r4              /* Field IMM16 is src2, not field B. */
+       movi r4, 0x27           /* OPX of mul is 0x27 */
+
+multiply:
+       /* Initialize the multiplication loop. */
+       movi r9, 0      /* mul_product    = 0 */
+       movi r10, 0     /* mulxuu_product = 0 */
+       mov r11, r5     /* save original multiplier for mulxsu and mulxss */
+       mov r12, r5     /* mulxuu_multiplier (will be shifted) */
+       movi r16, 1     /* used to create "rori B,A,1" from "ror B,A,r16" */
+
+       /* Now
+       * r3 = multiplicand
+       * r5 = mul_multiplier
+       * r6 = 4 * dest_register (used later as offset to sp)
+       * r7 = temp
+       * r9 = mul_product
+       * r10 = mulxuu_product
+       * r11 = original multiplier
+       * r12 = mulxuu_multiplier
+       * r14 = loop counter (already initialized)
+       * r16 = 1
+       */
+
+
+       /*
+       *   for (count = 32; count > 0; --count)
+       *   {
+       */
+multiply_loop:
+
+       /*
+       *       mul_product <<= 1;
+       *       lsb = multiplier & 1;
+       */
+       slli r9, r9, 1
+       andi r7, r12, 1
+
+       /*
+       *       if (lsb == 1)
+       *       {
+       *           mulxuu_product += multiplicand;
+       *       }
+       */
+       beq r7, zero, mulx_skip
+       add r10, r10, r3
+       cmpltu r7, r10, r3 /* Save the carry from the MSB of mulxuu_product. */
+       ror r7, r7, r16 /* r7 = 0x80000000 on carry, or else 0x00000000 */
+mulx_skip:
+
+       /*
+       *       if (MSB of mul_multiplier == 1)
+       *       {
+       *           mul_product += multiplicand;
+       *       }
+       */
+       bge r5, zero, mul_skip
+       add r9, r9, r3
+mul_skip:
+
+       /*
+       *       mulxuu_product >>= 1;           logical shift
+       *       mul_multiplier <<= 1;           done with MSB
+       *       mulx_multiplier >>= 1;          done with LSB
+       */
+       srli r10, r10, 1
+       or r10, r10, r7         /* OR in the saved carry bit. */
+       slli r5, r5, 1
+       srli r12, r12, 1
+
+
+       /*
+       *   }
+       */
+       subi r14, r14, 1
+       bne r14, zero, multiply_loop
+
+
+       /*
+       *  Multiply emulation loop done.
+       */
+
+       /* Now
+       * r3 = multiplicand
+       * r4 = OPX
+       * r6 = 4 * dest_register (used later as offset to sp)
+       * r7 = temp
+       * r9 = mul_product
+       * r10 = mulxuu_product
+       * r11 = original multiplier
+       */
+
+
+       /* Calculate address for result from 4 * dest_register */
+       add r6, r6, sp
+
+
+       /*
+       * Select/compute the result based on OPX.
+       */
+
+
+       /* OPX == mul?  Then store. */
+       xori r7, r4, 0x27
+       beq r7, zero, store_product
+
+       /* It's one of the mulx.. opcodes.  Move over the result. */
+       mov r9, r10
+
+       /* OPX == mulxuu?  Then store. */
+       xori r7, r4, 0x07
+       beq r7, zero, store_product
+
+       /* Compute mulxsu
+        *
+        * mulxsu = mulxuu - (rA < 0) ? rB : 0;
+        */
+       bge r3, zero, mulxsu_skip
+       sub r9, r9, r11
+mulxsu_skip:
+
+       /* OPX == mulxsu?  Then store. */
+       xori r7, r4, 0x17
+       beq r7, zero, store_product
+
+       /* Compute mulxss
+        *
+        * mulxss = mulxsu - (rB < 0) ? rA : 0;
+        */
+       bge r11,zero,mulxss_skip
+       sub r9, r9, r3
+mulxss_skip:
+       /* At this point, assume that OPX is mulxss, so store*/
+
+
+store_product:
+       stw r9, 0(r6)
+
+
+restore_registers:
+                       /* No need to restore r0. */
+       ldw r5, 100(sp)
+       wrctl estatus, r5
+
+       ldw r1, 4(sp)
+       ldw r2, 8(sp)
+       ldw r3, 12(sp)
+       ldw r4, 16(sp)
+       ldw r5, 20(sp)
+       ldw r6, 24(sp)
+       ldw r7, 28(sp)
+       ldw r8, 32(sp)
+       ldw r9, 36(sp)
+       ldw r10, 40(sp)
+       ldw r11, 44(sp)
+       ldw r12, 48(sp)
+       ldw r13, 52(sp)
+       ldw r14, 56(sp)
+       ldw r15, 60(sp)
+       ldw r16, 64(sp)
+       ldw r17, 68(sp)
+       ldw r18, 72(sp)
+       ldw r19, 76(sp)
+       ldw r20, 80(sp)
+       ldw r21, 84(sp)
+       ldw r22, 88(sp)
+       ldw r23, 92(sp)
+                       /* Does not need to restore et */
+       ldw gp, 104(sp)
+
+       ldw fp, 112(sp)
+       ldw ea, 116(sp)
+       ldw ra, 120(sp)
+       ldw sp, 108(sp) /* last restore sp */
+       eret
+
+.set at
+.set break
diff --git a/arch/nios2/kernel/irq.c b/arch/nios2/kernel/irq.c
new file mode 100644 (file)
index 0000000..f5b74ae
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * based on irq.c from m68k which is:
+ *
+ * Copyright (C) 2007 Greg Ungerer <gerg@snapgear.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/>.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+
+static u32 ienable;
+
+asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
+{
+       struct pt_regs *oldregs = set_irq_regs(regs);
+       int irq;
+
+       irq_enter();
+       irq = irq_find_mapping(NULL, hwirq);
+       generic_handle_irq(irq);
+       irq_exit();
+
+       set_irq_regs(oldregs);
+}
+
+static void chip_unmask(struct irq_data *d)
+{
+       ienable |= (1 << d->hwirq);
+       WRCTL(CTL_IENABLE, ienable);
+}
+
+static void chip_mask(struct irq_data *d)
+{
+       ienable &= ~(1 << d->hwirq);
+       WRCTL(CTL_IENABLE, ienable);
+}
+
+static struct irq_chip m_irq_chip = {
+       .name           = "NIOS2-INTC",
+       .irq_unmask     = chip_unmask,
+       .irq_mask       = chip_mask,
+};
+
+static int irq_map(struct irq_domain *h, unsigned int virq,
+                               irq_hw_number_t hw_irq_num)
+{
+       irq_set_chip_and_handler(virq, &m_irq_chip, handle_level_irq);
+
+       return 0;
+}
+
+static struct irq_domain_ops irq_ops = {
+       .map    = irq_map,
+       .xlate  = irq_domain_xlate_onecell,
+};
+
+void __init init_IRQ(void)
+{
+       struct irq_domain *domain;
+       struct device_node *node;
+
+       node = of_find_compatible_node(NULL, NULL, "altr,nios2-1.0");
+       if (!node)
+               node = of_find_compatible_node(NULL, NULL, "altr,nios2-1.1");
+
+       BUG_ON(!node);
+
+       domain = irq_domain_add_linear(node, NIOS2_CPU_NR_IRQS, &irq_ops, NULL);
+       BUG_ON(!domain);
+
+       irq_set_default_host(domain);
+       of_node_put(node);
+       /* Load the initial ienable value */
+       ienable = RDCTL(CTL_IENABLE);
+}
diff --git a/arch/nios2/kernel/misaligned.c b/arch/nios2/kernel/misaligned.c
new file mode 100644 (file)
index 0000000..4e5907a
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ *  linux/arch/nios2/kernel/misaligned.c
+ *
+ *  basic emulation for mis-aligned accesses on the NIOS II cpu
+ *  modelled after the version for arm in arm/alignment.c
+ *
+ *  Brad Parker <brad@heeltoe.com>
+ *  Copyright (C) 2010 Ambient Corporation
+ *  Copyright (c) 2010 Altera Corporation, San Jose, California, USA.
+ *  Copyright (c) 2010 Arrow Electronics, Inc.
+ *
+ * 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/errno.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
+
+#include <asm/traps.h>
+#include <asm/unaligned.h>
+
+/* instructions we emulate */
+#define INST_LDHU      0x0b
+#define INST_STH       0x0d
+#define INST_LDH       0x0f
+#define INST_STW       0x15
+#define INST_LDW       0x17
+
+static unsigned long ma_user, ma_kern, ma_skipped, ma_half, ma_word;
+
+static unsigned int ma_usermode;
+#define UM_WARN                0x01
+#define UM_FIXUP       0x02
+#define UM_SIGNAL      0x04
+#define KM_WARN                0x08
+
+/* see arch/nios2/include/asm/ptrace.h */
+static u8 sys_stack_frame_reg_offset[] = {
+       /* struct pt_regs */
+       8, 9, 10, 11, 12, 13, 14, 15, 1, 2, 3, 4, 5, 6, 7, 0,
+       /* struct switch_stack */
+       16, 17, 18, 19, 20, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int reg_offsets[32];
+
+static inline u32 get_reg_val(struct pt_regs *fp, int reg)
+{
+       u8 *p = ((u8 *)fp) + reg_offsets[reg];
+
+       return *(u32 *)p;
+}
+
+static inline void put_reg_val(struct pt_regs *fp, int reg, u32 val)
+{
+       u8 *p = ((u8 *)fp) + reg_offsets[reg];
+       *(u32 *)p = val;
+}
+
+/*
+ * (mis)alignment handler
+ */
+asmlinkage void handle_unaligned_c(struct pt_regs *fp, int cause)
+{
+       u32 isn, addr, val;
+       int in_kernel;
+       u8 a, b, d0, d1, d2, d3;
+       u16 imm16;
+       unsigned int fault;
+
+       /* back up one instruction */
+       fp->ea -= 4;
+
+       if (fixup_exception(fp)) {
+               ma_skipped++;
+               return;
+       }
+
+       in_kernel = !user_mode(fp);
+
+       isn = *(unsigned long *)(fp->ea);
+
+       fault = 0;
+
+       /* do fixup if in kernel or mode turned on */
+       if (in_kernel || (ma_usermode & UM_FIXUP)) {
+               /* decompose instruction */
+               a = (isn >> 27) & 0x1f;
+               b = (isn >> 22) & 0x1f;
+               imm16 = (isn >> 6) & 0xffff;
+               addr = get_reg_val(fp, a) + imm16;
+
+               /* do fixup to saved registers */
+               switch (isn & 0x3f) {
+               case INST_LDHU:
+                       fault |= __get_user(d0, (u8 *)(addr+0));
+                       fault |= __get_user(d1, (u8 *)(addr+1));
+                       val = (d1 << 8) | d0;
+                       put_reg_val(fp, b, val);
+                       ma_half++;
+                       break;
+               case INST_STH:
+                       val = get_reg_val(fp, b);
+                       d1 = val >> 8;
+                       d0 = val >> 0;
+
+                       pr_debug("sth: ra=%d (%08x) rb=%d (%08x), imm16 %04x addr %08x val %08x\n",
+                               a, get_reg_val(fp, a),
+                               b, get_reg_val(fp, b),
+                               imm16, addr, val);
+
+                       if (in_kernel) {
+                               *(u8 *)(addr+0) = d0;
+                               *(u8 *)(addr+1) = d1;
+                       } else {
+                               fault |= __put_user(d0, (u8 *)(addr+0));
+                               fault |= __put_user(d1, (u8 *)(addr+1));
+                       }
+                       ma_half++;
+                       break;
+               case INST_LDH:
+                       fault |= __get_user(d0, (u8 *)(addr+0));
+                       fault |= __get_user(d1, (u8 *)(addr+1));
+                       val = (short)((d1 << 8) | d0);
+                       put_reg_val(fp, b, val);
+                       ma_half++;
+                       break;
+               case INST_STW:
+                       val = get_reg_val(fp, b);
+                       d3 = val >> 24;
+                       d2 = val >> 16;
+                       d1 = val >> 8;
+                       d0 = val >> 0;
+                       if (in_kernel) {
+                               *(u8 *)(addr+0) = d0;
+                               *(u8 *)(addr+1) = d1;
+                               *(u8 *)(addr+2) = d2;
+                               *(u8 *)(addr+3) = d3;
+                       } else {
+                               fault |= __put_user(d0, (u8 *)(addr+0));
+                               fault |= __put_user(d1, (u8 *)(addr+1));
+                               fault |= __put_user(d2, (u8 *)(addr+2));
+                               fault |= __put_user(d3, (u8 *)(addr+3));
+                       }
+                       ma_word++;
+                       break;
+               case INST_LDW:
+                       fault |= __get_user(d0, (u8 *)(addr+0));
+                       fault |= __get_user(d1, (u8 *)(addr+1));
+                       fault |= __get_user(d2, (u8 *)(addr+2));
+                       fault |= __get_user(d3, (u8 *)(addr+3));
+                       val = (d3 << 24) | (d2 << 16) | (d1 << 8) | d0;
+                       put_reg_val(fp, b, val);
+                       ma_word++;
+                       break;
+               }
+       }
+
+       addr = RDCTL(CTL_BADADDR);
+       cause >>= 2;
+
+       if (fault) {
+               if (in_kernel) {
+                       pr_err("fault during kernel misaligned fixup @ %#lx; addr 0x%08x; isn=0x%08x\n",
+                               fp->ea, (unsigned int)addr,
+                               (unsigned int)isn);
+               } else {
+                       pr_err("fault during user misaligned fixup @ %#lx; isn=%08x addr=0x%08x sp=0x%08lx pid=%d\n",
+                               fp->ea,
+                               (unsigned int)isn, addr, fp->sp,
+                               current->pid);
+
+                       _exception(SIGSEGV, fp, SEGV_MAPERR, fp->ea);
+                       return;
+               }
+       }
+
+       /*
+        * kernel mode -
+        *  note exception and skip bad instruction (return)
+        */
+       if (in_kernel) {
+               ma_kern++;
+               fp->ea += 4;
+
+               if (ma_usermode & KM_WARN) {
+                       pr_err("kernel unaligned access @ %#lx; BADADDR 0x%08x; cause=%d, isn=0x%08x\n",
+                               fp->ea,
+                               (unsigned int)addr, cause,
+                               (unsigned int)isn);
+                       /* show_regs(fp); */
+               }
+
+               return;
+       }
+
+       ma_user++;
+
+       /*
+        * user mode -
+        *  possibly warn,
+        *  possibly send SIGBUS signal to process
+        */
+       if (ma_usermode & UM_WARN) {
+               pr_err("user unaligned access @ %#lx; isn=0x%08lx ea=0x%08lx ra=0x%08lx sp=0x%08lx\n",
+                       (unsigned long)addr, (unsigned long)isn,
+                       fp->ea, fp->ra, fp->sp);
+       }
+
+       if (ma_usermode & UM_SIGNAL)
+               _exception(SIGBUS, fp, BUS_ADRALN, fp->ea);
+       else
+               fp->ea += 4;    /* else advance */
+}
+
+static void __init misaligned_calc_reg_offsets(void)
+{
+       int i, r, offset;
+
+       /* pre-calc offsets of registers on sys call stack frame */
+       offset = 0;
+
+       /* struct pt_regs */
+       for (i = 0; i < 16; i++) {
+               r = sys_stack_frame_reg_offset[i];
+               reg_offsets[r] = offset;
+               offset += 4;
+       }
+
+       /* struct switch_stack */
+       offset = -sizeof(struct switch_stack);
+       for (i = 16; i < 32; i++) {
+               r = sys_stack_frame_reg_offset[i];
+               reg_offsets[r] = offset;
+               offset += 4;
+       }
+}
+
+
+static int __init misaligned_init(void)
+{
+       /* default mode - silent fix */
+       ma_usermode = UM_FIXUP | KM_WARN;
+
+       misaligned_calc_reg_offsets();
+
+       return 0;
+}
+
+fs_initcall(misaligned_init);
diff --git a/arch/nios2/kernel/module.c b/arch/nios2/kernel/module.c
new file mode 100644 (file)
index 0000000..cc924a3
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Kernel module support for Nios II.
+ *
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *   Written by Wentao Xu <xuwentao@microtronix.com>
+ * Copyright (C) 2001, 2003 Rusty Russell
+ *
+ * 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/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Modules should NOT be allocated with kmalloc for (obvious) reasons.
+ * But we do it for now to avoid relocation issues. CALL26/PCREL26 cannot reach
+ * from 0x80000000 (vmalloc area) to 0xc00000000 (kernel) (kmalloc returns
+ * addresses in 0xc0000000)
+ */
+void *module_alloc(unsigned long size)
+{
+       if (size == 0)
+               return NULL;
+       return kmalloc(size, GFP_KERNEL);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+       kfree(module_region);
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+                       unsigned int symindex, unsigned int relsec,
+                       struct module *mod)
+{
+       unsigned int i;
+       Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+
+       pr_debug("Applying relocate section %u to %u\n", relsec,
+                sechdrs[relsec].sh_info);
+
+       for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
+               /* This is where to make the change */
+               uint32_t word;
+               uint32_t *loc
+                       = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+                          + rela[i].r_offset);
+               /* This is the symbol it is referring to.  Note that all
+                  undefined symbols have been resolved.  */
+               Elf32_Sym *sym
+                       = ((Elf32_Sym *)sechdrs[symindex].sh_addr
+                               + ELF32_R_SYM(rela[i].r_info));
+               uint32_t v = sym->st_value + rela[i].r_addend;
+
+               pr_debug("reltype %d 0x%x name:<%s>\n",
+                       ELF32_R_TYPE(rela[i].r_info),
+                       rela[i].r_offset, strtab + sym->st_name);
+
+               switch (ELF32_R_TYPE(rela[i].r_info)) {
+               case R_NIOS2_NONE:
+                       break;
+               case R_NIOS2_BFD_RELOC_32:
+                       *loc += v;
+                       break;
+               case R_NIOS2_PCREL16:
+                       v -= (uint32_t)loc + 4;
+                       if ((int32_t)v > 0x7fff ||
+                               (int32_t)v < -(int32_t)0x8000) {
+                               pr_err("module %s: relocation overflow\n",
+                                       mod->name);
+                               return -ENOEXEC;
+                       }
+                       word = *loc;
+                       *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
+                               (word & 0x3f);
+                       break;
+               case R_NIOS2_CALL26:
+                       if (v & 3) {
+                               pr_err("module %s: dangerous relocation\n",
+                                       mod->name);
+                               return -ENOEXEC;
+                       }
+                       if ((v >> 28) != ((uint32_t)loc >> 28)) {
+                               pr_err("module %s: relocation overflow\n",
+                                       mod->name);
+                               return -ENOEXEC;
+                       }
+                       *loc = (*loc & 0x3f) | ((v >> 2) << 6);
+                       break;
+               case R_NIOS2_HI16:
+                       word = *loc;
+                       *loc = ((((word >> 22) << 16) |
+                               ((v >> 16) & 0xffff)) << 6) | (word & 0x3f);
+                       break;
+               case R_NIOS2_LO16:
+                       word = *loc;
+                       *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
+                                       (word & 0x3f);
+                       break;
+               case R_NIOS2_HIADJ16:
+                       {
+                               Elf32_Addr word2;
+
+                               word = *loc;
+                               word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
+                               *loc = ((((word >> 22) << 16) | word2) << 6) |
+                                               (word & 0x3f);
+                       }
+                       break;
+
+               default:
+                       pr_err("module %s: Unknown reloc: %u\n",
+                               mod->name, ELF32_R_TYPE(rela[i].r_info));
+                       return -ENOEXEC;
+               }
+       }
+
+       return 0;
+}
+
+int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+                       struct module *me)
+{
+       flush_cache_all();
+       return 0;
+}
diff --git a/arch/nios2/kernel/nios2_ksyms.c b/arch/nios2/kernel/nios2_ksyms.c
new file mode 100644 (file)
index 0000000..bf2f55d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * 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/export.h>
+#include <linux/string.h>
+
+/* string functions */
+
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memmove);
+
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler...  (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+#define DECLARE_EXPORT(name)   extern void name(void); EXPORT_SYMBOL(name)
+
+DECLARE_EXPORT(__gcc_bcmp);
+DECLARE_EXPORT(__divsi3);
+DECLARE_EXPORT(__moddi3);
+DECLARE_EXPORT(__modsi3);
+DECLARE_EXPORT(__udivmoddi4);
+DECLARE_EXPORT(__udivsi3);
+DECLARE_EXPORT(__umoddi3);
+DECLARE_EXPORT(__umodsi3);
+DECLARE_EXPORT(__muldi3);
diff --git a/arch/nios2/kernel/process.c b/arch/nios2/kernel/process.c
new file mode 100644 (file)
index 0000000..0e075b5
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Architecture-dependent parts of process handling.
+ *
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * 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/export.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+#include <linux/uaccess.h>
+
+#include <asm/unistd.h>
+#include <asm/traps.h>
+#include <asm/cpuinfo.h>
+
+asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
+
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
+void arch_cpu_idle(void)
+{
+       local_irq_enable();
+}
+
+/*
+ * The development boards have no way to pull a board reset. Just jump to the
+ * cpu reset address and let the boot loader or the code in head.S take care of
+ * resetting peripherals.
+ */
+void machine_restart(char *__unused)
+{
+       pr_notice("Machine restart (%08x)...\n", cpuinfo.reset_addr);
+       local_irq_disable();
+       __asm__ __volatile__ (
+       "jmp    %0\n\t"
+       :
+       : "r" (cpuinfo.reset_addr)
+       : "r4");
+}
+
+void machine_halt(void)
+{
+       pr_notice("Machine halt...\n");
+       local_irq_disable();
+       for (;;)
+               ;
+}
+
+/*
+ * There is no way to power off the development boards. So just spin for now. If
+ * we ever have a way of resetting a board using a GPIO we should add that here.
+ */
+void machine_power_off(void)
+{
+       pr_notice("Machine power off...\n");
+       local_irq_disable();
+       for (;;)
+               ;
+}
+
+void show_regs(struct pt_regs *regs)
+{
+       pr_notice("\n");
+       show_regs_print_info(KERN_DEFAULT);
+
+       pr_notice("r1: %08lx r2: %08lx r3: %08lx r4: %08lx\n",
+               regs->r1,  regs->r2,  regs->r3,  regs->r4);
+
+       pr_notice("r5: %08lx r6: %08lx r7: %08lx r8: %08lx\n",
+               regs->r5,  regs->r6,  regs->r7,  regs->r8);
+
+       pr_notice("r9: %08lx r10: %08lx r11: %08lx r12: %08lx\n",
+               regs->r9,  regs->r10, regs->r11, regs->r12);
+
+       pr_notice("r13: %08lx r14: %08lx r15: %08lx\n",
+               regs->r13, regs->r14, regs->r15);
+
+       pr_notice("ra: %08lx fp:  %08lx sp: %08lx gp: %08lx\n",
+               regs->ra,  regs->fp,  regs->sp,  regs->gp);
+
+       pr_notice("ea: %08lx estatus: %08lx\n",
+               regs->ea,  regs->estatus);
+}
+
+void flush_thread(void)
+{
+       set_fs(USER_DS);
+}
+
+int copy_thread(unsigned long clone_flags,
+               unsigned long usp, unsigned long arg, struct task_struct *p)
+{
+       struct pt_regs *childregs = task_pt_regs(p);
+       struct pt_regs *regs;
+       struct switch_stack *stack;
+       struct switch_stack *childstack =
+               ((struct switch_stack *)childregs) - 1;
+
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               memset(childstack, 0,
+                       sizeof(struct switch_stack) + sizeof(struct pt_regs));
+
+               childstack->r16 = usp;          /* fn */
+               childstack->r17 = arg;
+               childstack->ra = (unsigned long) ret_from_kernel_thread;
+               childregs->estatus = STATUS_PIE;
+               childregs->sp = (unsigned long) childstack;
+
+               p->thread.ksp = (unsigned long) childstack;
+               p->thread.kregs = childregs;
+               return 0;
+       }
+
+       regs = current_pt_regs();
+       *childregs = *regs;
+       childregs->r2 = 0;      /* Set the return value for the child. */
+       childregs->r7 = 0;
+
+       stack = ((struct switch_stack *) regs) - 1;
+       *childstack = *stack;
+       childstack->ra = (unsigned long)ret_from_fork;
+       p->thread.kregs = childregs;
+       p->thread.ksp = (unsigned long) childstack;
+
+       if (usp)
+               childregs->sp = usp;
+
+       /* Initialize tls register. */
+       if (clone_flags & CLONE_SETTLS)
+               childstack->r23 = regs->r8;
+
+       return 0;
+}
+
+/*
+ *     Generic dumping code. Used for panic and debug.
+ */
+void dump(struct pt_regs *fp)
+{
+       unsigned long   *sp;
+       unsigned char   *tp;
+       int             i;
+
+       pr_emerg("\nCURRENT PROCESS:\n\n");
+       pr_emerg("COMM=%s PID=%d\n", current->comm, current->pid);
+
+       if (current->mm) {
+               pr_emerg("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
+                       (int) current->mm->start_code,
+                       (int) current->mm->end_code,
+                       (int) current->mm->start_data,
+                       (int) current->mm->end_data,
+                       (int) current->mm->end_data,
+                       (int) current->mm->brk);
+               pr_emerg("USER-STACK=%08x  KERNEL-STACK=%08x\n\n",
+                       (int) current->mm->start_stack,
+                       (int)(((unsigned long) current) + THREAD_SIZE));
+       }
+
+       pr_emerg("PC: %08lx\n", fp->ea);
+       pr_emerg("SR: %08lx    SP: %08lx\n",
+               (long) fp->estatus, (long) fp);
+
+       pr_emerg("r1: %08lx    r2: %08lx    r3: %08lx\n",
+               fp->r1, fp->r2, fp->r3);
+
+       pr_emerg("r4: %08lx    r5: %08lx    r6: %08lx    r7: %08lx\n",
+               fp->r4, fp->r5, fp->r6, fp->r7);
+       pr_emerg("r8: %08lx    r9: %08lx    r10: %08lx    r11: %08lx\n",
+               fp->r8, fp->r9, fp->r10, fp->r11);
+       pr_emerg("r12: %08lx  r13: %08lx    r14: %08lx    r15: %08lx\n",
+               fp->r12, fp->r13, fp->r14, fp->r15);
+       pr_emerg("or2: %08lx   ra: %08lx     fp: %08lx    sp: %08lx\n",
+               fp->orig_r2, fp->ra, fp->fp, fp->sp);
+       pr_emerg("\nUSP: %08x   TRAPFRAME: %08x\n",
+               (unsigned int) fp->sp, (unsigned int) fp);
+
+       pr_emerg("\nCODE:");
+       tp = ((unsigned char *) fp->ea) - 0x20;
+       for (sp = (unsigned long *) tp, i = 0; (i < 0x40);  i += 4) {
+               if ((i % 0x10) == 0)
+                       pr_emerg("\n%08x: ", (int) (tp + i));
+               pr_emerg("%08x ", (int) *sp++);
+       }
+       pr_emerg("\n");
+
+       pr_emerg("\nKERNEL STACK:");
+       tp = ((unsigned char *) fp) - 0x40;
+       for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
+               if ((i % 0x10) == 0)
+                       pr_emerg("\n%08x: ", (int) (tp + i));
+               pr_emerg("%08x ", (int) *sp++);
+       }
+       pr_emerg("\n");
+       pr_emerg("\n");
+
+       pr_emerg("\nUSER STACK:");
+       tp = (unsigned char *) (fp->sp - 0x10);
+       for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
+               if ((i % 0x10) == 0)
+                       pr_emerg("\n%08x: ", (int) (tp + i));
+               pr_emerg("%08x ", (int) *sp++);
+       }
+       pr_emerg("\n\n");
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+       unsigned long fp, pc;
+       unsigned long stack_page;
+       int count = 0;
+
+       if (!p || p == current || p->state == TASK_RUNNING)
+               return 0;
+
+       stack_page = (unsigned long)p;
+       fp = ((struct switch_stack *)p->thread.ksp)->fp;        /* ;dgt2 */
+       do {
+               if (fp < stack_page+sizeof(struct task_struct) ||
+                       fp >= 8184+stack_page)  /* ;dgt2;tmp */
+                       return 0;
+               pc = ((unsigned long *)fp)[1];
+               if (!in_sched_functions(pc))
+                       return pc;
+               fp = *(unsigned long *) fp;
+       } while (count++ < 16);         /* ;dgt2;tmp */
+       return 0;
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ * Will startup in user mode (status_extension = 0).
+ */
+void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
+{
+       memset((void *) regs, 0, sizeof(struct pt_regs));
+       regs->estatus = ESTATUS_EPIE | ESTATUS_EU;
+       regs->ea = pc;
+       regs->sp = sp;
+}
+
+#include <linux/elfcore.h>
+
+/* Fill in the FPU structure for a core dump. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
+{
+       return 0; /* Nios2 has no FPU and thus no FPU registers */
+}
diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c
new file mode 100644 (file)
index 0000000..0522d33
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Device tree support
+ *
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * Based on MIPS support for CONFIG_OF device tree support
+ *
+ * Copyright (C) 2010 Cisco Systems Inc. <dediao@cisco.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/>.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bootmem.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/io.h>
+
+#include <asm/sections.h>
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+       u64 kernel_start = (u64)virt_to_phys(_text);
+
+       if (!memory_size &&
+           (kernel_start >= base) && (kernel_start < (base + size)))
+               memory_size = size;
+
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+       return alloc_bootmem_align(size, align);
+}
+
+void __init early_init_devtree(void *params)
+{
+       __be32 *dtb = (u32 *)__dtb_start;
+#if defined(CONFIG_NIOS2_DTB_AT_PHYS_ADDR)
+       if (be32_to_cpup((__be32 *)CONFIG_NIOS2_DTB_PHYS_ADDR) ==
+                OF_DT_HEADER) {
+               params = (void *)CONFIG_NIOS2_DTB_PHYS_ADDR;
+               early_init_dt_scan(params);
+               return;
+       }
+#endif
+       if (be32_to_cpu((__be32) *dtb) == OF_DT_HEADER)
+               params = (void *)__dtb_start;
+
+       early_init_dt_scan(params);
+}
diff --git a/arch/nios2/kernel/ptrace.c b/arch/nios2/kernel/ptrace.c
new file mode 100644 (file)
index 0000000..681dda9
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2014 Altera Corporation
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ *
+ * 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/elf.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/regset.h>
+#include <linux/sched.h>
+#include <linux/tracehook.h>
+#include <linux/uaccess.h>
+#include <linux/user.h>
+
+static int genregs_get(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      void *kbuf, void __user *ubuf)
+{
+       const struct pt_regs *regs = task_pt_regs(target);
+       const struct switch_stack *sw = (struct switch_stack *)regs - 1;
+       int ret = 0;
+
+#define REG_O_ZERO_RANGE(START, END)           \
+       if (!ret)                                       \
+               ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, \
+                       START * 4, (END * 4) + 4);
+
+#define REG_O_ONE(PTR, LOC)    \
+       if (!ret)                       \
+               ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
+                       LOC * 4, (LOC * 4) + 4);
+
+#define REG_O_RANGE(PTR, START, END)   \
+       if (!ret)                               \
+               ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, PTR, \
+                       START * 4, (END * 4) + 4);
+
+       REG_O_ZERO_RANGE(PTR_R0, PTR_R0);
+       REG_O_RANGE(&regs->r1, PTR_R1, PTR_R7);
+       REG_O_RANGE(&regs->r8, PTR_R8, PTR_R15);
+       REG_O_RANGE(sw, PTR_R16, PTR_R23);
+       REG_O_ZERO_RANGE(PTR_R24, PTR_R25); /* et and bt */
+       REG_O_ONE(&regs->gp, PTR_GP);
+       REG_O_ONE(&regs->sp, PTR_SP);
+       REG_O_ONE(&regs->fp, PTR_FP);
+       REG_O_ONE(&regs->ea, PTR_EA);
+       REG_O_ZERO_RANGE(PTR_BA, PTR_BA);
+       REG_O_ONE(&regs->ra, PTR_RA);
+       REG_O_ONE(&regs->ea, PTR_PC); /* use ea for PC */
+       if (!ret)
+               ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+                                        PTR_STATUS * 4, -1);
+
+       return ret;
+}
+
+/*
+ * Set the thread state from a regset passed in via ptrace
+ */
+static int genregs_set(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      const void *kbuf, const void __user *ubuf)
+{
+       struct pt_regs *regs = task_pt_regs(target);
+       const struct switch_stack *sw = (struct switch_stack *)regs - 1;
+       int ret = 0;
+
+#define REG_IGNORE_RANGE(START, END)           \
+       if (!ret)                                       \
+               ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
+                       START * 4, (END * 4) + 4);
+
+#define REG_IN_ONE(PTR, LOC)   \
+       if (!ret)                       \
+               ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
+                       (void *)(PTR), LOC * 4, (LOC * 4) + 4);
+
+#define REG_IN_RANGE(PTR, START, END)  \
+       if (!ret)                               \
+               ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
+                       (void *)(PTR), START * 4, (END * 4) + 4);
+
+       REG_IGNORE_RANGE(PTR_R0, PTR_R0);
+       REG_IN_RANGE(&regs->r1, PTR_R1, PTR_R7);
+       REG_IN_RANGE(&regs->r8, PTR_R8, PTR_R15);
+       REG_IN_RANGE(sw, PTR_R16, PTR_R23);
+       REG_IGNORE_RANGE(PTR_R24, PTR_R25); /* et and bt */
+       REG_IN_ONE(&regs->gp, PTR_GP);
+       REG_IN_ONE(&regs->sp, PTR_SP);
+       REG_IN_ONE(&regs->fp, PTR_FP);
+       REG_IN_ONE(&regs->ea, PTR_EA);
+       REG_IGNORE_RANGE(PTR_BA, PTR_BA);
+       REG_IN_ONE(&regs->ra, PTR_RA);
+       REG_IN_ONE(&regs->ea, PTR_PC); /* use ea for PC */
+       if (!ret)
+               ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                        PTR_STATUS * 4, -1);
+
+       return ret;
+}
+
+/*
+ * Define the register sets available on Nios2 under Linux
+ */
+enum nios2_regset {
+       REGSET_GENERAL,
+};
+
+static const struct user_regset nios2_regsets[] = {
+       [REGSET_GENERAL] = {
+               .core_note_type = NT_PRSTATUS,
+               .n = NUM_PTRACE_REG,
+               .size = sizeof(unsigned long),
+               .align = sizeof(unsigned long),
+               .get = genregs_get,
+               .set = genregs_set,
+       }
+};
+
+static const struct user_regset_view nios2_user_view = {
+       .name = "nios2",
+       .e_machine = ELF_ARCH,
+       .ei_osabi = ELF_OSABI,
+       .regsets = nios2_regsets,
+       .n = ARRAY_SIZE(nios2_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+       return &nios2_user_view;
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+
+}
+
+long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
+                unsigned long data)
+{
+       return ptrace_request(child, request, addr, data);
+}
+
+asmlinkage int do_syscall_trace_enter(void)
+{
+       int ret = 0;
+
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               ret = tracehook_report_syscall_entry(task_pt_regs(current));
+
+       return ret;
+}
+
+asmlinkage void do_syscall_trace_exit(void)
+{
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(task_pt_regs(current), 0);
+}
diff --git a/arch/nios2/kernel/setup.c b/arch/nios2/kernel/setup.c
new file mode 100644 (file)
index 0000000..cb3121f
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Nios2-specific parts of system setup
+ *
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ * Copyright (C) 2001 Vic Phillips <vic@microtronix.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.
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <linux/of_fdt.h>
+
+#include <asm/mmu_context.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/cpuinfo.h>
+
+unsigned long memory_start;
+EXPORT_SYMBOL(memory_start);
+
+unsigned long memory_end;
+EXPORT_SYMBOL(memory_end);
+
+unsigned long memory_size;
+
+static struct pt_regs fake_regs = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0, 0, 0, 0, 0,
+                                       0};
+
+/* Copy a short hook instruction sequence to the exception address */
+static inline void copy_exception_handler(unsigned int addr)
+{
+       unsigned int start = (unsigned int) exception_handler_hook;
+       volatile unsigned int tmp = 0;
+
+       if (start == addr) {
+               /* The CPU exception address already points to the handler. */
+               return;
+       }
+
+       __asm__ __volatile__ (
+               "ldw    %2,0(%0)\n"
+               "stw    %2,0(%1)\n"
+               "ldw    %2,4(%0)\n"
+               "stw    %2,4(%1)\n"
+               "ldw    %2,8(%0)\n"
+               "stw    %2,8(%1)\n"
+               "flushd 0(%1)\n"
+               "flushd 4(%1)\n"
+               "flushd 8(%1)\n"
+               "flushi %1\n"
+               "addi   %1,%1,4\n"
+               "flushi %1\n"
+               "addi   %1,%1,4\n"
+               "flushi %1\n"
+               "flushp\n"
+               : /* no output registers */
+               : "r" (start), "r" (addr), "r" (tmp)
+               : "memory"
+       );
+}
+
+/* Copy the fast TLB miss handler */
+static inline void copy_fast_tlb_miss_handler(unsigned int addr)
+{
+       unsigned int start = (unsigned int) fast_handler;
+       unsigned int end = (unsigned int) fast_handler_end;
+       volatile unsigned int tmp = 0;
+
+       __asm__ __volatile__ (
+               "1:\n"
+               "       ldw     %3,0(%0)\n"
+               "       stw     %3,0(%1)\n"
+               "       flushd  0(%1)\n"
+               "       flushi  %1\n"
+               "       flushp\n"
+               "       addi    %0,%0,4\n"
+               "       addi    %1,%1,4\n"
+               "       bne     %0,%2,1b\n"
+               : /* no output registers */
+               : "r" (start), "r" (addr), "r" (end), "r" (tmp)
+               : "memory"
+       );
+}
+
+/*
+ * save args passed from u-boot, called from head.S
+ *
+ * @r4: NIOS magic
+ * @r5: initrd start
+ * @r6: initrd end or fdt
+ * @r7: kernel command line
+ */
+asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6,
+                                      unsigned r7)
+{
+       unsigned dtb_passed = 0;
+       char cmdline_passed[COMMAND_LINE_SIZE] = { 0, };
+
+#if defined(CONFIG_NIOS2_PASS_CMDLINE)
+       if (r4 == 0x534f494e) { /* r4 is magic NIOS */
+#if defined(CONFIG_BLK_DEV_INITRD)
+               if (r5) { /* initramfs */
+                       initrd_start = r5;
+                       initrd_end = r6;
+               }
+#endif /* CONFIG_BLK_DEV_INITRD */
+               dtb_passed = r6;
+
+               if (r7)
+                       strncpy(cmdline_passed, (char *)r7, COMMAND_LINE_SIZE);
+       }
+#endif
+
+       early_init_devtree((void *)dtb_passed);
+
+#ifndef CONFIG_CMDLINE_FORCE
+       if (cmdline_passed[0])
+               strncpy(boot_command_line, cmdline_passed, COMMAND_LINE_SIZE);
+#ifdef CONFIG_NIOS2_CMDLINE_IGNORE_DTB
+       else
+               strncpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+#endif
+#endif
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+       int bootmap_size;
+
+       console_verbose();
+
+       memory_start = PAGE_ALIGN((unsigned long)__pa(_end));
+       memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size;
+
+       init_mm.start_code = (unsigned long) _stext;
+       init_mm.end_code = (unsigned long) _etext;
+       init_mm.end_data = (unsigned long) _edata;
+       init_mm.brk = (unsigned long) _end;
+       init_task.thread.kregs = &fake_regs;
+
+       /* Keep a copy of command line */
+       *cmdline_p = boot_command_line;
+
+       min_low_pfn = PFN_UP(memory_start);
+       max_low_pfn = PFN_DOWN(memory_end);
+       max_mapnr = max_low_pfn;
+
+       /*
+        * give all the memory to the bootmap allocator,  tell it to put the
+        * boot mem_map at the start of memory
+        */
+       pr_debug("init_bootmem_node(?,%#lx, %#x, %#lx)\n",
+               min_low_pfn, PFN_DOWN(PHYS_OFFSET), max_low_pfn);
+       bootmap_size = init_bootmem_node(NODE_DATA(0),
+                                       min_low_pfn, PFN_DOWN(PHYS_OFFSET),
+                                       max_low_pfn);
+
+       /*
+        * free the usable memory,  we have to make sure we do not free
+        * the bootmem bitmap so we then reserve it after freeing it :-)
+        */
+       pr_debug("free_bootmem(%#lx, %#lx)\n",
+               memory_start, memory_end - memory_start);
+       free_bootmem(memory_start, memory_end - memory_start);
+
+       /*
+        * Reserve the bootmem bitmap itself as well. We do this in two
+        * steps (first step was init_bootmem()) because this catches
+        * the (very unlikely) case of us accidentally initializing the
+        * bootmem allocator with an invalid RAM area.
+        *
+        * Arguments are start, size
+        */
+       pr_debug("reserve_bootmem(%#lx, %#x)\n", memory_start, bootmap_size);
+       reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start) {
+               reserve_bootmem(virt_to_phys((void *)initrd_start),
+                               initrd_end - initrd_start, BOOTMEM_DEFAULT);
+       }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+       unflatten_and_copy_device_tree();
+
+       setup_cpuinfo();
+
+       copy_exception_handler(cpuinfo.exception_addr);
+
+       mmu_init();
+
+       copy_fast_tlb_miss_handler(cpuinfo.fast_tlb_miss_exc_addr);
+
+       /*
+        * Initialize MMU context handling here because data from cpuinfo is
+        * needed for this.
+        */
+       mmu_context_init();
+
+       /*
+        * get kmalloc into gear
+        */
+       paging_init();
+
+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+       conswitchp = &dummy_con;
+#endif
+}
diff --git a/arch/nios2/kernel/signal.c b/arch/nios2/kernel/signal.c
new file mode 100644 (file)
index 0000000..f9d2788
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2013-2014 Altera Corporation
+ * Copyright (C) 2011-2012 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * 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/signal.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/uaccess.h>
+#include <linux/unistd.h>
+#include <linux/personality.h>
+#include <linux/tracehook.h>
+
+#include <asm/ucontext.h>
+#include <asm/cacheflush.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/*
+ * Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
+ */
+
+struct rt_sigframe {
+       struct siginfo info;
+       struct ucontext uc;
+};
+
+static inline int rt_restore_ucontext(struct pt_regs *regs,
+                                       struct switch_stack *sw,
+                                       struct ucontext *uc, int *pr2)
+{
+       int temp;
+       greg_t *gregs = uc->uc_mcontext.gregs;
+       int err;
+
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+       err = __get_user(temp, &uc->uc_mcontext.version);
+       if (temp != MCONTEXT_VERSION)
+               goto badframe;
+       /* restore passed registers */
+       err |= __get_user(regs->r1, &gregs[0]);
+       err |= __get_user(regs->r2, &gregs[1]);
+       err |= __get_user(regs->r3, &gregs[2]);
+       err |= __get_user(regs->r4, &gregs[3]);
+       err |= __get_user(regs->r5, &gregs[4]);
+       err |= __get_user(regs->r6, &gregs[5]);
+       err |= __get_user(regs->r7, &gregs[6]);
+       err |= __get_user(regs->r8, &gregs[7]);
+       err |= __get_user(regs->r9, &gregs[8]);
+       err |= __get_user(regs->r10, &gregs[9]);
+       err |= __get_user(regs->r11, &gregs[10]);
+       err |= __get_user(regs->r12, &gregs[11]);
+       err |= __get_user(regs->r13, &gregs[12]);
+       err |= __get_user(regs->r14, &gregs[13]);
+       err |= __get_user(regs->r15, &gregs[14]);
+       err |= __get_user(sw->r16, &gregs[15]);
+       err |= __get_user(sw->r17, &gregs[16]);
+       err |= __get_user(sw->r18, &gregs[17]);
+       err |= __get_user(sw->r19, &gregs[18]);
+       err |= __get_user(sw->r20, &gregs[19]);
+       err |= __get_user(sw->r21, &gregs[20]);
+       err |= __get_user(sw->r22, &gregs[21]);
+       err |= __get_user(sw->r23, &gregs[22]);
+       /* gregs[23] is handled below */
+       err |= __get_user(sw->fp, &gregs[24]);  /* Verify, should this be
+                                                       settable */
+       err |= __get_user(sw->gp, &gregs[25]);  /* Verify, should this be
+                                                       settable */
+
+       err |= __get_user(temp, &gregs[26]);  /* Not really necessary no user
+                                                       settable bits */
+       err |= __get_user(regs->ea, &gregs[27]);
+
+       err |= __get_user(regs->ra, &gregs[23]);
+       err |= __get_user(regs->sp, &gregs[28]);
+
+       regs->orig_r2 = -1;             /* disable syscall checks */
+
+       err |= restore_altstack(&uc->uc_stack);
+       if (err)
+               goto badframe;
+
+       *pr2 = regs->r2;
+       return err;
+
+badframe:
+       return 1;
+}
+
+asmlinkage int do_rt_sigreturn(struct switch_stack *sw)
+{
+       struct pt_regs *regs = (struct pt_regs *)(sw + 1);
+       /* Verify, can we follow the stack back */
+       struct rt_sigframe *frame = (struct rt_sigframe *) regs->sp;
+       sigset_t set;
+       int rval;
+
+       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+               goto badframe;
+
+       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+               goto badframe;
+
+       set_current_blocked(&set);
+
+       if (rt_restore_ucontext(regs, sw, &frame->uc, &rval))
+               goto badframe;
+
+       return rval;
+
+badframe:
+       force_sig(SIGSEGV, current);
+       return 0;
+}
+
+static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
+{
+       struct switch_stack *sw = (struct switch_stack *)regs - 1;
+       greg_t *gregs = uc->uc_mcontext.gregs;
+       int err = 0;
+
+       err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
+       err |= __put_user(regs->r1, &gregs[0]);
+       err |= __put_user(regs->r2, &gregs[1]);
+       err |= __put_user(regs->r3, &gregs[2]);
+       err |= __put_user(regs->r4, &gregs[3]);
+       err |= __put_user(regs->r5, &gregs[4]);
+       err |= __put_user(regs->r6, &gregs[5]);
+       err |= __put_user(regs->r7, &gregs[6]);
+       err |= __put_user(regs->r8, &gregs[7]);
+       err |= __put_user(regs->r9, &gregs[8]);
+       err |= __put_user(regs->r10, &gregs[9]);
+       err |= __put_user(regs->r11, &gregs[10]);
+       err |= __put_user(regs->r12, &gregs[11]);
+       err |= __put_user(regs->r13, &gregs[12]);
+       err |= __put_user(regs->r14, &gregs[13]);
+       err |= __put_user(regs->r15, &gregs[14]);
+       err |= __put_user(sw->r16, &gregs[15]);
+       err |= __put_user(sw->r17, &gregs[16]);
+       err |= __put_user(sw->r18, &gregs[17]);
+       err |= __put_user(sw->r19, &gregs[18]);
+       err |= __put_user(sw->r20, &gregs[19]);
+       err |= __put_user(sw->r21, &gregs[20]);
+       err |= __put_user(sw->r22, &gregs[21]);
+       err |= __put_user(sw->r23, &gregs[22]);
+       err |= __put_user(regs->ra, &gregs[23]);
+       err |= __put_user(sw->fp, &gregs[24]);
+       err |= __put_user(sw->gp, &gregs[25]);
+       err |= __put_user(regs->ea, &gregs[27]);
+       err |= __put_user(regs->sp, &gregs[28]);
+       return err;
+}
+
+static inline void *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
+                                size_t frame_size)
+{
+       unsigned long usp;
+
+       /* Default to using normal stack.  */
+       usp = regs->sp;
+
+       /* This is the X/Open sanctioned signal stack switching.  */
+       usp = sigsp(usp, ksig);
+
+       /* Verify, is it 32 or 64 bit aligned */
+       return (void *)((usp - frame_size) & -8UL);
+}
+
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+                         struct pt_regs *regs)
+{
+       struct rt_sigframe *frame;
+       int err = 0;
+
+       frame = get_sigframe(ksig, regs, sizeof(*frame));
+
+       if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+               err |= copy_siginfo_to_user(&frame->info, &ksig->info);
+
+       /* Create the ucontext.  */
+       err |= __put_user(0, &frame->uc.uc_flags);
+       err |= __put_user(0, &frame->uc.uc_link);
+       err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
+       err |= rt_setup_ucontext(&frame->uc, regs);
+       err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+       if (err)
+               goto give_sigsegv;
+
+       /* Set up to return from userspace; jump to fixed address sigreturn
+          trampoline on kuser page.  */
+       regs->ra = (unsigned long) (0x1040);
+
+       /* Set up registers for signal handler */
+       regs->sp = (unsigned long) frame;
+       regs->r4 = (unsigned long) ksig->sig;
+       regs->r5 = (unsigned long) &frame->info;
+       regs->r6 = (unsigned long) &frame->uc;
+       regs->ea = (unsigned long) ksig->ka.sa.sa_handler;
+       return 0;
+
+give_sigsegv:
+       force_sigsegv(ksig->sig, current);
+       return -EFAULT;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
+{
+       int ret;
+       sigset_t *oldset = sigmask_to_save();
+
+       /* set up the stack frame */
+       ret = setup_rt_frame(ksig, oldset, regs);
+
+       signal_setup_done(ret, ksig, 0);
+}
+
+static int do_signal(struct pt_regs *regs)
+{
+       unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
+       int restart = 0;
+       struct ksignal ksig;
+
+       current->thread.kregs = regs;
+
+       /*
+        * If we were from a system call, check for system call restarting...
+        */
+       if (regs->orig_r2 >= 0) {
+               continue_addr = regs->ea;
+               restart_addr = continue_addr - 4;
+               retval = regs->r2;
+
+               /*
+                * Prepare for system call restart. We do this here so that a
+                * debugger will see the already changed PC.
+                */
+               switch (retval) {
+               case ERESTART_RESTARTBLOCK:
+                       restart = -2;
+               case ERESTARTNOHAND:
+               case ERESTARTSYS:
+               case ERESTARTNOINTR:
+                       restart++;
+                       regs->r2 = regs->orig_r2;
+                       regs->r7 = regs->orig_r7;
+                       regs->ea = restart_addr;
+                       break;
+               }
+       }
+
+       if (get_signal(&ksig)) {
+               /* handler */
+               if (unlikely(restart && regs->ea == restart_addr)) {
+                       if (retval == ERESTARTNOHAND ||
+                           retval == ERESTART_RESTARTBLOCK ||
+                            (retval == ERESTARTSYS
+                               && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
+                               regs->r2 = EINTR;
+                               regs->r7 = 1;
+                               regs->ea = continue_addr;
+                       }
+               }
+               handle_signal(&ksig, regs);
+               return 0;
+       }
+
+       /*
+        * No handler present
+        */
+       if (unlikely(restart) && regs->ea == restart_addr) {
+               regs->ea = continue_addr;
+               regs->r2 = __NR_restart_syscall;
+       }
+
+       /*
+       * If there's no signal to deliver, we just put the saved sigmask back.
+       */
+       restore_saved_sigmask();
+
+       return restart;
+}
+
+asmlinkage int do_notify_resume(struct pt_regs *regs)
+{
+       /*
+        * We want the common case to go fast, which is why we may in certain
+        * cases get here from kernel mode. Just return without doing anything
+        * if so.
+        */
+       if (!user_mode(regs))
+               return 0;
+
+       if (test_thread_flag(TIF_SIGPENDING)) {
+               int restart = do_signal(regs);
+
+               if (unlikely(restart)) {
+                       /*
+                        * Restart without handlers.
+                        * Deal with it without leaving
+                        * the kernel space.
+                        */
+                       return restart;
+               }
+       } else if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME))
+               tracehook_notify_resume(regs);
+
+       return 0;
+}
diff --git a/arch/nios2/kernel/sys_nios2.c b/arch/nios2/kernel/sys_nios2.c
new file mode 100644 (file)
index 0000000..cd390ec
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2011-2012 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
+
+/* sys_cacheflush -- flush the processor cache. */
+asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len,
+                               unsigned int op)
+{
+       struct vm_area_struct *vma;
+
+       if (len == 0)
+               return 0;
+
+       /* We only support op 0 now, return error if op is non-zero.*/
+       if (op)
+               return -EINVAL;
+
+       /* Check for overflow */
+       if (addr + len < addr)
+               return -EFAULT;
+
+       /*
+        * Verify that the specified address region actually belongs
+        * to this process.
+        */
+       vma = find_vma(current->mm, addr);
+       if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+               return -EFAULT;
+
+       flush_cache_range(vma, addr, addr + len);
+
+       return 0;
+}
+
+asmlinkage int sys_getpagesize(void)
+{
+       return PAGE_SIZE;
+}
diff --git a/arch/nios2/kernel/syscall_table.c b/arch/nios2/kernel/syscall_table.c
new file mode 100644 (file)
index 0000000..06e6ac1
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright Altera Corporation (C) 2013. 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/>.
+ *
+ */
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
diff --git a/arch/nios2/kernel/time.c b/arch/nios2/kernel/time.c
new file mode 100644 (file)
index 0000000..7f45474
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2013-2014 Altera Corporation
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define ALTERA_TIMER_STATUS_REG                0
+#define ALTERA_TIMER_CONTROL_REG       4
+#define ALTERA_TIMER_PERIODL_REG       8
+#define ALTERA_TIMER_PERIODH_REG       12
+#define ALTERA_TIMER_SNAPL_REG         16
+#define ALTERA_TIMER_SNAPH_REG         20
+
+#define ALTERA_TIMER_CONTROL_ITO_MSK   (0x1)
+#define ALTERA_TIMER_CONTROL_CONT_MSK  (0x2)
+#define ALTERA_TIMER_CONTROL_START_MSK (0x4)
+#define ALTERA_TIMER_CONTROL_STOP_MSK  (0x8)
+
+struct nios2_timer {
+       void __iomem *base;
+       unsigned long freq;
+};
+
+struct nios2_clockevent_dev {
+       struct nios2_timer timer;
+       struct clock_event_device ced;
+};
+
+struct nios2_clocksource {
+       struct nios2_timer timer;
+       struct clocksource cs;
+};
+
+static inline struct nios2_clockevent_dev *
+       to_nios2_clkevent(struct clock_event_device *evt)
+{
+       return container_of(evt, struct nios2_clockevent_dev, ced);
+}
+
+static inline struct nios2_clocksource *
+       to_nios2_clksource(struct clocksource *cs)
+{
+       return container_of(cs, struct nios2_clocksource, cs);
+}
+
+static u16 timer_readw(struct nios2_timer *timer, u32 offs)
+{
+       return readw(timer->base + offs);
+}
+
+static void timer_writew(struct nios2_timer *timer, u16 val, u32 offs)
+{
+       writew(val, timer->base + offs);
+}
+
+static inline unsigned long read_timersnapshot(struct nios2_timer *timer)
+{
+       unsigned long count;
+
+       timer_writew(timer, 0, ALTERA_TIMER_SNAPL_REG);
+       count = timer_readw(timer, ALTERA_TIMER_SNAPH_REG) << 16 |
+               timer_readw(timer, ALTERA_TIMER_SNAPL_REG);
+
+       return count;
+}
+
+static cycle_t nios2_timer_read(struct clocksource *cs)
+{
+       struct nios2_clocksource *nios2_cs = to_nios2_clksource(cs);
+       unsigned long flags;
+       u32 count;
+
+       local_irq_save(flags);
+       count = read_timersnapshot(&nios2_cs->timer);
+       local_irq_restore(flags);
+
+       /* Counter is counting down */
+       return ~count;
+}
+
+static struct nios2_clocksource nios2_cs = {
+       .cs = {
+               .name   = "nios2-clksrc",
+               .rating = 250,
+               .read   = nios2_timer_read,
+               .mask   = CLOCKSOURCE_MASK(32),
+               .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+       },
+};
+
+cycles_t get_cycles(void)
+{
+       return nios2_timer_read(&nios2_cs.cs);
+}
+
+static void nios2_timer_start(struct nios2_timer *timer)
+{
+       u16 ctrl;
+
+       ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
+       ctrl |= ALTERA_TIMER_CONTROL_START_MSK;
+       timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
+}
+
+static void nios2_timer_stop(struct nios2_timer *timer)
+{
+       u16 ctrl;
+
+       ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
+       ctrl |= ALTERA_TIMER_CONTROL_STOP_MSK;
+       timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
+}
+
+static void nios2_timer_config(struct nios2_timer *timer, unsigned long period,
+       enum clock_event_mode mode)
+{
+       u16 ctrl;
+
+       /* The timer's actual period is one cycle greater than the value
+        * stored in the period register. */
+        period--;
+
+       ctrl = timer_readw(timer, ALTERA_TIMER_CONTROL_REG);
+       /* stop counter */
+       timer_writew(timer, ctrl | ALTERA_TIMER_CONTROL_STOP_MSK,
+               ALTERA_TIMER_CONTROL_REG);
+
+       /* write new count */
+       timer_writew(timer, period, ALTERA_TIMER_PERIODL_REG);
+       timer_writew(timer, period >> 16, ALTERA_TIMER_PERIODH_REG);
+
+       ctrl |= ALTERA_TIMER_CONTROL_START_MSK | ALTERA_TIMER_CONTROL_ITO_MSK;
+       if (mode == CLOCK_EVT_MODE_PERIODIC)
+               ctrl |= ALTERA_TIMER_CONTROL_CONT_MSK;
+       else
+               ctrl &= ~ALTERA_TIMER_CONTROL_CONT_MSK;
+       timer_writew(timer, ctrl, ALTERA_TIMER_CONTROL_REG);
+}
+
+static int nios2_timer_set_next_event(unsigned long delta,
+       struct clock_event_device *evt)
+{
+       struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
+
+       nios2_timer_config(&nios2_ced->timer, delta, evt->mode);
+
+       return 0;
+}
+
+static void nios2_timer_set_mode(enum clock_event_mode mode,
+       struct clock_event_device *evt)
+{
+       unsigned long period;
+       struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
+       struct nios2_timer *timer = &nios2_ced->timer;
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               period = DIV_ROUND_UP(timer->freq, HZ);
+               nios2_timer_config(timer, period, CLOCK_EVT_MODE_PERIODIC);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               nios2_timer_stop(timer);
+               break;
+       case CLOCK_EVT_MODE_RESUME:
+               nios2_timer_start(timer);
+               break;
+       }
+}
+
+irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = (struct clock_event_device *) dev_id;
+       struct nios2_clockevent_dev *nios2_ced = to_nios2_clkevent(evt);
+
+       /* Clear the interrupt condition */
+       timer_writew(&nios2_ced->timer, 0, ALTERA_TIMER_STATUS_REG);
+       evt->event_handler(evt);
+
+       return IRQ_HANDLED;
+}
+
+static void __init nios2_timer_get_base_and_freq(struct device_node *np,
+                               void __iomem **base, u32 *freq)
+{
+       *base = of_iomap(np, 0);
+       if (!*base)
+               panic("Unable to map reg for %s\n", np->name);
+
+       if (of_property_read_u32(np, "clock-frequency", freq))
+               panic("Unable to get %s clock frequency\n", np->name);
+}
+
+static struct nios2_clockevent_dev nios2_ce = {
+       .ced = {
+               .name = "nios2-clkevent",
+               .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+               .rating = 250,
+               .shift = 32,
+               .set_next_event = nios2_timer_set_next_event,
+               .set_mode = nios2_timer_set_mode,
+       },
+};
+
+static __init void nios2_clockevent_init(struct device_node *timer)
+{
+       void __iomem *iobase;
+       u32 freq;
+       int irq;
+
+       nios2_timer_get_base_and_freq(timer, &iobase, &freq);
+
+       irq = irq_of_parse_and_map(timer, 0);
+       if (!irq)
+               panic("Unable to parse timer irq\n");
+
+       nios2_ce.timer.base = iobase;
+       nios2_ce.timer.freq = freq;
+
+       nios2_ce.ced.cpumask = cpumask_of(0);
+       nios2_ce.ced.irq = irq;
+
+       nios2_timer_stop(&nios2_ce.timer);
+       /* clear pending interrupt */
+       timer_writew(&nios2_ce.timer, 0, ALTERA_TIMER_STATUS_REG);
+
+       if (request_irq(irq, timer_interrupt, IRQF_TIMER, timer->name,
+               &nios2_ce.ced))
+               panic("Unable to setup timer irq\n");
+
+       clockevents_config_and_register(&nios2_ce.ced, freq, 1, ULONG_MAX);
+}
+
+static __init void nios2_clocksource_init(struct device_node *timer)
+{
+       unsigned int ctrl;
+       void __iomem *iobase;
+       u32 freq;
+
+       nios2_timer_get_base_and_freq(timer, &iobase, &freq);
+
+       nios2_cs.timer.base = iobase;
+       nios2_cs.timer.freq = freq;
+
+       clocksource_register_hz(&nios2_cs.cs, freq);
+
+       timer_writew(&nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODL_REG);
+       timer_writew(&nios2_cs.timer, USHRT_MAX, ALTERA_TIMER_PERIODH_REG);
+
+       /* interrupt disable + continuous + start */
+       ctrl = ALTERA_TIMER_CONTROL_CONT_MSK | ALTERA_TIMER_CONTROL_START_MSK;
+       timer_writew(&nios2_cs.timer, ctrl, ALTERA_TIMER_CONTROL_REG);
+
+       /* Calibrate the delay loop directly */
+       lpj_fine = freq / HZ;
+}
+
+/*
+ * The first timer instance will use as a clockevent. If there are two or
+ * more instances, the second one gets used as clocksource and all
+ * others are unused.
+*/
+static void __init nios2_time_init(struct device_node *timer)
+{
+       static int num_called;
+
+       switch (num_called) {
+       case 0:
+               nios2_clockevent_init(timer);
+               break;
+       case 1:
+               nios2_clocksource_init(timer);
+               break;
+       default:
+               break;
+       }
+
+       num_called++;
+}
+
+void read_persistent_clock(struct timespec *ts)
+{
+       ts->tv_sec = mktime(2007, 1, 1, 0, 0, 0);
+       ts->tv_nsec = 0;
+}
+
+void __init time_init(void)
+{
+       clocksource_of_init();
+}
+
+CLOCKSOURCE_OF_DECLARE(nios2_timer, "altr,timer-1.0", nios2_time_init);
diff --git a/arch/nios2/kernel/traps.c b/arch/nios2/kernel/traps.c
new file mode 100644 (file)
index 0000000..b7b9764
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Hardware exception handling
+ *
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ * Copyright (C) 2001 Vic Phillips
+ *
+ * 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/sched.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+
+#include <asm/traps.h>
+#include <asm/sections.h>
+#include <asm/uaccess.h>
+
+static DEFINE_SPINLOCK(die_lock);
+
+void die(const char *str, struct pt_regs *regs, long err)
+{
+       console_verbose();
+       spin_lock_irq(&die_lock);
+       pr_warn("Oops: %s, sig: %ld\n", str, err);
+       show_regs(regs);
+       spin_unlock_irq(&die_lock);
+       /*
+        * do_exit() should take care of panic'ing from an interrupt
+        * context so we don't handle it here
+        */
+       do_exit(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);
+}
+
+/*
+ * The show_stack is an external API which we do not use ourselves.
+ */
+
+int kstack_depth_to_print = 48;
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+       unsigned long *endstack, addr;
+       int i;
+
+       if (!stack) {
+               if (task)
+                       stack = (unsigned long *)task->thread.ksp;
+               else
+                       stack = (unsigned long *)&stack;
+       }
+
+       addr = (unsigned long) stack;
+       endstack = (unsigned long *) PAGE_ALIGN(addr);
+
+       pr_emerg("Stack from %08lx:", (unsigned long)stack);
+       for (i = 0; i < kstack_depth_to_print; i++) {
+               if (stack + 1 > endstack)
+                       break;
+               if (i % 8 == 0)
+                       pr_emerg("\n       ");
+               pr_emerg(" %08lx", *stack++);
+       }
+
+       pr_emerg("\nCall Trace:");
+       i = 0;
+       while (stack + 1 <= endstack) {
+               addr = *stack++;
+               /*
+                * If the address is either in the text segment of the
+                * kernel, or in the region which contains vmalloc'ed
+                * memory, it *may* be the address of a calling
+                * routine; if so, print it so that someone tracing
+                * down the cause of the crash will be able to figure
+                * out the call path that was taken.
+                */
+               if (((addr >= (unsigned long) _stext) &&
+                    (addr <= (unsigned long) _etext))) {
+                       if (i % 4 == 0)
+                               pr_emerg("\n       ");
+                       pr_emerg(" [<%08lx>]", addr);
+                       i++;
+               }
+       }
+       pr_emerg("\n");
+}
+
+void __init trap_init(void)
+{
+       /* Nothing to do here */
+}
+
+/* Breakpoint handler */
+asmlinkage void breakpoint_c(struct pt_regs *fp)
+{
+       /*
+        * The breakpoint entry code has moved the PC on by 4 bytes, so we must
+        * move it back. This could be done on the host but we do it here
+        * because monitor.S of JTAG gdbserver does it too.
+        */
+       fp->ea -= 4;
+       _exception(SIGTRAP, fp, TRAP_BRKPT, fp->ea);
+}
+
+#ifndef CONFIG_NIOS2_ALIGNMENT_TRAP
+/* Alignment exception handler */
+asmlinkage void handle_unaligned_c(struct pt_regs *fp, int cause)
+{
+       unsigned long addr = RDCTL(CTL_BADADDR);
+
+       cause >>= 2;
+       fp->ea -= 4;
+
+       if (fixup_exception(fp))
+               return;
+
+       if (!user_mode(fp)) {
+               pr_alert("Unaligned access from kernel mode, this might be a hardware\n");
+               pr_alert("problem, dump registers and restart the instruction\n");
+               pr_alert("  BADADDR 0x%08lx\n", addr);
+               pr_alert("  cause   %d\n", cause);
+               pr_alert("  op-code 0x%08lx\n", *(unsigned long *)(fp->ea));
+               show_regs(fp);
+               return;
+       }
+
+       _exception(SIGBUS, fp, BUS_ADRALN, addr);
+}
+#endif /* CONFIG_NIOS2_ALIGNMENT_TRAP */
+
+/* Illegal instruction handler */
+asmlinkage void handle_illegal_c(struct pt_regs *fp)
+{
+       fp->ea -= 4;
+       _exception(SIGILL, fp, ILL_ILLOPC, fp->ea);
+}
+
+/* Supervisor instruction handler */
+asmlinkage void handle_supervisor_instr(struct pt_regs *fp)
+{
+       fp->ea -= 4;
+       _exception(SIGILL, fp, ILL_PRVOPC, fp->ea);
+}
+
+/* Division error handler */
+asmlinkage void handle_diverror_c(struct pt_regs *fp)
+{
+       fp->ea -= 4;
+       _exception(SIGFPE, fp, FPE_INTDIV, fp->ea);
+}
+
+/* Unhandled exception handler */
+asmlinkage void unhandled_exception(struct pt_regs *regs, int cause)
+{
+       unsigned long addr = RDCTL(CTL_BADADDR);
+
+       cause /= 4;
+
+       pr_emerg("Unhandled exception #%d in %s mode (badaddr=0x%08lx)\n",
+                       cause, user_mode(regs) ? "user" : "kernel", addr);
+
+       regs->ea -= 4;
+       show_regs(regs);
+
+       pr_emerg("opcode: 0x%08lx\n", *(unsigned long *)(regs->ea));
+}
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
new file mode 100644 (file)
index 0000000..326fab4
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 <asm/page.h>
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
+
+OUTPUT_FORMAT("elf32-littlenios2", "elf32-littlenios2", "elf32-littlenios2")
+
+OUTPUT_ARCH(nios)
+ENTRY(_start)  /* Defined in head.S */
+
+jiffies = jiffies_64;
+
+SECTIONS
+{
+       . = CONFIG_NIOS2_MEM_BASE | CONFIG_NIOS2_KERNEL_REGION_BASE;
+
+       _text = .;
+       _stext = .;
+       HEAD_TEXT_SECTION
+       .text : {
+               TEXT_TEXT
+               SCHED_TEXT
+               LOCK_TEXT
+               IRQENTRY_TEXT
+               KPROBES_TEXT
+       } =0
+       _etext = .;
+
+       .got : {
+               *(.got.plt)
+               *(.igot.plt)
+               *(.got)
+               *(.igot)
+       }
+
+       EXCEPTION_TABLE(L1_CACHE_BYTES)
+
+       . = ALIGN(PAGE_SIZE);
+       __init_begin = .;
+       INIT_TEXT_SECTION(PAGE_SIZE)
+       INIT_DATA_SECTION(PAGE_SIZE)
+       PERCPU_SECTION(L1_CACHE_BYTES)
+       __init_end = .;
+
+       _sdata = .;
+       RO_DATA_SECTION(PAGE_SIZE)
+       RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+       _edata = .;
+
+       BSS_SECTION(0, 0, 0)
+       _end = .;
+
+       STABS_DEBUG
+       DWARF_DEBUG
+       NOTES
+
+       DISCARDS
+}
diff --git a/arch/nios2/lib/Makefile b/arch/nios2/lib/Makefile
new file mode 100644 (file)
index 0000000..5572566
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for Nios2-specific library files.
+#
+
+lib-y += delay.o
+lib-y += memcpy.o
+lib-y += memmove.o
+lib-y += memset.o
diff --git a/arch/nios2/lib/delay.c b/arch/nios2/lib/delay.c
new file mode 100644 (file)
index 0000000..088119c
--- /dev/null
@@ -0,0 +1,52 @@
+/* Copyright Altera Corporation (C) 2014. 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/module.h>
+#include <asm/delay.h>
+#include <asm/param.h>
+#include <asm/processor.h>
+#include <asm/timex.h>
+
+void __delay(unsigned long cycles)
+{
+       cycles_t start = get_cycles();
+
+       while ((get_cycles() - start) < cycles)
+               cpu_relax();
+}
+EXPORT_SYMBOL(__delay);
+
+void __const_udelay(unsigned long xloops)
+{
+       u64 loops;
+
+       loops = (u64)xloops * loops_per_jiffy * HZ;
+
+       __delay(loops >> 32);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+       __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+       __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/nios2/lib/memcpy.c b/arch/nios2/lib/memcpy.c
new file mode 100644 (file)
index 0000000..1715f5d
--- /dev/null
@@ -0,0 +1,202 @@
+/* Extracted from GLIBC memcpy.c and memcopy.h, which is:
+   Copyright (C) 1991, 1992, 1993, 1997, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <linux/types.h>
+
+/* Type to use for aligned memory operations.
+   This should normally be the biggest type supported by a single load
+   and store.  */
+#define        op_t    unsigned long int
+#define OPSIZ  (sizeof(op_t))
+
+/* Optimal type for storing bytes in registers.  */
+#define        reg_char        char
+
+#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
+
+/* Copy exactly NBYTES bytes from SRC_BP to DST_BP,
+   without any assumptions about alignment of the pointers.  */
+#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes)                          \
+do {                                                                   \
+       size_t __nbytes = (nbytes);                                     \
+       while (__nbytes > 0) {                                          \
+               unsigned char __x = ((unsigned char *) src_bp)[0];      \
+               src_bp += 1;                                            \
+               __nbytes -= 1;                                          \
+               ((unsigned char *) dst_bp)[0] = __x;                    \
+               dst_bp += 1;                                            \
+       }                                                               \
+} while (0)
+
+/* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with
+   the assumption that DST_BP is aligned on an OPSIZ multiple.  If
+   not all bytes could be easily copied, store remaining number of bytes
+   in NBYTES_LEFT, otherwise store 0.  */
+/* extern void _wordcopy_fwd_aligned __P ((long int, long int, size_t)); */
+/* extern void _wordcopy_fwd_dest_aligned __P ((long int, long int, size_t)); */
+#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes)             \
+do {                                                                   \
+       if (src_bp % OPSIZ == 0)                                        \
+               _wordcopy_fwd_aligned(dst_bp, src_bp, (nbytes) / OPSIZ);\
+       else                                                            \
+               _wordcopy_fwd_dest_aligned(dst_bp, src_bp, (nbytes) / OPSIZ);\
+       src_bp += (nbytes) & -OPSIZ;                                    \
+       dst_bp += (nbytes) & -OPSIZ;                                    \
+       (nbytes_left) = (nbytes) % OPSIZ;                               \
+} while (0)
+
+
+/* Threshold value for when to enter the unrolled loops.  */
+#define        OP_T_THRES      16
+
+/* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to
+   block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
+   Both SRCP and DSTP should be aligned for memory operations on `op_t's.  */
+/* stream-lined (read x8 + write x8) */
+static void _wordcopy_fwd_aligned(long int dstp, long int srcp, size_t len)
+{
+       while (len > 7) {
+               register op_t a0, a1, a2, a3, a4, a5, a6, a7;
+
+               a0 = ((op_t *) srcp)[0];
+               a1 = ((op_t *) srcp)[1];
+               a2 = ((op_t *) srcp)[2];
+               a3 = ((op_t *) srcp)[3];
+               a4 = ((op_t *) srcp)[4];
+               a5 = ((op_t *) srcp)[5];
+               a6 = ((op_t *) srcp)[6];
+               a7 = ((op_t *) srcp)[7];
+               ((op_t *) dstp)[0] = a0;
+               ((op_t *) dstp)[1] = a1;
+               ((op_t *) dstp)[2] = a2;
+               ((op_t *) dstp)[3] = a3;
+               ((op_t *) dstp)[4] = a4;
+               ((op_t *) dstp)[5] = a5;
+               ((op_t *) dstp)[6] = a6;
+               ((op_t *) dstp)[7] = a7;
+
+               srcp += 8 * OPSIZ;
+               dstp += 8 * OPSIZ;
+               len -= 8;
+       }
+       while (len > 0) {
+               *(op_t *)dstp = *(op_t *)srcp;
+
+               srcp += OPSIZ;
+               dstp += OPSIZ;
+               len -= 1;
+       }
+}
+
+/* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to
+   block beginning at DSTP with LEN `op_t' words (not LEN bytes!).
+   DSTP should be aligned for memory operations on `op_t's, but SRCP must
+   *not* be aligned.  */
+/* stream-lined (read x4 + write x4) */
+static void _wordcopy_fwd_dest_aligned(long int dstp, long int srcp,
+                                       size_t len)
+{
+       op_t ap;
+       int sh_1, sh_2;
+
+       /* Calculate how to shift a word read at the memory operation
+       aligned srcp to make it aligned for copy. */
+
+       sh_1 = 8 * (srcp % OPSIZ);
+       sh_2 = 8 * OPSIZ - sh_1;
+
+       /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
+       it points in the middle of. */
+       srcp &= -OPSIZ;
+       ap = ((op_t *) srcp)[0];
+       srcp += OPSIZ;
+
+       while (len > 3) {
+               op_t a0, a1, a2, a3;
+
+               a0 = ((op_t *) srcp)[0];
+               a1 = ((op_t *) srcp)[1];
+               a2 = ((op_t *) srcp)[2];
+               a3 = ((op_t *) srcp)[3];
+               ((op_t *) dstp)[0] = MERGE(ap, sh_1, a0, sh_2);
+               ((op_t *) dstp)[1] = MERGE(a0, sh_1, a1, sh_2);
+               ((op_t *) dstp)[2] = MERGE(a1, sh_1, a2, sh_2);
+               ((op_t *) dstp)[3] = MERGE(a2, sh_1, a3, sh_2);
+
+               ap = a3;
+               srcp += 4 * OPSIZ;
+               dstp += 4 * OPSIZ;
+               len -= 4;
+       }
+       while (len > 0) {
+               register op_t a0;
+
+               a0 = ((op_t *) srcp)[0];
+               ((op_t *) dstp)[0] = MERGE(ap, sh_1, a0, sh_2);
+
+               ap = a0;
+               srcp += OPSIZ;
+               dstp += OPSIZ;
+               len -= 1;
+       }
+}
+
+void *memcpy(void *dstpp, const void *srcpp, size_t len)
+{
+       unsigned long int dstp = (long int) dstpp;
+       unsigned long int srcp = (long int) srcpp;
+
+       /* Copy from the beginning to the end.  */
+
+       /* If there not too few bytes to copy, use word copy.  */
+       if (len >= OP_T_THRES) {
+               /* Copy just a few bytes to make DSTP aligned.  */
+               len -= (-dstp) % OPSIZ;
+               BYTE_COPY_FWD(dstp, srcp, (-dstp) % OPSIZ);
+
+               /* Copy whole pages from SRCP to DSTP by virtual address
+                  manipulation, as much as possible.  */
+
+               /* PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); */
+
+               /* Copy from SRCP to DSTP taking advantage of the known
+                  alignment of DSTP. Number of bytes remaining is put in the
+                  third argument, i.e. in LEN.  This number may vary from
+                  machine to machine. */
+
+               WORD_COPY_FWD(dstp, srcp, len, len);
+
+               /* Fall out and copy the tail. */
+       }
+
+       /* There are just a few bytes to copy.  Use byte memory operations. */
+       BYTE_COPY_FWD(dstp, srcp, len);
+
+       return dstpp;
+}
+
+void *memcpyb(void *dstpp, const void *srcpp, unsigned len)
+{
+       unsigned long int dstp = (long int) dstpp;
+       unsigned long int srcp = (long int) srcpp;
+
+       BYTE_COPY_FWD(dstp, srcp, len);
+
+       return dstpp;
+}
diff --git a/arch/nios2/lib/memmove.c b/arch/nios2/lib/memmove.c
new file mode 100644 (file)
index 0000000..c65ef51
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * 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/types.h>
+#include <linux/string.h>
+
+#ifdef __HAVE_ARCH_MEMMOVE
+void *memmove(void *d, const void *s, size_t count)
+{
+       unsigned long dst, src;
+
+       if (!count)
+               return d;
+
+       if (d < s) {
+               dst = (unsigned long) d;
+               src = (unsigned long) s;
+
+               if ((count < 8) || ((dst ^ src) & 3))
+                       goto restup;
+
+               if (dst & 1) {
+                       *(char *)dst++ = *(char *)src++;
+                       count--;
+               }
+               if (dst & 2) {
+                       *(short *)dst = *(short *)src;
+                       src += 2;
+                       dst += 2;
+                       count -= 2;
+               }
+               while (count > 3) {
+                       *(long *)dst = *(long *)src;
+                       src += 4;
+                       dst += 4;
+                       count -= 4;
+               }
+restup:
+               while (count--)
+                       *(char *)dst++ = *(char *)src++;
+       } else {
+               dst = (unsigned long) d + count;
+               src = (unsigned long) s + count;
+
+               if ((count < 8) || ((dst ^ src) & 3))
+                       goto restdown;
+
+               if (dst & 1) {
+                       src--;
+                       dst--;
+                       count--;
+                       *(char *)dst = *(char *)src;
+               }
+               if (dst & 2) {
+                       src -= 2;
+                       dst -= 2;
+                       count -= 2;
+                       *(short *)dst = *(short *)src;
+               }
+               while (count > 3) {
+                       src -= 4;
+                       dst -= 4;
+                       count -= 4;
+                       *(long *)dst = *(long *)src;
+               }
+restdown:
+               while (count--) {
+                       src--;
+                       dst--;
+                       *(char *)dst = *(char *)src;
+               }
+       }
+
+       return d;
+}
+#endif /* __HAVE_ARCH_MEMMOVE */
diff --git a/arch/nios2/lib/memset.c b/arch/nios2/lib/memset.c
new file mode 100644 (file)
index 0000000..65e9780
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * 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/types.h>
+#include <linux/string.h>
+
+#ifdef __HAVE_ARCH_MEMSET
+void *memset(void *s, int c, size_t count)
+{
+       int destptr, charcnt, dwordcnt, fill8reg, wrkrega;
+
+       if (!count)
+               return s;
+
+       c &= 0xFF;
+
+       if (count <= 8) {
+               char *xs = (char *) s;
+
+               while (count--)
+                       *xs++ = c;
+               return s;
+       }
+
+       __asm__ __volatile__ (
+               /* fill8 %3, %5 (c & 0xff) */
+               "       slli    %4, %5, 8\n"
+               "       or      %4, %4, %5\n"
+               "       slli    %3, %4, 16\n"
+               "       or      %3, %3, %4\n"
+               /* Word-align %0 (s) if necessary */
+               "       andi    %4, %0, 0x01\n"
+               "       beq     %4, zero, 1f\n"
+               "       addi    %1, %1, -1\n"
+               "       stb     %3, 0(%0)\n"
+               "       addi    %0, %0, 1\n"
+               "1:     mov     %2, %1\n"
+               /* Dword-align %0 (s) if necessary */
+               "       andi    %4, %0, 0x02\n"
+               "       beq     %4, zero, 2f\n"
+               "       addi    %1, %1, -2\n"
+               "       sth     %3, 0(%0)\n"
+               "       addi    %0, %0, 2\n"
+               "       mov     %2, %1\n"
+               /* %1 and %2 are how many more bytes to set */
+               "2:     srli    %2, %2, 2\n"
+               /* %2 is how many dwords to set */
+               "3:     stw     %3, 0(%0)\n"
+               "       addi    %0, %0, 4\n"
+               "       addi    %2, %2, -1\n"
+               "       bne     %2, zero, 3b\n"
+               /* store residual word and/or byte if necessary */
+               "       andi    %4, %1, 0x02\n"
+               "       beq     %4, zero, 4f\n"
+               "       sth     %3, 0(%0)\n"
+               "       addi    %0, %0, 2\n"
+               /* store residual byte if necessary */
+               "4:     andi    %4, %1, 0x01\n"
+               "       beq     %4, zero, 5f\n"
+               "       stb     %3, 0(%0)\n"
+               "5:\n"
+               : "=r" (destptr),       /* %0  Output */
+                 "=r" (charcnt),       /* %1  Output */
+                 "=r" (dwordcnt),      /* %2  Output */
+                 "=r" (fill8reg),      /* %3  Output */
+                 "=r" (wrkrega)        /* %4  Output */
+               : "r" (c),              /* %5  Input */
+                 "0" (s),              /* %0  Input/Output */
+                 "1" (count)           /* %1  Input/Output */
+               : "memory"              /* clobbered */
+       );
+
+       return s;
+}
+#endif /* __HAVE_ARCH_MEMSET */
diff --git a/arch/nios2/mm/Makefile b/arch/nios2/mm/Makefile
new file mode 100644 (file)
index 0000000..3cbd084
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for the Nios2-specific parts of the memory manager.
+#
+
+obj-y  += cacheflush.o
+obj-y  += dma-mapping.o
+obj-y  += extable.o
+obj-y  += fault.o
+obj-y  += init.o
+obj-y  += ioremap.o
+obj-y  += mmu_context.o
+obj-y  += pgtable.o
+obj-y  += tlb.o
+obj-y  += uaccess.o
diff --git a/arch/nios2/mm/cacheflush.c b/arch/nios2/mm/cacheflush.c
new file mode 100644 (file)
index 0000000..2ae482b
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009, Wind River Systems Inc
+ * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ */
+
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cpuinfo.h>
+
+static void __flush_dcache(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(cpuinfo.dcache_line_size - 1);
+       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__ ("   flushda 0(%0)\n"
+                                       : /* Outputs */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+}
+
+static void __flush_dcache_all(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(cpuinfo.dcache_line_size - 1);
+       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__ ("   flushd 0(%0)\n"
+                                       : /* Outputs */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+}
+
+static void __invalidate_dcache(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(cpuinfo.dcache_line_size - 1);
+       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 */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+}
+
+static void __flush_icache(unsigned long start, unsigned long end)
+{
+       unsigned long addr;
+
+       start &= ~(cpuinfo.icache_line_size - 1);
+       end += (cpuinfo.icache_line_size - 1);
+       end &= ~(cpuinfo.icache_line_size - 1);
+
+       if (end > start + cpuinfo.icache_size)
+               end = start + cpuinfo.icache_size;
+
+       for (addr = start; addr < end; addr += cpuinfo.icache_line_size) {
+               __asm__ __volatile__ ("   flushi %0\n"
+                                       : /* Outputs */
+                                       : /* Inputs  */ "r"(addr)
+                                       /* : No clobber */);
+       }
+       __asm__ __volatile(" flushp\n");
+}
+
+static void flush_aliases(struct address_space *mapping, struct page *page)
+{
+       struct mm_struct *mm = current->active_mm;
+       struct vm_area_struct *mpnt;
+       pgoff_t pgoff;
+
+       pgoff = page->index;
+
+       flush_dcache_mmap_lock(mapping);
+       vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
+               unsigned long offset;
+
+               if (mpnt->vm_mm != mm)
+                       continue;
+               if (!(mpnt->vm_flags & VM_MAYSHARE))
+                       continue;
+
+               offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
+               flush_cache_page(mpnt, mpnt->vm_start + offset,
+                       page_to_pfn(page));
+       }
+       flush_dcache_mmap_unlock(mapping);
+}
+
+void flush_cache_all(void)
+{
+       __flush_dcache_all(0, cpuinfo.dcache_size);
+       __flush_icache(0, cpuinfo.icache_size);
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+       flush_cache_all();
+}
+
+void flush_cache_dup_mm(struct mm_struct *mm)
+{
+       flush_cache_all();
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+       __flush_icache(start, end);
+}
+
+void flush_dcache_range(unsigned long start, unsigned long end)
+{
+       __flush_dcache(start, end);
+}
+EXPORT_SYMBOL(flush_dcache_range);
+
+void invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+       __invalidate_dcache(start, end);
+}
+EXPORT_SYMBOL(invalidate_dcache_range);
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                       unsigned long end)
+{
+       __flush_dcache(start, end);
+       if (vma == NULL || (vma->vm_flags & VM_EXEC))
+               __flush_icache(start, end);
+}
+
+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_icache(start, end);
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
+                       unsigned long pfn)
+{
+       unsigned long start = vmaddr;
+       unsigned long end = start + PAGE_SIZE;
+
+       __flush_dcache(start, end);
+       if (vma->vm_flags & VM_EXEC)
+               __flush_icache(start, end);
+}
+
+void flush_dcache_page(struct page *page)
+{
+       struct address_space *mapping;
+
+       /*
+        * The zero page is never written to, so never has any dirty
+        * cache lines, and therefore never needs to be flushed.
+        */
+       if (page == ZERO_PAGE(0))
+               return;
+
+       mapping = page_mapping(page);
+
+       /* Flush this page if there are aliases. */
+       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_aliases(mapping,  page);
+               set_bit(PG_dcache_clean, &page->flags);
+       }
+}
+EXPORT_SYMBOL(flush_dcache_page);
+
+void update_mmu_cache(struct vm_area_struct *vma,
+                     unsigned long address, pte_t *pte)
+{
+       unsigned long pfn = pte_pfn(*pte);
+       struct page *page;
+
+       if (!pfn_valid(pfn))
+               return;
+
+       /*
+       * The zero page is never written to, so never has any dirty
+       * cache lines, and therefore never needs to be flushed.
+       */
+       page = pfn_to_page(pfn);
+       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);
+       }
+}
+
+void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
+                   struct page *to)
+{
+       __flush_dcache(vaddr, vaddr + PAGE_SIZE);
+       copy_page(vto, vfrom);
+       __flush_dcache((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);
+       clear_page(addr);
+       __flush_dcache((unsigned long)addr, (unsigned long)addr + PAGE_SIZE);
+}
+
+void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
+                       unsigned long user_vaddr,
+                       void *dst, void *src, int len)
+{
+       flush_cache_page(vma, user_vaddr, page_to_pfn(page));
+       memcpy(dst, src, len);
+       __flush_dcache((unsigned long)src, (unsigned long)src + len);
+       if (vma->vm_flags & VM_EXEC)
+               __flush_icache((unsigned long)src, (unsigned long)src + len);
+}
+
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+                       unsigned long user_vaddr,
+                       void *dst, void *src, int len)
+{
+       flush_cache_page(vma, user_vaddr, page_to_pfn(page));
+       memcpy(dst, src, len);
+       __flush_dcache((unsigned long)dst, (unsigned long)dst + len);
+       if (vma->vm_flags & VM_EXEC)
+               __flush_icache((unsigned long)dst, (unsigned long)dst + len);
+}
diff --git a/arch/nios2/mm/dma-mapping.c b/arch/nios2/mm/dma-mapping.c
new file mode 100644 (file)
index 0000000..ac5da75
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *  Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ *
+ * Based on DMA code from MIPS.
+ *
+ * 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/types.h>
+#include <linux/mm.h>
+#include <linux/export.h>
+#include <linux/string.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/cache.h>
+#include <asm/cacheflush.h>
+
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+                           dma_addr_t *dma_handle, gfp_t gfp)
+{
+       void *ret;
+
+       /* ignore region specifiers */
+       gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+       /* optimized page clearing */
+       gfp |= __GFP_ZERO;
+
+       if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
+               gfp |= GFP_DMA;
+
+       ret = (void *) __get_free_pages(gfp, get_order(size));
+       if (ret != NULL) {
+               *dma_handle = virt_to_phys(ret);
+               flush_dcache_range((unsigned long) ret,
+                       (unsigned long) ret + size);
+               ret = UNCAC_ADDR(ret);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+                       dma_addr_t dma_handle)
+{
+       unsigned long addr = (unsigned long) CAC_ADDR((unsigned long) vaddr);
+
+       free_pages(addr, get_order(size));
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+               enum dma_data_direction direction)
+{
+       int i;
+
+       BUG_ON(!valid_dma_direction(direction));
+
+       for_each_sg(sg, sg, nents, i) {
+               void *addr;
+
+               addr = sg_virt(sg);
+               if (addr) {
+                       __dma_sync_for_device(addr, sg->length, direction);
+                       sg->dma_address = sg_phys(sg);
+               }
+       }
+
+       return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+                       unsigned long offset, size_t size,
+                       enum dma_data_direction direction)
+{
+       void *addr;
+
+       BUG_ON(!valid_dma_direction(direction));
+
+       addr = page_address(page) + offset;
+       __dma_sync_for_device(addr, size, direction);
+
+       return page_to_phys(page) + offset;
+}
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+                   enum dma_data_direction direction)
+{
+       BUG_ON(!valid_dma_direction(direction));
+
+       __dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
+}
+EXPORT_SYMBOL(dma_unmap_page);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+                 enum dma_data_direction direction)
+{
+       void *addr;
+       int i;
+
+       BUG_ON(!valid_dma_direction(direction));
+
+       if (direction == DMA_TO_DEVICE)
+               return;
+
+       for_each_sg(sg, sg, nhwentries, i) {
+               addr = sg_virt(sg);
+               if (addr)
+                       __dma_sync_for_cpu(addr, sg->length, direction);
+       }
+}
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+                            size_t size, enum dma_data_direction direction)
+{
+       BUG_ON(!valid_dma_direction(direction));
+
+       __dma_sync_for_cpu(phys_to_virt(dma_handle), size, direction);
+}
+EXPORT_SYMBOL(dma_sync_single_for_cpu);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+                               size_t size, enum dma_data_direction direction)
+{
+       BUG_ON(!valid_dma_direction(direction));
+
+       __dma_sync_for_device(phys_to_virt(dma_handle), size, direction);
+}
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+                                       unsigned long offset, size_t size,
+                                       enum dma_data_direction direction)
+{
+       BUG_ON(!valid_dma_direction(direction));
+
+       __dma_sync_for_cpu(phys_to_virt(dma_handle), size, direction);
+}
+EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
+
+void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+                                       unsigned long offset, size_t size,
+                                       enum dma_data_direction direction)
+{
+       BUG_ON(!valid_dma_direction(direction));
+
+       __dma_sync_for_device(phys_to_virt(dma_handle), size, direction);
+}
+EXPORT_SYMBOL(dma_sync_single_range_for_device);
+
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+                        enum dma_data_direction direction)
+{
+       int i;
+
+       BUG_ON(!valid_dma_direction(direction));
+
+       /* Make sure that gcc doesn't leave the empty loop body.  */
+       for_each_sg(sg, sg, nelems, i)
+               __dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+                               int nelems, enum dma_data_direction direction)
+{
+       int i;
+
+       BUG_ON(!valid_dma_direction(direction));
+
+       /* Make sure that gcc doesn't leave the empty loop body.  */
+       for_each_sg(sg, sg, nelems, i)
+               __dma_sync_for_device(sg_virt(sg), sg->length, direction);
+
+}
+EXPORT_SYMBOL(dma_sync_sg_for_device);
diff --git a/arch/nios2/mm/extable.c b/arch/nios2/mm/extable.c
new file mode 100644 (file)
index 0000000..4d2fc5a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010, Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009, Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.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.
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+       const struct exception_table_entry *fixup;
+
+       fixup = search_exception_tables(regs->ea);
+       if (fixup) {
+               regs->ea = fixup->fixup;
+               return 1;
+       }
+
+       return 0;
+}
diff --git a/arch/nios2/mm/fault.c b/arch/nios2/mm/fault.c
new file mode 100644 (file)
index 0000000..15a0bb5
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2009 Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ *
+ * based on arch/mips/mm/fault.c which is:
+ *
+ * Copyright (C) 1995-2000 Ralf Baechle
+ *
+ * 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/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/ptrace.h>
+
+#include <asm/mmu_context.h>
+#include <asm/traps.h>
+
+#define EXC_SUPERV_INSN_ACCESS 9  /* Supervisor only instruction address */
+#define EXC_SUPERV_DATA_ACCESS 11 /* Supervisor only data address */
+#define EXC_X_PROTECTION_FAULT 13 /* TLB permission violation (x) */
+#define EXC_R_PROTECTION_FAULT 14 /* TLB permission violation (r) */
+#define EXC_W_PROTECTION_FAULT 15 /* TLB permission violation (w) */
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause,
+                               unsigned long address)
+{
+       struct vm_area_struct *vma = NULL;
+       struct task_struct *tsk = current;
+       struct mm_struct *mm = tsk->mm;
+       int code = SEGV_MAPERR;
+       int fault;
+       unsigned int flags = 0;
+
+       cause >>= 2;
+
+       /* Restart the instruction */
+       regs->ea -= 4;
+
+       /*
+        * We fault-in kernel-space virtual memory on-demand. The
+        * 'reference' page table is init_mm.pgd.
+        *
+        * NOTE! We MUST NOT take any locks for this case. We may
+        * be in an interrupt or a critical region, and should
+        * only copy the information from the master page table,
+        * nothing more.
+        */
+       if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END)) {
+               if (user_mode(regs))
+                       goto bad_area_nosemaphore;
+               else
+                       goto vmalloc_fault;
+       }
+
+       if (unlikely(address >= TASK_SIZE))
+               goto bad_area_nosemaphore;
+
+       /*
+        * If we're in an interrupt or have no user
+        * context, we must not take the fault..
+        */
+       if (in_atomic() || !mm)
+               goto bad_area_nosemaphore;
+
+       if (user_mode(regs))
+               flags |= FAULT_FLAG_USER;
+
+       if (!down_read_trylock(&mm->mmap_sem)) {
+               if (!user_mode(regs) && !search_exception_tables(regs->ea))
+                       goto bad_area_nosemaphore;
+               down_read(&mm->mmap_sem);
+       }
+
+       vma = find_vma(mm, address);
+       if (!vma)
+               goto bad_area;
+       if (vma->vm_start <= address)
+               goto good_area;
+       if (!(vma->vm_flags & VM_GROWSDOWN))
+               goto bad_area;
+       if (expand_stack(vma, address))
+               goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+       code = SEGV_ACCERR;
+
+       switch (cause) {
+       case EXC_SUPERV_INSN_ACCESS:
+               goto bad_area;
+       case EXC_SUPERV_DATA_ACCESS:
+               goto bad_area;
+       case EXC_X_PROTECTION_FAULT:
+               if (!(vma->vm_flags & VM_EXEC))
+                       goto bad_area;
+               break;
+       case EXC_R_PROTECTION_FAULT:
+               if (!(vma->vm_flags & VM_READ))
+                       goto bad_area;
+               break;
+       case EXC_W_PROTECTION_FAULT:
+               if (!(vma->vm_flags & VM_WRITE))
+                       goto bad_area;
+               flags = FAULT_FLAG_WRITE;
+               break;
+       }
+
+survive:
+       /*
+        * If for any reason at all we couldn't handle the fault,
+        * make sure we exit gracefully rather than endlessly redo
+        * the fault.
+        */
+       fault = handle_mm_fault(mm, vma, address, flags);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
+                       goto out_of_memory;
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
+       }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
+
+       up_read(&mm->mmap_sem);
+       return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+       up_read(&mm->mmap_sem);
+
+bad_area_nosemaphore:
+       /* User mode accesses just cause a SIGSEGV */
+       if (user_mode(regs)) {
+               pr_alert("%s: unhandled page fault (%d) at 0x%08lx, "
+                       "cause %ld\n", current->comm, SIGSEGV, address, cause);
+               show_regs(regs);
+               _exception(SIGSEGV, regs, code, address);
+               return;
+       }
+
+no_context:
+       /* Are we prepared to handle this kernel fault? */
+       if (fixup_exception(regs))
+               return;
+
+       /*
+        * Oops. The kernel tried to access some bad page. We'll have to
+        * terminate things with extreme prejudice.
+        */
+       bust_spinlocks(1);
+
+       pr_alert("Unable to handle kernel %s at virtual address %08lx",
+               address < PAGE_SIZE ? "NULL pointer dereference" :
+               "paging request", address);
+       pr_alert("ea = %08lx, ra = %08lx, cause = %ld\n", regs->ea, regs->ra,
+               cause);
+       panic("Oops");
+       return;
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+       up_read(&mm->mmap_sem);
+       if (is_global_init(tsk)) {
+               yield();
+               down_read(&mm->mmap_sem);
+               goto survive;
+       }
+       if (!user_mode(regs))
+               goto no_context;
+       pagefault_out_of_memory();
+       return;
+
+do_sigbus:
+       up_read(&mm->mmap_sem);
+
+       /* Kernel mode? Handle exceptions or die */
+       if (!user_mode(regs))
+               goto no_context;
+
+       _exception(SIGBUS, regs, BUS_ADRERR, address);
+       return;
+
+vmalloc_fault:
+       {
+               /*
+                * Synchronize this task's top level page-table
+                * with the 'reference' page table.
+                *
+                * Do _not_ use "tsk" here. We might be inside
+                * an interrupt in the middle of a task switch..
+                */
+               int offset = pgd_index(address);
+               pgd_t *pgd, *pgd_k;
+               pud_t *pud, *pud_k;
+               pmd_t *pmd, *pmd_k;
+               pte_t *pte_k;
+
+               pgd = pgd_current + offset;
+               pgd_k = init_mm.pgd + offset;
+
+               if (!pgd_present(*pgd_k))
+                       goto no_context;
+               set_pgd(pgd, *pgd_k);
+
+               pud = pud_offset(pgd, address);
+               pud_k = pud_offset(pgd_k, address);
+               if (!pud_present(*pud_k))
+                       goto no_context;
+               pmd = pmd_offset(pud, address);
+               pmd_k = pmd_offset(pud_k, address);
+               if (!pmd_present(*pmd_k))
+                       goto no_context;
+               set_pmd(pmd, *pmd_k);
+
+               pte_k = pte_offset_kernel(pmd_k, address);
+               if (!pte_present(*pte_k))
+                       goto no_context;
+
+               flush_tlb_one(address);
+               return;
+       }
+}
diff --git a/arch/nios2/mm/init.c b/arch/nios2/mm/init.c
new file mode 100644 (file)
index 0000000..e75c75d
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ * Copyright (C) 2004 Microtronix Datacom Ltd
+ *
+ * based on arch/m68k/mm/init.c
+ *
+ * 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/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/slab.h>
+#include <linux/binfmts.h>
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+#include <asm/cpuinfo.h>
+#include <asm/processor.h>
+
+pgd_t *pgd_current;
+
+/*
+ * paging_init() continues the virtual memory environment setup which
+ * was begun by the code in arch/head.S.
+ * The parameters are pointers to where to stick the starting and ending
+ * addresses of available kernel virtual memory.
+ */
+void __init paging_init(void)
+{
+       unsigned long zones_size[MAX_NR_ZONES];
+
+       memset(zones_size, 0, sizeof(zones_size));
+
+       pagetable_init();
+       pgd_current = swapper_pg_dir;
+
+       zones_size[ZONE_NORMAL] = max_mapnr;
+
+       /* pass the memory from the bootmem allocator to the main allocator */
+       free_area_init(zones_size);
+
+       flush_dcache_range((unsigned long)empty_zero_page,
+                       (unsigned long)empty_zero_page + PAGE_SIZE);
+}
+
+void __init mem_init(void)
+{
+       unsigned long end_mem   = memory_end; /* this must not include
+                                               kernel stack at top */
+
+       pr_debug("mem_init: start=%lx, end=%lx\n", memory_start, memory_end);
+
+       end_mem &= PAGE_MASK;
+       high_memory = __va(end_mem);
+
+       /* this will put all memory onto the freelists */
+       free_all_bootmem();
+       mem_init_print_info(NULL);
+}
+
+void __init mmu_init(void)
+{
+       flush_tlb_all();
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init free_initrd_mem(unsigned long start, unsigned long end)
+{
+       free_reserved_area((void *)start, (void *)end, -1, "initrd");
+}
+#endif
+
+void __init_refok free_initmem(void)
+{
+       free_initmem_default(-1);
+}
+
+#define __page_aligned(order) __aligned(PAGE_SIZE << (order))
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned(PGD_ORDER);
+pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned(PTE_ORDER);
+static struct page *kuser_page[1];
+
+static int alloc_kuser_page(void)
+{
+       extern char __kuser_helper_start[], __kuser_helper_end[];
+       int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+       unsigned long vpage;
+
+       vpage = get_zeroed_page(GFP_ATOMIC);
+       if (!vpage)
+               return -ENOMEM;
+
+       /* Copy kuser helpers */
+       memcpy((void *)vpage, __kuser_helper_start, kuser_sz);
+
+       flush_icache_range(vpage, vpage + KUSER_SIZE);
+       kuser_page[0] = virt_to_page(vpage);
+
+       return 0;
+}
+arch_initcall(alloc_kuser_page);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+       struct mm_struct *mm = current->mm;
+       int ret;
+
+       down_write(&mm->mmap_sem);
+
+       /* Map kuser helpers to user space address */
+       ret = install_special_mapping(mm, KUSER_BASE, KUSER_SIZE,
+                                     VM_READ | VM_EXEC | VM_MAYREAD |
+                                     VM_MAYEXEC, kuser_page);
+
+       up_write(&mm->mmap_sem);
+
+       return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+       return (vma->vm_start == KUSER_BASE) ? "[kuser]" : NULL;
+}
diff --git a/arch/nios2/mm/ioremap.c b/arch/nios2/mm/ioremap.c
new file mode 100644 (file)
index 0000000..3a28177
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ * Copyright (C) 2004 Microtronix Datacom Ltd.
+ *
+ * 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/export.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+static inline void remap_area_pte(pte_t *pte, unsigned long address,
+                               unsigned long size, unsigned long phys_addr,
+                               unsigned long flags)
+{
+       unsigned long end;
+       unsigned long pfn;
+       pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_READ
+                               | _PAGE_WRITE | flags);
+
+       address &= ~PMD_MASK;
+       end = address + size;
+       if (end > PMD_SIZE)
+               end = PMD_SIZE;
+       if (address >= end)
+               BUG();
+       pfn = PFN_DOWN(phys_addr);
+       do {
+               if (!pte_none(*pte)) {
+                       pr_err("remap_area_pte: page already exists\n");
+                       BUG();
+               }
+               set_pte(pte, pfn_pte(pfn, pgprot));
+               address += PAGE_SIZE;
+               pfn++;
+               pte++;
+       } while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t *pmd, unsigned long address,
+                               unsigned long size, unsigned long phys_addr,
+                               unsigned long flags)
+{
+       unsigned long end;
+
+       address &= ~PGDIR_MASK;
+       end = address + size;
+       if (end > PGDIR_SIZE)
+               end = PGDIR_SIZE;
+       phys_addr -= address;
+       if (address >= end)
+               BUG();
+       do {
+               pte_t *pte = pte_alloc_kernel(pmd, address);
+
+               if (!pte)
+                       return -ENOMEM;
+               remap_area_pte(pte, address, end - address, address + phys_addr,
+                       flags);
+               address = (address + PMD_SIZE) & PMD_MASK;
+               pmd++;
+       } while (address && (address < end));
+       return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+                               unsigned long size, unsigned long flags)
+{
+       int error;
+       pgd_t *dir;
+       unsigned long end = address + size;
+
+       phys_addr -= address;
+       dir = pgd_offset(&init_mm, address);
+       flush_cache_all();
+       if (address >= end)
+               BUG();
+       do {
+               pud_t *pud;
+               pmd_t *pmd;
+
+               error = -ENOMEM;
+               pud = pud_alloc(&init_mm, dir, address);
+               if (!pud)
+                       break;
+               pmd = pmd_alloc(&init_mm, pud, address);
+               if (!pmd)
+                       break;
+               if (remap_area_pmd(pmd, address, end - address,
+                       phys_addr + address, flags))
+                       break;
+               error = 0;
+               address = (address + PGDIR_SIZE) & PGDIR_MASK;
+               dir++;
+       } while (address && (address < end));
+       flush_tlb_all();
+       return error;
+}
+
+#define IS_MAPPABLE_UNCACHEABLE(addr) (addr < 0x20000000UL)
+
+/*
+ * Map some physical address range into the kernel address space.
+ */
+void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
+                       unsigned long cacheflag)
+{
+       struct vm_struct *area;
+       unsigned long offset;
+       unsigned long last_addr;
+       void *addr;
+
+       /* Don't allow wraparound or zero size */
+       last_addr = phys_addr + size - 1;
+
+       if (!size || last_addr < phys_addr)
+               return NULL;
+
+       /* Don't allow anybody to remap normal RAM that we're using */
+       if (phys_addr > PHYS_OFFSET && phys_addr < virt_to_phys(high_memory)) {
+               char *t_addr, *t_end;
+               struct page *page;
+
+               t_addr = __va(phys_addr);
+               t_end = t_addr + (size - 1);
+               for (page = virt_to_page(t_addr);
+                       page <= virt_to_page(t_end); page++)
+                       if (!PageReserved(page))
+                               return NULL;
+       }
+
+       /*
+        * Map uncached objects in the low part of address space to
+        * CONFIG_NIOS2_IO_REGION_BASE
+        */
+       if (IS_MAPPABLE_UNCACHEABLE(phys_addr) &&
+           IS_MAPPABLE_UNCACHEABLE(last_addr) &&
+           !(cacheflag & _PAGE_CACHED))
+               return (void __iomem *)(CONFIG_NIOS2_IO_REGION_BASE + phys_addr);
+
+       /* Mappings have to be page-aligned */
+       offset = phys_addr & ~PAGE_MASK;
+       phys_addr &= PAGE_MASK;
+       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+       /* Ok, go for it */
+       area = get_vm_area(size, VM_IOREMAP);
+       if (!area)
+               return NULL;
+       addr = area->addr;
+       if (remap_area_pages((unsigned long) addr, phys_addr, size,
+               cacheflag)) {
+               vunmap(addr);
+               return NULL;
+       }
+       return (void __iomem *) (offset + (char *)addr);
+}
+EXPORT_SYMBOL(__ioremap);
+
+/*
+ * __iounmap unmaps nearly everything, so be careful
+ * it doesn't free currently pointer/page tables anymore but it
+ * wasn't used anyway and might be added later.
+ */
+void __iounmap(void __iomem *addr)
+{
+       struct vm_struct *p;
+
+       if ((unsigned long) addr > CONFIG_NIOS2_IO_REGION_BASE)
+               return;
+
+       p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+       if (!p)
+               pr_err("iounmap: bad address %p\n", addr);
+       kfree(p);
+}
+EXPORT_SYMBOL(__iounmap);
diff --git a/arch/nios2/mm/mmu_context.c b/arch/nios2/mm/mmu_context.c
new file mode 100644 (file)
index 0000000..45d6b9c
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * MMU context handling.
+ *
+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
+ * Copyright (C) 2009 Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.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.
+ */
+
+#include <linux/mm.h>
+
+#include <asm/cpuinfo.h>
+#include <asm/mmu_context.h>
+#include <asm/tlb.h>
+
+/* The pids position and mask in context */
+#define PID_SHIFT      0
+#define PID_BITS       (cpuinfo.tlb_pid_num_bits)
+#define PID_MASK       ((1UL << PID_BITS) - 1)
+
+/* The versions position and mask in context */
+#define VERSION_BITS   (32 - PID_BITS)
+#define VERSION_SHIFT  (PID_SHIFT + PID_BITS)
+#define VERSION_MASK   ((1UL << VERSION_BITS) - 1)
+
+/* Return the version part of a context */
+#define CTX_VERSION(c) (((c) >> VERSION_SHIFT) & VERSION_MASK)
+
+/* Return the pid part of a context */
+#define CTX_PID(c)     (((c) >> PID_SHIFT) & PID_MASK)
+
+/* Value of the first context (version 1, pid 0) */
+#define FIRST_CTX      ((1UL << VERSION_SHIFT) | (0 << PID_SHIFT))
+
+static mm_context_t next_mmu_context;
+
+/*
+ * Initialize MMU context management stuff.
+ */
+void __init mmu_context_init(void)
+{
+       /* We need to set this here because the value depends on runtime data
+        * from cpuinfo */
+       next_mmu_context = FIRST_CTX;
+}
+
+/*
+ * Set new context (pid), keep way
+ */
+static void set_context(mm_context_t context)
+{
+       set_mmu_pid(CTX_PID(context));
+}
+
+static mm_context_t get_new_context(void)
+{
+       /* Return the next pid */
+       next_mmu_context += (1UL << PID_SHIFT);
+
+       /* If the pid field wraps around we increase the version and
+        * flush the tlb */
+       if (unlikely(CTX_PID(next_mmu_context) == 0)) {
+               /* Version is incremented since the pid increment above
+                * overflows info version */
+               flush_cache_all();
+               flush_tlb_all();
+       }
+
+       /* If the version wraps we start over with the first generation, we do
+        * not need to flush the tlb here since it's always done above */
+       if (unlikely(CTX_VERSION(next_mmu_context) == 0))
+               next_mmu_context = FIRST_CTX;
+
+       return next_mmu_context;
+}
+
+void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+              struct task_struct *tsk)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       /* If the process context we are swapping in has a different context
+        * generation then we have it should get a new generation/pid */
+       if (unlikely(CTX_VERSION(next->context) !=
+               CTX_VERSION(next_mmu_context)))
+               next->context = get_new_context();
+
+       /* Save the current pgd so the fast tlb handler can find it */
+       pgd_current = next->pgd;
+
+       /* Set the current context */
+       set_context(next->context);
+
+       local_irq_restore(flags);
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+       next->context = get_new_context();
+       set_context(next->context);
+       pgd_current = next->pgd;
+}
+
+unsigned long get_pid_from_context(mm_context_t *context)
+{
+       return CTX_PID((*context));
+}
diff --git a/arch/nios2/mm/pgtable.c b/arch/nios2/mm/pgtable.c
new file mode 100644 (file)
index 0000000..61e24a2
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.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.
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <asm/pgtable.h>
+#include <asm/cpuinfo.h>
+
+/* pteaddr:
+ *   ptbase | vpn* | zero
+ *   31-22  | 21-2 | 1-0
+ *
+ *   *vpn is preserved on double fault
+ *
+ * tlbacc:
+ *   IG   |*flags| pfn
+ *   31-25|24-20 | 19-0
+ *
+ *   *crwxg
+ *
+ * tlbmisc:
+ *   resv  |way   |rd | we|pid |dbl|bad|perm|d
+ *   31-24 |23-20 |19 | 20|17-4|3  |2  |1   |0
+ *
+ */
+
+/*
+ * Initialize a new pgd / pmd table with invalid pointers.
+ */
+static void pgd_init(pgd_t *pgd)
+{
+       unsigned long *p = (unsigned long *) pgd;
+       int i;
+
+       for (i = 0; i < USER_PTRS_PER_PGD; i += 8) {
+               p[i + 0] = (unsigned long) invalid_pte_table;
+               p[i + 1] = (unsigned long) invalid_pte_table;
+               p[i + 2] = (unsigned long) invalid_pte_table;
+               p[i + 3] = (unsigned long) invalid_pte_table;
+               p[i + 4] = (unsigned long) invalid_pte_table;
+               p[i + 5] = (unsigned long) invalid_pte_table;
+               p[i + 6] = (unsigned long) invalid_pte_table;
+               p[i + 7] = (unsigned long) invalid_pte_table;
+       }
+}
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+       pgd_t *ret, *init;
+
+       ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
+       if (ret) {
+               init = pgd_offset(&init_mm, 0UL);
+               pgd_init(ret);
+               memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+       }
+
+       return ret;
+}
+
+void __init pagetable_init(void)
+{
+       /* Initialize the entire pgd.  */
+       pgd_init(swapper_pg_dir);
+       pgd_init(swapper_pg_dir + USER_PTRS_PER_PGD);
+}
diff --git a/arch/nios2/mm/tlb.c b/arch/nios2/mm/tlb.c
new file mode 100644 (file)
index 0000000..cf10326
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Nios2 TLB handling
+ *
+ * Copyright (C) 2009, Wind River Systems Inc
+ *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.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.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/cpuinfo.h>
+
+#define TLB_INDEX_MASK         \
+       ((((1UL << (cpuinfo.tlb_ptr_sz - cpuinfo.tlb_num_ways_log2))) - 1) \
+               << PAGE_SHIFT)
+
+/* Used as illegal PHYS_ADDR for TLB mappings
+ */
+#define MAX_PHYS_ADDR 0
+
+static void get_misc_and_pid(unsigned long *misc, unsigned long *pid)
+{
+       *misc  = RDCTL(CTL_TLBMISC);
+       *misc &= (TLBMISC_PID | TLBMISC_WAY);
+       *pid  = *misc & TLBMISC_PID;
+}
+
+/*
+ * All entries common to a mm share an asid.  To effectively flush these
+ * entries, we just bump the asid.
+ */
+void flush_tlb_mm(struct mm_struct *mm)
+{
+       if (current->mm == mm)
+               flush_tlb_all();
+       else
+               memset(&mm->context, 0, sizeof(mm_context_t));
+}
+
+/*
+ * This one is only used for pages with the global bit set so we don't care
+ * much about the ASID.
+ */
+void flush_tlb_one_pid(unsigned long addr, unsigned long mmu_pid)
+{
+       unsigned int way;
+       unsigned long org_misc, pid_misc;
+
+       pr_debug("Flush tlb-entry for vaddr=%#lx\n", addr);
+
+       /* remember pid/way until we return. */
+       get_misc_and_pid(&org_misc, &pid_misc);
+
+       WRCTL(CTL_PTEADDR, (addr >> PAGE_SHIFT) << 2);
+
+       for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
+               unsigned long pteaddr;
+               unsigned long tlbmisc;
+               unsigned long pid;
+
+               tlbmisc = pid_misc | TLBMISC_RD | (way << TLBMISC_WAY_SHIFT);
+               WRCTL(CTL_TLBMISC, tlbmisc);
+               pteaddr = RDCTL(CTL_PTEADDR);
+               tlbmisc = RDCTL(CTL_TLBMISC);
+               pid = (tlbmisc >> TLBMISC_PID_SHIFT) & TLBMISC_PID_MASK;
+               if (((((pteaddr >> 2) & 0xfffff)) == (addr >> PAGE_SHIFT)) &&
+                               pid == mmu_pid) {
+                       unsigned long vaddr = CONFIG_NIOS2_IO_REGION_BASE +
+                               ((PAGE_SIZE * cpuinfo.tlb_num_lines) * way) +
+                               (addr & TLB_INDEX_MASK);
+                       pr_debug("Flush entry by writing %#lx way=%dl pid=%ld\n",
+                               vaddr, way, (pid_misc >> TLBMISC_PID_SHIFT));
+
+                       WRCTL(CTL_PTEADDR, (vaddr >> 12) << 2);
+                       tlbmisc = pid_misc | TLBMISC_WE |
+                               (way << TLBMISC_WAY_SHIFT);
+                       WRCTL(CTL_TLBMISC, tlbmisc);
+                       WRCTL(CTL_TLBACC, (MAX_PHYS_ADDR >> PAGE_SHIFT));
+               }
+       }
+
+       WRCTL(CTL_TLBMISC, org_misc);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+                       unsigned long end)
+{
+       unsigned long mmu_pid = get_pid_from_context(&vma->vm_mm->context);
+
+       while (start < end) {
+               flush_tlb_one_pid(start, mmu_pid);
+               start += PAGE_SIZE;
+       }
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       while (start < end) {
+               flush_tlb_one(start);
+               start += PAGE_SIZE;
+       }
+}
+
+/*
+ * This one is only used for pages with the global bit set so we don't care
+ * much about the ASID.
+ */
+void flush_tlb_one(unsigned long addr)
+{
+       unsigned int way;
+       unsigned long org_misc, pid_misc;
+
+       pr_debug("Flush tlb-entry for vaddr=%#lx\n", addr);
+
+       /* remember pid/way until we return. */
+       get_misc_and_pid(&org_misc, &pid_misc);
+
+       WRCTL(CTL_PTEADDR, (addr >> PAGE_SHIFT) << 2);
+
+       for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
+               unsigned long pteaddr;
+               unsigned long tlbmisc;
+
+               tlbmisc = pid_misc | TLBMISC_RD | (way << TLBMISC_WAY_SHIFT);
+               WRCTL(CTL_TLBMISC, tlbmisc);
+               pteaddr = RDCTL(CTL_PTEADDR);
+               tlbmisc = RDCTL(CTL_TLBMISC);
+
+               if ((((pteaddr >> 2) & 0xfffff)) == (addr >> PAGE_SHIFT)) {
+                       unsigned long vaddr = CONFIG_NIOS2_IO_REGION_BASE +
+                               ((PAGE_SIZE * cpuinfo.tlb_num_lines) * way) +
+                               (addr & TLB_INDEX_MASK);
+
+                       pr_debug("Flush entry by writing %#lx way=%dl pid=%ld\n",
+                               vaddr, way, (pid_misc >> TLBMISC_PID_SHIFT));
+
+                       tlbmisc = pid_misc | TLBMISC_WE |
+                               (way << TLBMISC_WAY_SHIFT);
+                       WRCTL(CTL_PTEADDR, (vaddr >> 12) << 2);
+                       WRCTL(CTL_TLBMISC, tlbmisc);
+                       WRCTL(CTL_TLBACC, (MAX_PHYS_ADDR >> PAGE_SHIFT));
+               }
+       }
+
+       WRCTL(CTL_TLBMISC, org_misc);
+}
+
+void dump_tlb_line(unsigned long line)
+{
+       unsigned int way;
+       unsigned long org_misc;
+
+       pr_debug("dump tlb-entries for line=%#lx (addr %08lx)\n", line,
+               line << (PAGE_SHIFT + cpuinfo.tlb_num_ways_log2));
+
+       /* remember pid/way until we return */
+       org_misc = (RDCTL(CTL_TLBMISC) & (TLBMISC_PID | TLBMISC_WAY));
+
+       WRCTL(CTL_PTEADDR, line << 2);
+
+       for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
+               unsigned long pteaddr;
+               unsigned long tlbmisc;
+               unsigned long tlbacc;
+
+               WRCTL(CTL_TLBMISC, TLBMISC_RD | (way << TLBMISC_WAY_SHIFT));
+               pteaddr = RDCTL(CTL_PTEADDR);
+               tlbmisc = RDCTL(CTL_TLBMISC);
+               tlbacc = RDCTL(CTL_TLBACC);
+
+               if ((tlbacc << PAGE_SHIFT) != (MAX_PHYS_ADDR & PAGE_MASK)) {
+                       pr_debug("-- way:%02x vpn:0x%08lx phys:0x%08lx pid:0x%02lx flags:%c%c%c%c%c\n",
+                               way,
+                               (pteaddr << (PAGE_SHIFT-2)),
+                               (tlbacc << PAGE_SHIFT),
+                               ((tlbmisc >> TLBMISC_PID_SHIFT) &
+                               TLBMISC_PID_MASK),
+                               (tlbacc & _PAGE_READ ? 'r' : '-'),
+                               (tlbacc & _PAGE_WRITE ? 'w' : '-'),
+                               (tlbacc & _PAGE_EXEC ? 'x' : '-'),
+                               (tlbacc & _PAGE_GLOBAL ? 'g' : '-'),
+                               (tlbacc & _PAGE_CACHED ? 'c' : '-'));
+               }
+       }
+
+       WRCTL(CTL_TLBMISC, org_misc);
+}
+
+void dump_tlb(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < cpuinfo.tlb_num_lines; i++)
+               dump_tlb_line(i);
+}
+
+void flush_tlb_pid(unsigned long pid)
+{
+       unsigned int line;
+       unsigned int way;
+       unsigned long org_misc, pid_misc;
+
+       /* remember pid/way until we return */
+       get_misc_and_pid(&org_misc, &pid_misc);
+
+       for (line = 0; line < cpuinfo.tlb_num_lines; line++) {
+               WRCTL(CTL_PTEADDR, line << 2);
+
+               for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
+                       unsigned long pteaddr;
+                       unsigned long tlbmisc;
+                       unsigned long tlbacc;
+
+                       tlbmisc = pid_misc | TLBMISC_RD |
+                               (way << TLBMISC_WAY_SHIFT);
+                       WRCTL(CTL_TLBMISC, tlbmisc);
+                       pteaddr = RDCTL(CTL_PTEADDR);
+                       tlbmisc = RDCTL(CTL_TLBMISC);
+                       tlbacc = RDCTL(CTL_TLBACC);
+
+                       if (((tlbmisc>>TLBMISC_PID_SHIFT) & TLBMISC_PID_MASK)
+                               == pid) {
+                               tlbmisc = pid_misc | TLBMISC_WE |
+                                       (way << TLBMISC_WAY_SHIFT);
+                               WRCTL(CTL_TLBMISC, tlbmisc);
+                               WRCTL(CTL_TLBACC,
+                                       (MAX_PHYS_ADDR >> PAGE_SHIFT));
+                       }
+               }
+
+               WRCTL(CTL_TLBMISC, org_misc);
+       }
+}
+
+void flush_tlb_all(void)
+{
+       int i;
+       unsigned long vaddr = CONFIG_NIOS2_IO_REGION_BASE;
+       unsigned int way;
+       unsigned long org_misc, pid_misc, tlbmisc;
+
+       /* remember pid/way until we return */
+       get_misc_and_pid(&org_misc, &pid_misc);
+       pid_misc |= TLBMISC_WE;
+
+       /* Map each TLB entry to physcal address 0 with no-access and a
+          bad ptbase */
+       for (way = 0; way < cpuinfo.tlb_num_ways; way++) {
+               tlbmisc = pid_misc | (way << TLBMISC_WAY_SHIFT);
+               for (i = 0; i < cpuinfo.tlb_num_lines; i++) {
+                       WRCTL(CTL_PTEADDR, ((vaddr) >> PAGE_SHIFT) << 2);
+                       WRCTL(CTL_TLBMISC, tlbmisc);
+                       WRCTL(CTL_TLBACC, (MAX_PHYS_ADDR >> PAGE_SHIFT));
+                       vaddr += 1UL << 12;
+               }
+       }
+
+       /* restore pid/way */
+       WRCTL(CTL_TLBMISC, org_misc);
+}
+
+void set_mmu_pid(unsigned long pid)
+{
+       WRCTL(CTL_TLBMISC, (RDCTL(CTL_TLBMISC) & TLBMISC_WAY) |
+               ((pid & TLBMISC_PID_MASK) << TLBMISC_PID_SHIFT));
+}
diff --git a/arch/nios2/mm/uaccess.c b/arch/nios2/mm/uaccess.c
new file mode 100644 (file)
index 0000000..7663e15
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009, Wind River Systems Inc
+ * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
+ */
+
+#include <linux/export.h>
+#include <linux/uaccess.h>
+
+asm(".global   __copy_from_user\n"
+       "   .type __copy_from_user, @function\n"
+       "__copy_from_user:\n"
+       "   movi  r2,7\n"
+       "   mov   r3,r4\n"
+       "   bge   r2,r6,1f\n"
+       "   xor   r2,r4,r5\n"
+       "   andi  r2,r2,3\n"
+       "   movi  r7,3\n"
+       "   beq   r2,zero,4f\n"
+       "1: addi  r6,r6,-1\n"
+       "   movi  r2,-1\n"
+       "   beq   r6,r2,3f\n"
+       "   mov   r7,r2\n"
+       "2: ldbu  r2,0(r5)\n"
+       "   addi  r6,r6,-1\n"
+       "   addi  r5,r5,1\n"
+       "   stb   r2,0(r3)\n"
+       "   addi  r3,r3,1\n"
+       "   bne   r6,r7,2b\n"
+       "3:\n"
+       "   addi  r2,r6,1\n"
+       "   ret\n"
+       "13:mov   r2,r6\n"
+       "   ret\n"
+       "4: andi  r2,r4,1\n"
+       "   cmpeq r2,r2,zero\n"
+       "   beq   r2,zero,7f\n"
+       "5: andi  r2,r3,2\n"
+       "   beq   r2,zero,6f\n"
+       "9: ldhu  r2,0(r5)\n"
+       "   addi  r6,r6,-2\n"
+       "   addi  r5,r5,2\n"
+       "   sth   r2,0(r3)\n"
+       "   addi  r3,r3,2\n"
+       "6: bge   r7,r6,1b\n"
+       "10:ldw   r2,0(r5)\n"
+       "   addi  r6,r6,-4\n"
+       "   addi  r5,r5,4\n"
+       "   stw   r2,0(r3)\n"
+       "   addi  r3,r3,4\n"
+       "   br    6b\n"
+       "7: ldbu  r2,0(r5)\n"
+       "   addi  r6,r6,-1\n"
+       "   addi  r5,r5,1\n"
+       "   addi  r3,r4,1\n"
+       "   stb   r2,0(r4)\n"
+       "   br    5b\n"
+       ".section __ex_table,\"a\"\n"
+       ".word 2b,3b\n"
+       ".word 9b,13b\n"
+       ".word 10b,13b\n"
+       ".word 7b,13b\n"
+       ".previous\n"
+       );
+EXPORT_SYMBOL(__copy_from_user);
+
+asm(
+       "   .global __copy_to_user\n"
+       "   .type __copy_to_user, @function\n"
+       "__copy_to_user:\n"
+       "   movi  r2,7\n"
+       "   mov   r3,r4\n"
+       "   bge   r2,r6,1f\n"
+       "   xor   r2,r4,r5\n"
+       "   andi  r2,r2,3\n"
+       "   movi  r7,3\n"
+       "   beq   r2,zero,4f\n"
+       /* Bail if we try to copy zero bytes  */
+       "1: addi  r6,r6,-1\n"
+       "   movi  r2,-1\n"
+       "   beq   r6,r2,3f\n"
+       /* Copy byte by byte for small copies and if src^dst != 0 */
+       "   mov   r7,r2\n"
+       "2: ldbu  r2,0(r5)\n"
+       "   addi  r5,r5,1\n"
+       "9: stb   r2,0(r3)\n"
+       "   addi  r6,r6,-1\n"
+       "   addi  r3,r3,1\n"
+       "   bne   r6,r7,2b\n"
+       "3: addi  r2,r6,1\n"
+       "   ret\n"
+       "13:mov   r2,r6\n"
+       "   ret\n"
+       /*  If 'to' is an odd address byte copy */
+       "4: andi  r2,r4,1\n"
+       "   cmpeq r2,r2,zero\n"
+       "   beq   r2,zero,7f\n"
+       /* If 'to' is not divideable by four copy halfwords */
+       "5: andi  r2,r3,2\n"
+       "   beq   r2,zero,6f\n"
+       "   ldhu  r2,0(r5)\n"
+       "   addi  r5,r5,2\n"
+       "10:sth   r2,0(r3)\n"
+       "   addi  r6,r6,-2\n"
+       "   addi  r3,r3,2\n"
+       /* Copy words */
+       "6: bge   r7,r6,1b\n"
+       "   ldw   r2,0(r5)\n"
+       "   addi  r5,r5,4\n"
+       "11:stw   r2,0(r3)\n"
+       "   addi  r6,r6,-4\n"
+       "   addi  r3,r3,4\n"
+       "   br    6b\n"
+       /* Copy remaining bytes */
+       "7: ldbu  r2,0(r5)\n"
+       "   addi  r5,r5,1\n"
+       "   addi  r3,r4,1\n"
+       "12: stb  r2,0(r4)\n"
+       "   addi  r6,r6,-1\n"
+       "   br    5b\n"
+       ".section __ex_table,\"a\"\n"
+       ".word 9b,3b\n"
+       ".word 10b,13b\n"
+       ".word 11b,13b\n"
+       ".word 12b,13b\n"
+       ".previous\n");
+EXPORT_SYMBOL(__copy_to_user);
+
+long strncpy_from_user(char *__to, const char __user *__from, long __len)
+{
+       int l = strnlen_user(__from, __len);
+       int is_zt = 1;
+
+       if (l > __len) {
+               is_zt = 0;
+               l = __len;
+       }
+
+       if (l == 0 || copy_from_user(__to, __from, l))
+               return -EFAULT;
+
+       if (is_zt)
+               l--;
+       return l;
+}
+
+long strnlen_user(const char __user *s, long n)
+{
+       long i;
+
+       for (i = 0; i < n; i++) {
+               char c;
+
+               if (get_user(c, s + i) == -EFAULT)
+                       return 0;
+               if (c == 0)
+                       return i + 1;
+       }
+       return n + 1;
+}
diff --git a/arch/nios2/platform/Kconfig.platform b/arch/nios2/platform/Kconfig.platform
new file mode 100644 (file)
index 0000000..d3e5df9
--- /dev/null
@@ -0,0 +1,129 @@
+menu "Platform options"
+
+comment "Memory settings"
+
+config NIOS2_MEM_BASE
+       hex "Memory base address"
+       default "0x00000000"
+       help
+         This is the physical address of the memory that the kernel will run
+         from. This address is used to link the kernel and setup initial memory
+         management. You should take the raw memory address without any MMU
+         or cache bits set.
+         Please not that this address is used directly so you have to manually
+         do address translation if it's connected to a bridge.
+
+comment "Device tree"
+
+config NIOS2_DTB_AT_PHYS_ADDR
+       bool "DTB at physical address"
+       default n
+       help
+         When enabled you can select a physical address to load the dtb from.
+         Normally this address is passed by a bootloader such as u-boot but
+         using this you can use a devicetree without a bootloader.
+         This way you can store a devicetree in NOR flash or an onchip rom.
+         Please note that this address is used directly so you have to manually
+         do address translation if it's connected to a bridge. Also take into
+         account that when using an MMU you'd have to ad 0xC0000000 to your
+         address
+
+config NIOS2_DTB_PHYS_ADDR
+       hex "DTB Address"
+       depends on NIOS2_DTB_AT_PHYS_ADDR
+       default "0xC0000000"
+       help
+         Physical address of a dtb blob.
+
+config NIOS2_DTB_SOURCE_BOOL
+       bool "Compile and link device tree into kernel image"
+       default n
+       help
+         This allows you to specify a dts (device tree source) file
+         which will be compiled and linked into the kernel image.
+
+config NIOS2_DTB_SOURCE
+       string "Device tree source file"
+       depends on NIOS2_DTB_SOURCE_BOOL
+       default ""
+       help
+         Absolute path to the device tree source (dts) file describing your
+         system.
+
+comment "Nios II instructions"
+
+config NIOS2_HW_MUL_SUPPORT
+       bool "Enable MUL instruction"
+       default n
+       help
+         Set to true if you configured the Nios II to include the MUL
+         instruction.  This will enable the -mhw-mul compiler flag.
+
+config NIOS2_HW_MULX_SUPPORT
+       bool "Enable MULX instruction"
+       default n
+       help
+         Set to true if you configured the Nios II to include the MULX
+         instruction.  Enables the -mhw-mulx compiler flag.
+
+config NIOS2_HW_DIV_SUPPORT
+       bool "Enable DIV instruction"
+       default n
+       help
+         Set to true if you configured the Nios II to include the DIV
+         instruction.  Enables the -mhw-div compiler flag.
+
+config NIOS2_FPU_SUPPORT
+       bool "Custom floating point instr support"
+       default n
+       help
+         Enables the -mcustom-fpu-cfg=60-1 compiler flag.
+
+config NIOS2_CI_SWAB_SUPPORT
+       bool "Byteswap custom instruction"
+       default n
+       help
+         Use the byteswap (endian converter) Nios II custom instruction provided
+         by Altera and which can be enabled in QSYS builder. This accelerates
+         endian conversions in the kernel (e.g. ntohs).
+
+config NIOS2_CI_SWAB_NO
+       int "Byteswap custom instruction number" if NIOS2_CI_SWAB_SUPPORT
+       default 0
+       help
+         Number of the instruction as configured in QSYS Builder.
+
+comment "Cache settings"
+
+config CUSTOM_CACHE_SETTINGS
+       bool "Custom cache settings"
+       help
+         This option allows you to tweak the cache settings used during early
+         boot (where the information from device tree is not yet available).
+         There should be no reason to change these values. Linux will work
+         perfectly fine, even if the Nios II is configured with smaller caches.
+
+         Say N here unless you know what you are doing.
+
+config NIOS2_DCACHE_SIZE
+       hex "D-Cache size" if CUSTOM_CACHE_SETTINGS
+       range 0x200 0x10000
+       default "0x800"
+       help
+         Maximum possible data cache size.
+
+config NIOS2_DCACHE_LINE_SIZE
+       hex "D-Cache line size" if CUSTOM_CACHE_SETTINGS
+       range 0x10 0x20
+       default "0x20"
+       help
+         Minimum possible data cache line size.
+
+config NIOS2_ICACHE_SIZE
+       hex "I-Cache size" if CUSTOM_CACHE_SETTINGS
+       range 0x200 0x10000
+       default "0x1000"
+       help
+         Maximum possible instruction cache size.
+
+endmenu
diff --git a/arch/nios2/platform/Makefile b/arch/nios2/platform/Makefile
new file mode 100644 (file)
index 0000000..46364f1
--- /dev/null
@@ -0,0 +1 @@
+obj-y += platform.o
diff --git a/arch/nios2/platform/platform.c b/arch/nios2/platform/platform.c
new file mode 100644 (file)
index 0000000..d478773
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 Altera Corporation
+ * Copyright (C) 2011 Thomas Chou
+ * Copyright (C) 2011 Walter Goossens
+ *
+ * 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/init.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/io.h>
+
+static int __init nios2_soc_device_init(void)
+{
+       struct soc_device *soc_dev;
+       struct soc_device_attribute *soc_dev_attr;
+       const char *machine;
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (soc_dev_attr) {
+               machine = of_flat_dt_get_machine_name();
+               if (machine)
+                       soc_dev_attr->machine = kasprintf(GFP_KERNEL, "%s",
+                                               machine);
+
+               soc_dev_attr->family = "Nios II";
+
+               soc_dev = soc_device_register(soc_dev_attr);
+               if (IS_ERR(soc_dev)) {
+                       kfree(soc_dev_attr->machine);
+                       kfree(soc_dev_attr);
+               }
+       }
+
+       return of_platform_populate(NULL, of_default_bus_match_table,
+               NULL, NULL);
+}
+
+device_initcall(nios2_soc_device_init);
index 1f6d2ae7aba59dfe2956dd6439569aa867f5b8a1..8cd0abf28ffbbe400a4f5e1c408573085184add2 100644 (file)
@@ -217,10 +217,14 @@ static inline void writeq(unsigned long long q, volatile void __iomem *addr)
 #define writel writel
 #define writeq writeq
 
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-#define readq_relaxed(addr) readq(addr)
+#define readb_relaxed(addr)    readb(addr)
+#define readw_relaxed(addr)    readw(addr)
+#define readl_relaxed(addr)    readl(addr)
+#define readq_relaxed(addr)    readq(addr)
+#define writeb_relaxed(b, addr)        writeb(b, addr)
+#define writew_relaxed(w, addr)        writew(w, addr)
+#define writel_relaxed(l, addr)        writel(l, addr)
+#define writeq_relaxed(q, addr)        writeq(q, addr)
 
 #define mmiowb() do { } while (0)
 
index 4006964d8e12646761d954b9f73ff0b503e736b6..a5cb070b54bf4ade7cce44e50f763a5223991e83 100644 (file)
@@ -9,6 +9,8 @@
 #include <asm/errno.h>
 #include <asm-generic/uaccess-unaligned.h>
 
+#include <linux/bug.h>
+
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
  * that put_user is the same as __put_user, etc.
  */
 
-extern int __get_kernel_bad(void);
-extern int __get_user_bad(void);
-extern int __put_kernel_bad(void);
-extern int __put_user_bad(void);
-
 static inline long access_ok(int type, const void __user * addr,
                unsigned long size)
 {
@@ -43,8 +40,8 @@ static inline long access_ok(int type, const void __user * addr,
 #define get_user __get_user
 
 #if !defined(CONFIG_64BIT)
-#define LDD_KERNEL(ptr)                __get_kernel_bad();
-#define LDD_USER(ptr)          __get_user_bad();
+#define LDD_KERNEL(ptr)                BUILD_BUG()
+#define LDD_USER(ptr)          BUILD_BUG()
 #define STD_KERNEL(x, ptr)     __put_kernel_asm64(x,ptr)
 #define STD_USER(x, ptr)       __put_user_asm64(x,ptr)
 #define ASM_WORD_INSN          ".word\t"
@@ -94,7 +91,7 @@ struct exception_data {
            case 2: __get_kernel_asm("ldh",ptr); break; \
            case 4: __get_kernel_asm("ldw",ptr); break; \
            case 8: LDD_KERNEL(ptr); break;             \
-           default: __get_kernel_bad(); break;         \
+           default: BUILD_BUG(); break;                \
            }                                           \
        }                                               \
        else {                                          \
@@ -103,7 +100,7 @@ struct exception_data {
            case 2: __get_user_asm("ldh",ptr); break;   \
            case 4: __get_user_asm("ldw",ptr); break;   \
            case 8: LDD_USER(ptr);  break;              \
-           default: __get_user_bad(); break;           \
+           default: BUILD_BUG(); break;                \
            }                                           \
        }                                               \
                                                        \
@@ -136,7 +133,7 @@ struct exception_data {
            case 2: __put_kernel_asm("sth",__x,ptr); break;     \
            case 4: __put_kernel_asm("stw",__x,ptr); break;     \
            case 8: STD_KERNEL(__x,ptr); break;                 \
-           default: __put_kernel_bad(); break;                 \
+           default: BUILD_BUG(); break;                        \
            }                                                   \
        }                                                       \
        else {                                                  \
@@ -145,7 +142,7 @@ struct exception_data {
            case 2: __put_user_asm("sth",__x,ptr); break;       \
            case 4: __put_user_asm("stw",__x,ptr); break;       \
            case 8: STD_USER(__x,ptr); break;                   \
-           default: __put_user_bad(); break;                   \
+           default: BUILD_BUG(); break;                        \
            }                                                   \
        }                                                       \
                                                                \
index 75196b415d3f8f313ec94025847427bf15a28bd6..e0a23c7bdd432adc59f4f4ebefcc4d51f91b05f1 100644 (file)
@@ -1,13 +1,7 @@
 #ifndef __ASM_PARISC_BITSPERLONG_H
 #define __ASM_PARISC_BITSPERLONG_H
 
-/*
- * using CONFIG_* outside of __KERNEL__ is wrong,
- * __LP64__ was also removed from headers, so what
- * is the right approach on parisc?
- *     -arnd
- */
-#if (defined(__KERNEL__) && defined(CONFIG_64BIT)) || defined (__LP64__)
+#if defined(__LP64__)
 #define __BITS_PER_LONG 64
 #define SHIFT_PER_LONG 6
 #else
index fe88f2649418e63c77022ed74ff43b12c1bccda2..342138983914ce8e0f5641622fb4a46bf9034155 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _PARISC_MSGBUF_H
 #define _PARISC_MSGBUF_H
 
+#include <asm/bitsperlong.h>
+
 /* 
  * The msqid64_ds structure for parisc architecture, copied from sparc.
  * Note extra padding because this structure is passed back and forth
 
 struct msqid64_ds {
        struct ipc64_perm msg_perm;
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int   __pad1;
 #endif
        __kernel_time_t msg_stime;      /* last msgsnd time */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int   __pad2;
 #endif
        __kernel_time_t msg_rtime;      /* last msgrcv time */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int   __pad3;
 #endif
        __kernel_time_t msg_ctime;      /* last change time */
index 1e59ffd3bd1ee6663acc20e663e4dafe282f4b2b..f01d89e30d735098d682b4cca2a71e79e689d4e8 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _PARISC_SEMBUF_H
 #define _PARISC_SEMBUF_H
 
+#include <asm/bitsperlong.h>
+
 /* 
  * The semid64_ds structure for parisc architecture.
  * Note extra padding because this structure is passed back and forth
 
 struct semid64_ds {
        struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int    __pad1;
 #endif
        __kernel_time_t sem_otime;              /* last semop time */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int    __pad2;
 #endif
        __kernel_time_t sem_ctime;              /* last change time */
index 0a3eada1863b71e1e859e5bf1536da089a65ffd1..8496c38560c6bd63c1a780acef9f7bcd1d00b475 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _PARISC_SHMBUF_H
 #define _PARISC_SHMBUF_H
 
+#include <asm/bitsperlong.h>
+
 /* 
  * The shmid64_ds structure for parisc architecture.
  * Note extra padding because this structure is passed back and forth
 
 struct shmid64_ds {
        struct ipc64_perm       shm_perm;       /* operation perms */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int            __pad1;
 #endif
        __kernel_time_t         shm_atime;      /* last attach time */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int            __pad2;
 #endif
        __kernel_time_t         shm_dtime;      /* last detach time */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int            __pad3;
 #endif
        __kernel_time_t         shm_ctime;      /* last change time */
-#ifndef CONFIG_64BIT
+#if __BITS_PER_LONG != 64
        unsigned int            __pad4;
 #endif
        size_t                  shm_segsz;      /* size of segment (bytes) */
@@ -36,23 +38,16 @@ struct shmid64_ds {
        unsigned int            __unused2;
 };
 
-#ifdef CONFIG_64BIT
-/* The 'unsigned int' (formerly 'unsigned long') data types below will
- * ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on
- * a wide kernel, but if some of these values are meant to contain pointers
- * they may need to be 'long long' instead. -PB XXX FIXME
- */
-#endif
 struct shminfo64 {
-       unsigned int    shmmax;
-       unsigned int    shmmin;
-       unsigned int    shmmni;
-       unsigned int    shmseg;
-       unsigned int    shmall;
-       unsigned int    __unused1;
-       unsigned int    __unused2;
-       unsigned int    __unused3;
-       unsigned int    __unused4;
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
 };
 
 #endif /* _PARISC_SHMBUF_H */
index 10df7079f4cdf08dec0e26d871e4270d157a50ed..e26043b73f5d8e32280b4bd1cfe087f4c93aa3b9 100644 (file)
@@ -85,7 +85,7 @@
 struct siginfo;
 
 /* Type of a signal handler.  */
-#ifdef CONFIG_64BIT
+#if defined(__LP64__)
 /* function pointers on 64-bit parisc are pointers to little structs and the
  * compiler doesn't support code which changes or tests the address of
  * the function in the little struct.  This is really ugly -PB
index 8667f18be2385d7423da2efac3803671b500740e..5f5c0373de63cb6dc898e9b3a273427a96fbe607 100644 (file)
 #define __NR_seccomp           (__NR_Linux + 338)
 #define __NR_getrandom         (__NR_Linux + 339)
 #define __NR_memfd_create      (__NR_Linux + 340)
+#define __NR_bpf               (__NR_Linux + 341)
 
-#define __NR_Linux_syscalls    (__NR_memfd_create + 1)
+#define __NR_Linux_syscalls    (__NR_bpf + 1)
 
 
 #define __IGNORE_select                /* newselect */
index b563d9c8268b153429a06cfc85924c236d00c688..fe4f0b89bf8fa0ed21d3f5a568dd946a0dd81be0 100644 (file)
        ENTRY_COMP(msgsnd)
        ENTRY_COMP(msgrcv)
        ENTRY_SAME(msgget)              /* 190 */
-       ENTRY_SAME(msgctl)
-       ENTRY_SAME(shmat)
+       ENTRY_COMP(msgctl)
+       ENTRY_COMP(shmat)
        ENTRY_SAME(shmdt)
        ENTRY_SAME(shmget)
-       ENTRY_SAME(shmctl)              /* 195 */
+       ENTRY_COMP(shmctl)              /* 195 */
        ENTRY_SAME(ni_syscall)          /* streams1 */
        ENTRY_SAME(ni_syscall)          /* streams2 */
        ENTRY_SAME(lstat64)
        ENTRY_SAME(epoll_ctl)           /* 225 */
        ENTRY_SAME(epoll_wait)
        ENTRY_SAME(remap_file_pages)
-       ENTRY_SAME(semtimedop)
+       ENTRY_COMP(semtimedop)
        ENTRY_COMP(mq_open)
        ENTRY_SAME(mq_unlink)           /* 230 */
        ENTRY_COMP(mq_timedsend)
        ENTRY_SAME(seccomp)
        ENTRY_SAME(getrandom)
        ENTRY_SAME(memfd_create)        /* 340 */
+       ENTRY_SAME(bpf)
 
        /* Nothing yet */
 
index 63392f4b29a4f7876210b48a52bff5ba39f2ee77..d2008887eb8c7fd8f3271b73438f8d5c578cb2b4 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
-CONFIG_CMA=y
 CONFIG_PPC_64K_PAGES=y
 CONFIG_PPC_SUBPAGE_PROT=y
 CONFIG_SCHED_SMT=y
@@ -138,6 +137,7 @@ CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL_TRAP=y
 CONFIG_TUN=m
 CONFIG_VIRTIO_NET=m
+CONFIG_VHOST_NET=m
 CONFIG_VORTEX=y
 CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
@@ -303,4 +303,9 @@ CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_DEV_NX=y
 CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
index 3b260efbfbf9833a5d23263b64f50c833564b74a..ca07f9c27335dd7beb66c9d11e4dba89b30dadc2 100644 (file)
@@ -71,9 +71,10 @@ struct device_node;
 
 #define EEH_PE_ISOLATED                (1 << 0)        /* Isolated PE          */
 #define EEH_PE_RECOVERING      (1 << 1)        /* Recovering PE        */
-#define EEH_PE_RESET           (1 << 2)        /* PE reset in progress */
+#define EEH_PE_CFG_BLOCKED     (1 << 2)        /* Block config access  */
 
 #define EEH_PE_KEEP            (1 << 8)        /* Keep PE on hotplug   */
+#define EEH_PE_CFG_RESTRICTED  (1 << 9)        /* Block config on error */
 
 struct eeh_pe {
        int type;                       /* PE type: PHB/Bus/Device      */
index a6774560afe3753dd0f4636124c1021305b7a391..493e72f64b35feac4a03fe7912aa7c04067e6fe6 100644 (file)
 #define CPU_UNKNOWN            (~((u32)0))
 
 /* Utility macros */
-#define SKIP_TO_NEXT_CPU(reg_entry)                    \
-({                                                     \
-       while (reg_entry->reg_id != REG_ID("CPUEND"))   \
-               reg_entry++;                            \
-       reg_entry++;                                    \
+#define SKIP_TO_NEXT_CPU(reg_entry)                                    \
+({                                                                     \
+       while (be64_to_cpu(reg_entry->reg_id) != REG_ID("CPUEND"))      \
+               reg_entry++;                                            \
+       reg_entry++;                                                    \
 })
 
 /* Kernel Dump section info */
 struct fadump_section {
-       u32     request_flag;
-       u16     source_data_type;
-       u16     error_flags;
-       u64     source_address;
-       u64     source_len;
-       u64     bytes_dumped;
-       u64     destination_address;
+       __be32  request_flag;
+       __be16  source_data_type;
+       __be16  error_flags;
+       __be64  source_address;
+       __be64  source_len;
+       __be64  bytes_dumped;
+       __be64  destination_address;
 };
 
 /* ibm,configure-kernel-dump header. */
 struct fadump_section_header {
-       u32     dump_format_version;
-       u16     dump_num_sections;
-       u16     dump_status_flag;
-       u32     offset_first_dump_section;
+       __be32  dump_format_version;
+       __be16  dump_num_sections;
+       __be16  dump_status_flag;
+       __be32  offset_first_dump_section;
 
        /* Fields for disk dump option. */
-       u32     dd_block_size;
-       u64     dd_block_offset;
-       u64     dd_num_blocks;
-       u32     dd_offset_disk_path;
+       __be32  dd_block_size;
+       __be64  dd_block_offset;
+       __be64  dd_num_blocks;
+       __be32  dd_offset_disk_path;
 
        /* Maximum time allowed to prevent an automatic dump-reboot. */
-       u32     max_time_auto;
+       __be32  max_time_auto;
 };
 
 /*
@@ -174,15 +174,15 @@ static inline u64 str_to_u64(const char *str)
 
 /* Register save area header. */
 struct fadump_reg_save_area_header {
-       u64             magic_number;
-       u32             version;
-       u32             num_cpu_offset;
+       __be64          magic_number;
+       __be32          version;
+       __be32          num_cpu_offset;
 };
 
 /* Register entry. */
 struct fadump_reg_entry {
-       u64             reg_id;
-       u64             reg_value;
+       __be64          reg_id;
+       __be64          reg_value;
 };
 
 /* fadump crash info structure */
index 623f2971ce0ed8d4d947642c862d4dce7640d28d..766b77d527ac6e1c7286c4d1618229b5f2dac72e 100644 (file)
@@ -71,7 +71,7 @@ pte_t *huge_pte_offset_and_shift(struct mm_struct *mm,
 
 void flush_dcache_icache_hugepage(struct page *page);
 
-#if defined(CONFIG_PPC_MM_SLICES) || defined(CONFIG_PPC_SUBPAGE_PROT)
+#if defined(CONFIG_PPC_MM_SLICES)
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
                           unsigned long len);
 #else
index 97d3869991ca691ebf0342b496ebe767aee7492a..9eaf301ac952fccb9270d0dc89fb293ef17b34a9 100644 (file)
@@ -617,10 +617,14 @@ static inline void name at                                        \
 /*
  * We don't do relaxed operations yet, at least not with this semantic
  */
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-#define readq_relaxed(addr) readq(addr)
+#define readb_relaxed(addr)    readb(addr)
+#define readw_relaxed(addr)    readw(addr)
+#define readl_relaxed(addr)    readl(addr)
+#define readq_relaxed(addr)    readq(addr)
+#define writeb_relaxed(v, addr)        writeb(v, addr)
+#define writew_relaxed(v, addr)        writew(v, addr)
+#define writel_relaxed(v, addr)        writel(v, addr)
+#define writeq_relaxed(v, addr)        writeq(v, addr)
 
 #ifdef CONFIG_PPC32
 #define mmiowb()
index 42632c7a2a4e77e86fa0768646f30b7508365fd9..9cfa3706a1b8750942d7e41a91ef44996053a2ad 100644 (file)
@@ -137,13 +137,16 @@ static inline void set_iommu_table_base_and_group(struct device *dev,
        iommu_add_device(dev);
 }
 
-extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
-                       struct scatterlist *sglist, int nelems,
-                       unsigned long mask, enum dma_data_direction direction,
-                       struct dma_attrs *attrs);
-extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
-                          int nelems, enum dma_data_direction direction,
-                          struct dma_attrs *attrs);
+extern int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
+                           struct scatterlist *sglist, int nelems,
+                           unsigned long mask,
+                           enum dma_data_direction direction,
+                           struct dma_attrs *attrs);
+extern void ppc_iommu_unmap_sg(struct iommu_table *tbl,
+                              struct scatterlist *sglist,
+                              int nelems,
+                              enum dma_data_direction direction,
+                              struct dma_attrs *attrs);
 
 extern void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
                                  size_t size, dma_addr_t *dma_handle,
index 4ca90a39d6d01af63da46c73d19b816b0979e538..725247beebecda3493e9e477f7fd4ec29911b558 100644 (file)
@@ -159,8 +159,6 @@ struct pci_dn {
 
        int     pci_ext_config_space;   /* for pci devices */
 
-       bool    force_32bit_msi;
-
        struct  pci_dev *pcidev;        /* back-pointer to the pci device */
 #ifdef CONFIG_EEH
        struct eeh_dev *edev;           /* eeh device */
index 0bb23725b1e721a0d5e89f23db233f15b8a9b3ac..8bf1b6351716ee424d80bf240bbcea54abc35c9e 100644 (file)
@@ -34,7 +34,7 @@
        do {                                                    \
                (regs)->result = 0;                             \
                (regs)->nip = __ip;                             \
-               (regs)->gpr[1] = *(unsigned long *)__get_SP();  \
+               (regs)->gpr[1] = current_stack_pointer();       \
                asm volatile("mfmsr %0" : "=r" ((regs)->msr));  \
        } while (0)
 #endif
index e9a9f60e596df4c4ef900965498e9f99565915ad..fc3ee06eab876ec12b20150aeffafe4e045260ae 100644 (file)
@@ -3,7 +3,6 @@
 #ifdef __KERNEL__
 
 #include <linux/mm.h>
-#include <asm-generic/tlb.h>
 
 #ifdef CONFIG_PPC_BOOK3E
 extern void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address);
@@ -14,6 +13,8 @@ static inline void tlb_flush_pgtable(struct mmu_gather *tlb,
 }
 #endif /* !CONFIG_PPC_BOOK3E */
 
+extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
+
 #ifdef CONFIG_PPC64
 #include <asm/pgalloc-64.h>
 #else
index fe3f9488f321e5ec20448ac92c6e6a3e16d4fc77..c998279bd85b1b5cec6cf719b88fadc90aacd79f 100644 (file)
@@ -1265,8 +1265,7 @@ static inline unsigned long mfvtb (void)
 
 #define proc_trap()    asm volatile("trap")
 
-#define __get_SP()     ({unsigned long sp; \
-                       asm volatile("mr %0,1": "=r" (sp)); sp;})
+extern unsigned long current_stack_pointer(void);
 
 extern unsigned long scom970_read(unsigned int address);
 extern void scom970_write(unsigned int address, unsigned long value);
index 6fa2708da15304b7bc3ad10f3480e81a837532f8..6240698fee9a60fbbbf5403c10f710a5c41b861b 100644 (file)
@@ -19,7 +19,7 @@
 
 /* ftrace syscalls requires exporting the sys_call_table */
 #ifdef CONFIG_FTRACE_SYSCALLS
-extern const unsigned long *sys_call_table;
+extern const unsigned long sys_call_table[];
 #endif /* CONFIG_FTRACE_SYSCALLS */
 
 static inline long syscall_get_nr(struct task_struct *task,
index 7d8a600688058ec5025cfd3688b6eb369cdadea5..ce9577d693be1c7849c18ac0259a35525d46c6fe 100644 (file)
@@ -365,3 +365,4 @@ SYSCALL_SPU(renameat2)
 SYSCALL_SPU(seccomp)
 SYSCALL_SPU(getrandom)
 SYSCALL_SPU(memfd_create)
+SYSCALL_SPU(bpf)
index e2b428b0f7babd3626e880be36b45a682a95b1ab..20733fa518ae135995abfeb161b227d9a105adce 100644 (file)
@@ -27,6 +27,7 @@
 
 #define tlb_start_vma(tlb, vma)        do { } while (0)
 #define tlb_end_vma(tlb, vma)  do { } while (0)
+#define __tlb_remove_tlb_entry __tlb_remove_tlb_entry
 
 extern void tlb_flush(struct mmu_gather *tlb);
 
index 4e9af3fd43e7d062755255d932c2123ea5f54c8a..e0da021caa004205fc8b645d95b3047c8cd9b73e 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          361
+#define __NR_syscalls          362
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 0688fc06e18394268002ae2b7e419f183e6a7dc4..f55351f2e66e962097bc078c25f77a176ca52e2a 100644 (file)
 #define __NR_seccomp           358
 #define __NR_getrandom         359
 #define __NR_memfd_create      360
+#define __NR_bpf               361
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index 54d0116256f752247abd63d6619068c4d619d24d..4c68bfe4108a9873de802765373b9b7361058ecf 100644 (file)
@@ -60,16 +60,16 @@ static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
                            int nelems, enum dma_data_direction direction,
                            struct dma_attrs *attrs)
 {
-       return iommu_map_sg(dev, get_iommu_table_base(dev), sglist, nelems,
-                           device_to_mask(dev), direction, attrs);
+       return ppc_iommu_map_sg(dev, get_iommu_table_base(dev), sglist, nelems,
+                               device_to_mask(dev), direction, attrs);
 }
 
 static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
                int nelems, enum dma_data_direction direction,
                struct dma_attrs *attrs)
 {
-       iommu_unmap_sg(get_iommu_table_base(dev), sglist, nelems, direction,
-                      attrs);
+       ppc_iommu_unmap_sg(get_iommu_table_base(dev), sglist, nelems,
+                          direction, attrs);
 }
 
 /* We support DMA to/from any memory page via the iommu */
index adac9dc54aeed2c748ae62a7a3cd1ad9fad8eb2f..484b2d4462c10cd954aad0a5e9cb7776022b1db1 100644 (file)
@@ -53,9 +53,16 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 #else
        struct page *page;
        int node = dev_to_node(dev);
+#ifdef CONFIG_FSL_SOC
        u64 pfn = get_pfn_limit(dev);
        int zone;
 
+       /*
+        * This code should be OK on other platforms, but we have drivers that
+        * don't set coherent_dma_mask. As a workaround we just ifdef it. This
+        * whole routine needs some serious cleanup.
+        */
+
        zone = dma_pfn_limit_to_zone(pfn);
        if (zone < 0) {
                dev_err(dev, "%s: No suitable zone for pfn %#llx\n",
@@ -73,6 +80,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
                break;
 #endif
        };
+#endif /* CONFIG_FSL_SOC */
 
        /* ignore region specifiers */
        flag  &= ~(__GFP_HIGHMEM);
index d543e4179c18cc7737569c8a0e5ef5e8ebf48e14..2248a1999c64e18d50b5cc6aaae902a37279ad5e 100644 (file)
@@ -257,6 +257,13 @@ static void *eeh_dump_pe_log(void *data, void *flag)
        struct eeh_dev *edev, *tmp;
        size_t *plen = flag;
 
+       /* If the PE's config space is blocked, 0xFF's will be
+        * returned. It's pointless to collect the log in this
+        * case.
+        */
+       if (pe->state & EEH_PE_CFG_BLOCKED)
+               return NULL;
+
        eeh_pe_for_each_dev(pe, edev, tmp)
                *plen += eeh_dump_dev_log(edev, pci_regs_buf + *plen,
                                          EEH_PCI_REGS_LOG_LEN - *plen);
@@ -673,18 +680,18 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
        switch (state) {
        case pcie_deassert_reset:
                eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
-               eeh_pe_state_clear(pe, EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                break;
        case pcie_hot_reset:
-               eeh_pe_state_mark(pe, EEH_PE_RESET);
+               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_RESET);
+               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_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                return -EINVAL;
        };
 
@@ -1523,7 +1530,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
        switch (option) {
        case EEH_RESET_DEACTIVATE:
                ret = eeh_ops->reset(pe, option);
-               eeh_pe_state_clear(pe, EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                if (ret)
                        break;
 
@@ -1538,7 +1545,7 @@ int eeh_pe_reset(struct eeh_pe *pe, int option)
                 */
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
 
-               eeh_pe_state_mark(pe, EEH_PE_RESET);
+               eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                ret = eeh_ops->reset(pe, option);
                break;
        default:
index 3fd514f8e4b2a8e300b87171378185260dc901b3..6535936bdf27a38c2e535ae63599af23df8ce414 100644 (file)
@@ -528,13 +528,13 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
        eeh_pe_dev_traverse(pe, eeh_report_error, &result);
 
        /* Issue reset */
-       eeh_pe_state_mark(pe, EEH_PE_RESET);
+       eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
        ret = eeh_reset_pe(pe);
        if (ret) {
-               eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_RECOVERING | EEH_PE_CFG_BLOCKED);
                return ret;
        }
-       eeh_pe_state_clear(pe, EEH_PE_RESET);
+       eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
 
        /* Unfreeze the PE */
        ret = eeh_clear_pe_frozen_state(pe, true);
@@ -601,10 +601,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
         * config accesses. So we prefer to block them. However, controlled
         * PCI config accesses initiated from EEH itself are allowed.
         */
-       eeh_pe_state_mark(pe, EEH_PE_RESET);
+       eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
        rc = eeh_reset_pe(pe);
        if (rc) {
-               eeh_pe_state_clear(pe, EEH_PE_RESET);
+               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                return rc;
        }
 
@@ -613,7 +613,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
        /* Restore PE */
        eeh_ops->configure_bridge(pe);
        eeh_pe_restore_bars(pe);
-       eeh_pe_state_clear(pe, EEH_PE_RESET);
+       eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
 
        /* Clear frozen state */
        rc = eeh_clear_pe_frozen_state(pe, false);
index 53dd0915e6907165aaed9740575d4c8f7b7a5c5a..5a63e2b0f65b616e3c6f5b066921e25d0f20d384 100644 (file)
@@ -525,7 +525,7 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
        pe->state |= state;
 
        /* Offline PCI devices if applicable */
-       if (state != EEH_PE_ISOLATED)
+       if (!(state & EEH_PE_ISOLATED))
                return NULL;
 
        eeh_pe_for_each_dev(pe, edev, tmp) {
@@ -534,6 +534,10 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
                        pdev->error_state = pci_channel_io_frozen;
        }
 
+       /* Block PCI config access if required */
+       if (pe->state & EEH_PE_CFG_RESTRICTED)
+               pe->state |= EEH_PE_CFG_BLOCKED;
+
        return NULL;
 }
 
@@ -611,6 +615,10 @@ static void *__eeh_pe_state_clear(void *data, void *flag)
                pdev->error_state = pci_channel_io_normal;
        }
 
+       /* Unblock PCI config access if required */
+       if (pe->state & EEH_PE_CFG_RESTRICTED)
+               pe->state &= ~EEH_PE_CFG_BLOCKED;
+
        return NULL;
 }
 
index f19b1e5cb06096e2bd9b68b8cd620669c8943cac..1ceecdda810b04722b88329d52b866c3c540ad0e 100644 (file)
@@ -65,7 +65,7 @@ static ssize_t eeh_pe_state_show(struct device *dev,
                return -ENODEV;
 
        state = eeh_ops->get_state(edev->pe, NULL);
-       return sprintf(buf, "%0x08x %0x08x\n",
+       return sprintf(buf, "0x%08x 0x%08x\n",
                       state, edev->pe->state);
 }
 
index 5bbd1bc8c3b0a3f4265e263ce315311d8562f689..0905c8da90f1bb6e2aedb5e4cbfd7a7351df44a7 100644 (file)
@@ -659,7 +659,13 @@ _GLOBAL(ret_from_except_lite)
 3:
 #endif
        bl      save_nvgprs
+       /*
+        * Use a non volatile GPR to save and restore our thread_info flags
+        * across the call to restore_interrupts.
+        */
+       mr      r30,r4
        bl      restore_interrupts
+       mr      r4,r30
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      do_notify_resume
        b       ret_from_except
index 050f79a4a168cd16a1c4f22be4046cd06a5e6a85..72e783ea06811fd936fef0d8b5e75e0f3a8b9db1 100644 (file)
@@ -1270,11 +1270,6 @@ hmi_exception_early:
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      hmi_exception_realmode
        /* Windup the stack. */
-       /* Clear MSR_RI before setting SRR0 and SRR1. */
-       li      r0,MSR_RI
-       mfmsr   r9                      /* get MSR value */
-       andc    r9,r9,r0
-       mtmsrd  r9,1                    /* Clear MSR_RI */
        /* Move original HSRR0 and HSRR1 into the respective regs */
        ld      r9,_MSR(r1)
        mtspr   SPRN_HSRR1,r9
index 742694c1d85238fe380e4ceecd7443506bb8d0b7..26d091a1a54cf555627fd95bb135cf98eb3e52b8 100644 (file)
@@ -58,7 +58,7 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
        const __be32 *sections;
        int i, num_sections;
        int size;
-       const int *token;
+       const __be32 *token;
 
        if (depth != 1 || strcmp(uname, "rtas") != 0)
                return 0;
@@ -72,7 +72,7 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
                return 1;
 
        fw_dump.fadump_supported = 1;
-       fw_dump.ibm_configure_kernel_dump = *token;
+       fw_dump.ibm_configure_kernel_dump = be32_to_cpu(*token);
 
        /*
         * The 'ibm,kernel-dump' rtas node is present only if there is
@@ -147,11 +147,11 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
        memset(fdm, 0, sizeof(struct fadump_mem_struct));
        addr = addr & PAGE_MASK;
 
-       fdm->header.dump_format_version = 0x00000001;
-       fdm->header.dump_num_sections = 3;
+       fdm->header.dump_format_version = cpu_to_be32(0x00000001);
+       fdm->header.dump_num_sections = cpu_to_be16(3);
        fdm->header.dump_status_flag = 0;
        fdm->header.offset_first_dump_section =
-               (u32)offsetof(struct fadump_mem_struct, cpu_state_data);
+               cpu_to_be32((u32)offsetof(struct fadump_mem_struct, cpu_state_data));
 
        /*
         * Fields for disk dump option.
@@ -167,27 +167,27 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
 
        /* Kernel dump sections */
        /* cpu state data section. */
-       fdm->cpu_state_data.request_flag = FADUMP_REQUEST_FLAG;
-       fdm->cpu_state_data.source_data_type = FADUMP_CPU_STATE_DATA;
+       fdm->cpu_state_data.request_flag = cpu_to_be32(FADUMP_REQUEST_FLAG);
+       fdm->cpu_state_data.source_data_type = cpu_to_be16(FADUMP_CPU_STATE_DATA);
        fdm->cpu_state_data.source_address = 0;
-       fdm->cpu_state_data.source_len = fw_dump.cpu_state_data_size;
-       fdm->cpu_state_data.destination_address = addr;
+       fdm->cpu_state_data.source_len = cpu_to_be64(fw_dump.cpu_state_data_size);
+       fdm->cpu_state_data.destination_address = cpu_to_be64(addr);
        addr += fw_dump.cpu_state_data_size;
 
        /* hpte region section */
-       fdm->hpte_region.request_flag = FADUMP_REQUEST_FLAG;
-       fdm->hpte_region.source_data_type = FADUMP_HPTE_REGION;
+       fdm->hpte_region.request_flag = cpu_to_be32(FADUMP_REQUEST_FLAG);
+       fdm->hpte_region.source_data_type = cpu_to_be16(FADUMP_HPTE_REGION);
        fdm->hpte_region.source_address = 0;
-       fdm->hpte_region.source_len = fw_dump.hpte_region_size;
-       fdm->hpte_region.destination_address = addr;
+       fdm->hpte_region.source_len = cpu_to_be64(fw_dump.hpte_region_size);
+       fdm->hpte_region.destination_address = cpu_to_be64(addr);
        addr += fw_dump.hpte_region_size;
 
        /* RMA region section */
-       fdm->rmr_region.request_flag = FADUMP_REQUEST_FLAG;
-       fdm->rmr_region.source_data_type = FADUMP_REAL_MODE_REGION;
-       fdm->rmr_region.source_address = RMA_START;
-       fdm->rmr_region.source_len = fw_dump.boot_memory_size;
-       fdm->rmr_region.destination_address = addr;
+       fdm->rmr_region.request_flag = cpu_to_be32(FADUMP_REQUEST_FLAG);
+       fdm->rmr_region.source_data_type = cpu_to_be16(FADUMP_REAL_MODE_REGION);
+       fdm->rmr_region.source_address = cpu_to_be64(RMA_START);
+       fdm->rmr_region.source_len = cpu_to_be64(fw_dump.boot_memory_size);
+       fdm->rmr_region.destination_address = cpu_to_be64(addr);
        addr += fw_dump.boot_memory_size;
 
        return addr;
@@ -272,7 +272,7 @@ int __init fadump_reserve_mem(void)
         * first kernel.
         */
        if (fdm_active)
-               fw_dump.boot_memory_size = fdm_active->rmr_region.source_len;
+               fw_dump.boot_memory_size = be64_to_cpu(fdm_active->rmr_region.source_len);
        else
                fw_dump.boot_memory_size = fadump_calculate_reserve_size();
 
@@ -314,8 +314,8 @@ int __init fadump_reserve_mem(void)
                                (unsigned long)(base >> 20));
 
                fw_dump.fadumphdr_addr =
-                               fdm_active->rmr_region.destination_address +
-                               fdm_active->rmr_region.source_len;
+                               be64_to_cpu(fdm_active->rmr_region.destination_address) +
+                               be64_to_cpu(fdm_active->rmr_region.source_len);
                pr_debug("fadumphdr_addr = %p\n",
                                (void *) fw_dump.fadumphdr_addr);
        } else {
@@ -472,9 +472,9 @@ fadump_read_registers(struct fadump_reg_entry *reg_entry, struct pt_regs *regs)
 {
        memset(regs, 0, sizeof(struct pt_regs));
 
-       while (reg_entry->reg_id != REG_ID("CPUEND")) {
-               fadump_set_regval(regs, reg_entry->reg_id,
-                                       reg_entry->reg_value);
+       while (be64_to_cpu(reg_entry->reg_id) != REG_ID("CPUEND")) {
+               fadump_set_regval(regs, be64_to_cpu(reg_entry->reg_id),
+                                       be64_to_cpu(reg_entry->reg_value));
                reg_entry++;
        }
        reg_entry++;
@@ -603,20 +603,20 @@ static int __init fadump_build_cpu_notes(const struct fadump_mem_struct *fdm)
        if (!fdm->cpu_state_data.bytes_dumped)
                return -EINVAL;
 
-       addr = fdm->cpu_state_data.destination_address;
+       addr = be64_to_cpu(fdm->cpu_state_data.destination_address);
        vaddr = __va(addr);
 
        reg_header = vaddr;
-       if (reg_header->magic_number != REGSAVE_AREA_MAGIC) {
+       if (be64_to_cpu(reg_header->magic_number) != REGSAVE_AREA_MAGIC) {
                printk(KERN_ERR "Unable to read register save area.\n");
                return -ENOENT;
        }
        pr_debug("--------CPU State Data------------\n");
-       pr_debug("Magic Number: %llx\n", reg_header->magic_number);
-       pr_debug("NumCpuOffset: %x\n", reg_header->num_cpu_offset);
+       pr_debug("Magic Number: %llx\n", be64_to_cpu(reg_header->magic_number));
+       pr_debug("NumCpuOffset: %x\n", be32_to_cpu(reg_header->num_cpu_offset));
 
-       vaddr += reg_header->num_cpu_offset;
-       num_cpus = *((u32 *)(vaddr));
+       vaddr += be32_to_cpu(reg_header->num_cpu_offset);
+       num_cpus = be32_to_cpu(*((__be32 *)(vaddr)));
        pr_debug("NumCpus     : %u\n", num_cpus);
        vaddr += sizeof(u32);
        reg_entry = (struct fadump_reg_entry *)vaddr;
@@ -639,13 +639,13 @@ static int __init fadump_build_cpu_notes(const struct fadump_mem_struct *fdm)
                fdh = __va(fw_dump.fadumphdr_addr);
 
        for (i = 0; i < num_cpus; i++) {
-               if (reg_entry->reg_id != REG_ID("CPUSTRT")) {
+               if (be64_to_cpu(reg_entry->reg_id) != REG_ID("CPUSTRT")) {
                        printk(KERN_ERR "Unable to read CPU state data\n");
                        rc = -ENOENT;
                        goto error_out;
                }
                /* Lower 4 bytes of reg_value contains logical cpu id */
-               cpu = reg_entry->reg_value & FADUMP_CPU_ID_MASK;
+               cpu = be64_to_cpu(reg_entry->reg_value) & FADUMP_CPU_ID_MASK;
                if (fdh && !cpumask_test_cpu(cpu, &fdh->cpu_online_mask)) {
                        SKIP_TO_NEXT_CPU(reg_entry);
                        continue;
@@ -692,7 +692,7 @@ static int __init process_fadump(const struct fadump_mem_struct *fdm_active)
                return -EINVAL;
 
        /* Check if the dump data is valid. */
-       if ((fdm_active->header.dump_status_flag == FADUMP_ERROR_FLAG) ||
+       if ((be16_to_cpu(fdm_active->header.dump_status_flag) == FADUMP_ERROR_FLAG) ||
                        (fdm_active->cpu_state_data.error_flags != 0) ||
                        (fdm_active->rmr_region.error_flags != 0)) {
                printk(KERN_ERR "Dump taken by platform is not valid\n");
@@ -828,7 +828,7 @@ static void fadump_setup_crash_memory_ranges(void)
 static inline unsigned long fadump_relocate(unsigned long paddr)
 {
        if (paddr > RMA_START && paddr < fw_dump.boot_memory_size)
-               return fdm.rmr_region.destination_address + paddr;
+               return be64_to_cpu(fdm.rmr_region.destination_address) + paddr;
        else
                return paddr;
 }
@@ -902,7 +902,7 @@ static int fadump_create_elfcore_headers(char *bufp)
                         * to the specified destination_address. Hence set
                         * the correct offset.
                         */
-                       phdr->p_offset = fdm.rmr_region.destination_address;
+                       phdr->p_offset = be64_to_cpu(fdm.rmr_region.destination_address);
                }
 
                phdr->p_paddr = mbase;
@@ -951,7 +951,7 @@ static void register_fadump(void)
 
        fadump_setup_crash_memory_ranges();
 
-       addr = fdm.rmr_region.destination_address + fdm.rmr_region.source_len;
+       addr = be64_to_cpu(fdm.rmr_region.destination_address) + be64_to_cpu(fdm.rmr_region.source_len);
        /* Initialize fadump crash info header. */
        addr = init_fadump_header(addr);
        vaddr = __va(addr);
@@ -1023,7 +1023,7 @@ void fadump_cleanup(void)
        /* Invalidate the registration only if dump is active. */
        if (fw_dump.dump_active) {
                init_fadump_mem_struct(&fdm,
-                       fdm_active->cpu_state_data.destination_address);
+                       be64_to_cpu(fdm_active->cpu_state_data.destination_address));
                fadump_invalidate_dump(&fdm);
        }
 }
@@ -1063,7 +1063,7 @@ static void fadump_invalidate_release_mem(void)
                return;
        }
 
-       destination_address = fdm_active->cpu_state_data.destination_address;
+       destination_address = be64_to_cpu(fdm_active->cpu_state_data.destination_address);
        fadump_cleanup();
        mutex_unlock(&fadump_mutex);
 
@@ -1183,31 +1183,31 @@ static int fadump_region_show(struct seq_file *m, void *private)
        seq_printf(m,
                        "CPU : [%#016llx-%#016llx] %#llx bytes, "
                        "Dumped: %#llx\n",
-                       fdm_ptr->cpu_state_data.destination_address,
-                       fdm_ptr->cpu_state_data.destination_address +
-                       fdm_ptr->cpu_state_data.source_len - 1,
-                       fdm_ptr->cpu_state_data.source_len,
-                       fdm_ptr->cpu_state_data.bytes_dumped);
+                       be64_to_cpu(fdm_ptr->cpu_state_data.destination_address),
+                       be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) +
+                       be64_to_cpu(fdm_ptr->cpu_state_data.source_len) - 1,
+                       be64_to_cpu(fdm_ptr->cpu_state_data.source_len),
+                       be64_to_cpu(fdm_ptr->cpu_state_data.bytes_dumped));
        seq_printf(m,
                        "HPTE: [%#016llx-%#016llx] %#llx bytes, "
                        "Dumped: %#llx\n",
-                       fdm_ptr->hpte_region.destination_address,
-                       fdm_ptr->hpte_region.destination_address +
-                       fdm_ptr->hpte_region.source_len - 1,
-                       fdm_ptr->hpte_region.source_len,
-                       fdm_ptr->hpte_region.bytes_dumped);
+                       be64_to_cpu(fdm_ptr->hpte_region.destination_address),
+                       be64_to_cpu(fdm_ptr->hpte_region.destination_address) +
+                       be64_to_cpu(fdm_ptr->hpte_region.source_len) - 1,
+                       be64_to_cpu(fdm_ptr->hpte_region.source_len),
+                       be64_to_cpu(fdm_ptr->hpte_region.bytes_dumped));
        seq_printf(m,
                        "DUMP: [%#016llx-%#016llx] %#llx bytes, "
                        "Dumped: %#llx\n",
-                       fdm_ptr->rmr_region.destination_address,
-                       fdm_ptr->rmr_region.destination_address +
-                       fdm_ptr->rmr_region.source_len - 1,
-                       fdm_ptr->rmr_region.source_len,
-                       fdm_ptr->rmr_region.bytes_dumped);
+                       be64_to_cpu(fdm_ptr->rmr_region.destination_address),
+                       be64_to_cpu(fdm_ptr->rmr_region.destination_address) +
+                       be64_to_cpu(fdm_ptr->rmr_region.source_len) - 1,
+                       be64_to_cpu(fdm_ptr->rmr_region.source_len),
+                       be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped));
 
        if (!fdm_active ||
                (fw_dump.reserve_dump_area_start ==
-               fdm_ptr->cpu_state_data.destination_address))
+               be64_to_cpu(fdm_ptr->cpu_state_data.destination_address)))
                goto out;
 
        /* Dump is active. Show reserved memory region. */
@@ -1215,10 +1215,10 @@ static int fadump_region_show(struct seq_file *m, void *private)
                        "    : [%#016llx-%#016llx] %#llx bytes, "
                        "Dumped: %#llx\n",
                        (unsigned long long)fw_dump.reserve_dump_area_start,
-                       fdm_ptr->cpu_state_data.destination_address - 1,
-                       fdm_ptr->cpu_state_data.destination_address -
+                       be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) - 1,
+                       be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) -
                        fw_dump.reserve_dump_area_start,
-                       fdm_ptr->cpu_state_data.destination_address -
+                       be64_to_cpu(fdm_ptr->cpu_state_data.destination_address) -
                        fw_dump.reserve_dump_area_start);
 out:
        if (fdm_active)
index a10642a0d861cd6a5a80cbe796b36e97d37f9df9..a83cf5ef64883669efebe3271c5ed77a0479e737 100644 (file)
@@ -428,10 +428,10 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
                ppc_md.tce_flush(tbl);
 }
 
-int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
-                struct scatterlist *sglist, int nelems,
-                unsigned long mask, enum dma_data_direction direction,
-                struct dma_attrs *attrs)
+int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
+                    struct scatterlist *sglist, int nelems,
+                    unsigned long mask, enum dma_data_direction direction,
+                    struct dma_attrs *attrs)
 {
        dma_addr_t dma_next = 0, dma_addr;
        struct scatterlist *s, *outs, *segstart;
@@ -539,7 +539,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 
        DBG("mapped %d elements:\n", outcount);
 
-       /* For the sake of iommu_unmap_sg, we clear out the length in the
+       /* For the sake of ppc_iommu_unmap_sg, we clear out the length in the
         * next entry of the sglist if we didn't fill the list completely
         */
        if (outcount < incount) {
@@ -572,9 +572,9 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 }
 
 
-void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
-               int nelems, enum dma_data_direction direction,
-               struct dma_attrs *attrs)
+void ppc_iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+                       int nelems, enum dma_data_direction direction,
+                       struct dma_attrs *attrs)
 {
        struct scatterlist *sg;
 
index 8eb857f216c1ba1404a4e3b153a2077b7f7880c4..c14383575fe8f68ed4224ef097acfbbf93189cc2 100644 (file)
@@ -466,7 +466,7 @@ static inline void check_stack_overflow(void)
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
        long sp;
 
-       sp = __get_SP() & (THREAD_SIZE-1);
+       sp = current_stack_pointer() & (THREAD_SIZE-1);
 
        /* check for stack overflow: is there less than 2KB free? */
        if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
index 7ce26d45777ef1d5497ab778eff937b11204aef3..0d432194c01825286b4f629ad1637cdbeed32a22 100644 (file)
@@ -114,3 +114,7 @@ _GLOBAL(longjmp)
        mtlr    r0
        mr      r3,r4
        blr
+
+_GLOBAL(current_stack_pointer)
+       PPC_LL  r3,0(r1)
+       blr
index 155013da27e05cb801ba961b102d41f3edbfb48d..b15194e2c5fc55ca934dba97fe4863b2c273baa5 100644 (file)
@@ -266,13 +266,3 @@ int pcibus_to_node(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibus_to_node);
 #endif
-
-static void quirk_radeon_32bit_msi(struct pci_dev *dev)
-{
-       struct pci_dn *pdn = pci_get_pdn(dev);
-
-       if (pdn)
-               pdn->force_32bit_msi = true;
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x68f2, quirk_radeon_32bit_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0xaa68, quirk_radeon_32bit_msi);
index c4dfff6c2719ca5bfc6a17c9faf204fa836cad7f..202963ee013a81c76b62dcbd6bc59c0c8cbc9844 100644 (file)
@@ -41,3 +41,5 @@ EXPORT_SYMBOL(giveup_spe);
 #ifdef CONFIG_EPAPR_PARAVIRT
 EXPORT_SYMBOL(epapr_hypercall_start);
 #endif
+
+EXPORT_SYMBOL(current_stack_pointer);
index aa1df89c8b2a8165411d588af394ea85f833265b..923cd2daba89d88f37299b0a0f19803cdacb2532 100644 (file)
@@ -1545,7 +1545,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
                tsk = current;
        if (sp == 0) {
                if (tsk == current)
-                       asm("mr %0,1" : "=r" (sp));
+                       sp = current_stack_pointer();
                else
                        sp = tsk->thread.ksp;
        }
index c168337aef9dd3ccc48c70a00a41d19f4bc3f92d..7c55b86206b3f7ed4ad2846437e5867f97b21861 100644 (file)
@@ -66,6 +66,11 @@ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
+#ifdef CONFIG_EEH
+       if (pdn->edev && pdn->edev->pe &&
+           (pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
+               return PCIBIOS_SET_FAILED;
+#endif
 
        addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
        buid = pdn->phb->buid;
@@ -90,9 +95,6 @@ static int rtas_pci_read_config(struct pci_bus *bus,
        struct device_node *busdn, *dn;
        struct pci_dn *pdn;
        bool found = false;
-#ifdef CONFIG_EEH
-       struct eeh_dev *edev;
-#endif
        int ret;
 
        /* Search only direct children of the bus */
@@ -109,11 +111,6 @@ static int rtas_pci_read_config(struct pci_bus *bus,
 
        if (!found)
                return PCIBIOS_DEVICE_NOT_FOUND;
-#ifdef CONFIG_EEH
-       edev = of_node_to_eeh_dev(dn);
-       if (edev && edev->pe && edev->pe->state & EEH_PE_RESET)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-#endif
 
        ret = rtas_read_config(pdn, where, size, val);
        if (*val == EEH_IO_ERROR_VALUE(size) &&
@@ -132,6 +129,11 @@ int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val)
                return PCIBIOS_DEVICE_NOT_FOUND;
        if (!config_access_valid(pdn, where))
                return PCIBIOS_BAD_REGISTER_NUMBER;
+#ifdef CONFIG_EEH
+       if (pdn->edev && pdn->edev->pe &&
+           (pdn->edev->pe->state & EEH_PE_CFG_BLOCKED))
+               return PCIBIOS_SET_FAILED;
+#endif
 
        addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
        buid = pdn->phb->buid;
@@ -155,10 +157,6 @@ static int rtas_pci_write_config(struct pci_bus *bus,
        struct device_node *busdn, *dn;
        struct pci_dn *pdn;
        bool found = false;
-#ifdef CONFIG_EEH
-       struct eeh_dev *edev;
-#endif
-       int ret;
 
        /* Search only direct children of the bus */
        busdn = pci_bus_to_OF_node(bus);
@@ -173,14 +171,8 @@ static int rtas_pci_write_config(struct pci_bus *bus,
 
        if (!found)
                return PCIBIOS_DEVICE_NOT_FOUND;
-#ifdef CONFIG_EEH
-       edev = of_node_to_eeh_dev(dn);
-       if (edev && edev->pe && (edev->pe->state & EEH_PE_RESET))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-#endif
-       ret = rtas_write_config(pdn, where, size, val);
 
-       return ret;
+       return rtas_write_config(pdn, where, size, val);
 }
 
 static struct pci_ops rtas_pci_ops = {
index cd07d79ad21cac659d9966fb09e2ac41fa13a374..4f3cfe1b6a336e506fcb114af430a8080f4a949a 100644 (file)
@@ -522,36 +522,36 @@ void __init setup_system(void)
        smp_release_cpus();
 #endif
 
-       printk("Starting Linux PPC64 %s\n", init_utsname()->version);
+       pr_info("Starting Linux PPC64 %s\n", init_utsname()->version);
 
-       printk("-----------------------------------------------------\n");
-       printk("ppc64_pft_size    = 0x%llx\n", ppc64_pft_size);
-       printk("phys_mem_size     = 0x%llx\n", memblock_phys_mem_size());
+       pr_info("-----------------------------------------------------\n");
+       pr_info("ppc64_pft_size    = 0x%llx\n", ppc64_pft_size);
+       pr_info("phys_mem_size     = 0x%llx\n", memblock_phys_mem_size());
 
        if (ppc64_caches.dline_size != 0x80)
-               printk("dcache_line_size  = 0x%x\n", ppc64_caches.dline_size);
+               pr_info("dcache_line_size  = 0x%x\n", ppc64_caches.dline_size);
        if (ppc64_caches.iline_size != 0x80)
-               printk("icache_line_size  = 0x%x\n", ppc64_caches.iline_size);
+               pr_info("icache_line_size  = 0x%x\n", ppc64_caches.iline_size);
 
-       printk("cpu_features      = 0x%016lx\n", cur_cpu_spec->cpu_features);
-       printk("  possible        = 0x%016lx\n", CPU_FTRS_POSSIBLE);
-       printk("  always          = 0x%016lx\n", CPU_FTRS_ALWAYS);
-       printk("cpu_user_features = 0x%08x 0x%08x\n", cur_cpu_spec->cpu_user_features,
+       pr_info("cpu_features      = 0x%016lx\n", cur_cpu_spec->cpu_features);
+       pr_info("  possible        = 0x%016lx\n", CPU_FTRS_POSSIBLE);
+       pr_info("  always          = 0x%016lx\n", CPU_FTRS_ALWAYS);
+       pr_info("cpu_user_features = 0x%08x 0x%08x\n", cur_cpu_spec->cpu_user_features,
                cur_cpu_spec->cpu_user_features2);
-       printk("mmu_features      = 0x%08x\n", cur_cpu_spec->mmu_features);
-       printk("firmware_features = 0x%016lx\n", powerpc_firmware_features);
+       pr_info("mmu_features      = 0x%08x\n", cur_cpu_spec->mmu_features);
+       pr_info("firmware_features = 0x%016lx\n", powerpc_firmware_features);
 
 #ifdef CONFIG_PPC_STD_MMU_64
        if (htab_address)
-               printk("htab_address      = 0x%p\n", htab_address);
+               pr_info("htab_address      = 0x%p\n", htab_address);
 
-       printk("htab_hash_mask    = 0x%lx\n", htab_hash_mask);
+       pr_info("htab_hash_mask    = 0x%lx\n", htab_hash_mask);
 #endif
 
        if (PHYSICAL_START > 0)
-               printk("physical_start    = 0x%llx\n",
+               pr_info("physical_start    = 0x%llx\n",
                       (unsigned long long)PHYSICAL_START);
-       printk("-----------------------------------------------------\n");
+       pr_info("-----------------------------------------------------\n");
 
        DBG(" <- setup_system()\n");
 }
index 3d30ef1038e5e285f1fe43f1d85ace5b1c3463b4..ea43a347a1044c37a800d7f78487e6f238078c94 100644 (file)
@@ -50,7 +50,7 @@ void save_stack_trace(struct stack_trace *trace)
 {
        unsigned long sp;
 
-       asm("mr %0,1" : "=r" (sp));
+       sp = current_stack_pointer();
 
        save_context_stack(trace, sp, current, 1);
 }
index 23eb9a9441bdad612481a7d1b2fcf12dd17a7ed3..c62be60c727485cce5108fcf4770b28f42129eee 100644 (file)
@@ -30,8 +30,8 @@
 V_FUNCTION_BEGIN(__kernel_getcpu)
   .cfi_startproc
        mfspr   r5,SPRN_SPRG_VDSO_READ
-       cmpdi   cr0,r3,0
-       cmpdi   cr1,r4,0
+       cmpwi   cr0,r3,0
+       cmpwi   cr1,r4,0
        clrlwi  r6,r5,16
        rlwinm  r7,r5,16,31-15,31-0
        beq     cr0,1f
index 0f9939e693df6b8422a7b87301f7dcd250816c34..5a236f082c78386a47b9b415f98f619e8e615688 100644 (file)
@@ -99,8 +99,6 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
        u64 vsid;
        int psize, ssize;
 
-       slb->esid = (ea & ESID_MASK) | SLB_ESID_V;
-
        switch (REGION_ID(ea)) {
        case USER_REGION_ID:
                pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea);
@@ -133,6 +131,7 @@ int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
        vsid |= mmu_psize_defs[psize].sllp |
                ((ssize == MMU_SEGSIZE_1T) ? SLB_VSID_B_1T : 0);
 
+       slb->esid = (ea & (ssize == MMU_SEGSIZE_1T ? ESID_MASK_1T : ESID_MASK)) | SLB_ESID_V;
        slb->vsid = vsid;
 
        return 0;
index 7e70ae968e5f9df04cdf372e06ebea433be34d5b..6a4a5fcb9730877e0f089add23c6c522a41cc72c 100644 (file)
@@ -517,8 +517,6 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
        for (i = 0; i < num_hugepd; i++, hpdp++)
                hpdp->pd = 0;
 
-       tlb->need_flush = 1;
-
 #ifdef CONFIG_PPC_FSL_BOOK3E
        hugepd_free(tlb, hugepte);
 #else
index cad68ff8eca5322990cfa56ee46003ae530e1d39..415a51b028b952c14b4f1ad3c88dd79b73657142 100644 (file)
@@ -103,7 +103,7 @@ unsigned long __max_low_memory = MAX_LOW_MEM;
 /*
  * Check for command-line options that affect what MMU_init will do.
  */
-void MMU_setup(void)
+void __init MMU_setup(void)
 {
        /* Check for nobats option (used in mapin_ram). */
        if (strstr(boot_command_line, "nobats")) {
index 649666d5d1c20520ed554a3375c11393660871e1..b9d1dfdbe5bbaa5bdaad7446ec945aa909f2befd 100644 (file)
@@ -8,6 +8,8 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#define pr_fmt(fmt) "numa: " fmt
+
 #include <linux/threads.h>
 #include <linux/bootmem.h>
 #include <linux/init.h>
@@ -1153,6 +1155,22 @@ static int __init early_numa(char *p)
 }
 early_param("numa", early_numa);
 
+static bool topology_updates_enabled = true;
+
+static int __init early_topology_updates(char *p)
+{
+       if (!p)
+               return 0;
+
+       if (!strcmp(p, "off")) {
+               pr_info("Disabling topology updates\n");
+               topology_updates_enabled = false;
+       }
+
+       return 0;
+}
+early_param("topology_updates", early_topology_updates);
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * Find the node associated with a hot added memory section for
@@ -1442,8 +1460,11 @@ static long hcall_vphn(unsigned long cpu, __be32 *associativity)
        long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
        u64 flags = 1;
        int hwcpu = get_hard_smp_processor_id(cpu);
+       int i;
 
        rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
+       for (i = 0; i < 6; i++)
+               retbuf[i] = cpu_to_be64(retbuf[i]);
        vphn_unpack_associativity(retbuf, associativity);
 
        return rc;
@@ -1488,11 +1509,14 @@ static int update_cpu_topology(void *data)
        cpu = smp_processor_id();
 
        for (update = data; update; update = update->next) {
+               int new_nid = update->new_nid;
                if (cpu != update->cpu)
                        continue;
 
-               unmap_cpu_from_node(update->cpu);
-               map_cpu_to_node(update->cpu, update->new_nid);
+               unmap_cpu_from_node(cpu);
+               map_cpu_to_node(cpu, new_nid);
+               set_cpu_numa_node(cpu, new_nid);
+               set_cpu_numa_mem(cpu, local_memory_node(new_nid));
                vdso_getcpu_init();
        }
 
@@ -1539,6 +1563,9 @@ int arch_update_cpu_topology(void)
        struct device *dev;
        int weight, new_nid, i = 0;
 
+       if (!prrn_enabled && !vphn_enabled)
+               return 0;
+
        weight = cpumask_weight(&cpu_associativity_changes_mask);
        if (!weight)
                return 0;
@@ -1592,6 +1619,15 @@ int arch_update_cpu_topology(void)
                cpu = cpu_last_thread_sibling(cpu);
        }
 
+       pr_debug("Topology update for the following CPUs:\n");
+       if (cpumask_weight(&updated_cpus)) {
+               for (ud = &updates[0]; ud; ud = ud->next) {
+                       pr_debug("cpu %d moving from node %d "
+                                         "to %d\n", ud->cpu,
+                                         ud->old_nid, ud->new_nid);
+               }
+       }
+
        /*
         * In cases where we have nothing to update (because the updates list
         * is too short or because the new topology is same as the old one),
@@ -1800,8 +1836,12 @@ static const struct file_operations topology_ops = {
 
 static int topology_update_init(void)
 {
-       start_topology_update();
-       proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops);
+       /* Do not poll for changes if disabled at boot */
+       if (topology_updates_enabled)
+               start_topology_update();
+
+       if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
+               return -ENOMEM;
 
        return 0;
 }
index 8d7bda94d1969b2325073315875a05545922b0fc..ded0ea1afde4021578d21d2e969318ea6cd046eb 100644 (file)
@@ -682,6 +682,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
        slice_convert(mm, mask, psize);
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
 /*
  * is_hugepage_only_range() is used by generic code to verify whether
  * a normal mmap mapping (non hugetlbfs) is valid on a given area.
@@ -726,4 +727,4 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 #endif
        return !slice_check_fit(mask, available);
 }
-
+#endif
index 6c8710dd90c9b12d7e746113b43fdc9231c8b8b3..dba34088da2896187a390ee720af2a4a65bc3216 100644 (file)
@@ -417,11 +417,6 @@ static int h_24x7_event_add(struct perf_event *event, int flags)
        return 0;
 }
 
-static int h_24x7_event_idx(struct perf_event *event)
-{
-       return 0;
-}
-
 static struct pmu h_24x7_pmu = {
        .task_ctx_nr = perf_invalid_context,
 
@@ -433,7 +428,6 @@ static struct pmu h_24x7_pmu = {
        .start       = h_24x7_event_start,
        .stop        = h_24x7_event_stop,
        .read        = h_24x7_event_update,
-       .event_idx   = h_24x7_event_idx,
 };
 
 static int hv_24x7_init(void)
index 15fc76c930227e7b2cff67cfc00889de1e4d6c97..a051fe946c63a2eecc88b041e0ce67f14f329b4b 100644 (file)
@@ -246,11 +246,6 @@ static int h_gpci_event_init(struct perf_event *event)
        return 0;
 }
 
-static int h_gpci_event_idx(struct perf_event *event)
-{
-       return 0;
-}
-
 static struct pmu h_gpci_pmu = {
        .task_ctx_nr = perf_invalid_context,
 
@@ -262,7 +257,6 @@ static struct pmu h_gpci_pmu = {
        .start       = h_gpci_event_start,
        .stop        = h_gpci_event_stop,
        .read        = h_gpci_event_update,
-       .event_idx   = h_gpci_event_idx,
 };
 
 static int hv_gpci_init(void)
index 2b90ff8a93bea7542fee7d89f99d3439bf9e0d13..c7c8720aa39f5ebfedeb9bb3d925ce16992fd63a 100644 (file)
@@ -621,8 +621,9 @@ static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
        if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
                return dma_direct_ops.map_sg(dev, sg, nents, direction, attrs);
        else
-               return iommu_map_sg(dev, cell_get_iommu_table(dev), sg, nents,
-                                   device_to_mask(dev), direction, attrs);
+               return ppc_iommu_map_sg(dev, cell_get_iommu_table(dev), sg,
+                                       nents, device_to_mask(dev),
+                                       direction, attrs);
 }
 
 static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
@@ -632,8 +633,8 @@ static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
        if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
                dma_direct_ops.unmap_sg(dev, sg, nents, direction, attrs);
        else
-               iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents, direction,
-                              attrs);
+               ppc_iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents,
+                                  direction, attrs);
 }
 
 static int dma_fixed_dma_supported(struct device *dev, u64 mask)
index 426814a2ede34db7f83c6405a123aa4317a3008c..eba9cb10619ceac9108d09036b97528d2a03e45f 100644 (file)
@@ -373,7 +373,7 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe)
         * moving forward, we have to return operational
         * state during PE reset.
         */
-       if (pe->state & EEH_PE_RESET) {
+       if (pe->state & EEH_PE_CFG_BLOCKED) {
                result = (EEH_STATE_MMIO_ACTIVE  |
                          EEH_STATE_DMA_ACTIVE   |
                          EEH_STATE_MMIO_ENABLED |
index 3e89cbf5588547660ed9f3543735c6b644ae77e9..1d19e7917d7fc5e59cb2e4945c30a90be8e9e50a 100644 (file)
@@ -168,6 +168,26 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag)
                return ret;
        }
 
+       /*
+        * If the PE contains any one of following adapters, the
+        * PCI config space can't be accessed when dumping EEH log.
+        * Otherwise, we will run into fenced PHB caused by shortage
+        * of outbound credits in the adapter. The PCI config access
+        * should be blocked until PE reset. MMIO access is dropped
+        * by hardware certainly. In order to drop PCI config requests,
+        * one more flag (EEH_PE_CFG_RESTRICTED) is introduced, which
+        * will be checked in the backend for PE state retrival. If
+        * the PE becomes frozen for the first time and the flag has
+        * been set for the PE, we will set EEH_PE_CFG_BLOCKED for
+        * that PE to block its config space.
+        *
+        * Broadcom Austin 4-ports NICs (14e4:1657)
+        * Broadcom Shiner 2-ports 10G NICs (14e4:168e)
+        */
+       if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) ||
+           (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e))
+               edev->pe->state |= EEH_PE_CFG_RESTRICTED;
+
        /*
         * Cache the PE primary bus, which can't be fetched when
         * full hotplug is in progress. In that case, all child
@@ -383,6 +403,39 @@ static int powernv_eeh_err_inject(struct eeh_pe *pe, int type, int func,
        return ret;
 }
 
+static inline bool powernv_eeh_cfg_blocked(struct device_node *dn)
+{
+       struct eeh_dev *edev = of_node_to_eeh_dev(dn);
+
+       if (!edev || !edev->pe)
+               return false;
+
+       if (edev->pe->state & EEH_PE_CFG_BLOCKED)
+               return true;
+
+       return false;
+}
+
+static int powernv_eeh_read_config(struct device_node *dn,
+                                  int where, int size, u32 *val)
+{
+       if (powernv_eeh_cfg_blocked(dn)) {
+               *val = 0xFFFFFFFF;
+               return PCIBIOS_SET_FAILED;
+       }
+
+       return pnv_pci_cfg_read(dn, where, size, val);
+}
+
+static int powernv_eeh_write_config(struct device_node *dn,
+                                   int where, int size, u32 val)
+{
+       if (powernv_eeh_cfg_blocked(dn))
+               return PCIBIOS_SET_FAILED;
+
+       return pnv_pci_cfg_write(dn, where, size, val);
+}
+
 /**
  * powernv_eeh_next_error - Retrieve next EEH error to handle
  * @pe: Affected PE
@@ -440,8 +493,8 @@ static struct eeh_ops powernv_eeh_ops = {
        .get_log                = powernv_eeh_get_log,
        .configure_bridge       = powernv_eeh_configure_bridge,
        .err_inject             = powernv_eeh_err_inject,
-       .read_config            = pnv_pci_cfg_read,
-       .write_config           = pnv_pci_cfg_write,
+       .read_config            = powernv_eeh_read_config,
+       .write_config           = powernv_eeh_write_config,
        .next_error             = powernv_eeh_next_error,
        .restore_config         = powernv_eeh_restore_config
 };
index 5e1ed1575aabe23c245edcdff06433cfb0a62327..b322bfb51343f65fdfe76d265cdcb76928011d21 100644 (file)
@@ -57,7 +57,7 @@ static void print_hmi_event_info(struct OpalHMIEvent *hmi_evt)
        };
 
        /* Print things out */
-       if (hmi_evt->version != OpalHMIEvt_V1) {
+       if (hmi_evt->version < OpalHMIEvt_V1) {
                pr_err("HMI Interrupt, Unknown event version %d !\n",
                        hmi_evt->version);
                return;
index dd2c285ad1708d755b5a1950558566149e837839..e4169d68cb3289a98230a7547b0ef24e3fb5c260 100644 (file)
@@ -191,7 +191,6 @@ static ssize_t lpc_debug_read(struct file *filp, char __user *ubuf,
 {
        struct lpc_debugfs_entry *lpc = filp->private_data;
        u32 data, pos, len, todo;
-       __be32 bedata;
        int rc;
 
        if (!access_ok(VERIFY_WRITE, ubuf, count))
@@ -214,18 +213,57 @@ static ssize_t lpc_debug_read(struct file *filp, char __user *ubuf,
                                len = 2;
                }
                rc = opal_lpc_read(opal_lpc_chip_id, lpc->lpc_type, pos,
-                                  &bedata, len);
+                                  &data, len);
                if (rc)
                        return -ENXIO;
-               data = be32_to_cpu(bedata);
+
+               /*
+                * Now there is some trickery with the data returned by OPAL
+                * as it's the desired data right justified in a 32-bit BE
+                * word.
+                *
+                * This is a very bad interface and I'm to blame for it :-(
+                *
+                * So we can't just apply a 32-bit swap to what comes from OPAL,
+                * because user space expects the *bytes* to be in their proper
+                * respective positions (ie, LPC position).
+                *
+                * So what we really want to do here is to shift data right
+                * appropriately on a LE kernel.
+                *
+                * IE. If the LPC transaction has bytes B0, B1, B2 and B3 in that
+                * order, we have in memory written to by OPAL at the "data"
+                * pointer:
+                *
+                *               Bytes:      OPAL "data"   LE "data"
+                *   32-bit:   B0 B1 B2 B3   B0B1B2B3      B3B2B1B0
+                *   16-bit:   B0 B1         0000B0B1      B1B00000
+                *    8-bit:   B0            000000B0      B0000000
+                *
+                * So a BE kernel will have the leftmost of the above in the MSB
+                * and rightmost in the LSB and can just then "cast" the u32 "data"
+                * down to the appropriate quantity and write it.
+                *
+                * However, an LE kernel can't. It doesn't need to swap because a
+                * load from data followed by a store to user are going to preserve
+                * the byte ordering which is the wire byte order which is what the
+                * user wants, but in order to "crop" to the right size, we need to
+                * shift right first.
+                */
                switch(len) {
                case 4:
                        rc = __put_user((u32)data, (u32 __user *)ubuf);
                        break;
                case 2:
+#ifdef __LITTLE_ENDIAN__
+                       data >>= 16;
+#endif
                        rc = __put_user((u16)data, (u16 __user *)ubuf);
                        break;
                default:
+#ifdef __LITTLE_ENDIAN__
+                       data >>= 24;
+#endif
                        rc = __put_user((u8)data, (u8 __user *)ubuf);
                        break;
                }
@@ -265,12 +303,31 @@ static ssize_t lpc_debug_write(struct file *filp, const char __user *ubuf,
                        else if (todo > 1 && (pos & 1) == 0)
                                len = 2;
                }
+
+               /*
+                * Similarly to the read case, we have some trickery here but
+                * it's different to handle. We need to pass the value to OPAL in
+                * a register whose layout depends on the access size. We want
+                * to reproduce the memory layout of the user, however we aren't
+                * doing a load from user and a store to another memory location
+                * which would achieve that. Here we pass the value to OPAL via
+                * a register which is expected to contain the "BE" interpretation
+                * of the byte sequence. IE: for a 32-bit access, byte 0 should be
+                * in the MSB. So here we *do* need to byteswap on LE.
+                *
+                *           User bytes:    LE "data"  OPAL "data"
+                *  32-bit:  B0 B1 B2 B3    B3B2B1B0   B0B1B2B3
+                *  16-bit:  B0 B1          0000B1B0   0000B0B1
+                *   8-bit:  B0             000000B0   000000B0
+                */
                switch(len) {
                case 4:
                        rc = __get_user(data, (u32 __user *)ubuf);
+                       data = cpu_to_be32(data);
                        break;
                case 2:
                        rc = __get_user(data, (u16 __user *)ubuf);
+                       data = cpu_to_be16(data);
                        break;
                default:
                        rc = __get_user(data, (u8 __user *)ubuf);
index 10271ad1fac45129599cb8ac20c5bf6c94c20462..4ab67ef7abc9d8a0d07079795f3801b3d62e035f 100644 (file)
@@ -20,7 +20,9 @@
 
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/of_platform.h>
 #include <asm/opal.h>
+#include <asm/machdep.h>
 
 static DEFINE_MUTEX(opal_sensor_mutex);
 
@@ -64,3 +66,21 @@ out:
        return ret;
 }
 EXPORT_SYMBOL_GPL(opal_get_sensor_data);
+
+static __init int opal_sensor_init(void)
+{
+       struct platform_device *pdev;
+       struct device_node *sensor;
+
+       sensor = of_find_node_by_path("/ibm,opal/sensors");
+       if (!sensor) {
+               pr_err("Opal node 'sensors' not found\n");
+               return -ENODEV;
+       }
+
+       pdev = of_platform_device_create(sensor, "opal-sensor", NULL);
+       of_node_put(sensor);
+
+       return PTR_ERR_OR_ZERO(pdev);
+}
+machine_subsys_initcall(powernv, opal_sensor_init);
index e9e2450c1fddd3bb6988084fb38039a8b3c3300b..feb549aa3eea98ee5369f6c3ecf5087dc871b4d8 100644 (file)
@@ -58,7 +58,7 @@ END_FTR_SECTION(0, 1);                                                \
  */
 
 #define OPAL_CALL(name, token)         \
- _GLOBAL(name);                                \
+ _GLOBAL_TOC(name);                    \
        mflr    r0;                     \
        std     r0,16(r1);              \
        li      r0,token;               \
index b642b0562f5aca3e8ecde20d3f86738e621f9092..d019b081df9d846177c76b5c923b7e0a41e12fe8 100644 (file)
@@ -194,6 +194,27 @@ static int __init opal_register_exception_handlers(void)
         * fwnmi area at 0x7000 to provide the glue space to OPAL
         */
        glue = 0x7000;
+
+       /*
+        * Check if we are running on newer firmware that exports
+        * OPAL_HANDLE_HMI token. If yes, then don't ask OPAL to patch
+        * the HMI interrupt and we catch it directly in Linux.
+        *
+        * For older firmware (i.e currently released POWER8 System Firmware
+        * as of today <= SV810_087), we fallback to old behavior and let OPAL
+        * patch the HMI vector and handle it inside OPAL firmware.
+        *
+        * For newer firmware (in development/yet to be released) we will
+        * start catching/handling HMI directly in Linux.
+        */
+       if (!opal_check_token(OPAL_HANDLE_HMI)) {
+               pr_info("opal: Old firmware detected, OPAL handles HMIs.\n");
+               opal_register_exception_handler(
+                               OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+                               0, glue);
+               glue += 128;
+       }
+
        opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
 #endif
 
index 468a0f23c7f2b5f756c1b553315793c03492c0d6..3ba435ec3dcd584e5f466b78eae18379a69d482b 100644 (file)
@@ -1509,7 +1509,6 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
                                  unsigned int is_64, struct msi_msg *msg)
 {
        struct pnv_ioda_pe *pe = pnv_ioda_get_pe(dev);
-       struct pci_dn *pdn = pci_get_pdn(dev);
        unsigned int xive_num = hwirq - phb->msi_base;
        __be32 data;
        int rc;
@@ -1523,7 +1522,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev,
                return -ENXIO;
 
        /* Force 32-bit MSI on some broken devices */
-       if (pdn && pdn->force_32bit_msi)
+       if (dev->no_64bit_msi)
                is_64 = 0;
 
        /* Assign XIVE to PE */
@@ -1997,7 +1996,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
        if (is_kdump_kernel()) {
                pr_info("  Issue PHB reset ...\n");
                ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL);
-               ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET);
+               ioda_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE);
        }
 
        /* Configure M64 window */
index b3ca77ddf36dfbd07de81feb5015b27bd675c009..4b20f2c6b3b24ba950d3ea10014e0b1fffbfc0b6 100644 (file)
@@ -50,7 +50,6 @@ static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        struct pnv_phb *phb = hose->private_data;
-       struct pci_dn *pdn = pci_get_pdn(pdev);
        struct msi_desc *entry;
        struct msi_msg msg;
        int hwirq;
@@ -60,7 +59,7 @@ static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        if (WARN_ON(!phb) || !phb->msi_bmp.bitmap)
                return -ENODEV;
 
-       if (pdn && pdn->force_32bit_msi && !phb->msi32_support)
+       if (pdev->no_64bit_msi && !phb->msi32_support)
                return -ENODEV;
 
        list_for_each_entry(entry, &pdev->msi_list, list) {
@@ -505,7 +504,7 @@ static bool pnv_pci_cfg_check(struct pci_controller *hose,
        edev = of_node_to_eeh_dev(dn);
        if (edev) {
                if (edev->pe &&
-                   (edev->pe->state & EEH_PE_RESET))
+                   (edev->pe->state & EEH_PE_CFG_BLOCKED))
                        return false;
 
                if (edev->mode & EEH_DEV_REMOVED)
index fdf01b660d5930cd31c4f246c7d4f4659aad6690..c22bb1b4beb878c50bbe2f3c8d4dba7fd5d142f1 100644 (file)
 #include <asm/rtas.h>
 
 struct cc_workarea {
-       u32     drc_index;
-       u32     zero;
-       u32     name_offset;
-       u32     prop_length;
-       u32     prop_offset;
+       __be32  drc_index;
+       __be32  zero;
+       __be32  name_offset;
+       __be32  prop_length;
+       __be32  prop_offset;
 };
 
 void dlpar_free_cc_property(struct property *prop)
@@ -49,11 +49,11 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa)
        if (!prop)
                return NULL;
 
-       name = (char *)ccwa + ccwa->name_offset;
+       name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
        prop->name = kstrdup(name, GFP_KERNEL);
 
-       prop->length = ccwa->prop_length;
-       value = (char *)ccwa + ccwa->prop_offset;
+       prop->length = be32_to_cpu(ccwa->prop_length);
+       value = (char *)ccwa + be32_to_cpu(ccwa->prop_offset);
        prop->value = kmemdup(value, prop->length, GFP_KERNEL);
        if (!prop->value) {
                dlpar_free_cc_property(prop);
@@ -79,7 +79,7 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa,
        if (!dn)
                return NULL;
 
-       name = (char *)ccwa + ccwa->name_offset;
+       name = (char *)ccwa + be32_to_cpu(ccwa->name_offset);
        dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name);
        if (!dn->full_name) {
                kfree(dn);
@@ -126,7 +126,7 @@ void dlpar_free_cc_nodes(struct device_node *dn)
 #define CALL_AGAIN     -2
 #define ERR_CFG_USE     -9003
 
-struct device_node *dlpar_configure_connector(u32 drc_index,
+struct device_node *dlpar_configure_connector(__be32 drc_index,
                                              struct device_node *parent)
 {
        struct device_node *dn;
@@ -382,7 +382,7 @@ static int dlpar_online_cpu(struct device_node *dn)
                        BUG_ON(get_cpu_current_state(cpu)
                                        != CPU_STATE_OFFLINE);
                        cpu_maps_update_done();
-                       rc = cpu_up(cpu);
+                       rc = device_online(get_cpu_device(cpu));
                        if (rc)
                                goto out;
                        cpu_maps_update_begin();
@@ -414,7 +414,7 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
        if (!parent)
                return -ENODEV;
 
-       dn = dlpar_configure_connector(drc_index, parent);
+       dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
        if (!dn)
                return -EINVAL;
 
@@ -467,7 +467,7 @@ static int dlpar_offline_cpu(struct device_node *dn)
                        if (get_cpu_current_state(cpu) == CPU_STATE_ONLINE) {
                                set_preferred_offline_state(cpu, CPU_STATE_OFFLINE);
                                cpu_maps_update_done();
-                               rc = cpu_down(cpu);
+                               rc = device_offline(get_cpu_device(cpu));
                                if (rc)
                                        goto out;
                                cpu_maps_update_begin();
index b174fa751d260bcebd20b0af83cf5e13ba28158a..5c375f93c669cac9cdbc5dc028e72e297f7713de 100644 (file)
@@ -247,7 +247,7 @@ static int pseries_add_processor(struct device_node *np)
        unsigned int cpu;
        cpumask_var_t candidate_mask, tmp;
        int err = -ENOSPC, len, nthreads, i;
-       const u32 *intserv;
+       const __be32 *intserv;
 
        intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len);
        if (!intserv)
@@ -293,7 +293,7 @@ static int pseries_add_processor(struct device_node *np)
        for_each_cpu(cpu, tmp) {
                BUG_ON(cpu_present(cpu));
                set_cpu_present(cpu, true);
-               set_hard_smp_processor_id(cpu, *intserv++);
+               set_hard_smp_processor_id(cpu, be32_to_cpu(*intserv++));
        }
        err = 0;
 out_unlock:
index de1ec54a2a57924ac2f3c29a6d43153e773e8aee..e32e00976a949a8a1ed07210f1f7b892595dc499 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/mm.h>
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
-#include <linux/sched.h>       /* for show_stack */
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
@@ -168,7 +167,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
                        printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                        printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
                        printk("\ttce val = 0x%llx\n", tce );
-                       show_stack(current, (unsigned long *)__get_SP());
+                       dump_stack();
                }
 
                tcenum++;
@@ -257,7 +256,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                printk("\tnpages  = 0x%llx\n", (u64)npages);
                printk("\ttce[0] val = 0x%llx\n", tcep[0]);
-               show_stack(current, (unsigned long *)__get_SP());
+               dump_stack();
        }
        return ret;
 }
@@ -273,7 +272,7 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages
                        printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
                        printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                        printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
-                       show_stack(current, (unsigned long *)__get_SP());
+                       dump_stack();
                }
 
                tcenum++;
@@ -292,7 +291,7 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
                printk("\trc      = %lld\n", rc);
                printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                printk("\tnpages  = 0x%llx\n", (u64)npages);
-               show_stack(current, (unsigned long *)__get_SP());
+               dump_stack();
        }
 }
 
@@ -307,7 +306,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
                printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc);
                printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
                printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
-               show_stack(current, (unsigned long *)__get_SP());
+               dump_stack();
        }
 
        return tce_ret;
index 8c509d5397c6e9a6f54c19ec569612e0005f96e2..f6880d2a40fbeffed49375c1cfcb174ce47ccb86 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/trace.h>
 #include <asm/firmware.h>
 #include <asm/plpar_wrappers.h>
+#include <asm/fadump.h>
 
 #include "pseries.h"
 
@@ -247,8 +248,17 @@ static void pSeries_lpar_hptab_clear(void)
        }
 
 #ifdef __LITTLE_ENDIAN__
-       /* Reset exceptions to big endian */
-       if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
+       /*
+        * Reset exceptions to big endian.
+        *
+        * FIXME this is a hack for kexec, we need to reset the exception
+        * endian before starting the new kernel and this is a convenient place
+        * to do it.
+        *
+        * This is also called on boot when a fadump happens. In that case we
+        * must not change the exception endian mode.
+        */
+       if (firmware_has_feature(FW_FEATURE_SET_MODE) && !is_fadump_active()) {
                long rc;
 
                rc = pseries_big_endian_exceptions();
index 8ab5add4ac824f43c6a6b299b24ed15bf0deafb2..8b909e94fd9a10bbee407c2e1a04df7320e93a71 100644 (file)
@@ -420,7 +420,7 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
         */
 again:
        if (type == PCI_CAP_ID_MSI) {
-               if (pdn->force_32bit_msi) {
+               if (pdev->no_64bit_msi) {
                        rc = rtas_change_msi(pdn, RTAS_CHANGE_32MSI_FN, nvec);
                        if (rc < 0) {
                                /*
index 361add62abf1089d4cd65aa28c72264a040de635..1796c5438cc661d22a3e026dae6000891f9773d7 100644 (file)
@@ -56,7 +56,8 @@ extern void hvc_vio_init_early(void);
 /* Dynamic logical Partitioning/Mobility */
 extern void dlpar_free_cc_nodes(struct device_node *);
 extern void dlpar_free_cc_property(struct property *);
-extern struct device_node *dlpar_configure_connector(u32, struct device_node *);
+extern struct device_node *dlpar_configure_connector(__be32,
+                                               struct device_node *);
 extern int dlpar_attach_node(struct device_node *);
 extern int dlpar_detach_node(struct device_node *);
 
index de40b48b460e83a8aaec5168c8a4a1f025d8dd38..da08ed08815751cec116164e8f6d3e828bda9fd4 100644 (file)
@@ -361,7 +361,7 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, struct platform_device *dev,
        cascade_data->virq = virt_msir;
        msi->cascade_array[irq_index] = cascade_data;
 
-       ret = request_irq(virt_msir, fsl_msi_cascade, 0,
+       ret = request_irq(virt_msir, fsl_msi_cascade, IRQF_NO_THREAD,
                          "fsl-msi-cascade", cascade_data);
        if (ret) {
                dev_err(&dev->dev, "failed to request_irq(%d), ret = %d\n",
index 0c75214b6f9220d433f8ea88776041694f744add..73b64c73505bee493809dccbf886af0108c1129f 100644 (file)
@@ -145,59 +145,64 @@ void msi_bitmap_free(struct msi_bitmap *bmp)
 
 #ifdef CONFIG_MSI_BITMAP_SELFTEST
 
-#define check(x)       \
-       if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__);
-
 static void __init test_basics(void)
 {
        struct msi_bitmap bmp;
-       int i, size = 512;
+       int rc, i, size = 512;
 
        /* Can't allocate a bitmap of 0 irqs */
-       check(msi_bitmap_alloc(&bmp, 0, NULL) != 0);
+       WARN_ON(msi_bitmap_alloc(&bmp, 0, NULL) == 0);
 
        /* of_node may be NULL */
-       check(0 == msi_bitmap_alloc(&bmp, size, NULL));
+       WARN_ON(msi_bitmap_alloc(&bmp, size, NULL));
 
        /* Should all be free by default */
-       check(0 == bitmap_find_free_region(bmp.bitmap, size,
-                                          get_count_order(size)));
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
        bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
        /* With no node, there's no msi-available-ranges, so expect > 0 */
-       check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+       WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
 
        /* Should all still be free */
-       check(0 == bitmap_find_free_region(bmp.bitmap, size,
-                                          get_count_order(size)));
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
        bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
        /* Check we can fill it up and then no more */
        for (i = 0; i < size; i++)
-               check(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
+               WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
 
-       check(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
+       WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
 
        /* Should all be allocated */
-       check(bitmap_find_free_region(bmp.bitmap, size, 0) < 0);
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, 0) >= 0);
 
        /* And if we free one we can then allocate another */
        msi_bitmap_free_hwirqs(&bmp, size / 2, 1);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2);
+       WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) != size / 2);
+
+       /* Free most of them for the alignment tests */
+       msi_bitmap_free_hwirqs(&bmp, 3, size - 3);
 
        /* Check we get a naturally aligned offset */
-       check(msi_bitmap_alloc_hwirqs(&bmp, 2) % 2 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 4) % 4 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 8) % 8 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 9) % 16 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 3) % 4 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 7) % 8 == 0);
-       check(msi_bitmap_alloc_hwirqs(&bmp, 121) % 128 == 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 2);
+       WARN_ON(rc < 0 && rc % 2 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 4);
+       WARN_ON(rc < 0 && rc % 4 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 8);
+       WARN_ON(rc < 0 && rc % 8 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 9);
+       WARN_ON(rc < 0 && rc % 16 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 3);
+       WARN_ON(rc < 0 && rc % 4 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 7);
+       WARN_ON(rc < 0 && rc % 8 != 0);
+       rc = msi_bitmap_alloc_hwirqs(&bmp, 121);
+       WARN_ON(rc < 0 && rc % 128 != 0);
 
        msi_bitmap_free(&bmp);
 
-       /* Clients may check bitmap == NULL for "not-allocated" */
-       check(bmp.bitmap == NULL);
+       /* Clients may WARN_ON bitmap == NULL for "not-allocated" */
+       WARN_ON(bmp.bitmap != NULL);
 
        kfree(bmp.bitmap);
 }
@@ -219,14 +224,13 @@ static void __init test_of_node(void)
        of_node_init(&of_node);
        of_node.full_name = node_name;
 
-       check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
+       WARN_ON(msi_bitmap_alloc(&bmp, size, &of_node));
 
        /* No msi-available-ranges, so expect > 0 */
-       check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+       WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
 
        /* Should all still be free */
-       check(0 == bitmap_find_free_region(bmp.bitmap, size,
-                                          get_count_order(size)));
+       WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
        bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
        /* Now create a fake msi-available-ranges property */
@@ -240,11 +244,11 @@ static void __init test_of_node(void)
        of_node.properties = &prop;
 
        /* msi-available-ranges, so expect == 0 */
-       check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0);
+       WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp));
 
        /* Check we got the expected result */
-       check(0 == bitmap_parselist(expected_str, expected, size));
-       check(bitmap_equal(expected, bmp.bitmap, size));
+       WARN_ON(bitmap_parselist(expected_str, expected, size));
+       WARN_ON(!bitmap_equal(expected, bmp.bitmap, size));
 
        msi_bitmap_free(&bmp);
        kfree(bmp.bitmap);
index b988b5addf864a581ff8c36e177379c32ba92518..c8efbb37d6e076ab123a3d5d8066f58edd36acd8 100644 (file)
@@ -293,10 +293,10 @@ static inline void disable_surveillance(void)
        args.token = rtas_token("set-indicator");
        if (args.token == RTAS_UNKNOWN_SERVICE)
                return;
-       args.nargs = 3;
-       args.nret = 1;
+       args.nargs = cpu_to_be32(3);
+       args.nret = cpu_to_be32(1);
        args.rets = &args.args[3];
-       args.args[0] = SURVEILLANCE_TOKEN;
+       args.args[0] = cpu_to_be32(SURVEILLANCE_TOKEN);
        args.args[1] = 0;
        args.args[2] = 0;
        enter_rtas(__pa(&args));
index 9d94fdd9f525e9503d7f39f0a71c89cacaf53349..9432d0f202ef20a6bd5ee8300d8f1ac654029c60 100644 (file)
@@ -35,7 +35,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
@@ -245,6 +244,7 @@ CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -252,11 +252,6 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT_IPV4=m
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -270,6 +265,7 @@ CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
+CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -286,9 +282,6 @@ CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
-CONFIG_NF_NAT_IPV6=m
-CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_NET_SCTPPROBE=m
 CONFIG_RDS=m
@@ -374,14 +367,13 @@ CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
 CONFIG_SCSI_ENCLOSURE=m
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
 CONFIG_ISCSI_TCP=m
-CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
 CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=m
@@ -427,7 +419,6 @@ CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
 CONFIG_VHOST_NET=m
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -481,14 +472,14 @@ CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 CONFIG_JFS_SECURITY=y
 CONFIG_JFS_STATISTICS=y
-CONFIG_XFS_FS=m
+CONFIG_XFS_FS=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_XFS_RT=y
 CONFIG_XFS_DEBUG=y
 CONFIG_GFS2_FS=m
 CONFIG_OCFS2_FS=m
-CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS=y
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_NILFS2_FS=m
 CONFIG_FANOTIFY=y
@@ -574,7 +565,6 @@ CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_RT_MUTEX_TESTER=y
 CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
@@ -600,8 +590,13 @@ CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_LATENCYTOP=y
 CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-# CONFIG_KPROBE_EVENT is not set
+CONFIG_UPROBE_EVENT=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
 CONFIG_KPROBES_SANITY_TEST=y
@@ -609,7 +604,10 @@ CONFIG_RBTREE_TEST=y
 CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_TEST_STRING_HELPERS=y
+CONFIG_TEST_KSTRTOX=y
 CONFIG_DMA_API_DEBUG=y
+CONFIG_TEST_BPF=m
 # CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
@@ -673,12 +671,6 @@ CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
-CONFIG_XZ_DEC_X86=y
-CONFIG_XZ_DEC_POWERPC=y
-CONFIG_XZ_DEC_IA64=y
-CONFIG_XZ_DEC_ARM=y
-CONFIG_XZ_DEC_ARMTHUMB=y
-CONFIG_XZ_DEC_SPARC=y
 CONFIG_CORDIC=m
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
index 90f514baa37d0b091eda7e04d45d4be45be3cd67..219dca6ea92684485e56d68c4b6d04719217a4f2 100644 (file)
@@ -35,7 +35,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
@@ -243,6 +242,7 @@ CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -250,11 +250,6 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT_IPV4=m
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -268,6 +263,7 @@ CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
+CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -284,9 +280,6 @@ CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
-CONFIG_NF_NAT_IPV6=m
-CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_NET_SCTPPROBE=m
 CONFIG_RDS=m
@@ -371,14 +364,13 @@ CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
 CONFIG_SCSI_ENCLOSURE=m
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
 CONFIG_ISCSI_TCP=m
-CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
 CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=m
@@ -424,7 +416,6 @@ CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
 CONFIG_VHOST_NET=m
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -478,13 +469,13 @@ CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 CONFIG_JFS_SECURITY=y
 CONFIG_JFS_STATISTICS=y
-CONFIG_XFS_FS=m
+CONFIG_XFS_FS=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_XFS_RT=y
 CONFIG_GFS2_FS=m
 CONFIG_OCFS2_FS=m
-CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS=y
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_NILFS2_FS=m
 CONFIG_FANOTIFY=y
@@ -626,12 +617,6 @@ CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
-CONFIG_XZ_DEC_X86=y
-CONFIG_XZ_DEC_POWERPC=y
-CONFIG_XZ_DEC_IA64=y
-CONFIG_XZ_DEC_ARM=y
-CONFIG_XZ_DEC_ARMTHUMB=y
-CONFIG_XZ_DEC_SPARC=y
 CONFIG_CORDIC=m
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
index 13559d32af696b9917d9c84678beea19f498461f..822c2f2e0c25d4adac076344e9ceafc971196082 100644 (file)
@@ -33,7 +33,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
@@ -241,6 +240,7 @@ CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_NAT_IPV4=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -248,11 +248,6 @@ CONFIG_IP_NF_MATCH_RPFILTER=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_NF_NAT_IPV4=m
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -266,6 +261,7 @@ CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NF_TABLES_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
+CONFIG_NF_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_MATCH_AH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
@@ -282,9 +278,6 @@ CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
-CONFIG_NF_NAT_IPV6=m
-CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_IP6_NF_TARGET_NPT=m
 CONFIG_NF_TABLES_BRIDGE=m
 CONFIG_NET_SCTPPROBE=m
 CONFIG_RDS=m
@@ -369,14 +362,13 @@ CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
 CONFIG_SCSI_ENCLOSURE=m
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SAS_LIBSAS=m
 CONFIG_SCSI_SRP_ATTRS=m
 CONFIG_ISCSI_TCP=m
-CONFIG_LIBFCOE=m
 CONFIG_SCSI_DEBUG=m
 CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=m
@@ -422,7 +414,6 @@ CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
 CONFIG_VHOST_NET=m
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -476,13 +467,13 @@ CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 CONFIG_JFS_SECURITY=y
 CONFIG_JFS_STATISTICS=y
-CONFIG_XFS_FS=m
+CONFIG_XFS_FS=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_XFS_RT=y
 CONFIG_GFS2_FS=m
 CONFIG_OCFS2_FS=m
-CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS=y
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_NILFS2_FS=m
 CONFIG_FANOTIFY=y
@@ -550,8 +541,11 @@ CONFIG_TIMER_STATS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-# CONFIG_KPROBE_EVENT is not set
+CONFIG_UPROBE_EVENT=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
@@ -618,12 +612,6 @@ CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
-CONFIG_XZ_DEC_X86=y
-CONFIG_XZ_DEC_POWERPC=y
-CONFIG_XZ_DEC_IA64=y
-CONFIG_XZ_DEC_ARM=y
-CONFIG_XZ_DEC_ARMTHUMB=y
-CONFIG_XZ_DEC_SPARC=y
 CONFIG_CORDIC=m
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
index e376789f2d8daa6ac407ca2c103d2f49be69ad6f..9d63051ebec42556cc545835cdb5cb6fe4d94f7a 100644 (file)
@@ -22,8 +22,8 @@ CONFIG_HZ_100=y
 CONFIG_CRASH_DUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SECCOMP is not set
-# CONFIG_IUCV is not set
 CONFIG_NET=y
+# CONFIG_IUCV is not set
 CONFIG_ATM=y
 CONFIG_ATM_LANE=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -36,9 +36,9 @@ CONFIG_ENCLOSURE_SERVICES=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_ENCLOSURE=y
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_SRP_ATTRS=y
 CONFIG_ZFCP=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
@@ -75,12 +75,6 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 # CONFIG_FTRACE is not set
 # CONFIG_STRICT_DEVMEM is not set
-CONFIG_XZ_DEC_X86=y
-CONFIG_XZ_DEC_POWERPC=y
-CONFIG_XZ_DEC_IA64=y
-CONFIG_XZ_DEC_ARM=y
-CONFIG_XZ_DEC_ARMTHUMB=y
-CONFIG_XZ_DEC_SPARC=y
 # CONFIG_PFAULT is not set
 # CONFIG_S390_HYPFS_FS is not set
 # CONFIG_VIRTUALIZATION is not set
index fab35a8efa4f924ee2b69a3a3c9e32e73ebaa9a6..785c5f24d6f9e5c7b99d71a11b7eee9dc6e670e2 100644 (file)
@@ -92,10 +92,10 @@ CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_FC_ATTRS=y
 CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=y
 CONFIG_NETDEVICES=y
@@ -164,14 +164,13 @@ CONFIG_CRYPTO_CMAC=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_CRCT10DIF=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
-CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
index cd6b9ee7b69c928118e9bce7c8691651a79a9b52..6ad9013c67e72342e50fcda2c25e9b9215fe41c5 100644 (file)
 #include <asm/page.h>
 #include <asm/pci_io.h>
 
-void *xlate_dev_mem_ptr(unsigned long phys);
 #define xlate_dev_mem_ptr xlate_dev_mem_ptr
-void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+void *xlate_dev_mem_ptr(phys_addr_t phys);
+#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
+void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
 
 /*
  * Convert a virtual cached pointer to an uncached pointer
@@ -60,11 +61,6 @@ static inline void iounmap(volatile void __iomem *addr)
 #define __raw_writel   zpci_write_u32
 #define __raw_writeq   zpci_write_u64
 
-#define readb_relaxed  readb
-#define readw_relaxed  readw
-#define readl_relaxed  readl
-#define readq_relaxed  readq
-
 #endif /* CONFIG_PCI */
 
 #include <asm-generic/io.h>
index 940ac49198db1dd406b99944f51183df869cd420..4197c89c52d4cc3349e2ad0cbe4d2c87d2e51e5b 100644 (file)
 #define __NR_seccomp           348
 #define __NR_getrandom         349
 #define __NR_memfd_create      350
-#define NR_syscalls 351
+#define __NR_bpf               351
+#define NR_syscalls 352
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index faf6caa510dcedb862ad65be7108e1042a754939..c4f7a3d655b8025c78511e43f153a469599a34a5 100644 (file)
@@ -217,3 +217,4 @@ COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int,
 COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
 COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
 COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
+COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
index 51d14fe5eb9a318349876eb376b359695770a0a2..ca1cabb3a96c1ba98062ce399803805cb9743858 100644 (file)
@@ -121,6 +121,8 @@ unsigned long __kprobes prepare_ftrace_return(unsigned long parent,
 {
        struct ftrace_graph_ent trace;
 
+       if (unlikely(ftrace_graph_is_dead()))
+               goto out;
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                goto out;
        ip = (ip & PSW_ADDR_INSN) - MCOUNT_INSN_SIZE;
index dd1c24ceda50245978c97e13c5b992db3139f329..3f51cf4e8f020e1b972eaa15ef4640ebe028e4e3 100644 (file)
@@ -54,12 +54,8 @@ void s390_handle_mcck(void)
         */
        local_irq_save(flags);
        local_mcck_disable();
-       /*
-        * Ummm... Does this make sense at all? Copying the percpu struct
-        * and then zapping it one statement later?
-        */
-       memcpy(&mcck, this_cpu_ptr(&cpu_mcck), sizeof(mcck));
-       memset(&mcck, 0, sizeof(struct mcck_struct));
+       mcck = *this_cpu_ptr(&cpu_mcck);
+       memset(this_cpu_ptr(&cpu_mcck), 0, sizeof(mcck));
        clear_cpu_flag(CIF_MCCK_PENDING);
        local_mcck_enable();
        local_irq_restore(flags);
index 08e761318c17d786d2e40ce85fcd0b631fecc731..b878f12a9597201476ffda4aabaf676f66735b99 100644 (file)
@@ -1411,11 +1411,6 @@ static void cpumsf_pmu_del(struct perf_event *event, int flags)
        perf_pmu_enable(event->pmu);
 }
 
-static int cpumsf_pmu_event_idx(struct perf_event *event)
-{
-       return event->hw.idx;
-}
-
 CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC, PERF_EVENT_CPUM_SF);
 CPUMF_EVENT_ATTR(SF, SF_CYCLES_BASIC_DIAG, PERF_EVENT_CPUM_SF_DIAG);
 
@@ -1458,7 +1453,6 @@ static struct pmu cpumf_sampling = {
        .stop         = cpumsf_pmu_stop,
        .read         = cpumsf_pmu_read,
 
-       .event_idx    = cpumsf_pmu_event_idx,
        .attr_groups  = cpumsf_pmu_attr_groups,
 };
 
index 6fe886ac2db596a81f67a80e69e4f5f54609c45f..9f7087fd58de5f47251fafe7fe6530d6e3fea163 100644 (file)
@@ -359,3 +359,4 @@ SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
 SYSCALL(sys_seccomp,sys_seccomp,compat_sys_seccomp)
 SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom)
 SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */
+SYSCALL(sys_bpf,sys_bpf,compat_sys_bpf)
index 956f4f7a591c18b1cd6f03129e0c0bc46750a7b6..f6b3cd056ec22c1c28b908c4cefc46bc4a4e2099 100644 (file)
@@ -5,13 +5,13 @@
  *    Author(s): Jan Willeke,
  */
 
-#include <linux/kprobes.h>
 #include <linux/uaccess.h>
 #include <linux/uprobes.h>
 #include <linux/compat.h>
 #include <linux/kdebug.h>
 #include <asm/switch_to.h>
 #include <asm/facility.h>
+#include <asm/kprobes.h>
 #include <asm/dis.h>
 #include "entry.h"
 
index 48c2206a39561ea9373bb3fb8ec48297b3509867..5eec9afbb5b5852cdcbf2a50685a43030f3af5f7 100644 (file)
@@ -19,6 +19,7 @@
        .type  __kernel_clock_gettime,@function
 __kernel_clock_gettime:
        .cfi_startproc
+       ahi     %r15,-16
        basr    %r5,0
 0:     al      %r5,21f-0b(%r5)                 /* get &_vdso_data */
        chi     %r2,__CLOCK_REALTIME_COARSE
@@ -34,8 +35,8 @@ __kernel_clock_gettime:
 1:     l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     1b
-       stcke   24(%r15)                        /* Store TOD clock */
-       lm      %r0,%r1,25(%r15)
+       stcke   0(%r15)                         /* Store TOD clock */
+       lm      %r0,%r1,1(%r15)
        s       %r0,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,2f
@@ -70,6 +71,7 @@ __kernel_clock_gettime:
 8:     st      %r2,0(%r3)                      /* store tp->tv_sec */
        st      %r1,4(%r3)                      /* store tp->tv_nsec */
        lhi     %r2,0
+       ahi     %r15,16
        br      %r14
 
        /* CLOCK_MONOTONIC_COARSE */
@@ -96,8 +98,8 @@ __kernel_clock_gettime:
 11:    l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     11b
-       stcke   24(%r15)                        /* Store TOD clock */
-       lm      %r0,%r1,25(%r15)
+       stcke   0(%r15)                         /* Store TOD clock */
+       lm      %r0,%r1,1(%r15)
        s       %r0,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,12f
@@ -132,11 +134,13 @@ __kernel_clock_gettime:
 17:    st      %r2,0(%r3)                      /* store tp->tv_sec */
        st      %r1,4(%r3)                      /* store tp->tv_nsec */
        lhi     %r2,0
+       ahi     %r15,16
        br      %r14
 
        /* Fallback to system call */
 19:    lhi     %r1,__NR_clock_gettime
        svc     0
+       ahi     %r15,16
        br      %r14
 
 20:    .long   1000000000
index 60def5f562db532e4c014687e38dcefdf1344383..719de6186b206e17c60b973b1661e57cf1505747 100644 (file)
@@ -19,6 +19,7 @@
        .type  __kernel_gettimeofday,@function
 __kernel_gettimeofday:
        .cfi_startproc
+       ahi     %r15,-16
        basr    %r5,0
 0:     al      %r5,13f-0b(%r5)                 /* get &_vdso_data */
 1:     ltr     %r3,%r3                         /* check if tz is NULL */
@@ -29,30 +30,30 @@ __kernel_gettimeofday:
        l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     1b
-       stcke   24(%r15)                        /* Store TOD clock */
-       lm      %r0,%r1,25(%r15)
+       stcke   0(%r15)                         /* Store TOD clock */
+       lm      %r0,%r1,1(%r15)
        s       %r0,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        sl      %r1,__VDSO_XTIME_STAMP+4(%r5)
        brc     3,3f
        ahi     %r0,-1
 3:     ms      %r0,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
-       st      %r0,24(%r15)
+       st      %r0,0(%r15)
        l       %r0,__VDSO_TK_MULT(%r5)
        ltr     %r1,%r1
        mr      %r0,%r0
        jnm     4f
        a       %r0,__VDSO_TK_MULT(%r5)
-4:     al      %r0,24(%r15)
+4:     al      %r0,0(%r15)
        al      %r0,__VDSO_XTIME_NSEC(%r5)      /*  + xtime */
        al      %r1,__VDSO_XTIME_NSEC+4(%r5)
        brc     12,5f
        ahi     %r0,1
-5:     mvc     24(4,%r15),__VDSO_XTIME_SEC+4(%r5)
+5:     mvc     0(4,%r15),__VDSO_XTIME_SEC+4(%r5)
        cl      %r4,__VDSO_UPD_COUNT+4(%r5)     /* check update counter */
        jne     1b
        l       %r4,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
        srdl    %r0,0(%r4)                      /*  >> tk->shift */
-       l       %r4,24(%r15)                    /* get tv_sec from stack */
+       l       %r4,0(%r15)                     /* get tv_sec from stack */
        basr    %r5,0
 6:     ltr     %r0,%r0
        jnz     7f
@@ -71,6 +72,7 @@ __kernel_gettimeofday:
 9:     srl     %r0,6
        st      %r0,4(%r2)                      /* store tv->tv_usec */
 10:    slr     %r2,%r2
+       ahi     %r15,16
        br      %r14
 11:    .long   1000000000
 12:    .long   274877907
index 9d9761f8e11035761c3b1143c6486a9fc52193c6..7699e735ae28ed726f4725ee97619119e1aa5e1e 100644 (file)
@@ -19,6 +19,7 @@
        .type  __kernel_clock_gettime,@function
 __kernel_clock_gettime:
        .cfi_startproc
+       aghi    %r15,-16
        larl    %r5,_vdso_data
        cghi    %r2,__CLOCK_REALTIME_COARSE
        je      4f
@@ -37,10 +38,10 @@ __kernel_clock_gettime:
 0:     lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
        tmll    %r4,0x0001                      /* pending update ? loop */
        jnz     0b
-       stcke   48(%r15)                        /* Store TOD clock */
+       stcke   0(%r15)                         /* Store TOD clock */
        lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
        lg      %r0,__VDSO_WTOM_SEC(%r5)
-       lg      %r1,49(%r15)
+       lg      %r1,1(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
        alg     %r1,__VDSO_WTOM_NSEC(%r5)
@@ -56,6 +57,7 @@ __kernel_clock_gettime:
 2:     stg     %r0,0(%r3)                      /* store tp->tv_sec */
        stg     %r1,8(%r3)                      /* store tp->tv_nsec */
        lghi    %r2,0
+       aghi    %r15,16
        br      %r14
 
        /* CLOCK_MONOTONIC_COARSE */
@@ -82,9 +84,9 @@ __kernel_clock_gettime:
 5:     lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
        tmll    %r4,0x0001                      /* pending update ? loop */
        jnz     5b
-       stcke   48(%r15)                        /* Store TOD clock */
+       stcke   0(%r15)                         /* Store TOD clock */
        lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
-       lg      %r1,49(%r15)
+       lg      %r1,1(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
        alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
@@ -101,6 +103,7 @@ __kernel_clock_gettime:
 7:     stg     %r0,0(%r3)                      /* store tp->tv_sec */
        stg     %r1,8(%r3)                      /* store tp->tv_nsec */
        lghi    %r2,0
+       aghi    %r15,16
        br      %r14
 
        /* CLOCK_THREAD_CPUTIME_ID for this thread */
@@ -134,11 +137,13 @@ __kernel_clock_gettime:
        slgr    %r4,%r0                         /* r4 = tv_nsec */
        stg     %r4,8(%r3)
        lghi    %r2,0
+       aghi    %r15,16
        br      %r14
 
        /* Fallback to system call */
 12:    lghi    %r1,__NR_clock_gettime
        svc     0
+       aghi    %r15,16
        br      %r14
 
 13:    .quad   1000000000
index 7a344995a97fd21246de5554f09674449db8f2fd..6ce46707663cc9d8248e5feedb71a0268d9629f2 100644 (file)
@@ -19,6 +19,7 @@
        .type  __kernel_gettimeofday,@function
 __kernel_gettimeofday:
        .cfi_startproc
+       aghi    %r15,-16
        larl    %r5,_vdso_data
 0:     ltgr    %r3,%r3                         /* check if tz is NULL */
        je      1f
@@ -28,8 +29,8 @@ __kernel_gettimeofday:
        lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
        tmll    %r4,0x0001                      /* pending update ? loop */
        jnz     0b
-       stcke   48(%r15)                        /* Store TOD clock */
-       lg      %r1,49(%r15)
+       stcke   0(%r15)                         /* Store TOD clock */
+       lg      %r1,1(%r15)
        sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
        msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
        alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
@@ -50,6 +51,7 @@ __kernel_gettimeofday:
        srlg    %r0,%r0,6
        stg     %r0,8(%r2)                      /* store tv->tv_usec */
 4:     lghi    %r2,0
+       aghi    %r15,16
        br      %r14
 5:     .quad   1000000000
        .long   274877907
index 416f2a323ba5e3a3d59a806a921751749ccb7a46..7f0089d9a4aa47ef86e7691502281c140ee637c3 100644 (file)
@@ -66,7 +66,11 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
        clock = S390_lowcore.last_update_clock;
        asm volatile(
                "       stpt    %0\n"   /* Store current cpu timer value */
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+               "       stckf   %1"     /* Store current tod clock value */
+#else
                "       stck    %1"     /* Store current tod clock value */
+#endif
                : "=m" (S390_lowcore.last_update_timer),
                  "=m" (S390_lowcore.last_update_clock));
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
index c5d64a0997193f77d0cd56ce2e7ac2c62c0b3f28..ae90e1ae3607052c6ac4403f815d33061fcaf604 100644 (file)
@@ -4,7 +4,7 @@
  *    Copyright IBM Corp. 2014
  */
 
-#include <linux/kprobes.h>
+#include <asm/kprobes.h>
 #include <asm/dis.h>
 
 int probe_is_prohibited_opcode(u16 *insn)
index 2a2e35416d2fe7fc4a835795f5c64bca444f1de4..2eb34bdfc61311f54fe0d29be01bdf0819fa18c7 100644 (file)
@@ -176,7 +176,7 @@ static int is_swapped(unsigned long addr)
  * For swapped prefix pages a new buffer is returned that contains a copy of
  * the absolute memory. The buffer size is maximum one page large.
  */
-void *xlate_dev_mem_ptr(unsigned long addr)
+void *xlate_dev_mem_ptr(phys_addr_t addr)
 {
        void *bounce = (void *) addr;
        unsigned long size;
@@ -197,7 +197,7 @@ void *xlate_dev_mem_ptr(unsigned long addr)
 /*
  * Free converted buffer for /dev/mem access (if necessary)
  */
-void unxlate_dev_mem_ptr(unsigned long addr, void *buf)
+void unxlate_dev_mem_ptr(phys_addr_t addr, void *buf)
 {
        if ((void *) addr != buf)
                free_page((unsigned long) buf);
index 296b61a4af5974d59cd5692814d907614a7cf6d8..1b79ca67392fdffc2e6dd7328717267d16d87650 100644 (file)
@@ -656,7 +656,7 @@ void __gmap_zap(struct gmap *gmap, unsigned long gaddr)
        }
        pgste_set_unlock(ptep, pgste);
 out_pte:
-       pte_unmap_unlock(*ptep, ptl);
+       pte_unmap_unlock(ptep, ptl);
 }
 EXPORT_SYMBOL_GPL(__gmap_zap);
 
@@ -943,7 +943,7 @@ retry:
        }
        if (!(pte_val(*ptep) & _PAGE_INVALID) &&
             (pte_val(*ptep) & _PAGE_PROTECT)) {
-               pte_unmap_unlock(*ptep, ptl);
+               pte_unmap_unlock(ptep, ptl);
                if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) {
                        up_read(&mm->mmap_sem);
                        return -EFAULT;
@@ -974,7 +974,7 @@ retry:
                pgste_val(new) |= PGSTE_UC_BIT;
 
        pgste_set_unlock(ptep, new);
-       pte_unmap_unlock(*ptep, ptl);
+       pte_unmap_unlock(ptep, ptl);
        up_read(&mm->mmap_sem);
        return 0;
 }
index 9139d14b9c53460587b4be67de041e44e49893fe..538c10db35379dfd3b4c97fb137453609b0ded7c 100644 (file)
@@ -118,7 +118,7 @@ static struct plat_sci_port scif0_platform_data = {
 };
 
 static struct resource scif0_resources[] = {
-       DEFINE_RES_MEM(0xfffffe80, 0x100),
+       DEFINE_RES_MEM(0xfffffe80, 0x10),
        DEFINE_RES_IRQ(evt2irq(0x4e0)),
 };
 
@@ -143,7 +143,7 @@ static struct plat_sci_port scif1_platform_data = {
 };
 
 static struct resource scif1_resources[] = {
-       DEFINE_RES_MEM(0xa4000150, 0x100),
+       DEFINE_RES_MEM(0xa4000150, 0x10),
        DEFINE_RES_IRQ(evt2irq(0x900)),
 };
 
@@ -169,7 +169,7 @@ static struct plat_sci_port scif2_platform_data = {
 };
 
 static struct resource scif2_resources[] = {
-       DEFINE_RES_MEM(0xa4000140, 0x100),
+       DEFINE_RES_MEM(0xa4000140, 0x10),
        DEFINE_RES_IRQ(evt2irq(0x880)),
 };
 
index 765c1776ec9fd6e900e8c23f39e55af0bf2b316b..0e69b7e7a439ce90e2f831c173fd67d55af53be0 100644 (file)
@@ -22,7 +22,7 @@
 
 int atomic_add_return(int, atomic_t *);
 int atomic_cmpxchg(atomic_t *, int, int);
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+int atomic_xchg(atomic_t *, int);
 int __atomic_add_unless(atomic_t *, int, int);
 void atomic_set(atomic_t *, int);
 
index 32c29a133f9d4b199f1a6a4476f274fd4c0b9890..d38b52dca216273a147328cc2d0288c20c2eeba6 100644 (file)
 #ifndef __ARCH_SPARC_CMPXCHG__
 #define __ARCH_SPARC_CMPXCHG__
 
-static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
-{
-       __asm__ __volatile__("swap [%2], %0"
-                            : "=&r" (val)
-                            : "0" (val), "r" (m)
-                            : "memory");
-       return val;
-}
-
+unsigned long __xchg_u32(volatile u32 *m, u32 new);
 void __xchg_called_with_bad_pointer(void);
 
 static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
 {
        switch (size) {
        case 4:
-               return xchg_u32(ptr, x);
+               return __xchg_u32(ptr, x);
        }
        __xchg_called_with_bad_pointer();
        return x;
index 5b1b52a04ad6283fb67308d9bf84b08494870140..7e064c68c5ec8a0ab538a15947d5c44b2db0a322 100644 (file)
@@ -12,6 +12,14 @@ int dma_supported(struct device *dev, u64 mask);
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+                                 enum dma_data_direction dir)
+{
+       /* Since dma_{alloc,free}_noncoherent() allocated coherent memory, this
+        * routine can be a nop.
+        */
+}
+
 extern struct dma_map_ops *dma_ops;
 extern struct dma_map_ops *leon_dma_ops;
 extern struct dma_map_ops pci32_dma_ops;
index 9f532902627c4412b08968645eda5667975b104e..407ac14295f43ec01e93141e1673794d5e3f024c 100644 (file)
@@ -4,10 +4,6 @@
 #include <linux/kernel.h>
 #include <linux/ioport.h>  /* struct resource */
 
-#define readb_relaxed(__addr)  readb(__addr)
-#define readw_relaxed(__addr)  readw(__addr)
-#define readl_relaxed(__addr)  readl(__addr)
-
 #define IO_SPACE_LIMIT 0xffffffff
 
 #define memset_io(d,c,sz)     _memset_io(d,c,sz)
index 80b54b326d4983f5c2ccdd48557276d459c5fb62..9b672be70dda6e84802853b0cd6acf7d5aa13e08 100644 (file)
@@ -101,6 +101,7 @@ static inline void __raw_writeq(u64 q, const volatile void __iomem *addr)
  * the cache by using ASI_PHYS_BYPASS_EC_E_L
  */
 #define readb readb
+#define readb_relaxed readb
 static inline u8 readb(const volatile void __iomem *addr)
 {      u8 ret;
 
@@ -112,6 +113,7 @@ static inline u8 readb(const volatile void __iomem *addr)
 }
 
 #define readw readw
+#define readw_relaxed readw
 static inline u16 readw(const volatile void __iomem *addr)
 {      u16 ret;
 
@@ -124,6 +126,7 @@ static inline u16 readw(const volatile void __iomem *addr)
 }
 
 #define readl readl
+#define readl_relaxed readl
 static inline u32 readl(const volatile void __iomem *addr)
 {      u32 ret;
 
@@ -136,6 +139,7 @@ static inline u32 readl(const volatile void __iomem *addr)
 }
 
 #define readq readq
+#define readq_relaxed readq
 static inline u64 readq(const volatile void __iomem *addr)
 {      u64 ret;
 
@@ -148,6 +152,7 @@ static inline u64 readq(const volatile void __iomem *addr)
 }
 
 #define writeb writeb
+#define writeb_relaxed writeb
 static inline void writeb(u8 b, volatile void __iomem *addr)
 {
        __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
@@ -157,6 +162,7 @@ static inline void writeb(u8 b, volatile void __iomem *addr)
 }
 
 #define writew writew
+#define writew_relaxed writew
 static inline void writew(u16 w, volatile void __iomem *addr)
 {
        __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
@@ -166,6 +172,7 @@ static inline void writew(u16 w, volatile void __iomem *addr)
 }
 
 #define writel writel
+#define writel_relaxed writel
 static inline void writel(u32 l, volatile void __iomem *addr)
 {
        __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
@@ -175,6 +182,7 @@ static inline void writel(u32 l, volatile void __iomem *addr)
 }
 
 #define writeq writeq
+#define writeq_relaxed writeq
 static inline void writeq(u64 q, volatile void __iomem *addr)
 {
        __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
@@ -183,7 +191,6 @@ static inline void writeq(u64 q, volatile void __iomem *addr)
                             : "memory");
 }
 
-
 #define inb inb
 static inline u8 inb(unsigned long addr)
 {
@@ -264,11 +271,6 @@ static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned l
        outsl((unsigned long __force)port, buf, count);
 }
 
-#define readb_relaxed(__addr)  readb(__addr)
-#define readw_relaxed(__addr)  readw(__addr)
-#define readl_relaxed(__addr)  readl(__addr)
-#define readq_relaxed(__addr)  readq(__addr)
-
 /* Valid I/O Space regions are anywhere, because each PCI bus supported
  * can live in an arbitrary area of the physical address range.
  */
index f34682430fcf476c90276f60b6f1e8e12733b8bb..2e3a4add8591b61455af1730e3667d1f26c0f6fa 100644 (file)
@@ -62,7 +62,8 @@ struct linux_mem_p1275 {
 /* You must call prom_init() before using any of the library services,
  * preferably as early as possible.  Pass it the romvec pointer.
  */
-void prom_init(void *cif_handler, void *cif_stack);
+void prom_init(void *cif_handler);
+void prom_init_report(void);
 
 /* Boot argument acquisition, returns the boot command line string. */
 char *prom_getbootargs(void);
index f5fffd84d0dd815f74ba69e30ff15504edf98f65..29d64b1758ed2a0ceb795a07c10205e6f923e6c6 100644 (file)
@@ -48,6 +48,8 @@ unsigned long safe_compute_effective_address(struct pt_regs *, unsigned int);
 #endif
 
 #ifdef CONFIG_SPARC64
+void __init start_early_boot(void);
+
 /* unaligned_64.c */
 int handle_ldf_stq(u32 insn, struct pt_regs *regs);
 void handle_ld_nf(u32 insn, struct pt_regs *regs);
index a34ad079487e85ea8e3dbc5b314f1235ccf7cc4d..4c7c12d69bea6b78f51efcec0a0b8c0b19372a4d 100644 (file)
@@ -9,9 +9,9 @@ static inline __u16 __arch_swab16p(const __u16 *addr)
 {
        __u16 ret;
 
-       __asm__ __volatile__ ("lduha [%1] %2, %0"
+       __asm__ __volatile__ ("lduha [%2] %3, %0"
                              : "=r" (ret)
-                             : "r" (addr), "i" (ASI_PL));
+                             : "m" (*addr), "r" (addr), "i" (ASI_PL));
        return ret;
 }
 #define __arch_swab16p __arch_swab16p
@@ -20,9 +20,9 @@ static inline __u32 __arch_swab32p(const __u32 *addr)
 {
        __u32 ret;
 
-       __asm__ __volatile__ ("lduwa [%1] %2, %0"
+       __asm__ __volatile__ ("lduwa [%2] %3, %0"
                              : "=r" (ret)
-                             : "r" (addr), "i" (ASI_PL));
+                             : "m" (*addr), "r" (addr), "i" (ASI_PL));
        return ret;
 }
 #define __arch_swab32p __arch_swab32p
@@ -31,9 +31,9 @@ static inline __u64 __arch_swab64p(const __u64 *addr)
 {
        __u64 ret;
 
-       __asm__ __volatile__ ("ldxa [%1] %2, %0"
+       __asm__ __volatile__ ("ldxa [%2] %3, %0"
                              : "=r" (ret)
-                             : "r" (addr), "i" (ASI_PL));
+                             : "m" (*addr), "r" (addr), "i" (ASI_PL));
        return ret;
 }
 #define __arch_swab64p __arch_swab64p
index c842a89b11903aaa56d89ff65fd3b87658046a68..46d83842eddc6ceae0496b6397a0a04e77ce0e10 100644 (file)
 #define __NR_seccomp           346
 #define __NR_getrandom         347
 #define __NR_memfd_create      348
+#define __NR_bpf               349
 
-#define NR_syscalls            349
+#define NR_syscalls            350
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
index ebaba6167dd4e533b38d8213a8cf003f360a3939..88d322b67fac4d4be308280dd59bd52f2ecf92c0 100644 (file)
@@ -65,13 +65,10 @@ struct pause_patch_entry {
 extern struct pause_patch_entry __pause_3insn_patch,
        __pause_3insn_patch_end;
 
-void __init per_cpu_patch(void);
 void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
                             struct sun4v_1insn_patch_entry *);
 void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
                             struct sun4v_2insn_patch_entry *);
-void __init sun4v_patch(void);
-void __init boot_cpu_id_too_large(int cpu);
 extern unsigned int dcache_parity_tl1_occurred;
 extern unsigned int icache_parity_tl1_occurred;
 
index 4fdeb8040d4dd4ae0326909f6b77231dcbc3a89d..3d61fcae7ee38beaabe1b6f66bbdd781c43f1353 100644 (file)
@@ -672,14 +672,12 @@ tlb_fixup_done:
        sethi   %hi(init_thread_union), %g6
        or      %g6, %lo(init_thread_union), %g6
        ldx     [%g6 + TI_TASK], %g4
-       mov     %sp, %l6
 
        wr      %g0, ASI_P, %asi
        mov     1, %g1
        sllx    %g1, THREAD_SHIFT, %g1
        sub     %g1, (STACKFRAME_SZ + STACK_BIAS), %g1
        add     %g6, %g1, %sp
-       mov     0, %fp
 
        /* Set per-cpu pointer initially to zero, this makes
         * the boot-cpu use the in-kernel-image per-cpu areas
@@ -706,44 +704,14 @@ tlb_fixup_done:
         nop
 #endif
 
-       mov     %l6, %o1                        ! OpenPROM stack
        call    prom_init
         mov    %l7, %o0                        ! OpenPROM cif handler
 
-       /* Initialize current_thread_info()->cpu as early as possible.
-        * In order to do that accurately we have to patch up the get_cpuid()
-        * assembler sequences.  And that, in turn, requires that we know
-        * if we are on a Starfire box or not.  While we're here, patch up
-        * the sun4v sequences as well.
+       /* To create a one-register-window buffer between the kernel's
+        * initial stack and the last stack frame we use from the firmware,
+        * do the rest of the boot from a C helper function.
         */
-       call    check_if_starfire
-        nop
-       call    per_cpu_patch
-        nop
-       call    sun4v_patch
-        nop
-
-#ifdef CONFIG_SMP
-       call    hard_smp_processor_id
-        nop
-       cmp     %o0, NR_CPUS
-       blu,pt  %xcc, 1f
-        nop
-       call    boot_cpu_id_too_large
-        nop
-       /* Not reached... */
-
-1:
-#else
-       mov     0, %o0
-#endif
-       sth     %o0, [%g6 + TI_CPU]
-
-       call    prom_init_report
-        nop
-
-       /* Off we go.... */
-       call    start_kernel
+       call    start_early_boot
         nop
        /* Not reached... */
 
index b7ddcdd1dea943a9f5e768c006547a3e7737d4f7..cdbfec299f2f80a976441e854b74856a79733e78 100644 (file)
@@ -109,7 +109,6 @@ hv_cpu_startup:
        sllx            %g5, THREAD_SHIFT, %g5
        sub             %g5, (STACKFRAME_SZ + STACK_BIAS), %g5
        add             %g6, %g5, %sp
-       mov             0, %fp
 
        call            init_irqwork_curcpu
         nop
index 8f76f23dac38ec66b0afea55a5311e612f2459f0..f9c6813c132d606c2a2d138342d4ed9941165f47 100644 (file)
@@ -581,7 +581,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
 {
        unsigned long csr_reg, csr, csr_error_bits;
        irqreturn_t ret = IRQ_NONE;
-       u16 stat;
+       u32 stat;
 
        csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL;
        csr = upa_readq(csr_reg);
@@ -617,7 +617,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
                               pbm->name);
                ret = IRQ_HANDLED;
        }
-       pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat);
+       pbm->pci_ops->read(pbm->pci_bus, 0, PCI_STATUS, 2, &stat);
        if (stat & (PCI_STATUS_PARITY |
                    PCI_STATUS_SIG_TARGET_ABORT |
                    PCI_STATUS_REC_TARGET_ABORT |
@@ -625,7 +625,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
                    PCI_STATUS_SIG_SYSTEM_ERROR)) {
                printk("%s: PCI bus error, PCI_STATUS[%04x]\n",
                       pbm->name, stat);
-               pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff);
+               pbm->pci_ops->write(pbm->pci_bus, 0, PCI_STATUS, 2, 0xffff);
                ret = IRQ_HANDLED;
        }
        return ret;
index e629b83775879496a50b3db46684bb1c71fab0c4..c38d19fc27baac8821acc57cf2e42120b7d66a3e 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/cpu.h>
 #include <linux/initrd.h>
 #include <linux/module.h>
+#include <linux/start_kernel.h>
 
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -162,7 +163,7 @@ char reboot_command[COMMAND_LINE_SIZE];
 
 static struct pt_regs fake_swapper_regs = { { 0, }, 0, 0, 0, 0 };
 
-void __init per_cpu_patch(void)
+static void __init per_cpu_patch(void)
 {
        struct cpuid_patch_entry *p;
        unsigned long ver;
@@ -254,7 +255,7 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
        }
 }
 
-void __init sun4v_patch(void)
+static void __init sun4v_patch(void)
 {
        extern void sun4v_hvapi_init(void);
 
@@ -323,14 +324,25 @@ static void __init pause_patch(void)
        }
 }
 
-#ifdef CONFIG_SMP
-void __init boot_cpu_id_too_large(int cpu)
+void __init start_early_boot(void)
 {
-       prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
-                   cpu, NR_CPUS);
-       prom_halt();
+       int cpu;
+
+       check_if_starfire();
+       per_cpu_patch();
+       sun4v_patch();
+
+       cpu = hard_smp_processor_id();
+       if (cpu >= NR_CPUS) {
+               prom_printf("Serious problem, boot cpu id (%d) >= NR_CPUS (%d)\n",
+                           cpu, NR_CPUS);
+               prom_halt();
+       }
+       current_thread_info()->cpu = cpu;
+
+       prom_init_report();
+       start_kernel();
 }
-#endif
 
 /* On Ultra, we support all of the v8 capabilities. */
 unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
index 302c476413d5c5eaeb29fd5cedd529f86de2d30f..da6f1a7fc4db4713425d1927af185cb797b4c1fc 100644 (file)
@@ -816,13 +816,17 @@ void arch_send_call_function_single_ipi(int cpu)
 void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs)
 {
        clear_softint(1 << irq);
+       irq_enter();
        generic_smp_call_function_interrupt();
+       irq_exit();
 }
 
 void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs)
 {
        clear_softint(1 << irq);
+       irq_enter();
        generic_smp_call_function_single_interrupt();
+       irq_exit();
 }
 
 static void tsb_sync(void *info)
index 6a873c344bc0b970b4f0da915f4e5042763b82b9..ad0cdf497b785de84fe3f8f5e1e092a4f2de7429 100644 (file)
@@ -86,4 +86,4 @@ sys_call_table:
 /*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 /*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
 /*340*/        .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
-/*345*/        .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
+/*345*/        .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
index d9151b6490d8810b2bbd2b0f3bee53e535711375..580cde9370c9317a2cc8b6522579d5c38fa48ee3 100644 (file)
@@ -87,7 +87,7 @@ sys_call_table32:
 /*330*/        .word compat_sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
        .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
-       .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
+       .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
 
 #endif /* CONFIG_COMPAT */
 
@@ -166,4 +166,4 @@ sys_call_table:
 /*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
        .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
-       .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create
+       .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
index 737f8cbc7d56cda4e4afbdb1c7166c4fcaad3ece..88ede1d53b4c66221b9c35905abe727d1cf9b5c2 100644 (file)
@@ -109,10 +109,13 @@ startup_continue:
        brnz,pn         %g1, 1b
         nop
 
-       sethi           %hi(p1275buf), %g2
-       or              %g2, %lo(p1275buf), %g2
-       ldx             [%g2 + 0x10], %l2
-       add             %l2, -(192 + 128), %sp
+       /* Get onto temporary stack which will be in the locked
+        * kernel image.
+        */
+       sethi           %hi(tramp_stack), %g1
+       or              %g1, %lo(tramp_stack), %g1
+       add             %g1, TRAMP_STACK_SIZE, %g1
+       sub             %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp
        flushw
 
        /* Setup the loop variables:
@@ -394,7 +397,6 @@ after_lock_tlb:
        sllx            %g5, THREAD_SHIFT, %g5
        sub             %g5, (STACKFRAME_SZ + STACK_BIAS), %g5
        add             %g6, %g5, %sp
-       mov             0, %fp
 
        rdpr            %pstate, %o1
        or              %o1, PSTATE_IE, %o1
index a7c418ac26afbb46500ff812d939a8aefff27945..71cd65ab200c8739634447a995fb5e069cac3717 100644 (file)
@@ -45,6 +45,19 @@ ATOMIC_OP(add, +=)
 
 #undef ATOMIC_OP
 
+int atomic_xchg(atomic_t *v, int new)
+{
+       int ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(ATOMIC_HASH(v), flags);
+       ret = v->counter;
+       v->counter = new;
+       spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
+       return ret;
+}
+EXPORT_SYMBOL(atomic_xchg);
+
 int atomic_cmpxchg(atomic_t *v, int old, int new)
 {
        int ret;
@@ -137,3 +150,17 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new)
        return (unsigned long)prev;
 }
 EXPORT_SYMBOL(__cmpxchg_u32);
+
+unsigned long __xchg_u32(volatile u32 *ptr, u32 new)
+{
+       unsigned long flags;
+       u32 prev;
+
+       spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
+       prev = *ptr;
+       *ptr = new;
+       spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
+
+       return (unsigned long)prev;
+}
+EXPORT_SYMBOL(__xchg_u32);
index 1aed0432c64bab8344ad524ed28b835381588035..ae6ce383d4df6e3188cc547d365f366364f873e9 100644 (file)
@@ -160,6 +160,36 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
        return 1;
 }
 
+int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
+                         struct page **pages)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long addr, len, end;
+       unsigned long next, flags;
+       pgd_t *pgdp;
+       int nr = 0;
+
+       start &= PAGE_MASK;
+       addr = start;
+       len = (unsigned long) nr_pages << PAGE_SHIFT;
+       end = start + len;
+
+       local_irq_save(flags);
+       pgdp = pgd_offset(mm, addr);
+       do {
+               pgd_t pgd = *pgdp;
+
+               next = pgd_addr_end(addr, end);
+               if (pgd_none(pgd))
+                       break;
+               if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
+                       break;
+       } while (pgdp++, addr = next, addr != end);
+       local_irq_restore(flags);
+
+       return nr;
+}
+
 int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                        struct page **pages)
 {
index 9c86b4b7d4290b75a5967c28790c59b3ee24b5c9..8050f381f51812113143c462536dca3343562baf 100644 (file)
        .text
        .globl  prom_cif_direct
 prom_cif_direct:
+       save    %sp, -192, %sp
        sethi   %hi(p1275buf), %o1
        or      %o1, %lo(p1275buf), %o1
-       ldx     [%o1 + 0x0010], %o2     ! prom_cif_stack
-       save    %o2, -192, %sp
-       ldx     [%i1 + 0x0008], %l2     ! prom_cif_handler
+       ldx     [%o1 + 0x0008], %l2     ! prom_cif_handler
        mov     %g4, %l0
        mov     %g5, %l1
        mov     %g6, %l3
index d95db755828f351f18e2c1f1b160ebf571edead6..110b0d78b864113c2825271724b9363b5fb8e1ba 100644 (file)
@@ -26,13 +26,13 @@ phandle prom_chosen_node;
  * It gets passed the pointer to the PROM vector.
  */
 
-extern void prom_cif_init(void *, void *);
+extern void prom_cif_init(void *);
 
-void __init prom_init(void *cif_handler, void *cif_stack)
+void __init prom_init(void *cif_handler)
 {
        phandle node;
 
-       prom_cif_init(cif_handler, cif_stack);
+       prom_cif_init(cif_handler);
 
        prom_chosen_node = prom_finddevice(prom_chosen_path);
        if (!prom_chosen_node || (s32)prom_chosen_node == -1)
index b2340f008ae06a27614f2fc1c78e3b45b36946b0..545d8bb79b65245984ed36c7963bd3c97768a2f5 100644 (file)
@@ -20,7 +20,6 @@
 struct {
        long prom_callback;                     /* 0x00 */
        void (*prom_cif_handler)(long *);       /* 0x08 */
-       unsigned long prom_cif_stack;           /* 0x10 */
 } p1275buf;
 
 extern void prom_world(int);
@@ -52,5 +51,4 @@ void p1275_cmd_direct(unsigned long *args)
 void prom_cif_init(void *cif_handler, void *cif_stack)
 {
        p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
-       p1275buf.prom_cif_stack = (unsigned long)cif_stack;
 }
index 9fe434969fab0eef3a4e28c824f6f6a415e3abb8..d372641054d910546d3426148e54ad3eac82b93a 100644 (file)
@@ -241,6 +241,10 @@ static inline void writeq(u64 val, unsigned long addr)
 #define readw_relaxed readw
 #define readl_relaxed readl
 #define readq_relaxed readq
+#define writeb_relaxed writeb
+#define writew_relaxed writew
+#define writel_relaxed writel
+#define writeq_relaxed writeq
 
 #define ioread8 readb
 #define ioread16 readw
index f2327e88e07cc64236636a9f5973af898be947f1..41a503c158626a870906de36516765869c40ae1d 100644 (file)
@@ -142,6 +142,10 @@ config INSTRUCTION_DECODER
        def_bool y
        depends on KPROBES || PERF_EVENTS || UPROBES
 
+config PERF_EVENTS_INTEL_UNCORE
+       def_bool y
+       depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
+
 config OUTPUT_FORMAT
        string
        default "elf32-i386" if X86_32
index 704f58aa79cd4853f91663512232a59b3441b4c8..45abc363dd3e44dac4b5ced56d28ad9b510241f3 100644 (file)
@@ -76,8 +76,10 @@ suffix-$(CONFIG_KERNEL_XZ)   := xz
 suffix-$(CONFIG_KERNEL_LZO)    := lzo
 suffix-$(CONFIG_KERNEL_LZ4)    := lz4
 
+RUN_SIZE = $(shell $(OBJDUMP) -h vmlinux | \
+            perl $(srctree)/arch/x86/tools/calc_run_size.pl)
 quiet_cmd_mkpiggy = MKPIGGY $@
-      cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false )
+      cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false )
 
 targets += piggy.S
 $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE
index de8eebd6f67c825b3f013f7bc20a228b807c181f..1acf605a646dd87830f22694991142415c6ff351 100644 (file)
@@ -330,8 +330,10 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
        size = pci->romsize + sizeof(*rom);
 
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to alloc mem for rom\n");
                return status;
+       }
 
        memset(rom, 0, sizeof(*rom));
 
@@ -344,14 +346,18 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_VENDOR_ID, 1, &(rom->vendor));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->vendor\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_DEVICE_ID, 1, &(rom->devid));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->devid\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->get_location, pci, &(rom->segment),
                                 &(rom->bus), &(rom->device), &(rom->function));
@@ -432,8 +438,10 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
        size = pci->romsize + sizeof(*rom);
 
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, size, &rom);
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to alloc mem for rom\n");
                return status;
+       }
 
        rom->data.type = SETUP_PCI;
        rom->data.len = size - sizeof(struct setup_data);
@@ -444,14 +452,18 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_VENDOR_ID, 1, &(rom->vendor));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->vendor\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
                                 PCI_DEVICE_ID, 1, &(rom->devid));
 
-       if (status != EFI_SUCCESS)
+       if (status != EFI_SUCCESS) {
+               efi_printk(sys_table, "Failed to read rom->devid\n");
                goto free_struct;
+       }
 
        status = efi_early->call(pci->get_location, pci, &(rom->segment),
                                 &(rom->bus), &(rom->device), &(rom->function));
@@ -538,8 +550,10 @@ static void setup_efi_pci(struct boot_params *params)
                                        EFI_LOADER_DATA,
                                        size, (void **)&pci_handle);
 
-               if (status != EFI_SUCCESS)
+               if (status != EFI_SUCCESS) {
+                       efi_printk(sys_table, "Failed to alloc mem for pci_handle\n");
                        return;
+               }
 
                status = efi_call_early(locate_handle,
                                        EFI_LOCATE_BY_PROTOCOL, &pci_proto,
@@ -1105,6 +1119,10 @@ struct boot_params *make_boot_params(struct efi_config *c)
 
        memset(sdt, 0, sizeof(*sdt));
 
+       status = efi_parse_options(cmdline_ptr);
+       if (status != EFI_SUCCESS)
+               goto fail2;
+
        status = handle_cmdline_files(sys_table, image,
                                      (char *)(unsigned long)hdr->cmd_line_ptr,
                                      "initrd=", hdr->initrd_addr_max,
index cbed1407a5cdb7ead8fa0cae90d2e7902133aaa7..1d7fbbcc196d6f8b661545130972453f109e27d7 100644 (file)
@@ -207,7 +207,8 @@ relocated:
  * Do the decompression, and jump to the new kernel..
  */
                                /* push arguments for decompress_kernel: */
-       pushl   $z_output_len   /* decompressed length */
+       pushl   $z_run_size     /* size of kernel with .bss and .brk */
+       pushl   $z_output_len   /* decompressed length, end of relocs */
        leal    z_extract_offset_negative(%ebx), %ebp
        pushl   %ebp            /* output address */
        pushl   $z_input_len    /* input_len */
@@ -217,7 +218,7 @@ relocated:
        pushl   %eax            /* heap area */
        pushl   %esi            /* real mode pointer */
        call    decompress_kernel /* returns kernel location in %eax */
-       addl    $24, %esp
+       addl    $28, %esp
 
 /*
  * Jump to the decompressed kernel.
index 2884e0c3e8a5880411ce63955b01c103e6eabd00..6b1766c6c08205f3bda8a527dff88097b48e77e3 100644 (file)
@@ -402,13 +402,16 @@ relocated:
  * Do the decompression, and jump to the new kernel..
  */
        pushq   %rsi                    /* Save the real mode argument */
+       movq    $z_run_size, %r9        /* size of kernel with .bss and .brk */
+       pushq   %r9
        movq    %rsi, %rdi              /* real mode address */
        leaq    boot_heap(%rip), %rsi   /* malloc area for uncompression */
        leaq    input_data(%rip), %rdx  /* input_data */
        movl    $z_input_len, %ecx      /* input_len */
        movq    %rbp, %r8               /* output target address */
-       movq    $z_output_len, %r9      /* decompressed length */
+       movq    $z_output_len, %r9      /* decompressed length, end of relocs */
        call    decompress_kernel       /* returns kernel location in %rax */
+       popq    %r9
        popq    %rsi
 
 /*
index 57ab74df7eeaa3eef4954b89f36d20b4c528afd7..30dd59a9f0b4acfd6a70587f6f4e247adbbeb8fd 100644 (file)
@@ -358,7 +358,8 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
                                  unsigned char *input_data,
                                  unsigned long input_len,
                                  unsigned char *output,
-                                 unsigned long output_len)
+                                 unsigned long output_len,
+                                 unsigned long run_size)
 {
        real_mode = rmode;
 
@@ -381,8 +382,14 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
        free_mem_ptr     = heap;        /* Heap */
        free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
 
-       output = choose_kernel_location(input_data, input_len,
-                                       output, output_len);
+       /*
+        * The memory hole needed for the kernel is the larger of either
+        * the entire decompressed kernel plus relocation table, or the
+        * entire decompressed kernel plus .bss and .brk sections.
+        */
+       output = choose_kernel_location(input_data, input_len, output,
+                                       output_len > run_size ? output_len
+                                                             : run_size);
 
        /* Validate memory location choices. */
        if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
index b669ab65bf6cf2e6973d6dc50cb693a1a8568324..d8222f213182f120c6f1d4c43e9ac477b2c2ca24 100644 (file)
@@ -36,11 +36,13 @@ int main(int argc, char *argv[])
        uint32_t olen;
        long ilen;
        unsigned long offs;
+       unsigned long run_size;
        FILE *f = NULL;
        int retval = 1;
 
-       if (argc < 2) {
-               fprintf(stderr, "Usage: %s compressed_file\n", argv[0]);
+       if (argc < 3) {
+               fprintf(stderr, "Usage: %s compressed_file run_size\n",
+                               argv[0]);
                goto bail;
        }
 
@@ -74,6 +76,7 @@ int main(int argc, char *argv[])
        offs += olen >> 12;     /* Add 8 bytes for each 32K block */
        offs += 64*1024 + 128;  /* Add 64K + 128 bytes slack */
        offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
+       run_size = atoi(argv[2]);
 
        printf(".section \".rodata..compressed\",\"a\",@progbits\n");
        printf(".globl z_input_len\n");
@@ -85,6 +88,8 @@ int main(int argc, char *argv[])
        /* z_extract_offset_negative allows simplification of head_32.S */
        printf(".globl z_extract_offset_negative\n");
        printf("z_extract_offset_negative = -0x%lx\n", offs);
+       printf(".globl z_run_size\n");
+       printf("z_run_size = %lu\n", run_size);
 
        printf(".globl input_data, input_data_end\n");
        printf("input_data:\n");
index 8ffba18395c8bb0a93c6a9dc65cfd8739a5937f3..ffe71228fc10c3080795c576b1ffae6b62160d7f 100644 (file)
@@ -157,7 +157,7 @@ ENTRY(ia32_sysenter_target)
         * ourselves.  To save a few cycles, we can check whether
         * NT was set instead of doing an unconditional popfq.
         */
-       testl $X86_EFLAGS_NT,EFLAGS(%rsp)       /* saved EFLAGS match cpu */
+       testl $X86_EFLAGS_NT,EFLAGS-ARGOFFSET(%rsp)
        jnz sysenter_fix_flags
 sysenter_flags_fixed:
 
index 0ec241ede5a256327f9a578ac2d61d0def83b2c5..9b11757975d025045b747097e95ad0009293a8a2 100644 (file)
@@ -81,24 +81,23 @@ extern u64 asmlinkage efi_call(void *fp, ...);
  */
 #define __efi_call_virt(f, args...) efi_call_virt(f, args)
 
-extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
-                                u32 type, u64 attribute);
+extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
+                                       u32 type, u64 attribute);
 
 #endif /* CONFIG_X86_32 */
 
-extern int add_efi_memmap;
 extern struct efi_scratch efi_scratch;
-extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
-extern int efi_memblock_x86_reserve_range(void);
-extern void efi_call_phys_prelog(void);
-extern void efi_call_phys_epilog(void);
-extern void efi_unmap_memmap(void);
-extern void efi_memory_uc(u64 addr, unsigned long size);
+extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
+extern int __init efi_memblock_x86_reserve_range(void);
+extern void __init efi_call_phys_prolog(void);
+extern void __init efi_call_phys_epilog(void);
+extern void __init efi_unmap_memmap(void);
+extern void __init efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
 extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
 extern void efi_sync_low_kernel_mappings(void);
-extern int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
-extern void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+extern int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+extern void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
 extern void __init old_map_region(efi_memory_desc_t *md);
 extern void __init runtime_code_page_mkexec(void);
 extern void __init efi_runtime_mkexec(void);
@@ -162,16 +161,6 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
 extern bool efi_reboot_required(void);
 
 #else
-/*
- * IF EFI is not configured, have the EFI calls return -ENOSYS.
- */
-#define efi_call0(_f)                                  (-ENOSYS)
-#define efi_call1(_f, _a1)                             (-ENOSYS)
-#define efi_call2(_f, _a1, _a2)                                (-ENOSYS)
-#define efi_call3(_f, _a1, _a2, _a3)                   (-ENOSYS)
-#define efi_call4(_f, _a1, _a2, _a3, _a4)              (-ENOSYS)
-#define efi_call5(_f, _a1, _a2, _a3, _a4, _a5)         (-ENOSYS)
-#define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6)    (-ENOSYS)
 static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
 static inline bool efi_reboot_required(void)
 {
index b8237d8a1e0c86ac2d801cefa94e7f8f0c344cd6..0cdbe6e81b453405cbc7b39c09eb33c49043490a 100644 (file)
@@ -74,6 +74,9 @@ build_mmio_write(__writel, "l", unsigned int, "r", )
 #define __raw_readw __readw
 #define __raw_readl __readl
 
+#define writeb_relaxed(v, a) __writeb(v, a)
+#define writew_relaxed(v, a) __writew(v, a)
+#define writel_relaxed(v, a) __writel(v, a)
 #define __raw_writeb __writeb
 #define __raw_writew __writew
 #define __raw_writel __writel
@@ -86,6 +89,7 @@ build_mmio_read(readq, "q", unsigned long, "=r", :"memory")
 build_mmio_write(writeq, "q", unsigned long, "r", :"memory")
 
 #define readq_relaxed(a)       readq(a)
+#define writeq_relaxed(v, a)   writeq(v, a)
 
 #define __raw_readq(a)         readq(a)
 #define __raw_writeq(val, addr)        writeq(val, addr)
@@ -310,8 +314,8 @@ BUILDIO(b, b, char)
 BUILDIO(w, w, short)
 BUILDIO(l, , int)
 
-extern void *xlate_dev_mem_ptr(unsigned long phys);
-extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+extern void *xlate_dev_mem_ptr(phys_addr_t phys);
+extern void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
 
 extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
                                unsigned long prot_val);
index 7d603a71ab3a9f36ea6729e2924b998e3a83c556..6ed0c30d6a0c347e6dd4c9ac0cbd26acfb9ec53b 100644 (file)
@@ -989,6 +989,20 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
        kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
 }
 
+static inline u64 get_canonical(u64 la)
+{
+       return ((int64_t)la << 16) >> 16;
+}
+
+static inline bool is_noncanonical_address(u64 la)
+{
+#ifdef CONFIG_X86_64
+       return get_canonical(la) != la;
+#else
+       return false;
+#endif
+}
+
 #define TSS_IOPB_BASE_OFFSET 0x66
 #define TSS_BASE_SIZE 0x68
 #define TSS_IOPB_SIZE (65536 / 8)
@@ -1050,7 +1064,7 @@ void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
                                           unsigned long address);
 
 void kvm_define_shared_msr(unsigned index, u32 msr);
-void kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
+int kvm_set_shared_msr(unsigned index, u64 val, u64 mask);
 
 bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip);
 
index f48b17df42249e45cca9ef6de99bfd43083507cd..3a52ee0e726d4ca2643ff6b0dec4675f39e296b5 100644 (file)
@@ -20,7 +20,6 @@
 #define THREAD_SIZE_ORDER      1
 #define THREAD_SIZE            (PAGE_SIZE << THREAD_SIZE_ORDER)
 
-#define STACKFAULT_STACK 0
 #define DOUBLEFAULT_STACK 1
 #define NMI_STACK 0
 #define DEBUG_STACK 0
index 678205195ae118e16ca34609a24f472d9875e568..75450b2c7be48393607da8a5fdf050e663eb48c8 100644 (file)
 #define IRQ_STACK_ORDER 2
 #define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER)
 
-#define STACKFAULT_STACK 1
-#define DOUBLEFAULT_STACK 2
-#define NMI_STACK 3
-#define DEBUG_STACK 4
-#define MCE_STACK 5
-#define N_EXCEPTION_STACKS 5  /* hw limit: 7 */
+#define DOUBLEFAULT_STACK 1
+#define NMI_STACK 2
+#define DEBUG_STACK 3
+#define MCE_STACK 4
+#define N_EXCEPTION_STACKS 4  /* hw limit: 7 */
 
 #define PUD_PAGE_SIZE          (_AC(1, UL) << PUD_SHIFT)
 #define PUD_PAGE_MASK          (~(PUD_PAGE_SIZE-1))
index 8dfc9fd094a3b3fea4912da838d2114766017295..dc0f6ed35b0864d061f7383cab6055f9764995a6 100644 (file)
@@ -177,6 +177,9 @@ struct x86_pmu_capability {
 #define IBS_CAPS_BRNTRGT               (1U<<5)
 #define IBS_CAPS_OPCNTEXT              (1U<<6)
 #define IBS_CAPS_RIPINVALIDCHK         (1U<<7)
+#define IBS_CAPS_OPBRNFUSE             (1U<<8)
+#define IBS_CAPS_FETCHCTLEXTD          (1U<<9)
+#define IBS_CAPS_OPDATA4               (1U<<10)
 
 #define IBS_CAPS_DEFAULT               (IBS_CAPS_AVAIL         \
                                         | IBS_CAPS_FETCHSAM    \
index 7024c12f7bfe9cd15252f29f3502db75d92ebccc..8f32718425339f426778bbe09e2c468e5ff63814 100644 (file)
@@ -30,9 +30,6 @@ static __always_inline void preempt_count_set(int pc)
 /*
  * must be macros to avoid header recursion hell
  */
-#define task_preempt_count(p) \
-       (task_thread_info(p)->saved_preempt_count & ~PREEMPT_NEED_RESCHED)
-
 #define init_task_preempt_count(p) do { \
        task_thread_info(p)->saved_preempt_count = PREEMPT_DISABLED; \
 } while (0)
@@ -105,6 +102,7 @@ static __always_inline bool should_resched(void)
 # ifdef CONFIG_CONTEXT_TRACKING
     extern asmlinkage void ___preempt_schedule_context(void);
 #   define __preempt_schedule_context() asm ("call ___preempt_schedule_context")
+    extern asmlinkage void preempt_schedule_context(void);
 # endif
 #endif
 
index 8cd27e08e23c47cec2f736b6b674b921554eb680..8cd1cc3bc8356ffef29e349f08b3de43aeb79506 100644 (file)
@@ -150,6 +150,7 @@ static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 }
 
 void cpu_disable_common(void);
+void cpu_die_common(unsigned int cpu);
 void native_smp_prepare_boot_cpu(void);
 void native_smp_prepare_cpus(unsigned int max_cpus);
 void native_smp_cpus_done(unsigned int max_cpus);
index 9295016485c9039e96cb982da754aee40162ce96..a4efe477ceab0815244765a5d882f286aec0817c 100644 (file)
@@ -183,8 +183,20 @@ static __always_inline void arch_spin_lock_flags(arch_spinlock_t *lock,
 
 static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
 {
-       while (arch_spin_is_locked(lock))
+       __ticket_t head = ACCESS_ONCE(lock->tickets.head);
+
+       for (;;) {
+               struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
+               /*
+                * We need to check "unlocked" in a loop, tmp.head == head
+                * can be false positive because of overflow.
+                */
+               if (tmp.head == (tmp.tail & ~TICKET_SLOWPATH_FLAG) ||
+                   tmp.head != head)
+                       break;
+
                cpu_relax();
+       }
 }
 
 /*
index 854053889d4d2d6f74cdb3143da4f6c63e213996..547e344a6dc60d7db27d43c74d44c783326291bb 100644 (file)
@@ -141,7 +141,7 @@ struct thread_info {
 /* Only used for 64 bit */
 #define _TIF_DO_NOTIFY_MASK                                            \
        (_TIF_SIGPENDING | _TIF_MCE_NOTIFY | _TIF_NOTIFY_RESUME |       \
-        _TIF_USER_RETURN_NOTIFY)
+        _TIF_USER_RETURN_NOTIFY | _TIF_UPROBE)
 
 /* flags to check in __switch_to() */
 #define _TIF_WORK_CTXSW                                                        \
index bc8352e7010a9e805c54068da84b3848dcc12048..707adc6549d82335a20bdf18d18b697fa1fe9eab 100644 (file)
@@ -39,6 +39,7 @@ asmlinkage void simd_coprocessor_error(void);
 
 #ifdef CONFIG_TRACING
 asmlinkage void trace_page_fault(void);
+#define trace_stack_segment stack_segment
 #define trace_divide_error divide_error
 #define trace_bounds bounds
 #define trace_invalid_op invalid_op
index e21331ce368fc60a4ae7fd727448a4ca30d7bdf2..8f02f6990759ba91b7002950b1c738fda7d54533 100644 (file)
 #define MSR_AMD64_IBSOP_REG_MASK       ((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
 #define MSR_AMD64_IBSCTL               0xc001103a
 #define MSR_AMD64_IBSBRTARGET          0xc001103b
+#define MSR_AMD64_IBSOPDATA4           0xc001103d
 #define MSR_AMD64_IBS_REG_COUNT_MAX    8 /* includes MSR_AMD64_IBSBRTARGET */
 
 /* Fam 16h MSRs */
index 0e79420376eb93d51224e8ff6d41ecdf55280224..990a2fe1588d53d1c101394e5f9827f9fc63c557 100644 (file)
@@ -67,6 +67,7 @@
 #define EXIT_REASON_EPT_MISCONFIG       49
 #define EXIT_REASON_INVEPT              50
 #define EXIT_REASON_PREEMPTION_TIMER    52
+#define EXIT_REASON_INVVPID             53
 #define EXIT_REASON_WBINVD              54
 #define EXIT_REASON_XSETBV              55
 #define EXIT_REASON_APIC_WRITE          56
        { EXIT_REASON_EOI_INDUCED,           "EOI_INDUCED" }, \
        { EXIT_REASON_INVALID_STATE,         "INVALID_STATE" }, \
        { EXIT_REASON_INVD,                  "INVD" }, \
+       { EXIT_REASON_INVVPID,               "INVVPID" }, \
        { EXIT_REASON_INVPCID,               "INVPCID" }
 
 #endif /* _UAPIVMX_H */
index b436fc735aa455be7f007a7bcb089741ace98c1c..a142e77693e179334987d3502e33c5444fde885c 100644 (file)
@@ -397,7 +397,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
 
        /* Don't set up the ACPI SCI because it's already set up */
        if (acpi_gbl_FADT.sci_interrupt == gsi)
-               return gsi;
+               return mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
 
        trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
        polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
@@ -604,14 +604,18 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
 
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
 {
-       int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+       int irq;
 
-       if (irq >= 0) {
+       if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+               *irqp = gsi;
+       } else {
+               irq = mp_map_gsi_to_irq(gsi,
+                                       IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
+               if (irq < 0)
+                       return -1;
                *irqp = irq;
-               return 0;
        }
-
-       return -1;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
 
index f04dbb3069b8fda5168e7a95dc935baf4389f127..5caed1dd7ccf89e6595fc4a7db7d1d5b7f92f0a6 100644 (file)
@@ -21,6 +21,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
        {}
@@ -30,6 +31,7 @@ EXPORT_SYMBOL(amd_nb_misc_ids);
 static const struct pci_device_id amd_nb_link_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
        {}
index 5972b108f15a739a06b47276a05d86713d08a3a2..b708738d016e09f44e15040333741382caaffd34 100644 (file)
@@ -185,8 +185,6 @@ static void apbt_setup_irq(struct apbt_dev *adev)
 
        irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
        irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
-       /* APB timer irqs are set up as mp_irqs, timer is edge type */
-       __irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
 }
 
 /* Should be called with per cpu */
index 00853b254ab09c36afdb2a681bd9c68037ac17dc..ba6cc041edb12e23a783fc0c5aaaed788af39dc0 100644 (file)
@@ -1297,7 +1297,7 @@ void setup_local_APIC(void)
        unsigned int value, queued;
        int i, j, acked = 0;
        unsigned long long tsc = 0, ntsc;
-       long long max_loops = cpu_khz;
+       long long max_loops = cpu_khz ? cpu_khz : 1000000;
 
        if (cpu_has_tsc)
                rdtscll(tsc);
@@ -1383,7 +1383,7 @@ void setup_local_APIC(void)
                        break;
                }
                if (queued) {
-                       if (cpu_has_tsc) {
+                       if (cpu_has_tsc && cpu_khz) {
                                rdtscll(ntsc);
                                max_loops = (cpu_khz << 10) - (ntsc - tsc);
                        } else
index 01d5453b5502c235759712b751da809123b565cc..e27b49d7c922a3caaa6c45446e8bc383a86d27bc 100644 (file)
@@ -39,9 +39,12 @@ obj-$(CONFIG_CPU_SUP_AMD)            += perf_event_amd_iommu.o
 endif
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_knc.o perf_event_p4.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore.o perf_event_intel_uncore_snb.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore_snbep.o perf_event_intel_uncore_nhmex.o
 obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_rapl.o
+
+obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += perf_event_intel_uncore.o \
+                                          perf_event_intel_uncore_snb.o \
+                                          perf_event_intel_uncore_snbep.o \
+                                          perf_event_intel_uncore_nhmex.o
 endif
 
 
index 4b4f78c9ba1902ed87127738052135ed54071088..cfa9b5b2c27a0b72d794f4aa048deaa404e8baef 100644 (file)
@@ -146,6 +146,8 @@ EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
 
 static int __init x86_xsave_setup(char *s)
 {
+       if (strlen(s))
+               return 0;
        setup_clear_cpu_cap(X86_FEATURE_XSAVE);
        setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
        setup_clear_cpu_cap(X86_FEATURE_XSAVES);
index 1ef456273172c8875e5673d890916dd70033e8e4..9cc6b6f25f424d18426adbab3e31e251e78c13af 100644 (file)
@@ -213,12 +213,13 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_X86_F00F_BUG
        /*
-        * All current models of Pentium and Pentium with MMX technology CPUs
+        * All models of Pentium and Pentium with MMX technology CPUs
         * have the F0 0F bug, which lets nonprivileged users lock up the
         * system. Announce that the fault handler will be checking for it.
+        * The Quark is also family 5, but does not have the same bug.
         */
        clear_cpu_bug(c, X86_BUG_F00F);
-       if (!paravirt_enabled() && c->x86 == 5) {
+       if (!paravirt_enabled() && c->x86 == 5 && c->x86_model < 9) {
                static int f00f_workaround_enabled;
 
                set_cpu_bug(c, X86_BUG_F00F);
index 7aa1acc79789aa9c38de7509dcb018132a50d901..06674473b0e66736d0a64c235c1e9fe7e774deb9 100644 (file)
@@ -108,12 +108,13 @@ static size_t compute_container_size(u8 *data, u32 total_size)
  * load_microcode_amd() to save equivalent cpu table and microcode patches in
  * kernel heap memory.
  */
-static void apply_ucode_in_initrd(void *ucode, size_t size)
+static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
 {
        struct equiv_cpu_entry *eq;
        size_t *cont_sz;
        u32 *header;
        u8  *data, **cont;
+       u8 (*patch)[PATCH_MAX_SIZE];
        u16 eq_id = 0;
        int offset, left;
        u32 rev, eax, ebx, ecx, edx;
@@ -123,10 +124,12 @@ static void apply_ucode_in_initrd(void *ucode, size_t size)
        new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
        cont_sz = (size_t *)__pa_nodebug(&container_size);
        cont    = (u8 **)__pa_nodebug(&container);
+       patch   = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
 #else
        new_rev = &ucode_new_rev;
        cont_sz = &container_size;
        cont    = &container;
+       patch   = &amd_ucode_patch;
 #endif
 
        data   = ucode;
@@ -213,9 +216,9 @@ static void apply_ucode_in_initrd(void *ucode, size_t size)
                                rev = mc->hdr.patch_id;
                                *new_rev = rev;
 
-                               /* save ucode patch */
-                               memcpy(amd_ucode_patch, mc,
-                                      min_t(u32, header[1], PATCH_MAX_SIZE));
+                               if (save_patch)
+                                       memcpy(patch, mc,
+                                              min_t(u32, header[1], PATCH_MAX_SIZE));
                        }
                }
 
@@ -246,7 +249,7 @@ void __init load_ucode_amd_bsp(void)
        *data = cp.data;
        *size = cp.size;
 
-       apply_ucode_in_initrd(cp.data, cp.size);
+       apply_ucode_in_initrd(cp.data, cp.size, true);
 }
 
 #ifdef CONFIG_X86_32
@@ -263,7 +266,7 @@ void load_ucode_amd_ap(void)
        size_t *usize;
        void **ucode;
 
-       mc = (struct microcode_amd *)__pa(amd_ucode_patch);
+       mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch);
        if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
                __apply_microcode_amd(mc);
                return;
@@ -275,7 +278,7 @@ void load_ucode_amd_ap(void)
        if (!*ucode || !*usize)
                return;
 
-       apply_ucode_in_initrd(*ucode, *usize);
+       apply_ucode_in_initrd(*ucode, *usize, false);
 }
 
 static void __init collect_cpu_sig_on_bsp(void *arg)
@@ -339,7 +342,7 @@ void load_ucode_amd_ap(void)
                 * AP has a different equivalence ID than BSP, looks like
                 * mixed-steppings silicon so go through the ucode blob anew.
                 */
-               apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size);
+               apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false);
        }
 }
 #endif
@@ -347,7 +350,9 @@ void load_ucode_amd_ap(void)
 int __init save_microcode_in_initrd_amd(void)
 {
        unsigned long cont;
+       int retval = 0;
        enum ucode_state ret;
+       u8 *cont_va;
        u32 eax;
 
        if (!container)
@@ -355,13 +360,15 @@ int __init save_microcode_in_initrd_amd(void)
 
 #ifdef CONFIG_X86_32
        get_bsp_sig();
-       cont = (unsigned long)container;
+       cont    = (unsigned long)container;
+       cont_va = __va(container);
 #else
        /*
         * We need the physical address of the container for both bitness since
         * boot_params.hdr.ramdisk_image is a physical address.
         */
-       cont = __pa(container);
+       cont    = __pa(container);
+       cont_va = container;
 #endif
 
        /*
@@ -372,6 +379,8 @@ int __init save_microcode_in_initrd_amd(void)
        if (relocated_ramdisk)
                container = (u8 *)(__va(relocated_ramdisk) +
                             (cont - boot_params.hdr.ramdisk_image));
+       else
+               container = cont_va;
 
        if (ucode_new_rev)
                pr_info("microcode: updated early to new patch_level=0x%08x\n",
@@ -382,7 +391,7 @@ int __init save_microcode_in_initrd_amd(void)
 
        ret = load_microcode_amd(eax, container, container_size);
        if (ret != UCODE_OK)
-               return -EINVAL;
+               retval = -EINVAL;
 
        /*
         * This will be freed any msec now, stash patches for the current
@@ -391,5 +400,5 @@ int __init save_microcode_in_initrd_amd(void)
        container = NULL;
        container_size = 0;
 
-       return 0;
+       return retval;
 }
index dd9d6190b08dfae5fdaee714ab5f556040af516e..08fe6e8a726e5160e51b9c992da765e2fab29348 100644 (file)
@@ -465,6 +465,16 @@ static void mc_bp_resume(void)
 
        if (uci->valid && uci->mc)
                microcode_ops->apply_microcode(cpu);
+#ifdef CONFIG_X86_64
+       else if (!uci->mc)
+               /*
+                * We might resume and not have applied late microcode but still
+                * have a newer patch stashed from the early loader. We don't
+                * have it in uci->mc so we have to load it the same way we're
+                * applying patches early on the APs.
+                */
+               load_ucode_ap();
+#endif
 }
 
 static struct syscore_ops mc_syscore_ops = {
index 5f28a64e71ea9e834bb835ed5fe4d8e7adaf472f..2c017f242a78144ba18499f52aa5ca0c069aa880 100644 (file)
@@ -124,7 +124,7 @@ void __init load_ucode_bsp(void)
 static bool check_loader_disabled_ap(void)
 {
 #ifdef CONFIG_X86_32
-       return __pa_nodebug(dis_ucode_ldr);
+       return *((bool *)__pa_nodebug(&dis_ucode_ldr));
 #else
        return dis_ucode_ldr;
 #endif
index 1b8299dd3d919de522374301b6b33777412e7e7b..143e5f5dc8551b568b7eabb84d83da764268d6b2 100644 (file)
@@ -243,8 +243,9 @@ static bool check_hw_exists(void)
 
 msr_fail:
        printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n");
-       printk(boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR
-              "Failed to access perfctr msr (MSR %x is %Lx)\n", reg, val_new);
+       printk("%sFailed to access perfctr msr (MSR %x is %Lx)\n",
+               boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR,
+               reg, val_new);
 
        return false;
 }
@@ -444,12 +445,6 @@ int x86_pmu_hw_config(struct perf_event *event)
        if (event->attr.type == PERF_TYPE_RAW)
                event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK;
 
-       if (event->attr.sample_period && x86_pmu.limit_period) {
-               if (x86_pmu.limit_period(event, event->attr.sample_period) >
-                               event->attr.sample_period)
-                       return -EINVAL;
-       }
-
        return x86_setup_perfctr(event);
 }
 
@@ -987,9 +982,6 @@ int x86_perf_event_set_period(struct perf_event *event)
        if (left > x86_pmu.max_period)
                left = x86_pmu.max_period;
 
-       if (x86_pmu.limit_period)
-               left = x86_pmu.limit_period(event, left);
-
        per_cpu(pmc_prev_left[idx], smp_processor_id()) = left;
 
        /*
index d98a34d435d7b5260154bcf4463bbcb24ad073fb..4e6cdb0ddc70c86472649dc6e1beee3af93ddcae 100644 (file)
@@ -253,6 +253,10 @@ struct cpu_hw_events {
 #define INTEL_UEVENT_CONSTRAINT(c, n)  \
        EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
 
+/* Like UEVENT_CONSTRAINT, but match flags too */
+#define INTEL_FLAGS_UEVENT_CONSTRAINT(c, n)    \
+       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
+
 #define INTEL_PLD_CONSTRAINT(c, n)     \
        __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
                           HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LDLAT)
@@ -445,7 +449,6 @@ struct x86_pmu {
        struct x86_pmu_quirk *quirks;
        int             perfctr_second_write;
        bool            late_ack;
-       unsigned        (*limit_period)(struct perf_event *event, unsigned l);
 
        /*
         * sysfs attrs
index cbb1be3ed9e432aab5ff3b679e5e0ecc0bfd731a..a61f5c6911daac339588b9099e5b897a3ef9d774 100644 (file)
@@ -565,6 +565,21 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
                                       perf_ibs->offset_max,
                                       offset + 1);
        } while (offset < offset_max);
+       if (event->attr.sample_type & PERF_SAMPLE_RAW) {
+               /*
+                * Read IbsBrTarget and IbsOpData4 separately
+                * depending on their availability.
+                * Can't add to offset_max as they are staggered
+                */
+               if (ibs_caps & IBS_CAPS_BRNTRGT) {
+                       rdmsrl(MSR_AMD64_IBSBRTARGET, *buf++);
+                       size++;
+               }
+               if (ibs_caps & IBS_CAPS_OPDATA4) {
+                       rdmsrl(MSR_AMD64_IBSOPDATA4, *buf++);
+                       size++;
+               }
+       }
        ibs_data.size = sizeof(u64) * size;
 
        regs = *iregs;
index a73947c53b65aa683f29d61a115d0e6d19a9ec5b..944bf019b74f425e06cc465358d25b85741a5b47 100644 (file)
@@ -220,15 +220,6 @@ static struct event_constraint intel_hsw_event_constraints[] = {
        EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_bdw_event_constraints[] = {
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0),      /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1),      /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2),      /* CPU_CLK_UNHALTED.REF */
-       INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
-       INTEL_EVENT_CONSTRAINT(0xa3, 0x4),      /* CYCLE_ACTIVITY.* */
-       EVENT_CONSTRAINT_END
-};
-
 static u64 intel_pmu_event_map(int hw_event)
 {
        return intel_perfmon_event_map[hw_event];
@@ -424,126 +415,6 @@ static __initconst const u64 snb_hw_cache_event_ids
 
 };
 
-static __initconst const u64 hsw_hw_cache_event_ids
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(L1D ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x151,   /* L1D.REPLACEMENT */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x280,   /* ICACHE.MISSES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD */
-               [ C(RESULT_ACCESS) ] = 0x1b7,
-               /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD|SUPPLIER_NONE|
-                   L3_MISS|ANY_SNOOP */
-               [ C(RESULT_MISS)   ] = 0x1b7,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE:ALL_RFO */
-               /* OFFCORE_RESPONSE:ALL_RFO|SUPPLIER_NONE|L3_MISS|ANY_SNOOP */
-               [ C(RESULT_MISS)   ] = 0x1b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x108,   /* DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x149,   /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x6085,  /* ITLB_MISSES.STLB_HIT */
-               [ C(RESULT_MISS)   ] = 0x185,   /* ITLB_MISSES.MISS_CAUSES_A_WALK */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0xc4,    /* BR_INST_RETIRED.ALL_BRANCHES */
-               [ C(RESULT_MISS)   ] = 0xc5,    /* BR_MISP_RETIRED.ALL_BRANCHES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-static __initconst const u64 hsw_hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD */
-               [ C(RESULT_ACCESS) ] = 0x2d5,
-               /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD|SUPPLIER_NONE|
-                   L3_MISS|ANY_SNOOP */
-               [ C(RESULT_MISS)   ] = 0x3fbc0202d5ull,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x122,   /* OFFCORE_RESPONSE:ALL_RFO */
-               /* OFFCORE_RESPONSE:ALL_RFO|SUPPLIER_NONE|L3_MISS|ANY_SNOOP */
-               [ C(RESULT_MISS)   ] = 0x3fbc020122ull,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
-};
-
 static __initconst const u64 westmere_hw_cache_event_ids
                                [PERF_COUNT_HW_CACHE_MAX]
                                [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -2034,24 +1905,6 @@ hsw_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
        return c;
 }
 
-/*
- * Broadwell:
- * The INST_RETIRED.ALL period always needs to have lowest
- * 6bits cleared (BDM57). It shall not use a period smaller
- * than 100 (BDM11). We combine the two to enforce
- * a min-period of 128.
- */
-static unsigned bdw_limit_period(struct perf_event *event, unsigned left)
-{
-       if ((event->hw.config & INTEL_ARCH_EVENT_MASK) ==
-                       X86_CONFIG(.event=0xc0, .umask=0x01)) {
-               if (left < 128)
-                       left = 128;
-               left &= ~0x3fu;
-       }
-       return left;
-}
-
 PMU_FORMAT_ATTR(event, "config:0-7"    );
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -2692,8 +2545,8 @@ __init int intel_pmu_init(void)
        case 69: /* 22nm Haswell ULT */
        case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
                x86_pmu.late_ack = true;
-               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
 
                intel_pmu_lbr_init_snb();
 
@@ -2712,28 +2565,6 @@ __init int intel_pmu_init(void)
                pr_cont("Haswell events, ");
                break;
 
-       case 61: /* 14nm Broadwell Core-M */
-               x86_pmu.late_ack = true;
-               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
-
-               intel_pmu_lbr_init_snb();
-
-               x86_pmu.event_constraints = intel_bdw_event_constraints;
-               x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
-               x86_pmu.extra_regs = intel_snbep_extra_regs;
-               x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
-               /* all extra regs are per-cpu when HT is on */
-               x86_pmu.er_flags |= ERF_HAS_RSP_1;
-               x86_pmu.er_flags |= ERF_NO_HT_SHARING;
-
-               x86_pmu.hw_config = hsw_hw_config;
-               x86_pmu.get_event_constraints = hsw_get_event_constraints;
-               x86_pmu.cpu_events = hsw_events_attrs;
-               x86_pmu.limit_period = bdw_limit_period;
-               pr_cont("Broadwell events, ");
-               break;
-
        default:
                switch (x86_pmu.version) {
                case 1:
index 46211bcc813ee812760c15be6c7c11da4bfd52c2..495ae9793628fb6e9ed324e97c16fbc34fc83f13 100644 (file)
@@ -552,18 +552,18 @@ int intel_pmu_drain_bts_buffer(void)
  * PEBS
  */
 struct event_constraint intel_core2_pebs_event_constraints[] = {
-       INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
-       INTEL_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
-       INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
-       INTEL_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
-       INTEL_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
        EVENT_CONSTRAINT_END
 };
 
 struct event_constraint intel_atom_pebs_event_constraints[] = {
-       INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
-       INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
-       INTEL_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
        EVENT_CONSTRAINT_END
 };
 
@@ -577,36 +577,36 @@ struct event_constraint intel_slm_pebs_event_constraints[] = {
 
 struct event_constraint intel_nehalem_pebs_event_constraints[] = {
        INTEL_PLD_CONSTRAINT(0x100b, 0xf),      /* MEM_INST_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
-       INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
-       INTEL_EVENT_CONSTRAINT(0xc0, 0xf),    /* INST_RETIRED.ANY */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf),    /* INST_RETIRED.ANY */
        INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
-       INTEL_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
-       INTEL_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
-       INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
-       INTEL_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
        EVENT_CONSTRAINT_END
 };
 
 struct event_constraint intel_westmere_pebs_event_constraints[] = {
        INTEL_PLD_CONSTRAINT(0x100b, 0xf),      /* MEM_INST_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
-       INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
-       INTEL_EVENT_CONSTRAINT(0xc0, 0xf),    /* INSTR_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf),    /* INSTR_RETIRED.* */
        INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
-       INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
-       INTEL_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
        EVENT_CONSTRAINT_END
 };
 
 struct event_constraint intel_snb_pebs_event_constraints[] = {
-       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
        INTEL_PLD_CONSTRAINT(0x01cd, 0x8),    /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
        INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
        /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
@@ -617,7 +617,7 @@ struct event_constraint intel_snb_pebs_event_constraints[] = {
 };
 
 struct event_constraint intel_ivb_pebs_event_constraints[] = {
-        INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+        INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
         INTEL_PLD_CONSTRAINT(0x01cd, 0x8),    /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
        INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
        /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
@@ -628,7 +628,7 @@ struct event_constraint intel_ivb_pebs_event_constraints[] = {
 };
 
 struct event_constraint intel_hsw_pebs_event_constraints[] = {
-       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
        INTEL_PLD_CONSTRAINT(0x01cd, 0xf),    /* MEM_TRANS_RETIRED.* */
        /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
        INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
@@ -886,6 +886,29 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
        regs.bp = pebs->bp;
        regs.sp = pebs->sp;
 
+       if (sample_type & PERF_SAMPLE_REGS_INTR) {
+               regs.ax = pebs->ax;
+               regs.bx = pebs->bx;
+               regs.cx = pebs->cx;
+               regs.dx = pebs->dx;
+               regs.si = pebs->si;
+               regs.di = pebs->di;
+               regs.bp = pebs->bp;
+               regs.sp = pebs->sp;
+
+               regs.flags = pebs->flags;
+#ifndef CONFIG_X86_32
+               regs.r8 = pebs->r8;
+               regs.r9 = pebs->r9;
+               regs.r10 = pebs->r10;
+               regs.r11 = pebs->r11;
+               regs.r12 = pebs->r12;
+               regs.r13 = pebs->r13;
+               regs.r14 = pebs->r14;
+               regs.r15 = pebs->r15;
+#endif
+       }
+
        if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) {
                regs.ip = pebs->real_ip;
                regs.flags |= PERF_EFLAGS_EXACT;
index adf138eac85c3384550e2f14ec5ac3377ed87000..745b158e9a65768134caaba91d2f55f43200a481 100644 (file)
@@ -449,7 +449,11 @@ static struct attribute *snbep_uncore_qpi_formats_attr[] = {
 static struct uncore_event_desc snbep_uncore_imc_events[] = {
        INTEL_UNCORE_EVENT_DESC(clockticks,      "event=0xff,umask=0x00"),
        INTEL_UNCORE_EVENT_DESC(cas_count_read,  "event=0x04,umask=0x03"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.unit, "MiB"),
        INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.unit, "MiB"),
        { /* end: all zeroes */ },
 };
 
@@ -486,14 +490,17 @@ static struct attribute_group snbep_uncore_qpi_format_group = {
        .attrs = snbep_uncore_qpi_formats_attr,
 };
 
-#define SNBEP_UNCORE_MSR_OPS_COMMON_INIT()                     \
-       .init_box       = snbep_uncore_msr_init_box,            \
+#define __SNBEP_UNCORE_MSR_OPS_COMMON_INIT()                   \
        .disable_box    = snbep_uncore_msr_disable_box,         \
        .enable_box     = snbep_uncore_msr_enable_box,          \
        .disable_event  = snbep_uncore_msr_disable_event,       \
        .enable_event   = snbep_uncore_msr_enable_event,        \
        .read_counter   = uncore_msr_read_counter
 
+#define SNBEP_UNCORE_MSR_OPS_COMMON_INIT()                     \
+       __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),                   \
+       .init_box       = snbep_uncore_msr_init_box             \
+
 static struct intel_uncore_ops snbep_uncore_msr_ops = {
        SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
 };
@@ -1919,6 +1926,30 @@ static struct intel_uncore_type hswep_uncore_cbox = {
        .format_group           = &hswep_uncore_cbox_format_group,
 };
 
+/*
+ * Write SBOX Initialization register bit by bit to avoid spurious #GPs
+ */
+static void hswep_uncore_sbox_msr_init_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+
+       if (msr) {
+               u64 init = SNBEP_PMON_BOX_CTL_INT;
+               u64 flags = 0;
+               int i;
+
+               for_each_set_bit(i, (unsigned long *)&init, 64) {
+                       flags |= (1ULL << i);
+                       wrmsrl(msr, flags);
+               }
+       }
+}
+
+static struct intel_uncore_ops hswep_uncore_sbox_msr_ops = {
+       __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+       .init_box               = hswep_uncore_sbox_msr_init_box
+};
+
 static struct attribute *hswep_uncore_sbox_formats_attr[] = {
        &format_attr_event.attr,
        &format_attr_umask.attr,
@@ -1944,7 +1975,7 @@ static struct intel_uncore_type hswep_uncore_sbox = {
        .event_mask             = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
        .box_ctl                = HSWEP_S0_MSR_PMON_BOX_CTL,
        .msr_offset             = HSWEP_SBOX_MSR_OFFSET,
-       .ops                    = &snbep_uncore_msr_ops,
+       .ops                    = &hswep_uncore_sbox_msr_ops,
        .format_group           = &hswep_uncore_sbox_format_group,
 };
 
@@ -2009,7 +2040,11 @@ static struct intel_uncore_type hswep_uncore_ha = {
 static struct uncore_event_desc hswep_uncore_imc_events[] = {
        INTEL_UNCORE_EVENT_DESC(clockticks,      "event=0x00,umask=0x00"),
        INTEL_UNCORE_EVENT_DESC(cas_count_read,  "event=0x04,umask=0x03"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.unit, "MiB"),
        INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.unit, "MiB"),
        { /* end: all zeroes */ },
 };
 
@@ -2025,13 +2060,27 @@ static struct intel_uncore_type hswep_uncore_imc = {
        SNBEP_UNCORE_PCI_COMMON_INIT(),
 };
 
+static unsigned hswep_uncore_irp_ctrs[] = {0xa0, 0xa8, 0xb0, 0xb8};
+
+static u64 hswep_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 count = 0;
+
+       pci_read_config_dword(pdev, hswep_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
+       pci_read_config_dword(pdev, hswep_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
+
+       return count;
+}
+
 static struct intel_uncore_ops hswep_uncore_irp_ops = {
        .init_box       = snbep_uncore_pci_init_box,
        .disable_box    = snbep_uncore_pci_disable_box,
        .enable_box     = snbep_uncore_pci_enable_box,
        .disable_event  = ivbep_uncore_irp_disable_event,
        .enable_event   = ivbep_uncore_irp_enable_event,
-       .read_counter   = ivbep_uncore_irp_read_counter,
+       .read_counter   = hswep_uncore_irp_read_counter,
 };
 
 static struct intel_uncore_type hswep_uncore_irp = {
index 1abcb50b48ae042fd06c2581802af0e1af7f49d5..ff86f19b575849fca7e20a4086e09f798ae8291d 100644 (file)
@@ -24,7 +24,6 @@ static char x86_stack_ids[][8] = {
                [ DEBUG_STACK-1                 ]       = "#DB",
                [ NMI_STACK-1                   ]       = "NMI",
                [ DOUBLEFAULT_STACK-1           ]       = "#DF",
-               [ STACKFAULT_STACK-1            ]       = "#SS",
                [ MCE_STACK-1                   ]       = "#MC",
 #if DEBUG_STKSZ > EXCEPTION_STKSZ
                [ N_EXCEPTION_STACKS ...
index b553ed89e5f5e97346ac460934ce6e016b45455f..344b63f18d14b7d5ae1b55a85a8e28fa7a63642d 100644 (file)
@@ -447,15 +447,14 @@ sysenter_exit:
 sysenter_audit:
        testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
        jnz syscall_trace_entry
-       addl $4,%esp
-       CFI_ADJUST_CFA_OFFSET -4
-       movl %esi,4(%esp)               /* 5th arg: 4th syscall arg */
-       movl %edx,(%esp)                /* 4th arg: 3rd syscall arg */
-       /* %ecx already in %ecx            3rd arg: 2nd syscall arg */
-       movl %ebx,%edx                  /* 2nd arg: 1st syscall arg */
-       /* %eax already in %eax            1st arg: syscall number */
+       /* movl PT_EAX(%esp), %eax      already set, syscall number: 1st arg to audit */
+       movl PT_EBX(%esp), %edx         /* ebx/a0: 2nd arg to audit */
+       /* movl PT_ECX(%esp), %ecx      already set, a1: 3nd arg to audit */
+       pushl_cfi PT_ESI(%esp)          /* a3: 5th arg */
+       pushl_cfi PT_EDX+4(%esp)        /* a2: 4th arg */
        call __audit_syscall_entry
-       pushl_cfi %ebx
+       popl_cfi %ecx /* get that remapped edx off the stack */
+       popl_cfi %ecx /* get that remapped esi off the stack */
        movl PT_EAX(%esp),%eax          /* reload syscall number */
        jmp sysenter_do_call
 
index df088bb03fb3ffec9148c7cc44cb65ef1aa36118..c0226ab541061870bb590a9c817d0770e618697c 100644 (file)
@@ -828,9 +828,15 @@ ENTRY(native_iret)
        jnz native_irq_return_ldt
 #endif
 
+.global native_irq_return_iret
 native_irq_return_iret:
+       /*
+        * This may fault.  Non-paranoid faults on return to userspace are
+        * handled by fixup_bad_iret.  These include #SS, #GP, and #NP.
+        * Double-faults due to espfix64 are handled in do_double_fault.
+        * Other faults here are fatal.
+        */
        iretq
-       _ASM_EXTABLE(native_irq_return_iret, bad_iret)
 
 #ifdef CONFIG_X86_ESPFIX64
 native_irq_return_ldt:
@@ -858,25 +864,6 @@ native_irq_return_ldt:
        jmp native_irq_return_iret
 #endif
 
-       .section .fixup,"ax"
-bad_iret:
-       /*
-        * The iret traps when the %cs or %ss being restored is bogus.
-        * We've lost the original trap vector and error code.
-        * #GPF is the most likely one to get for an invalid selector.
-        * So pretend we completed the iret and took the #GPF in user mode.
-        *
-        * We are now running with the kernel GS after exception recovery.
-        * But error_entry expects us to have user GS to match the user %cs,
-        * so swap back.
-        */
-       pushq $0
-
-       SWAPGS
-       jmp general_protection
-
-       .previous
-
        /* edi: workmask, edx: work */
 retint_careful:
        CFI_RESTORE_STATE
@@ -922,37 +909,6 @@ ENTRY(retint_kernel)
        CFI_ENDPROC
 END(common_interrupt)
 
-       /*
-        * If IRET takes a fault on the espfix stack, then we
-        * end up promoting it to a doublefault.  In that case,
-        * modify the stack to make it look like we just entered
-        * the #GP handler from user space, similar to bad_iret.
-        */
-#ifdef CONFIG_X86_ESPFIX64
-       ALIGN
-__do_double_fault:
-       XCPT_FRAME 1 RDI+8
-       movq RSP(%rdi),%rax             /* Trap on the espfix stack? */
-       sarq $PGDIR_SHIFT,%rax
-       cmpl $ESPFIX_PGD_ENTRY,%eax
-       jne do_double_fault             /* No, just deliver the fault */
-       cmpl $__KERNEL_CS,CS(%rdi)
-       jne do_double_fault
-       movq RIP(%rdi),%rax
-       cmpq $native_irq_return_iret,%rax
-       jne do_double_fault             /* This shouldn't happen... */
-       movq PER_CPU_VAR(kernel_stack),%rax
-       subq $(6*8-KERNEL_STACK_OFFSET),%rax    /* Reset to original stack */
-       movq %rax,RSP(%rdi)
-       movq $0,(%rax)                  /* Missing (lost) #GP error code */
-       movq $general_protection,RIP(%rdi)
-       retq
-       CFI_ENDPROC
-END(__do_double_fault)
-#else
-# define __do_double_fault do_double_fault
-#endif
-
 /*
  * APIC interrupts.
  */
@@ -1124,7 +1080,7 @@ idtentry overflow do_overflow has_error_code=0
 idtentry bounds do_bounds has_error_code=0
 idtentry invalid_op do_invalid_op has_error_code=0
 idtentry device_not_available do_device_not_available has_error_code=0
-idtentry double_fault __do_double_fault has_error_code=1 paranoid=1
+idtentry double_fault do_double_fault has_error_code=1 paranoid=1
 idtentry coprocessor_segment_overrun do_coprocessor_segment_overrun has_error_code=0
 idtentry invalid_TSS do_invalid_TSS has_error_code=1
 idtentry segment_not_present do_segment_not_present has_error_code=1
@@ -1289,7 +1245,7 @@ apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \
 
 idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
 idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
-idtentry stack_segment do_stack_segment has_error_code=1 paranoid=1
+idtentry stack_segment do_stack_segment has_error_code=1
 #ifdef CONFIG_XEN
 idtentry xen_debug do_debug has_error_code=0
 idtentry xen_int3 do_int3 has_error_code=0
@@ -1399,17 +1355,16 @@ error_sti:
 
 /*
  * There are two places in the kernel that can potentially fault with
- * usergs. Handle them here. The exception handlers after iret run with
- * kernel gs again, so don't set the user space flag. B stepping K8s
- * sometimes report an truncated RIP for IRET exceptions returning to
- * compat mode. Check for these here too.
+ * usergs. Handle them here.  B stepping K8s sometimes report a
+ * truncated RIP for IRET exceptions returning to compat mode. Check
+ * for these here too.
  */
 error_kernelspace:
        CFI_REL_OFFSET rcx, RCX+8
        incl %ebx
        leaq native_irq_return_iret(%rip),%rcx
        cmpq %rcx,RIP+8(%rsp)
-       je error_swapgs
+       je error_bad_iret
        movl %ecx,%eax  /* zero extend */
        cmpq %rax,RIP+8(%rsp)
        je bstep_iret
@@ -1420,7 +1375,15 @@ error_kernelspace:
 bstep_iret:
        /* Fix truncated RIP */
        movq %rcx,RIP+8(%rsp)
-       jmp error_swapgs
+       /* fall through */
+
+error_bad_iret:
+       SWAPGS
+       mov %rsp,%rdi
+       call fixup_bad_iret
+       mov %rax,%rsp
+       decl %ebx       /* Return to usergs */
+       jmp error_sti
        CFI_ENDPROC
 END(error_entry)
 
index 8af817105e29cbc25ffaa8b2430a57c5de782dd6..e7cc5370cd2fcade87dc1cecae2ab85184f62d27 100644 (file)
@@ -111,8 +111,7 @@ static void make_8259A_irq(unsigned int irq)
 {
        disable_irq_nosync(irq);
        io_apic_irqs &= ~(1<<irq);
-       irq_set_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
-                                     i8259A_chip.name);
+       irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
        enable_irq(irq);
 }
 
index 44f1ed42fdf2136c0b2654256745d20edca1a28d..4de73ee78361311493163414dc7439b7bbea75e5 100644 (file)
@@ -70,7 +70,6 @@ int vector_used_by_percpu_irq(unsigned int vector)
 void __init init_ISA_irqs(void)
 {
        struct irq_chip *chip = legacy_pic->chip;
-       const char *name = chip->name;
        int i;
 
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
@@ -79,7 +78,7 @@ void __init init_ISA_irqs(void)
        legacy_pic->init(0);
 
        for (i = 0; i < nr_legacy_irqs(); i++)
-               irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
+               irq_set_chip_and_handler(i, chip, handle_level_irq);
 }
 
 void __init init_IRQ(void)
index 749b0e423419fee7b97698e725dc6d665c1aa828..e510618b2e91a7969bb8cf6c74a35f59e4bf1bea 100644 (file)
@@ -1484,7 +1484,7 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
         */
        if (work & _TIF_NOHZ) {
                user_exit();
-               work &= ~TIF_NOHZ;
+               work &= ~_TIF_NOHZ;
        }
 
 #ifdef CONFIG_SECCOMP
index 235cfd39e0d793c23299da10a9eb45f7b29006a4..ab08aa2276fb803a83c5cbf369b6dc69d605a0f8 100644 (file)
@@ -1128,7 +1128,6 @@ void __init setup_arch(char **cmdline_p)
        setup_real_mode();
 
        memblock_set_current_limit(get_max_mapped());
-       dma_contiguous_reserve(max_pfn_mapped << PAGE_SHIFT);
 
        /*
         * NOTE: On x86-32, only from this point on, fixmaps are ready for use.
@@ -1159,6 +1158,7 @@ void __init setup_arch(char **cmdline_p)
        early_acpi_boot_init();
 
        initmem_init();
+       dma_contiguous_reserve(max_pfn_mapped << PAGE_SHIFT);
 
        /*
         * Reserve memory for crash kernel after SRAT is parsed so that it
index 2d5200e56357d49f3466ce55e8ab2b3273306f68..668d8f2a8781ea11fab5110315a946171b0e274d 100644 (file)
@@ -102,8 +102,6 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
 DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
 EXPORT_PER_CPU_SYMBOL(cpu_info);
 
-static DEFINE_PER_CPU(struct completion, die_complete);
-
 atomic_t init_deasserted;
 
 /*
@@ -1305,10 +1303,14 @@ static void __ref remove_cpu_from_maps(int cpu)
        numa_remove_cpu(cpu);
 }
 
+static DEFINE_PER_CPU(struct completion, die_complete);
+
 void cpu_disable_common(void)
 {
        int cpu = smp_processor_id();
 
+       init_completion(&per_cpu(die_complete, smp_processor_id()));
+
        remove_siblinginfo(cpu);
 
        /* It's now safe to remove this processor from the online map */
@@ -1327,16 +1329,21 @@ int native_cpu_disable(void)
                return ret;
 
        clear_local_APIC();
-       init_completion(&per_cpu(die_complete, smp_processor_id()));
        cpu_disable_common();
 
        return 0;
 }
 
+void cpu_die_common(unsigned int cpu)
+{
+       wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ);
+}
+
 void native_cpu_die(unsigned int cpu)
 {
        /* We don't do anything here: idle task is faking death itself. */
-       wait_for_completion_timeout(&per_cpu(die_complete, cpu), HZ);
+
+       cpu_die_common(cpu);
 
        /* They ack this in play_dead() by setting CPU_DEAD */
        if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
index 0d0e922fafc149400b4320c793e1d311c96d147b..07ab8e9733c5ae18ace7b905c6ff3d2a0499aac6 100644 (file)
@@ -233,32 +233,40 @@ DO_ERROR(X86_TRAP_UD,     SIGILL,  "invalid opcode",              invalid_op)
 DO_ERROR(X86_TRAP_OLD_MF, SIGFPE,  "coprocessor segment overrun",coprocessor_segment_overrun)
 DO_ERROR(X86_TRAP_TS,     SIGSEGV, "invalid TSS",              invalid_TSS)
 DO_ERROR(X86_TRAP_NP,     SIGBUS,  "segment not present",      segment_not_present)
-#ifdef CONFIG_X86_32
 DO_ERROR(X86_TRAP_SS,     SIGBUS,  "stack segment",            stack_segment)
-#endif
 DO_ERROR(X86_TRAP_AC,     SIGBUS,  "alignment check",          alignment_check)
 
 #ifdef CONFIG_X86_64
 /* Runs on IST stack */
-dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
-{
-       enum ctx_state prev_state;
-
-       prev_state = exception_enter();
-       if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
-                      X86_TRAP_SS, SIGBUS) != NOTIFY_STOP) {
-               preempt_conditional_sti(regs);
-               do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
-               preempt_conditional_cli(regs);
-       }
-       exception_exit(prev_state);
-}
-
 dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
 {
        static const char str[] = "double fault";
        struct task_struct *tsk = current;
 
+#ifdef CONFIG_X86_ESPFIX64
+       extern unsigned char native_irq_return_iret[];
+
+       /*
+        * If IRET takes a non-IST fault on the espfix64 stack, then we
+        * end up promoting it to a doublefault.  In that case, modify
+        * the stack to make it look like we just entered the #GP
+        * handler from user space, similar to bad_iret.
+        */
+       if (((long)regs->sp >> PGDIR_SHIFT) == ESPFIX_PGD_ENTRY &&
+               regs->cs == __KERNEL_CS &&
+               regs->ip == (unsigned long)native_irq_return_iret)
+       {
+               struct pt_regs *normal_regs = task_pt_regs(current);
+
+               /* Fake a #GP(0) from userspace. */
+               memmove(&normal_regs->ip, (void *)regs->sp, 5*8);
+               normal_regs->orig_ax = 0;  /* Missing (lost) #GP error code */
+               regs->ip = (unsigned long)general_protection;
+               regs->sp = (unsigned long)&normal_regs->orig_ax;
+               return;
+       }
+#endif
+
        exception_enter();
        /* Return not checked because double check cannot be ignored */
        notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
@@ -379,7 +387,7 @@ NOKPROBE_SYMBOL(do_int3);
  * for scheduling or signal handling. The actual stack switch is done in
  * entry.S
  */
-asmlinkage __visible struct pt_regs *sync_regs(struct pt_regs *eregs)
+asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs)
 {
        struct pt_regs *regs = eregs;
        /* Did already sync */
@@ -399,6 +407,36 @@ asmlinkage __visible struct pt_regs *sync_regs(struct pt_regs *eregs)
        return regs;
 }
 NOKPROBE_SYMBOL(sync_regs);
+
+struct bad_iret_stack {
+       void *error_entry_ret;
+       struct pt_regs regs;
+};
+
+asmlinkage __visible notrace
+struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
+{
+       /*
+        * This is called from entry_64.S early in handling a fault
+        * caused by a bad iret to user mode.  To handle the fault
+        * correctly, we want move our stack frame to task_pt_regs
+        * and we want to pretend that the exception came from the
+        * iret target.
+        */
+       struct bad_iret_stack *new_stack =
+               container_of(task_pt_regs(current),
+                            struct bad_iret_stack, regs);
+
+       /* Copy the IRET target to the new stack. */
+       memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8);
+
+       /* Copy the remainder of the stack from the current stack. */
+       memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip));
+
+       BUG_ON(!user_mode_vm(&new_stack->regs));
+       return new_stack;
+}
+NOKPROBE_SYMBOL(fixup_bad_iret);
 #endif
 
 /*
@@ -778,7 +816,7 @@ void __init trap_init(void)
        set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun);
        set_intr_gate(X86_TRAP_TS, invalid_TSS);
        set_intr_gate(X86_TRAP_NP, segment_not_present);
-       set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK);
+       set_intr_gate(X86_TRAP_SS, stack_segment);
        set_intr_gate(X86_TRAP_GP, general_protection);
        set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug);
        set_intr_gate(X86_TRAP_MF, coprocessor_error);
index b6025f9e36c65d7e83ddf05a7da99922a703a31e..b7e50bba3bbbb98066fac741d826e5f6f4d7e946 100644 (file)
@@ -1166,14 +1166,17 @@ void __init tsc_init(void)
 
        x86_init.timers.tsc_pre_init();
 
-       if (!cpu_has_tsc)
+       if (!cpu_has_tsc) {
+               setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
                return;
+       }
 
        tsc_khz = x86_platform.calibrate_tsc();
        cpu_khz = tsc_khz;
 
        if (!tsc_khz) {
                mark_tsc_unstable("could not calculate TSC khz");
+               setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
                return;
        }
 
index a46207a0583508ad662d179f2db1ede320a7645e..9f8a2faf50407b6212f71a5de81aea8680855f87 100644 (file)
@@ -504,11 +504,6 @@ static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc)
        masked_increment(reg_rmw(ctxt, VCPU_REGS_RSP), stack_mask(ctxt), inc);
 }
 
-static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
-{
-       register_address_increment(ctxt, &ctxt->_eip, rel);
-}
-
 static u32 desc_limit_scaled(struct desc_struct *desc)
 {
        u32 limit = get_desc_limit(desc);
@@ -569,6 +564,40 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt)
        return emulate_exception(ctxt, NM_VECTOR, 0, false);
 }
 
+static inline int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
+                              int cs_l)
+{
+       switch (ctxt->op_bytes) {
+       case 2:
+               ctxt->_eip = (u16)dst;
+               break;
+       case 4:
+               ctxt->_eip = (u32)dst;
+               break;
+#ifdef CONFIG_X86_64
+       case 8:
+               if ((cs_l && is_noncanonical_address(dst)) ||
+                   (!cs_l && (dst >> 32) != 0))
+                       return emulate_gp(ctxt, 0);
+               ctxt->_eip = dst;
+               break;
+#endif
+       default:
+               WARN(1, "unsupported eip assignment size\n");
+       }
+       return X86EMUL_CONTINUE;
+}
+
+static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
+{
+       return assign_eip_far(ctxt, dst, ctxt->mode == X86EMUL_MODE_PROT64);
+}
+
+static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
+{
+       return assign_eip_near(ctxt, ctxt->_eip + rel);
+}
+
 static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg)
 {
        u16 selector;
@@ -614,7 +643,8 @@ static bool insn_aligned(struct x86_emulate_ctxt *ctxt, unsigned size)
 
 static int __linearize(struct x86_emulate_ctxt *ctxt,
                     struct segmented_address addr,
-                    unsigned size, bool write, bool fetch,
+                    unsigned *max_size, unsigned size,
+                    bool write, bool fetch,
                     ulong *linear)
 {
        struct desc_struct desc;
@@ -625,10 +655,15 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
        unsigned cpl;
 
        la = seg_base(ctxt, addr.seg) + addr.ea;
+       *max_size = 0;
        switch (ctxt->mode) {
        case X86EMUL_MODE_PROT64:
                if (((signed long)la << 16) >> 16 != la)
                        return emulate_gp(ctxt, 0);
+
+               *max_size = min_t(u64, ~0u, (1ull << 48) - la);
+               if (size > *max_size)
+                       goto bad;
                break;
        default:
                usable = ctxt->ops->get_segment(ctxt, &sel, &desc, NULL,
@@ -646,20 +681,25 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
                if ((ctxt->mode == X86EMUL_MODE_REAL) && !fetch &&
                    (ctxt->d & NoBigReal)) {
                        /* la is between zero and 0xffff */
-                       if (la > 0xffff || (u32)(la + size - 1) > 0xffff)
+                       if (la > 0xffff)
                                goto bad;
+                       *max_size = 0x10000 - la;
                } else if ((desc.type & 8) || !(desc.type & 4)) {
                        /* expand-up segment */
-                       if (addr.ea > lim || (u32)(addr.ea + size - 1) > lim)
+                       if (addr.ea > lim)
                                goto bad;
+                       *max_size = min_t(u64, ~0u, (u64)lim + 1 - addr.ea);
                } else {
                        /* expand-down segment */
-                       if (addr.ea <= lim || (u32)(addr.ea + size - 1) <= lim)
+                       if (addr.ea <= lim)
                                goto bad;
                        lim = desc.d ? 0xffffffff : 0xffff;
-                       if (addr.ea > lim || (u32)(addr.ea + size - 1) > lim)
+                       if (addr.ea > lim)
                                goto bad;
+                       *max_size = min_t(u64, ~0u, (u64)lim + 1 - addr.ea);
                }
+               if (size > *max_size)
+                       goto bad;
                cpl = ctxt->ops->cpl(ctxt);
                if (!(desc.type & 8)) {
                        /* data segment */
@@ -684,9 +724,9 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
        return X86EMUL_CONTINUE;
 bad:
        if (addr.seg == VCPU_SREG_SS)
-               return emulate_ss(ctxt, sel);
+               return emulate_ss(ctxt, 0);
        else
-               return emulate_gp(ctxt, sel);
+               return emulate_gp(ctxt, 0);
 }
 
 static int linearize(struct x86_emulate_ctxt *ctxt,
@@ -694,7 +734,8 @@ static int linearize(struct x86_emulate_ctxt *ctxt,
                     unsigned size, bool write,
                     ulong *linear)
 {
-       return __linearize(ctxt, addr, size, write, false, linear);
+       unsigned max_size;
+       return __linearize(ctxt, addr, &max_size, size, write, false, linear);
 }
 
 
@@ -719,17 +760,27 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
 static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
 {
        int rc;
-       unsigned size;
+       unsigned size, max_size;
        unsigned long linear;
        int cur_size = ctxt->fetch.end - ctxt->fetch.data;
        struct segmented_address addr = { .seg = VCPU_SREG_CS,
                                           .ea = ctxt->eip + cur_size };
 
-       size = 15UL ^ cur_size;
-       rc = __linearize(ctxt, addr, size, false, true, &linear);
+       /*
+        * We do not know exactly how many bytes will be needed, and
+        * __linearize is expensive, so fetch as much as possible.  We
+        * just have to avoid going beyond the 15 byte limit, the end
+        * of the segment, or the end of the page.
+        *
+        * __linearize is called with size 0 so that it does not do any
+        * boundary check itself.  Instead, we use max_size to check
+        * against op_size.
+        */
+       rc = __linearize(ctxt, addr, &max_size, 0, false, true, &linear);
        if (unlikely(rc != X86EMUL_CONTINUE))
                return rc;
 
+       size = min_t(unsigned, 15UL ^ cur_size, max_size);
        size = min_t(unsigned, size, PAGE_SIZE - offset_in_page(linear));
 
        /*
@@ -739,7 +790,8 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
         * still, we must have hit the 15-byte boundary.
         */
        if (unlikely(size < op_size))
-               return X86EMUL_UNHANDLEABLE;
+               return emulate_gp(ctxt, 0);
+
        rc = ctxt->ops->fetch(ctxt, linear, ctxt->fetch.end,
                              size, &ctxt->exception);
        if (unlikely(rc != X86EMUL_CONTINUE))
@@ -751,8 +803,10 @@ static int __do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt, int op_size)
 static __always_inline int do_insn_fetch_bytes(struct x86_emulate_ctxt *ctxt,
                                               unsigned size)
 {
-       if (unlikely(ctxt->fetch.end - ctxt->fetch.ptr < size))
-               return __do_insn_fetch_bytes(ctxt, size);
+       unsigned done_size = ctxt->fetch.end - ctxt->fetch.ptr;
+
+       if (unlikely(done_size < size))
+               return __do_insn_fetch_bytes(ctxt, size - done_size);
        else
                return X86EMUL_CONTINUE;
 }
@@ -1416,7 +1470,9 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 
 /* Does not support long mode */
 static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
-                                    u16 selector, int seg, u8 cpl, bool in_task_switch)
+                                    u16 selector, int seg, u8 cpl,
+                                    bool in_task_switch,
+                                    struct desc_struct *desc)
 {
        struct desc_struct seg_desc, old_desc;
        u8 dpl, rpl;
@@ -1557,6 +1613,8 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
        }
 load:
        ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg);
+       if (desc)
+               *desc = seg_desc;
        return X86EMUL_CONTINUE;
 exception:
        return emulate_exception(ctxt, err_vec, err_code, true);
@@ -1566,7 +1624,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                                   u16 selector, int seg)
 {
        u8 cpl = ctxt->ops->cpl(ctxt);
-       return __load_segment_descriptor(ctxt, selector, seg, cpl, false);
+       return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL);
 }
 
 static void write_register_operand(struct operand *op)
@@ -1960,17 +2018,31 @@ static int em_iret(struct x86_emulate_ctxt *ctxt)
 static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
 {
        int rc;
-       unsigned short sel;
+       unsigned short sel, old_sel;
+       struct desc_struct old_desc, new_desc;
+       const struct x86_emulate_ops *ops = ctxt->ops;
+       u8 cpl = ctxt->ops->cpl(ctxt);
+
+       /* Assignment of RIP may only fail in 64-bit mode */
+       if (ctxt->mode == X86EMUL_MODE_PROT64)
+               ops->get_segment(ctxt, &old_sel, &old_desc, NULL,
+                                VCPU_SREG_CS);
 
        memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
 
-       rc = load_segment_descriptor(ctxt, sel, VCPU_SREG_CS);
+       rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
+                                      &new_desc);
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
-       ctxt->_eip = 0;
-       memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
-       return X86EMUL_CONTINUE;
+       rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
+       if (rc != X86EMUL_CONTINUE) {
+               WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
+               /* assigning eip failed; restore the old cs */
+               ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
+               return rc;
+       }
+       return rc;
 }
 
 static int em_grp45(struct x86_emulate_ctxt *ctxt)
@@ -1981,13 +2053,15 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
        case 2: /* call near abs */ {
                long int old_eip;
                old_eip = ctxt->_eip;
-               ctxt->_eip = ctxt->src.val;
+               rc = assign_eip_near(ctxt, ctxt->src.val);
+               if (rc != X86EMUL_CONTINUE)
+                       break;
                ctxt->src.val = old_eip;
                rc = em_push(ctxt);
                break;
        }
        case 4: /* jmp abs */
-               ctxt->_eip = ctxt->src.val;
+               rc = assign_eip_near(ctxt, ctxt->src.val);
                break;
        case 5: /* jmp far */
                rc = em_jmp_far(ctxt);
@@ -2022,30 +2096,47 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
 
 static int em_ret(struct x86_emulate_ctxt *ctxt)
 {
-       ctxt->dst.type = OP_REG;
-       ctxt->dst.addr.reg = &ctxt->_eip;
-       ctxt->dst.bytes = ctxt->op_bytes;
-       return em_pop(ctxt);
+       int rc;
+       unsigned long eip;
+
+       rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+
+       return assign_eip_near(ctxt, eip);
 }
 
 static int em_ret_far(struct x86_emulate_ctxt *ctxt)
 {
        int rc;
-       unsigned long cs;
+       unsigned long eip, cs;
+       u16 old_cs;
        int cpl = ctxt->ops->cpl(ctxt);
+       struct desc_struct old_desc, new_desc;
+       const struct x86_emulate_ops *ops = ctxt->ops;
 
-       rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
+       if (ctxt->mode == X86EMUL_MODE_PROT64)
+               ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
+                                VCPU_SREG_CS);
+
+       rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
        if (rc != X86EMUL_CONTINUE)
                return rc;
-       if (ctxt->op_bytes == 4)
-               ctxt->_eip = (u32)ctxt->_eip;
        rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
        if (rc != X86EMUL_CONTINUE)
                return rc;
        /* Outer-privilege level return is not implemented */
        if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl)
                return X86EMUL_UNHANDLEABLE;
-       rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
+       rc = __load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS, 0, false,
+                                      &new_desc);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+       rc = assign_eip_far(ctxt, eip, new_desc.l);
+       if (rc != X86EMUL_CONTINUE) {
+               WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
+               ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
+       }
        return rc;
 }
 
@@ -2306,7 +2397,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
 {
        const struct x86_emulate_ops *ops = ctxt->ops;
        struct desc_struct cs, ss;
-       u64 msr_data;
+       u64 msr_data, rcx, rdx;
        int usermode;
        u16 cs_sel = 0, ss_sel = 0;
 
@@ -2322,6 +2413,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
        else
                usermode = X86EMUL_MODE_PROT32;
 
+       rcx = reg_read(ctxt, VCPU_REGS_RCX);
+       rdx = reg_read(ctxt, VCPU_REGS_RDX);
+
        cs.dpl = 3;
        ss.dpl = 3;
        ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
@@ -2339,6 +2433,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
                ss_sel = cs_sel + 8;
                cs.d = 0;
                cs.l = 1;
+               if (is_noncanonical_address(rcx) ||
+                   is_noncanonical_address(rdx))
+                       return emulate_gp(ctxt, 0);
                break;
        }
        cs_sel |= SELECTOR_RPL_MASK;
@@ -2347,8 +2444,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
        ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
        ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
-       ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX);
-       *reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX);
+       ctxt->_eip = rdx;
+       *reg_write(ctxt, VCPU_REGS_RSP) = rcx;
 
        return X86EMUL_CONTINUE;
 }
@@ -2466,19 +2563,24 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
         * Now load segment descriptors. If fault happens at this stage
         * it is handled in a context of new task
         */
-       ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
 
@@ -2603,25 +2705,32 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
         * Now load segment descriptors. If fault happenes at this stage
         * it is handled in a context of new task
         */
-       ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR,
+                                       cpl, true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
-       ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl, true);
+       ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl,
+                                       true, NULL);
        if (ret != X86EMUL_CONTINUE)
                return ret;
 
@@ -2888,10 +2997,13 @@ static int em_aad(struct x86_emulate_ctxt *ctxt)
 
 static int em_call(struct x86_emulate_ctxt *ctxt)
 {
+       int rc;
        long rel = ctxt->src.val;
 
        ctxt->src.val = (unsigned long)ctxt->_eip;
-       jmp_rel(ctxt, rel);
+       rc = jmp_rel(ctxt, rel);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
        return em_push(ctxt);
 }
 
@@ -2900,34 +3012,50 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
        u16 sel, old_cs;
        ulong old_eip;
        int rc;
+       struct desc_struct old_desc, new_desc;
+       const struct x86_emulate_ops *ops = ctxt->ops;
+       int cpl = ctxt->ops->cpl(ctxt);
 
-       old_cs = get_segment_selector(ctxt, VCPU_SREG_CS);
        old_eip = ctxt->_eip;
+       ops->get_segment(ctxt, &old_cs, &old_desc, NULL, VCPU_SREG_CS);
 
        memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
-       if (load_segment_descriptor(ctxt, sel, VCPU_SREG_CS))
+       rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false,
+                                      &new_desc);
+       if (rc != X86EMUL_CONTINUE)
                return X86EMUL_CONTINUE;
 
-       ctxt->_eip = 0;
-       memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes);
+       rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
+       if (rc != X86EMUL_CONTINUE)
+               goto fail;
 
        ctxt->src.val = old_cs;
        rc = em_push(ctxt);
        if (rc != X86EMUL_CONTINUE)
-               return rc;
+               goto fail;
 
        ctxt->src.val = old_eip;
-       return em_push(ctxt);
+       rc = em_push(ctxt);
+       /* If we failed, we tainted the memory, but the very least we should
+          restore cs */
+       if (rc != X86EMUL_CONTINUE)
+               goto fail;
+       return rc;
+fail:
+       ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
+       return rc;
+
 }
 
 static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
 {
        int rc;
+       unsigned long eip;
 
-       ctxt->dst.type = OP_REG;
-       ctxt->dst.addr.reg = &ctxt->_eip;
-       ctxt->dst.bytes = ctxt->op_bytes;
-       rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
+       rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+       rc = assign_eip_near(ctxt, eip);
        if (rc != X86EMUL_CONTINUE)
                return rc;
        rsp_increment(ctxt, ctxt->src.val);
@@ -3254,20 +3382,24 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt)
 
 static int em_loop(struct x86_emulate_ctxt *ctxt)
 {
+       int rc = X86EMUL_CONTINUE;
+
        register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1);
        if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) &&
            (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
-               jmp_rel(ctxt, ctxt->src.val);
+               rc = jmp_rel(ctxt, ctxt->src.val);
 
-       return X86EMUL_CONTINUE;
+       return rc;
 }
 
 static int em_jcxz(struct x86_emulate_ctxt *ctxt)
 {
+       int rc = X86EMUL_CONTINUE;
+
        if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0)
-               jmp_rel(ctxt, ctxt->src.val);
+               rc = jmp_rel(ctxt, ctxt->src.val);
 
-       return X86EMUL_CONTINUE;
+       return rc;
 }
 
 static int em_in(struct x86_emulate_ctxt *ctxt)
@@ -3355,6 +3487,12 @@ static int em_bswap(struct x86_emulate_ctxt *ctxt)
        return X86EMUL_CONTINUE;
 }
 
+static int em_clflush(struct x86_emulate_ctxt *ctxt)
+{
+       /* emulating clflush regardless of cpuid */
+       return X86EMUL_CONTINUE;
+}
+
 static bool valid_cr(int nr)
 {
        switch (nr) {
@@ -3693,6 +3831,16 @@ static const struct opcode group11[] = {
        X7(D(Undefined)),
 };
 
+static const struct gprefix pfx_0f_ae_7 = {
+       I(SrcMem | ByteOp, em_clflush), N, N, N,
+};
+
+static const struct group_dual group15 = { {
+       N, N, N, N, N, N, N, GP(0, &pfx_0f_ae_7),
+}, {
+       N, N, N, N, N, N, N, N,
+} };
+
 static const struct gprefix pfx_0f_6f_0f_7f = {
        I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
 };
@@ -3901,10 +4049,11 @@ static const struct opcode twobyte_table[256] = {
        N, I(ImplicitOps | EmulateOnUD, em_syscall),
        II(ImplicitOps | Priv, em_clts, clts), N,
        DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
-       N, D(ImplicitOps | ModRM), N, N,
+       N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N,
        /* 0x10 - 0x1F */
        N, N, N, N, N, N, N, N,
-       D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM),
+       D(ImplicitOps | ModRM | SrcMem | NoAccess),
+       N, N, N, N, N, N, D(ImplicitOps | ModRM | SrcMem | NoAccess),
        /* 0x20 - 0x2F */
        DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_read),
        DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read),
@@ -3956,7 +4105,7 @@ static const struct opcode twobyte_table[256] = {
        F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts),
        F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd),
        F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
-       D(ModRM), F(DstReg | SrcMem | ModRM, em_imul),
+       GD(0, &group15), F(DstReg | SrcMem | ModRM, em_imul),
        /* 0xB0 - 0xB7 */
        I2bv(DstMem | SrcReg | ModRM | Lock | PageTable, em_cmpxchg),
        I(DstReg | SrcMemFAddr | ModRM | Src2SS, em_lseg),
@@ -4138,6 +4287,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
                fetch_register_operand(op);
                break;
        case OpCL:
+               op->type = OP_IMM;
                op->bytes = 1;
                op->val = reg_read(ctxt, VCPU_REGS_RCX) & 0xff;
                break;
@@ -4145,6 +4295,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
                rc = decode_imm(ctxt, op, 1, true);
                break;
        case OpOne:
+               op->type = OP_IMM;
                op->bytes = 1;
                op->val = 1;
                break;
@@ -4203,21 +4354,27 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
                ctxt->memop.bytes = ctxt->op_bytes + 2;
                goto mem_common;
        case OpES:
+               op->type = OP_IMM;
                op->val = VCPU_SREG_ES;
                break;
        case OpCS:
+               op->type = OP_IMM;
                op->val = VCPU_SREG_CS;
                break;
        case OpSS:
+               op->type = OP_IMM;
                op->val = VCPU_SREG_SS;
                break;
        case OpDS:
+               op->type = OP_IMM;
                op->val = VCPU_SREG_DS;
                break;
        case OpFS:
+               op->type = OP_IMM;
                op->val = VCPU_SREG_FS;
                break;
        case OpGS:
+               op->type = OP_IMM;
                op->val = VCPU_SREG_GS;
                break;
        case OpImplicit:
@@ -4473,10 +4630,10 @@ done_prefixes:
        /* Decode and fetch the destination operand: register or memory. */
        rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
 
-done:
        if (ctxt->rip_relative)
                ctxt->memopp->addr.mem.ea += ctxt->_eip;
 
+done:
        return (rc != X86EMUL_CONTINUE) ? EMULATION_FAILED : EMULATION_OK;
 }
 
@@ -4726,7 +4883,7 @@ special_insn:
                break;
        case 0x70 ... 0x7f: /* jcc (short) */
                if (test_cc(ctxt->b, ctxt->eflags))
-                       jmp_rel(ctxt, ctxt->src.val);
+                       rc = jmp_rel(ctxt, ctxt->src.val);
                break;
        case 0x8d: /* lea r16/r32, m */
                ctxt->dst.val = ctxt->src.addr.mem.ea;
@@ -4756,7 +4913,7 @@ special_insn:
                break;
        case 0xe9: /* jmp rel */
        case 0xeb: /* jmp rel short */
-               jmp_rel(ctxt, ctxt->src.val);
+               rc = jmp_rel(ctxt, ctxt->src.val);
                ctxt->dst.type = OP_NONE; /* Disable writeback. */
                break;
        case 0xf4:              /* hlt */
@@ -4881,13 +5038,11 @@ twobyte_insn:
                break;
        case 0x80 ... 0x8f: /* jnz rel, etc*/
                if (test_cc(ctxt->b, ctxt->eflags))
-                       jmp_rel(ctxt, ctxt->src.val);
+                       rc = jmp_rel(ctxt, ctxt->src.val);
                break;
        case 0x90 ... 0x9f:     /* setcc r/m8 */
                ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
                break;
-       case 0xae:              /* clflush */
-               break;
        case 0xb6 ... 0xb7:     /* movzx */
                ctxt->dst.bytes = ctxt->op_bytes;
                ctxt->dst.val = (ctxt->src.bytes == 1) ? (u8) ctxt->src.val
index 518d86471b76f0be7460c6e038755a18083b26b4..298781d4cfb44b7c6d6536d6d2779ada2eeb150a 100644 (file)
@@ -262,8 +262,10 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
                return;
 
        timer = &pit->pit_state.timer;
+       mutex_lock(&pit->pit_state.lock);
        if (hrtimer_cancel(timer))
                hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
+       mutex_unlock(&pit->pit_state.lock);
 }
 
 static void destroy_pit_timer(struct kvm_pit *pit)
index ac1c4de3a48491d9b0cf939897e9af57238b3f71..978f402006eef21ee569720a0d573a6a48e12c97 100644 (file)
@@ -630,7 +630,7 @@ static int mmu_spte_clear_track_bits(u64 *sptep)
         * kvm mmu, before reclaiming the page, we should
         * unmap it from mmu first.
         */
-       WARN_ON(!kvm_is_mmio_pfn(pfn) && !page_count(pfn_to_page(pfn)));
+       WARN_ON(!kvm_is_reserved_pfn(pfn) && !page_count(pfn_to_page(pfn)));
 
        if (!shadow_accessed_mask || old_spte & shadow_accessed_mask)
                kvm_set_pfn_accessed(pfn);
@@ -2461,7 +2461,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                spte |= PT_PAGE_SIZE_MASK;
        if (tdp_enabled)
                spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn,
-                       kvm_is_mmio_pfn(pfn));
+                       kvm_is_reserved_pfn(pfn));
 
        if (host_writable)
                spte |= SPTE_HOST_WRITEABLE;
@@ -2737,7 +2737,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
         * PT_PAGE_TABLE_LEVEL and there would be no adjustment done
         * here.
         */
-       if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
+       if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
            level == PT_PAGE_TABLE_LEVEL &&
            PageTransCompound(pfn_to_page(pfn)) &&
            !has_wrprotected_page(vcpu->kvm, gfn, PT_DIRECTORY_LEVEL)) {
index 806d58e3c320ae8d7f703bb745cd988c73c07b77..fd49c867b25a11927fc2f6ef4522e1ef9ee80c11 100644 (file)
@@ -298,7 +298,7 @@ retry_walk:
        }
 #endif
        walker->max_level = walker->level;
-       ASSERT(!is_long_mode(vcpu) && is_pae(vcpu));
+       ASSERT(!(is_long_mode(vcpu) && !is_pae(vcpu)));
 
        accessed_dirty = PT_GUEST_ACCESSED_MASK;
        pt_access = pte_access = ACC_ALL;
index 65510f624dfe2a42571bc22e73d8755a23e801e5..7527cefc5a43ac9f24a6b1bea6c1eab43299421f 100644 (file)
@@ -3251,7 +3251,7 @@ static int wrmsr_interception(struct vcpu_svm *svm)
        msr.host_initiated = false;
 
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
-       if (svm_set_msr(&svm->vcpu, &msr)) {
+       if (kvm_set_msr(&svm->vcpu, &msr)) {
                trace_kvm_msr_write_ex(ecx, data);
                kvm_inject_gp(&svm->vcpu, 0);
        } else {
@@ -3551,9 +3551,9 @@ static int handle_exit(struct kvm_vcpu *vcpu)
 
        if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
            || !svm_exit_handlers[exit_code]) {
-               kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
-               kvm_run->hw.hardware_exit_reason = exit_code;
-               return 0;
+               WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_code);
+               kvm_queue_exception(vcpu, UD_VECTOR);
+               return 1;
        }
 
        return svm_exit_handlers[exit_code](svm);
index 0acac81f198b0b03c83b4f4f9ef86178fa84f821..3e556c68351b7a1356c05e7fe94c6c0895d9755d 100644 (file)
@@ -2659,12 +2659,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        default:
                msr = find_msr_entry(vmx, msr_index);
                if (msr) {
+                       u64 old_msr_data = msr->data;
                        msr->data = data;
                        if (msr - vmx->guest_msrs < vmx->save_nmsrs) {
                                preempt_disable();
-                               kvm_set_shared_msr(msr->index, msr->data,
-                                                  msr->mask);
+                               ret = kvm_set_shared_msr(msr->index, msr->data,
+                                                        msr->mask);
                                preempt_enable();
+                               if (ret)
+                                       msr->data = old_msr_data;
                        }
                        break;
                }
@@ -4576,7 +4579,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu)
                vmcs_write32(TPR_THRESHOLD, 0);
        }
 
-       kvm_vcpu_reload_apic_access_page(vcpu);
+       kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
 
        if (vmx_vm_has_apicv(vcpu->kvm))
                memset(&vmx->pi_desc, 0, sizeof(struct pi_desc));
@@ -5291,7 +5294,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu)
        msr.data = data;
        msr.index = ecx;
        msr.host_initiated = false;
-       if (vmx_set_msr(vcpu, &msr) != 0) {
+       if (kvm_set_msr(vcpu, &msr) != 0) {
                trace_kvm_msr_write_ex(ecx, data);
                kvm_inject_gp(vcpu, 0);
                return 1;
@@ -6423,6 +6426,8 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
        const unsigned long *fields = shadow_read_write_fields;
        const int num_fields = max_shadow_read_write_fields;
 
+       preempt_disable();
+
        vmcs_load(shadow_vmcs);
 
        for (i = 0; i < num_fields; i++) {
@@ -6446,6 +6451,8 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
 
        vmcs_clear(shadow_vmcs);
        vmcs_load(vmx->loaded_vmcs->vmcs);
+
+       preempt_enable();
 }
 
 static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
@@ -6743,6 +6750,12 @@ static int handle_invept(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+static int handle_invvpid(struct kvm_vcpu *vcpu)
+{
+       kvm_queue_exception(vcpu, UD_VECTOR);
+       return 1;
+}
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -6788,6 +6801,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
        [EXIT_REASON_MWAIT_INSTRUCTION]       = handle_mwait,
        [EXIT_REASON_MONITOR_INSTRUCTION]     = handle_monitor,
        [EXIT_REASON_INVEPT]                  = handle_invept,
+       [EXIT_REASON_INVVPID]                 = handle_invvpid,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -7023,7 +7037,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
        case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD:
        case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE:
        case EXIT_REASON_VMOFF: case EXIT_REASON_VMON:
-       case EXIT_REASON_INVEPT:
+       case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID:
                /*
                 * VMX instructions trap unconditionally. This allows L1 to
                 * emulate them for its L2 guest, i.e., allows 3-level nesting!
@@ -7164,10 +7178,10 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
            && kvm_vmx_exit_handlers[exit_reason])
                return kvm_vmx_exit_handlers[exit_reason](vcpu);
        else {
-               vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
-               vcpu->run->hw.hardware_exit_reason = exit_reason;
+               WARN_ONCE(1, "vmx: unexpected exit reason 0x%x\n", exit_reason);
+               kvm_queue_exception(vcpu, UD_VECTOR);
+               return 1;
        }
-       return 0;
 }
 
 static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
index 34c8f94331f83dad10ff80f6b3f1fafa861b9ed6..0033df32a74585f69f5a8d83515f7182f1c7d7af 100644 (file)
@@ -229,20 +229,25 @@ static void kvm_shared_msr_cpu_online(void)
                shared_msr_update(i, shared_msrs_global.msrs[i]);
 }
 
-void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
+int kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
 {
        unsigned int cpu = smp_processor_id();
        struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
+       int err;
 
        if (((value ^ smsr->values[slot].curr) & mask) == 0)
-               return;
+               return 0;
        smsr->values[slot].curr = value;
-       wrmsrl(shared_msrs_global.msrs[slot], value);
+       err = wrmsrl_safe(shared_msrs_global.msrs[slot], value);
+       if (err)
+               return 1;
+
        if (!smsr->registered) {
                smsr->urn.on_user_return = kvm_on_user_return;
                user_return_notifier_register(&smsr->urn);
                smsr->registered = true;
        }
+       return 0;
 }
 EXPORT_SYMBOL_GPL(kvm_set_shared_msr);
 
@@ -987,7 +992,6 @@ void kvm_enable_efer_bits(u64 mask)
 }
 EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
 
-
 /*
  * Writes msr value into into the appropriate "register".
  * Returns 0 on success, non-0 otherwise.
@@ -995,8 +999,34 @@ EXPORT_SYMBOL_GPL(kvm_enable_efer_bits);
  */
 int kvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
 {
+       switch (msr->index) {
+       case MSR_FS_BASE:
+       case MSR_GS_BASE:
+       case MSR_KERNEL_GS_BASE:
+       case MSR_CSTAR:
+       case MSR_LSTAR:
+               if (is_noncanonical_address(msr->data))
+                       return 1;
+               break;
+       case MSR_IA32_SYSENTER_EIP:
+       case MSR_IA32_SYSENTER_ESP:
+               /*
+                * IA32_SYSENTER_ESP and IA32_SYSENTER_EIP cause #GP if
+                * non-canonical address is written on Intel but not on
+                * AMD (which ignores the top 32-bits, because it does
+                * not implement 64-bit SYSENTER).
+                *
+                * 64-bit code should hence be able to write a non-canonical
+                * value on AMD.  Making the address canonical ensures that
+                * vmentry does not fail on Intel after writing a non-canonical
+                * value, and that something deterministic happens if the guest
+                * invokes 64-bit SYSENTER.
+                */
+               msr->data = get_canonical(msr->data);
+       }
        return kvm_x86_ops->set_msr(vcpu, msr);
 }
+EXPORT_SYMBOL_GPL(kvm_set_msr);
 
 /*
  * Adapt set_msr() to msr_io()'s calling convention
index 7609e0e421ece96f6671cc7d2310e0c59402ac1b..1318f75d56e4f072885276a18ca00363f074fcd4 100644 (file)
@@ -41,9 +41,8 @@ csum_partial_copy_from_user(const void __user *src, void *dst,
                while (((unsigned long)src & 6) && len >= 2) {
                        __u16 val16;
 
-                       *errp = __get_user(val16, (const __u16 __user *)src);
-                       if (*errp)
-                               return isum;
+                       if (__get_user(val16, (const __u16 __user *)src))
+                               goto out_err;
 
                        *(__u16 *)dst = val16;
                        isum = (__force __wsum)add32_with_carry(
index 4cb8763868fc20add0018a26df9752f1cd03937d..4e5dfec750fc9296e726a213b8e097f4f885fb70 100644 (file)
@@ -1123,7 +1123,7 @@ void mark_rodata_ro(void)
        unsigned long end = (unsigned long) &__end_rodata_hpage_align;
        unsigned long text_end = PFN_ALIGN(&__stop___ex_table);
        unsigned long rodata_end = PFN_ALIGN(&__end_rodata);
-       unsigned long all_end = PFN_ALIGN(&_end);
+       unsigned long all_end;
 
        printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n",
               (end - start) >> 10);
@@ -1134,7 +1134,16 @@ void mark_rodata_ro(void)
        /*
         * The rodata/data/bss/brk section (but not the kernel text!)
         * should also be not-executable.
+        *
+        * We align all_end to PMD_SIZE because the existing mapping
+        * is a full PMD. If we would align _brk_end to PAGE_SIZE we
+        * split the PMD and the reminder between _brk_end and the end
+        * of the PMD will remain mapped executable.
+        *
+        * Any PMD which was setup after the one which covers _brk_end
+        * has been zapped already via cleanup_highmem().
         */
+       all_end = roundup((unsigned long)_brk_end, PMD_SIZE);
        set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT);
 
        rodata_test();
index af78e50ca6cee7e4b7293075171986ab6f7166d5..b12f43c192cf71e839ffeb09ca3f6682690616b6 100644 (file)
@@ -327,7 +327,7 @@ EXPORT_SYMBOL(iounmap);
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
  */
-void *xlate_dev_mem_ptr(unsigned long phys)
+void *xlate_dev_mem_ptr(phys_addr_t phys)
 {
        void *addr;
        unsigned long start = phys & PAGE_MASK;
@@ -343,7 +343,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
        return addr;
 }
 
-void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 {
        if (page_is_ram(phys >> PAGE_SHIFT))
                return;
index ae242a7c11c7473cfeb163b78d54fa62005b8e44..36de293caf25c3bfe3fcd062ef95f583d5eb398e 100644 (file)
@@ -409,7 +409,7 @@ phys_addr_t slow_virt_to_phys(void *__virt_addr)
        psize = page_level_size(level);
        pmask = page_level_mask(level);
        offset = virt_addr & ~pmask;
-       phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
+       phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
        return (phys_addr | offset);
 }
 EXPORT_SYMBOL_GPL(slow_virt_to_phys);
index f15103dff4b43f04e16ff8bbd59354435aec4cb7..d143d216d52bec69b912128d88c3283cd0122c6c 100644 (file)
@@ -40,20 +40,40 @@ void __init efi_bgrt_init(void)
        if (ACPI_FAILURE(status))
                return;
 
-       if (bgrt_tab->header.length < sizeof(*bgrt_tab))
+       if (bgrt_tab->header.length < sizeof(*bgrt_tab)) {
+               pr_err("Ignoring BGRT: invalid length %u (expected %zu)\n",
+                      bgrt_tab->header.length, sizeof(*bgrt_tab));
                return;
-       if (bgrt_tab->version != 1 || bgrt_tab->status != 1)
+       }
+       if (bgrt_tab->version != 1) {
+               pr_err("Ignoring BGRT: invalid version %u (expected 1)\n",
+                      bgrt_tab->version);
+               return;
+       }
+       if (bgrt_tab->status != 1) {
+               pr_err("Ignoring BGRT: invalid status %u (expected 1)\n",
+                      bgrt_tab->status);
+               return;
+       }
+       if (bgrt_tab->image_type != 0) {
+               pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n",
+                      bgrt_tab->image_type);
                return;
-       if (bgrt_tab->image_type != 0 || !bgrt_tab->image_address)
+       }
+       if (!bgrt_tab->image_address) {
+               pr_err("Ignoring BGRT: null image address\n");
                return;
+       }
 
        image = efi_lookup_mapped_addr(bgrt_tab->image_address);
        if (!image) {
                image = early_memremap(bgrt_tab->image_address,
                                       sizeof(bmp_header));
                ioremapped = true;
-               if (!image)
+               if (!image) {
+                       pr_err("Ignoring BGRT: failed to map image header memory\n");
                        return;
+               }
        }
 
        memcpy_fromio(&bmp_header, image, sizeof(bmp_header));
@@ -61,14 +81,18 @@ void __init efi_bgrt_init(void)
                early_iounmap(image, sizeof(bmp_header));
        bgrt_image_size = bmp_header.size;
 
-       bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL);
-       if (!bgrt_image)
+       bgrt_image = kmalloc(bgrt_image_size, GFP_KERNEL | __GFP_NOWARN);
+       if (!bgrt_image) {
+               pr_err("Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)\n",
+                      bgrt_image_size);
                return;
+       }
 
        if (ioremapped) {
                image = early_memremap(bgrt_tab->image_address,
                                       bmp_header.size);
                if (!image) {
+                       pr_err("Ignoring BGRT: failed to map image memory\n");
                        kfree(bgrt_image);
                        bgrt_image = NULL;
                        return;
index 850da94fef305f65e20bdb52370cc75c1420fd5c..dbc8627a5cdf6d569a5f69cbea05ebac924d2279 100644 (file)
@@ -70,17 +70,7 @@ static efi_config_table_type_t arch_tables[] __initdata = {
 
 u64 efi_setup;         /* efi setup_data physical address */
 
-static bool disable_runtime __initdata = false;
-static int __init setup_noefi(char *arg)
-{
-       disable_runtime = true;
-       return 0;
-}
-early_param("noefi", setup_noefi);
-
-int add_efi_memmap;
-EXPORT_SYMBOL(add_efi_memmap);
-
+static int add_efi_memmap __initdata;
 static int __init setup_add_efi_memmap(char *arg)
 {
        add_efi_memmap = 1;
@@ -96,7 +86,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
 {
        efi_status_t status;
 
-       efi_call_phys_prelog();
+       efi_call_phys_prolog();
        status = efi_call_phys(efi_phys.set_virtual_address_map,
                               memory_map_size, descriptor_size,
                               descriptor_version, virtual_map);
@@ -210,9 +200,12 @@ static void __init print_efi_memmap(void)
        for (p = memmap.map, i = 0;
             p < memmap.map_end;
             p += memmap.desc_size, i++) {
+               char buf[64];
+
                md = p;
-               pr_info("mem%02u: type=%u, attr=0x%llx, range=[0x%016llx-0x%016llx) (%lluMB)\n",
-                       i, md->type, md->attribute, md->phys_addr,
+               pr_info("mem%02u: %s range=[0x%016llx-0x%016llx) (%lluMB)\n",
+                       i, efi_md_typeattr_format(buf, sizeof(buf), md),
+                       md->phys_addr,
                        md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
                        (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
        }
@@ -344,9 +337,9 @@ static int __init efi_runtime_init32(void)
        }
 
        /*
-        * We will only need *early* access to the following two
-        * EFI runtime services before set_virtual_address_map
-        * is invoked.
+        * We will only need *early* access to the SetVirtualAddressMap
+        * EFI runtime service. All other runtime services will be called
+        * via the virtual mapping.
         */
        efi_phys.set_virtual_address_map =
                        (efi_set_virtual_address_map_t *)
@@ -368,9 +361,9 @@ static int __init efi_runtime_init64(void)
        }
 
        /*
-        * We will only need *early* access to the following two
-        * EFI runtime services before set_virtual_address_map
-        * is invoked.
+        * We will only need *early* access to the SetVirtualAddressMap
+        * EFI runtime service. All other runtime services will be called
+        * via the virtual mapping.
         */
        efi_phys.set_virtual_address_map =
                        (efi_set_virtual_address_map_t *)
@@ -492,7 +485,7 @@ void __init efi_init(void)
        if (!efi_runtime_supported())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else {
-               if (disable_runtime || efi_runtime_init())
+               if (efi_runtime_disabled() || efi_runtime_init())
                        return;
        }
        if (efi_memmap_init())
@@ -537,7 +530,7 @@ void __init runtime_code_page_mkexec(void)
        }
 }
 
-void efi_memory_uc(u64 addr, unsigned long size)
+void __init efi_memory_uc(u64 addr, unsigned long size)
 {
        unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
        u64 npages;
@@ -732,6 +725,7 @@ static void __init kexec_enter_virtual_mode(void)
         */
        if (!efi_is_native()) {
                efi_unmap_memmap();
+               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
                return;
        }
 
@@ -805,6 +799,7 @@ static void __init __efi_enter_virtual_mode(void)
        new_memmap = efi_map_regions(&count, &pg_shift);
        if (!new_memmap) {
                pr_err("Error reallocating memory, EFI runtime non-functional!\n");
+               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
                return;
        }
 
@@ -812,8 +807,10 @@ static void __init __efi_enter_virtual_mode(void)
 
        BUG_ON(!efi.systab);
 
-       if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift))
+       if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift)) {
+               clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
                return;
+       }
 
        efi_sync_low_kernel_mappings();
        efi_dump_pagetable();
@@ -938,14 +935,11 @@ u64 efi_mem_attributes(unsigned long phys_addr)
        return 0;
 }
 
-static int __init parse_efi_cmdline(char *str)
+static int __init arch_parse_efi_cmdline(char *str)
 {
-       if (*str == '=')
-               str++;
-
-       if (!strncmp(str, "old_map", 7))
+       if (parse_option_str(str, "old_map"))
                set_bit(EFI_OLD_MEMMAP, &efi.flags);
 
        return 0;
 }
-early_param("efi", parse_efi_cmdline);
+early_param("efi", arch_parse_efi_cmdline);
index 9ee3491e31fbab7f6643462395d31c6f9f36f1b4..40e7cda529365133b50bab8745d9995c47557d53 100644 (file)
@@ -33,7 +33,7 @@
 
 /*
  * To make EFI call EFI runtime service in physical addressing mode we need
- * prelog/epilog before/after the invocation to disable interrupt, to
+ * prolog/epilog before/after the invocation to disable interrupt, to
  * claim EFI runtime service handler exclusively and to duplicate a memory in
  * low memory space say 0 - 3G.
  */
@@ -41,11 +41,13 @@ static unsigned long efi_rt_eflags;
 
 void efi_sync_low_kernel_mappings(void) {}
 void __init efi_dump_pagetable(void) {}
-int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
        return 0;
 }
-void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages) {}
+void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+{
+}
 
 void __init efi_map_region(efi_memory_desc_t *md)
 {
@@ -55,7 +57,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
 void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
 void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
 
-void efi_call_phys_prelog(void)
+void __init efi_call_phys_prolog(void)
 {
        struct desc_ptr gdt_descr;
 
@@ -69,7 +71,7 @@ void efi_call_phys_prelog(void)
        load_gdt(&gdt_descr);
 }
 
-void efi_call_phys_epilog(void)
+void __init efi_call_phys_epilog(void)
 {
        struct desc_ptr gdt_descr;
 
index 290d397e1dd9125e408a1ee140fe4d3ced51a33d..35aecb6042fbc1dcf938e8779a0f60961d76aeb6 100644 (file)
@@ -79,7 +79,7 @@ static void __init early_code_mapping_set_exec(int executable)
        }
 }
 
-void __init efi_call_phys_prelog(void)
+void __init efi_call_phys_prolog(void)
 {
        unsigned long vaddress;
        int pgd;
@@ -139,7 +139,7 @@ void efi_sync_low_kernel_mappings(void)
                sizeof(pgd_t) * num_pgds);
 }
 
-int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
        unsigned long text;
        struct page *page;
@@ -192,7 +192,7 @@ int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
        return 0;
 }
 
-void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+void __init efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 {
        pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
 
index fbe66e626c09f437da6110bec5c080ef39e6bf95..040192b50d0209b46b64e2607b0e41fe2bb0123b 100644 (file)
@@ -27,13 +27,13 @@ ENTRY(efi_call_phys)
         * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
         * the values of these registers are the same. And, the corresponding
         * GDT entries are identical. So I will do nothing about segment reg
-        * and GDT, but change GDT base register in prelog and epilog.
+        * and GDT, but change GDT base register in prolog and epilog.
         */
 
        /*
         * 1. Now I am running with EIP = <physical address> + PAGE_OFFSET.
         * But to make it smoothly switch from virtual mode to flat mode.
-        * The mapping of lower virtual memory has been created in prelog and
+        * The mapping of lower virtual memory has been created in prolog and
         * epilog.
         */
        movl    $1f, %edx
index 46aa25c8ce06c3366b15357d110111de2bd004fc..3c1c3866d82b683334951d9151dcbfd522189388 100644 (file)
  */
 
 
-/* __attribute__((weak)) makes these declarations overridable */
 /* For every CPU addition a new get_<cpuname>_ops interface needs
  * to be added.
  */
-extern void *get_penwell_ops(void) __attribute__((weak));
-extern void *get_cloverview_ops(void) __attribute__((weak));
-extern void *get_tangier_ops(void) __attribute__((weak));
+extern void *get_penwell_ops(void);
+extern void *get_cloverview_ops(void);
+extern void *get_tangier_ops(void);
index 3c53a90fdb18b8d446bcb6ef3cc711ab543974d8..c14ad34776c466f3cb18fe4b0a50fe40db8cd3ec 100644 (file)
@@ -106,6 +106,7 @@ int __init sfi_parse_mtmr(struct sfi_table_header *table)
                        mp_irq.dstapic = MP_APIC_ALL;
                        mp_irq.dstirq = pentry->irq;
                        mp_save_irq(&mp_irq);
+                       mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
        }
 
        return 0;
@@ -176,6 +177,7 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
                mp_irq.dstapic = MP_APIC_ALL;
                mp_irq.dstirq = pentry->irq;
                mp_save_irq(&mp_irq);
+               mp_map_gsi_to_irq(pentry->irq, IOAPIC_MAP_ALLOC);
        }
        return 0;
 }
diff --git a/arch/x86/tools/calc_run_size.pl b/arch/x86/tools/calc_run_size.pl
new file mode 100644 (file)
index 0000000..23210ba
--- /dev/null
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+#
+# Calculate the amount of space needed to run the kernel, including room for
+# the .bss and .brk sections.
+#
+# Usage:
+# objdump -h a.out | perl calc_run_size.pl
+use strict;
+
+my $mem_size = 0;
+my $file_offset = 0;
+
+my $sections=" *[0-9]+ \.(?:bss|brk) +";
+while (<>) {
+       if (/^$sections([0-9a-f]+) +(?:[0-9a-f]+ +){2}([0-9a-f]+)/) {
+               my $size = hex($1);
+               my $offset = hex($2);
+               $mem_size += $size;
+               if ($file_offset == 0) {
+                       $file_offset = $offset;
+               } elsif ($file_offset != $offset) {
+                       # BFD linker shows the same file offset in ELF.
+                       # Gold linker shows them as consecutive.
+                       next if ($file_offset + $mem_size == $offset + $size);
+
+                       printf STDERR "file_offset: 0x%lx\n", $file_offset;
+                       printf STDERR "mem_size: 0x%lx\n", $mem_size;
+                       printf STDERR "offset: 0x%lx\n", $offset;
+                       printf STDERR "size: 0x%lx\n", $size;
+
+                       die ".bss and .brk are non-contiguous\n";
+               }
+       }
+}
+
+if ($file_offset == 0) {
+       die "Never found .bss or .brk file offset\n";
+}
+printf("%d\n", $mem_size + $file_offset);
index 1a3f0445432a31fa1b654ab8af882bc317e5d363..fac5e4f9607c28716d97ea382702304ea188bdb3 100644 (file)
@@ -1636,9 +1636,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
        xen_raw_console_write("mapping kernel into physical memory\n");
        xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base, xen_start_info->nr_pages);
 
-       /* Allocate and initialize top and mid mfn levels for p2m structure */
-       xen_build_mfn_list_list();
-
        /* keep using Xen gdt for now; no urgent need to change it */
 
 #ifdef CONFIG_X86_32
index f62af7647ec9879055f433a540166cb4162a1f0d..a8a1a3d08d4d938ef975754f9e586685043b6233 100644 (file)
@@ -1217,10 +1217,13 @@ static void __init xen_pagetable_p2m_copy(void)
 static void __init xen_pagetable_init(void)
 {
        paging_init();
-       xen_setup_shared_info();
 #ifdef CONFIG_X86_64
        xen_pagetable_p2m_copy();
 #endif
+       /* Allocate and initialize top and mid mfn levels for p2m structure */
+       xen_build_mfn_list_list();
+
+       xen_setup_shared_info();
        xen_post_allocator_init();
 }
 static void xen_write_cr2(unsigned long cr2)
index 9f5983b01ed91ebe7080a0e5928e3f549d0c1242..b456b048eca9b86467b2069f03e22b7db05c3bfb 100644 (file)
 #include <linux/hash.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
+#include <linux/bootmem.h>
 
 #include <asm/cache.h>
 #include <asm/setup.h>
@@ -181,21 +182,20 @@ static void __init m2p_override_init(void);
 
 unsigned long xen_max_p2m_pfn __read_mostly;
 
+static unsigned long *p2m_mid_missing_mfn;
+static unsigned long *p2m_top_mfn;
+static unsigned long **p2m_top_mfn_p;
+
 /* Placeholders for holes in the address space */
 static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
 
 static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
 
 static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_identity, P2M_MID_PER_PAGE);
-static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE);
 
 RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
-RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 
 /* For each I/O range remapped we may lose up to two leaf pages for the boundary
  * violations and three mid pages to cover up to 3GB. With
@@ -272,11 +272,11 @@ static void p2m_init(unsigned long *p2m)
  * Build the parallel p2m_top_mfn and p2m_mid_mfn structures
  *
  * This is called both at boot time, and after resuming from suspend:
- * - At boot time we're called very early, and must use extend_brk()
+ * - At boot time we're called rather early, and must use alloc_bootmem*()
  *   to allocate memory.
  *
  * - After resume we're called from within stop_machine, but the mfn
- *   tree should alreay be completely allocated.
+ *   tree should already be completely allocated.
  */
 void __ref xen_build_mfn_list_list(void)
 {
@@ -287,20 +287,17 @@ void __ref xen_build_mfn_list_list(void)
 
        /* Pre-initialize p2m_top_mfn to be completely missing */
        if (p2m_top_mfn == NULL) {
-               p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               p2m_mid_missing_mfn = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
                p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
-               p2m_mid_identity_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
-               p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
 
-               p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               p2m_top_mfn_p = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
                p2m_top_mfn_p_init(p2m_top_mfn_p);
 
-               p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               p2m_top_mfn = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
                p2m_top_mfn_init(p2m_top_mfn);
        } else {
                /* Reinitialise, mfn's all change after migration */
                p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
-               p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
        }
 
        for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
@@ -328,10 +325,9 @@ void __ref xen_build_mfn_list_list(void)
                        /*
                         * XXX boot-time only!  We should never find
                         * missing parts of the mfn tree after
-                        * runtime.  extend_brk() will BUG if we call
-                        * it too late.
+                        * runtime.
                         */
-                       mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
+                       mid_mfn_p = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
                        p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
 
                        p2m_top_mfn_p[topidx] = mid_mfn_p;
@@ -415,7 +411,6 @@ void __init xen_build_dynamic_phys_to_machine(void)
        m2p_override_init();
 }
 #ifdef CONFIG_X86_64
-#include <linux/bootmem.h>
 unsigned long __init xen_revector_p2m_tree(void)
 {
        unsigned long va_start;
@@ -477,7 +472,6 @@ unsigned long __init xen_revector_p2m_tree(void)
 
                        copy_page(new, mid_p);
                        p2m_top[topidx][mididx] = &mfn_list[pfn_free];
-                       p2m_top_mfn_p[topidx][mididx] = virt_to_mfn(&mfn_list[pfn_free]);
 
                        pfn_free += P2M_PER_PAGE;
 
@@ -538,12 +532,13 @@ static bool alloc_p2m(unsigned long pfn)
        unsigned topidx, mididx;
        unsigned long ***top_p, **mid;
        unsigned long *top_mfn_p, *mid_mfn;
+       unsigned long *p2m_orig;
 
        topidx = p2m_top_index(pfn);
        mididx = p2m_mid_index(pfn);
 
        top_p = &p2m_top[topidx];
-       mid = *top_p;
+       mid = ACCESS_ONCE(*top_p);
 
        if (mid == p2m_mid_missing) {
                /* Mid level is missing, allocate a new one */
@@ -558,7 +553,7 @@ static bool alloc_p2m(unsigned long pfn)
        }
 
        top_mfn_p = &p2m_top_mfn[topidx];
-       mid_mfn = p2m_top_mfn_p[topidx];
+       mid_mfn = ACCESS_ONCE(p2m_top_mfn_p[topidx]);
 
        BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
 
@@ -566,6 +561,7 @@ static bool alloc_p2m(unsigned long pfn)
                /* Separately check the mid mfn level */
                unsigned long missing_mfn;
                unsigned long mid_mfn_mfn;
+               unsigned long old_mfn;
 
                mid_mfn = alloc_p2m_page();
                if (!mid_mfn)
@@ -575,17 +571,19 @@ static bool alloc_p2m(unsigned long pfn)
 
                missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
                mid_mfn_mfn = virt_to_mfn(mid_mfn);
-               if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
+               old_mfn = cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn);
+               if (old_mfn != missing_mfn) {
                        free_p2m_page(mid_mfn);
-               else
+                       mid_mfn = mfn_to_virt(old_mfn);
+               } else {
                        p2m_top_mfn_p[topidx] = mid_mfn;
+               }
        }
 
-       if (p2m_top[topidx][mididx] == p2m_identity ||
-           p2m_top[topidx][mididx] == p2m_missing) {
+       p2m_orig = ACCESS_ONCE(p2m_top[topidx][mididx]);
+       if (p2m_orig == p2m_identity || p2m_orig == p2m_missing) {
                /* p2m leaf page is missing */
                unsigned long *p2m;
-               unsigned long *p2m_orig = p2m_top[topidx][mididx];
 
                p2m = alloc_p2m_page();
                if (!p2m)
@@ -606,7 +604,6 @@ static bool __init early_alloc_p2m(unsigned long pfn, bool check_boundary)
 {
        unsigned topidx, mididx, idx;
        unsigned long *p2m;
-       unsigned long *mid_mfn_p;
 
        topidx = p2m_top_index(pfn);
        mididx = p2m_mid_index(pfn);
@@ -633,43 +630,21 @@ static bool __init early_alloc_p2m(unsigned long pfn, bool check_boundary)
 
        p2m_top[topidx][mididx] = p2m;
 
-       /* For save/restore we need to MFN of the P2M saved */
-
-       mid_mfn_p = p2m_top_mfn_p[topidx];
-       WARN(mid_mfn_p[mididx] != virt_to_mfn(p2m_missing),
-               "P2M_TOP_P[%d][%d] != MFN of p2m_missing!\n",
-               topidx, mididx);
-       mid_mfn_p[mididx] = virt_to_mfn(p2m);
-
        return true;
 }
 
 static bool __init early_alloc_p2m_middle(unsigned long pfn)
 {
        unsigned topidx = p2m_top_index(pfn);
-       unsigned long *mid_mfn_p;
        unsigned long **mid;
 
        mid = p2m_top[topidx];
-       mid_mfn_p = p2m_top_mfn_p[topidx];
        if (mid == p2m_mid_missing) {
                mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
 
                p2m_mid_init(mid, p2m_missing);
 
                p2m_top[topidx] = mid;
-
-               BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
-       }
-       /* And the save/restore P2M tables.. */
-       if (mid_mfn_p == p2m_mid_missing_mfn) {
-               mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
-               p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
-
-               p2m_top_mfn_p[topidx] = mid_mfn_p;
-               p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
-               /* Note: we don't set mid_mfn_p[midix] here,
-                * look in early_alloc_p2m() */
        }
        return true;
 }
@@ -680,14 +655,13 @@ static bool __init early_alloc_p2m_middle(unsigned long pfn)
  * replace the P2M leaf with a p2m_missing or p2m_identity.
  * Stick the old page in the new P2M tree location.
  */
-bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_mfn)
+static bool __init early_can_reuse_p2m_middle(unsigned long set_pfn)
 {
        unsigned topidx;
        unsigned mididx;
        unsigned ident_pfns;
        unsigned inv_pfns;
        unsigned long *p2m;
-       unsigned long *mid_mfn_p;
        unsigned idx;
        unsigned long pfn;
 
@@ -733,11 +707,6 @@ bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_
 found:
        /* Found one, replace old with p2m_identity or p2m_missing */
        p2m_top[topidx][mididx] = (ident_pfns ? p2m_identity : p2m_missing);
-       /* And the other for save/restore.. */
-       mid_mfn_p = p2m_top_mfn_p[topidx];
-       /* NOTE: Even if it is a p2m_identity it should still be point to
-        * a page filled with INVALID_P2M_ENTRY entries. */
-       mid_mfn_p[mididx] = virt_to_mfn(p2m_missing);
 
        /* Reset where we want to stick the old page in. */
        topidx = p2m_top_index(set_pfn);
@@ -752,8 +721,6 @@ found:
 
        p2m_init(p2m);
        p2m_top[topidx][mididx] = p2m;
-       mid_mfn_p = p2m_top_mfn_p[topidx];
-       mid_mfn_p[mididx] = virt_to_mfn(p2m);
 
        return true;
 }
@@ -763,7 +730,7 @@ bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
                if (!early_alloc_p2m_middle(pfn))
                        return false;
 
-               if (early_can_reuse_p2m_middle(pfn, mfn))
+               if (early_can_reuse_p2m_middle(pfn))
                        return __set_phys_to_machine(pfn, mfn);
 
                if (!early_alloc_p2m(pfn, false /* boundary crossover OK!*/))
index af7216128d93ac4949e574b52d45f91079f6898f..29834b3fd87f8eba807d5b969f09085f857ceeb9 100644 (file)
@@ -595,6 +595,7 @@ char * __init xen_memory_setup(void)
                rc = 0;
        }
        BUG_ON(rc);
+       BUG_ON(memmap.nr_entries == 0);
 
        /*
         * Xen won't allow a 1:1 mapping to be created to UNUSABLE
index 8650cdb53209d0f298fa219ac617454cea0fa087..4c071aeb8417bb419a45632c7d9f9a5c96bf3e76 100644 (file)
@@ -510,6 +510,9 @@ static void xen_cpu_die(unsigned int cpu)
                current->state = TASK_UNINTERRUPTIBLE;
                schedule_timeout(HZ/10);
        }
+
+       cpu_die_common(cpu);
+
        xen_smp_intr_free(cpu);
        xen_uninit_lock_cpu(cpu);
        xen_teardown_timer(cpu);
index a1d430b112b33cc23ad07f925fa96325d327127f..f473d268d387fcdc8f237153b378508ec0c03f56 100644 (file)
@@ -158,7 +158,7 @@ cycle_t xen_clocksource_read(void)
        cycle_t ret;
 
        preempt_disable_notrace();
-       src = this_cpu_ptr(&xen_vcpu->time);
+       src = &__this_cpu_read(xen_vcpu)->time;
        ret = pvclock_clocksource_read(src);
        preempt_enable_notrace();
        return ret;
index 49c6c3d9444916e0dc727d51c96349e92c424d6a..81f57e8c8f1be91f6cffea3b157b6bead7a541e1 100644 (file)
@@ -319,8 +319,8 @@ config XTENSA_PLATFORM_S6105
 
 config XTENSA_PLATFORM_XTFPGA
        bool "XTFPGA"
+       select ETHOC if ETHERNET
        select SERIAL_CONSOLE
-       select ETHOC
        select XTENSA_CALIBRATE_CCOUNT
        help
          XTFPGA is the name of Tensilica board family (LX60, LX110, LX200, ML605).
@@ -367,7 +367,7 @@ config BUILTIN_DTB
 config BLK_DEV_SIMDISK
        tristate "Host file-based simulated block device support"
        default n
-       depends on XTENSA_PLATFORM_ISS
+       depends on XTENSA_PLATFORM_ISS && BLOCK
        help
          Create block devices that map to files in the host file system.
          Device binding to host file may be changed at runtime via proc
diff --git a/arch/xtensa/boot/dts/lx200mx.dts b/arch/xtensa/boot/dts/lx200mx.dts
new file mode 100644 (file)
index 0000000..249822b
--- /dev/null
@@ -0,0 +1,16 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-16m.dtsi"
+
+/ {
+       compatible = "cdns,xtensa-lx200";
+       memory@0 {
+               device_type = "memory";
+               reg = <0x00000000 0x06000000>;
+       };
+       pic: pic {
+               compatible = "cdns,xtensa-mx";
+               #interrupt-cells = <2>;
+               interrupt-controller;
+       };
+};
diff --git a/arch/xtensa/configs/generic_kc705_defconfig b/arch/xtensa/configs/generic_kc705_defconfig
new file mode 100644 (file)
index 0000000..f4b7b38
--- /dev/null
@@ -0,0 +1,131 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_MEMCG=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_XTENSA_VARIANT_DC233C=y
+CONFIG_XTENSA_UNALIGNED_USER=y
+CONFIG_PREEMPT=y
+CONFIG_HIGHMEM=y
+# CONFIG_PCI is not set
+CONFIG_XTENSA_PLATFORM_XTFPGA=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug"
+CONFIG_USE_OF=y
+CONFIG_BUILTIN_DTB="kc705"
+# CONFIG_COMPACTION is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+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_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_MTD=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MARVELL_PHY=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
+CONFIG_SUNRPC_DEBUG=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_STACKTRACE=y
+CONFIG_RCU_TRACE=y
+# CONFIG_FTRACE is not set
+CONFIG_LD_NO_RELAX=y
+# CONFIG_S32C1I_SELFTEST is not set
+CONFIG_CRYPTO_ANSI_CPRNG=y
diff --git a/arch/xtensa/configs/smp_lx200_defconfig b/arch/xtensa/configs/smp_lx200_defconfig
new file mode 100644 (file)
index 0000000..22eeacb
--- /dev/null
@@ -0,0 +1,135 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_MEMCG=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_XTENSA_VARIANT_CUSTOM=y
+CONFIG_XTENSA_VARIANT_CUSTOM_NAME="test_mmuhifi_c3"
+CONFIG_XTENSA_UNALIGNED_USER=y
+CONFIG_PREEMPT=y
+CONFIG_HAVE_SMP=y
+CONFIG_SMP=y
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX is not set
+# CONFIG_PCI is not set
+CONFIG_XTENSA_PLATFORM_XTFPGA=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug"
+CONFIG_USE_OF=y
+CONFIG_BUILTIN_DTB="lx200mx"
+# CONFIG_COMPACTION is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+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_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_MTD=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_MARVELL_PHY=y
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_FANOTIFY=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_ROOT_NFS=y
+CONFIG_SUNRPC_DEBUG=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_VM=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_STACKTRACE=y
+CONFIG_RCU_TRACE=y
+# CONFIG_FTRACE is not set
+CONFIG_LD_NO_RELAX=y
+# CONFIG_S32C1I_SELFTEST is not set
+CONFIG_CRYPTO_ANSI_CPRNG=y
index 74944207167eccfb0f6e122ad7418d5728d4a2b7..fe1600a094384e8c18a988e91862b531031984f3 100644 (file)
@@ -74,13 +74,6 @@ static inline void iounmap(volatile void __iomem *addr)
 
 #endif /* CONFIG_MMU */
 
-/*
- * Generic I/O
- */
-#define readb_relaxed readb
-#define readw_relaxed readw
-#define readl_relaxed readl
-
 #endif /* __KERNEL__ */
 
 #include <asm-generic/io.h>
index b2173e5da601cbe57303f9060faacb0dde0310cf..0383aed5912111b6a0b2cd4d0c58f758a95b4a7e 100644 (file)
@@ -277,6 +277,8 @@ static inline pte_t pte_mkwrite(pte_t pte)
 static inline pte_t pte_mkspecial(pte_t pte)
        { return pte; }
 
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) & ~_PAGE_CA_MASK))
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
index 8883fc877c5c93334cacfd29ffe6a12300bb0961..db5bb72e2f4eda85f6ad5fe127be9796c8862ad9 100644 (file)
@@ -384,7 +384,8 @@ __SYSCALL(174, sys_chroot, 1)
 #define __NR_pivot_root                        175
 __SYSCALL(175, sys_pivot_root, 2)
 #define __NR_umount                            176
-__SYSCALL(176, sys_umount, 2)
+__SYSCALL(176, sys_oldumount, 1)
+#define __ARCH_WANT_SYS_OLDUMOUNT
 #define __NR_swapoff                           177
 __SYSCALL(177, sys_swapoff, 1)
 #define __NR_sync                              178
@@ -742,7 +743,14 @@ __SYSCALL(335, sys_sched_getattr, 3)
 #define __NR_renameat2                         336
 __SYSCALL(336, sys_renameat2, 5)
 
-#define __NR_syscall_count                     337
+#define __NR_seccomp                           337
+__SYSCALL(337, sys_seccomp, 3)
+#define __NR_getrandom                         338
+__SYSCALL(338, sys_getrandom, 3)
+#define __NR_memfd_create                      339
+__SYSCALL(339, sys_memfd_create, 2)
+
+#define __NR_syscall_count                     340
 
 /*
  * sysxtensa syscall handler
index 0984232e429fb61d427c90340fa0c77e55c1fee2..5cbd5d9ea61dd52969d9c55313dbf703f3c4d24f 100644 (file)
@@ -216,9 +216,10 @@ static int bio_integrity_process(struct bio *bio,
 {
        struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
        struct blk_integrity_iter iter;
-       struct bio_vec *bv;
+       struct bvec_iter bviter;
+       struct bio_vec bv;
        struct bio_integrity_payload *bip = bio_integrity(bio);
-       unsigned int i, ret = 0;
+       unsigned int ret = 0;
        void *prot_buf = page_address(bip->bip_vec->bv_page) +
                bip->bip_vec->bv_offset;
 
@@ -227,11 +228,11 @@ static int bio_integrity_process(struct bio *bio,
        iter.seed = bip_get_seed(bip);
        iter.prot_buf = prot_buf;
 
-       bio_for_each_segment_all(bv, bio, i) {
-               void *kaddr = kmap_atomic(bv->bv_page);
+       bio_for_each_segment(bv, bio, bviter) {
+               void *kaddr = kmap_atomic(bv.bv_page);
 
-               iter.data_buf = kaddr + bv->bv_offset;
-               iter.data_size = bv->bv_len;
+               iter.data_buf = kaddr + bv.bv_offset;
+               iter.data_size = bv.bv_len;
 
                ret = proc_fn(&iter);
                if (ret) {
index 0421b53e6431fe9c2522f0b280058594bc9608cb..2e7424b42947d414090e03b9b7d81ef24207dc8a 100644 (file)
@@ -1266,7 +1266,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq)
        blk_clear_rq_complete(rq);
        trace_block_rq_requeue(q, rq);
 
-       if (blk_rq_tagged(rq))
+       if (rq->cmd_flags & REQ_QUEUED)
                blk_queue_end_tag(q, rq);
 
        BUG_ON(blk_queued_rq(rq));
@@ -2554,7 +2554,7 @@ EXPORT_SYMBOL_GPL(blk_unprep_request);
  */
 void blk_finish_request(struct request *req, int error)
 {
-       if (blk_rq_tagged(req))
+       if (req->cmd_flags & REQ_QUEUED)
                blk_queue_end_tag(req->q, req);
 
        BUG_ON(blk_queued_rq(req));
index ba99351c0f58898cb83bd336299c773230e9e73f..89b97b5e0881853054c0807c5607c20d91d90762 100644 (file)
@@ -97,18 +97,22 @@ void blk_recalc_rq_segments(struct request *rq)
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
 {
-       bool no_sg_merge = !!test_bit(QUEUE_FLAG_NO_SG_MERGE,
-                       &q->queue_flags);
+       unsigned short seg_cnt;
+
+       /* estimate segment number by bi_vcnt for non-cloned bio */
+       if (bio_flagged(bio, BIO_CLONED))
+               seg_cnt = bio_segments(bio);
+       else
+               seg_cnt = bio->bi_vcnt;
 
-       if (no_sg_merge && !bio_flagged(bio, BIO_CLONED) &&
-                       bio->bi_vcnt < queue_max_segments(q))
-               bio->bi_phys_segments = bio->bi_vcnt;
+       if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags) &&
+                       (seg_cnt < queue_max_segments(q)))
+               bio->bi_phys_segments = seg_cnt;
        else {
                struct bio *nxt = bio->bi_next;
 
                bio->bi_next = NULL;
-               bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio,
-                               no_sg_merge);
+               bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, false);
                bio->bi_next = nxt;
        }
 
index 8317175a3009cb994d66f1f6128de6d9591ee249..728b9a4d5f561a45d037e0b0ee71f5648b2c7942 100644 (file)
@@ -584,6 +584,34 @@ int blk_mq_tag_update_depth(struct blk_mq_tags *tags, unsigned int tdepth)
        return 0;
 }
 
+/**
+ * blk_mq_unique_tag() - return a tag that is unique queue-wide
+ * @rq: request for which to compute a unique tag
+ *
+ * The tag field in struct request is unique per hardware queue but not over
+ * all hardware queues. Hence this function that returns a tag with the
+ * hardware context index in the upper bits and the per hardware queue tag in
+ * the lower bits.
+ *
+ * Note: When called for a request that is queued on a non-multiqueue request
+ * queue, the hardware context index is set to zero.
+ */
+u32 blk_mq_unique_tag(struct request *rq)
+{
+       struct request_queue *q = rq->q;
+       struct blk_mq_hw_ctx *hctx;
+       int hwq = 0;
+
+       if (q->mq_ops) {
+               hctx = q->mq_ops->map_queue(q, rq->mq_ctx->cpu);
+               hwq = hctx->queue_num;
+       }
+
+       return (hwq << BLK_MQ_UNIQUE_TAG_BITS) |
+               (rq->tag & BLK_MQ_UNIQUE_TAG_MASK);
+}
+EXPORT_SYMBOL(blk_mq_unique_tag);
+
 ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page)
 {
        char *orig_page = page;
index 68929bad9a6a4048151f485cc1e44db2d655fc0f..92ceef0d2ab932a58526f721dec08811a310613e 100644 (file)
@@ -107,11 +107,7 @@ static void blk_mq_usage_counter_release(struct percpu_ref *ref)
        wake_up_all(&q->mq_freeze_wq);
 }
 
-/*
- * Guarantee no request is in use, so we can change any data structure of
- * the queue afterward.
- */
-void blk_mq_freeze_queue(struct request_queue *q)
+static void blk_mq_freeze_queue_start(struct request_queue *q)
 {
        bool freeze;
 
@@ -123,9 +119,23 @@ void blk_mq_freeze_queue(struct request_queue *q)
                percpu_ref_kill(&q->mq_usage_counter);
                blk_mq_run_queues(q, false);
        }
+}
+
+static void blk_mq_freeze_queue_wait(struct request_queue *q)
+{
        wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
 }
 
+/*
+ * Guarantee no request is in use, so we can change any data structure of
+ * the queue afterward.
+ */
+void blk_mq_freeze_queue(struct request_queue *q)
+{
+       blk_mq_freeze_queue_start(q);
+       blk_mq_freeze_queue_wait(q);
+}
+
 static void blk_mq_unfreeze_queue(struct request_queue *q)
 {
        bool wake;
@@ -1921,7 +1931,7 @@ void blk_mq_free_queue(struct request_queue *q)
 /* Basically redo blk_mq_init_queue with queue frozen */
 static void blk_mq_queue_reinit(struct request_queue *q)
 {
-       blk_mq_freeze_queue(q);
+       WARN_ON_ONCE(!q->mq_freeze_depth);
 
        blk_mq_sysfs_unregister(q);
 
@@ -1936,8 +1946,6 @@ static void blk_mq_queue_reinit(struct request_queue *q)
        blk_mq_map_swqueue(q);
 
        blk_mq_sysfs_register(q);
-
-       blk_mq_unfreeze_queue(q);
 }
 
 static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
@@ -1956,8 +1964,25 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
                return NOTIFY_OK;
 
        mutex_lock(&all_q_mutex);
+
+       /*
+        * We need to freeze and reinit all existing queues.  Freezing
+        * involves synchronous wait for an RCU grace period and doing it
+        * one by one may take a long time.  Start freezing all queues in
+        * one swoop and then wait for the completions so that freezing can
+        * take place in parallel.
+        */
+       list_for_each_entry(q, &all_q_list, all_q_node)
+               blk_mq_freeze_queue_start(q);
+       list_for_each_entry(q, &all_q_list, all_q_node)
+               blk_mq_freeze_queue_wait(q);
+
        list_for_each_entry(q, &all_q_list, all_q_node)
                blk_mq_queue_reinit(q);
+
+       list_for_each_entry(q, &all_q_list, all_q_node)
+               blk_mq_unfreeze_queue(q);
+
        mutex_unlock(&all_q_mutex);
        return NOTIFY_OK;
 }
@@ -2024,6 +2049,8 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
  */
 int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
 {
+       BUILD_BUG_ON(BLK_MQ_MAX_DEPTH > 1 << BLK_MQ_UNIQUE_TAG_BITS);
+
        if (!set->nr_hw_queues)
                return -EINVAL;
        if (!set->queue_depth)
index 24c28b659bb34f00eae0e4b900266e1dca069169..afa3b037a17c3dfcfb466699544dbaf0fb05221e 100644 (file)
@@ -229,7 +229,9 @@ int elevator_init(struct request_queue *q, char *name)
        }
 
        err = e->ops.elevator_init_fn(q, e);
-       return 0;
+       if (err)
+               elevator_put(e);
+       return err;
 }
 EXPORT_SYMBOL(elevator_init);
 
index e50170ca7c33f446acc16e29a0d0097828919c30..31666c92b46af29919f42ea3e1093caed7127d71 100644 (file)
@@ -157,14 +157,16 @@ out:
 
 int ioprio_best(unsigned short aprio, unsigned short bprio)
 {
-       unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
-       unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
+       unsigned short aclass;
+       unsigned short bclass;
 
-       if (aclass == IOPRIO_CLASS_NONE)
-               aclass = IOPRIO_CLASS_BE;
-       if (bclass == IOPRIO_CLASS_NONE)
-               bclass = IOPRIO_CLASS_BE;
+       if (!ioprio_valid(aprio))
+               aprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
+       if (!ioprio_valid(bprio))
+               bprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
 
+       aclass = IOPRIO_PRIO_CLASS(aprio);
+       bclass = IOPRIO_PRIO_CLASS(bprio);
        if (aclass == bclass)
                return min(aprio, bprio);
        if (aclass > bclass)
index abb2e65b24ccb4cbd64e0194d5bdaf9751e2b145..28163fad3c5d8800661e2b2c8868300a99e162c2 100644 (file)
@@ -142,7 +142,7 @@ static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
        __set_bit(GPCMD_VERIFY_10, filter->read_ok);
        __set_bit(VERIFY_16, filter->read_ok);
        __set_bit(REPORT_LUNS, filter->read_ok);
-       __set_bit(SERVICE_ACTION_IN, filter->read_ok);
+       __set_bit(SERVICE_ACTION_IN_16, filter->read_ok);
        __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok);
        __set_bit(MAINTENANCE_IN, filter->read_ok);
        __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok);
@@ -458,7 +458,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
        rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT);
        if (IS_ERR(rq)) {
                err = PTR_ERR(rq);
-               goto error;
+               goto error_free_buffer;
        }
        blk_rq_set_block_pc(rq);
 
@@ -508,7 +508,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
 
        if (bytes && blk_rq_map_kern(q, rq, buffer, bytes, __GFP_WAIT)) {
                err = DRIVER_ERROR << 24;
-               goto out;
+               goto error;
        }
 
        memset(sense, 0, sizeof(sense));
@@ -517,7 +517,6 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
 
        blk_execute_rq(q, disk, rq, 0);
 
-out:
        err = rq->errors & 0xff;        /* only 8 bit SCSI status */
        if (err) {
                if (rq->sense_len && rq->sense) {
@@ -532,9 +531,11 @@ out:
        }
        
 error:
+       blk_put_request(rq);
+
+error_free_buffer:
        kfree(buffer);
-       if (rq)
-               blk_put_request(rq);
+
        return err;
 }
 EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
index 042223f8e73364529be44a850d0dce174352c858..133f0874c95eccc7e02c26f834afed08a504a0a9 100644 (file)
@@ -202,7 +202,8 @@ static int cts_cbc_decrypt(struct crypto_cts_ctx *ctx,
        /* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */
        memcpy(s + bsize + lastn, tmp + lastn, bsize - lastn);
        /* 6. Decrypt En to create Pn-1 */
-       memset(iv, 0, sizeof(iv));
+       memzero_explicit(iv, sizeof(iv));
+
        sg_set_buf(&sgsrc[0], s + bsize, bsize);
        sg_set_buf(&sgdst[0], d, bsize);
        err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
index 42794803c480531a60cc465657741a42ea5485dc..7bb04743278216e99a011adafa8ce8d3d97c7b4d 100644 (file)
@@ -64,7 +64,7 @@ int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
                        src = data + done;
                } while (done + SHA1_BLOCK_SIZE <= len);
 
-               memset(temp, 0, sizeof(temp));
+               memzero_explicit(temp, sizeof(temp));
                partial = 0;
        }
        memcpy(sctx->buffer + partial, src, len - done);
index 0bb5583446993aae173c0b7c015b0db9214f723f..65e7b76b057fcddc8f88a04d54b678df245a8c85 100644 (file)
@@ -211,10 +211,9 @@ static void sha256_transform(u32 *state, const u8 *input)
 
        /* clear any sensitive info... */
        a = b = c = d = e = f = g = h = t1 = t2 = 0;
-       memset(W, 0, 64 * sizeof(u32));
+       memzero_explicit(W, 64 * sizeof(u32));
 }
 
-
 static int sha224_init(struct shash_desc *desc)
 {
        struct sha256_state *sctx = shash_desc_ctx(desc);
@@ -317,7 +316,7 @@ static int sha224_final(struct shash_desc *desc, u8 *hash)
        sha256_final(desc, D);
 
        memcpy(hash, D, SHA224_DIGEST_SIZE);
-       memset(D, 0, SHA256_DIGEST_SIZE);
+       memzero_explicit(D, SHA256_DIGEST_SIZE);
 
        return 0;
 }
index 6dde57dc511bab6c0068837356c7992f47b298cf..95db67197cd99dd1fd0cd538311f6e3f2202e7f3 100644 (file)
@@ -239,7 +239,7 @@ static int sha384_final(struct shash_desc *desc, u8 *hash)
        sha512_final(desc, D);
 
        memcpy(hash, D, 48);
-       memset(D, 0, 64);
+       memzero_explicit(D, 64);
 
        return 0;
 }
index 87403556fd0bfa5c3a4ecd40a5a707b6892fbc04..3c7af0d1ff7a6f396538a41a89e0dd5a9405e99e 100644 (file)
@@ -612,7 +612,7 @@ static int tgr160_final(struct shash_desc *desc, u8 * out)
 
        tgr192_final(desc, D);
        memcpy(out, D, TGR160_DIGEST_SIZE);
-       memset(D, 0, TGR192_DIGEST_SIZE);
+       memzero_explicit(D, TGR192_DIGEST_SIZE);
 
        return 0;
 }
@@ -623,7 +623,7 @@ static int tgr128_final(struct shash_desc *desc, u8 * out)
 
        tgr192_final(desc, D);
        memcpy(out, D, TGR128_DIGEST_SIZE);
-       memset(D, 0, TGR192_DIGEST_SIZE);
+       memzero_explicit(D, TGR192_DIGEST_SIZE);
 
        return 0;
 }
index 2eb11a30c29cee93203a1b90a990cc4463368440..d84c24bd7ff7bb3752484a175aee7a7aadd28b21 100644 (file)
@@ -613,7 +613,7 @@ static int vmac_final(struct shash_desc *pdesc, u8 *out)
        }
        mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx);
        memcpy(out, &mac, sizeof(vmac_t));
-       memset(&mac, 0, sizeof(vmac_t));
+       memzero_explicit(&mac, sizeof(vmac_t));
        memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
        ctx->partial_size = 0;
        return 0;
index 180f1d6e03f48fc20ef787061d8866e6af429c68..ec64e7762fbb55a579fefd781757a9d29182f5da 100644 (file)
@@ -1102,8 +1102,8 @@ static int wp384_final(struct shash_desc *desc, u8 *out)
        u8 D[64];
 
        wp512_final(desc, D);
-       memcpy (out, D, WP384_DIGEST_SIZE);
-       memset (D, 0, WP512_DIGEST_SIZE);
+       memcpy(out, D, WP384_DIGEST_SIZE);
+       memzero_explicit(D, WP512_DIGEST_SIZE);
 
        return 0;
 }
@@ -1113,8 +1113,8 @@ static int wp256_final(struct shash_desc *desc, u8 *out)
        u8 D[64];
 
        wp512_final(desc, D);
-       memcpy (out, D, WP256_DIGEST_SIZE);
-       memset (D, 0, WP512_DIGEST_SIZE);
+       memcpy(out, D, WP256_DIGEST_SIZE);
+       memzero_explicit(D, WP512_DIGEST_SIZE);
 
        return 0;
 }
index 1a693d3f9d51b52e116ee3ad76ad30023a2ea49c..af02a8a8ec4ab4bf07f7eb7cccf9cbff2c41a5b3 100644 (file)
@@ -1,5 +1,7 @@
 menu "Device Drivers"
 
+source "drivers/amba/Kconfig"
+
 source "drivers/base/Kconfig"
 
 source "drivers/bus/Kconfig"
index d0f3265fb85d5a1f24646db40cc911364e62bfdf..b23fe37f67c02e563875b0227562ba917150a0d5 100644 (file)
@@ -144,7 +144,7 @@ config ACPI_VIDEO
 
 config ACPI_FAN
        tristate "Fan"
-       select THERMAL
+       depends on THERMAL
        default y
        help
          This driver supports ACPI fan devices, allowing user-mode
index 505d4d79fe3e4ce74a631f487ce243e6ae7decb3..c3b2fcb729f30ffc29482774d1656373526e66e5 100644 (file)
@@ -43,6 +43,7 @@ acpi-y                                += pci_root.o pci_link.o pci_irq.o
 acpi-y                         += acpi_lpss.o
 acpi-y                         += acpi_platform.o
 acpi-y                         += acpi_pnp.o
+acpi-y                         += int340x_thermal.o
 acpi-y                         += power.o
 acpi-y                         += event.o
 acpi-y                         += sysfs.o
index 2bf9082f7523cce812780ae17b712ce6a48778f9..6ba8beb6b9d2a515828c3987393dc75fa8b6bc2c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 
 #include "internal.h"
@@ -102,6 +103,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
        pdevinfo.res = resources;
        pdevinfo.num_res = count;
        pdevinfo.acpi_node.companion = adev;
+       pdevinfo.dma_mask = DMA_BIT_MASK(32);
        pdev = platform_device_register_full(&pdevinfo);
        if (IS_ERR(pdev))
                dev_err(&adev->dev, "platform device creation failed: %ld\n",
@@ -113,3 +115,4 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
        kfree(resources);
        return pdev;
 }
+EXPORT_SYMBOL_GPL(acpi_create_platform_device);
index 2ad2351a983321e31c1a4aa6983dfd0dfe419c09..c318d3e27893b6a4c6436ca5b906edcd6df3b656 100644 (file)
@@ -127,7 +127,7 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 
 acpi_status
 acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
-                      acpi_event_status * event_status);
+                      acpi_event_status *event_status);
 
 acpi_status acpi_hw_disable_all_gpes(void);
 
index 2747279fbe3c8e873e02fa9692d79416fb07f729..c00e7e41ad75ae387886d6327f664b090cd19133 100644 (file)
@@ -413,8 +413,8 @@ struct acpi_gpe_handler_info {
        acpi_gpe_handler address;       /* Address of handler, if any */
        void *context;          /* Context to be passed to handler */
        struct acpi_namespace_node *method_node;        /* Method node for this GPE level (saved) */
-       u8 original_flags;      /* Original (pre-handler) GPE info */
-       u8 originally_enabled;  /* True if GPE was originally enabled */
+       u8 original_flags;      /* Original (pre-handler) GPE info */
+       u8 originally_enabled;  /* True if GPE was originally enabled */
 };
 
 /* Notify info for implicit notify, multiple device objects */
index f14882788eeea6fe1f98ee20f9f3ec28e041daa0..1afe46e44dacda512b5429e3f58465aabf95082c 100644 (file)
@@ -49,6 +49,8 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count);
 /*
  * tbxfroot - Root pointer utilities
  */
+u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp);
+
 acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
 
 u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length);
index f3f834408441c34e40ab88127bb83d30c2e2aa0c..3a0beeb86ba5cbb46f2cb9c8c86b31fcf7fd9c22 100644 (file)
@@ -117,6 +117,12 @@ struct asl_resource_node {
        struct asl_resource_node *next;
 };
 
+struct asl_resource_info {
+       union acpi_parse_object *descriptor_type_op;    /* Resource descriptor parse node */
+       union acpi_parse_object *mapping_op;    /* Used for mapfile support */
+       u32 current_byte_offset;        /* Offset in resource template */
+};
+
 /* Macros used to generate AML resource length fields */
 
 #define ACPI_AML_SIZE_LARGE(r)      (sizeof (r) - sizeof (struct aml_resource_large_header))
@@ -449,4 +455,32 @@ union aml_resource {
        u8 byte_item;
 };
 
+/* Interfaces used by both the disassembler and compiler */
+
+void
+mp_save_gpio_info(union acpi_parse_object *op,
+                 union aml_resource *resource,
+                 u32 pin_count, u16 *pin_list, char *device_name);
+
+void
+mp_save_serial_info(union acpi_parse_object *op,
+                   union aml_resource *resource, char *device_name);
+
+char *mp_get_hid_from_parse_tree(struct acpi_namespace_node *hid_node);
+
+char *mp_get_hid_via_namestring(char *device_name);
+
+char *mp_get_connection_info(union acpi_parse_object *op,
+                            u32 pin_index,
+                            struct acpi_namespace_node **target_node,
+                            char **target_name);
+
+char *mp_get_parent_device_hid(union acpi_parse_object *op,
+                              struct acpi_namespace_node **target_node,
+                              char **parent_device_name);
+
+char *mp_get_ddn_value(char *device_name);
+
+char *mp_get_hid_value(struct acpi_namespace_node *device_node);
+
 #endif
index e4ba4dec86af19ef447f3a4783c39015e558778f..2095dfb72bcb3c9fd7a48512c3024d58e09e6c76 100644 (file)
@@ -100,13 +100,14 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
  *
  * FUNCTION:    acpi_ev_enable_gpe
  *
- * PARAMETERS:  gpe_event_info  - GPE to enable
+ * PARAMETERS:  gpe_event_info          - GPE to enable
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Clear a GPE of stale events and enable it.
  *
  ******************************************************************************/
+
 acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 {
        acpi_status status;
@@ -125,6 +126,7 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
        }
 
        /* Clear the GPE (of stale events) */
+
        status = acpi_hw_clear_gpe(gpe_event_info);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
@@ -136,7 +138,6 @@ acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
        return_ACPI_STATUS(status);
 }
 
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_add_gpe_reference
@@ -212,7 +213,7 @@ acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
                if (ACPI_SUCCESS(status)) {
                        status =
                            acpi_hw_low_set_gpe(gpe_event_info,
-                                                    ACPI_GPE_DISABLE);
+                                               ACPI_GPE_DISABLE);
                }
 
                if (ACPI_FAILURE(status)) {
@@ -334,7 +335,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
  *
  ******************************************************************************/
 
-u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
+u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list)
 {
        acpi_status status;
        struct acpi_gpe_block_info *gpe_block;
@@ -427,7 +428,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 
                        /* Check if there is anything active at all in this register */
 
-                       enabled_status_byte = (u8) (status_reg & enable_reg);
+                       enabled_status_byte = (u8)(status_reg & enable_reg);
                        if (!enabled_status_byte) {
 
                                /* No active GPEs in this register, move on */
@@ -450,7 +451,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
                                            acpi_ev_gpe_dispatch(gpe_block->
                                                                 node,
                                                                 &gpe_block->
-                                               event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);
+                                                                event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number);
                                }
                        }
                }
@@ -636,7 +637,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info * gpe_event_info)
 {
        acpi_status status;
 
@@ -666,9 +667,9 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
  *
  * FUNCTION:    acpi_ev_gpe_dispatch
  *
- * PARAMETERS:  gpe_device      - Device node. NULL for GPE0/GPE1
- *              gpe_event_info  - Info for this GPE
- *              gpe_number      - Number relative to the parent GPE block
+ * PARAMETERS:  gpe_device          - Device node. NULL for GPE0/GPE1
+ *              gpe_event_info      - Info for this GPE
+ *              gpe_number          - Number relative to the parent GPE block
  *
  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
  *
@@ -681,7 +682,7 @@ acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
 
 u32
 acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
-                   struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
+                    struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
 {
        acpi_status status;
        u32 return_value;
index 49fc7effd961113031bf2f89b6cc411de503f1aa..7be9283798795e72ec8eadf4bbc6a8a894807fc7 100644 (file)
@@ -424,6 +424,7 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
        }
 
        /* Disable the GPE in case it's been enabled already. */
+
        (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
 
        /*
index 11e5803b8b41958824c4f108954d6bb4ae37aaa8..55a58f3ec8dfa66de2ac6465ad71b7cacca1db58 100644 (file)
@@ -786,18 +786,26 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
        handler->method_node = gpe_event_info->dispatch.method_node;
        handler->original_flags = (u8)(gpe_event_info->flags &
                                       (ACPI_GPE_XRUPT_TYPE_MASK |
-                                       ACPI_GPE_DISPATCH_MASK));
+                                       ACPI_GPE_DISPATCH_MASK));
 
        /*
         * If the GPE is associated with a method, it may have been enabled
         * automatically during initialization, in which case it has to be
         * disabled now to avoid spurious execution of the handler.
         */
-
-       if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
-           && gpe_event_info->runtime_count) {
-               handler->originally_enabled = 1;
+       if (((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) ||
+            (handler->original_flags & ACPI_GPE_DISPATCH_NOTIFY)) &&
+           gpe_event_info->runtime_count) {
+               handler->originally_enabled = TRUE;
                (void)acpi_ev_remove_gpe_reference(gpe_event_info);
+
+               /* Sanity check of original type against new type */
+
+               if (type !=
+                   (u32)(gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {
+                       ACPI_WARNING((AE_INFO,
+                                     "GPE type mismatch (level/edge)"));
+               }
        }
 
        /* Install the handler */
@@ -808,7 +816,7 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
 
        gpe_event_info->flags &=
            ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
-       gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
+       gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_HANDLER);
 
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 
@@ -893,7 +901,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
 
        gpe_event_info->dispatch.method_node = handler->method_node;
        gpe_event_info->flags &=
-               ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
+           ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
        gpe_event_info->flags |= handler->original_flags;
 
        /*
@@ -901,7 +909,8 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
         * enabled, it should be enabled at this point to restore the
         * post-initialization configuration.
         */
-       if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) &&
+       if (((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) ||
+            (handler->original_flags & ACPI_GPE_DISPATCH_NOTIFY)) &&
            handler->originally_enabled) {
                (void)acpi_ev_add_gpe_reference(gpe_event_info);
        }
@@ -946,7 +955,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
  * handle is returned.
  *
  ******************************************************************************/
-acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
+acpi_status acpi_acquire_global_lock(u16 timeout, u32 *handle)
 {
        acpi_status status;
 
index e286640ad4ff9e02974bc9d7c9c1d2a64fd58a92..bb8cbf5961bf46de0cf241e18bd76cf18c6f8b6e 100644 (file)
@@ -324,8 +324,9 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event)
  ******************************************************************************/
 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
 {
-       acpi_status status = AE_OK;
-       u32 value;
+       acpi_status status;
+       acpi_event_status local_event_status = 0;
+       u32 in_byte;
 
        ACPI_FUNCTION_TRACE(acpi_get_event_status);
 
@@ -339,29 +340,40 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
-       /* Get the status of the requested fixed event */
+       /* Fixed event currently can be dispatched? */
+
+       if (acpi_gbl_fixed_event_handlers[event].handler) {
+               local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
+       }
+
+       /* Fixed event currently enabled? */
 
        status =
            acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
-                             enable_register_id, &value);
-       if (ACPI_FAILURE(status))
+                                  enable_register_id, &in_byte);
+       if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
+       }
 
-       *event_status = value;
+       if (in_byte) {
+               local_event_status |= ACPI_EVENT_FLAG_ENABLED;
+       }
+
+       /* Fixed event currently active? */
 
        status =
            acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
-                             status_register_id, &value);
-       if (ACPI_FAILURE(status))
+                                  status_register_id, &in_byte);
+       if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
+       }
 
-       if (value)
-               *event_status |= ACPI_EVENT_FLAG_SET;
-
-       if (acpi_gbl_fixed_event_handlers[event].handler)
-               *event_status |= ACPI_EVENT_FLAG_HANDLE;
+       if (in_byte) {
+               local_event_status |= ACPI_EVENT_FLAG_SET;
+       }
 
-       return_ACPI_STATUS(status);
+       (*event_status) = local_event_status;
+       return_ACPI_STATUS(AE_OK);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
index 56710a03c9b0785229ac56470d82cd449f0478d8..e889a5304abd2fe9206b4a9a911378f4f4a0e050 100644 (file)
@@ -106,8 +106,8 @@ ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
  *
  * FUNCTION:    acpi_enable_gpe
  *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
+ * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number          - GPE level within the GPE block
  *
  * RETURN:      Status
  *
@@ -115,7 +115,6 @@ ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
  *              hardware-enabled.
  *
  ******************************************************************************/
-
 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
 {
        acpi_status status = AE_BAD_PARAMETER;
@@ -490,8 +489,8 @@ ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
  *
  * FUNCTION:    acpi_get_gpe_status
  *
- * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
- *              gpe_number      - GPE level within the GPE block
+ * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
+ *              gpe_number          - GPE level within the GPE block
  *              event_status        - Where the current status of the event
  *                                    will be returned
  *
@@ -524,9 +523,6 @@ acpi_get_gpe_status(acpi_handle gpe_device,
 
        status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
 
-       if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
-               *event_status |= ACPI_EVENT_FLAG_HANDLE;
-
 unlock_and_exit:
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
index ea62d40fd161c75c9a598ef1e317ecb3c81a4ede..48ac7b7b59cdcf7edf954897d1ec1336dd0534bb 100644 (file)
@@ -202,7 +202,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
 
 acpi_status
 acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
-                      acpi_event_status * event_status)
+                      acpi_event_status *event_status)
 {
        u32 in_byte;
        u32 register_bit;
@@ -216,6 +216,13 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
                return (AE_BAD_PARAMETER);
        }
 
+       /* GPE currently handled? */
+
+       if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
+           ACPI_GPE_DISPATCH_NONE) {
+               local_event_status |= ACPI_EVENT_FLAG_HAS_HANDLER;
+       }
+
        /* Get the info block for the entire GPE register */
 
        gpe_register_info = gpe_event_info->register_info;
index 65ab8fed3d5e504011328030cd192b663b1ed507..43a54af2b548fef2b3ebabadd5fe347d8a6a9ecb 100644 (file)
 #define _COMPONENT          ACPI_TABLES
 ACPI_MODULE_NAME("tbxfroot")
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_get_rsdp_length
+ *
+ * PARAMETERS:  rsdp                - Pointer to RSDP
+ *
+ * RETURN:      Table length
+ *
+ * DESCRIPTION: Get the length of the RSDP
+ *
+ ******************************************************************************/
+u32 acpi_tb_get_rsdp_length(struct acpi_table_rsdp *rsdp)
+{
+
+       if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
+
+               /* BAD Signature */
+
+               return (0);
+       }
+
+       /* "Length" field is available if table version >= 2 */
+
+       if (rsdp->revision >= 2) {
+               return (rsdp->length);
+       } else {
+               return (ACPI_RSDP_CHECKSUM_LENGTH);
+       }
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_tb_validate_rsdp
@@ -59,7 +89,8 @@ ACPI_MODULE_NAME("tbxfroot")
  * DESCRIPTION: Validate the RSDP (ptr)
  *
  ******************************************************************************/
-acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
+
+acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp * rsdp)
 {
 
        /*
index ed122e17636e32298129a8e28429ef86cb27a4fa..7556e7c4a055cd0c2dad68fa11a3f8746e6ab16e 100644 (file)
@@ -290,6 +290,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                    DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
                },
        },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Dell Vostro 3546",
+       .matches = {
+                   DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                   DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
+               },
+       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index bea6896be1229b12d5983bb7a738db2c256fd3d1..7db19316076659b493ab1d1c9a295dc88450381d 100644 (file)
@@ -343,6 +343,7 @@ int acpi_device_update_power(struct acpi_device *device, int *state_p)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(acpi_device_update_power);
 
 int acpi_bus_update_power(acpi_handle handle, int *state_p)
 {
@@ -710,7 +711,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
                return -ENODEV;
        }
 
-       return acpi_device_wakeup(adev, enable, ACPI_STATE_S0);
+       return acpi_device_wakeup(adev, ACPI_STATE_S0, enable);
 }
 EXPORT_SYMBOL(acpi_pm_device_run_wake);
 #endif /* CONFIG_PM_RUNTIME */
@@ -877,7 +878,7 @@ int acpi_dev_suspend_late(struct device *dev)
                return 0;
 
        target_state = acpi_target_system_state();
-       wakeup = device_may_wakeup(dev);
+       wakeup = device_may_wakeup(dev) && acpi_device_can_wakeup(adev);
        error = acpi_device_wakeup(adev, target_state, wakeup);
        if (wakeup && error)
                return error;
index cb6066c809ea03dddec42b0871e22a67ef242726..5f9b74b9b71f0a9a6ad2ba4243ceab58c57ff69b 100644 (file)
@@ -126,14 +126,16 @@ static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
 static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
 static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
 static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
+static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
 
 /* --------------------------------------------------------------------------
                            Transaction Management
  -------------------------------------------------------------------------- */
*                           Transaction Management
* -------------------------------------------------------------------------- */
 
 static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
 {
        u8 x = inb(ec->command_addr);
+
        pr_debug("EC_SC(R) = 0x%2.2x "
                 "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n",
                 x,
@@ -148,6 +150,7 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
 static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
 {
        u8 x = inb(ec->data_addr);
+
        pr_debug("EC_DATA(R) = 0x%2.2x\n", x);
        return x;
 }
@@ -164,10 +167,32 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
        outb(data, ec->data_addr);
 }
 
+#ifdef DEBUG
+static const char *acpi_ec_cmd_string(u8 cmd)
+{
+       switch (cmd) {
+       case 0x80:
+               return "RD_EC";
+       case 0x81:
+               return "WR_EC";
+       case 0x82:
+               return "BE_EC";
+       case 0x83:
+               return "BD_EC";
+       case 0x84:
+               return "QR_EC";
+       }
+       return "UNKNOWN";
+}
+#else
+#define acpi_ec_cmd_string(cmd)                "UNDEF"
+#endif
+
 static int ec_transaction_completed(struct acpi_ec *ec)
 {
        unsigned long flags;
        int ret = 0;
+
        spin_lock_irqsave(&ec->lock, flags);
        if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
                ret = 1;
@@ -181,7 +206,8 @@ static bool advance_transaction(struct acpi_ec *ec)
        u8 status;
        bool wakeup = false;
 
-       pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK");
+       pr_debug("===== %s (%d) =====\n",
+                in_interrupt() ? "IRQ" : "TASK", smp_processor_id());
        status = acpi_ec_read_status(ec);
        t = ec->curr;
        if (!t)
@@ -198,7 +224,8 @@ static bool advance_transaction(struct acpi_ec *ec)
                                if (t->rlen == t->ri) {
                                        t->flags |= ACPI_EC_COMMAND_COMPLETE;
                                        if (t->command == ACPI_EC_COMMAND_QUERY)
-                                               pr_debug("hardware QR_EC completion\n");
+                                               pr_debug("***** Command(%s) hardware completion *****\n",
+                                                        acpi_ec_cmd_string(t->command));
                                        wakeup = true;
                                }
                        } else
@@ -210,18 +237,14 @@ static bool advance_transaction(struct acpi_ec *ec)
                }
                return wakeup;
        } else {
-               /*
-                * There is firmware refusing to respond QR_EC when SCI_EVT
-                * is not set, for which case, we complete the QR_EC
-                * without issuing it to the firmware.
-                * https://bugzilla.kernel.org/show_bug.cgi?id=86211
-                */
-               if (!(status & ACPI_EC_FLAG_SCI) &&
+               if (EC_FLAGS_QUERY_HANDSHAKE &&
+                   !(status & ACPI_EC_FLAG_SCI) &&
                    (t->command == ACPI_EC_COMMAND_QUERY)) {
                        t->flags |= ACPI_EC_COMMAND_POLL;
                        t->rdata[t->ri++] = 0x00;
                        t->flags |= ACPI_EC_COMMAND_COMPLETE;
-                       pr_debug("software QR_EC completion\n");
+                       pr_debug("***** Command(%s) software completion *****\n",
+                                acpi_ec_cmd_string(t->command));
                        wakeup = true;
                } else if ((status & ACPI_EC_FLAG_IBF) == 0) {
                        acpi_ec_write_cmd(ec, t->command);
@@ -264,6 +287,7 @@ static int ec_poll(struct acpi_ec *ec)
 {
        unsigned long flags;
        int repeat = 5; /* number of command restarts */
+
        while (repeat--) {
                unsigned long delay = jiffies +
                        msecs_to_jiffies(ec_delay);
@@ -296,18 +320,25 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
 {
        unsigned long tmp;
        int ret = 0;
+
        if (EC_FLAGS_MSI)
                udelay(ACPI_EC_MSI_UDELAY);
        /* start transaction */
        spin_lock_irqsave(&ec->lock, tmp);
        /* following two actions should be kept atomic */
        ec->curr = t;
+       pr_debug("***** Command(%s) started *****\n",
+                acpi_ec_cmd_string(t->command));
        start_transaction(ec);
+       if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
+               clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+               pr_debug("***** Event stopped *****\n");
+       }
        spin_unlock_irqrestore(&ec->lock, tmp);
        ret = ec_poll(ec);
        spin_lock_irqsave(&ec->lock, tmp);
-       if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
-               clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
+       pr_debug("***** Command(%s) stopped *****\n",
+                acpi_ec_cmd_string(t->command));
        ec->curr = NULL;
        spin_unlock_irqrestore(&ec->lock, tmp);
        return ret;
@@ -317,6 +348,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
 {
        int status;
        u32 glk;
+
        if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
                return -EINVAL;
        if (t->rdata)
@@ -333,8 +365,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                        goto unlock;
                }
        }
-       pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
-                       t->command, t->wdata ? t->wdata[0] : 0);
        /* disable GPE during transaction if storm is detected */
        if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
                /* It has to be disabled, so that it doesn't trigger. */
@@ -355,7 +385,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                        t->irq_count);
                set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
        }
-       pr_debug("transaction end\n");
        if (ec->global_lock)
                acpi_release_global_lock(glk);
 unlock:
@@ -383,7 +412,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
                                acpi_ec_transaction(ec, &t) : 0;
 }
 
-static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
+static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
 {
        int result;
        u8 d;
@@ -419,10 +448,9 @@ int ec_read(u8 addr, u8 *val)
        if (!err) {
                *val = temp_data;
                return 0;
-       } else
-               return err;
+       }
+       return err;
 }
-
 EXPORT_SYMBOL(ec_read);
 
 int ec_write(u8 addr, u8 val)
@@ -436,22 +464,21 @@ int ec_write(u8 addr, u8 val)
 
        return err;
 }
-
 EXPORT_SYMBOL(ec_write);
 
 int ec_transaction(u8 command,
-                  const u8 * wdata, unsigned wdata_len,
-                  u8 * rdata, unsigned rdata_len)
+                  const u8 *wdata, unsigned wdata_len,
+                  u8 *rdata, unsigned rdata_len)
 {
        struct transaction t = {.command = command,
                                .wdata = wdata, .rdata = rdata,
                                .wlen = wdata_len, .rlen = rdata_len};
+
        if (!first_ec)
                return -ENODEV;
 
        return acpi_ec_transaction(first_ec, &t);
 }
-
 EXPORT_SYMBOL(ec_transaction);
 
 /* Get the handle to the EC device */
@@ -461,7 +488,6 @@ acpi_handle ec_get_handle(void)
                return NULL;
        return first_ec->handle;
 }
-
 EXPORT_SYMBOL(ec_get_handle);
 
 /*
@@ -525,13 +551,14 @@ void acpi_ec_unblock_transactions_early(void)
                clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
 }
 
-static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
+static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data)
 {
        int result;
        u8 d;
        struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
                                .wdata = NULL, .rdata = &d,
                                .wlen = 0, .rlen = 1};
+
        if (!ec || !data)
                return -EINVAL;
        /*
@@ -557,6 +584,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
 {
        struct acpi_ec_query_handler *handler =
            kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
+
        if (!handler)
                return -ENOMEM;
 
@@ -569,12 +597,12 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
        mutex_unlock(&ec->mutex);
        return 0;
 }
-
 EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
 
 void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 {
        struct acpi_ec_query_handler *handler, *tmp;
+
        mutex_lock(&ec->mutex);
        list_for_each_entry_safe(handler, tmp, &ec->list, node) {
                if (query_bit == handler->query_bit) {
@@ -584,20 +612,20 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
        }
        mutex_unlock(&ec->mutex);
 }
-
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
 static void acpi_ec_run(void *cxt)
 {
        struct acpi_ec_query_handler *handler = cxt;
+
        if (!handler)
                return;
-       pr_debug("start query execution\n");
+       pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit);
        if (handler->func)
                handler->func(handler->data);
        else if (handler->handle)
                acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
-       pr_debug("stop query execution\n");
+       pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit);
        kfree(handler);
 }
 
@@ -620,8 +648,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
                        if (!copy)
                                return -ENOMEM;
                        memcpy(copy, handler, sizeof(*copy));
-                       pr_debug("push query execution (0x%2x) on queue\n",
-                               value);
+                       pr_debug("##### Query(0x%02x) scheduled #####\n",
+                                handler->query_bit);
                        return acpi_os_execute((copy->func) ?
                                OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
                                acpi_ec_run, copy);
@@ -633,6 +661,7 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
 static void acpi_ec_gpe_query(void *ec_cxt)
 {
        struct acpi_ec *ec = ec_cxt;
+
        if (!ec)
                return;
        mutex_lock(&ec->mutex);
@@ -644,7 +673,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
 {
        if (state & ACPI_EC_FLAG_SCI) {
                if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
-                       pr_debug("push gpe query to the queue\n");
+                       pr_debug("***** Event started *****\n");
                        return acpi_os_execute(OSL_NOTIFY_HANDLER,
                                acpi_ec_gpe_query, ec);
                }
@@ -667,8 +696,8 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
 }
 
 /* --------------------------------------------------------------------------
                            Address Space Management
  -------------------------------------------------------------------------- */
*                           Address Space Management
* -------------------------------------------------------------------------- */
 
 static acpi_status
 acpi_ec_space_handler(u32 function, acpi_physical_address address,
@@ -699,27 +728,26 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
        switch (result) {
        case -EINVAL:
                return AE_BAD_PARAMETER;
-               break;
        case -ENODEV:
                return AE_NOT_FOUND;
-               break;
        case -ETIME:
                return AE_TIME;
-               break;
        default:
                return AE_OK;
        }
 }
 
 /* --------------------------------------------------------------------------
-                               Driver Interface
-   -------------------------------------------------------------------------- */
+ *                             Driver Interface
+ * -------------------------------------------------------------------------- */
+
 static acpi_status
 ec_parse_io_ports(struct acpi_resource *resource, void *context);
 
 static struct acpi_ec *make_acpi_ec(void)
 {
        struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+
        if (!ec)
                return NULL;
        ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
@@ -742,9 +770,8 @@ acpi_ec_register_query_methods(acpi_handle handle, u32 level,
 
        status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
 
-       if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1) {
+       if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1)
                acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
-       }
        return AE_OK;
 }
 
@@ -753,7 +780,6 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
 {
        acpi_status status;
        unsigned long long tmp = 0;
-
        struct acpi_ec *ec = context;
 
        /* clear addr values, ec_parse_io_ports depend on it */
@@ -781,6 +807,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
 static int ec_install_handlers(struct acpi_ec *ec)
 {
        acpi_status status;
+
        if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
                return 0;
        status = acpi_install_gpe_handler(NULL, ec->gpe,
@@ -980,6 +1007,18 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
        return 0;
 }
 
+/*
+ * Acer EC firmware refuses to respond QR_EC when SCI_EVT is not set, for
+ * which case, we complete the QR_EC without issuing it to the firmware.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=86211
+ */
+static int ec_flag_query_handshake(const struct dmi_system_id *id)
+{
+       pr_debug("Detected the EC firmware requiring QR_EC issued when SCI_EVT set\n");
+       EC_FLAGS_QUERY_HANDSHAKE = 1;
+       return 0;
+}
+
 /*
  * On some hardware it is necessary to clear events accumulated by the EC during
  * sleep. These ECs stop reporting GPEs until they are manually polled, if too
@@ -1054,6 +1093,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
        {
        ec_clear_on_resume, "Samsung hardware", {
        DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
+       {
+       ec_flag_query_handshake, "Acer hardware", {
+       DMI_MATCH(DMI_SYS_VENDOR, "Acer"), }, NULL},
        {},
 };
 
@@ -1078,7 +1120,8 @@ int __init acpi_ec_ecdt_probe(void)
                boot_ec->data_addr = ecdt_ptr->data.address;
                boot_ec->gpe = ecdt_ptr->gpe;
                boot_ec->handle = ACPI_ROOT_OBJECT;
-               acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
+               acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id,
+                               &boot_ec->handle);
                /* Don't trust ECDT, which comes from ASUSTek */
                if (!EC_FLAGS_VALIDATE_ECDT)
                        goto install;
@@ -1162,6 +1205,5 @@ static void __exit acpi_ec_exit(void)
 {
 
        acpi_bus_unregister_driver(&acpi_ec_driver);
-       return;
 }
 #endif /* 0 */
index 5328b1090e08681dc4905585470fcd43b2b514f1..caf9b76b7ef83f08bca8d7ba1aac487224d68143 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/thermal.h>
 #include <linux/acpi.h>
-
-#define ACPI_FAN_CLASS                 "fan"
-#define ACPI_FAN_FILE_STATE            "state"
-
-#define _COMPONENT             ACPI_FAN_COMPONENT
-ACPI_MODULE_NAME("fan");
+#include <linux/platform_device.h>
+#include <linux/sort.h>
 
 MODULE_AUTHOR("Paul Diefenbaugh");
 MODULE_DESCRIPTION("ACPI Fan Driver");
 MODULE_LICENSE("GPL");
 
-static int acpi_fan_add(struct acpi_device *device);
-static int acpi_fan_remove(struct acpi_device *device);
+static int acpi_fan_probe(struct platform_device *pdev);
+static int acpi_fan_remove(struct platform_device *pdev);
 
 static const struct acpi_device_id fan_device_ids[] = {
        {"PNP0C0B", 0},
+       {"INT3404", 0},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
@@ -64,37 +61,100 @@ static struct dev_pm_ops acpi_fan_pm = {
 #define FAN_PM_OPS_PTR NULL
 #endif
 
-static struct acpi_driver acpi_fan_driver = {
-       .name = "fan",
-       .class = ACPI_FAN_CLASS,
-       .ids = fan_device_ids,
-       .ops = {
-               .add = acpi_fan_add,
-               .remove = acpi_fan_remove,
-               },
-       .drv.pm = FAN_PM_OPS_PTR,
+struct acpi_fan_fps {
+       u64 control;
+       u64 trip_point;
+       u64 speed;
+       u64 noise_level;
+       u64 power;
+};
+
+struct acpi_fan_fif {
+       u64 revision;
+       u64 fine_grain_ctrl;
+       u64 step_size;
+       u64 low_speed_notification;
+};
+
+struct acpi_fan {
+       bool acpi4;
+       struct acpi_fan_fif fif;
+       struct acpi_fan_fps *fps;
+       int fps_count;
+       struct thermal_cooling_device *cdev;
+};
+
+static struct platform_driver acpi_fan_driver = {
+       .probe = acpi_fan_probe,
+       .remove = acpi_fan_remove,
+       .driver = {
+               .name = "acpi-fan",
+               .acpi_match_table = fan_device_ids,
+               .pm = FAN_PM_OPS_PTR,
+       },
 };
 
 /* thermal cooling device callbacks */
 static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
                             *state)
 {
-       /* ACPI fan device only support two states: ON/OFF */
-       *state = 1;
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_fan *fan = acpi_driver_data(device);
+
+       if (fan->acpi4)
+               *state = fan->fps_count - 1;
+       else
+               *state = 1;
        return 0;
 }
 
-static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
-                            *state)
+static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state)
+{
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_fan *fan = acpi_driver_data(device);
+       union acpi_object *obj;
+       acpi_status status;
+       int control, i;
+
+       status = acpi_evaluate_object(device->handle, "_FST", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               dev_err(&device->dev, "Get fan state failed\n");
+               return status;
+       }
+
+       obj = buffer.pointer;
+       if (!obj || obj->type != ACPI_TYPE_PACKAGE ||
+           obj->package.count != 3 ||
+           obj->package.elements[1].type != ACPI_TYPE_INTEGER) {
+               dev_err(&device->dev, "Invalid _FST data\n");
+               status = -EINVAL;
+               goto err;
+       }
+
+       control = obj->package.elements[1].integer.value;
+       for (i = 0; i < fan->fps_count; i++) {
+               if (control == fan->fps[i].control)
+                       break;
+       }
+       if (i == fan->fps_count) {
+               dev_dbg(&device->dev, "Invalid control value returned\n");
+               status = -EINVAL;
+               goto err;
+       }
+
+       *state = i;
+
+err:
+       kfree(obj);
+       return status;
+}
+
+static int fan_get_state(struct acpi_device *device, unsigned long *state)
 {
-       struct acpi_device *device = cdev->devdata;
        int result;
        int acpi_state = ACPI_STATE_D0;
 
-       if (!device)
-               return -EINVAL;
-
-       result = acpi_bus_update_power(device->handle, &acpi_state);
+       result = acpi_device_update_power(device, &acpi_state);
        if (result)
                return result;
 
@@ -103,21 +163,57 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
        return 0;
 }
 
-static int
-fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
+                            *state)
 {
        struct acpi_device *device = cdev->devdata;
-       int result;
+       struct acpi_fan *fan = acpi_driver_data(device);
 
-       if (!device || (state != 0 && state != 1))
+       if (fan->acpi4)
+               return fan_get_state_acpi4(device, state);
+       else
+               return fan_get_state(device, state);
+}
+
+static int fan_set_state(struct acpi_device *device, unsigned long state)
+{
+       if (state != 0 && state != 1)
                return -EINVAL;
 
-       result = acpi_bus_set_power(device->handle,
-                               state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
+       return acpi_device_set_power(device,
+                                    state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD);
+}
 
-       return result;
+static int fan_set_state_acpi4(struct acpi_device *device, unsigned long state)
+{
+       struct acpi_fan *fan = acpi_driver_data(device);
+       acpi_status status;
+
+       if (state >= fan->fps_count)
+               return -EINVAL;
+
+       status = acpi_execute_simple_method(device->handle, "_FSL",
+                                           fan->fps[state].control);
+       if (ACPI_FAILURE(status)) {
+               dev_dbg(&device->dev, "Failed to set state by _FSL\n");
+               return status;
+       }
+
+       return 0;
 }
 
+static int
+fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+{
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_fan *fan = acpi_driver_data(device);
+
+       if (fan->acpi4)
+               return fan_set_state_acpi4(device, state);
+       else
+               return fan_set_state(device, state);
+ }
+
 static const struct thermal_cooling_device_ops fan_cooling_ops = {
        .get_max_state = fan_get_max_state,
        .get_cur_state = fan_get_cur_state,
@@ -129,21 +225,125 @@ static const struct thermal_cooling_device_ops fan_cooling_ops = {
  * --------------------------------------------------------------------------
 */
 
-static int acpi_fan_add(struct acpi_device *device)
+static bool acpi_fan_is_acpi4(struct acpi_device *device)
 {
-       int result = 0;
-       struct thermal_cooling_device *cdev;
+       return acpi_has_method(device->handle, "_FIF") &&
+              acpi_has_method(device->handle, "_FPS") &&
+              acpi_has_method(device->handle, "_FSL") &&
+              acpi_has_method(device->handle, "_FST");
+}
 
-       if (!device)
-               return -EINVAL;
+static int acpi_fan_get_fif(struct acpi_device *device)
+{
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_fan *fan = acpi_driver_data(device);
+       struct acpi_buffer format = { sizeof("NNNN"), "NNNN" };
+       struct acpi_buffer fif = { sizeof(fan->fif), &fan->fif };
+       union acpi_object *obj;
+       acpi_status status;
+
+       status = acpi_evaluate_object(device->handle, "_FIF", NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return status;
+
+       obj = buffer.pointer;
+       if (!obj || obj->type != ACPI_TYPE_PACKAGE) {
+               dev_err(&device->dev, "Invalid _FIF data\n");
+               status = -EINVAL;
+               goto err;
+       }
 
-       strcpy(acpi_device_name(device), "Fan");
-       strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
+       status = acpi_extract_package(obj, &format, &fif);
+       if (ACPI_FAILURE(status)) {
+               dev_err(&device->dev, "Invalid _FIF element\n");
+               status = -EINVAL;
+       }
 
-       result = acpi_bus_update_power(device->handle, NULL);
-       if (result) {
-               dev_err(&device->dev, "Setting initial power state\n");
-               goto end;
+err:
+       kfree(obj);
+       return status;
+}
+
+static int acpi_fan_speed_cmp(const void *a, const void *b)
+{
+       const struct acpi_fan_fps *fps1 = a;
+       const struct acpi_fan_fps *fps2 = b;
+       return fps1->speed - fps2->speed;
+}
+
+static int acpi_fan_get_fps(struct acpi_device *device)
+{
+       struct acpi_fan *fan = acpi_driver_data(device);
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       acpi_status status;
+       int i;
+
+       status = acpi_evaluate_object(device->handle, "_FPS", NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return status;
+
+       obj = buffer.pointer;
+       if (!obj || obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) {
+               dev_err(&device->dev, "Invalid _FPS data\n");
+               status = -EINVAL;
+               goto err;
+       }
+
+       fan->fps_count = obj->package.count - 1; /* minus revision field */
+       fan->fps = devm_kzalloc(&device->dev,
+                               fan->fps_count * sizeof(struct acpi_fan_fps),
+                               GFP_KERNEL);
+       if (!fan->fps) {
+               dev_err(&device->dev, "Not enough memory\n");
+               status = -ENOMEM;
+               goto err;
+       }
+       for (i = 0; i < fan->fps_count; i++) {
+               struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
+               struct acpi_buffer fps = { sizeof(fan->fps[i]), &fan->fps[i] };
+               status = acpi_extract_package(&obj->package.elements[i + 1],
+                                             &format, &fps);
+               if (ACPI_FAILURE(status)) {
+                       dev_err(&device->dev, "Invalid _FPS element\n");
+                       break;
+               }
+       }
+
+       /* sort the state array according to fan speed in increase order */
+       sort(fan->fps, fan->fps_count, sizeof(*fan->fps),
+            acpi_fan_speed_cmp, NULL);
+
+err:
+       kfree(obj);
+       return status;
+}
+
+static int acpi_fan_probe(struct platform_device *pdev)
+{
+       int result = 0;
+       struct thermal_cooling_device *cdev;
+       struct acpi_fan *fan;
+       struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+
+       fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
+       if (!fan) {
+               dev_err(&device->dev, "No memory for fan\n");
+               return -ENOMEM;
+       }
+       device->driver_data = fan;
+       platform_set_drvdata(pdev, fan);
+
+       if (acpi_fan_is_acpi4(device)) {
+               if (acpi_fan_get_fif(device) || acpi_fan_get_fps(device))
+                       goto end;
+               fan->acpi4 = true;
+       } else {
+               result = acpi_device_update_power(device, NULL);
+               if (result) {
+                       dev_err(&device->dev, "Setting initial power state\n");
+                       goto end;
+               }
        }
 
        cdev = thermal_cooling_device_register("Fan", device,
@@ -153,44 +353,32 @@ static int acpi_fan_add(struct acpi_device *device)
                goto end;
        }
 
-       dev_dbg(&device->dev, "registered as cooling_device%d\n", cdev->id);
+       dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);
 
-       device->driver_data = cdev;
-       result = sysfs_create_link(&device->dev.kobj,
+       fan->cdev = cdev;
+       result = sysfs_create_link(&pdev->dev.kobj,
                                   &cdev->device.kobj,
                                   "thermal_cooling");
        if (result)
-               dev_err(&device->dev, "Failed to create sysfs link "
-                       "'thermal_cooling'\n");
+               dev_err(&pdev->dev, "Failed to create sysfs link 'thermal_cooling'\n");
 
        result = sysfs_create_link(&cdev->device.kobj,
-                                  &device->dev.kobj,
+                                  &pdev->dev.kobj,
                                   "device");
        if (result)
-               dev_err(&device->dev, "Failed to create sysfs link 'device'\n");
-
-       dev_info(&device->dev, "ACPI: %s [%s] (%s)\n",
-              acpi_device_name(device), acpi_device_bid(device),
-              !device->power.state ? "on" : "off");
+               dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");
 
 end:
        return result;
 }
 
-static int acpi_fan_remove(struct acpi_device *device)
+static int acpi_fan_remove(struct platform_device *pdev)
 {
-       struct thermal_cooling_device *cdev;
-
-       if (!device)
-               return -EINVAL;
-
-       cdev =  acpi_driver_data(device);
-       if (!cdev)
-               return -EINVAL;
+       struct acpi_fan *fan = platform_get_drvdata(pdev);
 
-       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-       sysfs_remove_link(&cdev->device.kobj, "device");
-       thermal_cooling_device_unregister(cdev);
+       sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling");
+       sysfs_remove_link(&fan->cdev->device.kobj, "device");
+       thermal_cooling_device_unregister(fan->cdev);
 
        return 0;
 }
@@ -198,10 +386,11 @@ static int acpi_fan_remove(struct acpi_device *device)
 #ifdef CONFIG_PM_SLEEP
 static int acpi_fan_suspend(struct device *dev)
 {
-       if (!dev)
-               return -EINVAL;
+       struct acpi_fan *fan = dev_get_drvdata(dev);
+       if (fan->acpi4)
+               return 0;
 
-       acpi_bus_set_power(to_acpi_device(dev)->handle, ACPI_STATE_D0);
+       acpi_device_set_power(ACPI_COMPANION(dev), ACPI_STATE_D0);
 
        return AE_OK;
 }
@@ -209,11 +398,12 @@ static int acpi_fan_suspend(struct device *dev)
 static int acpi_fan_resume(struct device *dev)
 {
        int result;
+       struct acpi_fan *fan = dev_get_drvdata(dev);
 
-       if (!dev)
-               return -EINVAL;
+       if (fan->acpi4)
+               return 0;
 
-       result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL);
+       result = acpi_device_update_power(ACPI_COMPANION(dev), NULL);
        if (result)
                dev_err(dev, "Error updating fan power state\n");
 
@@ -221,4 +411,4 @@ static int acpi_fan_resume(struct device *dev)
 }
 #endif
 
-module_acpi_driver(acpi_fan_driver);
+module_platform_driver(acpi_fan_driver);
diff --git a/drivers/acpi/int340x_thermal.c b/drivers/acpi/int340x_thermal.c
new file mode 100644 (file)
index 0000000..a27d31d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ACPI support for int340x thermal drivers
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Zhang Rui <rui.zhang@intel.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/module.h>
+
+#include "internal.h"
+
+#define DO_ENUMERATION 0x01
+static const struct acpi_device_id int340x_thermal_device_ids[] = {
+       {"INT3400", DO_ENUMERATION },
+       {"INT3401"},
+       {"INT3402"},
+       {"INT3403"},
+       {"INT3404"},
+       {"INT3406"},
+       {"INT3407"},
+       {"INT3408"},
+       {"INT3409"},
+       {"INT340A"},
+       {"INT340B"},
+       {""},
+};
+
+static int int340x_thermal_handler_attach(struct acpi_device *adev,
+                                       const struct acpi_device_id *id)
+{
+#if defined(CONFIG_INT340X_THERMAL) || defined(CONFIG_INT340X_THERMAL_MODULE)
+       if (id->driver_data == DO_ENUMERATION)
+               acpi_create_platform_device(adev);
+#endif
+       return 1;
+}
+
+static struct acpi_scan_handler int340x_thermal_handler = {
+       .ids = int340x_thermal_device_ids,
+       .attach = int340x_thermal_handler_attach,
+};
+
+void __init acpi_int340x_thermal_init(void)
+{
+       acpi_scan_add_handler(&int340x_thermal_handler);
+}
index 4c5cf77e7576ea10b9e11a07b7fc5a9adbb60214..447f6d679b29ad7e35ffb8223e58d95266f31dde 100644 (file)
@@ -31,6 +31,7 @@ void acpi_pci_link_init(void);
 void acpi_processor_init(void);
 void acpi_platform_init(void);
 void acpi_pnp_init(void);
+void acpi_int340x_thermal_init(void);
 int acpi_sysfs_init(void);
 void acpi_container_init(void);
 void acpi_memory_hotplug_init(void);
@@ -103,8 +104,6 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
 int acpi_power_on_resources(struct acpi_device *device, int state);
 int acpi_power_transition(struct acpi_device *device, int state);
 
-int acpi_device_update_power(struct acpi_device *device, int *state_p);
-
 int acpi_wakeup_device_init(void);
 
 #ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC
@@ -167,13 +166,6 @@ static inline int suspend_nvs_save(void) { return 0; }
 static inline void suspend_nvs_restore(void) {}
 #endif
 
-/*--------------------------------------------------------------------------
-                               Platform bus support
-  -------------------------------------------------------------------------- */
-struct platform_device;
-
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
-
 /*--------------------------------------------------------------------------
                                        Video
   -------------------------------------------------------------------------- */
index ae44d8654c8248c73870727098666e2b42dec6f8..0476e90b2091faac82867e686a8bddde36ed8781 100644 (file)
@@ -141,6 +141,53 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
        return len;
 }
 
+/*
+ * acpi_companion_match() - Can we match via ACPI companion device
+ * @dev: Device in question
+ *
+ * Check if the given device has an ACPI companion and if that companion has
+ * a valid list of PNP IDs, and if the device is the first (primary) physical
+ * device associated with it.
+ *
+ * If multiple physical devices are attached to a single ACPI companion, we need
+ * to be careful.  The usage scenario for this kind of relationship is that all
+ * of the physical devices in question use resources provided by the ACPI
+ * companion.  A typical case is an MFD device where all the sub-devices share
+ * the parent's ACPI companion.  In such cases we can only allow the primary
+ * (first) physical device to be matched with the help of the companion's PNP
+ * IDs.
+ *
+ * Additional physical devices sharing the ACPI companion can still use
+ * resources available from it but they will be matched normally using functions
+ * provided by their bus types (and analogously for their modalias).
+ */
+static bool acpi_companion_match(const struct device *dev)
+{
+       struct acpi_device *adev;
+       bool ret;
+
+       adev = ACPI_COMPANION(dev);
+       if (!adev)
+               return false;
+
+       if (list_empty(&adev->pnp.ids))
+               return false;
+
+       mutex_lock(&adev->physical_node_lock);
+       if (list_empty(&adev->physical_node_list)) {
+               ret = false;
+       } else {
+               const struct acpi_device_physical_node *node;
+
+               node = list_first_entry(&adev->physical_node_list,
+                                       struct acpi_device_physical_node, node);
+               ret = node->dev == dev;
+       }
+       mutex_unlock(&adev->physical_node_lock);
+
+       return ret;
+}
+
 /*
  * Creates uevent modalias field for ACPI enumerated devices.
  * Because the other buses does not support ACPI HIDs & CIDs.
@@ -149,20 +196,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
  */
 int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
 {
-       struct acpi_device *acpi_dev;
        int len;
 
-       acpi_dev = ACPI_COMPANION(dev);
-       if (!acpi_dev)
-               return -ENODEV;
-
-       /* Fall back to bus specific way of modalias exporting */
-       if (list_empty(&acpi_dev->pnp.ids))
+       if (!acpi_companion_match(dev))
                return -ENODEV;
 
        if (add_uevent_var(env, "MODALIAS="))
                return -ENOMEM;
-       len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
+       len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1],
                                sizeof(env->buf) - env->buflen);
        if (len <= 0)
                return len;
@@ -179,18 +220,12 @@ EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
  */
 int acpi_device_modalias(struct device *dev, char *buf, int size)
 {
-       struct acpi_device *acpi_dev;
        int len;
 
-       acpi_dev = ACPI_COMPANION(dev);
-       if (!acpi_dev)
+       if (!acpi_companion_match(dev))
                return -ENODEV;
 
-       /* Fall back to bus specific way of modalias exporting */
-       if (list_empty(&acpi_dev->pnp.ids))
-               return -ENODEV;
-
-       len = create_modalias(acpi_dev, buf, size -1);
+       len = create_modalias(ACPI_COMPANION(dev), buf, size -1);
        if (len <= 0)
                return len;
        buf[len++] = '\n';
@@ -853,6 +888,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
        if (!ids || !handle || acpi_bus_get_device(handle, &adev))
                return NULL;
 
+       if (!acpi_companion_match(dev))
+               return NULL;
+
        return __acpi_match_device(adev, ids);
 }
 EXPORT_SYMBOL_GPL(acpi_match_device);
@@ -1470,7 +1508,7 @@ static void acpi_wakeup_gpe_init(struct acpi_device *device)
        if (ACPI_FAILURE(status))
                return;
 
-       wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HANDLE);
+       wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HAS_HANDLER);
 }
 
 static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
@@ -2315,6 +2353,7 @@ int __init acpi_scan_init(void)
        acpi_container_init();
        acpi_memory_hotplug_init();
        acpi_pnp_init();
+       acpi_int340x_thermal_init();
 
        mutex_lock(&acpi_scan_lock);
        /*
index 38cb9782d4b871f54c646fc360f922bac03a68fd..13e577c80201bb1ce4341f9b99007e28d1a0a261 100644 (file)
@@ -537,7 +537,7 @@ static ssize_t counter_show(struct kobject *kobj,
        if (result)
                goto end;
 
-       if (!(status & ACPI_EVENT_FLAG_HANDLE))
+       if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER))
                size += sprintf(buf + size, "   invalid");
        else if (status & ACPI_EVENT_FLAG_ENABLED)
                size += sprintf(buf + size, "   enabled");
@@ -581,7 +581,7 @@ static ssize_t counter_set(struct kobject *kobj,
        if (result)
                goto end;
 
-       if (!(status & ACPI_EVENT_FLAG_HANDLE)) {
+       if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER)) {
                printk(KERN_WARNING PREFIX
                       "Can not change Invalid GPE/Fixed Event status\n");
                return -EINVAL;
index 112817e963e05f01ab11fe9234ef46ec56cc9886..d24fa1964eb8ff1e6195610f9e258cdd00f22b6c 100644 (file)
@@ -528,7 +528,6 @@ static void acpi_thermal_check(void *data)
 }
 
 /* sys I/F for generic thermal sysfs support */
-#define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
 
 static int thermal_get_temp(struct thermal_zone_device *thermal,
                            unsigned long *temp)
@@ -543,7 +542,8 @@ static int thermal_get_temp(struct thermal_zone_device *thermal,
        if (result)
                return result;
 
-       *temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
+       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(tz->temperature,
+                                                       tz->kelvin_offset);
        return 0;
 }
 
@@ -647,7 +647,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.critical.flags.valid) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.critical.temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -657,7 +657,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.hot.flags.valid) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.hot.temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -667,7 +667,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.passive.flags.valid) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.passive.temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -678,7 +678,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
                tz->trips.active[i].flags.valid; i++) {
                if (!trip) {
-                       *temp = KELVIN_TO_MILLICELSIUS(
+                       *temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.active[i].temperature,
                                tz->kelvin_offset);
                        return 0;
@@ -694,7 +694,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
        struct acpi_thermal *tz = thermal->devdata;
 
        if (tz->trips.critical.flags.valid) {
-               *temperature = KELVIN_TO_MILLICELSIUS(
+               *temperature = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
                                tz->trips.critical.temperature,
                                tz->kelvin_offset);
                return 0;
@@ -714,8 +714,8 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
 
        if (type == THERMAL_TRIP_ACTIVE) {
                unsigned long trip_temp;
-               unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature,
-                                                       tz->kelvin_offset);
+               unsigned long temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
+                                       tz->temperature, tz->kelvin_offset);
                if (thermal_get_trip_temp(thermal, trip, &trip_temp))
                        return -EINVAL;
 
index 834f35c4bf8d50061e1cae9f0b581cdad9467369..371ac12d25b16ee4c651649a147c7e3e9f9fdc87 100644 (file)
@@ -149,6 +149,21 @@ acpi_extract_package(union acpi_object *package,
                                break;
                        }
                        break;
+               case ACPI_TYPE_LOCAL_REFERENCE:
+                       switch (format_string[i]) {
+                       case 'R':
+                               size_required += sizeof(void *);
+                               tail_offset += sizeof(void *);
+                               break;
+                       default:
+                               printk(KERN_WARNING PREFIX "Invalid package element"
+                                             " [%d] got reference,"
+                                             " expecting [%c]\n",
+                                             i, format_string[i]);
+                               return AE_BAD_DATA;
+                               break;
+                       }
+                       break;
 
                case ACPI_TYPE_PACKAGE:
                default:
@@ -247,7 +262,18 @@ acpi_extract_package(union acpi_object *package,
                                break;
                        }
                        break;
-
+               case ACPI_TYPE_LOCAL_REFERENCE:
+                       switch (format_string[i]) {
+                       case 'R':
+                               *(void **)head =
+                                   (void *)element->reference.handle;
+                               head += sizeof(void *);
+                               break;
+                       default:
+                               /* Should never get here */
+                               break;
+                       }
+                       break;
                case ACPI_TYPE_PACKAGE:
                        /* TBD: handle nested packages... */
                default:
index 807a88a0f394f8a639cbc3f6e2b78073078986cc..9d75ead2a1f9107e92bf7f6408348add2cd71a7f 100644 (file)
@@ -1164,7 +1164,8 @@ static bool acpi_video_device_in_dod(struct acpi_video_device *device)
                return true;
 
        for (i = 0; i < video->attached_count; i++) {
-               if (video->attached_array[i].bind_info == device)
+               if ((video->attached_array[i].value.int_val & 0xfff) ==
+                   (device->device_id & 0xfff))
                        return true;
        }
 
diff --git a/drivers/amba/Kconfig b/drivers/amba/Kconfig
new file mode 100644 (file)
index 0000000..4a5c9d2
--- /dev/null
@@ -0,0 +1,14 @@
+config ARM_AMBA
+       bool
+
+if ARM_AMBA
+
+config TEGRA_AHB
+       bool "Enable AHB driver for NVIDIA Tegra SoCs"
+       default y if ARCH_TEGRA
+       help
+         Adds AHB configuration functionality for NVIDIA Tegra SoCs,
+         which controls AHB bus master arbitration and some performance
+         parameters (priority, prefetch size).
+
+endif
index 5f039f1910677ff45d59cb4f7c0812f84f1dac23..49f1e6890587e0b7f8970fe2dbdb7d879da92871 100644 (file)
@@ -60,6 +60,7 @@ enum board_ids {
        /* board IDs by feature in alphabetical order */
        board_ahci,
        board_ahci_ign_iferr,
+       board_ahci_nomsi,
        board_ahci_noncq,
        board_ahci_nosntf,
        board_ahci_yes_fbs,
@@ -121,6 +122,13 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
        },
+       [board_ahci_nomsi] = {
+               AHCI_HFLAGS     (AHCI_HFLAG_NO_MSI),
+               .flags          = AHCI_FLAG_COMMON,
+               .pio_mask       = ATA_PIO4,
+               .udma_mask      = ATA_UDMA6,
+               .port_ops       = &ahci_ops,
+       },
        [board_ahci_noncq] = {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_NCQ),
                .flags          = AHCI_FLAG_COMMON,
@@ -313,6 +321,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
        { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
        { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
+       { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
+       { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
+       { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */
+       { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
+       { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
+       { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -475,10 +491,11 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1062 */
 
        /*
-        * Samsung SSDs found on some macbooks.  NCQ times out.
-        * https://bugzilla.kernel.org/show_bug.cgi?id=60731
+        * Samsung SSDs found on some macbooks.  NCQ times out if MSI is
+        * enabled.  https://bugzilla.kernel.org/show_bug.cgi?id=60731
         */
-       { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq },
+       { PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
+       { PCI_VDEVICE(SAMSUNG, 0xa800), board_ahci_nomsi },
 
        /* Enmotus */
        { PCI_DEVICE(0x1c44, 0x8000), board_ahci },
@@ -514,12 +531,9 @@ MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
 static void ahci_pci_save_initial_config(struct pci_dev *pdev,
                                         struct ahci_host_priv *hpriv)
 {
-       unsigned int force_port_map = 0;
-       unsigned int mask_port_map = 0;
-
        if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
                dev_info(&pdev->dev, "JMB361 has only one port\n");
-               force_port_map = 1;
+               hpriv->force_port_map = 1;
        }
 
        /*
@@ -529,9 +543,9 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
         */
        if (hpriv->flags & AHCI_HFLAG_MV_PATA) {
                if (pdev->device == 0x6121)
-                       mask_port_map = 0x3;
+                       hpriv->mask_port_map = 0x3;
                else
-                       mask_port_map = 0xf;
+                       hpriv->mask_port_map = 0xf;
                dev_info(&pdev->dev,
                          "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
        }
index 5eb61c9e63da95cbd24a54ee0604262288c8a9f6..97683e45ab043be5045ae22945a5520e845cfe4f 100644 (file)
@@ -1778,16 +1778,15 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
        }
 }
 
-static void ahci_update_intr_status(struct ata_port *ap)
+static void ahci_port_intr(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
-       struct ahci_port_priv *pp = ap->private_data;
        u32 status;
 
        status = readl(port_mmio + PORT_IRQ_STAT);
        writel(status, port_mmio + PORT_IRQ_STAT);
 
-       atomic_or(status, &pp->intr_status);
+       ahci_handle_port_interrupt(ap, port_mmio, status);
 }
 
 static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
@@ -1808,34 +1807,6 @@ static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
-irqreturn_t ahci_thread_fn(int irq, void *dev_instance)
-{
-       struct ata_host *host = dev_instance;
-       struct ahci_host_priv *hpriv = host->private_data;
-       u32 irq_masked = hpriv->port_map;
-       unsigned int i;
-
-       for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap;
-
-               if (!(irq_masked & (1 << i)))
-                       continue;
-
-               ap = host->ports[i];
-               if (ap) {
-                       ahci_port_thread_fn(irq, ap);
-                       VPRINTK("port %u\n", i);
-               } else {
-                       VPRINTK("port %u (no irq)\n", i);
-                       if (ata_ratelimit())
-                               dev_warn(host->dev,
-                                        "interrupt on disabled port %u\n", i);
-               }
-       }
-
-       return IRQ_HANDLED;
-}
-
 static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance)
 {
        struct ata_port *ap = dev_instance;
@@ -1875,6 +1846,8 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
 
        irq_masked = irq_stat & hpriv->port_map;
 
+       spin_lock(&host->lock);
+
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap;
 
@@ -1883,7 +1856,7 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
 
                ap = host->ports[i];
                if (ap) {
-                       ahci_update_intr_status(ap);
+                       ahci_port_intr(ap);
                        VPRINTK("port %u\n", i);
                } else {
                        VPRINTK("port %u (no irq)\n", i);
@@ -1906,9 +1879,11 @@ static irqreturn_t ahci_single_irq_intr(int irq, void *dev_instance)
         */
        writel(irq_stat, mmio + HOST_IRQ_STAT);
 
+       spin_unlock(&host->lock);
+
        VPRINTK("EXIT\n");
 
-       return handled ? IRQ_WAKE_THREAD : IRQ_NONE;
+       return IRQ_RETVAL(handled);
 }
 
 unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
@@ -2320,8 +2295,13 @@ static int ahci_port_start(struct ata_port *ap)
         */
        pp->intr_mask = DEF_PORT_IRQ;
 
-       spin_lock_init(&pp->lock);
-       ap->lock = &pp->lock;
+       /*
+        * Switch to per-port locking in case each port has its own MSI vector.
+        */
+       if ((hpriv->flags & AHCI_HFLAG_MULTI_MSI)) {
+               spin_lock_init(&pp->lock);
+               ap->lock = &pp->lock;
+       }
 
        ap->private_data = pp;
 
@@ -2482,31 +2462,6 @@ out_free_irqs:
        return rc;
 }
 
-static int ahci_host_activate_single_irq(struct ata_host *host, int irq,
-                                        struct scsi_host_template *sht)
-{
-       int i, rc;
-
-       rc = ata_host_start(host);
-       if (rc)
-               return rc;
-
-       rc = devm_request_threaded_irq(host->dev, irq, ahci_single_irq_intr,
-                                      ahci_thread_fn, IRQF_SHARED,
-                                      dev_driver_string(host->dev), host);
-       if (rc)
-               return rc;
-
-       for (i = 0; i < host->n_ports; i++)
-               ata_port_desc(host->ports[i], "irq %d", irq);
-
-       rc = ata_host_register(host, sht);
-       if (rc)
-               devm_free_irq(host->dev, irq, host);
-
-       return rc;
-}
-
 /**
  *     ahci_host_activate - start AHCI host, request IRQs and register it
  *     @host: target ATA host
@@ -2532,7 +2487,8 @@ int ahci_host_activate(struct ata_host *host, int irq,
        if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
                rc = ahci_host_activate_multi_irqs(host, irq, sht);
        else
-               rc = ahci_host_activate_single_irq(host, irq, sht);
+               rc = ata_host_activate(host, irq, ahci_single_irq_intr,
+                                      IRQF_SHARED, sht);
        return rc;
 }
 EXPORT_SYMBOL_GPL(ahci_host_activate);
index 0586f66d70fad3a52e37e2cc87bc6c5de5e8ec7c..dd45c6a03e5d3d0acb6c8e33d97230c2707167ed 100644 (file)
@@ -1164,7 +1164,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
 
                depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
                depth = min(ATA_MAX_QUEUE - 1, depth);
-               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
+               scsi_change_queue_depth(sdev, depth);
        }
 
        blk_queue_flush_queueable(q, false);
@@ -1243,21 +1243,17 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
  *     @ap: ATA port to which the device change the queue depth
  *     @sdev: SCSI device to configure queue depth for
  *     @queue_depth: new queue depth
- *     @reason: calling context
  *
  *     libsas and libata have different approaches for associating a sdev to
  *     its ata_port.
  *
  */
 int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
-                            int queue_depth, int reason)
+                            int queue_depth)
 {
        struct ata_device *dev;
        unsigned long flags;
 
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (queue_depth < 1 || queue_depth == sdev->queue_depth)
                return sdev->queue_depth;
 
@@ -1282,15 +1278,13 @@ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
        if (sdev->queue_depth == queue_depth)
                return -EINVAL;
 
-       scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
-       return queue_depth;
+       return scsi_change_queue_depth(sdev, queue_depth);
 }
 
 /**
  *     ata_scsi_change_queue_depth - SCSI callback for queue depth config
  *     @sdev: SCSI device to configure queue depth for
  *     @queue_depth: new queue depth
- *     @reason: calling context
  *
  *     This is libata standard hostt->change_queue_depth callback.
  *     SCSI will call into this callback when user tries to set queue
@@ -1302,12 +1296,11 @@ int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
  *     RETURNS:
  *     Newly configured queue depth.
  */
-int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth,
-                               int reason)
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
 {
        struct ata_port *ap = ata_shost_to_port(sdev->host);
 
-       return __ata_change_queue_depth(ap, sdev, queue_depth, reason);
+       return __ata_change_queue_depth(ap, sdev, queue_depth);
 }
 
 /**
@@ -3570,7 +3563,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
                ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
                break;
 
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
                        ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
                else
index 07bc7e4dbd04b836722d42b1051dc3da33f99a9d..65071591b143f5b0914b3ba37c8a0ac8f16f01fb 100644 (file)
@@ -1488,7 +1488,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
        host_priv->csr_base = csr_base;
 
        irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
-       if (irq < 0) {
+       if (!irq) {
                dev_err(&ofdev->dev, "invalid irq from platform\n");
                goto error_exit_with_cleanup;
        }
index cdf99fac139a1c2bc5e4f77df39ec2d3be32f400..1db6f5ce5e8912b149f33b49f8876ebc608fc8e8 100644 (file)
@@ -1951,7 +1951,7 @@ static int nv_swncq_slave_config(struct scsi_device *sdev)
        ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
        if (strncmp(model_num, "Maxtor", 6) == 0) {
-               ata_scsi_change_queue_depth(sdev, 1, SCSI_QDEPTH_DEFAULT);
+               ata_scsi_change_queue_depth(sdev, 1);
                ata_dev_notice(dev, "Disabling SWNCQ mode (depth %x)\n",
                               sdev->queue_depth);
        }
index 61eb6d77dac7f507403578a283eade305378f566..ea1fbc1d4c5f1134d05e69a8e9d322c3f54d0789 100644 (file)
 enum sata_rcar_type {
        RCAR_GEN1_SATA,
        RCAR_GEN2_SATA,
+       RCAR_R8A7790_ES1_SATA,
 };
 
 struct sata_rcar_priv {
@@ -763,6 +764,9 @@ static void sata_rcar_setup_port(struct ata_host *host)
        ap->udma_mask   = ATA_UDMA6;
        ap->flags       |= ATA_FLAG_SATA;
 
+       if (priv->type == RCAR_R8A7790_ES1_SATA)
+               ap->flags       |= ATA_FLAG_NO_DIPM;
+
        ioaddr->cmd_addr = base + SDATA_REG;
        ioaddr->ctl_addr = base + SSDEVCON_REG;
        ioaddr->scr_addr = base + SCRSSTS_REG;
@@ -792,6 +796,7 @@ static void sata_rcar_init_controller(struct ata_host *host)
                sata_rcar_gen1_phy_init(priv);
                break;
        case RCAR_GEN2_SATA:
+       case RCAR_R8A7790_ES1_SATA:
                sata_rcar_gen2_phy_init(priv);
                break;
        default:
@@ -837,10 +842,18 @@ static struct of_device_id sata_rcar_match[] = {
                .compatible = "renesas,sata-r8a7790",
                .data = (void *)RCAR_GEN2_SATA
        },
+       {
+               .compatible = "renesas,sata-r8a7790-es1",
+               .data = (void *)RCAR_R8A7790_ES1_SATA
+       },
        {
                .compatible = "renesas,sata-r8a7791",
                .data = (void *)RCAR_GEN2_SATA
        },
+       {
+               .compatible = "renesas,sata-r8a7793",
+               .data = (void *)RCAR_GEN2_SATA
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, sata_rcar_match);
@@ -849,7 +862,9 @@ static const struct platform_device_id sata_rcar_id_table[] = {
        { "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */
        { "sata-r8a7779", RCAR_GEN1_SATA },
        { "sata-r8a7790", RCAR_GEN2_SATA },
+       { "sata-r8a7790-es1", RCAR_R8A7790_ES1_SATA },
        { "sata-r8a7791", RCAR_GEN2_SATA },
+       { "sata-r8a7793", RCAR_GEN2_SATA },
        { },
 };
 MODULE_DEVICE_TABLE(platform, sata_rcar_id_table);
index 7652e8dc188f93036e03a23a99ac7aee3b543811..21b0bc6a9c969ea677630a827f69c45545a9e78a 100644 (file)
@@ -1225,11 +1225,13 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
        card->config_regs = pci_iomap(dev, 0, CONFIG_RAM_SIZE);
        if (!card->config_regs) {
                dev_warn(&dev->dev, "Failed to ioremap config registers\n");
+               err = -ENOMEM;
                goto out_release_regions;
        }
        card->buffers = pci_iomap(dev, 1, DATA_RAM_SIZE);
        if (!card->buffers) {
                dev_warn(&dev->dev, "Failed to ioremap data buffers\n");
+               err = -ENOMEM;
                goto out_unmap_config;
        }
 
index 61a33f4ba608cdc2fe01f691f46f92b2aba1d3e7..df04227d00cfae6fd729e32e5a28d354c501331f 100644 (file)
@@ -171,20 +171,23 @@ config WANT_DEV_COREDUMP
          Drivers should "select" this option if they desire to use the
          device coredump mechanism.
 
-config DISABLE_DEV_COREDUMP
-       bool "Disable device coredump" if EXPERT
+config ALLOW_DEV_COREDUMP
+       bool "Allow device coredump" if EXPERT
+       default y
        help
-         Disable the device coredump mechanism despite drivers wanting to
-         use it; this allows for more sensitive systems or systems that
-         don't want to ever access the information to not have the code,
-         nor keep any data.
+         This option controls if the device coredump mechanism is available or
+         not; if disabled, the mechanism will be omitted even if drivers that
+         can use it are enabled.
+         Say 'N' for more sensitive systems or systems that don't want
+         to ever access the information to not have the code, nor keep any
+         data.
 
-         If unsure, say N.
+         If unsure, say Y.
 
 config DEV_COREDUMP
        bool
        default y if WANT_DEV_COREDUMP
-       depends on !DISABLE_DEV_COREDUMP
+       depends on ALLOW_DEV_COREDUMP
 
 config DEBUG_DRIVER
        bool "Driver Core verbose debug messages"
index 14d162952c3bc21bdadf3966ccef0c7b2c43df91..842d04707de6b04dc6eec9f5aab9acb8885d235a 100644 (file)
@@ -724,12 +724,12 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj)
        return &dir->kobj;
 }
 
+static DEFINE_MUTEX(gdp_mutex);
 
 static struct kobject *get_device_parent(struct device *dev,
                                         struct device *parent)
 {
        if (dev->class) {
-               static DEFINE_MUTEX(gdp_mutex);
                struct kobject *kobj = NULL;
                struct kobject *parent_kobj;
                struct kobject *k;
@@ -793,7 +793,9 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
            glue_dir->kset != &dev->class->p->glue_dirs)
                return;
 
+       mutex_lock(&gdp_mutex);
        kobject_put(glue_dir);
+       mutex_unlock(&gdp_mutex);
 }
 
 static void cleanup_device_parent(struct device *dev)
index 473ff48924015f07daee1c81ebe3d6436727493e..950fff9ce45397024ac5751b452cdd96a6da9907 100644 (file)
@@ -223,9 +223,10 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
 #undef pr_fmt
 #define pr_fmt(fmt) fmt
 
-static void rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
+static int rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
 {
        dev_set_cma_area(dev, rmem->priv);
+       return 0;
 }
 
 static void rmem_cma_device_release(struct reserved_mem *rmem,
index 40bc2f4072cc28ea4138ae36b3b08cb96f2ed158..fb83d4acd400ef0c9e87fddf92f7c7f4da174487 100644 (file)
@@ -361,9 +361,19 @@ static int __pm_genpd_save_device(struct pm_domain_data *pdd,
        struct device *dev = pdd->dev;
        int ret = 0;
 
-       if (gpd_data->need_restore)
+       if (gpd_data->need_restore > 0)
                return 0;
 
+       /*
+        * If the value of the need_restore flag is still unknown at this point,
+        * we trust that pm_genpd_poweroff() has verified that the device is
+        * already runtime PM suspended.
+        */
+       if (gpd_data->need_restore < 0) {
+               gpd_data->need_restore = 1;
+               return 0;
+       }
+
        mutex_unlock(&genpd->lock);
 
        genpd_start_dev(genpd, dev);
@@ -373,7 +383,7 @@ static int __pm_genpd_save_device(struct pm_domain_data *pdd,
        mutex_lock(&genpd->lock);
 
        if (!ret)
-               gpd_data->need_restore = true;
+               gpd_data->need_restore = 1;
 
        return ret;
 }
@@ -389,12 +399,17 @@ static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
 {
        struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
        struct device *dev = pdd->dev;
-       bool need_restore = gpd_data->need_restore;
+       int need_restore = gpd_data->need_restore;
 
-       gpd_data->need_restore = false;
+       gpd_data->need_restore = 0;
        mutex_unlock(&genpd->lock);
 
        genpd_start_dev(genpd, dev);
+
+       /*
+        * Call genpd_restore_dev() for recently added devices too (need_restore
+        * is negative then).
+        */
        if (need_restore)
                genpd_restore_dev(genpd, dev);
 
@@ -603,6 +618,7 @@ static void genpd_power_off_work_fn(struct work_struct *work)
 static int pm_genpd_runtime_suspend(struct device *dev)
 {
        struct generic_pm_domain *genpd;
+       struct generic_pm_domain_data *gpd_data;
        bool (*stop_ok)(struct device *__dev);
        int ret;
 
@@ -628,6 +644,16 @@ static int pm_genpd_runtime_suspend(struct device *dev)
                return 0;
 
        mutex_lock(&genpd->lock);
+
+       /*
+        * If we have an unknown state of the need_restore flag, it means none
+        * of the runtime PM callbacks has been invoked yet. Let's update the
+        * flag to reflect that the current state is active.
+        */
+       gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+       if (gpd_data->need_restore < 0)
+               gpd_data->need_restore = 0;
+
        genpd->in_progress++;
        pm_genpd_poweroff(genpd);
        genpd->in_progress--;
@@ -1437,12 +1463,12 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
        spin_unlock_irq(&dev->power.lock);
 
        if (genpd->attach_dev)
-               genpd->attach_dev(dev);
+               genpd->attach_dev(genpd, dev);
 
        mutex_lock(&gpd_data->lock);
        gpd_data->base.dev = dev;
        list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
-       gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
+       gpd_data->need_restore = -1;
        gpd_data->td.constraint_changed = true;
        gpd_data->td.effective_constraint_ns = -1;
        mutex_unlock(&gpd_data->lock);
@@ -1499,7 +1525,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
        genpd->max_off_time_changed = true;
 
        if (genpd->detach_dev)
-               genpd->detach_dev(dev);
+               genpd->detach_dev(genpd, dev);
 
        spin_lock_irq(&dev->power.lock);
 
@@ -1546,7 +1572,7 @@ void pm_genpd_dev_need_restore(struct device *dev, bool val)
 
        psd = dev_to_psd(dev);
        if (psd && psd->domain_data)
-               to_gpd_data(psd->domain_data)->need_restore = val;
+               to_gpd_data(psd->domain_data)->need_restore = val ? 1 : 0;
 
        spin_unlock_irqrestore(&dev->power.lock, flags);
 }
index 44973196d3fd76d1b3a4b91bc728cf6cf87c2653..9717d5f20139018e8485ae6dcd7fdb79d1d37acf 100644 (file)
@@ -1266,6 +1266,8 @@ int dpm_suspend_late(pm_message_t state)
        }
        mutex_unlock(&dpm_list_mtx);
        async_synchronize_full();
+       if (!error)
+               error = async_error;
        if (error) {
                suspend_stats.failed_suspend_late++;
                dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
index 8a3f51f7b1b9167b1a84788c5a3def482a4c205c..db9d00c36a3e941e466665de2535399e2ee4a076 100644 (file)
@@ -3,12 +3,15 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ)
+       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ)
        select LZO_COMPRESS
        select LZO_DECOMPRESS
        select IRQ_DOMAIN if REGMAP_IRQ
        bool
 
+config REGMAP_AC97
+       tristate
+
 config REGMAP_I2C
        tristate
        depends on I2C
index a7c670b4123a171a3653e79ea0acb6234bc34329..0a533653ef3bec4ea52d4883792eb4f587c7a78c 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_REGMAP) += regmap.o regcache.o
 obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o
 obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
+obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o
 obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
 obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
 obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o
index d9762e41959b07b55fa22c239b9170344dc9b634..0246f44ded747478f3dab0ba0441d4fdff2ae318 100644 (file)
@@ -10,9 +10,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
 
 #include "internal.h"
 
index e210a6d1406a5798b60a49791ae8132cf4a8594a..2d53f6f138e1872dfc03988b0020e976b9e5d86b 100644 (file)
@@ -10,9 +10,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/lzo.h>
+#include <linux/slab.h>
 
 #include "internal.h"
 
index f3e8fe0cc65030a8fea51c00994a343df8220659..d453a2c98ad0a6529170dc5a8f21bab9204255f7 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include <linux/slab.h>
-#include <linux/device.h>
 #include <linux/debugfs.h>
+#include <linux/device.h>
 #include <linux/rbtree.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
 
 #include "internal.h"
 
index f1280dc356d095dee65ccaa47d29652bd97b38dc..f373c35f9e1db239874589464b6375ebfe5d769a 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/device.h>
-#include <trace/events/regmap.h>
 #include <linux/bsearch.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/slab.h>
 #include <linux/sort.h>
+#include <trace/events/regmap.h>
 
 #include "internal.h"
 
@@ -36,6 +36,23 @@ static int regcache_hw_init(struct regmap *map)
        if (!map->num_reg_defaults_raw)
                return -EINVAL;
 
+       /* calculate the size of reg_defaults */
+       for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++)
+               if (!regmap_volatile(map, i * map->reg_stride))
+                       count++;
+
+       /* all registers are volatile, so just bypass */
+       if (!count) {
+               map->cache_bypass = true;
+               return 0;
+       }
+
+       map->num_reg_defaults = count;
+       map->reg_defaults = kmalloc_array(count, sizeof(struct reg_default),
+                                         GFP_KERNEL);
+       if (!map->reg_defaults)
+               return -ENOMEM;
+
        if (!map->reg_defaults_raw) {
                u32 cache_bypass = map->cache_bypass;
                dev_warn(map->dev, "No cache defaults, reading back from HW\n");
@@ -43,40 +60,25 @@ static int regcache_hw_init(struct regmap *map)
                /* Bypass the cache access till data read from HW*/
                map->cache_bypass = 1;
                tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
-               if (!tmp_buf)
-                       return -EINVAL;
+               if (!tmp_buf) {
+                       ret = -ENOMEM;
+                       goto err_free;
+               }
                ret = regmap_raw_read(map, 0, tmp_buf,
                                      map->num_reg_defaults_raw);
                map->cache_bypass = cache_bypass;
-               if (ret < 0) {
-                       kfree(tmp_buf);
-                       return ret;
-               }
+               if (ret < 0)
+                       goto err_cache_free;
+
                map->reg_defaults_raw = tmp_buf;
                map->cache_free = 1;
        }
 
-       /* calculate the size of reg_defaults */
-       for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
-               val = regcache_get_val(map, map->reg_defaults_raw, i);
-               if (regmap_volatile(map, i * map->reg_stride))
-                       continue;
-               count++;
-       }
-
-       map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
-                                     GFP_KERNEL);
-       if (!map->reg_defaults) {
-               ret = -ENOMEM;
-               goto err_free;
-       }
-
        /* fill the reg_defaults */
-       map->num_reg_defaults = count;
        for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
-               val = regcache_get_val(map, map->reg_defaults_raw, i);
                if (regmap_volatile(map, i * map->reg_stride))
                        continue;
+               val = regcache_get_val(map, map->reg_defaults_raw, i);
                map->reg_defaults[j].reg = i * map->reg_stride;
                map->reg_defaults[j].def = val;
                j++;
@@ -84,9 +86,10 @@ static int regcache_hw_init(struct regmap *map)
 
        return 0;
 
+err_cache_free:
+       kfree(tmp_buf);
 err_free:
-       if (map->cache_free)
-               kfree(map->reg_defaults_raw);
+       kfree(map->reg_defaults);
 
        return ret;
 }
@@ -150,6 +153,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
                ret = regcache_hw_init(map);
                if (ret < 0)
                        return ret;
+               if (map->cache_bypass)
+                       return 0;
        }
 
        if (!map->max_register)
diff --git a/drivers/base/regmap/regmap-ac97.c b/drivers/base/regmap/regmap-ac97.c
new file mode 100644 (file)
index 0000000..e4c45d2
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Register map access API - AC'97 support
+ *
+ * Copyright 2013 Linaro Ltd.  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/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <sound/ac97_codec.h>
+
+bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case AC97_RESET:
+       case AC97_POWERDOWN:
+       case AC97_INT_PAGING:
+       case AC97_EXTENDED_ID:
+       case AC97_EXTENDED_STATUS:
+       case AC97_EXTENDED_MID:
+       case AC97_EXTENDED_MSTATUS:
+       case AC97_GPIO_STATUS:
+       case AC97_MISC_AFE:
+       case AC97_VENDOR_ID1:
+       case AC97_VENDOR_ID2:
+       case AC97_CODEC_CLASS_REV:
+       case AC97_PCI_SVID:
+       case AC97_PCI_SID:
+       case AC97_FUNC_SELECT:
+       case AC97_FUNC_INFO:
+       case AC97_SENSE_INFO:
+               return true;
+       default:
+               return false;
+       }
+}
+EXPORT_SYMBOL_GPL(regmap_ac97_default_volatile);
+
+static int regmap_ac97_reg_read(void *context, unsigned int reg,
+       unsigned int *val)
+{
+       struct snd_ac97 *ac97 = context;
+
+       *val = ac97->bus->ops->read(ac97, reg);
+
+       return 0;
+}
+
+static int regmap_ac97_reg_write(void *context, unsigned int reg,
+       unsigned int val)
+{
+       struct snd_ac97 *ac97 = context;
+
+       ac97->bus->ops->write(ac97, reg, val);
+
+       return 0;
+}
+
+static const struct regmap_bus ac97_regmap_bus = {
+               .reg_write = regmap_ac97_reg_write,
+               .reg_read = regmap_ac97_reg_read,
+};
+
+/**
+ * regmap_init_ac97(): Initialise AC'97 register map
+ *
+ * @ac97: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_ac97(struct snd_ac97 *ac97,
+                               const struct regmap_config *config)
+{
+       return regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_ac97);
+
+/**
+ * devm_regmap_init_ac97(): Initialise AC'97 register map
+ *
+ * @ac97: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap.  The regmap will be automatically freed by the
+ * device management code.
+ */
+struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97,
+                                    const struct regmap_config *config)
+{
+       return devm_regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_init_ac97);
+
+MODULE_LICENSE("GPL v2");
index 1e5ac0a796968b61e3de79a4ae2a82f9c2339916..cd9161a8b3a196bcc67634dc86bb84ae5b6190d1 100644 (file)
@@ -275,7 +275,7 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
 static const struct pci_device_id bcma_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
-       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },  /* 0xa8d8 */
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
@@ -285,7 +285,8 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
-       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },  /* 0xA8DB */
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },  /* 0xa8db, BCM43217 (sic!) */
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) },  /* 0xa8dc */
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
index d1656c2f70afa43198066681f6a02ded26eab80b..1000955ce09d870db23979e3950d75e32b75cfc1 100644 (file)
@@ -132,7 +132,7 @@ static bool bcma_is_core_needed_early(u16 core_id)
        return false;
 }
 
-#ifdef CONFIG_OF
+#if defined(CONFIG_OF) && defined(CONFIG_OF_ADDRESS)
 static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
                                                     struct bcma_device *core)
 {
index 2671a3f02f0cfb71831b049c52da9c0f46b20848..8001e812018bbbc0c4360dacd6dc71e8029ab068 100644 (file)
@@ -450,14 +450,10 @@ static int init_driver_queues(struct nullb *nullb)
 
                ret = setup_commands(nq);
                if (ret)
-                       goto err_queue;
+                       return ret;
                nullb->nr_queues++;
        }
-
        return 0;
-err_queue:
-       cleanup_queues(nullb);
-       return ret;
 }
 
 static int null_add_dev(void)
@@ -507,7 +503,9 @@ static int null_add_dev(void)
                        goto out_cleanup_queues;
                }
                blk_queue_make_request(nullb->q, null_queue_bio);
-               init_driver_queues(nullb);
+               rv = init_driver_queues(nullb);
+               if (rv)
+                       goto out_cleanup_blk_queue;
        } else {
                nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
                if (!nullb->q) {
@@ -516,7 +514,9 @@ static int null_add_dev(void)
                }
                blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
                blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
-               init_driver_queues(nullb);
+               rv = init_driver_queues(nullb);
+               if (rv)
+                       goto out_cleanup_blk_queue;
        }
 
        nullb->q->queuedata = nullb;
index a4cd6d691c63569f5e4757d5b32886edd7701815..0b4b2775600eafc2ec1be3afae29b92f5be4345c 100644 (file)
@@ -329,7 +329,7 @@ INQUIRY_EVPD_BIT_MASK) ? 1 : 0)
 (GET_U32_FROM_CDB(cdb, READ_CAP_16_CDB_ALLOC_LENGTH_OFFSET))
 
 #define IS_READ_CAP_16(cdb)                                    \
-((cdb[0] == SERVICE_ACTION_IN && cdb[1] == SAI_READ_CAPACITY_16) ? 1 : 0)
+((cdb[0] == SERVICE_ACTION_IN_16 && cdb[1] == SAI_READ_CAPACITY_16) ? 1 : 0)
 
 /* Request Sense Helper Macros */
 #define GET_REQUEST_SENSE_ALLOC_LENGTH(cdb)                    \
@@ -2947,7 +2947,7 @@ static int nvme_scsi_translate(struct nvme_ns *ns, struct sg_io_hdr *hdr)
        case READ_CAPACITY:
                retcode = nvme_trans_read_capacity(ns, hdr, cmd);
                break;
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                if (IS_READ_CAP_16(cmd))
                        retcode = nvme_trans_read_capacity(ns, hdr, cmd);
                else
index 0a54c588e433751f39084459193a5da7700d34db..27b71a0b72d0959e63fe2ea3efaeaaaa627a4e5d 100644 (file)
@@ -342,7 +342,6 @@ struct rbd_device {
 
        struct list_head        rq_queue;       /* incoming rq queue */
        spinlock_t              lock;           /* queue, flags, open_count */
-       struct workqueue_struct *rq_wq;
        struct work_struct      rq_work;
 
        struct rbd_image_header header;
@@ -402,6 +401,8 @@ static struct kmem_cache    *rbd_segment_name_cache;
 static int rbd_major;
 static DEFINE_IDA(rbd_dev_id_ida);
 
+static struct workqueue_struct *rbd_wq;
+
 /*
  * Default to false for now, as single-major requires >= 0.75 version of
  * userspace rbd utility.
@@ -3452,7 +3453,7 @@ static void rbd_request_fn(struct request_queue *q)
        }
 
        if (queued)
-               queue_work(rbd_dev->rq_wq, &rbd_dev->rq_work);
+               queue_work(rbd_wq, &rbd_dev->rq_work);
 }
 
 /*
@@ -3532,7 +3533,7 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
        page_count = (u32) calc_pages_for(offset, length);
        pages = ceph_alloc_page_vector(page_count, GFP_KERNEL);
        if (IS_ERR(pages))
-               ret = PTR_ERR(pages);
+               return PTR_ERR(pages);
 
        ret = -ENOMEM;
        obj_request = rbd_obj_request_create(object_name, offset, length,
@@ -5242,16 +5243,9 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
        set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
        set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only);
 
-       rbd_dev->rq_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0,
-                                        rbd_dev->disk->disk_name);
-       if (!rbd_dev->rq_wq) {
-               ret = -ENOMEM;
-               goto err_out_mapping;
-       }
-
        ret = rbd_bus_add_dev(rbd_dev);
        if (ret)
-               goto err_out_workqueue;
+               goto err_out_mapping;
 
        /* Everything's ready.  Announce the disk to the world. */
 
@@ -5263,9 +5257,6 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
 
        return ret;
 
-err_out_workqueue:
-       destroy_workqueue(rbd_dev->rq_wq);
-       rbd_dev->rq_wq = NULL;
 err_out_mapping:
        rbd_dev_mapping_clear(rbd_dev);
 err_out_disk:
@@ -5512,7 +5503,6 @@ static void rbd_dev_device_release(struct device *dev)
 {
        struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
-       destroy_workqueue(rbd_dev->rq_wq);
        rbd_free_disk(rbd_dev);
        clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
        rbd_dev_mapping_clear(rbd_dev);
@@ -5716,11 +5706,21 @@ static int __init rbd_init(void)
        if (rc)
                return rc;
 
+       /*
+        * The number of active work items is limited by the number of
+        * rbd devices, so leave @max_active at default.
+        */
+       rbd_wq = alloc_workqueue(RBD_DRV_NAME, WQ_MEM_RECLAIM, 0);
+       if (!rbd_wq) {
+               rc = -ENOMEM;
+               goto err_out_slab;
+       }
+
        if (single_major) {
                rbd_major = register_blkdev(0, RBD_DRV_NAME);
                if (rbd_major < 0) {
                        rc = rbd_major;
-                       goto err_out_slab;
+                       goto err_out_wq;
                }
        }
 
@@ -5738,6 +5738,8 @@ static int __init rbd_init(void)
 err_out_blkdev:
        if (single_major)
                unregister_blkdev(rbd_major, RBD_DRV_NAME);
+err_out_wq:
+       destroy_workqueue(rbd_wq);
 err_out_slab:
        rbd_slab_exit();
        return rc;
@@ -5749,6 +5751,7 @@ static void __exit rbd_exit(void)
        rbd_sysfs_cleanup();
        if (single_major)
                unregister_blkdev(rbd_major, RBD_DRV_NAME);
+       destroy_workqueue(rbd_wq);
        rbd_slab_exit();
 }
 
index 756b8ec00f16d73851bca0c8d5ec754752c58710..0ebadf93b6c5610cb0d7e46edcbdfa040719c199 100644 (file)
@@ -69,8 +69,6 @@ struct vdc_port {
        u8                      vdisk_mtype;
 
        char                    disk_name[32];
-
-       struct vio_disk_vtoc    label;
 };
 
 static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
@@ -710,13 +708,6 @@ static int probe_disk(struct vdc_port *port)
        if (comp.err)
                return comp.err;
 
-       err = generic_request(port, VD_OP_GET_VTOC,
-                             &port->label, sizeof(port->label));
-       if (err < 0) {
-               printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err);
-               return err;
-       }
-
        if (vdc_version_supported(port, 1, 1)) {
                /* vdisk_size should be set during the handshake, if it wasn't
                 * then the underlying disk is reserved by another system
index 0e63e8aa8279a7993344f15d0d2f48b2536b497a..3920ee45aa5942dd816a775180eeb16f662e804c 100644 (file)
@@ -99,11 +99,12 @@ static ssize_t mem_used_total_show(struct device *dev,
 {
        u64 val = 0;
        struct zram *zram = dev_to_zram(dev);
-       struct zram_meta *meta = zram->meta;
 
        down_read(&zram->init_lock);
-       if (init_done(zram))
+       if (init_done(zram)) {
+               struct zram_meta *meta = zram->meta;
                val = zs_get_total_pages(meta->mem_pool);
+       }
        up_read(&zram->init_lock);
 
        return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT);
@@ -173,16 +174,17 @@ static ssize_t mem_used_max_store(struct device *dev,
        int err;
        unsigned long val;
        struct zram *zram = dev_to_zram(dev);
-       struct zram_meta *meta = zram->meta;
 
        err = kstrtoul(buf, 10, &val);
        if (err || val != 0)
                return -EINVAL;
 
        down_read(&zram->init_lock);
-       if (init_done(zram))
+       if (init_done(zram)) {
+               struct zram_meta *meta = zram->meta;
                atomic_long_set(&zram->stats.max_used_pages,
                                zs_get_total_pages(meta->mem_pool));
+       }
        up_read(&zram->init_lock);
 
        return len;
@@ -558,7 +560,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
        }
 
        if (page_zero_filled(uncmem)) {
-               kunmap_atomic(user_mem);
+               if (user_mem)
+                       kunmap_atomic(user_mem);
                /* Free memory associated with this sector now. */
                bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value);
                zram_free_page(zram, index);
index 603eb1be4f6aa6bc79e0d3b9aeb31d92356018ff..b99729e368608bda800d03f2e2f339d86f2e4d6c 100644 (file)
@@ -6,7 +6,7 @@ menu "Bus devices"
 
 config BRCMSTB_GISB_ARB
        bool "Broadcom STB GISB bus arbiter"
-       depends on ARM
+       depends on ARM || MIPS
        help
          Driver for the Broadcom Set Top Box System-on-a-chip internal bus
          arbiter. This driver provides timeout and target abort error handling
index 7af78df241f2199d20bd692599027493a30dde6b..860da40b78effb96b16a779f84f9ea21d05aba95 100644 (file)
 
 #include <linux/arm-cci.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/perf_event.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
 #include <asm/cacheflush.h>
-#include <asm/irq_regs.h>
-#include <asm/pmu.h>
 #include <asm/smp_plat.h>
 
 #define DRIVER_NAME            "CCI-400"
@@ -98,6 +98,8 @@ static unsigned long cci_ctrl_phys;
 
 #define CCI_PMU_CNTR_BASE(idx) ((idx) * SZ_4K)
 
+#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
@@ -170,18 +172,29 @@ static char *const pmu_names[] = {
        [CCI_REV_R1] = "CCI_400_r1",
 };
 
-struct cci_pmu_drv_data {
+struct cci_pmu_hw_events {
+       struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
+       unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
+       raw_spinlock_t pmu_lock;
+};
+
+struct cci_pmu {
        void __iomem *base;
-       struct arm_pmu *cci_pmu;
+       struct pmu pmu;
        int nr_irqs;
        int irqs[CCI_PMU_MAX_HW_EVENTS];
        unsigned long active_irqs;
-       struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
-       unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
        struct pmu_port_event_ranges *port_ranges;
-       struct pmu_hw_events hw_events;
+       struct cci_pmu_hw_events hw_events;
+       struct platform_device *plat_device;
+       int num_events;
+       atomic_t active_events;
+       struct mutex reserve_mutex;
+       cpumask_t cpus;
 };
-static struct cci_pmu_drv_data *pmu;
+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)
 {
@@ -252,7 +265,7 @@ static int pmu_validate_hw_event(u8 hw_event)
        return -ENOENT;
 }
 
-static int pmu_is_valid_counter(struct arm_pmu *cci_pmu, int idx)
+static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
 {
        return CCI_PMU_CYCLE_CNTR_IDX <= idx &&
                idx <= CCI_PMU_CNTR_LAST(cci_pmu);
@@ -293,14 +306,9 @@ static u32 pmu_get_max_counters(void)
        return n_cnts + 1;
 }
 
-static struct pmu_hw_events *pmu_get_hw_events(void)
-{
-       return &pmu->hw_events;
-}
-
-static int pmu_get_event_idx(struct pmu_hw_events *hw, struct perf_event *event)
+static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *event)
 {
-       struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+       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;
        int idx;
@@ -336,7 +344,7 @@ static int pmu_map_event(struct perf_event *event)
        return mapping;
 }
 
-static int pmu_request_irq(struct arm_pmu *cci_pmu, irq_handler_t handler)
+static int pmu_request_irq(struct cci_pmu *cci_pmu, irq_handler_t handler)
 {
        int i;
        struct platform_device *pmu_device = cci_pmu->plat_device;
@@ -371,17 +379,91 @@ static int pmu_request_irq(struct arm_pmu *cci_pmu, irq_handler_t handler)
        return 0;
 }
 
+static void pmu_free_irq(struct cci_pmu *cci_pmu)
+{
+       int i;
+
+       for (i = 0; i < pmu->nr_irqs; i++) {
+               if (!test_and_clear_bit(i, &pmu->active_irqs))
+                       continue;
+
+               free_irq(pmu->irqs[i], cci_pmu);
+       }
+}
+
+static u32 pmu_read_counter(struct perf_event *event)
+{
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       struct hw_perf_event *hw_counter = &event->hw;
+       int idx = hw_counter->idx;
+       u32 value;
+
+       if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
+               dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+               return 0;
+       }
+       value = pmu_read_register(idx, CCI_PMU_CNTR);
+
+       return value;
+}
+
+static void pmu_write_counter(struct perf_event *event, u32 value)
+{
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       struct hw_perf_event *hw_counter = &event->hw;
+       int idx = hw_counter->idx;
+
+       if (unlikely(!pmu_is_valid_counter(cci_pmu, idx)))
+               dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+       else
+               pmu_write_register(value, idx, CCI_PMU_CNTR);
+}
+
+static u64 pmu_event_update(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 delta, prev_raw_count, new_raw_count;
+
+       do {
+               prev_raw_count = local64_read(&hwc->prev_count);
+               new_raw_count = pmu_read_counter(event);
+       } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                new_raw_count) != prev_raw_count);
+
+       delta = (new_raw_count - prev_raw_count) & CCI_PMU_CNTR_MASK;
+
+       local64_add(delta, &event->count);
+
+       return new_raw_count;
+}
+
+static void pmu_read(struct perf_event *event)
+{
+       pmu_event_update(event);
+}
+
+void pmu_event_set_period(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       /*
+        * The CCI PMU counters have a period of 2^32. To account for the
+        * possiblity of extreme interrupt latency we program for a period of
+        * half that. Hopefully we can handle the interrupt before another 2^31
+        * events occur and the counter overtakes its previous value.
+        */
+       u64 val = 1ULL << 31;
+       local64_set(&hwc->prev_count, val);
+       pmu_write_counter(event, val);
+}
+
 static irqreturn_t pmu_handle_irq(int irq_num, void *dev)
 {
        unsigned long flags;
-       struct arm_pmu *cci_pmu = (struct arm_pmu *)dev;
-       struct pmu_hw_events *events = cci_pmu->get_hw_events();
-       struct perf_sample_data data;
-       struct pt_regs *regs;
+       struct cci_pmu *cci_pmu = dev;
+       struct cci_pmu_hw_events *events = &pmu->hw_events;
        int idx, handled = IRQ_NONE;
 
        raw_spin_lock_irqsave(&events->pmu_lock, flags);
-       regs = get_irq_regs();
        /*
         * Iterate over counters and update the corresponding perf events.
         * This should work regardless of whether we have per-counter overflow
@@ -403,154 +485,407 @@ static irqreturn_t pmu_handle_irq(int irq_num, void *dev)
 
                pmu_write_register(CCI_PMU_OVRFLW_FLAG, idx, CCI_PMU_OVRFLW);
 
+               pmu_event_update(event);
+               pmu_event_set_period(event);
                handled = IRQ_HANDLED;
-
-               armpmu_event_update(event);
-               perf_sample_data_init(&data, 0, hw_counter->last_period);
-               if (!armpmu_event_set_period(event))
-                       continue;
-
-               if (perf_event_overflow(event, &data, regs))
-                       cci_pmu->disable(event);
        }
        raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
 
        return IRQ_RETVAL(handled);
 }
 
-static void pmu_free_irq(struct arm_pmu *cci_pmu)
+static int cci_pmu_get_hw(struct cci_pmu *cci_pmu)
 {
-       int i;
+       int ret = pmu_request_irq(cci_pmu, pmu_handle_irq);
+       if (ret) {
+               pmu_free_irq(cci_pmu);
+               return ret;
+       }
+       return 0;
+}
 
-       for (i = 0; i < pmu->nr_irqs; i++) {
-               if (!test_and_clear_bit(i, &pmu->active_irqs))
-                       continue;
+static void cci_pmu_put_hw(struct cci_pmu *cci_pmu)
+{
+       pmu_free_irq(cci_pmu);
+}
 
-               free_irq(pmu->irqs[i], cci_pmu);
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       atomic_t *active_events = &cci_pmu->active_events;
+       struct mutex *reserve_mutex = &cci_pmu->reserve_mutex;
+
+       if (atomic_dec_and_mutex_lock(active_events, reserve_mutex)) {
+               cci_pmu_put_hw(cci_pmu);
+               mutex_unlock(reserve_mutex);
        }
 }
 
-static void pmu_enable_event(struct perf_event *event)
+static void cci_pmu_enable(struct pmu *pmu)
 {
+       struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
+       struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
+       int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_events);
        unsigned long flags;
-       struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
-       struct pmu_hw_events *events = cci_pmu->get_hw_events();
-       struct hw_perf_event *hw_counter = &event->hw;
-       int idx = hw_counter->idx;
+       u32 val;
+
+       if (!enabled)
+               return;
+
+       raw_spin_lock_irqsave(&hw_events->pmu_lock, flags);
+
+       /* Enable all the PMU counters. */
+       val = readl_relaxed(cci_ctrl_base + CCI_PMCR) | CCI_PMCR_CEN;
+       writel(val, cci_ctrl_base + CCI_PMCR);
+       raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags);
+
+}
+
+static void cci_pmu_disable(struct pmu *pmu)
+{
+       struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
+       struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
+       unsigned long flags;
+       u32 val;
+
+       raw_spin_lock_irqsave(&hw_events->pmu_lock, flags);
+
+       /* Disable all the PMU counters. */
+       val = readl_relaxed(cci_ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN;
+       writel(val, cci_ctrl_base + CCI_PMCR);
+       raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags);
+}
+
+static void cci_pmu_start(struct perf_event *event, int pmu_flags)
+{
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+       unsigned long flags;
+
+       /*
+        * To handle interrupt latency, we always reprogram the period
+        * regardlesss of PERF_EF_RELOAD.
+        */
+       if (pmu_flags & PERF_EF_RELOAD)
+               WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+       hwc->state = 0;
 
        if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
                dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
                return;
        }
 
-       raw_spin_lock_irqsave(&events->pmu_lock, flags);
+       raw_spin_lock_irqsave(&hw_events->pmu_lock, flags);
 
        /* Configure the event to count, unless you are counting cycles */
        if (idx != CCI_PMU_CYCLE_CNTR_IDX)
-               pmu_set_event(idx, hw_counter->config_base);
+               pmu_set_event(idx, hwc->config_base);
 
+       pmu_event_set_period(event);
        pmu_enable_counter(idx);
 
-       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+       raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags);
 }
 
-static void pmu_disable_event(struct perf_event *event)
+static void cci_pmu_stop(struct perf_event *event, int pmu_flags)
 {
-       struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
-       struct hw_perf_event *hw_counter = &event->hw;
-       int idx = hw_counter->idx;
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
+
+       if (hwc->state & PERF_HES_STOPPED)
+               return;
 
        if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
                dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
                return;
        }
 
+       /*
+        * We always reprogram the counter, so ignore PERF_EF_UPDATE. See
+        * cci_pmu_start()
+        */
        pmu_disable_counter(idx);
+       pmu_event_update(event);
+       hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
 }
 
-static void pmu_start(struct arm_pmu *cci_pmu)
+static int cci_pmu_add(struct perf_event *event, int flags)
 {
-       u32 val;
-       unsigned long flags;
-       struct pmu_hw_events *events = cci_pmu->get_hw_events();
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
+       struct hw_perf_event *hwc = &event->hw;
+       int idx;
+       int err = 0;
 
-       raw_spin_lock_irqsave(&events->pmu_lock, flags);
+       perf_pmu_disable(event->pmu);
 
-       /* Enable all the PMU counters. */
-       val = readl_relaxed(cci_ctrl_base + CCI_PMCR) | CCI_PMCR_CEN;
-       writel(val, cci_ctrl_base + CCI_PMCR);
+       /* If we don't have a space for the counter then finish early. */
+       idx = pmu_get_event_idx(hw_events, event);
+       if (idx < 0) {
+               err = idx;
+               goto out;
+       }
 
-       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+       event->hw.idx = idx;
+       hw_events->events[idx] = event;
+
+       hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+       if (flags & PERF_EF_START)
+               cci_pmu_start(event, PERF_EF_RELOAD);
+
+       /* Propagate our changes to the userspace mapping. */
+       perf_event_update_userpage(event);
+
+out:
+       perf_pmu_enable(event->pmu);
+       return err;
 }
 
-static void pmu_stop(struct arm_pmu *cci_pmu)
+static void cci_pmu_del(struct perf_event *event, int flags)
 {
-       u32 val;
-       unsigned long flags;
-       struct pmu_hw_events *events = cci_pmu->get_hw_events();
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
+       struct hw_perf_event *hwc = &event->hw;
+       int idx = hwc->idx;
 
-       raw_spin_lock_irqsave(&events->pmu_lock, flags);
+       cci_pmu_stop(event, PERF_EF_UPDATE);
+       hw_events->events[idx] = NULL;
+       clear_bit(idx, hw_events->used_mask);
 
-       /* Disable all the PMU counters. */
-       val = readl_relaxed(cci_ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN;
-       writel(val, cci_ctrl_base + CCI_PMCR);
+       perf_event_update_userpage(event);
+}
 
-       raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+static int
+validate_event(struct cci_pmu_hw_events *hw_events,
+              struct perf_event *event)
+{
+       if (is_software_event(event))
+               return 1;
+
+       if (event->state < PERF_EVENT_STATE_OFF)
+               return 1;
+
+       if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
+               return 1;
+
+       return pmu_get_event_idx(hw_events, event) >= 0;
 }
 
-static u32 pmu_read_counter(struct perf_event *event)
+static int
+validate_group(struct perf_event *event)
 {
-       struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
-       struct hw_perf_event *hw_counter = &event->hw;
-       int idx = hw_counter->idx;
-       u32 value;
+       struct perf_event *sibling, *leader = event->group_leader;
+       struct cci_pmu_hw_events fake_pmu = {
+               /*
+                * Initialise the fake PMU. We only need to populate the
+                * used_mask for the purposes of validation.
+                */
+               .used_mask = CPU_BITS_NONE,
+       };
 
-       if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
-               dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
-               return 0;
+       if (!validate_event(&fake_pmu, leader))
+               return -EINVAL;
+
+       list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+               if (!validate_event(&fake_pmu, sibling))
+                       return -EINVAL;
        }
-       value = pmu_read_register(idx, CCI_PMU_CNTR);
 
-       return value;
+       if (!validate_event(&fake_pmu, event))
+               return -EINVAL;
+
+       return 0;
 }
 
-static void pmu_write_counter(struct perf_event *event, u32 value)
+static int
+__hw_perf_event_init(struct perf_event *event)
 {
-       struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
-       struct hw_perf_event *hw_counter = &event->hw;
-       int idx = hw_counter->idx;
+       struct hw_perf_event *hwc = &event->hw;
+       int mapping;
 
-       if (unlikely(!pmu_is_valid_counter(cci_pmu, idx)))
-               dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
-       else
-               pmu_write_register(value, idx, CCI_PMU_CNTR);
+       mapping = pmu_map_event(event);
+
+       if (mapping < 0) {
+               pr_debug("event %x:%llx not supported\n", event->attr.type,
+                        event->attr.config);
+               return mapping;
+       }
+
+       /*
+        * We don't assign an index until we actually place the event onto
+        * hardware. Use -1 to signify that we haven't decided where to put it
+        * yet.
+        */
+       hwc->idx                = -1;
+       hwc->config_base        = 0;
+       hwc->config             = 0;
+       hwc->event_base         = 0;
+
+       /*
+        * Store the event encoding into the config_base field.
+        */
+       hwc->config_base            |= (unsigned long)mapping;
+
+       /*
+        * Limit the sample_period to half of the counter width. That way, the
+        * new counter value is far less likely to overtake the previous one
+        * unless you have some serious IRQ latency issues.
+        */
+       hwc->sample_period  = CCI_PMU_CNTR_MASK >> 1;
+       hwc->last_period    = hwc->sample_period;
+       local64_set(&hwc->period_left, hwc->sample_period);
+
+       if (event->group_leader != event) {
+               if (validate_group(event) != 0)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int cci_pmu_event_init(struct perf_event *event)
+{
+       struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
+       atomic_t *active_events = &cci_pmu->active_events;
+       int err = 0;
+       int cpu;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       /* Shared by all CPUs, no meaningful state to sample */
+       if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+               return -EOPNOTSUPP;
+
+       /* We have no filtering of any kind */
+       if (event->attr.exclude_user    ||
+           event->attr.exclude_kernel  ||
+           event->attr.exclude_hv      ||
+           event->attr.exclude_idle    ||
+           event->attr.exclude_host    ||
+           event->attr.exclude_guest)
+               return -EINVAL;
+
+       /*
+        * Following the example set by other "uncore" PMUs, we accept any CPU
+        * and rewrite its affinity dynamically rather than having perf core
+        * handle cpu == -1 and pid == -1 for this case.
+        *
+        * The perf core will pin online CPUs for the duration of this call and
+        * the event being installed into its context, so the PMU's CPU can't
+        * change under our feet.
+        */
+       cpu = cpumask_first(&cci_pmu->cpus);
+       if (event->cpu < 0 || cpu < 0)
+               return -EINVAL;
+       event->cpu = cpu;
+
+       event->destroy = hw_perf_event_destroy;
+       if (!atomic_inc_not_zero(active_events)) {
+               mutex_lock(&cci_pmu->reserve_mutex);
+               if (atomic_read(active_events) == 0)
+                       err = cci_pmu_get_hw(cci_pmu);
+               if (!err)
+                       atomic_inc(active_events);
+               mutex_unlock(&cci_pmu->reserve_mutex);
+       }
+       if (err)
+               return err;
+
+       err = __hw_perf_event_init(event);
+       if (err)
+               hw_perf_event_destroy(event);
+
+       return err;
 }
 
-static int cci_pmu_init(struct arm_pmu *cci_pmu, struct platform_device *pdev)
+static ssize_t pmu_attr_cpumask_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
 {
-       *cci_pmu = (struct arm_pmu){
-               .name             = pmu_names[probe_cci_revision()],
-               .max_period       = (1LLU << 32) - 1,
-               .get_hw_events    = pmu_get_hw_events,
-               .get_event_idx    = pmu_get_event_idx,
-               .map_event        = pmu_map_event,
-               .request_irq      = pmu_request_irq,
-               .handle_irq       = pmu_handle_irq,
-               .free_irq         = pmu_free_irq,
-               .enable           = pmu_enable_event,
-               .disable          = pmu_disable_event,
-               .start            = pmu_start,
-               .stop             = pmu_stop,
-               .read_counter     = pmu_read_counter,
-               .write_counter    = pmu_write_counter,
+       int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &pmu->cpus);
+
+       buf[n++] = '\n';
+       buf[n] = '\0';
+       return n;
+}
+
+static DEVICE_ATTR(cpumask, S_IRUGO, pmu_attr_cpumask_show, NULL);
+
+static struct attribute *pmu_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group pmu_attr_group = {
+       .attrs = pmu_attrs,
+};
+
+static const struct attribute_group *pmu_attr_groups[] = {
+       &pmu_attr_group,
+       NULL
+};
+
+static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
+{
+       char *name = pmu_names[probe_cci_revision()];
+       cci_pmu->pmu = (struct pmu) {
+               .name           = pmu_names[probe_cci_revision()],
+               .task_ctx_nr    = perf_invalid_context,
+               .pmu_enable     = cci_pmu_enable,
+               .pmu_disable    = cci_pmu_disable,
+               .event_init     = cci_pmu_event_init,
+               .add            = cci_pmu_add,
+               .del            = cci_pmu_del,
+               .start          = cci_pmu_start,
+               .stop           = cci_pmu_stop,
+               .read           = pmu_read,
+               .attr_groups    = pmu_attr_groups,
        };
 
        cci_pmu->plat_device = pdev;
        cci_pmu->num_events = pmu_get_max_counters();
 
-       return armpmu_register(cci_pmu, -1);
+       return perf_pmu_register(&cci_pmu->pmu, name, -1);
 }
 
+static int cci_pmu_cpu_notifier(struct notifier_block *self,
+                               unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+       unsigned int target;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DOWN_PREPARE:
+               if (!cpumask_test_and_clear_cpu(cpu, &pmu->cpus))
+                       break;
+               target = cpumask_any_but(cpu_online_mask, cpu);
+               if (target < 0) // UP, last CPU
+                       break;
+               /*
+                * TODO: migrate context once core races on event->ctx have
+                * been fixed.
+                */
+               cpumask_set_cpu(target, &pmu->cpus);
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block cci_pmu_cpu_nb = {
+       .notifier_call  = cci_pmu_cpu_notifier,
+       /*
+        * to migrate uncore events, our notifier should be executed
+        * before perf core's notifier.
+        */
+       .priority       = CPU_PRI_PERF + 1,
+};
+
 static const struct of_device_id arm_cci_pmu_matches[] = {
        {
                .compatible = "arm,cci-400-pmu",
@@ -604,15 +939,16 @@ static int cci_pmu_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       pmu->cci_pmu = devm_kzalloc(&pdev->dev, sizeof(*(pmu->cci_pmu)), GFP_KERNEL);
-       if (!pmu->cci_pmu)
-               return -ENOMEM;
-
-       pmu->hw_events.events = pmu->events;
-       pmu->hw_events.used_mask = pmu->used_mask;
        raw_spin_lock_init(&pmu->hw_events.pmu_lock);
+       mutex_init(&pmu->reserve_mutex);
+       atomic_set(&pmu->active_events, 0);
+       cpumask_set_cpu(smp_processor_id(), &pmu->cpus);
+
+       ret = register_cpu_notifier(&cci_pmu_cpu_nb);
+       if (ret)
+               return ret;
 
-       ret = cci_pmu_init(pmu->cci_pmu, pdev);
+       ret = cci_pmu_init(pmu, pdev);
        if (ret)
                return ret;
 
index f2cd6a2d40b4e5fa1c40b7d1da99d204fafb080d..46de8dc39eb4c47b5f9046c7b750224b2c2bdfa7 100644 (file)
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/bitops.h>
+#include <linux/pm.h>
 
+#ifdef CONFIG_ARM
 #include <asm/bug.h>
 #include <asm/signal.h>
+#endif
 
-#define ARB_TIMER                      0x008
-#define ARB_ERR_CAP_CLR                        0x7e4
 #define  ARB_ERR_CAP_CLEAR             (1 << 0)
-#define ARB_ERR_CAP_HI_ADDR            0x7e8
-#define ARB_ERR_CAP_ADDR               0x7ec
-#define ARB_ERR_CAP_DATA               0x7f0
-#define ARB_ERR_CAP_STATUS             0x7f4
 #define  ARB_ERR_CAP_STATUS_TIMEOUT    (1 << 12)
 #define  ARB_ERR_CAP_STATUS_TEA                (1 << 11)
 #define  ARB_ERR_CAP_STATUS_BS_SHIFT   (1 << 2)
 #define  ARB_ERR_CAP_STATUS_BS_MASK    0x3c
 #define  ARB_ERR_CAP_STATUS_WRITE      (1 << 1)
 #define  ARB_ERR_CAP_STATUS_VALID      (1 << 0)
-#define ARB_ERR_CAP_MASTER             0x7f8
+
+enum {
+       ARB_TIMER,
+       ARB_ERR_CAP_CLR,
+       ARB_ERR_CAP_HI_ADDR,
+       ARB_ERR_CAP_ADDR,
+       ARB_ERR_CAP_DATA,
+       ARB_ERR_CAP_STATUS,
+       ARB_ERR_CAP_MASTER,
+};
+
+static const int gisb_offsets_bcm7038[] = {
+       [ARB_TIMER]             = 0x00c,
+       [ARB_ERR_CAP_CLR]       = 0x0c4,
+       [ARB_ERR_CAP_HI_ADDR]   = -1,
+       [ARB_ERR_CAP_ADDR]      = 0x0c8,
+       [ARB_ERR_CAP_DATA]      = 0x0cc,
+       [ARB_ERR_CAP_STATUS]    = 0x0d0,
+       [ARB_ERR_CAP_MASTER]    = -1,
+};
+
+static const int gisb_offsets_bcm7400[] = {
+       [ARB_TIMER]             = 0x00c,
+       [ARB_ERR_CAP_CLR]       = 0x0c8,
+       [ARB_ERR_CAP_HI_ADDR]   = -1,
+       [ARB_ERR_CAP_ADDR]      = 0x0cc,
+       [ARB_ERR_CAP_DATA]      = 0x0d0,
+       [ARB_ERR_CAP_STATUS]    = 0x0d4,
+       [ARB_ERR_CAP_MASTER]    = 0x0d8,
+};
+
+static const int gisb_offsets_bcm7435[] = {
+       [ARB_TIMER]             = 0x00c,
+       [ARB_ERR_CAP_CLR]       = 0x168,
+       [ARB_ERR_CAP_HI_ADDR]   = -1,
+       [ARB_ERR_CAP_ADDR]      = 0x16c,
+       [ARB_ERR_CAP_DATA]      = 0x170,
+       [ARB_ERR_CAP_STATUS]    = 0x174,
+       [ARB_ERR_CAP_MASTER]    = 0x178,
+};
+
+static const int gisb_offsets_bcm7445[] = {
+       [ARB_TIMER]             = 0x008,
+       [ARB_ERR_CAP_CLR]       = 0x7e4,
+       [ARB_ERR_CAP_HI_ADDR]   = 0x7e8,
+       [ARB_ERR_CAP_ADDR]      = 0x7ec,
+       [ARB_ERR_CAP_DATA]      = 0x7f0,
+       [ARB_ERR_CAP_STATUS]    = 0x7f4,
+       [ARB_ERR_CAP_MASTER]    = 0x7f8,
+};
 
 struct brcmstb_gisb_arb_device {
        void __iomem    *base;
+       const int       *gisb_offsets;
        struct mutex    lock;
        struct list_head next;
        u32 valid_mask;
        const char *master_names[sizeof(u32) * BITS_PER_BYTE];
+       u32 saved_timeout;
 };
 
 static LIST_HEAD(brcmstb_gisb_arb_device_list);
 
+static u32 gisb_read(struct brcmstb_gisb_arb_device *gdev, int reg)
+{
+       int offset = gdev->gisb_offsets[reg];
+
+       /* return 1 if the hardware doesn't have ARB_ERR_CAP_MASTER */
+       if (offset == -1)
+               return 1;
+
+       return ioread32(gdev->base + offset);
+}
+
+static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
+{
+       int offset = gdev->gisb_offsets[reg];
+
+       if (offset == -1)
+               return;
+       iowrite32(val, gdev->base + reg);
+}
+
 static ssize_t gisb_arb_get_timeout(struct device *dev,
                                    struct device_attribute *attr,
                                    char *buf)
@@ -61,7 +129,7 @@ static ssize_t gisb_arb_get_timeout(struct device *dev,
        u32 timeout;
 
        mutex_lock(&gdev->lock);
-       timeout = ioread32(gdev->base + ARB_TIMER);
+       timeout = gisb_read(gdev, ARB_TIMER);
        mutex_unlock(&gdev->lock);
 
        return sprintf(buf, "%d", timeout);
@@ -83,7 +151,7 @@ static ssize_t gisb_arb_set_timeout(struct device *dev,
                return -EINVAL;
 
        mutex_lock(&gdev->lock);
-       iowrite32(val, gdev->base + ARB_TIMER);
+       gisb_write(gdev, val, ARB_TIMER);
        mutex_unlock(&gdev->lock);
 
        return count;
@@ -110,18 +178,18 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev,
        const char *m_name;
        char m_fmt[11];
 
-       cap_status = ioread32(gdev->base + ARB_ERR_CAP_STATUS);
+       cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
 
        /* Invalid captured address, bail out */
        if (!(cap_status & ARB_ERR_CAP_STATUS_VALID))
                return 1;
 
        /* Read the address and master */
-       arb_addr = ioread32(gdev->base + ARB_ERR_CAP_ADDR) & 0xffffffff;
+       arb_addr = gisb_read(gdev, ARB_ERR_CAP_ADDR) & 0xffffffff;
 #if (IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT))
-       arb_addr |= (u64)ioread32(gdev->base + ARB_ERR_CAP_HI_ADDR) << 32;
+       arb_addr |= (u64)gisb_read(gdev, ARB_ERR_CAP_HI_ADDR) << 32;
 #endif
-       master = ioread32(gdev->base + ARB_ERR_CAP_MASTER);
+       master = gisb_read(gdev, ARB_ERR_CAP_MASTER);
 
        m_name = brcmstb_gisb_master_to_str(gdev, master);
        if (!m_name) {
@@ -136,11 +204,12 @@ static int brcmstb_gisb_arb_decode_addr(struct brcmstb_gisb_arb_device *gdev,
                m_name);
 
        /* clear the GISB error */
-       iowrite32(ARB_ERR_CAP_CLEAR, gdev->base + ARB_ERR_CAP_CLR);
+       gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
 
        return 0;
 }
 
+#ifdef CONFIG_ARM
 static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
                                     struct pt_regs *regs)
 {
@@ -159,12 +228,7 @@ static int brcmstb_bus_error_handler(unsigned long addr, unsigned int fsr,
 
        return ret;
 }
-
-void __init brcmstb_hook_fault_code(void)
-{
-       hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
-                       "imprecise external abort");
-}
+#endif
 
 static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
 {
@@ -192,10 +256,20 @@ static struct attribute_group gisb_arb_sysfs_attr_group = {
        .attrs = gisb_arb_sysfs_attrs,
 };
 
-static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
+static const struct of_device_id brcmstb_gisb_arb_of_match[] = {
+       { .compatible = "brcm,gisb-arb",         .data = gisb_offsets_bcm7445 },
+       { .compatible = "brcm,bcm7445-gisb-arb", .data = gisb_offsets_bcm7445 },
+       { .compatible = "brcm,bcm7435-gisb-arb", .data = gisb_offsets_bcm7435 },
+       { .compatible = "brcm,bcm7400-gisb-arb", .data = gisb_offsets_bcm7400 },
+       { .compatible = "brcm,bcm7038-gisb-arb", .data = gisb_offsets_bcm7038 },
+       { },
+};
+
+static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
 {
        struct device_node *dn = pdev->dev.of_node;
        struct brcmstb_gisb_arb_device *gdev;
+       const struct of_device_id *of_id;
        struct resource *r;
        int err, timeout_irq, tea_irq;
        unsigned int num_masters, j = 0;
@@ -216,6 +290,13 @@ static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
        if (IS_ERR(gdev->base))
                return PTR_ERR(gdev->base);
 
+       of_id = of_match_node(brcmstb_gisb_arb_of_match, dn);
+       if (!of_id) {
+               pr_err("failed to look up compatible string\n");
+               return -EINVAL;
+       }
+       gdev->gisb_offsets = of_id->data;
+
        err = devm_request_irq(&pdev->dev, timeout_irq,
                                brcmstb_gisb_timeout_handler, 0, pdev->name,
                                gdev);
@@ -261,29 +342,63 @@ static int brcmstb_gisb_arb_probe(struct platform_device *pdev)
 
        list_add_tail(&gdev->next, &brcmstb_gisb_arb_device_list);
 
+#ifdef CONFIG_ARM
+       hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
+                       "imprecise external abort");
+#endif
+
        dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
                        gdev->base, timeout_irq, tea_irq);
 
        return 0;
 }
 
-static const struct of_device_id brcmstb_gisb_arb_of_match[] = {
-       { .compatible = "brcm,gisb-arb" },
-       { },
+#ifdef CONFIG_PM_SLEEP
+static int brcmstb_gisb_arb_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
+
+       gdev->saved_timeout = gisb_read(gdev, ARB_TIMER);
+
+       return 0;
+}
+
+/* Make sure we provide the same timeout value that was configured before, and
+ * do this before the GISB timeout interrupt handler has any chance to run.
+ */
+static int brcmstb_gisb_arb_resume_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
+
+       gisb_write(gdev, gdev->saved_timeout, ARB_TIMER);
+
+       return 0;
+}
+#else
+#define brcmstb_gisb_arb_suspend       NULL
+#define brcmstb_gisb_arb_resume_noirq  NULL
+#endif
+
+static const struct dev_pm_ops brcmstb_gisb_arb_pm_ops = {
+       .suspend        = brcmstb_gisb_arb_suspend,
+       .resume_noirq   = brcmstb_gisb_arb_resume_noirq,
 };
 
 static struct platform_driver brcmstb_gisb_arb_driver = {
-       .probe  = brcmstb_gisb_arb_probe,
        .driver = {
                .name   = "brcm-gisb-arb",
                .owner  = THIS_MODULE,
                .of_match_table = brcmstb_gisb_arb_of_match,
+               .pm     = &brcmstb_gisb_arb_pm_ops,
        },
 };
 
 static int __init brcm_gisb_driver_init(void)
 {
-       return platform_driver_register(&brcmstb_gisb_arb_driver);
+       return platform_driver_probe(&brcmstb_gisb_arb_driver,
+                                    brcmstb_gisb_arb_probe);
 }
 
 module_init(brcm_gisb_driver_init);
index 26c3779d871da61ee7976dbfc180eb6ac2999b14..eb7682dc123be4ef22d3b0a05e305b5aa7b11045 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/of_address.h>
 #include <linux/debugfs.h>
 #include <linux/log2.h>
+#include <linux/syscore_ops.h>
 
 /*
  * DDR target is the same on all platforms.
 
 #define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
 
+/* Relative to mbusbridge_base */
+#define MBUS_BRIDGE_CTRL_OFF   0x0
+#define MBUS_BRIDGE_BASE_OFF   0x4
+
+/* Maximum number of windows, for all known platforms */
+#define MBUS_WINS_MAX           20
+
 struct mvebu_mbus_state;
 
 struct mvebu_mbus_soc_data {
        unsigned int num_wins;
        unsigned int num_remappable_wins;
+       bool has_mbus_bridge;
        unsigned int (*win_cfg_offset)(const int win);
        void (*setup_cpu_target)(struct mvebu_mbus_state *s);
+       int (*save_cpu_target)(struct mvebu_mbus_state *s,
+                              u32 *store_addr);
        int (*show_cpu_target)(struct mvebu_mbus_state *s,
                               struct seq_file *seq, void *v);
 };
 
+/*
+ * Used to store the state of one MBus window accross suspend/resume.
+ */
+struct mvebu_mbus_win_data {
+       u32 ctrl;
+       u32 base;
+       u32 remap_lo;
+       u32 remap_hi;
+};
+
 struct mvebu_mbus_state {
        void __iomem *mbuswins_base;
        void __iomem *sdramwins_base;
+       void __iomem *mbusbridge_base;
+       phys_addr_t sdramwins_phys_base;
        struct dentry *debugfs_root;
        struct dentry *debugfs_sdram;
        struct dentry *debugfs_devs;
@@ -115,6 +138,11 @@ struct mvebu_mbus_state {
        struct resource pcie_io_aperture;
        const struct mvebu_mbus_soc_data *soc;
        int hw_io_coherency;
+
+       /* Used during suspend/resume */
+       u32 mbus_bridge_ctrl;
+       u32 mbus_bridge_base;
+       struct mvebu_mbus_win_data wins[MBUS_WINS_MAX];
 };
 
 static struct mvebu_mbus_state mbus_state;
@@ -516,6 +544,28 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
        mvebu_mbus_dram_info.num_cs = cs;
 }
 
+static int
+mvebu_mbus_default_save_cpu_target(struct mvebu_mbus_state *mbus,
+                                  u32 *store_addr)
+{
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
+               u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
+
+               writel(mbus->sdramwins_phys_base + DDR_BASE_CS_OFF(i),
+                      store_addr++);
+               writel(base, store_addr++);
+               writel(mbus->sdramwins_phys_base + DDR_SIZE_CS_OFF(i),
+                      store_addr++);
+               writel(size, store_addr++);
+       }
+
+       /* We've written 16 words to the store address */
+       return 16;
+}
+
 static void __init
 mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
 {
@@ -546,10 +596,35 @@ mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
        mvebu_mbus_dram_info.num_cs = cs;
 }
 
+static int
+mvebu_mbus_dove_save_cpu_target(struct mvebu_mbus_state *mbus,
+                               u32 *store_addr)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               u32 map = readl(mbus->sdramwins_base + DOVE_DDR_BASE_CS_OFF(i));
+
+               writel(mbus->sdramwins_phys_base + DOVE_DDR_BASE_CS_OFF(i),
+                      store_addr++);
+               writel(map, store_addr++);
+       }
+
+       /* We've written 4 words to the store address */
+       return 4;
+}
+
+int mvebu_mbus_save_cpu_target(u32 *store_addr)
+{
+       return mbus_state.soc->save_cpu_target(&mbus_state, store_addr);
+}
+
 static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = {
        .num_wins            = 20,
        .num_remappable_wins = 8,
+       .has_mbus_bridge     = true,
        .win_cfg_offset      = armada_370_xp_mbus_win_offset,
+       .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
@@ -558,6 +633,7 @@ static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
        .num_wins            = 8,
        .num_remappable_wins = 4,
        .win_cfg_offset      = orion_mbus_win_offset,
+       .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
@@ -566,6 +642,7 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = {
        .num_wins            = 8,
        .num_remappable_wins = 4,
        .win_cfg_offset      = orion_mbus_win_offset,
+       .save_cpu_target     = mvebu_mbus_dove_save_cpu_target,
        .setup_cpu_target    = mvebu_mbus_dove_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_dove,
 };
@@ -578,6 +655,7 @@ static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
        .num_wins            = 8,
        .num_remappable_wins = 4,
        .win_cfg_offset      = orion_mbus_win_offset,
+       .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
@@ -586,6 +664,7 @@ static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
        .num_wins            = 8,
        .num_remappable_wins = 2,
        .win_cfg_offset      = orion_mbus_win_offset,
+       .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
@@ -594,6 +673,7 @@ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
        .num_wins            = 14,
        .num_remappable_wins = 8,
        .win_cfg_offset      = mv78xx0_mbus_win_offset,
+       .save_cpu_target     = mvebu_mbus_default_save_cpu_target,
        .setup_cpu_target    = mvebu_mbus_default_setup_cpu_target,
        .show_cpu_target     = mvebu_sdram_debug_show_orion,
 };
@@ -698,11 +778,73 @@ static __init int mvebu_mbus_debugfs_init(void)
 }
 fs_initcall(mvebu_mbus_debugfs_init);
 
+static int mvebu_mbus_suspend(void)
+{
+       struct mvebu_mbus_state *s = &mbus_state;
+       int win;
+
+       if (!s->mbusbridge_base)
+               return -ENODEV;
+
+       for (win = 0; win < s->soc->num_wins; win++) {
+               void __iomem *addr = s->mbuswins_base +
+                       s->soc->win_cfg_offset(win);
+
+               s->wins[win].base = readl(addr + WIN_BASE_OFF);
+               s->wins[win].ctrl = readl(addr + WIN_CTRL_OFF);
+
+               if (win >= s->soc->num_remappable_wins)
+                       continue;
+
+               s->wins[win].remap_lo = readl(addr + WIN_REMAP_LO_OFF);
+               s->wins[win].remap_hi = readl(addr + WIN_REMAP_HI_OFF);
+       }
+
+       s->mbus_bridge_ctrl = readl(s->mbusbridge_base +
+                                   MBUS_BRIDGE_CTRL_OFF);
+       s->mbus_bridge_base = readl(s->mbusbridge_base +
+                                   MBUS_BRIDGE_BASE_OFF);
+
+       return 0;
+}
+
+static void mvebu_mbus_resume(void)
+{
+       struct mvebu_mbus_state *s = &mbus_state;
+       int win;
+
+       writel(s->mbus_bridge_ctrl,
+              s->mbusbridge_base + MBUS_BRIDGE_CTRL_OFF);
+       writel(s->mbus_bridge_base,
+              s->mbusbridge_base + MBUS_BRIDGE_BASE_OFF);
+
+       for (win = 0; win < s->soc->num_wins; win++) {
+               void __iomem *addr = s->mbuswins_base +
+                       s->soc->win_cfg_offset(win);
+
+               writel(s->wins[win].base, addr + WIN_BASE_OFF);
+               writel(s->wins[win].ctrl, addr + WIN_CTRL_OFF);
+
+               if (win >= s->soc->num_remappable_wins)
+                       continue;
+
+               writel(s->wins[win].remap_lo, addr + WIN_REMAP_LO_OFF);
+               writel(s->wins[win].remap_hi, addr + WIN_REMAP_HI_OFF);
+       }
+}
+
+struct syscore_ops mvebu_mbus_syscore_ops = {
+       .suspend        = mvebu_mbus_suspend,
+       .resume         = mvebu_mbus_resume,
+};
+
 static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
                                         phys_addr_t mbuswins_phys_base,
                                         size_t mbuswins_size,
                                         phys_addr_t sdramwins_phys_base,
-                                        size_t sdramwins_size)
+                                        size_t sdramwins_size,
+                                        phys_addr_t mbusbridge_phys_base,
+                                        size_t mbusbridge_size)
 {
        int win;
 
@@ -716,11 +858,26 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
                return -ENOMEM;
        }
 
+       mbus->sdramwins_phys_base = sdramwins_phys_base;
+
+       if (mbusbridge_phys_base) {
+               mbus->mbusbridge_base = ioremap(mbusbridge_phys_base,
+                                               mbusbridge_size);
+               if (!mbus->mbusbridge_base) {
+                       iounmap(mbus->sdramwins_base);
+                       iounmap(mbus->mbuswins_base);
+                       return -ENOMEM;
+               }
+       } else
+               mbus->mbusbridge_base = NULL;
+
        for (win = 0; win < mbus->soc->num_wins; win++)
                mvebu_mbus_disable_window(mbus, win);
 
        mbus->soc->setup_cpu_target(mbus);
 
+       register_syscore_ops(&mvebu_mbus_syscore_ops);
+
        return 0;
 }
 
@@ -746,7 +903,7 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
                        mbuswins_phys_base,
                        mbuswins_size,
                        sdramwins_phys_base,
-                       sdramwins_size);
+                       sdramwins_size, 0, 0);
 }
 
 #ifdef CONFIG_OF
@@ -887,7 +1044,7 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
 
 int __init mvebu_mbus_dt_init(bool is_coherent)
 {
-       struct resource mbuswins_res, sdramwins_res;
+       struct resource mbuswins_res, sdramwins_res, mbusbridge_res;
        struct device_node *np, *controller;
        const struct of_device_id *of_id;
        const __be32 *prop;
@@ -923,6 +1080,19 @@ int __init mvebu_mbus_dt_init(bool is_coherent)
                return -EINVAL;
        }
 
+       /*
+        * Set the resource to 0 so that it can be left unmapped by
+        * mvebu_mbus_common_init() if the DT doesn't carry the
+        * necessary information. This is needed to preserve backward
+        * compatibility.
+        */
+       memset(&mbusbridge_res, 0, sizeof(mbusbridge_res));
+
+       if (mbus_state.soc->has_mbus_bridge) {
+               if (of_address_to_resource(controller, 2, &mbusbridge_res))
+                       pr_warn(FW_WARN "deprecated mbus-mvebu Device Tree, suspend/resume will not work\n");
+       }
+
        mbus_state.hw_io_coherency = is_coherent;
 
        /* Get optional pcie-{mem,io}-aperture properties */
@@ -933,7 +1103,9 @@ int __init mvebu_mbus_dt_init(bool is_coherent)
                                     mbuswins_res.start,
                                     resource_size(&mbuswins_res),
                                     sdramwins_res.start,
-                                    resource_size(&sdramwins_res));
+                                    resource_size(&sdramwins_res),
+                                    mbusbridge_res.start,
+                                    resource_size(&mbusbridge_res));
        if (ret)
                return ret;
 
index 531ae591783b18df0442b6b87aba369e3b70107c..17d86595951c03a00ab8d0389766bedb5635b45a 100644 (file)
@@ -222,10 +222,14 @@ static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
                        }
 
                        /* Error found so break the for loop */
-                       break;
+                       return IRQ_HANDLED;
                }
        }
-       return IRQ_HANDLED;
+
+       dev_err(l3->dev, "L3 %s IRQ not handled!!\n",
+               inttype ? "debug" : "application");
+
+       return IRQ_NONE;
 }
 
 static const struct of_device_id l3_noc_match[] = {
@@ -296,11 +300,66 @@ static int omap_l3_probe(struct platform_device *pdev)
        return ret;
 }
 
+#ifdef CONFIG_PM
+
+/**
+ * l3_resume_noirq() - resume function for l3_noc
+ * @dev:       pointer to l3_noc device structure
+ *
+ * We only have the resume handler only since we
+ * have already maintained the delta register
+ * configuration as part of configuring the system
+ */
+static int l3_resume_noirq(struct device *dev)
+{
+       struct omap_l3 *l3 = dev_get_drvdata(dev);
+       int i;
+       struct l3_flagmux_data *flag_mux;
+       void __iomem *base, *mask_regx = NULL;
+       u32 mask_val;
+
+       for (i = 0; i < l3->num_modules; i++) {
+               base = l3->l3_base[i];
+               flag_mux = l3->l3_flagmux[i];
+               if (!flag_mux->mask_app_bits && !flag_mux->mask_dbg_bits)
+                       continue;
+
+               mask_regx = base + flag_mux->offset + L3_FLAGMUX_MASK0 +
+                          (L3_APPLICATION_ERROR << 3);
+               mask_val = readl_relaxed(mask_regx);
+               mask_val &= ~(flag_mux->mask_app_bits);
+
+               writel_relaxed(mask_val, mask_regx);
+               mask_regx = base + flag_mux->offset + L3_FLAGMUX_MASK0 +
+                          (L3_DEBUG_ERROR << 3);
+               mask_val = readl_relaxed(mask_regx);
+               mask_val &= ~(flag_mux->mask_dbg_bits);
+
+               writel_relaxed(mask_val, mask_regx);
+       }
+
+       /* Dummy read to force OCP barrier */
+       if (mask_regx)
+               (void)readl(mask_regx);
+
+       return 0;
+}
+
+static const struct dev_pm_ops l3_dev_pm_ops = {
+       .resume_noirq           = l3_resume_noirq,
+};
+
+#define L3_DEV_PM_OPS (&l3_dev_pm_ops)
+#else
+#define L3_DEV_PM_OPS NULL
+#endif
+
 static struct platform_driver omap_l3_driver = {
        .probe          = omap_l3_probe,
        .driver         = {
                .name           = "omap_l3_noc",
                .owner          = THIS_MODULE,
+               .pm             = L3_DEV_PM_OPS,
                .of_match_table = of_match_ptr(l3_noc_match),
        },
 };
index acc216491b8a5908656354f7c2ba7ffbfce8944a..597fdaee731508c684fc5b83ac38a8963c34c2c6 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
 #include "omap_l3_smx.h"
 
 static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
@@ -211,7 +215,17 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
        return ret;
 }
 
-static int __init omap3_l3_probe(struct platform_device *pdev)
+#if IS_BUILTIN(CONFIG_OF)
+static const struct of_device_id omap3_l3_match[] = {
+       {
+               .compatible = "ti,omap3-l3-smx",
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, omap3_l3_match);
+#endif
+
+static int omap3_l3_probe(struct platform_device *pdev)
 {
        struct omap3_l3 *l3;
        struct resource *res;
@@ -265,7 +279,7 @@ err0:
        return ret;
 }
 
-static int __exit omap3_l3_remove(struct platform_device *pdev)
+static int omap3_l3_remove(struct platform_device *pdev)
 {
        struct omap3_l3         *l3 = platform_get_drvdata(pdev);
 
@@ -278,15 +292,17 @@ static int __exit omap3_l3_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver omap3_l3_driver = {
-       .remove         = __exit_p(omap3_l3_remove),
+       .probe          = omap3_l3_probe,
+       .remove         = omap3_l3_remove,
        .driver         = {
-       .name   = "omap_l3_smx",
+               .name   = "omap_l3_smx",
+               .of_match_table = of_match_ptr(omap3_l3_match),
        },
 };
 
 static int __init omap3_l3_init(void)
 {
-       return platform_driver_probe(&omap3_l3_driver, omap3_l3_probe);
+       return platform_driver_register(&omap3_l3_driver);
 }
 postcore_initcall_sync(omap3_l3_init);
 
index 6226aa08c36af59b9406b5a278880537e16ac9a4..bcf86f91800a2c1810791a4e3a508d490de0d8f9 100644 (file)
 #include <asm/vio.h>
 
 
-static int pseries_rng_data_read(struct hwrng *rng, u32 *data)
+static int pseries_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
+       u64 buffer[PLPAR_HCALL_BUFSIZE];
+       size_t size = max < 8 ? max : 8;
        int rc;
 
-       rc = plpar_hcall(H_RANDOM, (unsigned long *)data);
+       rc = plpar_hcall(H_RANDOM, (unsigned long *)buffer);
        if (rc != H_SUCCESS) {
                pr_err_ratelimited("H_RANDOM call failed %d\n", rc);
                return -EIO;
        }
+       memcpy(data, buffer, size);
 
        /* The hypervisor interface returns 64 bits */
-       return 8;
+       return size;
 }
 
 /**
@@ -55,7 +58,7 @@ static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev)
 
 static struct hwrng pseries_rng = {
        .name           = KBUILD_MODNAME,
-       .data_read      = pseries_rng_data_read,
+       .read           = pseries_rng_read,
 };
 
 static int __init pseries_rng_probe(struct vio_dev *dev,
index 524b707894ef14f43cf010bfd73c74928e811884..4c58333b42570d233ccfaa83dac3c67f69e73b49 100644 (file)
@@ -84,9 +84,12 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 }
 #endif
 
-void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+#ifndef unxlate_dev_mem_ptr
+#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
+void __weak unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
 {
 }
+#endif
 
 /*
  * This funcion reads the *physical* memory. The f_pos points directly to the
@@ -97,7 +100,7 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 {
        phys_addr_t p = *ppos;
        ssize_t read, sz;
-       char *ptr;
+       void *ptr;
 
        if (p != *ppos)
                return 0;
@@ -400,7 +403,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
                         * uncached, then it must also be accessed uncached
                         * by the kernel or data corruption may occur
                         */
-                       kbuf = xlate_dev_kmem_ptr((char *)p);
+                       kbuf = xlate_dev_kmem_ptr((void *)p);
 
                        if (copy_to_user(buf, kbuf, sz))
                                return -EFAULT;
@@ -461,7 +464,7 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
 #endif
 
        while (count > 0) {
-               char *ptr;
+               void *ptr;
 
                sz = size_inside_page(p, count);
 
@@ -470,7 +473,7 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
                 * it must also be accessed uncached by the kernel or data
                 * corruption may occur.
                 */
-               ptr = xlate_dev_kmem_ptr((char *)p);
+               ptr = xlate_dev_kmem_ptr((void *)p);
 
                copied = copy_from_user(ptr, buf, sz);
                if (copied) {
index 82759cef904332cbe6800d4be9c4e08aa420f19c..04645c09fe5e5eee7f6699c451e9e4f6f8368958 100644 (file)
@@ -1106,7 +1106,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
        __mix_pool_bytes(r, hash.w, sizeof(hash.w));
        spin_unlock_irqrestore(&r->lock, flags);
 
-       memset(workspace, 0, sizeof(workspace));
+       memzero_explicit(workspace, sizeof(workspace));
 
        /*
         * In case the hash function has some recognizable output
@@ -1118,7 +1118,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
        hash.w[2] ^= rol32(hash.w[2], 16);
 
        memcpy(out, &hash, EXTRACT_SIZE);
-       memset(&hash, 0, sizeof(hash));
+       memzero_explicit(&hash, sizeof(hash));
 }
 
 /*
@@ -1175,7 +1175,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
        }
 
        /* Wipe data just returned from memory */
-       memset(tmp, 0, sizeof(tmp));
+       memzero_explicit(tmp, sizeof(tmp));
 
        return ret;
 }
@@ -1218,7 +1218,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
        }
 
        /* Wipe data just returned from memory */
-       memset(tmp, 0, sizeof(tmp));
+       memzero_explicit(tmp, sizeof(tmp));
 
        return ret;
 }
index 0102dc788608ec0060cf2fe1666e058c2d2d8076..a24891b97547dcf87cb91b52401e63f4d9dc50a2 100644 (file)
@@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
 
 static const struct file_operations raw_fops = {
        .read           = new_sync_read,
-       .read_iter      = generic_file_read_iter,
+       .read_iter      = blkdev_read_iter,
        .write          = new_sync_write,
        .write_iter     = blkdev_write_iter,
        .fsync          = blkdev_fsync,
index bfa640023e64893251d2cb2cf54af5a853d89568..cf7a561fad7cd9f3cdd94fe16e5c22d65318428c 100644 (file)
@@ -1449,8 +1449,6 @@ static int add_port(struct ports_device *portdev, u32 id)
        spin_lock_init(&port->outvq_lock);
        init_waitqueue_head(&port->waitqueue);
 
-       virtio_device_ready(portdev->vdev);
-
        /* Fill the in_vq with buffers so the host can send us data. */
        nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
        if (!nr_added_bufs) {
@@ -2026,6 +2024,8 @@ static int virtcons_probe(struct virtio_device *vdev)
        spin_lock_init(&portdev->ports_lock);
        INIT_LIST_HEAD(&portdev->ports);
 
+       virtio_device_ready(portdev->vdev);
+
        if (multiport) {
                unsigned int nr_added_bufs;
 
index 24b5b020753a9e4a66a5d3db7c8f7ad8bee0b928..a23ac0c724f014643e66bc2485f7c79cef523920 100644 (file)
@@ -52,29 +52,26 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
 
        tmp = pmc_read(pmc, AT91_PMC_USB);
        usbdiv = (tmp & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT;
-       return parent_rate / (usbdiv + 1);
+
+       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)
 {
        unsigned long div;
-       unsigned long bestrate;
-       unsigned long tmp;
+
+       if (!rate)
+               return -EINVAL;
 
        if (rate >= *parent_rate)
                return *parent_rate;
 
-       div = *parent_rate / rate;
-       if (div >= SAM9X5_USB_MAX_DIV)
-               return *parent_rate / (SAM9X5_USB_MAX_DIV + 1);
-
-       bestrate = *parent_rate / div;
-       tmp = *parent_rate / (div + 1);
-       if (bestrate - rate > rate - tmp)
-               bestrate = tmp;
+       div = DIV_ROUND_CLOSEST(*parent_rate, rate);
+       if (div > SAM9X5_USB_MAX_DIV + 1)
+               div = SAM9X5_USB_MAX_DIV + 1;
 
-       return bestrate;
+       return DIV_ROUND_CLOSEST(*parent_rate, div);
 }
 
 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
@@ -106,9 +103,13 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
        u32 tmp;
        struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
        struct at91_pmc *pmc = usb->pmc;
-       unsigned long div = parent_rate / rate;
+       unsigned long div;
+
+       if (!rate)
+               return -EINVAL;
 
-       if (parent_rate % rate || div < 1 || div >= SAM9X5_USB_MAX_DIV)
+       div = DIV_ROUND_CLOSEST(parent_rate, rate);
+       if (div > SAM9X5_USB_MAX_DIV + 1 || !div)
                return -EINVAL;
 
        tmp = pmc_read(pmc, AT91_PMC_USB) & ~AT91_PMC_OHCIUSBDIV;
@@ -253,7 +254,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
 
                tmp_parent_rate = rate * usb->divisors[i];
                tmp_parent_rate = __clk_round_rate(parent, tmp_parent_rate);
-               tmprate = tmp_parent_rate / usb->divisors[i];
+               tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
                if (tmprate < rate)
                        tmpdiff = rate - tmprate;
                else
@@ -281,10 +282,10 @@ static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
        struct at91_pmc *pmc = usb->pmc;
        unsigned long div;
 
-       if (!rate || parent_rate % rate)
+       if (!rate)
                return -EINVAL;
 
-       div = parent_rate / rate;
+       div = DIV_ROUND_CLOSEST(parent_rate, rate);
 
        for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
                if (usb->divisors[i] == div) {
index 18a9de29df0e0c31dadd3de0b2bdb2485fab2733..c0a842b335c520c6c28f08308a1b62a743038dd3 100644 (file)
@@ -263,6 +263,14 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
        if (!rate)
                rate = 1;
 
+       /* if read only, just return current value */
+       if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+               bestdiv = readl(divider->reg) >> divider->shift;
+               bestdiv &= div_mask(divider);
+               bestdiv = _get_div(divider, bestdiv);
+               return bestdiv;
+       }
+
        maxdiv = _get_maxdiv(divider);
 
        if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
@@ -361,11 +369,6 @@ const struct clk_ops clk_divider_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_divider_ops);
 
-const struct clk_ops clk_divider_ro_ops = {
-       .recalc_rate = clk_divider_recalc_rate,
-};
-EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
-
 static struct clk *_register_divider(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 shift, u8 width,
@@ -391,10 +394,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
        }
 
        init.name = name;
-       if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
-               init.ops = &clk_divider_ro_ops;
-       else
-               init.ops = &clk_divider_ops;
+       init.ops = &clk_divider_ops;
        init.flags = flags | CLK_IS_BASIC;
        init.parent_names = (parent_name ? &parent_name: NULL);
        init.num_parents = (parent_name ? 1 : 0);
index b7797fb12e1254d5e9e8a2214b11286b21e991eb..7bb13af8e2148f1110b54db534476dbacdd80863 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/clk-provider.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s5m8767.h>
 #include <linux/mfd/samsung/core.h>
@@ -120,6 +121,24 @@ static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
        },
 };
 
+static struct clk_init_data s2mps13_clks_init[S2MPS11_CLKS_NUM] = {
+       [S2MPS11_CLK_AP] = {
+               .name = "s2mps13_ap",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_CP] = {
+               .name = "s2mps13_cp",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [S2MPS11_CLK_BT] = {
+               .name = "s2mps13_bt",
+               .ops = &s2mps11_clk_ops,
+               .flags = CLK_IS_ROOT,
+       },
+};
+
 static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
        [S2MPS11_CLK_AP] = {
                .name = "s2mps14_ap",
@@ -184,6 +203,10 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
                s2mps11_reg = S2MPS11_REG_RTC_CTRL;
                clks_init = s2mps11_clks_init;
                break;
+       case S2MPS13X:
+               s2mps11_reg = S2MPS13_REG_RTCCTRL;
+               clks_init = s2mps13_clks_init;
+               break;
        case S2MPS14X:
                s2mps11_reg = S2MPS14_REG_RTCCTRL;
                clks_init = s2mps14_clks_init;
@@ -279,6 +302,7 @@ static int s2mps11_clk_remove(struct platform_device *pdev)
 
 static const struct platform_device_id s2mps11_clk_id[] = {
        { "s2mps11-clk", S2MPS11X},
+       { "s2mps13-clk", S2MPS13X},
        { "s2mps14-clk", S2MPS14X},
        { "s5m8767-clk", S5M8767X},
        { },
index b7fcb469c87af73e6c6f45dcb1b98e188d99c0f8..0d4d1216f2dd25fb32f0b5417359d95957c9f086 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/syscore_ops.h>
 
 #include "common.h"
 
@@ -177,14 +178,17 @@ struct clk_gating_ctrl {
        spinlock_t *lock;
        struct clk **gates;
        int num_gates;
+       void __iomem *base;
+       u32 saved_reg;
 };
 
 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
 
+static struct clk_gating_ctrl *ctrl;
+
 static struct clk *clk_gating_get_src(
        struct of_phandle_args *clkspec, void *data)
 {
-       struct clk_gating_ctrl *ctrl = (struct clk_gating_ctrl *)data;
        int n;
 
        if (clkspec->args_count < 1)
@@ -199,15 +203,35 @@ static struct clk *clk_gating_get_src(
        return ERR_PTR(-ENODEV);
 }
 
+static int mvebu_clk_gating_suspend(void)
+{
+       ctrl->saved_reg = readl(ctrl->base);
+       return 0;
+}
+
+static void mvebu_clk_gating_resume(void)
+{
+       writel(ctrl->saved_reg, ctrl->base);
+}
+
+static struct syscore_ops clk_gate_syscore_ops = {
+       .suspend = mvebu_clk_gating_suspend,
+       .resume = mvebu_clk_gating_resume,
+};
+
 void __init mvebu_clk_gating_setup(struct device_node *np,
                                   const struct clk_gating_soc_desc *desc)
 {
-       struct clk_gating_ctrl *ctrl;
        struct clk *clk;
        void __iomem *base;
        const char *default_parent = NULL;
        int n;
 
+       if (ctrl) {
+               pr_err("mvebu-clk-gating: cannot instantiate more than one gatable clock device\n");
+               return;
+       }
+
        base = of_iomap(np, 0);
        if (WARN_ON(!base))
                return;
@@ -225,6 +249,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
        /* lock must already be initialized */
        ctrl->lock = &ctrl_gating_lock;
 
+       ctrl->base = base;
+
        /* Count, allocate, and register clock gates */
        for (n = 0; desc[n].name;)
                n++;
@@ -246,6 +272,8 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
 
        of_clk_add_provider(np, clk_gating_get_src, ctrl);
 
+       register_syscore_ops(&clk_gate_syscore_ops);
+
        return;
 gates_out:
        kfree(ctrl);
index b345cc791e5defdeeb57d0b8df4d566bd41aef2c..88b9fe13fa444b2a81a3bd8a2588b035357d0048 100644 (file)
@@ -322,7 +322,7 @@ static unsigned long clk_pxa27x_memory_get_rate(struct clk_hw *hw,
        unsigned long ccsr = CCSR;
 
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
-       a = cccr & CCCR_A_BIT;
+       a = cccr & (1 << CCCR_A_BIT);
        l  = ccsr & CCSR_L_MASK;
 
        if (osc_forced || a)
@@ -341,7 +341,7 @@ static u8 clk_pxa27x_memory_get_parent(struct clk_hw *hw)
        unsigned long ccsr = CCSR;
 
        osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
-       a = cccr & CCCR_A_BIT;
+       a = cccr & (1 << CCCR_A_BIT);
        if (osc_forced)
                return PXA_MEM_13Mhz;
        if (a)
index dab988ab8cf12740ac931c5f5efaa39b90887ec3..157139a5c1ca956d76d1be30dfb6687f82d01816 100644 (file)
@@ -3122,7 +3122,7 @@ static struct clk_regmap *mmcc_apq8084_clocks[] = {
        [ESC1_CLK_SRC] = &esc1_clk_src.clkr,
        [HDMI_CLK_SRC] = &hdmi_clk_src.clkr,
        [VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
-       [RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
+       [MMSS_RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,
        [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,
        [MAPLE_CLK_SRC] = &maple_clk_src.clkr,
        [VDP_CLK_SRC] = &vdp_clk_src.clkr,
index 1e68bff481b8e32ec440959002a2467287c269da..880a266f01431b3b9e7040565d3a3e81f0716a8b 100644 (file)
@@ -90,9 +90,7 @@ static struct clk *rockchip_clk_register_branch(const char *name,
                div->width = div_width;
                div->lock = lock;
                div->table = div_table;
-               div_ops = (div_flags & CLK_DIVIDER_READ_ONLY)
-                                               ? &clk_divider_ro_ops
-                                               : &clk_divider_ops;
+               div_ops = &clk_divider_ops;
        }
 
        clk = clk_register_composite(NULL, name, parent_names, num_parents,
index 00d1d00a41de5b99e0b92d65717c21507c1cf063..979e81389cdd04bf668f6982ea2ceee5ebb17f82 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
 
 #include "clk.h"
 #include "clk-pll.h"
@@ -23,6 +25,8 @@
 #define CPU_CLK_STATUS         0xfc
 #define MISC_DOUT1             0x558
 
+static void __iomem *reg_base;
+
 /* parent clock name list */
 PNAME(mout_armclk_p)   = { "cplla", "cpllb" };
 PNAME(mout_spi_p)      = { "div125", "div200" };
@@ -89,10 +93,30 @@ static const struct of_device_id ext_clk_match[] __initconst = {
        {},
 };
 
+static int exynos5440_clk_restart_notify(struct notifier_block *this,
+               unsigned long code, void *unused)
+{
+       u32 val, status;
+
+       status = readl_relaxed(reg_base + 0xbc);
+       val = readl_relaxed(reg_base + 0xcc);
+       val = (val & 0xffff0000) | (status & 0xffff);
+       writel_relaxed(val, reg_base + 0xcc);
+
+       return NOTIFY_DONE;
+}
+
+/*
+ * Exynos5440 Clock restart notifier, handles restart functionality
+ */
+static struct notifier_block exynos5440_clk_restart_handler = {
+       .notifier_call = exynos5440_clk_restart_notify,
+       .priority = 128,
+};
+
 /* register exynos5440 clocks */
 static void __init exynos5440_clk_init(struct device_node *np)
 {
-       void __iomem *reg_base;
        struct samsung_clk_provider *ctx;
 
        reg_base = of_iomap(np, 0);
@@ -125,6 +149,9 @@ static void __init exynos5440_clk_init(struct device_node *np)
 
        samsung_clk_of_add_provider(np, ctx);
 
+       if (register_restart_handler(&exynos5440_clk_restart_handler))
+               pr_warn("exynos5440 clock can't register restart handler\n");
+
        pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
        pr_info("exynos5440 clock initialization complete\n");
 }
index 290f9c1a37498ccf16ae0b09804ca15e722a2da2..59a5714dfe18c237323821027ccae5bb59916a38 100644 (file)
@@ -185,3 +185,16 @@ struct clk *tegra_clk_register_divider(const char *name,
 
        return clk;
 }
+
+static const struct clk_div_table mc_div_table[] = {
+       { .val = 0, .div = 2 },
+       { .val = 1, .div = 1 },
+       { .val = 0, .div = 0 },
+};
+
+struct clk *tegra_clk_register_mc(const char *name, const char *parent_name,
+                                 void __iomem *reg, spinlock_t *lock)
+{
+       return clk_register_divider_table(NULL, name, parent_name, 0, reg,
+                                         16, 1, 0, mc_div_table, lock);
+}
index f760f31d05c40feadb7db666f5e8cf4dd2871e58..0b03d2cf7264f7d42dafb84fd83bb29e18f420a1 100644 (file)
@@ -173,6 +173,7 @@ static DEFINE_SPINLOCK(pll_d_lock);
 static DEFINE_SPINLOCK(pll_d2_lock);
 static DEFINE_SPINLOCK(pll_u_lock);
 static DEFINE_SPINLOCK(pll_re_lock);
+static DEFINE_SPINLOCK(emc_lock);
 
 static struct div_nmp pllxc_nmp = {
        .divm_shift = 0,
@@ -1228,7 +1229,11 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
                               ARRAY_SIZE(mux_pllmcp_clkm),
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + CLK_SOURCE_EMC,
-                              29, 3, 0, NULL);
+                              29, 3, 0, &emc_lock);
+
+       clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+                                   &emc_lock);
+       clks[TEGRA114_CLK_MC] = clk;
 
        for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
                data = &tegra_periph_clk_list[i];
index e3a85842ce0c05890351f49f4d4a6c330812b9ab..f5f9baca7bb621924d14ff4d9364d18580e0fbc2 100644 (file)
@@ -132,6 +132,7 @@ static DEFINE_SPINLOCK(pll_d2_lock);
 static DEFINE_SPINLOCK(pll_e_lock);
 static DEFINE_SPINLOCK(pll_re_lock);
 static DEFINE_SPINLOCK(pll_u_lock);
+static DEFINE_SPINLOCK(emc_lock);
 
 /* possible OSC frequencies in Hz */
 static unsigned long tegra124_input_freq[] = {
@@ -1127,7 +1128,11 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
        clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
                               ARRAY_SIZE(mux_pllmcp_clkm), 0,
                               clk_base + CLK_SOURCE_EMC,
-                              29, 3, 0, NULL);
+                              29, 3, 0, &emc_lock);
+
+       clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+                                   &emc_lock);
+       clks[TEGRA124_CLK_MC] = clk;
 
        /* cml0 */
        clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
index dace2b1b5ae66dafab4fe4639e6291872491119d..41272dcc9e225758da291018dc71bf921f85be8f 100644 (file)
@@ -140,6 +140,8 @@ static struct cpu_clk_suspend_context {
 static void __iomem *clk_base;
 static void __iomem *pmc_base;
 
+static DEFINE_SPINLOCK(emc_lock);
+
 #define TEGRA_INIT_DATA_MUX(_name, _parents, _offset,  \
                            _clk_num, _gate_flags, _clk_id)     \
        TEGRA_INIT_DATA(_name, NULL, NULL, _parents, _offset,   \
@@ -819,11 +821,15 @@ static void __init tegra20_periph_clk_init(void)
                               ARRAY_SIZE(mux_pllmcp_clkm),
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + CLK_SOURCE_EMC,
-                              30, 2, 0, NULL);
+                              30, 2, 0, &emc_lock);
        clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
                                    57, periph_clk_enb_refcnt);
        clks[TEGRA20_CLK_EMC] = clk;
 
+       clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+                                   &emc_lock);
+       clks[TEGRA20_CLK_MC] = clk;
+
        /* dsi */
        clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
                                    48, periph_clk_enb_refcnt);
index 5bbacd01094f3770fcd3161e733070ea3412b97c..4b9d8bd3d0bfdd8e93f0436ea3bd0f016d5091fb 100644 (file)
@@ -177,6 +177,7 @@ static unsigned long input_freq;
 
 static DEFINE_SPINLOCK(cml_lock);
 static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(emc_lock);
 
 #define TEGRA_INIT_DATA_MUX(_name, _parents, _offset,  \
                            _clk_num, _gate_flags, _clk_id)     \
@@ -1157,11 +1158,15 @@ static void __init tegra30_periph_clk_init(void)
                               ARRAY_SIZE(mux_pllmcp_clkm),
                               CLK_SET_RATE_NO_REPARENT,
                               clk_base + CLK_SOURCE_EMC,
-                              30, 2, 0, NULL);
+                              30, 2, 0, &emc_lock);
        clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
                                    57, periph_clk_enb_refcnt);
        clks[TEGRA30_CLK_EMC] = clk;
 
+       clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+                                   &emc_lock);
+       clks[TEGRA30_CLK_MC] = clk;
+
        /* cml0 */
        clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
                                0, 0, &cml_lock);
index 16ec8d6bb87f287724ff53a362b8c39de2880193..4e458aa8d45c19e6ec1ee3cf9050cfc044cdec28 100644 (file)
@@ -86,6 +86,8 @@ struct clk *tegra_clk_register_divider(const char *name,
                const char *parent_name, void __iomem *reg,
                unsigned long flags, u8 clk_divider_flags, u8 shift, u8 width,
                u8 frac_width, spinlock_t *lock);
+struct clk *tegra_clk_register_mc(const char *name, const char *parent_name,
+                                 void __iomem *reg, spinlock_t *lock);
 
 /*
  * Tegra PLL:
index 79791e1bf2824814e67b7c3e40d0dc2cbbec28a7..85ac0dd501dea5fff98801ba47edabbf972492a5 100644 (file)
@@ -33,6 +33,9 @@ static const struct clk_ops dpll_m4xen_ck_ops = {
        .recalc_rate    = &omap4_dpll_regm4xen_recalc,
        .round_rate     = &omap4_dpll_regm4xen_round_rate,
        .set_rate       = &omap3_noncore_dpll_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_noncore_dpll_set_rate_and_parent,
+       .determine_rate = &omap4_dpll_regm4xen_determine_rate,
        .get_parent     = &omap2_init_dpll_parent,
 };
 #else
@@ -53,6 +56,9 @@ static const struct clk_ops dpll_ck_ops = {
        .recalc_rate    = &omap3_dpll_recalc,
        .round_rate     = &omap2_dpll_round_rate,
        .set_rate       = &omap3_noncore_dpll_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_noncore_dpll_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
        .get_parent     = &omap2_init_dpll_parent,
 };
 
@@ -61,6 +67,9 @@ static const struct clk_ops dpll_no_gate_ck_ops = {
        .get_parent     = &omap2_init_dpll_parent,
        .round_rate     = &omap2_dpll_round_rate,
        .set_rate       = &omap3_noncore_dpll_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_noncore_dpll_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
 };
 #else
 static const struct clk_ops dpll_core_ck_ops = {};
@@ -97,6 +106,9 @@ static const struct clk_ops omap3_dpll_ck_ops = {
        .get_parent     = &omap2_init_dpll_parent,
        .recalc_rate    = &omap3_dpll_recalc,
        .set_rate       = &omap3_noncore_dpll_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_noncore_dpll_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
        .round_rate     = &omap2_dpll_round_rate,
 };
 
@@ -106,6 +118,9 @@ static const struct clk_ops omap3_dpll_per_ck_ops = {
        .get_parent     = &omap2_init_dpll_parent,
        .recalc_rate    = &omap3_dpll_recalc,
        .set_rate       = &omap3_dpll4_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_dpll4_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
        .round_rate     = &omap2_dpll_round_rate,
 };
 #endif
index 162e519cb0f98aa664fd3363300ddeda68be35ef..8ff03744fe9890e1ec9069c31ac37dc2d4a329f4 100644 (file)
@@ -2,6 +2,5 @@
 obj-$(CONFIG_ICST)             += clk-icst.o clk-versatile.o
 obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)    += clk-realview.o
-obj-$(CONFIG_ARCH_VEXPRESS)    += clk-vexpress.o
 obj-$(CONFIG_CLK_SP810)                += clk-sp810.o
 obj-$(CONFIG_CLK_VEXPRESS_OSC) += clk-vexpress-osc.o
index 529a59c0fbfa4ced8f163abe77663d038dd78b24..765f1e0eeeb2a93e92aa3835dd09c4ea3d845e58 100644 (file)
@@ -70,7 +70,6 @@ static struct clk_ops vexpress_osc_ops = {
 
 static int vexpress_osc_probe(struct platform_device *pdev)
 {
-       struct clk_lookup *cl = pdev->dev.platform_data; /* Non-DT lookup */
        struct clk_init_data init;
        struct vexpress_osc *osc;
        struct clk *clk;
@@ -106,12 +105,6 @@ static int vexpress_osc_probe(struct platform_device *pdev)
 
        of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
 
-       /* Only happens for non-DT cases */
-       if (cl) {
-               cl->clk = clk;
-               clkdev_add(cl);
-       }
-
        dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);
 
        return 0;
diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c
deleted file mode 100644 (file)
index 2d5e1b4..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * This program is free software; you can 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.
- *
- * Copyright (C) 2012 ARM Limited
- */
-
-#include <linux/amba/sp810.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/err.h>
-#include <linux/vexpress.h>
-
-static struct clk *vexpress_sp810_timerclken[4];
-static DEFINE_SPINLOCK(vexpress_sp810_lock);
-
-static void __init vexpress_sp810_init(void __iomem *base)
-{
-       int i;
-
-       if (WARN_ON(!base))
-               return;
-
-       for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
-               char name[12];
-               const char *parents[] = {
-                       "v2m:refclk32khz", /* REFCLK */
-                       "v2m:refclk1mhz" /* TIMCLK */
-               };
-
-               snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
-
-               vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
-                               parents, 2, CLK_SET_RATE_NO_REPARENT,
-                               base + SCCTRL, SCCTRL_TIMERENnSEL_SHIFT(i), 1,
-                               0, &vexpress_sp810_lock);
-
-               if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
-                       break;
-       }
-}
-
-
-static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
-       "mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
-       "mb:mmci", "mb:kmi0", "mb:kmi1"
-};
-
-void __init vexpress_clk_init(void __iomem *sp810_base)
-{
-       struct clk *clk;
-       int i;
-
-       clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
-                       CLK_IS_ROOT, 0);
-       WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
-
-       clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
-                       CLK_IS_ROOT, 24000000);
-       for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
-               WARN_ON(clk_register_clkdev(clk, NULL,
-                               vexpress_clk_24mhz_periphs[i]));
-
-       clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
-                       CLK_IS_ROOT, 32768);
-       WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
-
-       clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
-                       CLK_IS_ROOT, 1000000);
-
-       vexpress_sp810_init(sp810_base);
-
-       for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
-               WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
-
-       WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
-                               "v2m-timer0", "sp804"));
-       WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
-                               "v2m-timer1", "sp804"));
-}
index 90420600e1eb1d6668d78eb6eb809e218d25673f..f657a48d20eb412a63b85a066711eb8c68aca3a9 100644 (file)
@@ -32,6 +32,7 @@ config ARMADA_370_XP_TIMER
 
 config MESON6_TIMER
        bool
+       select CLKSRC_MMIO
 
 config ORION_TIMER
        select CLKSRC_OF
index 756f6f10efa03de825a9b1ef48edf8315f331161..fae0435cc23d580df6c3e192051a4526cdb08acb 100644 (file)
@@ -45,4 +45,5 @@ obj-$(CONFIG_ARM_GLOBAL_TIMER)                += arm_global_timer.o
 obj-$(CONFIG_CLKSRC_METAG_GENERIC)     += metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)  += dummy_timer.o
 obj-$(CONFIG_ARCH_KEYSTONE)            += timer-keystone.o
+obj-$(CONFIG_ARCH_INTEGRATOR_AP)       += timer-integrator-ap.o
 obj-$(CONFIG_CLKSRC_VERSATILE)         += versatile.o
index 2133f9d59d06323bbf1f69ca80c21ddee66904f6..6a79fc4f900c4b56b4bd351cf050aa5c2b67175e 100644 (file)
@@ -462,7 +462,10 @@ static void __init arch_counter_register(unsigned type)
 
        /* Register the CP15 based counter if we have one */
        if (type & ARCH_CP15_TIMER) {
-               arch_timer_read_counter = arch_counter_get_cntvct;
+               if (arch_timer_use_virtual)
+                       arch_timer_read_counter = arch_counter_get_cntvct;
+               else
+                       arch_timer_read_counter = arch_counter_get_cntpct;
        } else {
                arch_timer_read_counter = arch_counter_get_cntvct_mem;
 
@@ -660,11 +663,11 @@ static bool __init
 arch_timer_probed(int type, const struct of_device_id *matches)
 {
        struct device_node *dn;
-       bool probed = false;
+       bool probed = true;
 
        dn = of_find_matching_node(NULL, matches);
-       if (dn && of_device_is_available(dn) && (arch_timers_present & type))
-               probed = true;
+       if (dn && of_device_is_available(dn) && !(arch_timers_present & type))
+               probed = false;
        of_node_put(dn);
 
        return probed;
@@ -701,6 +704,14 @@ static void __init arch_timer_init(struct device_node *np)
                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
index efb17c3ee120e5ee28fa05099c4c3c7ce09f0ac1..f4a9c0058b4d677382863a12bf887b40202f63fe 100644 (file)
@@ -182,6 +182,12 @@ static void __init sun4i_timer_init(struct device_node *node)
        /* Make sure timer is stopped before playing with interrupts */
        sun4i_clkevt_time_stop(0);
 
+       sun4i_clockevent.cpumask = cpu_possible_mask;
+       sun4i_clockevent.irq = irq;
+
+       clockevents_config_and_register(&sun4i_clockevent, rate,
+                                       TIMER_SYNC_TICKS, 0xffffffff);
+
        ret = setup_irq(irq, &sun4i_timer_irq);
        if (ret)
                pr_warn("failed to setup irq %d\n", irq);
@@ -189,12 +195,6 @@ static void __init sun4i_timer_init(struct device_node *node)
        /* Enable timer0 interrupt */
        val = readl(timer_base + TIMER_IRQ_EN_REG);
        writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
-
-       sun4i_clockevent.cpumask = cpu_possible_mask;
-       sun4i_clockevent.irq = irq;
-
-       clockevents_config_and_register(&sun4i_clockevent, rate,
-                                       TIMER_SYNC_TICKS, 0xffffffff);
 }
 CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
                       sun4i_timer_init);
index 0451e62fac7a8e31fd2bc370a83b4fdc4083bf01..0c8c5e3375407fad8c6f666c596d1b2c155acc04 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/module.h>
 #include <linux/sched_clock.h>
 #include <linux/percpu.h>
+#include <linux/syscore_ops.h>
 
 /*
  * Timer block registers.
@@ -223,6 +224,28 @@ static struct notifier_block armada_370_xp_timer_cpu_nb = {
        .notifier_call = armada_370_xp_timer_cpu_notify,
 };
 
+static u32 timer0_ctrl_reg, timer0_local_ctrl_reg;
+
+static int armada_370_xp_timer_suspend(void)
+{
+       timer0_ctrl_reg = readl(timer_base + TIMER_CTRL_OFF);
+       timer0_local_ctrl_reg = readl(local_base + TIMER_CTRL_OFF);
+       return 0;
+}
+
+static void armada_370_xp_timer_resume(void)
+{
+       writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+       writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+       writel(timer0_ctrl_reg, timer_base + TIMER_CTRL_OFF);
+       writel(timer0_local_ctrl_reg, local_base + TIMER_CTRL_OFF);
+}
+
+struct syscore_ops armada_370_xp_timer_syscore_ops = {
+       .suspend        = armada_370_xp_timer_suspend,
+       .resume         = armada_370_xp_timer_resume,
+};
+
 static void __init armada_370_xp_timer_common_init(struct device_node *np)
 {
        u32 clr = 0, set = 0;
@@ -285,6 +308,8 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
        /* Immediately configure the timer on the boot CPU */
        if (!res)
                armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
+
+       register_syscore_ops(&armada_370_xp_timer_syscore_ops);
 }
 
 static void __init armada_xp_timer_init(struct device_node *np)
@@ -293,6 +318,7 @@ static void __init armada_xp_timer_init(struct device_node *np)
 
        /* The 25Mhz fixed clock is mandatory, and must always be available */
        BUG_ON(IS_ERR(clk));
+       clk_prepare_enable(clk);
        timer_clk = clk_get_rate(clk);
 
        armada_370_xp_timer_common_init(np);
@@ -300,11 +326,40 @@ static void __init armada_xp_timer_init(struct device_node *np)
 CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
                       armada_xp_timer_init);
 
+static void __init armada_375_timer_init(struct device_node *np)
+{
+       struct clk *clk;
+
+       clk = of_clk_get_by_name(np, "fixed");
+       if (!IS_ERR(clk)) {
+               clk_prepare_enable(clk);
+               timer_clk = clk_get_rate(clk);
+       } else {
+
+               /*
+                * This fallback is required in order to retain proper
+                * devicetree backwards compatibility.
+                */
+               clk = of_clk_get(np, 0);
+
+               /* Must have at least a clock */
+               BUG_ON(IS_ERR(clk));
+               clk_prepare_enable(clk);
+               timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
+               timer25Mhz = false;
+       }
+
+       armada_370_xp_timer_common_init(np);
+}
+CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer",
+                      armada_375_timer_init);
+
 static void __init armada_370_timer_init(struct device_node *np)
 {
        struct clk *clk = of_clk_get(np, 0);
 
        BUG_ON(IS_ERR(clk));
+       clk_prepare_enable(clk);
        timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
        timer25Mhz = false;
 
index d5289098b3df41547e63630f1fc24b17e725cb0b..b5b4d4585c9aba41bc396e91cc107b710b154664 100644 (file)
@@ -262,35 +262,3 @@ static void __init at91sam926x_pit_dt_init(struct device_node *node)
 }
 CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
                       at91sam926x_pit_dt_init);
-
-static void __iomem *pit_base_addr;
-
-void __init at91sam926x_pit_init(int irq)
-{
-       struct pit_data *data;
-
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               panic(pr_fmt("Unable to allocate memory\n"));
-
-       data->base = pit_base_addr;
-
-       data->mck = clk_get(NULL, "mck");
-       if (IS_ERR(data->mck))
-               panic(pr_fmt("Unable to get mck clk\n"));
-
-       data->irq = irq;
-
-       at91sam926x_pit_common_init(data);
-}
-
-void __init at91sam926x_ioremap_pit(u32 addr)
-{
-       if (of_have_populated_dt())
-               return;
-
-       pit_base_addr = ioremap(addr, 16);
-
-       if (!pit_base_addr)
-               panic(pr_fmt("Impossible to ioremap PIT\n"));
-}
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c
new file mode 100644 (file)
index 0000000..b9efd30
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Integrator/AP timer driver
+ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
+ * Copyright (c) 2014, Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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/clk.h>
+#include <linux/clocksource.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/sched_clock.h>
+#include <asm/hardware/arm_timer.h>
+
+static void __iomem * sched_clk_base;
+
+static u64 notrace integrator_read_sched_clock(void)
+{
+       return -readl(sched_clk_base + TIMER_VALUE);
+}
+
+static void integrator_clocksource_init(unsigned long inrate,
+                                       void __iomem *base)
+{
+       u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
+       unsigned long rate = inrate;
+
+       if (rate >= 1500000) {
+               rate /= 16;
+               ctrl |= TIMER_CTRL_DIV16;
+       }
+
+       writel(0xffff, base + TIMER_LOAD);
+       writel(ctrl, base + TIMER_CTRL);
+
+       clocksource_mmio_init(base + TIMER_VALUE, "timer2",
+                       rate, 200, 16, clocksource_mmio_readl_down);
+
+       sched_clk_base = base;
+       sched_clock_register(integrator_read_sched_clock, 16, rate);
+}
+
+static unsigned long timer_reload;
+static void __iomem * clkevt_base;
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = dev_id;
+
+       /* clear the interrupt */
+       writel(1, clkevt_base + TIMER_INTCLR);
+
+       evt->event_handler(evt);
+
+       return IRQ_HANDLED;
+}
+
+static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
+{
+       u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
+
+       /* Disable timer */
+       writel(ctrl, clkevt_base + TIMER_CTRL);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               /* Enable the timer and start the periodic tick */
+               writel(timer_reload, clkevt_base + TIMER_LOAD);
+               ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
+               writel(ctrl, clkevt_base + TIMER_CTRL);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               /* Leave the timer disabled, .set_next_event will enable it */
+               ctrl &= ~TIMER_CTRL_PERIODIC;
+               writel(ctrl, clkevt_base + TIMER_CTRL);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_RESUME:
+       default:
+               /* Just leave in disabled state */
+               break;
+       }
+
+}
+
+static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
+{
+       unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
+
+       writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
+       writel(next, clkevt_base + TIMER_LOAD);
+       writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
+
+       return 0;
+}
+
+static struct clock_event_device integrator_clockevent = {
+       .name           = "timer1",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode       = clkevt_set_mode,
+       .set_next_event = clkevt_set_next_event,
+       .rating         = 300,
+};
+
+static struct irqaction integrator_timer_irq = {
+       .name           = "timer",
+       .flags          = IRQF_TIMER | IRQF_IRQPOLL,
+       .handler        = integrator_timer_interrupt,
+       .dev_id         = &integrator_clockevent,
+};
+
+static void integrator_clockevent_init(unsigned long inrate,
+                               void __iomem *base, int irq)
+{
+       unsigned long rate = inrate;
+       unsigned int ctrl = 0;
+
+       clkevt_base = base;
+       /* Calculate and program a divisor */
+       if (rate > 0x100000 * HZ) {
+               rate /= 256;
+               ctrl |= TIMER_CTRL_DIV256;
+       } else if (rate > 0x10000 * HZ) {
+               rate /= 16;
+               ctrl |= TIMER_CTRL_DIV16;
+       }
+       timer_reload = rate / HZ;
+       writel(ctrl, clkevt_base + TIMER_CTRL);
+
+       setup_irq(irq, &integrator_timer_irq);
+       clockevents_config_and_register(&integrator_clockevent,
+                                       rate,
+                                       1,
+                                       0xffffU);
+}
+
+static void __init integrator_ap_timer_init_of(struct device_node *node)
+{
+       const char *path;
+       void __iomem *base;
+       int err;
+       int irq;
+       struct clk *clk;
+       unsigned long rate;
+       struct device_node *pri_node;
+       struct device_node *sec_node;
+
+       base = of_io_request_and_map(node, 0, "integrator-timer");
+       if (!base)
+               return;
+
+       clk = of_clk_get(node, 0);
+       if (IS_ERR(clk)) {
+               pr_err("No clock for %s\n", node->name);
+               return;
+       }
+       clk_prepare_enable(clk);
+       rate = clk_get_rate(clk);
+       writel(0, base + TIMER_CTRL);
+
+       err = of_property_read_string(of_aliases,
+                               "arm,timer-primary", &path);
+       if (WARN_ON(err))
+               return;
+       pri_node = of_find_node_by_path(path);
+       err = of_property_read_string(of_aliases,
+                               "arm,timer-secondary", &path);
+       if (WARN_ON(err))
+               return;
+       sec_node = of_find_node_by_path(path);
+
+       if (node == pri_node) {
+               /* The primary timer lacks IRQ, use as clocksource */
+               integrator_clocksource_init(rate, base);
+               return;
+       }
+
+       if (node == sec_node) {
+               /* The secondary timer will drive the clock event */
+               irq = irq_of_parse_and_map(node, 0);
+               integrator_clockevent_init(rate, base, irq);
+               return;
+       }
+
+       pr_info("Timer @%p unused\n", base);
+       clk_disable_unprepare(clk);
+}
+
+CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",
+                      integrator_ap_timer_init_of);
index caf7a20304617f3153b0ea56564d702f2a3c0c42..361a789d4bee9403af6920bb0e6bbb1d22cbe3b5 100644 (file)
@@ -20,8 +20,6 @@
 #include <linux/of_address.h>
 #include <linux/sched_clock.h>
 
-#define MARCO_CLOCK_FREQ 1000000
-
 #define SIRFSOC_TIMER_32COUNTER_0_CTRL                 0x0000
 #define SIRFSOC_TIMER_32COUNTER_1_CTRL                 0x0004
 #define SIRFSOC_TIMER_MATCH_0                          0x0018
@@ -40,6 +38,8 @@
 
 #define SIRFSOC_TIMER_REG_CNT 6
 
+static unsigned long marco_timer_rate;
+
 static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
        SIRFSOC_TIMER_WATCHDOG_EN,
        SIRFSOC_TIMER_32COUNTER_0_CTRL,
@@ -195,7 +195,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
        ce->rating = 200;
        ce->set_mode = sirfsoc_timer_set_mode;
        ce->set_next_event = sirfsoc_timer_set_next_event;
-       clockevents_calc_mult_shift(ce, MARCO_CLOCK_FREQ, 60);
+       clockevents_calc_mult_shift(ce, marco_timer_rate, 60);
        ce->max_delta_ns = clockevent_delta2ns(-2, ce);
        ce->min_delta_ns = clockevent_delta2ns(2, ce);
        ce->cpumask = cpumask_of(cpu);
@@ -257,7 +257,6 @@ static void __init sirfsoc_clockevent_init(void)
 /* initialize the kernel jiffy timer source */
 static void __init sirfsoc_marco_timer_init(struct device_node *np)
 {
-       unsigned long rate;
        u32 timer_div;
        struct clk *clk;
 
@@ -266,16 +265,12 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np)
 
        BUG_ON(clk_prepare_enable(clk));
 
-       rate = clk_get_rate(clk);
-
-       BUG_ON(rate < MARCO_CLOCK_FREQ);
-       BUG_ON(rate % MARCO_CLOCK_FREQ);
+       marco_timer_rate = clk_get_rate(clk);
 
-       /* Initialize the timer dividers */
-       timer_div = rate / MARCO_CLOCK_FREQ - 1;
-       writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
-       writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
-       writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
+       /* timer dividers: 0, not divided */
+       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
+       writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
 
        /* Initialize timer counters to 0 */
        writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
@@ -288,7 +283,7 @@ static void __init sirfsoc_marco_timer_init(struct device_node *np)
        /* Clear all interrupts */
        writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
 
-       BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, MARCO_CLOCK_FREQ));
+       BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, marco_timer_rate));
 
        sirfsoc_clockevent_init();
 }
index 6bbb8b913446bf4ce7131c4fb9448db2ac7721c3..f657c571b18e4e6baaa52250640aac4e1fa26267 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/cpu.h>
 #include <linux/cpu_cooling.h>
 #include <linux/cpufreq.h>
+#include <linux/cpufreq-dt.h>
 #include <linux/cpumask.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -146,8 +147,8 @@ try_again:
                        goto try_again;
                }
 
-               dev_warn(cpu_dev, "failed to get cpu%d regulator: %ld\n",
-                        cpu, PTR_ERR(cpu_reg));
+               dev_dbg(cpu_dev, "no regulator for cpu%d: %ld\n",
+                       cpu, PTR_ERR(cpu_reg));
        }
 
        cpu_clk = clk_get(cpu_dev, NULL);
@@ -165,8 +166,8 @@ try_again:
                if (ret == -EPROBE_DEFER)
                        dev_dbg(cpu_dev, "cpu%d clock not ready, retry\n", cpu);
                else
-                       dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", ret,
-                               cpu);
+                       dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", cpu,
+                               ret);
        } else {
                *cdev = cpu_dev;
                *creg = cpu_reg;
@@ -178,6 +179,7 @@ try_again:
 
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
+       struct cpufreq_dt_platform_data *pd;
        struct cpufreq_frequency_table *freq_table;
        struct thermal_cooling_device *cdev;
        struct device_node *np;
@@ -185,6 +187,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
        struct device *cpu_dev;
        struct regulator *cpu_reg;
        struct clk *cpu_clk;
+       unsigned long min_uV = ~0, max_uV = 0;
        unsigned int transition_latency;
        int ret;
 
@@ -204,16 +207,10 @@ static int cpufreq_init(struct cpufreq_policy *policy)
        /* OPPs might be populated at runtime, don't check for error here */
        of_init_opp_table(cpu_dev);
 
-       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
-       if (ret) {
-               dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
-               goto out_put_node;
-       }
-
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
                ret = -ENOMEM;
-               goto out_free_table;
+               goto out_put_node;
        }
 
        of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
@@ -222,30 +219,51 @@ static int cpufreq_init(struct cpufreq_policy *policy)
                transition_latency = CPUFREQ_ETERNAL;
 
        if (!IS_ERR(cpu_reg)) {
-               struct dev_pm_opp *opp;
-               unsigned long min_uV, max_uV;
-               int i;
+               unsigned long opp_freq = 0;
 
                /*
-                * OPP is maintained in order of increasing frequency, and
-                * freq_table initialised from OPP is therefore sorted in the
-                * same order.
+                * Disable any OPPs where the connected regulator isn't able to
+                * provide the specified voltage and record minimum and maximum
+                * voltage levels.
                 */
-               for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
-                       ;
-               rcu_read_lock();
-               opp = dev_pm_opp_find_freq_exact(cpu_dev,
-                               freq_table[0].frequency * 1000, true);
-               min_uV = dev_pm_opp_get_voltage(opp);
-               opp = dev_pm_opp_find_freq_exact(cpu_dev,
-                               freq_table[i-1].frequency * 1000, true);
-               max_uV = dev_pm_opp_get_voltage(opp);
-               rcu_read_unlock();
+               while (1) {
+                       struct dev_pm_opp *opp;
+                       unsigned long opp_uV, tol_uV;
+
+                       rcu_read_lock();
+                       opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq);
+                       if (IS_ERR(opp)) {
+                               rcu_read_unlock();
+                               break;
+                       }
+                       opp_uV = dev_pm_opp_get_voltage(opp);
+                       rcu_read_unlock();
+
+                       tol_uV = opp_uV * priv->voltage_tolerance / 100;
+                       if (regulator_is_supported_voltage(cpu_reg, opp_uV,
+                                                          opp_uV + tol_uV)) {
+                               if (opp_uV < min_uV)
+                                       min_uV = opp_uV;
+                               if (opp_uV > max_uV)
+                                       max_uV = opp_uV;
+                       } else {
+                               dev_pm_opp_disable(cpu_dev, opp_freq);
+                       }
+
+                       opp_freq++;
+               }
+
                ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
                if (ret > 0)
                        transition_latency += ret * 1000;
        }
 
+       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
+       if (ret) {
+               pr_err("failed to init cpufreq table: %d\n", ret);
+               goto out_free_priv;
+       }
+
        /*
         * For now, just loading the cooling device;
         * thermal DT code takes care of matching them.
@@ -265,9 +283,18 @@ static int cpufreq_init(struct cpufreq_policy *policy)
        policy->driver_data = priv;
 
        policy->clk = cpu_clk;
-       ret = cpufreq_generic_init(policy, freq_table, transition_latency);
-       if (ret)
+       ret = cpufreq_table_validate_and_show(policy, freq_table);
+       if (ret) {
+               dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
+                       ret);
                goto out_cooling_unregister;
+       }
+
+       policy->cpuinfo.transition_latency = transition_latency;
+
+       pd = cpufreq_get_driver_data();
+       if (!pd || !pd->independent_clocks)
+               cpumask_setall(policy->cpus);
 
        of_node_put(np);
 
@@ -275,9 +302,9 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 
 out_cooling_unregister:
        cpufreq_cooling_unregister(priv->cdev);
-       kfree(priv);
-out_free_table:
        dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+out_free_priv:
+       kfree(priv);
 out_put_node:
        of_node_put(np);
 out_put_reg_clk:
@@ -335,6 +362,8 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
        if (!IS_ERR(cpu_reg))
                regulator_put(cpu_reg);
 
+       dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev);
+
        ret = cpufreq_register_driver(&dt_cpufreq_driver);
        if (ret)
                dev_err(cpu_dev, "failed register driver: %d\n", ret);
index 24bf76fba141197eda0c2d4ec24ecbf4311860d1..4473eba1d6b0b6084f632a8cb25e7c7cd815170b 100644 (file)
@@ -512,7 +512,18 @@ show_one(cpuinfo_max_freq, cpuinfo.max_freq);
 show_one(cpuinfo_transition_latency, cpuinfo.transition_latency);
 show_one(scaling_min_freq, min);
 show_one(scaling_max_freq, max);
-show_one(scaling_cur_freq, cur);
+
+static ssize_t show_scaling_cur_freq(
+       struct cpufreq_policy *policy, char *buf)
+{
+       ssize_t ret;
+
+       if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get)
+               ret = sprintf(buf, "%u\n", cpufreq_driver->get(policy->cpu));
+       else
+               ret = sprintf(buf, "%u\n", policy->cur);
+       return ret;
+}
 
 static int cpufreq_set_policy(struct cpufreq_policy *policy,
                                struct cpufreq_policy *new_policy);
@@ -906,11 +917,11 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy,
                if (ret)
                        goto err_out_kobj_put;
        }
-       if (has_target()) {
-               ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
-               if (ret)
-                       goto err_out_kobj_put;
-       }
+
+       ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+       if (ret)
+               goto err_out_kobj_put;
+
        if (cpufreq_driver->bios_limit) {
                ret = sysfs_create_file(&policy->kobj, &bios_limit.attr);
                if (ret)
@@ -1011,7 +1022,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
 
        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-       policy->governor = NULL;
+       if (policy)
+               policy->governor = NULL;
 
        return policy;
 }
@@ -1731,6 +1743,21 @@ const char *cpufreq_get_current_driver(void)
 }
 EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
 
+/**
+ *     cpufreq_get_driver_data - return current driver data
+ *
+ *     Return the private data of the currently loaded cpufreq
+ *     driver, or NULL if no cpufreq driver is loaded.
+ */
+void *cpufreq_get_driver_data(void)
+{
+       if (cpufreq_driver)
+               return cpufreq_driver->driver_data;
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(cpufreq_get_driver_data);
+
 /*********************************************************************
  *                     NOTIFIER LISTS INTERFACE                      *
  *********************************************************************/
index ec399ad2f059379891a4d384e5b24dc3b9c3ab59..1608f7105c9f882c9e787b34a3aa270d9ace75e5 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/of.h>
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
 #include <linux/platform_device.h>
 
 #define HB_CPUFREQ_CHANGE_NOTE 0x80000001
index 0668b389c5165cae8d02e4bedb270b32b8372bde..27bb6d3877ed6cc64ea1fc5bde5c1094a6ab34b0 100644 (file)
@@ -52,6 +52,17 @@ static inline int32_t div_fp(int32_t x, int32_t y)
        return div_s64((int64_t)x << FRAC_BITS, y);
 }
 
+static inline int ceiling_fp(int32_t x)
+{
+       int mask, ret;
+
+       ret = fp_toint(x);
+       mask = (1 << FRAC_BITS) - 1;
+       if (x & mask)
+               ret += 1;
+       return ret;
+}
+
 struct sample {
        int32_t core_pct_busy;
        u64 aperf;
@@ -64,6 +75,7 @@ struct pstate_data {
        int     current_pstate;
        int     min_pstate;
        int     max_pstate;
+       int     scaling;
        int     turbo_pstate;
 };
 
@@ -113,6 +125,7 @@ struct pstate_funcs {
        int (*get_max)(void);
        int (*get_min)(void);
        int (*get_turbo)(void);
+       int (*get_scaling)(void);
        void (*set)(struct cpudata*, int pstate);
        void (*get_vid)(struct cpudata *);
 };
@@ -138,6 +151,7 @@ struct perf_limits {
 
 static struct perf_limits limits = {
        .no_turbo = 0,
+       .turbo_disabled = 0,
        .max_perf_pct = 100,
        .max_perf = int_tofp(1),
        .min_perf_pct = 0,
@@ -218,6 +232,18 @@ static inline void intel_pstate_reset_all_pid(void)
        }
 }
 
+static inline void update_turbo_state(void)
+{
+       u64 misc_en;
+       struct cpudata *cpu;
+
+       cpu = all_cpu_data[0];
+       rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
+       limits.turbo_disabled =
+               (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
+                cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
+}
+
 /************************** debugfs begin ************************/
 static int pid_param_set(void *data, u64 val)
 {
@@ -274,6 +300,20 @@ static void __init intel_pstate_debug_expose_params(void)
                return sprintf(buf, "%u\n", limits.object);             \
        }
 
+static ssize_t show_no_turbo(struct kobject *kobj,
+                            struct attribute *attr, char *buf)
+{
+       ssize_t ret;
+
+       update_turbo_state();
+       if (limits.turbo_disabled)
+               ret = sprintf(buf, "%u\n", limits.turbo_disabled);
+       else
+               ret = sprintf(buf, "%u\n", limits.no_turbo);
+
+       return ret;
+}
+
 static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
                              const char *buf, size_t count)
 {
@@ -283,11 +323,14 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
        ret = sscanf(buf, "%u", &input);
        if (ret != 1)
                return -EINVAL;
-       limits.no_turbo = clamp_t(int, input, 0 , 1);
+
+       update_turbo_state();
        if (limits.turbo_disabled) {
                pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
-               limits.no_turbo = limits.turbo_disabled;
+               return -EPERM;
        }
+       limits.no_turbo = clamp_t(int, input, 0, 1);
+
        return count;
 }
 
@@ -323,7 +366,6 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
        return count;
 }
 
-show_one(no_turbo, no_turbo);
 show_one(max_perf_pct, max_perf_pct);
 show_one(min_perf_pct, min_perf_pct);
 
@@ -394,7 +436,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
                cpudata->vid.ratio);
 
        vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max);
-       vid = fp_toint(vid_fp);
+       vid = ceiling_fp(vid_fp);
 
        if (pstate > cpudata->pstate.max_pstate)
                vid = cpudata->vid.turbo;
@@ -404,6 +446,22 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
        wrmsrl(MSR_IA32_PERF_CTL, val);
 }
 
+#define BYT_BCLK_FREQS 5
+static int byt_freq_table[BYT_BCLK_FREQS] = { 833, 1000, 1333, 1167, 800};
+
+static int byt_get_scaling(void)
+{
+       u64 value;
+       int i;
+
+       rdmsrl(MSR_FSB_FREQ, value);
+       i = value & 0x3;
+
+       BUG_ON(i > BYT_BCLK_FREQS);
+
+       return byt_freq_table[i] * 100;
+}
+
 static void byt_get_vid(struct cpudata *cpudata)
 {
        u64 value;
@@ -449,6 +507,11 @@ static int core_get_turbo_pstate(void)
        return ret;
 }
 
+static inline int core_get_scaling(void)
+{
+       return 100000;
+}
+
 static void core_set_pstate(struct cpudata *cpudata, int pstate)
 {
        u64 val;
@@ -473,6 +536,7 @@ static struct cpu_defaults core_params = {
                .get_max = core_get_max_pstate,
                .get_min = core_get_min_pstate,
                .get_turbo = core_get_turbo_pstate,
+               .get_scaling = core_get_scaling,
                .set = core_set_pstate,
        },
 };
@@ -491,6 +555,7 @@ static struct cpu_defaults byt_params = {
                .get_min = byt_get_min_pstate,
                .get_turbo = byt_get_turbo_pstate,
                .set = byt_set_pstate,
+               .get_scaling = byt_get_scaling,
                .get_vid = byt_get_vid,
        },
 };
@@ -501,7 +566,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
        int max_perf_adj;
        int min_perf;
 
-       if (limits.no_turbo)
+       if (limits.no_turbo || limits.turbo_disabled)
                max_perf = cpu->pstate.max_pstate;
 
        max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf));
@@ -516,6 +581,8 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
 {
        int max_perf, min_perf;
 
+       update_turbo_state();
+
        intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
 
        pstate = clamp_t(int, pstate, min_perf, max_perf);
@@ -523,7 +590,7 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
        if (pstate == cpu->pstate.current_pstate)
                return;
 
-       trace_cpu_frequency(pstate * 100000, cpu->cpu);
+       trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
 
        cpu->pstate.current_pstate = pstate;
 
@@ -535,6 +602,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
        cpu->pstate.min_pstate = pstate_funcs.get_min();
        cpu->pstate.max_pstate = pstate_funcs.get_max();
        cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
+       cpu->pstate.scaling = pstate_funcs.get_scaling();
 
        if (pstate_funcs.get_vid)
                pstate_funcs.get_vid(cpu);
@@ -550,7 +618,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
        core_pct = div64_u64(core_pct, int_tofp(sample->mperf));
 
        sample->freq = fp_toint(
-               mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
+               mul_fp(int_tofp(
+                       cpu->pstate.max_pstate * cpu->pstate.scaling / 100),
+                       core_pct));
 
        sample->core_pct_busy = (int32_t)core_pct;
 }
@@ -671,7 +741,9 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
 {
        struct cpudata *cpu;
 
-       all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata), GFP_KERNEL);
+       if (!all_cpu_data[cpunum])
+               all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata),
+                                              GFP_KERNEL);
        if (!all_cpu_data[cpunum])
                return -ENOMEM;
 
@@ -714,9 +786,10 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
        if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
                limits.min_perf_pct = 100;
                limits.min_perf = int_tofp(1);
+               limits.max_policy_pct = 100;
                limits.max_perf_pct = 100;
                limits.max_perf = int_tofp(1);
-               limits.no_turbo = limits.turbo_disabled;
+               limits.no_turbo = 0;
                return 0;
        }
        limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
@@ -751,15 +824,12 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
 
        del_timer_sync(&all_cpu_data[cpu_num]->timer);
        intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
-       kfree(all_cpu_data[cpu_num]);
-       all_cpu_data[cpu_num] = NULL;
 }
 
 static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpudata *cpu;
        int rc;
-       u64 misc_en;
 
        rc = intel_pstate_init_cpu(policy->cpu);
        if (rc)
@@ -767,23 +837,18 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 
        cpu = all_cpu_data[policy->cpu];
 
-       rdmsrl(MSR_IA32_MISC_ENABLE, misc_en);
-       if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE ||
-           cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) {
-               limits.turbo_disabled = 1;
-               limits.no_turbo = 1;
-       }
        if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100)
                policy->policy = CPUFREQ_POLICY_PERFORMANCE;
        else
                policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
-       policy->min = cpu->pstate.min_pstate * 100000;
-       policy->max = cpu->pstate.turbo_pstate * 100000;
+       policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling;
+       policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
 
        /* cpuinfo and default policy values */
-       policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000;
-       policy->cpuinfo.max_freq = cpu->pstate.turbo_pstate * 100000;
+       policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
+       policy->cpuinfo.max_freq =
+               cpu->pstate.turbo_pstate * cpu->pstate.scaling;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
        cpumask_set_cpu(policy->cpu, policy->cpus);
 
@@ -841,6 +906,7 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs)
        pstate_funcs.get_max   = funcs->get_max;
        pstate_funcs.get_min   = funcs->get_min;
        pstate_funcs.get_turbo = funcs->get_turbo;
+       pstate_funcs.get_scaling = funcs->get_scaling;
        pstate_funcs.set       = funcs->set;
        pstate_funcs.get_vid   = funcs->get_vid;
 }
index 0e70ee28a5ca10f1690215b7de21ca5800d8681a..4102be01d06a03db5d98f91473b0083db81158d7 100644 (file)
@@ -3,7 +3,7 @@
 #
 config MIPS_CPS_CPUIDLE
        bool "CPU Idle driver for MIPS CPS platforms"
-       depends on CPU_IDLE
+       depends on CPU_IDLE && MIPS_CPS
        depends on SYS_SUPPORTS_MIPS_CPS
        select ARCH_NEEDS_CPU_IDLE_COUPLED if MIPS_MT
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
index a64be578dab2e30d75d06989385f9fd03c55ba03..7d3a3497dd4cfeef09f7d4fbaf88ecace4c4c5bf 100644 (file)
@@ -163,7 +163,8 @@ static int powernv_add_idle_states(void)
        int nr_idle_states = 1; /* Snooze */
        int dt_idle_states;
        const __be32 *idle_state_flags;
-       u32 len_flags, flags;
+       const __be32 *idle_state_latency;
+       u32 len_flags, flags, latency_ns;
        int i;
 
        /* Currently we have snooze statically defined */
@@ -180,18 +181,32 @@ static int powernv_add_idle_states(void)
                return nr_idle_states;
        }
 
+       idle_state_latency = of_get_property(power_mgt,
+                       "ibm,cpu-idle-state-latencies-ns", NULL);
+       if (!idle_state_latency) {
+               pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-latencies-ns\n");
+               return nr_idle_states;
+       }
+
        dt_idle_states = len_flags / sizeof(u32);
 
        for (i = 0; i < dt_idle_states; i++) {
 
                flags = be32_to_cpu(idle_state_flags[i]);
+
+               /* Cpuidle accepts exit_latency in us and we estimate
+                * target residency to be 10x exit_latency
+                */
+               latency_ns = be32_to_cpu(idle_state_latency[i]);
                if (flags & IDLE_USE_INST_NAP) {
                        /* Add NAP state */
                        strcpy(powernv_states[nr_idle_states].name, "Nap");
                        strcpy(powernv_states[nr_idle_states].desc, "Nap");
                        powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIME_VALID;
-                       powernv_states[nr_idle_states].exit_latency = 10;
-                       powernv_states[nr_idle_states].target_residency = 100;
+                       powernv_states[nr_idle_states].exit_latency =
+                                       ((unsigned int)latency_ns) / 1000;
+                       powernv_states[nr_idle_states].target_residency =
+                                       ((unsigned int)latency_ns / 100);
                        powernv_states[nr_idle_states].enter = &nap_loop;
                        nr_idle_states++;
                }
@@ -202,8 +217,10 @@ static int powernv_add_idle_states(void)
                        strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
                        powernv_states[nr_idle_states].flags =
                                CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TIMER_STOP;
-                       powernv_states[nr_idle_states].exit_latency = 300;
-                       powernv_states[nr_idle_states].target_residency = 1000000;
+                       powernv_states[nr_idle_states].exit_latency =
+                                       ((unsigned int)latency_ns) / 1000;
+                       powernv_states[nr_idle_states].target_residency =
+                                       ((unsigned int)latency_ns / 100);
                        powernv_states[nr_idle_states].enter = &fastsleep_loop;
                        nr_idle_states++;
                }
index 871703c49d2c09923d162af7651518d46a5ff3a4..e1eaf4ff9762646acac020c85c77bb122c570f0e 100644 (file)
@@ -48,23 +48,29 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
        u32 *desc;
        struct split_key_result result;
        dma_addr_t dma_addr_in, dma_addr_out;
-       int ret = 0;
+       int ret = -ENOMEM;
 
        desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
        if (!desc) {
                dev_err(jrdev, "unable to allocate key input memory\n");
-               return -ENOMEM;
+               return ret;
        }
 
-       init_job_desc(desc, 0);
-
        dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen,
                                     DMA_TO_DEVICE);
        if (dma_mapping_error(jrdev, dma_addr_in)) {
                dev_err(jrdev, "unable to map key input memory\n");
-               kfree(desc);
-               return -ENOMEM;
+               goto out_free;
        }
+
+       dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len,
+                                     DMA_FROM_DEVICE);
+       if (dma_mapping_error(jrdev, dma_addr_out)) {
+               dev_err(jrdev, "unable to map key output memory\n");
+               goto out_unmap_in;
+       }
+
+       init_job_desc(desc, 0);
        append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
 
        /* Sets MDHA up into an HMAC-INIT */
@@ -81,13 +87,6 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
         * FIFO_STORE with the explicit split-key content store
         * (0x26 output type)
         */
-       dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len,
-                                     DMA_FROM_DEVICE);
-       if (dma_mapping_error(jrdev, dma_addr_out)) {
-               dev_err(jrdev, "unable to map key output memory\n");
-               kfree(desc);
-               return -ENOMEM;
-       }
        append_fifo_store(desc, dma_addr_out, split_key_len,
                          LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
 
@@ -115,10 +114,10 @@ int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
 
        dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len,
                         DMA_FROM_DEVICE);
+out_unmap_in:
        dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE);
-
+out_free:
        kfree(desc);
-
        return ret;
 }
 EXPORT_SYMBOL(gen_split_key);
index 9282381b03ced19b0e890a10e51421224276be69..fe7b3f06f6e62ac9ab1e35a9bfb6a2c3f267c35a 100644 (file)
@@ -198,8 +198,7 @@ struct adf_accel_dev {
        struct dentry *debugfs_dir;
        struct list_head list;
        struct module *owner;
-       uint8_t accel_id;
-       uint8_t numa_node;
        struct adf_accel_pci accel_pci_dev;
+       uint8_t accel_id;
 } __packed;
 #endif
index 5f3fa45348b46c6c5f22093c7e5426ac43c4ec6d..9dd2cb72a4e862e8203b9a0ffdc109ce4480c0be 100644 (file)
@@ -419,9 +419,10 @@ static int adf_init_bank(struct adf_accel_dev *accel_dev,
                WRITE_CSR_RING_BASE(csr_addr, bank_num, i, 0);
                ring = &bank->rings[i];
                if (hw_data->tx_rings_mask & (1 << i)) {
-                       ring->inflights = kzalloc_node(sizeof(atomic_t),
-                                                      GFP_KERNEL,
-                                                      accel_dev->numa_node);
+                       ring->inflights =
+                               kzalloc_node(sizeof(atomic_t),
+                                            GFP_KERNEL,
+                                            dev_to_node(&GET_DEV(accel_dev)));
                        if (!ring->inflights)
                                goto err;
                } else {
@@ -469,13 +470,14 @@ int adf_init_etr_data(struct adf_accel_dev *accel_dev)
        int i, ret;
 
        etr_data = kzalloc_node(sizeof(*etr_data), GFP_KERNEL,
-                               accel_dev->numa_node);
+                               dev_to_node(&GET_DEV(accel_dev)));
        if (!etr_data)
                return -ENOMEM;
 
        num_banks = GET_MAX_BANKS(accel_dev);
        size = num_banks * sizeof(struct adf_etr_bank_data);
-       etr_data->banks = kzalloc_node(size, GFP_KERNEL, accel_dev->numa_node);
+       etr_data->banks = kzalloc_node(size, GFP_KERNEL,
+                                      dev_to_node(&GET_DEV(accel_dev)));
        if (!etr_data->banks) {
                ret = -ENOMEM;
                goto err_bank;
index f2e2f158cfbecec1bbef49a5b061d824c2365b3e..9e9619cd4a79b958dae8e6ceee84d0d267325322 100644 (file)
@@ -596,7 +596,8 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
        if (unlikely(!n))
                return -EINVAL;
 
-       bufl = kmalloc_node(sz, GFP_ATOMIC, inst->accel_dev->numa_node);
+       bufl = kmalloc_node(sz, GFP_ATOMIC,
+                           dev_to_node(&GET_DEV(inst->accel_dev)));
        if (unlikely(!bufl))
                return -ENOMEM;
 
@@ -605,6 +606,8 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
                goto err;
 
        for_each_sg(assoc, sg, assoc_n, i) {
+               if (!sg->length)
+                       continue;
                bufl->bufers[bufs].addr = dma_map_single(dev,
                                                         sg_virt(sg),
                                                         sg->length,
@@ -640,7 +643,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,
                struct qat_alg_buf *bufers;
 
                buflout = kmalloc_node(sz, GFP_ATOMIC,
-                                      inst->accel_dev->numa_node);
+                                      dev_to_node(&GET_DEV(inst->accel_dev)));
                if (unlikely(!buflout))
                        goto err;
                bloutp = dma_map_single(dev, buflout, sz, DMA_TO_DEVICE);
index 0d59bcb50de151c9355705ff39d18b9f600eb313..828f2a686aab26d474592829de8ac47f8f83c4fe 100644 (file)
@@ -109,12 +109,14 @@ struct qat_crypto_instance *qat_crypto_get_instance_node(int node)
 
        list_for_each(itr, adf_devmgr_get_head()) {
                accel_dev = list_entry(itr, struct adf_accel_dev, list);
-               if (accel_dev->numa_node == node && adf_dev_started(accel_dev))
+               if ((node == dev_to_node(&GET_DEV(accel_dev)) ||
+                       dev_to_node(&GET_DEV(accel_dev)) < 0)
+                               && adf_dev_started(accel_dev))
                        break;
                accel_dev = NULL;
        }
        if (!accel_dev) {
-               pr_err("QAT: Could not find device on give node\n");
+               pr_err("QAT: Could not find device on node %d\n", node);
                accel_dev = adf_devmgr_get_first();
        }
        if (!accel_dev || !adf_dev_started(accel_dev))
@@ -164,7 +166,7 @@ static int qat_crypto_create_instances(struct adf_accel_dev *accel_dev)
 
        for (i = 0; i < num_inst; i++) {
                inst = kzalloc_node(sizeof(*inst), GFP_KERNEL,
-                                   accel_dev->numa_node);
+                                   dev_to_node(&GET_DEV(accel_dev)));
                if (!inst)
                        goto err;
 
index 978d6c56639df105ffce07b9037d0556329c02c6..53c491b59f07c59ec9b4264b215078a8fe368be8 100644 (file)
@@ -108,7 +108,7 @@ int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
        uint64_t reg_val;
 
        admin = kzalloc_node(sizeof(*accel_dev->admin), GFP_KERNEL,
-                            accel_dev->numa_node);
+                            dev_to_node(&GET_DEV(accel_dev)));
        if (!admin)
                return -ENOMEM;
        admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
index 0d0435a41be996d239517e3325a36631802bb9d2..948f66be262b31eeeb51418696a3e482eb82736c 100644 (file)
@@ -119,21 +119,6 @@ static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
        kfree(accel_dev);
 }
 
-static uint8_t adf_get_dev_node_id(struct pci_dev *pdev)
-{
-       unsigned int bus_per_cpu = 0;
-       struct cpuinfo_x86 *c = &cpu_data(num_online_cpus() - 1);
-
-       if (!c->phys_proc_id)
-               return 0;
-
-       bus_per_cpu = 256 / (c->phys_proc_id + 1);
-
-       if (bus_per_cpu != 0)
-               return pdev->bus->number / bus_per_cpu;
-       return 0;
-}
-
 static int qat_dev_start(struct adf_accel_dev *accel_dev)
 {
        int cpus = num_online_cpus();
@@ -235,7 +220,6 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        void __iomem *pmisc_bar_addr = NULL;
        char name[ADF_DEVICE_NAME_LENGTH];
        unsigned int i, bar_nr;
-       uint8_t node;
        int ret;
 
        switch (ent->device) {
@@ -246,12 +230,19 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
-       node = adf_get_dev_node_id(pdev);
-       accel_dev = kzalloc_node(sizeof(*accel_dev), GFP_KERNEL, node);
+       if (num_possible_nodes() > 1 && dev_to_node(&pdev->dev) < 0) {
+               /* If the accelerator is connected to a node with no memory
+                * there is no point in using the accelerator since the remote
+                * memory transaction will be very slow. */
+               dev_err(&pdev->dev, "Invalid NUMA configuration.\n");
+               return -EINVAL;
+       }
+
+       accel_dev = kzalloc_node(sizeof(*accel_dev), GFP_KERNEL,
+                                dev_to_node(&pdev->dev));
        if (!accel_dev)
                return -ENOMEM;
 
-       accel_dev->numa_node = node;
        INIT_LIST_HEAD(&accel_dev->crypto_list);
 
        /* Add accel device to accel table.
@@ -264,7 +255,8 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        accel_dev->owner = THIS_MODULE;
        /* Allocate and configure device configuration structure */
-       hw_data = kzalloc_node(sizeof(*hw_data), GFP_KERNEL, node);
+       hw_data = kzalloc_node(sizeof(*hw_data), GFP_KERNEL,
+                              dev_to_node(&pdev->dev));
        if (!hw_data) {
                ret = -ENOMEM;
                goto out_err;
index 67ec61e51185b3e402da164d0c15b4b464d53ec6..d96ee21b9b77815f8ed018a78a36d43db7fc3c95 100644 (file)
@@ -168,7 +168,7 @@ static int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev)
        uint32_t msix_num_entries = hw_data->num_banks + 1;
 
        entries = kzalloc_node(msix_num_entries * sizeof(*entries),
-                              GFP_KERNEL, accel_dev->numa_node);
+                              GFP_KERNEL, dev_to_node(&GET_DEV(accel_dev)));
        if (!entries)
                return -ENOMEM;
 
index 123f578d6dd3b82d37887182fc092937c40e59d4..4cfaaa5a49bec6655b0e6588bae04503a82f17bc 100644 (file)
@@ -1107,52 +1107,14 @@ bool edma_filter_fn(struct dma_chan *chan, void *param)
 }
 EXPORT_SYMBOL(edma_filter_fn);
 
-static struct platform_device *pdev0, *pdev1;
-
-static const struct platform_device_info edma_dev_info0 = {
-       .name = "edma-dma-engine",
-       .id = 0,
-       .dma_mask = DMA_BIT_MASK(32),
-};
-
-static const struct platform_device_info edma_dev_info1 = {
-       .name = "edma-dma-engine",
-       .id = 1,
-       .dma_mask = DMA_BIT_MASK(32),
-};
-
 static int edma_init(void)
 {
-       int ret = platform_driver_register(&edma_driver);
-
-       if (ret == 0) {
-               pdev0 = platform_device_register_full(&edma_dev_info0);
-               if (IS_ERR(pdev0)) {
-                       platform_driver_unregister(&edma_driver);
-                       ret = PTR_ERR(pdev0);
-                       goto out;
-               }
-       }
-
-       if (!of_have_populated_dt() && EDMA_CTLRS == 2) {
-               pdev1 = platform_device_register_full(&edma_dev_info1);
-               if (IS_ERR(pdev1)) {
-                       platform_driver_unregister(&edma_driver);
-                       platform_device_unregister(pdev0);
-                       ret = PTR_ERR(pdev1);
-               }
-       }
-
-out:
-       return ret;
+       return platform_driver_register(&edma_driver);
 }
 subsys_initcall(edma_init);
 
 static void __exit edma_exit(void)
 {
-       platform_device_unregister(pdev0);
-       if (pdev1)
-               platform_device_unregister(pdev1);
        platform_driver_unregister(&edma_driver);
 }
 module_exit(edma_exit);
index 4839bfa74a107a1ad4cbdfb09017d86da1fd1a41..19a99743cf524670d5906400d286cc877bcf91d6 100644 (file)
@@ -271,7 +271,7 @@ struct pl330_config {
 #define DMAC_MODE_NS   (1 << 0)
        unsigned int    mode;
        unsigned int    data_bus_width:10; /* In number of bits */
-       unsigned int    data_buf_dep:10;
+       unsigned int    data_buf_dep:11;
        unsigned int    num_chan:4;
        unsigned int    num_peri:6;
        u32             peri_ns;
@@ -2336,7 +2336,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
        int burst_len;
 
        burst_len = pl330->pcfg.data_bus_width / 8;
-       burst_len *= pl330->pcfg.data_buf_dep;
+       burst_len *= pl330->pcfg.data_buf_dep / pl330->pcfg.num_chan;
        burst_len >>= desc->rqcfg.brst_size;
 
        /* src/dst_burst_len can't be more than 16 */
@@ -2459,16 +2459,25 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
        /* Select max possible burst size */
        burst = pl330->pcfg.data_bus_width / 8;
 
-       while (burst > 1) {
-               if (!(len % burst))
-                       break;
+       /*
+        * Make sure we use a burst size that aligns with all the memcpy
+        * parameters because our DMA programming algorithm doesn't cope with
+        * transfers which straddle an entry in the DMA device's MFIFO.
+        */
+       while ((src | dst | len) & (burst - 1))
                burst /= 2;
-       }
 
        desc->rqcfg.brst_size = 0;
        while (burst != (1 << desc->rqcfg.brst_size))
                desc->rqcfg.brst_size++;
 
+       /*
+        * If burst size is smaller than bus width then make sure we only
+        * transfer one at a time to avoid a burst stradling an MFIFO entry.
+        */
+       if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width)
+               desc->rqcfg.brst_len = 1;
+
        desc->rqcfg.brst_len = get_burst_len(desc, len);
 
        desc->txd.flags = flags;
@@ -2732,7 +2741,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 
 
        dev_info(&adev->dev,
-               "Loaded driver for PL330 DMAC-%d\n", adev->periphid);
+               "Loaded driver for PL330 DMAC-%x\n", adev->periphid);
        dev_info(&adev->dev,
                "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n",
                pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
index 3aa10b32825491dce9d5c0ad244ddc53f78df12e..91292f5513ff2df6d051b784fcb81d276f6e6c63 100644 (file)
@@ -230,30 +230,25 @@ static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev,
                readl(pchan->base + DMA_CHAN_CUR_PARA));
 }
 
-static inline int convert_burst(u32 maxburst, u8 *burst)
+static inline s8 convert_burst(u32 maxburst)
 {
        switch (maxburst) {
        case 1:
-               *burst = 0;
-               break;
+               return 0;
        case 8:
-               *burst = 2;
-               break;
+               return 2;
        default:
                return -EINVAL;
        }
-
-       return 0;
 }
 
-static inline int convert_buswidth(enum dma_slave_buswidth addr_width, u8 *width)
+static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
        if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
            (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
                return -EINVAL;
 
-       *width = addr_width >> 1;
-       return 0;
+       return addr_width >> 1;
 }
 
 static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev,
@@ -284,26 +279,25 @@ static inline int sun6i_dma_cfg_lli(struct sun6i_dma_lli *lli,
                                    struct dma_slave_config *config)
 {
        u8 src_width, dst_width, src_burst, dst_burst;
-       int ret;
 
        if (!config)
                return -EINVAL;
 
-       ret = convert_burst(config->src_maxburst, &src_burst);
-       if (ret)
-               return ret;
+       src_burst = convert_burst(config->src_maxburst);
+       if (src_burst)
+               return src_burst;
 
-       ret = convert_burst(config->dst_maxburst, &dst_burst);
-       if (ret)
-               return ret;
+       dst_burst = convert_burst(config->dst_maxburst);
+       if (dst_burst)
+               return dst_burst;
 
-       ret = convert_buswidth(config->src_addr_width, &src_width);
-       if (ret)
-               return ret;
+       src_width = convert_buswidth(config->src_addr_width);
+       if (src_width)
+               return src_width;
 
-       ret = convert_buswidth(config->dst_addr_width, &dst_width);
-       if (ret)
-               return ret;
+       dst_width = convert_buswidth(config->dst_addr_width);
+       if (dst_width)
+               return dst_width;
 
        lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
                DMA_CHAN_CFG_SRC_WIDTH(src_width) |
@@ -542,11 +536,10 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
 {
        struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
        struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
-       struct dma_slave_config *sconfig = &vchan->cfg;
        struct sun6i_dma_lli *v_lli;
        struct sun6i_desc *txd;
        dma_addr_t p_lli;
-       int ret;
+       s8 burst, width;
 
        dev_dbg(chan2dev(chan),
                "%s; chan: %d, dest: %pad, src: %pad, len: %zu. flags: 0x%08lx\n",
@@ -565,14 +558,21 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
                goto err_txd_free;
        }
 
-       ret = sun6i_dma_cfg_lli(v_lli, src, dest, len, sconfig);
-       if (ret)
-               goto err_dma_free;
+       v_lli->src = src;
+       v_lli->dst = dest;
+       v_lli->len = len;
+       v_lli->para = NORMAL_WAIT;
 
+       burst = convert_burst(8);
+       width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES);
        v_lli->cfg |= DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
                DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
                DMA_CHAN_CFG_DST_LINEAR_MODE |
-               DMA_CHAN_CFG_SRC_LINEAR_MODE;
+               DMA_CHAN_CFG_SRC_LINEAR_MODE |
+               DMA_CHAN_CFG_SRC_BURST(burst) |
+               DMA_CHAN_CFG_SRC_WIDTH(width) |
+               DMA_CHAN_CFG_DST_BURST(burst) |
+               DMA_CHAN_CFG_DST_WIDTH(width);
 
        sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
@@ -580,8 +580,6 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
 
        return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
 
-err_dma_free:
-       dma_pool_free(sdev->pool, v_lli, p_lli);
 err_txd_free:
        kfree(txd);
        return NULL;
@@ -915,6 +913,7 @@ static int sun6i_dma_probe(struct platform_device *pdev)
        sdc->slave.device_prep_dma_memcpy       = sun6i_dma_prep_dma_memcpy;
        sdc->slave.device_control               = sun6i_dma_control;
        sdc->slave.chancnt                      = NR_MAX_VCHANS;
+       sdc->slave.copy_align                   = 4;
 
        sdc->slave.dev = &pdev->dev;
 
index 7072c2892d633eb72dbea1bcea973a09eae68e30..49c265255a07fb15985d5743722de7c0a932220f 100644 (file)
@@ -61,14 +61,14 @@ config EDAC_DECODE_MCE
          has been initialized.
 
 config EDAC_MCE_INJ
-       tristate "Simple MCE injection interface over /sysfs"
-       depends on EDAC_DECODE_MCE
+       tristate "Simple MCE injection interface"
+       depends on EDAC_DECODE_MCE && DEBUG_FS
        default n
        help
-         This is a simple interface to inject MCEs over /sysfs and test
-         the MCE decoding code in EDAC.
+         This is a simple debugfs interface to inject MCEs and test different
+         aspects of the MCE handling code.
 
-         This is currently AMD-only.
+         WARNING: Do not even assume this interface is staying stable!
 
 config EDAC_MM_EDAC
        tristate "Main Memory EDAC (Error Detection And Correction) reporting"
@@ -105,11 +105,11 @@ config EDAC_GHES
          In doubt, say 'Y'.
 
 config EDAC_AMD64
-       tristate "AMD64 (Opteron, Athlon64) K8, F10h"
-       depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
+       tristate "AMD64 (Opteron, Athlon64)"
+       depends on EDAC_MM_EDAC && AMD_NB && EDAC_DECODE_MCE
        help
          Support for error detection and correction of DRAM ECC errors on
-         the AMD64 families of memory controllers (K8 and F10h)
+         the AMD64 families (>= K8) of memory controllers.
 
 config EDAC_AMD64_ERROR_INJECTION
        bool "Sysfs HW Error injection facilities"
index 359aa499b200d0f8bdd50c0532345dbaf7324956..d40c69a04df7dbf405fad20bc302a2491e91d827 100644 (file)
@@ -9,7 +9,7 @@
 obj-$(CONFIG_EDAC)                     := edac_stub.o
 obj-$(CONFIG_EDAC_MM_EDAC)             += edac_core.o
 
-edac_core-y    := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
+edac_core-y    := edac_mc.o edac_device.o edac_mc_sysfs.o
 edac_core-y    += edac_module.o edac_device_sysfs.o
 
 ifdef CONFIG_PCI
index bbd65149cdb230c3b250a551622849cb9a85cee2..17638d7cf5c279a3b2fd63aa2250939a8c059388 100644 (file)
@@ -692,9 +692,19 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 {
        edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr);
 
-       edac_dbg(1, "  DIMM type: %sbuffered; all DIMMs support ECC: %s\n",
-                (dclr & BIT(16)) ?  "un" : "",
-                (dclr & BIT(19)) ? "yes" : "no");
+       if (pvt->dram_type == MEM_LRDDR3) {
+               u32 dcsm = pvt->csels[chan].csmasks[0];
+               /*
+                * It's assumed all LRDIMMs in a DCT are going to be of
+                * same 'type' until proven otherwise. So, use a cs
+                * value of '0' here to get dcsm value.
+                */
+               edac_dbg(1, " LRDIMM %dx rank multiply\n", (dcsm & 0x3));
+       }
+
+       edac_dbg(1, "All DIMMs support ECC:%s\n",
+                   (dclr & BIT(19)) ? "yes" : "no");
+
 
        edac_dbg(1, "  PAR/ERR parity: %s\n",
                 (dclr & BIT(8)) ?  "enabled" : "disabled");
@@ -756,7 +766,7 @@ static void prep_chip_selects(struct amd64_pvt *pvt)
        if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) {
                pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
                pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8;
-       } else if (pvt->fam == 0x15 && pvt->model >= 0x30) {
+       } else if (pvt->fam == 0x15 && pvt->model == 0x30) {
                pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4;
                pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2;
        } else {
@@ -813,25 +823,63 @@ static void read_dct_base_mask(struct amd64_pvt *pvt)
        }
 }
 
-static enum mem_type determine_memory_type(struct amd64_pvt *pvt, int cs)
+static void determine_memory_type(struct amd64_pvt *pvt)
 {
-       enum mem_type type;
+       u32 dram_ctrl, dcsm;
 
-       /* F15h supports only DDR3 */
-       if (pvt->fam >= 0x15)
-               type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3;
-       else if (pvt->fam == 0x10 || pvt->ext_model >= K8_REV_F) {
+       switch (pvt->fam) {
+       case 0xf:
+               if (pvt->ext_model >= K8_REV_F)
+                       goto ddr3;
+
+               pvt->dram_type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR;
+               return;
+
+       case 0x10:
                if (pvt->dchr0 & DDR3_MODE)
-                       type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3;
+                       goto ddr3;
+
+               pvt->dram_type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2;
+               return;
+
+       case 0x15:
+               if (pvt->model < 0x60)
+                       goto ddr3;
+
+               /*
+                * Model 0x60h needs special handling:
+                *
+                * We use a Chip Select value of '0' to obtain dcsm.
+                * Theoretically, it is possible to populate LRDIMMs of different
+                * 'Rank' value on a DCT. But this is not the common case. So,
+                * it's reasonable to assume all DIMMs are going to be of same
+                * 'type' until proven otherwise.
+                */
+               amd64_read_dct_pci_cfg(pvt, 0, DRAM_CONTROL, &dram_ctrl);
+               dcsm = pvt->csels[0].csmasks[0];
+
+               if (((dram_ctrl >> 8) & 0x7) == 0x2)
+                       pvt->dram_type = MEM_DDR4;
+               else if (pvt->dclr0 & BIT(16))
+                       pvt->dram_type = MEM_DDR3;
+               else if (dcsm & 0x3)
+                       pvt->dram_type = MEM_LRDDR3;
                else
-                       type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2;
-       } else {
-               type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR;
-       }
+                       pvt->dram_type = MEM_RDDR3;
 
-       amd64_info("CS%d: %s\n", cs, edac_mem_types[type]);
+               return;
 
-       return type;
+       case 0x16:
+               goto ddr3;
+
+       default:
+               WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam);
+               pvt->dram_type = MEM_EMPTY;
+       }
+       return;
+
+ddr3:
+       pvt->dram_type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3;
 }
 
 /* Get the number of DCT channels the memory controller is using. */
@@ -958,8 +1006,12 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
        if (WARN_ON(!nb))
                return;
 
-       pci_func = (pvt->model == 0x30) ? PCI_DEVICE_ID_AMD_15H_M30H_NB_F1
-                                       : PCI_DEVICE_ID_AMD_15H_NB_F1;
+       if (pvt->model == 0x60)
+               pci_func = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1;
+       else if (pvt->model == 0x30)
+               pci_func = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1;
+       else
+               pci_func = PCI_DEVICE_ID_AMD_15H_NB_F1;
 
        f1 = pci_get_related_function(nb->misc->vendor, pci_func, nb->misc);
        if (WARN_ON(!f1))
@@ -1049,7 +1101,7 @@ static int ddr2_cs_size(unsigned i, bool dct_width)
 }
 
 static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
-                                 unsigned cs_mode)
+                                 unsigned cs_mode, int cs_mask_nr)
 {
        u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
 
@@ -1167,8 +1219,43 @@ static int ddr3_cs_size(unsigned i, bool dct_width)
        return cs_size;
 }
 
+static int ddr3_lrdimm_cs_size(unsigned i, unsigned rank_multiply)
+{
+       unsigned shift = 0;
+       int cs_size = 0;
+
+       if (i < 4 || i == 6)
+               cs_size = -1;
+       else if (i == 12)
+               shift = 7;
+       else if (!(i & 0x1))
+               shift = i >> 1;
+       else
+               shift = (i + 1) >> 1;
+
+       if (cs_size != -1)
+               cs_size = rank_multiply * (128 << shift);
+
+       return cs_size;
+}
+
+static int ddr4_cs_size(unsigned i)
+{
+       int cs_size = 0;
+
+       if (i == 0)
+               cs_size = -1;
+       else if (i == 1)
+               cs_size = 1024;
+       else
+               /* Min cs_size = 1G */
+               cs_size = 1024 * (1 << (i >> 1));
+
+       return cs_size;
+}
+
 static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
-                                  unsigned cs_mode)
+                                  unsigned cs_mode, int cs_mask_nr)
 {
        u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
 
@@ -1184,18 +1271,49 @@ static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
  * F15h supports only 64bit DCT interfaces
  */
 static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
-                                  unsigned cs_mode)
+                                  unsigned cs_mode, int cs_mask_nr)
 {
        WARN_ON(cs_mode > 12);
 
        return ddr3_cs_size(cs_mode, false);
 }
 
+/* F15h M60h supports DDR4 mapping as well.. */
+static int f15_m60h_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
+                                       unsigned cs_mode, int cs_mask_nr)
+{
+       int cs_size;
+       u32 dcsm = pvt->csels[dct].csmasks[cs_mask_nr];
+
+       WARN_ON(cs_mode > 12);
+
+       if (pvt->dram_type == MEM_DDR4) {
+               if (cs_mode > 9)
+                       return -1;
+
+               cs_size = ddr4_cs_size(cs_mode);
+       } else if (pvt->dram_type == MEM_LRDDR3) {
+               unsigned rank_multiply = dcsm & 0xf;
+
+               if (rank_multiply == 3)
+                       rank_multiply = 4;
+               cs_size = ddr3_lrdimm_cs_size(cs_mode, rank_multiply);
+       } else {
+               /* Minimum cs size is 512mb for F15hM60h*/
+               if (cs_mode == 0x1)
+                       return -1;
+
+               cs_size = ddr3_cs_size(cs_mode, false);
+       }
+
+       return cs_size;
+}
+
 /*
  * F16h and F15h model 30h have only limited cs_modes.
  */
 static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
-                               unsigned cs_mode)
+                               unsigned cs_mode, int cs_mask_nr)
 {
        WARN_ON(cs_mode > 12);
 
@@ -1757,13 +1875,20 @@ static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 
                size0 = 0;
                if (dcsb[dimm*2] & DCSB_CS_ENABLE)
+                       /* For f15m60h, need multiplier for LRDIMM cs_size
+                        * calculation. We pass 'dimm' value to the dbam_to_cs
+                        * mapper so we can find the multiplier from the
+                        * corresponding DCSM.
+                        */
                        size0 = pvt->ops->dbam_to_cs(pvt, ctrl,
-                                                    DBAM_DIMM(dimm, dbam));
+                                                    DBAM_DIMM(dimm, dbam),
+                                                    dimm);
 
                size1 = 0;
                if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
                        size1 = pvt->ops->dbam_to_cs(pvt, ctrl,
-                                                    DBAM_DIMM(dimm, dbam));
+                                                    DBAM_DIMM(dimm, dbam),
+                                                    dimm);
 
                amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
                                dimm * 2,     size0,
@@ -1812,6 +1937,16 @@ static struct amd64_family_type family_types[] = {
                        .dbam_to_cs             = f16_dbam_to_chip_select,
                }
        },
+       [F15_M60H_CPUS] = {
+               .ctl_name = "F15h_M60h",
+               .f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1,
+               .f3_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F3,
+               .ops = {
+                       .early_channel_count    = f1x_early_channel_count,
+                       .map_sysaddr_to_csrow   = f1x_map_sysaddr_to_csrow,
+                       .dbam_to_cs             = f15_m60h_dbam_to_chip_select,
+               }
+       },
        [F16_CPUS] = {
                .ctl_name = "F16h",
                .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1,
@@ -2175,6 +2310,8 @@ static void read_mc_regs(struct amd64_pvt *pvt)
        }
 
        pvt->ecc_sym_sz = 4;
+       determine_memory_type(pvt);
+       edac_dbg(1, "  DIMM type: %s\n", edac_mem_types[pvt->dram_type]);
 
        if (pvt->fam >= 0x10) {
                amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
@@ -2238,7 +2375,8 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
         */
        cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
 
-       nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);
+       nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
+                                                          << (20 - PAGE_SHIFT);
 
        edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
                    csrow_nr, dct,  cs_mode);
@@ -2257,7 +2395,6 @@ static int init_csrows(struct mem_ctl_info *mci)
        struct csrow_info *csrow;
        struct dimm_info *dimm;
        enum edac_type edac_mode;
-       enum mem_type mtype;
        int i, j, empty = 1;
        int nr_pages = 0;
        u32 val;
@@ -2302,8 +2439,6 @@ static int init_csrows(struct mem_ctl_info *mci)
                        nr_pages += row_dct1_pages;
                }
 
-               mtype = determine_memory_type(pvt, i);
-
                edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
 
                /*
@@ -2317,7 +2452,7 @@ static int init_csrows(struct mem_ctl_info *mci)
 
                for (j = 0; j < pvt->channel_count; j++) {
                        dimm = csrow->channels[j]->dimm;
-                       dimm->mtype = mtype;
+                       dimm->mtype = pvt->dram_type;
                        dimm->edac_mode = edac_mode;
                }
        }
@@ -2604,6 +2739,10 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
                        fam_type = &family_types[F15_M30H_CPUS];
                        pvt->ops = &family_types[F15_M30H_CPUS].ops;
                        break;
+               } else if (pvt->model == 0x60) {
+                       fam_type = &family_types[F15_M60H_CPUS];
+                       pvt->ops = &family_types[F15_M60H_CPUS].ops;
+                       break;
                }
 
                fam_type        = &family_types[F15_CPUS];
@@ -2828,55 +2967,13 @@ static void remove_one_instance(struct pci_dev *pdev)
  * inquiry this table to see if this driver is for a given device found.
  */
 static const struct pci_device_id amd64_pci_table[] = {
-       {
-               .vendor         = PCI_VENDOR_ID_AMD,
-               .device         = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .class          = 0,
-               .class_mask     = 0,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_AMD,
-               .device         = PCI_DEVICE_ID_AMD_10H_NB_DRAM,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .class          = 0,
-               .class_mask     = 0,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_AMD,
-               .device         = PCI_DEVICE_ID_AMD_15H_NB_F2,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .class          = 0,
-               .class_mask     = 0,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_AMD,
-               .device         = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .class          = 0,
-               .class_mask     = 0,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_AMD,
-               .device         = PCI_DEVICE_ID_AMD_16H_NB_F2,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .class          = 0,
-               .class_mask     = 0,
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_AMD,
-               .device         = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .class          = 0,
-               .class_mask     = 0,
-       },
-
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F2) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F2) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F2) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F2) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F2) },
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, amd64_pci_table);
@@ -2938,6 +3035,11 @@ static int __init amd64_edac_init(void)
                goto err_no_instances;
 
        setup_pci_device();
+
+#ifdef CONFIG_X86_32
+       amd64_err("%s on 32-bit is unsupported. USE AT YOUR OWN RISK!\n", EDAC_MOD_STR);
+#endif
+
        return 0;
 
 err_no_instances:
index 55fb5941c6d420dbcdb4545fcbf920a63f57116c..d8468c6679257b26b0157da63fd1d6bdd0633ba4 100644 (file)
 /*
  * PCI-defined configuration space registers
  */
-#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b
-#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F2 0x141c
 #define PCI_DEVICE_ID_AMD_15H_NB_F1    0x1601
 #define PCI_DEVICE_ID_AMD_15H_NB_F2    0x1602
+#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b
+#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F2 0x141c
+#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F1 0x1571
+#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F2 0x1572
 #define PCI_DEVICE_ID_AMD_16H_NB_F1    0x1531
 #define PCI_DEVICE_ID_AMD_16H_NB_F2    0x1532
 #define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581
 
 #define csrow_enabled(i, dct, pvt)     ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
 
+#define DRAM_CONTROL                   0x78
+
 #define DBAM0                          0x80
 #define DBAM1                          0x180
 
@@ -301,6 +305,7 @@ enum amd_families {
        F10_CPUS,
        F15_CPUS,
        F15_M30H_CPUS,
+       F15_M60H_CPUS,
        F16_CPUS,
        F16_M30H_CPUS,
        NUM_FAMILIES,
@@ -379,6 +384,9 @@ struct amd64_pvt {
 
        /* place to store error injection parameters prior to issue */
        struct error_injection injection;
+
+       /* cache the dram_type */
+       enum mem_type dram_type;
 };
 
 enum err_codes {
@@ -480,7 +488,8 @@ struct low_ops {
        int (*early_channel_count)      (struct amd64_pvt *pvt);
        void (*map_sysaddr_to_csrow)    (struct mem_ctl_info *mci, u64 sys_addr,
                                         struct err_info *);
-       int (*dbam_to_cs)               (struct amd64_pvt *pvt, u8 dct, unsigned cs_mode);
+       int (*dbam_to_cs)               (struct amd64_pvt *pvt, u8 dct,
+                                        unsigned cs_mode, int cs_mask_nr);
 };
 
 struct amd64_family_type {
index df6575f1430d948e4830c764be858d6138aa5db0..682288ced4acb23337899f97cbc8b3542556eb65 100644 (file)
@@ -562,7 +562,7 @@ static void cpc925_mc_check(struct mem_ctl_info *mci)
 
        if (apiexcp & UECC_EXCP_DETECTED) {
                cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n");
-               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
+               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
                                     pfn, offset, 0,
                                     csrow, -1, -1,
                                     mci->ctl_name, "");
index 3cda79bc8b0034d9917f6cafe457bfb67ba3815b..ece3aef16bb18e135aaa533fd32a298b8b1aa0a3 100644 (file)
@@ -226,7 +226,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
 static void process_ce_no_info(struct mem_ctl_info *mci)
 {
        edac_dbg(3, "\n");
-       edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
+       edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, -1, -1, -1,
                             "e7xxx CE log register overflow", "");
 }
 
index c3893b0ddb18425c733cb9446818d9feddcc2ace..1747906f10cedcd2f9b528065b4ae139fc34fdb4 100644 (file)
@@ -125,27 +125,27 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci)
 
 #endif                         /* CONFIG_EDAC_DEBUG */
 
-/*
- * keep those in sync with the enum mem_type
- */
 const char * const edac_mem_types[] = {
-       "Empty csrow",
-       "Reserved csrow type",
-       "Unknown csrow type",
-       "Fast page mode RAM",
-       "Extended data out RAM",
-       "Burst Extended data out RAM",
-       "Single data rate SDRAM",
-       "Registered single data rate SDRAM",
-       "Double data rate SDRAM",
-       "Registered Double data rate SDRAM",
-       "Rambus DRAM",
-       "Unbuffered DDR2 RAM",
-       "Fully buffered DDR2",
-       "Registered DDR2 RAM",
-       "Rambus XDR",
-       "Unbuffered DDR3 RAM",
-       "Registered DDR3 RAM",
+       [MEM_EMPTY]     = "Empty csrow",
+       [MEM_RESERVED]  = "Reserved csrow type",
+       [MEM_UNKNOWN]   = "Unknown csrow type",
+       [MEM_FPM]       = "Fast page mode RAM",
+       [MEM_EDO]       = "Extended data out RAM",
+       [MEM_BEDO]      = "Burst Extended data out RAM",
+       [MEM_SDR]       = "Single data rate SDRAM",
+       [MEM_RDR]       = "Registered single data rate SDRAM",
+       [MEM_DDR]       = "Double data rate SDRAM",
+       [MEM_RDDR]      = "Registered Double data rate SDRAM",
+       [MEM_RMBS]      = "Rambus DRAM",
+       [MEM_DDR2]      = "Unbuffered DDR2 RAM",
+       [MEM_FB_DDR2]   = "Fully buffered DDR2",
+       [MEM_RDDR2]     = "Registered DDR2 RAM",
+       [MEM_XDR]       = "Rambus XDR",
+       [MEM_DDR3]      = "Unbuffered DDR3 RAM",
+       [MEM_RDDR3]     = "Registered DDR3 RAM",
+       [MEM_LRDDR3]    = "Load-Reduced DDR3 RAM",
+       [MEM_DDR4]      = "Unbuffered DDR4 RAM",
+       [MEM_RDDR4]     = "Registered DDR4 RAM",
 };
 EXPORT_SYMBOL_GPL(edac_mem_types);
 
index e8658e451762647774f71b79101f61efb39194d9..24d877f6e57751b07123771c2f9e7b898c17cee6 100644 (file)
@@ -14,9 +14,6 @@
 #include "edac_core.h"
 #include "edac_module.h"
 
-/* Turn off this whole feature if PCI is not configured */
-#ifdef CONFIG_PCI
-
 #define EDAC_PCI_SYMLINK       "device"
 
 /* data variables exported via sysfs */
@@ -761,5 +758,3 @@ MODULE_PARM_DESC(check_pci_errors,
 module_param(edac_pci_panic_on_pe, int, 0644);
 MODULE_PARM_DESC(edac_pci_panic_on_pe,
                 "Panic on PCI Bus Parity error: 0=off 1=on");
-
-#endif                         /* CONFIG_PCI */
index 8399b4e16fe0916683ceb075ff3cb2b49e4baa5b..b24681998740033664331ed4ba5d8ced56af63d0 100644 (file)
@@ -413,8 +413,8 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev,
 
        /* Generate the trace event */
        grain_bits = fls_long(e->grain);
-       sprintf(pvt->detail_location, "APEI location: %s %s",
-               e->location, e->other_detail);
+       snprintf(pvt->detail_location, sizeof(pvt->detail_location),
+                "APEI location: %s %s", e->location, e->other_detail);
        trace_mc_event(type, e->msg, e->label, e->error_count,
                       mci->mc_idx, e->top_layer, e->mid_layer, e->low_layer,
                       PAGES_TO_MiB(e->page_frame_number) | e->offset_in_page,
index cd28b968e5c7a19e21105a1a2252e84a26f70074..5cb36a6022cc9eb31725343d0e712759d827dcf5 100644 (file)
@@ -542,8 +542,7 @@ fail1:
        pci_unregister_driver(&i3000_driver);
 
 fail0:
-       if (mci_pdev)
-               pci_dev_put(mci_pdev);
+       pci_dev_put(mci_pdev);
 
        return pci_rc;
 }
index 022a70273ada730a1c6afe6355387041dda36f2b..4ad062b0ef26141c203934eb1e3ce2d49dcc396c 100644 (file)
@@ -242,11 +242,11 @@ static void i3200_process_error_info(struct mem_ctl_info *mci,
                                             -1, -1,
                                             "i3000 UE", "");
                } else if (log & I3200_ECCERRLOG_CE) {
-                       edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
+                       edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
                                             0, 0, eccerrlog_syndrome(log),
                                             eccerrlog_row(channel, log),
                                             -1, -1,
-                                            "i3000 UE", "");
+                                            "i3000 CE", "");
                }
        }
 }
@@ -523,8 +523,7 @@ fail1:
        pci_unregister_driver(&i3200_driver);
 
 fail0:
-       if (mci_pdev)
-               pci_dev_put(mci_pdev);
+       pci_dev_put(mci_pdev);
 
        return pci_rc;
 }
index d730e276d1a8437526f168e83f503c1d5c236473..b4705d9366bf33d3c6223aacf8f47b8461b25a59 100644 (file)
@@ -458,8 +458,7 @@ static void __exit i82443bxgx_edacmc_exit(void)
        if (!i82443bxgx_registered)
                i82443bxgx_edacmc_remove_one(mci_pdev);
 
-       if (mci_pdev)
-               pci_dev_put(mci_pdev);
+       pci_dev_put(mci_pdev);
 }
 
 module_init(i82443bxgx_edacmc_init);
index 3382f6344e428b31a4659660140a7ea90e5cab28..4382343a7c60ed3cc4d5d1ea4f7661c62b1fe5bc 100644 (file)
@@ -124,7 +124,7 @@ static int i82860_process_error_info(struct mem_ctl_info *mci,
                                     dimm->location[0], dimm->location[1], -1,
                                     "i82860 UE", "");
        else
-               edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
+               edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
                                     info->eap, 0, info->derrsyn,
                                     dimm->location[0], dimm->location[1], -1,
                                     "i82860 CE", "");
index f78c1c54dbd57cb5de8c5fed48f5d677c613f89f..58586d59bf8ed2ff2b7a7abf20288105da43f2d3 100644 (file)
@@ -138,6 +138,15 @@ static const char * const mc5_mce_desc[] = {
        "Retire status queue"
 };
 
+static const char * const mc6_mce_desc[] = {
+       "Hardware Assertion",
+       "Free List",
+       "Physical Register File",
+       "Retire Queue",
+       "Scheduler table",
+       "Status Register File",
+};
+
 static bool f12h_mc0_mce(u16 ec, u8 xec)
 {
        bool ret = false;
@@ -432,8 +441,8 @@ static bool k8_mc2_mce(u16 ec, u8 xec)
                pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec));
        else if (xec == 0x0) {
                if (TLB_ERROR(ec))
-                       pr_cont(": %s error in a Page Descriptor Cache or "
-                               "Guest TLB.\n", TT_MSG(ec));
+                       pr_cont("%s error in a Page Descriptor Cache or Guest TLB.\n",
+                               TT_MSG(ec));
                else if (BUS_ERROR(ec))
                        pr_cont(": %s/ECC error in data read from NB: %s.\n",
                                R4_MSG(ec), PP_MSG(ec));
@@ -672,38 +681,10 @@ static void decode_mc6_mce(struct mce *m)
 
        pr_emerg(HW_ERR "MC6 Error: ");
 
-       switch (xec) {
-       case 0x0:
-               pr_cont("Hardware Assertion");
-               break;
-
-       case 0x1:
-               pr_cont("Free List");
-               break;
-
-       case 0x2:
-               pr_cont("Physical Register File");
-               break;
-
-       case 0x3:
-               pr_cont("Retire Queue");
-               break;
-
-       case 0x4:
-               pr_cont("Scheduler table");
-               break;
-
-       case 0x5:
-               pr_cont("Status Register File");
-               break;
-
-       default:
+       if (xec > 0x5)
                goto wrong_mc6_mce;
-               break;
-       }
-
-       pr_cont(" parity error.\n");
 
+       pr_cont("%s parity error.\n", mc6_mce_desc[xec]);
        return;
 
  wrong_mc6_mce:
@@ -800,7 +781,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
        pr_cont("]: 0x%016llx\n", m->status);
 
        if (m->status & MCI_STATUS_ADDRV)
-               pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr);
+               pr_emerg(HW_ERR "MC%d Error Address: 0x%016llx\n", m->bank, m->addr);
 
        if (!fam_ops)
                goto err_code;
index 5e46a9fea31bef134bb9f1d4685bec3c2f108250..0bd91a802c67a9fdc2a4d7af45f079202ac2505c 100644 (file)
 /*
- * A simple MCE injection facility for testing the MCE decoding code. This
- * driver should be built as module so that it can be loaded on production
- * kernels for testing purposes.
+ * A simple MCE injection facility for testing different aspects of the RAS
+ * code. This driver should be built as module so that it can be loaded
+ * on production kernels for testing purposes.
  *
  * This file may be distributed under the terms of the GNU General Public
  * License version 2.
  *
- * Copyright (c) 2010:  Borislav Petkov <bp@alien8.de>
+ * Copyright (c) 2010-14:  Borislav Petkov <bp@alien8.de>
  *                     Advanced Micro Devices Inc.
  */
 
 #include <linux/kobject.h>
+#include <linux/debugfs.h>
 #include <linux/device.h>
-#include <linux/edac.h>
 #include <linux/module.h>
+#include <linux/cpu.h>
 #include <asm/mce.h>
 
 #include "mce_amd.h"
 
-struct edac_mce_attr {
-       struct attribute attr;
-       ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf);
-       ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr,
-                        const char *buf, size_t count);
-};
-
-#define EDAC_MCE_ATTR(_name, _mode, _show, _store)                     \
-static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store)
-
-static struct kobject *mce_kobj;
-
 /*
  * Collect all the MCi_XXX settings
  */
 static struct mce i_mce;
+static struct dentry *dfs_inj;
 
-#define MCE_INJECT_STORE(reg)                                          \
-static ssize_t edac_inject_##reg##_store(struct kobject *kobj,         \
-                                        struct edac_mce_attr *attr,    \
-                                        const char *data, size_t count)\
+#define MCE_INJECT_SET(reg)                                            \
+static int inj_##reg##_set(void *data, u64 val)                                \
 {                                                                      \
-       int ret = 0;                                                    \
-       unsigned long value;                                            \
-                                                                       \
-       ret = kstrtoul(data, 16, &value);                               \
-       if (ret < 0)                                                    \
-               printk(KERN_ERR "Error writing MCE " #reg " field.\n"); \
+       struct mce *m = (struct mce *)data;                             \
                                                                        \
-       i_mce.reg = value;                                              \
-                                                                       \
-       return count;                                                   \
+       m->reg = val;                                                   \
+       return 0;                                                       \
 }
 
-MCE_INJECT_STORE(status);
-MCE_INJECT_STORE(misc);
-MCE_INJECT_STORE(addr);
+MCE_INJECT_SET(status);
+MCE_INJECT_SET(misc);
+MCE_INJECT_SET(addr);
 
-#define MCE_INJECT_SHOW(reg)                                           \
-static ssize_t edac_inject_##reg##_show(struct kobject *kobj,          \
-                                       struct edac_mce_attr *attr,     \
-                                       char *buf)                      \
+#define MCE_INJECT_GET(reg)                                            \
+static int inj_##reg##_get(void *data, u64 *val)                       \
 {                                                                      \
-       return sprintf(buf, "0x%016llx\n", i_mce.reg);                  \
+       struct mce *m = (struct mce *)data;                             \
+                                                                       \
+       *val = m->reg;                                                  \
+       return 0;                                                       \
 }
 
-MCE_INJECT_SHOW(status);
-MCE_INJECT_SHOW(misc);
-MCE_INJECT_SHOW(addr);
+MCE_INJECT_GET(status);
+MCE_INJECT_GET(misc);
+MCE_INJECT_GET(addr);
 
-EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store);
-EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store);
-EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store);
+DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n");
 
 /*
- * This denotes into which bank we're injecting and triggers
- * the injection, at the same time.
+ * Caller needs to be make sure this cpu doesn't disappear
+ * from under us, i.e.: get_cpu/put_cpu.
  */
-static ssize_t edac_inject_bank_store(struct kobject *kobj,
-                                     struct edac_mce_attr *attr,
-                                     const char *data, size_t count)
+static int toggle_hw_mce_inject(unsigned int cpu, bool enable)
 {
-       int ret = 0;
-       unsigned long value;
+       u32 l, h;
+       int err;
 
-       ret = kstrtoul(data, 10, &value);
-       if (ret < 0) {
-               printk(KERN_ERR "Invalid bank value!\n");
-               return -EINVAL;
+       err = rdmsr_on_cpu(cpu, MSR_K7_HWCR, &l, &h);
+       if (err) {
+               pr_err("%s: error reading HWCR\n", __func__);
+               return err;
        }
 
-       if (value > 5)
-               if (boot_cpu_data.x86 != 0x15 || value > 6) {
-                       printk(KERN_ERR "Non-existent MCE bank: %lu\n", value);
-                       return -EINVAL;
-               }
+       enable ? (l |= BIT(18)) : (l &= ~BIT(18));
 
-       i_mce.bank = value;
+       err = wrmsr_on_cpu(cpu, MSR_K7_HWCR, l, h);
+       if (err)
+               pr_err("%s: error writing HWCR\n", __func__);
 
-       amd_decode_mce(NULL, 0, &i_mce);
+       return err;
+}
 
-       return count;
+static int flags_get(void *data, u64 *val)
+{
+       struct mce *m = (struct mce *)data;
+
+       *val = m->inject_flags;
+
+       return 0;
 }
 
-static ssize_t edac_inject_bank_show(struct kobject *kobj,
-                                    struct edac_mce_attr *attr, char *buf)
+static int flags_set(void *data, u64 val)
 {
-       return sprintf(buf, "%d\n", i_mce.bank);
+       struct mce *m = (struct mce *)data;
+
+       m->inject_flags = (u8)val;
+       return 0;
 }
 
-EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store);
+DEFINE_SIMPLE_ATTRIBUTE(flags_fops, flags_get, flags_set, "%llu\n");
 
-static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc,
-                                              &mce_attr_addr, &mce_attr_bank
-};
+/*
+ * On which CPU to inject?
+ */
+MCE_INJECT_GET(extcpu);
 
-static int __init edac_init_mce_inject(void)
+static int inj_extcpu_set(void *data, u64 val)
 {
-       struct bus_type *edac_subsys = NULL;
-       int i, err = 0;
+       struct mce *m = (struct mce *)data;
 
-       edac_subsys = edac_get_sysfs_subsys();
-       if (!edac_subsys)
+       if (val >= nr_cpu_ids || !cpu_online(val)) {
+               pr_err("%s: Invalid CPU: %llu\n", __func__, val);
                return -EINVAL;
+       }
+       m->extcpu = val;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");
 
-       mce_kobj = kobject_create_and_add("mce", &edac_subsys->dev_root->kobj);
-       if (!mce_kobj) {
-               printk(KERN_ERR "Error creating a mce kset.\n");
-               err = -ENOMEM;
-               goto err_mce_kobj;
+static void trigger_mce(void *info)
+{
+       asm volatile("int $18");
+}
+
+static void do_inject(void)
+{
+       u64 mcg_status = 0;
+       unsigned int cpu = i_mce.extcpu;
+       u8 b = i_mce.bank;
+
+       if (!(i_mce.inject_flags & MCJ_EXCEPTION)) {
+               amd_decode_mce(NULL, 0, &i_mce);
+               return;
        }
 
-       for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) {
-               err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr);
-               if (err) {
-                       printk(KERN_ERR "Error creating %s in sysfs.\n",
-                                       sysfs_attrs[i]->attr.name);
-                       goto err_sysfs_create;
+       get_online_cpus();
+       if (!cpu_online(cpu))
+               goto err;
+
+       /* prep MCE global settings for the injection */
+       mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV;
+
+       if (!(i_mce.status & MCI_STATUS_PCC))
+               mcg_status |= MCG_STATUS_RIPV;
+
+       toggle_hw_mce_inject(cpu, true);
+
+       wrmsr_on_cpu(cpu, MSR_IA32_MCG_STATUS,
+                    (u32)mcg_status, (u32)(mcg_status >> 32));
+
+       wrmsr_on_cpu(cpu, MSR_IA32_MCx_STATUS(b),
+                    (u32)i_mce.status, (u32)(i_mce.status >> 32));
+
+       wrmsr_on_cpu(cpu, MSR_IA32_MCx_ADDR(b),
+                    (u32)i_mce.addr, (u32)(i_mce.addr >> 32));
+
+       wrmsr_on_cpu(cpu, MSR_IA32_MCx_MISC(b),
+                    (u32)i_mce.misc, (u32)(i_mce.misc >> 32));
+
+       toggle_hw_mce_inject(cpu, false);
+
+       smp_call_function_single(cpu, trigger_mce, NULL, 0);
+
+err:
+       put_online_cpus();
+
+}
+
+/*
+ * This denotes into which bank we're injecting and triggers
+ * the injection, at the same time.
+ */
+static int inj_bank_set(void *data, u64 val)
+{
+       struct mce *m = (struct mce *)data;
+
+       if (val > 5) {
+               if (boot_cpu_data.x86 != 0x15 || val > 6) {
+                       pr_err("Non-existent MCE bank: %llu\n", val);
+                       return -EINVAL;
                }
        }
-       return 0;
 
-err_sysfs_create:
-       while (--i >= 0)
-               sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+       m->bank = val;
+       do_inject();
 
-       kobject_del(mce_kobj);
+       return 0;
+}
 
-err_mce_kobj:
-       edac_put_sysfs_subsys();
+static int inj_bank_get(void *data, u64 *val)
+{
+       struct mce *m = (struct mce *)data;
 
-       return err;
+       *val = m->bank;
+       return 0;
 }
 
-static void __exit edac_exit_mce_inject(void)
+DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n");
+
+struct dfs_node {
+       char *name;
+       struct dentry *d;
+       const struct file_operations *fops;
+} dfs_fls[] = {
+       { .name = "status",     .fops = &status_fops },
+       { .name = "misc",       .fops = &misc_fops },
+       { .name = "addr",       .fops = &addr_fops },
+       { .name = "bank",       .fops = &bank_fops },
+       { .name = "flags",      .fops = &flags_fops },
+       { .name = "cpu",        .fops = &extcpu_fops },
+};
+
+static int __init init_mce_inject(void)
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++)
-               sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+       dfs_inj = debugfs_create_dir("mce-inject", NULL);
+       if (!dfs_inj)
+               return -EINVAL;
+
+       for (i = 0; i < ARRAY_SIZE(dfs_fls); i++) {
+               dfs_fls[i].d = debugfs_create_file(dfs_fls[i].name,
+                                                   S_IRUSR | S_IWUSR,
+                                                   dfs_inj,
+                                                   &i_mce,
+                                                   dfs_fls[i].fops);
+
+               if (!dfs_fls[i].d)
+                       goto err_dfs_add;
+       }
+
+       return 0;
+
+err_dfs_add:
+       while (--i >= 0)
+               debugfs_remove(dfs_fls[i].d);
 
-       kobject_del(mce_kobj);
+       debugfs_remove(dfs_inj);
+       dfs_inj = NULL;
 
-       edac_put_sysfs_subsys();
+       return -ENOMEM;
 }
 
-module_init(edac_init_mce_inject);
-module_exit(edac_exit_mce_inject);
+static void __exit exit_mce_inject(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dfs_fls); i++)
+               debugfs_remove(dfs_fls[i].d);
+
+       memset(&dfs_fls, 0, sizeof(dfs_fls));
+
+       debugfs_remove(dfs_inj);
+       dfs_inj = NULL;
+}
+module_init(init_mce_inject);
+module_exit(exit_mce_inject);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
 MODULE_AUTHOR("AMD Inc.");
-MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
+MODULE_DESCRIPTION("MCE injection facility for RAS testing");
index 542fad70e360d60f7c51c7db8f39ab9dc3de9038..6366e880f978c40419d81ed62bc848aa057d5668 100644 (file)
@@ -178,7 +178,7 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev)
                res = devm_request_irq(&pdev->dev,
                                       pdata->irq,
                                       mv64x60_pci_isr,
-                                      IRQF_DISABLED,
+                                      0,
                                       "[EDAC] PCI err",
                                       pci);
                if (res < 0) {
@@ -345,7 +345,7 @@ static int mv64x60_sram_err_probe(struct platform_device *pdev)
                res = devm_request_irq(&pdev->dev,
                                       pdata->irq,
                                       mv64x60_sram_isr,
-                                      IRQF_DISABLED,
+                                      0,
                                       "[EDAC] SRAM err",
                                       edac_dev);
                if (res < 0) {
@@ -540,7 +540,7 @@ static int mv64x60_cpu_err_probe(struct platform_device *pdev)
                res = devm_request_irq(&pdev->dev,
                                       pdata->irq,
                                       mv64x60_cpu_isr,
-                                      IRQF_DISABLED,
+                                      0,
                                       "[EDAC] CPU err",
                                       edac_dev);
                if (res < 0) {
@@ -800,7 +800,7 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev)
                res = devm_request_irq(&pdev->dev,
                                       pdata->irq,
                                       mv64x60_mc_isr,
-                                      IRQF_DISABLED,
+                                      0,
                                       "[EDAC] MC err",
                                       mci);
                if (res < 0) {
index 0f04d5ead521bd8097896783a6da532da9cfa60a..41593539cec441e27e0f6a16334c749996cfe2b0 100644 (file)
@@ -1120,7 +1120,7 @@ static int ppc4xx_edac_register_irq(struct platform_device *op,
 
        status = request_irq(ded_irq,
                             ppc4xx_edac_isr,
-                            IRQF_DISABLED,
+                            0,
                             "[EDAC] MC ECCDED",
                             mci);
 
@@ -1134,7 +1134,7 @@ static int ppc4xx_edac_register_irq(struct platform_device *op,
 
        status = request_irq(sec_irq,
                             ppc4xx_edac_isr,
-                            IRQF_DISABLED,
+                            0,
                             "[EDAC] MC ECCSEC",
                             mci);
 
index e644b52c287c41b3eddb206d24c283c4f1f7f6e9..7c5cdc62f31c35902e8c20d8af7c1c4bea431de1 100644 (file)
@@ -500,8 +500,7 @@ fail1:
        pci_unregister_driver(&x38_driver);
 
 fail0:
-       if (mci_pdev)
-               pci_dev_put(mci_pdev);
+       pci_dev_put(mci_pdev);
 
        return pci_rc;
 }
index 5d997a33907e431b895111fc27039468be244614..2a3973a7c44179457f635196696bc78e756a76e1 100644 (file)
@@ -1637,8 +1637,7 @@ static int dispatch_ioctl(struct client *client,
            _IOC_SIZE(cmd) > sizeof(buffer))
                return -ENOTTY;
 
-       if (_IOC_DIR(cmd) == _IOC_READ)
-               memset(&buffer, 0, _IOC_SIZE(cmd));
+       memset(&buffer, 0, sizeof(buffer));
 
        if (_IOC_DIR(cmd) & _IOC_WRITE)
                if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd)))
index 17afc51f3054402c22a2a8d2fd50c1c809edd160..c5f7b4e9eb6c6e490454958473893820bccaeb10 100644 (file)
@@ -92,6 +92,12 @@ static void dmi_table(u8 *buf, int len, int num,
        while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
                const struct dmi_header *dm = (const struct dmi_header *)data;
 
+               /*
+                * 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0]
+                */
+               if (dm->type == DMI_ENTRY_END_OF_TABLE)
+                       break;
+
                /*
                 *  We want to know the total length (formatted area and
                 *  strings) before decoding to make sure we won't run off the
@@ -107,7 +113,7 @@ static void dmi_table(u8 *buf, int len, int num,
        }
 }
 
-static u32 dmi_base;
+static phys_addr_t dmi_base;
 static u16 dmi_len;
 static u16 dmi_num;
 
@@ -467,7 +473,7 @@ static int __init dmi_present(const u8 *buf)
 
        if (memcmp(buf, "_SM_", 4) == 0 &&
            buf[5] < 32 && dmi_checksum(buf, buf[5])) {
-               smbios_ver = (buf[6] << 8) + buf[7];
+               smbios_ver = get_unaligned_be16(buf + 6);
 
                /* Some BIOS report weird SMBIOS version, fix that up */
                switch (smbios_ver) {
@@ -489,10 +495,9 @@ static int __init dmi_present(const u8 *buf)
        buf += 16;
 
        if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
-               dmi_num = (buf[13] << 8) | buf[12];
-               dmi_len = (buf[7] << 8) | buf[6];
-               dmi_base = (buf[11] << 24) | (buf[10] << 16) |
-                       (buf[9] << 8) | buf[8];
+               dmi_num = get_unaligned_le16(buf + 12);
+               dmi_len = get_unaligned_le16(buf + 6);
+               dmi_base = get_unaligned_le32(buf + 8);
 
                if (dmi_walk_early(dmi_decode) == 0) {
                        if (smbios_ver) {
@@ -514,12 +519,72 @@ static int __init dmi_present(const u8 *buf)
        return 1;
 }
 
+/*
+ * Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy
+ * 32-bit entry point, there is no embedded DMI header (_DMI_) in here.
+ */
+static int __init dmi_smbios3_present(const u8 *buf)
+{
+       if (memcmp(buf, "_SM3_", 5) == 0 &&
+           buf[6] < 32 && dmi_checksum(buf, buf[6])) {
+               dmi_ver = get_unaligned_be16(buf + 7);
+               dmi_len = get_unaligned_le32(buf + 12);
+               dmi_base = get_unaligned_le64(buf + 16);
+
+               /*
+                * The 64-bit SMBIOS 3.0 entry point no longer has a field
+                * containing the number of structures present in the table.
+                * Instead, it defines the table size as a maximum size, and
+                * relies on the end-of-table structure type (#127) to be used
+                * to signal the end of the table.
+                * So let's define dmi_num as an upper bound as well: each
+                * structure has a 4 byte header, so dmi_len / 4 is an upper
+                * bound for the number of structures in the table.
+                */
+               dmi_num = dmi_len / 4;
+
+               if (dmi_walk_early(dmi_decode) == 0) {
+                       pr_info("SMBIOS %d.%d present.\n",
+                               dmi_ver >> 8, dmi_ver & 0xFF);
+                       dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
+                       pr_debug("DMI: %s\n", dmi_ids_string);
+                       return 0;
+               }
+       }
+       return 1;
+}
+
 void __init dmi_scan_machine(void)
 {
        char __iomem *p, *q;
        char buf[32];
 
        if (efi_enabled(EFI_CONFIG_TABLES)) {
+               /*
+                * According to the DMTF SMBIOS reference spec v3.0.0, it is
+                * allowed to define both the 64-bit entry point (smbios3) and
+                * the 32-bit entry point (smbios), in which case they should
+                * either both point to the same SMBIOS structure table, or the
+                * table pointed to by the 64-bit entry point should contain a
+                * superset of the table contents pointed to by the 32-bit entry
+                * point (section 5.2)
+                * This implies that the 64-bit entry point should have
+                * precedence if it is defined and supported by the OS. If we
+                * have the 64-bit entry point, but fail to decode it, fall
+                * back to the legacy one (if available)
+                */
+               if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) {
+                       p = dmi_early_remap(efi.smbios3, 32);
+                       if (p == NULL)
+                               goto error;
+                       memcpy_fromio(buf, p, 32);
+                       dmi_early_unmap(p, 32);
+
+                       if (!dmi_smbios3_present(buf)) {
+                               dmi_available = 1;
+                               goto out;
+                       }
+               }
                if (efi.smbios == EFI_INVALID_TABLE_ADDR)
                        goto error;
 
@@ -552,7 +617,7 @@ void __init dmi_scan_machine(void)
                memset(buf, 0, 16);
                for (q = p; q < p + 0x10000; q += 16) {
                        memcpy_fromio(buf + 16, q, 16);
-                       if (!dmi_present(buf)) {
+                       if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
                                dmi_available = 1;
                                dmi_early_unmap(p, 0x10000);
                                goto out;
index 64ecbb501c5080df5e36b90dd73501b7dac881d4..9035c1b74d5839471445facd9100b8522c2e9dd8 100644 (file)
@@ -30,6 +30,7 @@ struct efi __read_mostly efi = {
        .acpi       = EFI_INVALID_TABLE_ADDR,
        .acpi20     = EFI_INVALID_TABLE_ADDR,
        .smbios     = EFI_INVALID_TABLE_ADDR,
+       .smbios3    = EFI_INVALID_TABLE_ADDR,
        .sal_systab = EFI_INVALID_TABLE_ADDR,
        .boot_info  = EFI_INVALID_TABLE_ADDR,
        .hcdp       = EFI_INVALID_TABLE_ADDR,
@@ -41,6 +42,28 @@ struct efi __read_mostly efi = {
 };
 EXPORT_SYMBOL(efi);
 
+static bool disable_runtime;
+static int __init setup_noefi(char *arg)
+{
+       disable_runtime = true;
+       return 0;
+}
+early_param("noefi", setup_noefi);
+
+bool efi_runtime_disabled(void)
+{
+       return disable_runtime;
+}
+
+static int __init parse_efi_cmdline(char *str)
+{
+       if (parse_option_str(str, "noruntime"))
+               disable_runtime = true;
+
+       return 0;
+}
+early_param("efi", parse_efi_cmdline);
+
 static struct kobject *efi_kobj;
 static struct kobject *efivars_kobj;
 
@@ -64,6 +87,8 @@ static ssize_t systab_show(struct kobject *kobj,
                str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
        if (efi.smbios != EFI_INVALID_TABLE_ADDR)
                str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
+       if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
+               str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
        if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
                str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
        if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
@@ -238,6 +263,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
        {MPS_TABLE_GUID, "MPS", &efi.mps},
        {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
        {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
+       {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
        {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
        {NULL_GUID, NULL, NULL},
 };
@@ -423,3 +449,60 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
        return ret;
 }
 #endif /* CONFIG_EFI_PARAMS_FROM_FDT */
+
+static __initdata char memory_type_name[][20] = {
+       "Reserved",
+       "Loader Code",
+       "Loader Data",
+       "Boot Code",
+       "Boot Data",
+       "Runtime Code",
+       "Runtime Data",
+       "Conventional Memory",
+       "Unusable Memory",
+       "ACPI Reclaim Memory",
+       "ACPI Memory NVS",
+       "Memory Mapped I/O",
+       "MMIO Port Space",
+       "PAL Code"
+};
+
+char * __init efi_md_typeattr_format(char *buf, size_t size,
+                                    const efi_memory_desc_t *md)
+{
+       char *pos;
+       int type_len;
+       u64 attr;
+
+       pos = buf;
+       if (md->type >= ARRAY_SIZE(memory_type_name))
+               type_len = snprintf(pos, size, "[type=%u", md->type);
+       else
+               type_len = snprintf(pos, size, "[%-*s",
+                                   (int)(sizeof(memory_type_name[0]) - 1),
+                                   memory_type_name[md->type]);
+       if (type_len >= size)
+               return buf;
+
+       pos += type_len;
+       size -= type_len;
+
+       attr = md->attribute;
+       if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
+                    EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
+                    EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
+               snprintf(pos, size, "|attr=0x%016llx]",
+                        (unsigned long long)attr);
+       else
+               snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
+                        attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
+                        attr & EFI_MEMORY_XP      ? "XP"  : "",
+                        attr & EFI_MEMORY_RP      ? "RP"  : "",
+                        attr & EFI_MEMORY_WP      ? "WP"  : "",
+                        attr & EFI_MEMORY_UCE     ? "UCE" : "",
+                        attr & EFI_MEMORY_WB      ? "WB"  : "",
+                        attr & EFI_MEMORY_WT      ? "WT"  : "",
+                        attr & EFI_MEMORY_WC      ? "WC"  : "",
+                        attr & EFI_MEMORY_UC      ? "UC"  : "");
+       return buf;
+}
index 480339b6b110db047848d33c010c7c217ddd04b2..eb48a1a1a576aa38d1be8a482b6037d302d1a060 100644 (file)
@@ -226,6 +226,10 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
                goto fail_free_image;
        }
 
+       status = efi_parse_options(cmdline_ptr);
+       if (status != EFI_SUCCESS)
+               pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
+
        /*
         * Unauthenticated device tree data is a security hazard, so
         * ignore 'dtb=' unless UEFI Secure Boot is disabled.
@@ -243,9 +247,18 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
                        goto fail_free_cmdline;
                }
        }
-       if (!fdt_addr)
+
+       if (fdt_addr) {
+               pr_efi(sys_table, "Using DTB from command line\n");
+       } else {
                /* Look for a device tree configuration table entry. */
                fdt_addr = (uintptr_t)get_fdt(sys_table);
+               if (fdt_addr)
+                       pr_efi(sys_table, "Using DTB from configuration table\n");
+       }
+
+       if (!fdt_addr)
+               pr_efi(sys_table, "Generating empty DTB\n");
 
        status = handle_cmdline_files(sys_table, image, cmdline_ptr,
                                      "initrd=", dram_base + SZ_512M,
index 32d5cca30f496d88594de5f74d0d1de9bce5057d..a920fec8fe8856132191e5b08b95c227310078f8 100644 (file)
 
 #include "efistub.h"
 
+/*
+ * Some firmware implementations have problems reading files in one go.
+ * A read chunk size of 1MB seems to work for most platforms.
+ *
+ * Unfortunately, reading files in chunks triggers *other* bugs on some
+ * platforms, so we provide a way to disable this workaround, which can
+ * be done by passing "efi=nochunk" on the EFI boot stub command line.
+ *
+ * If you experience issues with initrd images being corrupt it's worth
+ * trying efi=nochunk, but chunking is enabled by default because there
+ * are far more machines that require the workaround than those that
+ * break with it enabled.
+ */
 #define EFI_READ_CHUNK_SIZE    (1024 * 1024)
 
+static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
+
 struct file_info {
        efi_file_handle_t *handle;
        u64 size;
@@ -281,6 +296,49 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
        efi_call_early(free_pages, addr, nr_pages);
 }
 
+/*
+ * Parse the ASCII string 'cmdline' for EFI options, denoted by the efi=
+ * option, e.g. efi=nochunk.
+ *
+ * It should be noted that efi= is parsed in two very different
+ * environments, first in the early boot environment of the EFI boot
+ * stub, and subsequently during the kernel boot.
+ */
+efi_status_t efi_parse_options(char *cmdline)
+{
+       char *str;
+
+       /*
+        * If no EFI parameters were specified on the cmdline we've got
+        * nothing to do.
+        */
+       str = strstr(cmdline, "efi=");
+       if (!str)
+               return EFI_SUCCESS;
+
+       /* Skip ahead to first argument */
+       str += strlen("efi=");
+
+       /*
+        * Remember, because efi= is also used by the kernel we need to
+        * skip over arguments we don't understand.
+        */
+       while (*str) {
+               if (!strncmp(str, "nochunk", 7)) {
+                       str += strlen("nochunk");
+                       __chunk_size = -1UL;
+               }
+
+               /* Group words together, delimited by "," */
+               while (*str && *str != ',')
+                       str++;
+
+               if (*str == ',')
+                       str++;
+       }
+
+       return EFI_SUCCESS;
+}
 
 /*
  * Check the cmdline for a LILO-style file= arguments.
@@ -423,8 +481,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
                        size = files[j].size;
                        while (size) {
                                unsigned long chunksize;
-                               if (size > EFI_READ_CHUNK_SIZE)
-                                       chunksize = EFI_READ_CHUNK_SIZE;
+                               if (size > __chunk_size)
+                                       chunksize = __chunk_size;
                                else
                                        chunksize = size;
 
index 10daa4bbb25833321ffa15ed72e11b327100aa3c..228bbf91046137de619a4f8f89825e8ccc34b5ab 100644 (file)
  * This file is released under the GPLv2.
  */
 
+#include <linux/bug.h>
 #include <linux/efi.h>
-#include <linux/spinlock.h>             /* spinlock_t */
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <asm/efi.h>
 
+/*
+ * According to section 7.1 of the UEFI spec, Runtime Services are not fully
+ * reentrant, and there are particular combinations of calls that need to be
+ * serialized. (source: UEFI Specification v2.4A)
+ *
+ * Table 31. Rules for Reentry Into Runtime Services
+ * +------------------------------------+-------------------------------+
+ * | If previous call is busy in       | Forbidden to call             |
+ * +------------------------------------+-------------------------------+
+ * | Any                               | SetVirtualAddressMap()        |
+ * +------------------------------------+-------------------------------+
+ * | ConvertPointer()                  | ConvertPointer()              |
+ * +------------------------------------+-------------------------------+
+ * | SetVariable()                     | ResetSystem()                 |
+ * | UpdateCapsule()                   |                               |
+ * | SetTime()                         |                               |
+ * | SetWakeupTime()                   |                               |
+ * | GetNextHighMonotonicCount()       |                               |
+ * +------------------------------------+-------------------------------+
+ * | GetVariable()                     | GetVariable()                 |
+ * | GetNextVariableName()             | GetNextVariableName()         |
+ * | SetVariable()                     | SetVariable()                 |
+ * | QueryVariableInfo()               | QueryVariableInfo()           |
+ * | UpdateCapsule()                   | UpdateCapsule()               |
+ * | QueryCapsuleCapabilities()                | QueryCapsuleCapabilities()    |
+ * | GetNextHighMonotonicCount()       | GetNextHighMonotonicCount()   |
+ * +------------------------------------+-------------------------------+
+ * | GetTime()                         | GetTime()                     |
+ * | SetTime()                         | SetTime()                     |
+ * | GetWakeupTime()                   | GetWakeupTime()               |
+ * | SetWakeupTime()                   | SetWakeupTime()               |
+ * +------------------------------------+-------------------------------+
+ *
+ * Due to the fact that the EFI pstore may write to the variable store in
+ * interrupt context, we need to use a spinlock for at least the groups that
+ * contain SetVariable() and QueryVariableInfo(). That leaves little else, as
+ * none of the remaining functions are actually ever called at runtime.
+ * So let's just use a single spinlock to serialize all Runtime Services calls.
+ */
+static DEFINE_SPINLOCK(efi_runtime_lock);
+
+/*
+ * Some runtime services calls can be reentrant under NMI, even if the table
+ * above says they are not. (source: UEFI Specification v2.4A)
+ *
+ * Table 32. Functions that may be called after Machine Check, INIT and NMI
+ * +----------------------------+------------------------------------------+
+ * | Function                  | Called after Machine Check, INIT and NMI |
+ * +----------------------------+------------------------------------------+
+ * | GetTime()                 | Yes, even if previously busy.            |
+ * | GetVariable()             | Yes, even if previously busy             |
+ * | GetNextVariableName()     | Yes, even if previously busy             |
+ * | QueryVariableInfo()       | Yes, even if previously busy             |
+ * | SetVariable()             | Yes, even if previously busy             |
+ * | UpdateCapsule()           | Yes, even if previously busy             |
+ * | QueryCapsuleCapabilities()        | Yes, even if previously busy             |
+ * | ResetSystem()             | Yes, even if previously busy             |
+ * +----------------------------+------------------------------------------+
+ *
+ * In order to prevent deadlocks under NMI, the wrappers for these functions
+ * may only grab the efi_runtime_lock or rtc_lock spinlocks if !efi_in_nmi().
+ * However, not all of the services listed are reachable through NMI code paths,
+ * so the the special handling as suggested by the UEFI spec is only implemented
+ * for QueryVariableInfo() and SetVariable(), as these can be reached in NMI
+ * context through efi_pstore_write().
+ */
+
 /*
  * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
  * the EFI specification requires that callers of the time related runtime
@@ -32,7 +101,9 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(get_time, tm, tc);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -43,7 +114,9 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(set_time, tm);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -56,7 +129,9 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(get_wakeup_time, enabled, pending, tm);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -67,7 +142,9 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
        efi_status_t status;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       spin_lock(&efi_runtime_lock);
        status = efi_call_virt(set_wakeup_time, enabled, tm);
+       spin_unlock(&efi_runtime_lock);
        spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
@@ -78,14 +155,27 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
                                          unsigned long *data_size,
                                          void *data)
 {
-       return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(get_variable, name, vendor, attr, data_size,
+                              data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
                                               efi_char16_t *name,
                                               efi_guid_t *vendor)
 {
-       return efi_call_virt(get_next_variable, name_size, name, vendor);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(get_next_variable, name_size, name, vendor);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_set_variable(efi_char16_t *name,
@@ -94,24 +184,61 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
                                          unsigned long data_size,
                                          void *data)
 {
-       return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(set_variable, name, vendor, attr, data_size,
+                              data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
+static efi_status_t
+virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
+                                 u32 attr, unsigned long data_size,
+                                 void *data)
+{
+       unsigned long flags;
+       efi_status_t status;
+
+       if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
+               return EFI_NOT_READY;
+
+       status = efi_call_virt(set_variable, name, vendor, attr, data_size,
+                              data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
+}
+
+
 static efi_status_t virt_efi_query_variable_info(u32 attr,
                                                 u64 *storage_space,
                                                 u64 *remaining_space,
                                                 u64 *max_variable_size)
 {
+       unsigned long flags;
+       efi_status_t status;
+
        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
                return EFI_UNSUPPORTED;
 
-       return efi_call_virt(query_variable_info, attr, storage_space,
-                            remaining_space, max_variable_size);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(query_variable_info, attr, storage_space,
+                              remaining_space, max_variable_size);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
 {
-       return efi_call_virt(get_next_high_mono_count, count);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(get_next_high_mono_count, count);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static void virt_efi_reset_system(int reset_type,
@@ -119,17 +246,27 @@ static void virt_efi_reset_system(int reset_type,
                                  unsigned long data_size,
                                  efi_char16_t *data)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&efi_runtime_lock, flags);
        __efi_call_virt(reset_system, reset_type, status, data_size, data);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
 }
 
 static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
                                            unsigned long count,
                                            unsigned long sg_list)
 {
+       unsigned long flags;
+       efi_status_t status;
+
        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
                return EFI_UNSUPPORTED;
 
-       return efi_call_virt(update_capsule, capsules, count, sg_list);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(update_capsule, capsules, count, sg_list);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
@@ -137,11 +274,17 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
                                                u64 *max_size,
                                                int *reset_type)
 {
+       unsigned long flags;
+       efi_status_t status;
+
        if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
                return EFI_UNSUPPORTED;
 
-       return efi_call_virt(query_capsule_caps, capsules, count, max_size,
-                            reset_type);
+       spin_lock_irqsave(&efi_runtime_lock, flags);
+       status = efi_call_virt(query_capsule_caps, capsules, count, max_size,
+                              reset_type);
+       spin_unlock_irqrestore(&efi_runtime_lock, flags);
+       return status;
 }
 
 void efi_native_runtime_setup(void)
@@ -153,6 +296,7 @@ void efi_native_runtime_setup(void)
        efi.get_variable = virt_efi_get_variable;
        efi.get_next_variable = virt_efi_get_next_variable;
        efi.set_variable = virt_efi_set_variable;
+       efi.set_variable_nonblocking = virt_efi_set_variable_nonblocking;
        efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
        efi.reset_system = virt_efi_reset_system;
        efi.query_variable_info = virt_efi_query_variable_info;
index 5abe943e34042df45d8d1f643b0334e6ceb19748..70a0fb10517f94ea5b28bada280d9935f0693cc7 100644 (file)
@@ -321,11 +321,11 @@ static unsigned long var_name_strnsize(efi_char16_t *variable_name,
  * Print a warning when duplicate EFI variables are encountered and
  * disable the sysfs workqueue since the firmware is buggy.
  */
-static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
+static void dup_variable_bug(efi_char16_t *str16, efi_guid_t *vendor_guid,
                             unsigned long len16)
 {
        size_t i, len8 = len16 / sizeof(efi_char16_t);
-       char *s8;
+       char *str8;
 
        /*
         * Disable the workqueue since the algorithm it uses for
@@ -334,16 +334,16 @@ static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
         */
        efivar_wq_enabled = false;
 
-       s8 = kzalloc(len8, GFP_KERNEL);
-       if (!s8)
+       str8 = kzalloc(len8, GFP_KERNEL);
+       if (!str8)
                return;
 
        for (i = 0; i < len8; i++)
-               s8[i] = s16[i];
+               str8[i] = str16[i];
 
        printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
-              s8, vendor_guid);
-       kfree(s8);
+              str8, vendor_guid);
+       kfree(str8);
 }
 
 /**
@@ -595,6 +595,39 @@ int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
 }
 EXPORT_SYMBOL_GPL(efivar_entry_set);
 
+/*
+ * efivar_entry_set_nonblocking - call set_variable_nonblocking()
+ *
+ * This function is guaranteed to not block and is suitable for calling
+ * from crash/panic handlers.
+ *
+ * Crucially, this function will not block if it cannot acquire
+ * __efivars->lock. Instead, it returns -EBUSY.
+ */
+static int
+efivar_entry_set_nonblocking(efi_char16_t *name, efi_guid_t vendor,
+                            u32 attributes, unsigned long size, void *data)
+{
+       const struct efivar_operations *ops = __efivars->ops;
+       unsigned long flags;
+       efi_status_t status;
+
+       if (!spin_trylock_irqsave(&__efivars->lock, flags))
+               return -EBUSY;
+
+       status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
+       if (status != EFI_SUCCESS) {
+               spin_unlock_irqrestore(&__efivars->lock, flags);
+               return -ENOSPC;
+       }
+
+       status = ops->set_variable_nonblocking(name, &vendor, attributes,
+                                              size, data);
+
+       spin_unlock_irqrestore(&__efivars->lock, flags);
+       return efi_status_to_err(status);
+}
+
 /**
  * efivar_entry_set_safe - call set_variable() if enough space in firmware
  * @name: buffer containing the variable name
@@ -622,6 +655,20 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
        if (!ops->query_variable_store)
                return -ENOSYS;
 
+       /*
+        * If the EFI variable backend provides a non-blocking
+        * ->set_variable() operation and we're in a context where we
+        * cannot block, then we need to use it to avoid live-locks,
+        * since the implication is that the regular ->set_variable()
+        * will block.
+        *
+        * If no ->set_variable_nonblocking() is provided then
+        * ->set_variable() is assumed to be non-blocking.
+        */
+       if (!block && ops->set_variable_nonblocking)
+               return efivar_entry_set_nonblocking(name, vendor, attributes,
+                                                   size, data);
+
        if (!block) {
                if (!spin_trylock_irqsave(&__efivars->lock, flags))
                        return -EBUSY;
index 0959ca9b6b27b7ecea6c616c2d7e416233961d4b..23dfd5f59b393fe97a71c4b4f2683700286a1f77 100644 (file)
@@ -905,4 +905,16 @@ config GPIO_VIPERBOARD
           River Tech's viperboard.h for detailed meaning
           of the module parameters.
 
+config GPIO_DLN2
+       tristate "Diolan DLN2 GPIO support"
+       depends on MFD_DLN2
+       select GPIOLIB_IRQCHIP
+
+       help
+         Select this option to enable GPIO driver for the Diolan DLN2
+         board.
+
+         This driver can also be built as a module. If so, the module
+         will be called gpio-dln2.
+
 endif
index e5d346cf3b6e8a1d7cc564fe444d1941f02ffec6..e60677b8ccb451659510fdf0d8231bbdeb2f32c5 100644 (file)
@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_CRYSTAL_COVE)       += gpio-crystalcove.o
 obj-$(CONFIG_GPIO_DA9052)      += gpio-da9052.o
 obj-$(CONFIG_GPIO_DA9055)      += gpio-da9055.o
 obj-$(CONFIG_GPIO_DAVINCI)     += gpio-davinci.o
+obj-$(CONFIG_GPIO_DLN2)                += gpio-dln2.o
 obj-$(CONFIG_GPIO_DWAPB)       += gpio-dwapb.o
 obj-$(CONFIG_GPIO_EM)          += gpio-em.o
 obj-$(CONFIG_GPIO_EP93XX)      += gpio-ep93xx.o
diff --git a/drivers/gpio/gpio-dln2.c b/drivers/gpio/gpio-dln2.c
new file mode 100644 (file)
index 0000000..978b51e
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * Driver for the Diolan DLN-2 USB-GPIO adapter
+ *
+ * Copyright (c) 2014 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/dln2.h>
+
+#define DLN2_GPIO_ID                   0x01
+
+#define DLN2_GPIO_GET_PIN_COUNT                DLN2_CMD(0x01, DLN2_GPIO_ID)
+#define DLN2_GPIO_SET_DEBOUNCE         DLN2_CMD(0x04, DLN2_GPIO_ID)
+#define DLN2_GPIO_GET_DEBOUNCE         DLN2_CMD(0x05, DLN2_GPIO_ID)
+#define DLN2_GPIO_PORT_GET_VAL         DLN2_CMD(0x06, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_GET_VAL          DLN2_CMD(0x0B, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_SET_OUT_VAL      DLN2_CMD(0x0C, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_GET_OUT_VAL      DLN2_CMD(0x0D, DLN2_GPIO_ID)
+#define DLN2_GPIO_CONDITION_MET_EV     DLN2_CMD(0x0F, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_ENABLE           DLN2_CMD(0x10, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_DISABLE          DLN2_CMD(0x11, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_SET_DIRECTION    DLN2_CMD(0x13, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_GET_DIRECTION    DLN2_CMD(0x14, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_SET_EVENT_CFG    DLN2_CMD(0x1E, DLN2_GPIO_ID)
+#define DLN2_GPIO_PIN_GET_EVENT_CFG    DLN2_CMD(0x1F, DLN2_GPIO_ID)
+
+#define DLN2_GPIO_EVENT_NONE           0
+#define DLN2_GPIO_EVENT_CHANGE         1
+#define DLN2_GPIO_EVENT_LVL_HIGH       2
+#define DLN2_GPIO_EVENT_LVL_LOW                3
+#define DLN2_GPIO_EVENT_CHANGE_RISING  0x11
+#define DLN2_GPIO_EVENT_CHANGE_FALLING  0x21
+#define DLN2_GPIO_EVENT_MASK           0x0F
+
+#define DLN2_GPIO_MAX_PINS 32
+
+struct dln2_irq_work {
+       struct work_struct work;
+       struct dln2_gpio *dln2;
+       int pin;
+       int type;
+};
+
+struct dln2_gpio {
+       struct platform_device *pdev;
+       struct gpio_chip gpio;
+
+       /*
+        * Cache pin direction to save us one transfer, since the hardware has
+        * separate commands to read the in and out values.
+        */
+       DECLARE_BITMAP(output_enabled, DLN2_GPIO_MAX_PINS);
+
+       DECLARE_BITMAP(irqs_masked, DLN2_GPIO_MAX_PINS);
+       DECLARE_BITMAP(irqs_enabled, DLN2_GPIO_MAX_PINS);
+       DECLARE_BITMAP(irqs_pending, DLN2_GPIO_MAX_PINS);
+       struct dln2_irq_work *irq_work;
+};
+
+struct dln2_gpio_pin {
+       __le16 pin;
+};
+
+struct dln2_gpio_pin_val {
+       __le16 pin __packed;
+       u8 value;
+};
+
+static int dln2_gpio_get_pin_count(struct platform_device *pdev)
+{
+       int ret;
+       __le16 count;
+       int len = sizeof(count);
+
+       ret = dln2_transfer_rx(pdev, DLN2_GPIO_GET_PIN_COUNT, &count, &len);
+       if (ret < 0)
+               return ret;
+       if (len < sizeof(count))
+               return -EPROTO;
+
+       return le16_to_cpu(count);
+}
+
+static int dln2_gpio_pin_cmd(struct dln2_gpio *dln2, int cmd, unsigned pin)
+{
+       struct dln2_gpio_pin req = {
+               .pin = cpu_to_le16(pin),
+       };
+
+       return dln2_transfer_tx(dln2->pdev, cmd, &req, sizeof(req));
+}
+
+static int dln2_gpio_pin_val(struct dln2_gpio *dln2, int cmd, unsigned int pin)
+{
+       int ret;
+       struct dln2_gpio_pin req = {
+               .pin = cpu_to_le16(pin),
+       };
+       struct dln2_gpio_pin_val rsp;
+       int len = sizeof(rsp);
+
+       ret = dln2_transfer(dln2->pdev, cmd, &req, sizeof(req), &rsp, &len);
+       if (ret < 0)
+               return ret;
+       if (len < sizeof(rsp) || req.pin != rsp.pin)
+               return -EPROTO;
+
+       return rsp.value;
+}
+
+static int dln2_gpio_pin_get_in_val(struct dln2_gpio *dln2, unsigned int pin)
+{
+       int ret;
+
+       ret = dln2_gpio_pin_val(dln2, DLN2_GPIO_PIN_GET_VAL, pin);
+       if (ret < 0)
+               return ret;
+       return !!ret;
+}
+
+static int dln2_gpio_pin_get_out_val(struct dln2_gpio *dln2, unsigned int pin)
+{
+       int ret;
+
+       ret = dln2_gpio_pin_val(dln2, DLN2_GPIO_PIN_GET_OUT_VAL, pin);
+       if (ret < 0)
+               return ret;
+       return !!ret;
+}
+
+static void dln2_gpio_pin_set_out_val(struct dln2_gpio *dln2,
+                                     unsigned int pin, int value)
+{
+       struct dln2_gpio_pin_val req = {
+               .pin = cpu_to_le16(pin),
+               .value = value,
+       };
+
+       dln2_transfer_tx(dln2->pdev, DLN2_GPIO_PIN_SET_OUT_VAL, &req,
+                        sizeof(req));
+}
+
+#define DLN2_GPIO_DIRECTION_IN         0
+#define DLN2_GPIO_DIRECTION_OUT                1
+
+static int dln2_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct dln2_gpio *dln2 = container_of(chip, struct dln2_gpio, gpio);
+       struct dln2_gpio_pin req = {
+               .pin = cpu_to_le16(offset),
+       };
+       struct dln2_gpio_pin_val rsp;
+       int len = sizeof(rsp);
+       int ret;
+
+       ret = dln2_gpio_pin_cmd(dln2, DLN2_GPIO_PIN_ENABLE, offset);
+       if (ret < 0)
+               return ret;
+
+       /* cache the pin direction */
+       ret = dln2_transfer(dln2->pdev, DLN2_GPIO_PIN_GET_DIRECTION,
+                           &req, sizeof(req), &rsp, &len);
+       if (ret < 0)
+               return ret;
+       if (len < sizeof(rsp) || req.pin != rsp.pin) {
+               ret = -EPROTO;
+               goto out_disable;
+       }
+
+       switch (rsp.value) {
+       case DLN2_GPIO_DIRECTION_IN:
+               clear_bit(offset, dln2->output_enabled);
+               return 0;
+       case DLN2_GPIO_DIRECTION_OUT:
+               set_bit(offset, dln2->output_enabled);
+               return 0;
+       default:
+               ret = -EPROTO;
+               goto out_disable;
+       }
+
+out_disable:
+       dln2_gpio_pin_cmd(dln2, DLN2_GPIO_PIN_DISABLE, offset);
+       return ret;
+}
+
+static void dln2_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       struct dln2_gpio *dln2 = container_of(chip, struct dln2_gpio, gpio);
+
+       dln2_gpio_pin_cmd(dln2, DLN2_GPIO_PIN_DISABLE, offset);
+}
+
+static int dln2_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+       struct dln2_gpio *dln2 = container_of(chip, struct dln2_gpio, gpio);
+
+       if (test_bit(offset, dln2->output_enabled))
+               return GPIOF_DIR_OUT;
+
+       return GPIOF_DIR_IN;
+}
+
+static int dln2_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct dln2_gpio *dln2 = container_of(chip, struct dln2_gpio, gpio);
+       int dir;
+
+       dir = dln2_gpio_get_direction(chip, offset);
+       if (dir < 0)
+               return dir;
+
+       if (dir == GPIOF_DIR_IN)
+               return dln2_gpio_pin_get_in_val(dln2, offset);
+
+       return dln2_gpio_pin_get_out_val(dln2, offset);
+}
+
+static void dln2_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct dln2_gpio *dln2 = container_of(chip, struct dln2_gpio, gpio);
+
+       dln2_gpio_pin_set_out_val(dln2, offset, value);
+}
+
+static int dln2_gpio_set_direction(struct gpio_chip *chip, unsigned offset,
+                                  unsigned dir)
+{
+       struct dln2_gpio *dln2 = container_of(chip, struct dln2_gpio, gpio);
+       struct dln2_gpio_pin_val req = {
+               .pin = cpu_to_le16(offset),
+               .value = dir,
+       };
+       int ret;
+
+       ret = dln2_transfer_tx(dln2->pdev, DLN2_GPIO_PIN_SET_DIRECTION,
+                              &req, sizeof(req));
+       if (ret < 0)
+               return ret;
+
+       if (dir == DLN2_GPIO_DIRECTION_OUT)
+               set_bit(offset, dln2->output_enabled);
+       else
+               clear_bit(offset, dln2->output_enabled);
+
+       return ret;
+}
+
+static int dln2_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return dln2_gpio_set_direction(chip, offset, DLN2_GPIO_DIRECTION_IN);
+}
+
+static int dln2_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                     int value)
+{
+       return dln2_gpio_set_direction(chip, offset, DLN2_GPIO_DIRECTION_OUT);
+}
+
+static int dln2_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
+                                 unsigned debounce)
+{
+       struct dln2_gpio *dln2 = container_of(chip, struct dln2_gpio, gpio);
+       __le32 duration = cpu_to_le32(debounce);
+
+       return dln2_transfer_tx(dln2->pdev, DLN2_GPIO_SET_DEBOUNCE,
+                               &duration, sizeof(duration));
+}
+
+static int dln2_gpio_set_event_cfg(struct dln2_gpio *dln2, unsigned pin,
+                                  unsigned type, unsigned period)
+{
+       struct {
+               __le16 pin;
+               u8 type;
+               __le16 period;
+       } __packed req = {
+               .pin = cpu_to_le16(pin),
+               .type = type,
+               .period = cpu_to_le16(period),
+       };
+
+       return dln2_transfer_tx(dln2->pdev, DLN2_GPIO_PIN_SET_EVENT_CFG,
+                               &req, sizeof(req));
+}
+
+static void dln2_irq_work(struct work_struct *w)
+{
+       struct dln2_irq_work *iw = container_of(w, struct dln2_irq_work, work);
+       struct dln2_gpio *dln2 = iw->dln2;
+       u8 type = iw->type & DLN2_GPIO_EVENT_MASK;
+
+       if (test_bit(iw->pin, dln2->irqs_enabled))
+               dln2_gpio_set_event_cfg(dln2, iw->pin, type, 0);
+       else
+               dln2_gpio_set_event_cfg(dln2, iw->pin, DLN2_GPIO_EVENT_NONE, 0);
+}
+
+static void dln2_irq_enable(struct irq_data *irqd)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+       struct dln2_gpio *dln2 = container_of(gc, struct dln2_gpio, gpio);
+       int pin = irqd_to_hwirq(irqd);
+
+       set_bit(pin, dln2->irqs_enabled);
+       schedule_work(&dln2->irq_work[pin].work);
+}
+
+static void dln2_irq_disable(struct irq_data *irqd)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+       struct dln2_gpio *dln2 = container_of(gc, struct dln2_gpio, gpio);
+       int pin = irqd_to_hwirq(irqd);
+
+       clear_bit(pin, dln2->irqs_enabled);
+       schedule_work(&dln2->irq_work[pin].work);
+}
+
+static void dln2_irq_mask(struct irq_data *irqd)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+       struct dln2_gpio *dln2 = container_of(gc, struct dln2_gpio, gpio);
+       int pin = irqd_to_hwirq(irqd);
+
+       set_bit(pin, dln2->irqs_masked);
+}
+
+static void dln2_irq_unmask(struct irq_data *irqd)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+       struct dln2_gpio *dln2 = container_of(gc, struct dln2_gpio, gpio);
+       struct device *dev = dln2->gpio.dev;
+       int pin = irqd_to_hwirq(irqd);
+
+       if (test_and_clear_bit(pin, dln2->irqs_pending)) {
+               int irq;
+
+               irq = irq_find_mapping(dln2->gpio.irqdomain, pin);
+               if (!irq) {
+                       dev_err(dev, "pin %d not mapped to IRQ\n", pin);
+                       return;
+               }
+
+               generic_handle_irq(irq);
+       }
+}
+
+static int dln2_irq_set_type(struct irq_data *irqd, unsigned type)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
+       struct dln2_gpio *dln2 = container_of(gc, struct dln2_gpio, gpio);
+       int pin = irqd_to_hwirq(irqd);
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_HIGH:
+               dln2->irq_work[pin].type = DLN2_GPIO_EVENT_LVL_HIGH;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               dln2->irq_work[pin].type = DLN2_GPIO_EVENT_LVL_LOW;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               dln2->irq_work[pin].type = DLN2_GPIO_EVENT_CHANGE;
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+               dln2->irq_work[pin].type = DLN2_GPIO_EVENT_CHANGE_RISING;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               dln2->irq_work[pin].type = DLN2_GPIO_EVENT_CHANGE_FALLING;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct irq_chip dln2_gpio_irqchip = {
+       .name = "dln2-irq",
+       .irq_enable = dln2_irq_enable,
+       .irq_disable = dln2_irq_disable,
+       .irq_mask = dln2_irq_mask,
+       .irq_unmask = dln2_irq_unmask,
+       .irq_set_type = dln2_irq_set_type,
+};
+
+static void dln2_gpio_event(struct platform_device *pdev, u16 echo,
+                           const void *data, int len)
+{
+       int pin, irq;
+       const struct {
+               __le16 count;
+               __u8 type;
+               __le16 pin;
+               __u8 value;
+       } __packed *event = data;
+       struct dln2_gpio *dln2 = platform_get_drvdata(pdev);
+
+       if (len < sizeof(*event)) {
+               dev_err(dln2->gpio.dev, "short event message\n");
+               return;
+       }
+
+       pin = le16_to_cpu(event->pin);
+       if (pin >= dln2->gpio.ngpio) {
+               dev_err(dln2->gpio.dev, "out of bounds pin %d\n", pin);
+               return;
+       }
+
+       irq = irq_find_mapping(dln2->gpio.irqdomain, pin);
+       if (!irq) {
+               dev_err(dln2->gpio.dev, "pin %d not mapped to IRQ\n", pin);
+               return;
+       }
+
+       if (!test_bit(pin, dln2->irqs_enabled))
+               return;
+       if (test_bit(pin, dln2->irqs_masked)) {
+               set_bit(pin, dln2->irqs_pending);
+               return;
+       }
+
+       switch (dln2->irq_work[pin].type) {
+       case DLN2_GPIO_EVENT_CHANGE_RISING:
+               if (event->value)
+                       generic_handle_irq(irq);
+               break;
+       case DLN2_GPIO_EVENT_CHANGE_FALLING:
+               if (!event->value)
+                       generic_handle_irq(irq);
+               break;
+       default:
+               generic_handle_irq(irq);
+       }
+}
+
+static int dln2_gpio_probe(struct platform_device *pdev)
+{
+       struct dln2_gpio *dln2;
+       struct device *dev = &pdev->dev;
+       int pins;
+       int i, ret;
+
+       pins = dln2_gpio_get_pin_count(pdev);
+       if (pins < 0) {
+               dev_err(dev, "failed to get pin count: %d\n", pins);
+               return pins;
+       }
+       if (pins > DLN2_GPIO_MAX_PINS) {
+               pins = DLN2_GPIO_MAX_PINS;
+               dev_warn(dev, "clamping pins to %d\n", DLN2_GPIO_MAX_PINS);
+       }
+
+       dln2 = devm_kzalloc(&pdev->dev, sizeof(*dln2), GFP_KERNEL);
+       if (!dln2)
+               return -ENOMEM;
+
+       dln2->irq_work = devm_kcalloc(&pdev->dev, pins,
+                                     sizeof(struct dln2_irq_work), GFP_KERNEL);
+       if (!dln2->irq_work)
+               return -ENOMEM;
+       for (i = 0; i < pins; i++) {
+               INIT_WORK(&dln2->irq_work[i].work, dln2_irq_work);
+               dln2->irq_work[i].pin = i;
+               dln2->irq_work[i].dln2 = dln2;
+       }
+
+       dln2->pdev = pdev;
+
+       dln2->gpio.label = "dln2";
+       dln2->gpio.dev = dev;
+       dln2->gpio.owner = THIS_MODULE;
+       dln2->gpio.base = -1;
+       dln2->gpio.ngpio = pins;
+       dln2->gpio.exported = true;
+       dln2->gpio.can_sleep = true;
+       dln2->gpio.irq_not_threaded = true;
+       dln2->gpio.set = dln2_gpio_set;
+       dln2->gpio.get = dln2_gpio_get;
+       dln2->gpio.request = dln2_gpio_request;
+       dln2->gpio.free = dln2_gpio_free;
+       dln2->gpio.get_direction = dln2_gpio_get_direction;
+       dln2->gpio.direction_input = dln2_gpio_direction_input;
+       dln2->gpio.direction_output = dln2_gpio_direction_output;
+       dln2->gpio.set_debounce = dln2_gpio_set_debounce;
+
+       platform_set_drvdata(pdev, dln2);
+
+       ret = gpiochip_add(&dln2->gpio);
+       if (ret < 0) {
+               dev_err(dev, "failed to add gpio chip: %d\n", ret);
+               goto out;
+       }
+
+       ret = gpiochip_irqchip_add(&dln2->gpio, &dln2_gpio_irqchip, 0,
+                                  handle_simple_irq, IRQ_TYPE_NONE);
+       if (ret < 0) {
+               dev_err(dev, "failed to add irq chip: %d\n", ret);
+               goto out_gpiochip_remove;
+       }
+
+       ret = dln2_register_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV,
+                                    dln2_gpio_event);
+       if (ret) {
+               dev_err(dev, "failed to register event cb: %d\n", ret);
+               goto out_gpiochip_remove;
+       }
+
+       return 0;
+
+out_gpiochip_remove:
+       gpiochip_remove(&dln2->gpio);
+out:
+       return ret;
+}
+
+static int dln2_gpio_remove(struct platform_device *pdev)
+{
+       struct dln2_gpio *dln2 = platform_get_drvdata(pdev);
+       int i;
+
+       dln2_unregister_event_cb(pdev, DLN2_GPIO_CONDITION_MET_EV);
+       for (i = 0; i < dln2->gpio.ngpio; i++)
+               flush_work(&dln2->irq_work[i].work);
+       gpiochip_remove(&dln2->gpio);
+
+       return 0;
+}
+
+static struct platform_driver dln2_gpio_driver = {
+       .driver.name    = "dln2-gpio",
+       .probe          = dln2_gpio_probe,
+       .remove         = dln2_gpio_remove,
+};
+
+module_platform_driver(dln2_gpio_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
+MODULE_DESCRIPTION("Driver for the Diolan DLN2 GPIO interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dln2-gpio");
index ae0f6466eb09bf60e941b14966c62e0fbe7d1b77..abdcf58935f56c8c129b3b8d3f89a9e27c15a37a 100644 (file)
@@ -262,7 +262,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
        tc3589x_gpio->chip = template_chip;
        tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
        tc3589x_gpio->chip.dev = &pdev->dev;
-       tc3589x_gpio->chip.base = (pdata) ? pdata->gpio_base : -1;
+       tc3589x_gpio->chip.base = -1;
 
 #ifdef CONFIG_OF_GPIO
        tc3589x_gpio->chip.of_node = np;
index 9a0cc09e665308bd6d6a7c7b518b455f5acd050d..e4a1490b42c280bbc49fd8cfcdc51a4c84b473fe 100644 (file)
@@ -260,7 +260,7 @@ static void armada_drm_vblank_off(struct armada_crtc *dcrtc)
         * Tell the DRM core that vblank IRQs aren't going to happen for
         * a while.  This cleans up any pending vblank events for us.
         */
-       drm_vblank_off(dev, dcrtc->num);
+       drm_crtc_vblank_off(&dcrtc->crtc);
 
        /* Handle any pending flip event. */
        spin_lock_irq(&dev->event_lock);
@@ -289,6 +289,8 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms)
                armada_drm_crtc_update(dcrtc);
                if (dpms_blanked(dpms))
                        armada_drm_vblank_off(dcrtc);
+               else
+                       drm_crtc_vblank_on(&dcrtc->crtc);
        }
 }
 
@@ -526,7 +528,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
        /* Wait for pending flips to complete */
        wait_event(dcrtc->frame_wait, !dcrtc->frame_work);
 
-       drm_vblank_pre_modeset(crtc->dev, dcrtc->num);
+       drm_crtc_vblank_off(crtc);
 
        crtc->mode = *adj;
 
@@ -617,7 +619,7 @@ static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 
        armada_drm_crtc_update(dcrtc);
 
-       drm_vblank_post_modeset(crtc->dev, dcrtc->num);
+       drm_crtc_vblank_on(crtc);
        armada_drm_crtc_finish_fb(dcrtc, old_fb, dpms_blanked(dcrtc->dpms));
 
        return 0;
@@ -945,18 +947,15 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
        armada_reg_queue_end(work->regs, i);
 
        /*
-        * Hold the old framebuffer for the work - DRM appears to drop our
-        * reference to the old framebuffer in drm_mode_page_flip_ioctl().
+        * Ensure that we hold a reference on the new framebuffer.
+        * This has to match the behaviour in mode_set.
         */
-       drm_framebuffer_reference(work->old_fb);
+       drm_framebuffer_reference(fb);
 
        ret = armada_drm_crtc_queue_frame_work(dcrtc, work);
        if (ret) {
-               /*
-                * Undo our reference above; DRM does not drop the reference
-                * to this object on error, so that's okay.
-                */
-               drm_framebuffer_unreference(work->old_fb);
+               /* Undo our reference above */
+               drm_framebuffer_unreference(fb);
                kfree(work);
                return ret;
        }
index f672e6ad8afae05d42ebeb31b31bc9c3eb60c117..908e5316eac425ef7f71e8c7cf55d97b75ce853a 100644 (file)
@@ -190,6 +190,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags)
        if (ret)
                goto err_comp;
 
+       dev->irq_enabled = true;
        dev->vblank_disable_allowed = 1;
 
        ret = armada_fbdev_init(dev);
@@ -331,7 +332,7 @@ static struct drm_driver armada_drm_driver = {
        .desc                   = "Armada SoC DRM",
        .date                   = "20120730",
        .driver_features        = DRIVER_GEM | DRIVER_MODESET |
-                                 DRIVER_PRIME,
+                                 DRIVER_HAVE_IRQ | DRIVER_PRIME,
        .ioctls                 = armada_ioctls,
        .fops                   = &armada_drm_fops,
 };
index e705335101a59ea0a703d9b699d8ea7af9eafcb5..c2a1cba1e984546d63f033a4cf4b07ff3279bb16 100644 (file)
@@ -32,6 +32,8 @@ static struct drm_driver driver;
 static const struct pci_device_id pciidlist[] = {
        { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
          0, 0 },
+       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN,
+         0x0001, 0, 0, 0 },
        {0,}
 };
 
index cd50ece316016a403881ff7446f1ee9fdc512f9a..6adb1e5cfb086499537ea786a13e709da87a59ec 100644 (file)
@@ -1355,13 +1355,8 @@ static void exynos_dp_unbind(struct device *dev, struct device *master,
                                void *data)
 {
        struct exynos_drm_display *display = dev_get_drvdata(dev);
-       struct exynos_dp_device *dp = display->ctx;
-       struct drm_encoder *encoder = dp->encoder;
 
        exynos_dp_dpms(display, DRM_MODE_DPMS_OFF);
-
-       exynos_dp_connector_destroy(&dp->connector);
-       encoder->funcs->destroy(encoder);
 }
 
 static const struct component_ops exynos_dp_ops = {
index 8e38e9f8e542d17d9b793ceb1efed9cb3fcc0056..45026e693225bdc444aba756eec55fb90e138008 100644 (file)
@@ -71,13 +71,16 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
                                !atomic_read(&exynos_crtc->pending_flip),
                                HZ/20))
                        atomic_set(&exynos_crtc->pending_flip, 0);
-               drm_vblank_off(crtc->dev, exynos_crtc->pipe);
+               drm_crtc_vblank_off(crtc);
        }
 
        if (manager->ops->dpms)
                manager->ops->dpms(manager, mode);
 
        exynos_crtc->dpms = mode;
+
+       if (mode == DRM_MODE_DPMS_ON)
+               drm_crtc_vblank_on(crtc);
 }
 
 static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
index 96c87db388fb985614e7d4485b7df569dac40784..3dc678ed9949241737d1b0055044040d704439dd 100644 (file)
@@ -338,14 +338,10 @@ err_del_component:
 
 int exynos_dpi_remove(struct device *dev)
 {
-       struct drm_encoder *encoder = exynos_dpi_display.encoder;
        struct exynos_dpi *ctx = exynos_dpi_display.ctx;
 
        exynos_dpi_dpms(&exynos_dpi_display, DRM_MODE_DPMS_OFF);
 
-       exynos_dpi_connector_destroy(&ctx->connector);
-       encoder->funcs->destroy(encoder);
-
        if (ctx->panel)
                drm_panel_detach(ctx->panel);
 
index 443a2069858a7e8589599078802281cc465de709..e5c4c6c8c967066dc05f9964544520e9273a6d0a 100644 (file)
@@ -87,16 +87,12 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
                plane = exynos_plane_init(dev, possible_crtcs,
                                          DRM_PLANE_TYPE_OVERLAY);
-               if (IS_ERR(plane))
-                       goto err_mode_config_cleanup;
-       }
-
-       /* init kms poll for handling hpd */
-       drm_kms_helper_poll_init(dev);
+               if (!IS_ERR(plane))
+                       continue;
 
-       ret = drm_vblank_init(dev, MAX_CRTC);
-       if (ret)
+               ret = PTR_ERR(plane);
                goto err_mode_config_cleanup;
+       }
 
        /* setup possible_clones. */
        exynos_drm_encoder_setup(dev);
@@ -106,15 +102,16 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
        /* Try to bind all sub drivers. */
        ret = component_bind_all(dev->dev, dev);
        if (ret)
-               goto err_cleanup_vblank;
+               goto err_mode_config_cleanup;
 
-       /* Probe non kms sub drivers and virtual display driver. */
-       ret = exynos_drm_device_subdrv_probe(dev);
+       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
        if (ret)
                goto err_unbind_all;
 
-       /* force connectors detection */
-       drm_helper_hpd_irq_event(dev);
+       /* Probe non kms sub drivers and virtual display driver. */
+       ret = exynos_drm_device_subdrv_probe(dev);
+       if (ret)
+               goto err_cleanup_vblank;
 
        /*
         * enable drm irq mode.
@@ -133,12 +130,18 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
         */
        dev->vblank_disable_allowed = true;
 
+       /* init kms poll for handling hpd */
+       drm_kms_helper_poll_init(dev);
+
+       /* force connectors detection */
+       drm_helper_hpd_irq_event(dev);
+
        return 0;
 
-err_unbind_all:
-       component_unbind_all(dev->dev, dev);
 err_cleanup_vblank:
        drm_vblank_cleanup(dev);
+err_unbind_all:
+       component_unbind_all(dev->dev, dev);
 err_mode_config_cleanup:
        drm_mode_config_cleanup(dev);
        drm_release_iommu_mapping(dev);
@@ -155,8 +158,8 @@ static int exynos_drm_unload(struct drm_device *dev)
        exynos_drm_fbdev_fini(dev);
        drm_kms_helper_poll_fini(dev);
 
-       component_unbind_all(dev->dev, dev);
        drm_vblank_cleanup(dev);
+       component_unbind_all(dev->dev, dev);
        drm_mode_config_cleanup(dev);
        drm_release_iommu_mapping(dev);
 
@@ -191,8 +194,12 @@ static int exynos_drm_resume(struct drm_device *dev)
 
        drm_modeset_lock_all(dev);
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               if (connector->funcs->dpms)
-                       connector->funcs->dpms(connector, connector->dpms);
+               if (connector->funcs->dpms) {
+                       int dpms = connector->dpms;
+
+                       connector->dpms = DRM_MODE_DPMS_OFF;
+                       connector->funcs->dpms(connector, dpms);
+               }
        }
        drm_modeset_unlock_all(dev);
 
@@ -488,6 +495,12 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
 
        mutex_lock(&drm_component_lock);
 
+       /* Do not retry to probe if there is no any kms driver regitered. */
+       if (list_empty(&drm_component_list)) {
+               mutex_unlock(&drm_component_lock);
+               return ERR_PTR(-ENODEV);
+       }
+
        list_for_each_entry(cdev, &drm_component_list, list) {
                /*
                 * Add components to master only in case that crtc and
@@ -578,10 +591,21 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
                goto err_unregister_mixer_drv;
 #endif
 
+       match = exynos_drm_match_add(&pdev->dev);
+       if (IS_ERR(match)) {
+               ret = PTR_ERR(match);
+               goto err_unregister_hdmi_drv;
+       }
+
+       ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
+                                               match);
+       if (ret < 0)
+               goto err_unregister_hdmi_drv;
+
 #ifdef CONFIG_DRM_EXYNOS_G2D
        ret = platform_driver_register(&g2d_driver);
        if (ret < 0)
-               goto err_unregister_hdmi_drv;
+               goto err_del_component_master;
 #endif
 
 #ifdef CONFIG_DRM_EXYNOS_FIMC
@@ -612,23 +636,9 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
                goto err_unregister_ipp_drv;
 #endif
 
-       match = exynos_drm_match_add(&pdev->dev);
-       if (IS_ERR(match)) {
-               ret = PTR_ERR(match);
-               goto err_unregister_resources;
-       }
-
-       ret = component_master_add_with_match(&pdev->dev, &exynos_drm_ops,
-                                               match);
-       if (ret < 0)
-               goto err_unregister_resources;
-
        return ret;
 
-err_unregister_resources:
-
 #ifdef CONFIG_DRM_EXYNOS_IPP
-       exynos_platform_device_ipp_unregister();
 err_unregister_ipp_drv:
        platform_driver_unregister(&ipp_driver);
 err_unregister_gsc_drv:
@@ -651,9 +661,11 @@ err_unregister_g2d_drv:
 
 #ifdef CONFIG_DRM_EXYNOS_G2D
        platform_driver_unregister(&g2d_driver);
-err_unregister_hdmi_drv:
+err_del_component_master:
 #endif
+       component_master_del(&pdev->dev, &exynos_drm_ops);
 
+err_unregister_hdmi_drv:
 #ifdef CONFIG_DRM_EXYNOS_HDMI
        platform_driver_unregister(&hdmi_driver);
 err_unregister_mixer_drv:
@@ -734,6 +746,18 @@ static int exynos_drm_init(void)
 {
        int ret;
 
+       /*
+        * Register device object only in case of Exynos SoC.
+        *
+        * Below codes resolves temporarily infinite loop issue incurred
+        * by Exynos drm driver when using multi-platform kernel.
+        * So these codes will be replaced with more generic way later.
+        */
+       if (!of_machine_is_compatible("samsung,exynos3") &&
+                       !of_machine_is_compatible("samsung,exynos4") &&
+                       !of_machine_is_compatible("samsung,exynos5"))
+               return -ENODEV;
+
        exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1,
                                                                NULL, 0);
        if (IS_ERR(exynos_drm_pdev))
index 24741d8758e88521439f82309b656c35afa83785..acf7e9e39dcd86e11590d7398ee136a9f81d8a60 100644 (file)
@@ -1660,13 +1660,9 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master,
                                void *data)
 {
        struct exynos_dsi *dsi = exynos_dsi_display.ctx;
-       struct drm_encoder *encoder = dsi->encoder;
 
        exynos_dsi_dpms(&exynos_dsi_display, DRM_MODE_DPMS_OFF);
 
-       exynos_dsi_connector_destroy(&dsi->connector);
-       encoder->funcs->destroy(encoder);
-
        mipi_dsi_host_unregister(&dsi->dsi_host);
 }
 
index df7a77d3eff84b769342f04114a31a040a843769..6ff8599f6cbf0beb09dc48a5a1b1c7b110a739bf 100644 (file)
@@ -302,9 +302,12 @@ static void g2d_fini_cmdlist(struct g2d_data *g2d)
        struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
 
        kfree(g2d->cmdlist_node);
-       dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE,
-                       g2d->cmdlist_pool_virt,
-                       g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);
+
+       if (g2d->cmdlist_pool_virt && g2d->cmdlist_pool) {
+               dma_free_attrs(subdrv->drm_dev->dev, G2D_CMDLIST_POOL_SIZE,
+                               g2d->cmdlist_pool_virt,
+                               g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);
+       }
 }
 
 static struct g2d_cmdlist_node *g2d_get_cmdlist(struct g2d_data *g2d)
index d565207040a2590d416895b5dc9247ef68824492..50faf913e5749152f5d2a4dc29c655f33ce27f98 100644 (file)
@@ -630,7 +630,6 @@ static int vidi_remove(struct platform_device *pdev)
 {
        struct exynos_drm_manager *mgr = platform_get_drvdata(pdev);
        struct vidi_context *ctx = mgr->ctx;
-       struct drm_encoder *encoder = ctx->encoder;
 
        if (ctx->raw_edid != (struct edid *)fake_edid_info) {
                kfree(ctx->raw_edid);
@@ -639,9 +638,6 @@ static int vidi_remove(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       encoder->funcs->destroy(encoder);
-       drm_connector_cleanup(&ctx->connector);
-
        return 0;
 }
 
index 7910fb37d9bbd6df2092f0c7147d6e0a8b944875..563a19e62eb2cb5ccd9e13a7f35bc589c9824431 100644 (file)
@@ -2312,12 +2312,6 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
 
 static void hdmi_unbind(struct device *dev, struct device *master, void *data)
 {
-       struct exynos_drm_display *display = get_hdmi_display(dev);
-       struct drm_encoder *encoder = display->encoder;
-       struct hdmi_context *hdata = display->ctx;
-
-       hdmi_connector_destroy(&hdata->connector);
-       encoder->funcs->destroy(encoder);
 }
 
 static const struct component_ops hdmi_component_ops = {
index 1403b01e821695cce6c42cb8b3704eb284aba17e..318ade9bb5af54d786926983eb53f36115409583 100644 (file)
@@ -1670,15 +1670,17 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto out_regs;
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = i915_kick_out_vgacon(dev_priv);
+               /* WARNING: Apparently we must kick fbdev drivers before vgacon,
+                * otherwise the vga fbdev driver falls over. */
+               ret = i915_kick_out_firmware_fb(dev_priv);
                if (ret) {
-                       DRM_ERROR("failed to remove conflicting VGA console\n");
+                       DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
                        goto out_gtt;
                }
 
-               ret = i915_kick_out_firmware_fb(dev_priv);
+               ret = i915_kick_out_vgacon(dev_priv);
                if (ret) {
-                       DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
+                       DRM_ERROR("failed to remove conflicting VGA console\n");
                        goto out_gtt;
                }
        }
index 055d5e7fbf12a14473c7b82f314630d1e5615b9c..2318b4c7a8f82399ffbeba7b5d2704c1cd3e5ec0 100644 (file)
@@ -986,6 +986,15 @@ static int i915_pm_freeze(struct device *dev)
        return i915_drm_freeze(drm_dev);
 }
 
+static int i915_pm_freeze_late(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_i915_private *dev_priv = drm_dev->dev_private;
+
+       return intel_suspend_complete(dev_priv);
+}
+
 static int i915_pm_thaw_early(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -1570,6 +1579,7 @@ static const struct dev_pm_ops i915_pm_ops = {
        .resume_early = i915_pm_resume_early,
        .resume = i915_pm_resume,
        .freeze = i915_pm_freeze,
+       .freeze_late = i915_pm_freeze_late,
        .thaw_early = i915_pm_thaw_early,
        .thaw = i915_pm_thaw,
        .poweroff = i915_pm_poweroff,
index b672b843fd5e5831323094824116cffe912d8a55..728938f02341e31c2946724c5ac6c2d1c3ccbd50 100644 (file)
@@ -1902,6 +1902,22 @@ static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv)
              GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) |
              GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
 
+       if (!USES_PPGTT(dev_priv->dev))
+               /* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry,
+                * so RTL will always use the value corresponding to
+                * pat_sel = 000".
+                * So let's disable cache for GGTT to avoid screen corruptions.
+                * MOCS still can be used though.
+                * - System agent ggtt writes (i.e. cpu gtt mmaps) already work
+                * before this patch, i.e. the same uncached + snooping access
+                * like on gen6/7 seems to be in effect.
+                * - So this just fixes blitter/render access. Again it looks
+                * like it's not just uncached access, but uncached + snooping.
+                * So we can still hold onto all our assumptions wrt cpu
+                * clflushing on LLC machines.
+                */
+               pat = GEN8_PPAT(0, GEN8_PPAT_UC);
+
        /* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b
         * write would work. */
        I915_WRITE(GEN8_PRIVATE_PAT, pat);
index 2cefb597df6dc92d446557442073d5c998843a30..2b1eaa29ada448e2b6ec8b1d070482d7ee278933 100644 (file)
@@ -364,22 +364,9 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                 * has to also include the unfenced register the GPU uses
                 * whilst executing a fenced command for an untiled object.
                 */
-
-               obj->map_and_fenceable =
-                       !i915_gem_obj_ggtt_bound(obj) ||
-                       (i915_gem_obj_ggtt_offset(obj) +
-                        obj->base.size <= dev_priv->gtt.mappable_end &&
-                        i915_gem_object_fence_ok(obj, args->tiling_mode));
-
-               /* Rebind if we need a change of alignment */
-               if (!obj->map_and_fenceable) {
-                       u32 unfenced_align =
-                               i915_gem_get_gtt_alignment(dev, obj->base.size,
-                                                           args->tiling_mode,
-                                                           false);
-                       if (i915_gem_obj_ggtt_offset(obj) & (unfenced_align - 1))
-                               ret = i915_gem_object_ggtt_unbind(obj);
-               }
+               if (obj->map_and_fenceable &&
+                   !i915_gem_object_fence_ok(obj, args->tiling_mode))
+                       ret = i915_gem_object_ggtt_unbind(obj);
 
                if (ret == 0) {
                        obj->fence_dirty =
index 3201986bf25ebaf6a5b2a31089bd2e2b1871e09d..f66392b6e287c3036f420c022241a74108c65527 100644 (file)
@@ -1711,7 +1711,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
 #define HPD_STORM_DETECT_PERIOD 1000
 #define HPD_STORM_THRESHOLD 5
 
-static int ilk_port_to_hotplug_shift(enum port port)
+static int pch_port_to_hotplug_shift(enum port port)
 {
        switch (port) {
        case PORT_A:
@@ -1727,7 +1727,7 @@ static int ilk_port_to_hotplug_shift(enum port port)
        }
 }
 
-static int g4x_port_to_hotplug_shift(enum port port)
+static int i915_port_to_hotplug_shift(enum port port)
 {
        switch (port) {
        case PORT_A:
@@ -1785,12 +1785,12 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
                if (port && dev_priv->hpd_irq_port[port]) {
                        bool long_hpd;
 
-                       if (IS_G4X(dev)) {
-                               dig_shift = g4x_port_to_hotplug_shift(port);
-                               long_hpd = (hotplug_trigger >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
-                       } else {
-                               dig_shift = ilk_port_to_hotplug_shift(port);
+                       if (HAS_PCH_SPLIT(dev)) {
+                               dig_shift = pch_port_to_hotplug_shift(port);
                                long_hpd = (dig_hotplug_reg >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
+                       } else {
+                               dig_shift = i915_port_to_hotplug_shift(port);
+                               long_hpd = (hotplug_trigger >> dig_shift) & PORTB_HOTPLUG_LONG_DETECT;
                        }
 
                        DRM_DEBUG_DRIVER("digital hpd port %c - %s\n",
@@ -3458,12 +3458,13 @@ static void gen8_irq_reset(struct drm_device *dev)
 void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv)
 {
        unsigned long irqflags;
+       uint32_t extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN;
 
        spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
        GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_B, dev_priv->de_irq_mask[PIPE_B],
-                         ~dev_priv->de_irq_mask[PIPE_B]);
+                         ~dev_priv->de_irq_mask[PIPE_B] | extra_ier);
        GEN8_IRQ_INIT_NDX(DE_PIPE, PIPE_C, dev_priv->de_irq_mask[PIPE_C],
-                         ~dev_priv->de_irq_mask[PIPE_C]);
+                         ~dev_priv->de_irq_mask[PIPE_C] | extra_ier);
        spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
index 507370513f3d2e8494f4d4ad89fe265b0128e295..9cb5c95d58981341b6bcdba63e33a091517219ba 100644 (file)
@@ -73,9 +73,6 @@ static const uint32_t intel_cursor_formats[] = {
        DRM_FORMAT_ARGB8888,
 };
 
-#define DIV_ROUND_CLOSEST_ULL(ll, d)   \
-({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
-
 static void intel_increase_pllclock(struct drm_device *dev,
                                    enum pipe pipe);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
@@ -4328,7 +4325,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
                ironlake_fdi_disable(crtc);
 
                ironlake_disable_pch_transcoder(dev_priv, pipe);
-               intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
 
                if (HAS_PCH_CPT(dev)) {
                        /* disable TRANS_DP_CTL */
@@ -4392,7 +4388,6 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
        if (intel_crtc->config.has_pch_encoder) {
                lpt_disable_pch_transcoder(dev_priv);
-               intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
                intel_ddi_fdi_disable(crtc);
        }
 
@@ -4588,7 +4583,7 @@ static void vlv_update_cdclk(struct drm_device *dev)
         * BSpec erroneously claims we should aim for 4MHz, but
         * in fact 1MHz is the correct frequency.
         */
-       I915_WRITE(GMBUSFREQ_VLV, dev_priv->vlv_cdclk_freq);
+       I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->vlv_cdclk_freq, 1000));
 }
 
 /* Adjust CDclk dividers to allow high res or save power if possible */
@@ -9411,6 +9406,10 @@ static bool page_flip_finished(struct intel_crtc *crtc)
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       if (i915_reset_in_progress(&dev_priv->gpu_error) ||
+           crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
+               return true;
+
        /*
         * The relevant registers doen't exist on pre-ctg.
         * As the flip done interrupt doesn't trigger for mmio
@@ -12357,27 +12356,36 @@ static void intel_setup_outputs(struct drm_device *dev)
                if (I915_READ(PCH_DP_D) & DP_DETECTED)
                        intel_dp_init(dev, PCH_DP_D, PORT_D);
        } else if (IS_VALLEYVIEW(dev)) {
-               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) {
+               /*
+                * The DP_DETECTED bit is the latched state of the DDC
+                * SDA pin at boot. However since eDP doesn't require DDC
+                * (no way to plug in a DP->HDMI dongle) the DDC pins for
+                * eDP ports may have been muxed to an alternate function.
+                * Thus we can't rely on the DP_DETECTED bit alone to detect
+                * eDP ports. Consult the VBT as well as DP_DETECTED to
+                * detect eDP ports.
+                */
+               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED)
                        intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
                                        PORT_B);
-                       if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED)
-                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
-               }
+               if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED ||
+                   intel_dp_is_edp(dev, PORT_B))
+                       intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
 
-               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED) {
+               if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED)
                        intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
                                        PORT_C);
-                       if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
-                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
-               }
+               if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED ||
+                   intel_dp_is_edp(dev, PORT_C))
+                       intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
 
                if (IS_CHERRYVIEW(dev)) {
-                       if (I915_READ(VLV_DISPLAY_BASE + CHV_HDMID) & SDVO_DETECTED) {
+                       if (I915_READ(VLV_DISPLAY_BASE + CHV_HDMID) & SDVO_DETECTED)
                                intel_hdmi_init(dev, VLV_DISPLAY_BASE + CHV_HDMID,
                                                PORT_D);
-                               if (I915_READ(VLV_DISPLAY_BASE + DP_D) & DP_DETECTED)
-                                       intel_dp_init(dev, VLV_DISPLAY_BASE + DP_D, PORT_D);
-                       }
+                       /* eDP not supported on port D, so don't check VBT */
+                       if (I915_READ(VLV_DISPLAY_BASE + DP_D) & DP_DETECTED)
+                               intel_dp_init(dev, VLV_DISPLAY_BASE + DP_D, PORT_D);
                }
 
                intel_dsi_init(dev);
@@ -12879,6 +12887,9 @@ static struct intel_quirk intel_quirks[] = {
        /* Acer C720 Chromebook (Core i3 4005U) */
        { 0x0a16, 0x1025, 0x0a11, quirk_backlight_present },
 
+       /* Apple Macbook 2,1 (Core 2 T7400) */
+       { 0x27a2, 0x8086, 0x7270, quirk_backlight_present },
+
        /* Toshiba CB35 Chromebook (Celeron 2955U) */
        { 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
 
index f6a3fdd5589e33420e2f9b15ef4de42193eea356..4bcd9175732182dac168c60b0cd5a87730a527d1 100644 (file)
@@ -2806,6 +2806,13 @@ intel_dp_dpcd_read_wake(struct drm_dp_aux *aux, unsigned int offset,
        ssize_t ret;
        int i;
 
+       /*
+        * Sometime we just get the same incorrect byte repeated
+        * over the entire buffer. Doing just one throw away read
+        * initially seems to "solve" it.
+        */
+       drm_dp_dpcd_read(aux, DP_DPCD_REV, buffer, 1);
+
        for (i = 0; i < 3; i++) {
                ret = drm_dp_dpcd_read(aux, offset, buffer, size);
                if (ret == size)
@@ -3724,9 +3731,10 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
                }
        }
 
-       /* Training Pattern 3 support */
+       /* Training Pattern 3 support, both source and sink */
        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x12 &&
-           intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) {
+           intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED &&
+           (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)) {
                intel_dp->use_tps3 = true;
                DRM_DEBUG_KMS("Displayport TPS3 supported\n");
        } else
@@ -4442,6 +4450,7 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
         * vdd might still be enabled do to the delayed vdd off.
         * Make sure vdd is actually turned off here.
         */
+       cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
        pps_lock(intel_dp);
        edp_panel_vdd_off_sync(intel_dp);
        pps_unlock(intel_dp);
@@ -4491,6 +4500,18 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
        if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
                intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
 
+       if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
+               /*
+                * vdd off can generate a long pulse on eDP which
+                * would require vdd on to handle it, and thus we
+                * would end up in an endless cycle of
+                * "vdd off -> long hpd -> vdd on -> detect -> vdd off -> ..."
+                */
+               DRM_DEBUG_KMS("ignoring long hpd on eDP port %c\n",
+                             port_name(intel_dig_port->port));
+               return false;
+       }
+
        DRM_DEBUG_KMS("got hpd irq on port %c - %s\n",
                      port_name(intel_dig_port->port),
                      long_hpd ? "long" : "short");
index 07ce04683c3091a11afeacdee99e3b1b41c03461..ba715229a54016324411687113d730fec801c479 100644 (file)
@@ -35,6 +35,9 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_dp_mst_helper.h>
 
+#define DIV_ROUND_CLOSEST_ULL(ll, d)   \
+({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
+
 /**
  * _wait_for - magic (register) wait macro
  *
index a6bd1422e38fd33fccc19f2fd78684291c0f54d3..c0bbf21724461df812cd2dd2f87e585c4edd5116 100644 (file)
@@ -899,6 +899,17 @@ void intel_lvds_init(struct drm_device *dev)
        int pipe;
        u8 pin;
 
+       /*
+        * Unlock registers and just leave them unlocked. Do this before
+        * checking quirk lists to avoid bogus WARNINGs.
+        */
+       if (HAS_PCH_SPLIT(dev)) {
+               I915_WRITE(PCH_PP_CONTROL,
+                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
+       } else {
+               I915_WRITE(PP_CONTROL,
+                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
+       }
        if (!intel_lvds_supported(dev))
                return;
 
@@ -1097,17 +1108,6 @@ out:
        lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) &
                                 LVDS_A3_POWER_MASK;
 
-       /*
-        * Unlock registers and just
-        * leave them unlocked
-        */
-       if (HAS_PCH_SPLIT(dev)) {
-               I915_WRITE(PCH_PP_CONTROL,
-                          I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
-       } else {
-               I915_WRITE(PP_CONTROL,
-                          I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
-       }
        lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
        if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
                DRM_DEBUG_KMS("lid notifier registration failed\n");
index 18784470a760def6c6fd4af4938e53145acd4cab..41b3be217493b9a26315e2c69968f1c080161fe6 100644 (file)
@@ -419,9 +419,8 @@ static uint32_t scale(uint32_t source_val,
        source_val = clamp(source_val, source_min, source_max);
 
        /* avoid overflows */
-       target_val = (uint64_t)(source_val - source_min) *
-               (target_max - target_min);
-       do_div(target_val, source_max - source_min);
+       target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) *
+                       (target_max - target_min), source_max - source_min);
        target_val += target_min;
 
        return target_val;
@@ -1099,12 +1098,25 @@ static u32 get_backlight_min_vbt(struct intel_connector *connector)
        struct drm_device *dev = connector->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_panel *panel = &connector->panel;
+       int min;
 
        WARN_ON(panel->backlight.max == 0);
 
+       /*
+        * XXX: If the vbt value is 255, it makes min equal to max, which leads
+        * to problems. There are such machines out there. Either our
+        * interpretation is wrong or the vbt has bogus data. Or both. Safeguard
+        * against this by letting the minimum be at most (arbitrarily chosen)
+        * 25% of the max.
+        */
+       min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64);
+       if (min != dev_priv->vbt.backlight.min_brightness) {
+               DRM_DEBUG_KMS("clamping VBT min backlight %d/255 to %d/255\n",
+                             dev_priv->vbt.backlight.min_brightness, min);
+       }
+
        /* vbt value is a coefficient in range [0..255] */
-       return scale(dev_priv->vbt.backlight.min_brightness, 0, 255,
-                    0, panel->backlight.max);
+       return scale(min, 0, 255, 0, panel->backlight.max);
 }
 
 static int bdw_setup_backlight(struct intel_connector *connector)
index c27b6140bfd10e3912006f994da2bb75090c6b82..ad2fd605f76be43c847807996a0db06b8b8dbc05 100644 (file)
@@ -5469,11 +5469,6 @@ static void gen6_init_clock_gating(struct drm_device *dev)
        I915_WRITE(_3D_CHICKEN,
                   _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB));
 
-       /* WaSetupGtModeTdRowDispatch:snb */
-       if (IS_SNB_GT1(dev))
-               I915_WRITE(GEN6_GT_MODE,
-                          _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE));
-
        /* WaDisable_RenderCache_OperationalFlush:snb */
        I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 
index cd05677ad4b7a128a087f4b611f73b5ab4978006..72a40f95d048e06c9bc625ed2e0575edbce6e933 100644 (file)
@@ -218,7 +218,6 @@ nvc0_identify(struct nouveau_device *device)
                device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;
                device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;
                device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;
-               device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass;
                device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass;
                device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;
                break;
index 5ae6a43893b5996c0e13981851c71ed30947c5ad..1931057f996205d68ca93c94805211536c31aa4d 100644 (file)
@@ -551,8 +551,8 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
                        }
 
                        if (status & 0x40000000) {
-                               nouveau_fifo_uevent(&priv->base);
                                nv_wr32(priv, 0x002100, 0x40000000);
+                               nouveau_fifo_uevent(&priv->base);
                                status &= ~0x40000000;
                        }
                }
index 1fe1f8fbda0c0ab279d29630e7582fa48c607593..074d434c3077a53b74410b033a495ae58c3cd666 100644 (file)
@@ -740,6 +740,8 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
        u32 inte = nv_rd32(priv, 0x002628);
        u32 unkn;
 
+       nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr);
+
        for (unkn = 0; unkn < 8; unkn++) {
                u32 ints = (intr >> (unkn * 0x04)) & inte;
                if (ints & 0x1) {
@@ -751,8 +753,6 @@ nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn)
                        nv_mask(priv, 0x002628, ints, 0);
                }
        }
-
-       nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr);
 }
 
 static void
index d2f0fd39c1453c82e905c42ecf00551df7125f69..f8734eb74eaa083a3633256bf58ccb2f0298a337 100644 (file)
@@ -952,8 +952,8 @@ nve0_fifo_intr(struct nouveau_subdev *subdev)
        }
 
        if (stat & 0x80000000) {
-               nve0_fifo_intr_engine(priv);
                nv_wr32(priv, 0x002100, 0x80000000);
+               nve0_fifo_intr_engine(priv);
                stat &= ~0x80000000;
        }
 
index 552fdbd45ebe9e389c9e017d793959a6333a69e4..1d0e33fb5f617ac20b7610be037fa552722de078 100644 (file)
 #define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf)
 #define IS_NVAAF(x) ((x) >= 0xaa && (x) <= 0xac)
 
+#include <subdev/fb.h>
+
 /*
  * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's
  * the GPU itself that does context-switching, but it needs a special
@@ -569,8 +571,12 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
                        gr_def(ctx, 0x407d08, 0x00010040);
                else if (device->chipset < 0xa0)
                        gr_def(ctx, 0x407d08, 0x00390040);
-               else
-                       gr_def(ctx, 0x407d08, 0x003d0040);
+               else {
+                       if (nouveau_fb(device)->ram->type != NV_MEM_TYPE_GDDR5)
+                               gr_def(ctx, 0x407d08, 0x003d0040);
+                       else
+                               gr_def(ctx, 0x407d08, 0x003c0040);
+               }
                gr_def(ctx, 0x407d0c, 0x00000022);
        }
 
index a16024a747717e881d0d4e1464a02b1f6cdac45a..fde42e4d1b56002b733bac6f7d37ca90d6d09328 100644 (file)
@@ -26,6 +26,20 @@ struct gk20a_fb_priv {
        struct nouveau_fb base;
 };
 
+static int
+gk20a_fb_init(struct nouveau_object *object)
+{
+       struct gk20a_fb_priv *priv = (void *)object;
+       int ret;
+
+       ret = nouveau_fb_init(&priv->base);
+       if (ret)
+               return ret;
+
+       nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
+       return 0;
+}
+
 static int
 gk20a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
             struct nouveau_oclass *oclass, void *data, u32 size,
@@ -48,7 +62,7 @@ gk20a_fb_oclass = &(struct nouveau_fb_impl) {
        .base.ofuncs = &(struct nouveau_ofuncs) {
                .ctor = gk20a_fb_ctor,
                .dtor = _nouveau_fb_dtor,
-               .init = _nouveau_fb_init,
+               .init = gk20a_fb_init,
                .fini = _nouveau_fb_fini,
        },
        .memtype = nvc0_fb_memtype_valid,
index 589dbb582da200c543b2ee04e9296d58e0d70e1f..fd3dbd59d73e18113a6ef357e658570c113155be 100644 (file)
@@ -400,15 +400,20 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
                    struct nouveau_channel **pchan)
 {
        struct nouveau_cli *cli = (void *)nvif_client(&device->base);
+       bool super;
        int ret;
 
+       /* hack until fencenv50 is fixed, and agp access relaxed */
+       super = cli->base.super;
+       cli->base.super = true;
+
        ret = nouveau_channel_ind(drm, device, handle, arg0, pchan);
        if (ret) {
                NV_PRINTK(debug, cli, "ib channel create, %d\n", ret);
                ret = nouveau_channel_dma(drm, device, handle, pchan);
                if (ret) {
                        NV_PRINTK(debug, cli, "dma channel create, %d\n", ret);
-                       return ret;
+                       goto done;
                }
        }
 
@@ -416,8 +421,9 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
        if (ret) {
                NV_PRINTK(error, cli, "channel failed to initialise, %d\n", ret);
                nouveau_channel_del(pchan);
-               return ret;
        }
 
-       return 0;
+done:
+       cli->base.super = super;
+       return ret;
 }
index 57238076049f6fe16717ba6626bca954b1910aeb..62b97c4eef8dc0166490770e2691f00b5bfb487a 100644 (file)
@@ -629,7 +629,6 @@ int nouveau_pmops_suspend(struct device *dev)
 
        pci_save_state(pdev);
        pci_disable_device(pdev);
-       pci_ignore_hotplug(pdev);
        pci_set_power_state(pdev, PCI_D3hot);
        return 0;
 }
@@ -933,6 +932,7 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)
        ret = nouveau_do_suspend(drm_dev, true);
        pci_save_state(pdev);
        pci_disable_device(pdev);
+       pci_ignore_hotplug(pdev);
        pci_set_power_state(pdev, PCI_D3cold);
        drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
        return ret;
index 515cd9aebb9982d1c0c0c06f1deaf4d0c7bf3e5c..f32a434724e307f5da958de0bdf26bb09d115f4b 100644 (file)
@@ -52,20 +52,24 @@ nouveau_fctx(struct nouveau_fence *fence)
        return container_of(fence->base.lock, struct nouveau_fence_chan, lock);
 }
 
-static void
+static int
 nouveau_fence_signal(struct nouveau_fence *fence)
 {
+       int drop = 0;
+
        fence_signal_locked(&fence->base);
        list_del(&fence->head);
+       rcu_assign_pointer(fence->channel, NULL);
 
        if (test_bit(FENCE_FLAG_USER_BITS, &fence->base.flags)) {
                struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
 
                if (!--fctx->notify_ref)
-                       nvif_notify_put(&fctx->notify);
+                       drop = 1;
        }
 
        fence_put(&fence->base);
+       return drop;
 }
 
 static struct nouveau_fence *
@@ -88,16 +92,23 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
 {
        struct nouveau_fence *fence;
 
-       nvif_notify_fini(&fctx->notify);
-
        spin_lock_irq(&fctx->lock);
        while (!list_empty(&fctx->pending)) {
                fence = list_entry(fctx->pending.next, typeof(*fence), head);
 
-               nouveau_fence_signal(fence);
-               fence->channel = NULL;
+               if (nouveau_fence_signal(fence))
+                       nvif_notify_put(&fctx->notify);
        }
        spin_unlock_irq(&fctx->lock);
+
+       nvif_notify_fini(&fctx->notify);
+       fctx->dead = 1;
+
+       /*
+        * Ensure that all accesses to fence->channel complete before freeing
+        * the channel.
+        */
+       synchronize_rcu();
 }
 
 static void
@@ -112,21 +123,23 @@ nouveau_fence_context_free(struct nouveau_fence_chan *fctx)
        kref_put(&fctx->fence_ref, nouveau_fence_context_put);
 }
 
-static void
+static int
 nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fctx)
 {
        struct nouveau_fence *fence;
-
+       int drop = 0;
        u32 seq = fctx->read(chan);
 
        while (!list_empty(&fctx->pending)) {
                fence = list_entry(fctx->pending.next, typeof(*fence), head);
 
                if ((int)(seq - fence->base.seqno) < 0)
-                       return;
+                       break;
 
-               nouveau_fence_signal(fence);
+               drop |= nouveau_fence_signal(fence);
        }
+
+       return drop;
 }
 
 static int
@@ -135,18 +148,21 @@ nouveau_fence_wait_uevent_handler(struct nvif_notify *notify)
        struct nouveau_fence_chan *fctx =
                container_of(notify, typeof(*fctx), notify);
        unsigned long flags;
+       int ret = NVIF_NOTIFY_KEEP;
 
        spin_lock_irqsave(&fctx->lock, flags);
        if (!list_empty(&fctx->pending)) {
                struct nouveau_fence *fence;
+               struct nouveau_channel *chan;
 
                fence = list_entry(fctx->pending.next, typeof(*fence), head);
-               nouveau_fence_update(fence->channel, fctx);
+               chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
+               if (nouveau_fence_update(fence->channel, fctx))
+                       ret = NVIF_NOTIFY_DROP;
        }
        spin_unlock_irqrestore(&fctx->lock, flags);
 
-       /* Always return keep here. NVIF refcount is handled with nouveau_fence_update */
-       return NVIF_NOTIFY_KEEP;
+       return ret;
 }
 
 void
@@ -262,7 +278,10 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
        if (!ret) {
                fence_get(&fence->base);
                spin_lock_irq(&fctx->lock);
-               nouveau_fence_update(chan, fctx);
+
+               if (nouveau_fence_update(chan, fctx))
+                       nvif_notify_put(&fctx->notify);
+
                list_add_tail(&fence->head, &fctx->pending);
                spin_unlock_irq(&fctx->lock);
        }
@@ -276,13 +295,16 @@ nouveau_fence_done(struct nouveau_fence *fence)
        if (fence->base.ops == &nouveau_fence_ops_legacy ||
            fence->base.ops == &nouveau_fence_ops_uevent) {
                struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
+               struct nouveau_channel *chan;
                unsigned long flags;
 
                if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
                        return true;
 
                spin_lock_irqsave(&fctx->lock, flags);
-               nouveau_fence_update(fence->channel, fctx);
+               chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
+               if (chan && nouveau_fence_update(chan, fctx))
+                       nvif_notify_put(&fctx->notify);
                spin_unlock_irqrestore(&fctx->lock, flags);
        }
        return fence_is_signaled(&fence->base);
@@ -387,12 +409,18 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 
        if (fence && (!exclusive || !fobj || !fobj->shared_count)) {
                struct nouveau_channel *prev = NULL;
+               bool must_wait = true;
 
                f = nouveau_local_fence(fence, chan->drm);
-               if (f)
-                       prev = f->channel;
+               if (f) {
+                       rcu_read_lock();
+                       prev = rcu_dereference(f->channel);
+                       if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0))
+                               must_wait = false;
+                       rcu_read_unlock();
+               }
 
-               if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan))))
+               if (must_wait)
                        ret = fence_wait(fence, intr);
 
                return ret;
@@ -403,19 +431,22 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 
        for (i = 0; i < fobj->shared_count && !ret; ++i) {
                struct nouveau_channel *prev = NULL;
+               bool must_wait = true;
 
                fence = rcu_dereference_protected(fobj->shared[i],
                                                reservation_object_held(resv));
 
                f = nouveau_local_fence(fence, chan->drm);
-               if (f)
-                       prev = f->channel;
+               if (f) {
+                       rcu_read_lock();
+                       prev = rcu_dereference(f->channel);
+                       if (prev && (prev == chan || fctx->sync(f, prev, chan) == 0))
+                               must_wait = false;
+                       rcu_read_unlock();
+               }
 
-               if (!prev || (prev != chan && (ret = fctx->sync(f, prev, chan))))
+               if (must_wait)
                        ret = fence_wait(fence, intr);
-
-               if (ret)
-                       break;
        }
 
        return ret;
@@ -463,7 +494,7 @@ static const char *nouveau_fence_get_timeline_name(struct fence *f)
        struct nouveau_fence *fence = from_fence(f);
        struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
 
-       return fence->channel ? fctx->name : "dead channel";
+       return !fctx->dead ? fctx->name : "dead channel";
 }
 
 /*
@@ -476,9 +507,16 @@ static bool nouveau_fence_is_signaled(struct fence *f)
 {
        struct nouveau_fence *fence = from_fence(f);
        struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
-       struct nouveau_channel *chan = fence->channel;
+       struct nouveau_channel *chan;
+       bool ret = false;
+
+       rcu_read_lock();
+       chan = rcu_dereference(fence->channel);
+       if (chan)
+               ret = (int)(fctx->read(chan) - fence->base.seqno) >= 0;
+       rcu_read_unlock();
 
-       return (int)(fctx->read(chan) - fence->base.seqno) >= 0;
+       return ret;
 }
 
 static bool nouveau_fence_no_signaling(struct fence *f)
index 943b0b17b1fc760296eccea9b409f03696a644fc..96e461c6f68fac370602777d8e5bd363100fa0a5 100644 (file)
@@ -14,7 +14,7 @@ struct nouveau_fence {
 
        bool sysmem;
 
-       struct nouveau_channel *channel;
+       struct nouveau_channel __rcu *channel;
        unsigned long timeout;
 };
 
@@ -47,7 +47,7 @@ struct nouveau_fence_chan {
        char name[32];
 
        struct nvif_notify notify;
-       int notify_ref;
+       int notify_ref, dead;
 };
 
 struct nouveau_fence_priv {
index ae873d1a8d463f7cd55da92b550eec1c44d31e25..eb8b36714fa1c2e481ae67150626f2cf6ade3847 100644 (file)
@@ -790,6 +790,22 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
        return 0;
 }
 
+static int
+nv50_crtc_set_raster_vblank_dmi(struct nouveau_crtc *nv_crtc, u32 usec)
+{
+       struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
+       u32 *push;
+
+       push = evo_wait(mast, 8);
+       if (!push)
+               return -ENOMEM;
+
+       evo_mthd(push, 0x0828 + (nv_crtc->index * 0x400), 1);
+       evo_data(push, usec);
+       evo_kick(push, mast);
+       return 0;
+}
+
 static int
 nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
 {
@@ -1104,14 +1120,14 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
                        evo_mthd(push, 0x0804 + (nv_crtc->index * 0x400), 2);
                        evo_data(push, 0x00800000 | mode->clock);
                        evo_data(push, (ilace == 2) ? 2 : 0);
-                       evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 8);
+                       evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 6);
                        evo_data(push, 0x00000000);
                        evo_data(push, (vactive << 16) | hactive);
                        evo_data(push, ( vsynce << 16) | hsynce);
                        evo_data(push, (vblanke << 16) | hblanke);
                        evo_data(push, (vblanks << 16) | hblanks);
                        evo_data(push, (vblan2e << 16) | vblan2s);
-                       evo_data(push, vblankus);
+                       evo_mthd(push, 0x082c + (nv_crtc->index * 0x400), 1);
                        evo_data(push, 0x00000000);
                        evo_mthd(push, 0x0900 + (nv_crtc->index * 0x400), 2);
                        evo_data(push, 0x00000311);
@@ -1141,6 +1157,11 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
        nv_connector = nouveau_crtc_connector_get(nv_crtc);
        nv50_crtc_set_dither(nv_crtc, false);
        nv50_crtc_set_scale(nv_crtc, false);
+
+       /* G94 only accepts this after setting scale */
+       if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA)
+               nv50_crtc_set_raster_vblank_dmi(nv_crtc, vblankus);
+
        nv50_crtc_set_color_vibrance(nv_crtc, false);
        nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
        return 0;
index af9e785466883ae52a9812620421221af0630894..0d13962668578748af69ab19827c6f90598a36bf 100644 (file)
@@ -572,7 +572,6 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
        struct qxl_framebuffer *qfb;
        struct qxl_bo *bo, *old_bo = NULL;
        struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
-       uint32_t width, height, base_offset;
        bool recreate_primary = false;
        int ret;
        int surf_id;
@@ -602,9 +601,10 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
        if (qcrtc->index == 0)
                recreate_primary = true;
 
-       width = mode->hdisplay;
-       height = mode->vdisplay;
-       base_offset = 0;
+       if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
+               DRM_ERROR("Mode doesn't fit in vram size (vgamem)");
+               return -EINVAL;
+        }
 
        ret = qxl_bo_reserve(bo, false);
        if (ret != 0)
@@ -618,10 +618,10 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
        if (recreate_primary) {
                qxl_io_destroy_primary(qdev);
                qxl_io_log(qdev,
-                          "recreate primary: %dx%d (was %dx%d,%d,%d)\n",
-                          width, height, bo->surf.width,
-                          bo->surf.height, bo->surf.stride, bo->surf.format);
-               qxl_io_create_primary(qdev, base_offset, bo);
+                          "recreate primary: %dx%d,%d,%d\n",
+                          bo->surf.width, bo->surf.height,
+                          bo->surf.stride, bo->surf.format);
+               qxl_io_create_primary(qdev, 0, bo);
                bo->is_primary = true;
        }
 
index 15da7ef344a4e55fa11d604c21269e97ab361386..ec1593a6a561b550d873033d1c9cd7c9e6974af4 100644 (file)
@@ -1217,7 +1217,7 @@ free:
        return ret;
 }
 
-int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+int atom_execute_table_scratch_unlocked(struct atom_context *ctx, int index, uint32_t * params)
 {
        int r;
 
@@ -1238,6 +1238,15 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
        return r;
 }
 
+int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params)
+{
+       int r;
+       mutex_lock(&ctx->scratch_mutex);
+       r = atom_execute_table_scratch_unlocked(ctx, index, params);
+       mutex_unlock(&ctx->scratch_mutex);
+       return r;
+}
+
 static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 };
 
 static void atom_index_iio(struct atom_context *ctx, int base)
index feba6b8d36b346640ba09f19e571e069cb575f8f..6d014ddb6b7837f035bb332a9b9d12b22256c741 100644 (file)
@@ -125,6 +125,7 @@ struct card_info {
 struct atom_context {
        struct card_info *card;
        struct mutex mutex;
+       struct mutex scratch_mutex;
        void *bios;
        uint32_t cmd_table, data_table;
        uint16_t *iio;
@@ -145,6 +146,7 @@ extern int atom_debug;
 
 struct atom_context *atom_parse(struct card_info *, void *);
 int atom_execute_table(struct atom_context *, int, uint32_t *);
+int atom_execute_table_scratch_unlocked(struct atom_context *, int, uint32_t *);
 int atom_asic_init(struct atom_context *);
 void atom_destroy(struct atom_context *);
 bool atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size,
index 95d5d4ab3335edd2c86146c487c9cbd7bc269182..11ba9d21b89b608788f623822bcfb6f9f14dbbf1 100644 (file)
@@ -100,6 +100,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
        memset(&args, 0, sizeof(args));
 
        mutex_lock(&chan->mutex);
+       mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);
 
        base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
 
@@ -113,7 +114,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
        if (ASIC_IS_DCE4(rdev))
                args.v2.ucHPD_ID = chan->rec.hpd;
 
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+       atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 
        *ack = args.v1.ucReplyStatus;
 
@@ -147,6 +148,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
 
        r = recv_bytes;
 done:
+       mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
        mutex_unlock(&chan->mutex);
 
        return r;
index 9c570fb15b8c2e49a9765787d26a58a1467c8e0e..4157780585a0e8e89811e97349d99eb7bf026202 100644 (file)
@@ -48,6 +48,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
        memset(&args, 0, sizeof(args));
 
        mutex_lock(&chan->mutex);
+       mutex_lock(&rdev->mode_info.atom_context->scratch_mutex);
 
        base = (unsigned char *)rdev->mode_info.atom_context->scratch;
 
@@ -82,7 +83,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
        args.ucSlaveAddr = slave_addr << 1;
        args.ucLineNumber = chan->rec.i2c_id;
 
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+       atom_execute_table_scratch_unlocked(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 
        /* error */
        if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {
@@ -95,6 +96,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
                radeon_atom_copy_swap(buf, base, num, false);
 
 done:
+       mutex_unlock(&rdev->mode_info.atom_context->scratch_mutex);
        mutex_unlock(&chan->mutex);
 
        return r;
index 300d971187c4fca19f5b9676cb92d74c6b712969..0b2929de9f41b6839eb0e0f63b5f88bae70fe392 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "btcd.h"
 #include "r600_dpm.h"
 #include "cypress_dpm.h"
@@ -1170,6 +1171,23 @@ static const struct radeon_blacklist_clocks btc_blacklist_clocks[] =
         { 25000, 30000, RADEON_SCLK_UP }
 };
 
+void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table,
+                                                    u32 *max_clock)
+{
+       u32 i, clock = 0;
+
+       if ((table == NULL) || (table->count == 0)) {
+               *max_clock = clock;
+               return;
+       }
+
+       for (i = 0; i < table->count; i++) {
+               if (clock < table->entries[i].clk)
+                       clock = table->entries[i].clk;
+       }
+       *max_clock = clock;
+}
+
 void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
                                        u32 clock, u16 max_voltage, u16 *voltage)
 {
index 1a15e0e41950604ec8c27df9b11c6933c43d622d..3b6f12b7760ba48066f2144b73e0dc82c6521946 100644 (file)
@@ -46,6 +46,8 @@ void btc_adjust_clock_combinations(struct radeon_device *rdev,
                                   struct rv7xx_pl *pl);
 void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
                                        u32 clock, u16 max_voltage, u16 *voltage);
+void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table,
+                                                    u32 *max_clock);
 void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
                                   u16 max_vddc, u16 max_vddci,
                                   u16 *vddc, u16 *vddci);
index f5c8c0445a94bd1b75a48c38be49a09301e8674b..11a55e9dad7fef5d04ae838a6b7ae2c2f6b04958 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/firmware.h>
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "radeon_ucode.h"
 #include "cikd.h"
 #include "r600_dpm.h"
index 377afa504d2bd045cfdc5f2eed06599610c30920..89c01fa6dd8e3208fc428379e36264560133b818 100644 (file)
@@ -4313,8 +4313,8 @@ static int cik_cp_gfx_start(struct radeon_device *rdev)
        /* init the CE partitions.  CE only used for gfx on CIK */
        radeon_ring_write(ring, PACKET3(PACKET3_SET_BASE, 2));
        radeon_ring_write(ring, PACKET3_BASE_INDEX(CE_PARTITION_BASE));
-       radeon_ring_write(ring, 0xc000);
-       radeon_ring_write(ring, 0xc000);
+       radeon_ring_write(ring, 0x8000);
+       radeon_ring_write(ring, 0x8000);
 
        /* setup clear context state */
        radeon_ring_write(ring, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
@@ -9447,6 +9447,9 @@ void dce8_bandwidth_update(struct radeon_device *rdev)
        u32 num_heads = 0, lb_size;
        int i;
 
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        radeon_update_display_priority(rdev);
 
        for (i = 0; i < rdev->num_crtc; i++) {
index c77dad1a45769b151526377fac7e601129ee9221..d748963af08b7ea3215cf6dcfbf9ff92bbec8b69 100644 (file)
@@ -611,16 +611,19 @@ int cik_sdma_ring_test(struct radeon_device *rdev,
 {
        unsigned i;
        int r;
-       void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
+       unsigned index;
        u32 tmp;
+       u64 gpu_addr;
 
-       if (!ptr) {
-               DRM_ERROR("invalid vram scratch pointer\n");
-               return -EINVAL;
-       }
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               index = R600_WB_DMA_RING_TEST_OFFSET;
+       else
+               index = CAYMAN_WB_DMA1_RING_TEST_OFFSET;
+
+       gpu_addr = rdev->wb.gpu_addr + index;
 
        tmp = 0xCAFEDEAD;
-       writel(tmp, ptr);
+       rdev->wb.wb[index/4] = cpu_to_le32(tmp);
 
        r = radeon_ring_lock(rdev, ring, 5);
        if (r) {
@@ -628,14 +631,14 @@ int cik_sdma_ring_test(struct radeon_device *rdev,
                return r;
        }
        radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0));
-       radeon_ring_write(ring, rdev->vram_scratch.gpu_addr & 0xfffffffc);
-       radeon_ring_write(ring, upper_32_bits(rdev->vram_scratch.gpu_addr));
+       radeon_ring_write(ring, lower_32_bits(gpu_addr));
+       radeon_ring_write(ring, upper_32_bits(gpu_addr));
        radeon_ring_write(ring, 1); /* number of DWs to follow */
        radeon_ring_write(ring, 0xDEADBEEF);
        radeon_ring_unlock_commit(rdev, ring, false);
 
        for (i = 0; i < rdev->usec_timeout; i++) {
-               tmp = readl(ptr);
+               tmp = le32_to_cpu(rdev->wb.wb[index/4]);
                if (tmp == 0xDEADBEEF)
                        break;
                DRM_UDELAY(1);
@@ -664,17 +667,20 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        struct radeon_ib ib;
        unsigned i;
+       unsigned index;
        int r;
-       void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
        u32 tmp = 0;
+       u64 gpu_addr;
 
-       if (!ptr) {
-               DRM_ERROR("invalid vram scratch pointer\n");
-               return -EINVAL;
-       }
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               index = R600_WB_DMA_RING_TEST_OFFSET;
+       else
+               index = CAYMAN_WB_DMA1_RING_TEST_OFFSET;
+
+       gpu_addr = rdev->wb.gpu_addr + index;
 
        tmp = 0xCAFEDEAD;
-       writel(tmp, ptr);
+       rdev->wb.wb[index/4] = cpu_to_le32(tmp);
 
        r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256);
        if (r) {
@@ -683,8 +689,8 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
        }
 
        ib.ptr[0] = SDMA_PACKET(SDMA_OPCODE_WRITE, SDMA_WRITE_SUB_OPCODE_LINEAR, 0);
-       ib.ptr[1] = rdev->vram_scratch.gpu_addr & 0xfffffffc;
-       ib.ptr[2] = upper_32_bits(rdev->vram_scratch.gpu_addr);
+       ib.ptr[1] = lower_32_bits(gpu_addr);
+       ib.ptr[2] = upper_32_bits(gpu_addr);
        ib.ptr[3] = 1;
        ib.ptr[4] = 0xDEADBEEF;
        ib.length_dw = 5;
@@ -701,7 +707,7 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
                return r;
        }
        for (i = 0; i < rdev->usec_timeout; i++) {
-               tmp = readl(ptr);
+               tmp = le32_to_cpu(rdev->wb.wb[index/4]);
                if (tmp == 0xDEADBEEF)
                        break;
                DRM_UDELAY(1);
index 47d31e9157588d4bfb3d3131d20073e44e41d90b..9aad0327e4d1c22fdd7a1e5166a55e876ab4a040 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "evergreend.h"
 #include "r600_dpm.h"
 #include "cypress_dpm.h"
index 950af153f30e7a53748a0cdb943b9457db468f26..2fe8cfc966d9304b6845f6f6d29c9e236d80b0cb 100644 (file)
@@ -32,7 +32,7 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        struct drm_connector *connector;
        struct radeon_connector *radeon_connector = NULL;
        u32 tmp;
-       u8 *sadb;
+       u8 *sadb = NULL;
        int sad_count;
 
        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
@@ -49,8 +49,8 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder)
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
        if (sad_count < 0) {
-               DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-               return;
+               DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
+               sad_count = 0;
        }
 
        /* program the speaker allocation */
index c0bbf68dbc274f4d2055ea8f19850cdf3f6c747f..f312edf4d50eaedeac6fca1af4de8a8457b10e17 100644 (file)
@@ -155,7 +155,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        struct drm_connector *connector;
        struct radeon_connector *radeon_connector = NULL;
        u32 offset, tmp;
-       u8 *sadb;
+       u8 *sadb = NULL;
        int sad_count;
 
        if (!dig || !dig->afmt || !dig->afmt->pin)
@@ -176,9 +176,9 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
-       if (sad_count <= 0) {
-               DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-               return;
+       if (sad_count < 0) {
+               DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
+               sad_count = 0;
        }
 
        /* program the speaker allocation */
index a31f1ca40c6a7e81d06309e82bba86d3192a3562..85995b4e33387586448629c44ae31bbff103f10e 100644 (file)
@@ -2345,6 +2345,9 @@ void evergreen_bandwidth_update(struct radeon_device *rdev)
        u32 num_heads = 0, lb_size;
        int i;
 
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        radeon_update_display_priority(rdev);
 
        for (i = 0; i < rdev->num_crtc; i++) {
@@ -2552,6 +2555,7 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                                        WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
                                        tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
                                        WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+                                       WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
                                }
                        } else {
                                tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
@@ -3005,7 +3009,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        u32 vgt_cache_invalidation;
        u32 hdp_host_path_cntl, tmp;
        u32 disabled_rb_mask;
-       int i, j, num_shader_engines, ps_thread_count;
+       int i, j, ps_thread_count;
 
        switch (rdev->family) {
        case CHIP_CYPRESS:
@@ -3303,8 +3307,6 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
        rdev->config.evergreen.tile_config |=
                ((gb_addr_config & 0x30000000) >> 28) << 12;
 
-       num_shader_engines = (gb_addr_config & NUM_SHADER_ENGINES(3) >> 12) + 1;
-
        if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) {
                u32 efuse_straps_4;
                u32 efuse_straps_3;
index 2514d659b1ba1783fb4c6474ea6e45d0b3a1b941..53abd9b17a50b0490dd24b468461ccaab7b54e87 100644 (file)
@@ -133,7 +133,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        struct drm_connector *connector;
        struct radeon_connector *radeon_connector = NULL;
        u32 tmp;
-       u8 *sadb;
+       u8 *sadb = NULL;
        int sad_count;
 
        list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
@@ -149,9 +149,9 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
        }
 
        sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
-       if (sad_count <= 0) {
-               DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
-               return;
+       if (sad_count < 0) {
+               DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
+               sad_count = 0;
        }
 
        /* program the speaker allocation */
index 1dd976f447faccd700fcfeac3ebc14cebbdd1320..9b42001295ba587197f5bcb317daca4a0f83cb3d 100644 (file)
@@ -2725,7 +2725,11 @@ int kv_dpm_init(struct radeon_device *rdev)
 
         pi->sram_end = SMC_RAM_END;
 
-       pi->enable_nb_dpm = true;
+       /* Enabling nb dpm on an asrock system prevents dpm from working */
+       if (rdev->pdev->subsystem_vendor == 0x1849)
+               pi->enable_nb_dpm = false;
+       else
+               pi->enable_nb_dpm = true;
 
        pi->caps_power_containment = true;
        pi->caps_cac = true;
@@ -2740,10 +2744,19 @@ int kv_dpm_init(struct radeon_device *rdev)
        pi->caps_sclk_ds = true;
        pi->enable_auto_thermal_throttling = true;
        pi->disable_nb_ps3_in_battery = false;
-       if (radeon_bapm == 0)
+       if (radeon_bapm == -1) {
+               /* There are stability issues reported on with
+                * bapm enabled on an asrock system.
+                */
+               if (rdev->pdev->subsystem_vendor == 0x1849)
+                       pi->bapm_enable = false;
+               else
+                       pi->bapm_enable = true;
+       } else if (radeon_bapm == 0) {
                pi->bapm_enable = false;
-       else
+       } else {
                pi->bapm_enable = true;
+       }
        pi->voltage_drop_t = 0;
        pi->caps_sclk_throttle_low_notification = false;
        pi->caps_fps = false; /* true? */
index 715b181c6243503228bb638f39c36a60ac4acf2a..6d2f16cf2c1cf2cfcc5dd4e4c1baec731d221426 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "nid.h"
 #include "r600_dpm.h"
 #include "ni_dpm.h"
index 10f8be0ee1736394acaf9bac24eb516707917fd2..b53b31a7b76fd67f17614a2889c5f00a1e35441e 100644 (file)
@@ -3207,6 +3207,9 @@ void r100_bandwidth_update(struct radeon_device *rdev)
        uint32_t pixel_bytes1 = 0;
        uint32_t pixel_bytes2 = 0;
 
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        radeon_update_display_priority(rdev);
 
        if (rdev->mode_info.crtcs[0]->base.enabled) {
index 100189ec5fa85133b840851d4def58bbbae6ffc0..cf0df45d455e91ae3a363095dd02dccbb728bab3 100644 (file)
@@ -232,16 +232,19 @@ int r600_dma_ring_test(struct radeon_device *rdev,
 {
        unsigned i;
        int r;
-       void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
+       unsigned index;
        u32 tmp;
+       u64 gpu_addr;
 
-       if (!ptr) {
-               DRM_ERROR("invalid vram scratch pointer\n");
-               return -EINVAL;
-       }
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               index = R600_WB_DMA_RING_TEST_OFFSET;
+       else
+               index = CAYMAN_WB_DMA1_RING_TEST_OFFSET;
+
+       gpu_addr = rdev->wb.gpu_addr + index;
 
        tmp = 0xCAFEDEAD;
-       writel(tmp, ptr);
+       rdev->wb.wb[index/4] = cpu_to_le32(tmp);
 
        r = radeon_ring_lock(rdev, ring, 4);
        if (r) {
@@ -249,13 +252,13 @@ int r600_dma_ring_test(struct radeon_device *rdev,
                return r;
        }
        radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1));
-       radeon_ring_write(ring, rdev->vram_scratch.gpu_addr & 0xfffffffc);
-       radeon_ring_write(ring, upper_32_bits(rdev->vram_scratch.gpu_addr) & 0xff);
+       radeon_ring_write(ring, lower_32_bits(gpu_addr));
+       radeon_ring_write(ring, upper_32_bits(gpu_addr) & 0xff);
        radeon_ring_write(ring, 0xDEADBEEF);
        radeon_ring_unlock_commit(rdev, ring, false);
 
        for (i = 0; i < rdev->usec_timeout; i++) {
-               tmp = readl(ptr);
+               tmp = le32_to_cpu(rdev->wb.wb[index/4]);
                if (tmp == 0xDEADBEEF)
                        break;
                DRM_UDELAY(1);
@@ -335,17 +338,17 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
 {
        struct radeon_ib ib;
        unsigned i;
+       unsigned index;
        int r;
-       void __iomem *ptr = (void *)rdev->vram_scratch.ptr;
        u32 tmp = 0;
+       u64 gpu_addr;
 
-       if (!ptr) {
-               DRM_ERROR("invalid vram scratch pointer\n");
-               return -EINVAL;
-       }
+       if (ring->idx == R600_RING_TYPE_DMA_INDEX)
+               index = R600_WB_DMA_RING_TEST_OFFSET;
+       else
+               index = CAYMAN_WB_DMA1_RING_TEST_OFFSET;
 
-       tmp = 0xCAFEDEAD;
-       writel(tmp, ptr);
+       gpu_addr = rdev->wb.gpu_addr + index;
 
        r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256);
        if (r) {
@@ -354,8 +357,8 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
        }
 
        ib.ptr[0] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 1);
-       ib.ptr[1] = rdev->vram_scratch.gpu_addr & 0xfffffffc;
-       ib.ptr[2] = upper_32_bits(rdev->vram_scratch.gpu_addr) & 0xff;
+       ib.ptr[1] = lower_32_bits(gpu_addr);
+       ib.ptr[2] = upper_32_bits(gpu_addr) & 0xff;
        ib.ptr[3] = 0xDEADBEEF;
        ib.length_dw = 4;
 
@@ -371,7 +374,7 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
                return r;
        }
        for (i = 0; i < rdev->usec_timeout; i++) {
-               tmp = readl(ptr);
+               tmp = le32_to_cpu(rdev->wb.wb[index/4]);
                if (tmp == 0xDEADBEEF)
                        break;
                DRM_UDELAY(1);
index 9c61b74ef4415cbf1f7bce501b268662d80da8de..b5c73df8e202b76c21790eb1b20b12e410a8d696 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "r600d.h"
 #include "r600_dpm.h"
 #include "atom.h"
@@ -1255,7 +1256,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
                                        (mode_info->atom_context->bios + data_offset +
                                         le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
                                rdev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =
-                                       ppt->usMaximumPowerDeliveryLimit;
+                                       le16_to_cpu(ppt->usMaximumPowerDeliveryLimit);
                                pt = &ppt->power_tune_table;
                        } else {
                                ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)
index f7c4b226a284a162fcd088210d85b7b3ff57a838..a9717b3fbf1b4bd77417c38c29ac2c577179e947 100644 (file)
@@ -1133,6 +1133,8 @@ struct radeon_wb {
 #define R600_WB_EVENT_OFFSET     3072
 #define CIK_WB_CP1_WPTR_OFFSET     3328
 #define CIK_WB_CP2_WPTR_OFFSET     3584
+#define R600_WB_DMA_RING_TEST_OFFSET 3588
+#define CAYMAN_WB_DMA1_RING_TEST_OFFSET 3592
 
 /**
  * struct radeon_pm - power management datas
index 6a03624fadaa8005d40d4d4b818cf7c2a3580775..63ccb8fa799c209bc82db257d3da0c8fc60ba052 100644 (file)
@@ -658,12 +658,10 @@ bool radeon_get_bios(struct radeon_device *rdev)
                r = igp_read_bios_from_vram(rdev);
        if (r == false)
                r = radeon_read_bios(rdev);
-       if (r == false) {
+       if (r == false)
                r = radeon_read_disabled_bios(rdev);
-       }
-       if (r == false) {
+       if (r == false)
                r = radeon_read_platform_bios(rdev);
-       }
        if (r == false || rdev->bios == NULL) {
                DRM_ERROR("Unable to locate a BIOS ROM\n");
                rdev->bios = NULL;
index 300c4b3d4669426d5085d7e5d2e52e23321988d3..26baa9c05f6c49ac40e2a238a6079fa8e0e40920 100644 (file)
@@ -322,6 +322,12 @@ static void radeon_connector_get_edid(struct drm_connector *connector)
        }
 
        if (!radeon_connector->edid) {
+               /* don't fetch the edid from the vbios if ddc fails and runpm is
+                * enabled so we report disconnected.
+                */
+               if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
+                       return;
+
                if (rdev->is_atom_bios) {
                        /* some laptops provide a hardcoded edid in rom for LCDs */
                        if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
@@ -826,6 +832,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector,
 static enum drm_connector_status
 radeon_lvds_detect(struct drm_connector *connector, bool force)
 {
+       struct drm_device *dev = connector->dev;
+       struct radeon_device *rdev = dev->dev_private;
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder = radeon_best_single_encoder(connector);
        enum drm_connector_status ret = connector_status_disconnected;
@@ -842,7 +850,11 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
                /* check if panel is valid */
                if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
                        ret = connector_status_connected;
-
+               /* don't fetch the edid from the vbios if ddc fails and runpm is
+                * enabled so we report disconnected.
+                */
+               if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
+                       ret = connector_status_disconnected;
        }
 
        /* check for edid as well */
@@ -1589,6 +1601,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                        /* check if panel is valid */
                        if (native_mode->hdisplay >= 320 && native_mode->vdisplay >= 240)
                                ret = connector_status_connected;
+                       /* don't fetch the edid from the vbios if ddc fails and runpm is
+                        * enabled so we report disconnected.
+                        */
+                       if ((rdev->flags & RADEON_IS_PX) && (radeon_runtime_pm != 0))
+                               ret = connector_status_disconnected;
                }
                /* eDP is always DP */
                radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
index 1c893447d7cd60fff05fa029dd9d3260d9495c11..6f377de099f93ad44ec876e6d385ff916b08345a 100644 (file)
@@ -251,22 +251,19 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
 
 static int radeon_cs_sync_rings(struct radeon_cs_parser *p)
 {
-       int i, r = 0;
+       struct radeon_cs_reloc *reloc;
+       int r;
 
-       for (i = 0; i < p->nrelocs; i++) {
+       list_for_each_entry(reloc, &p->validated, tv.head) {
                struct reservation_object *resv;
 
-               if (!p->relocs[i].robj)
-                       continue;
-
-               resv = p->relocs[i].robj->tbo.resv;
+               resv = reloc->robj->tbo.resv;
                r = radeon_semaphore_sync_resv(p->rdev, p->ib.semaphore, resv,
-                                              p->relocs[i].tv.shared);
-
+                                              reloc->tv.shared);
                if (r)
-                       break;
+                       return r;
        }
-       return r;
+       return 0;
 }
 
 /* XXX: note that this is called from the legacy UMS CS ioctl as well */
@@ -450,7 +447,7 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bo
        kfree(parser->track);
        kfree(parser->relocs);
        kfree(parser->relocs_ptr);
-       kfree(parser->vm_bos);
+       drm_free_large(parser->vm_bos);
        for (i = 0; i < parser->nchunks; i++)
                drm_free_large(parser->chunks[i].kdata);
        kfree(parser->chunks);
index f41cc1538e4851fcafcec22e29ffcfb07d7b0c98..995a8b1770ddb9871c989c9428a554c313dbc5e9 100644 (file)
@@ -952,6 +952,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
        }
 
        mutex_init(&rdev->mode_info.atom_context->mutex);
+       mutex_init(&rdev->mode_info.atom_context->scratch_mutex);
        radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
        atom_allocate_fb_scratch(rdev->mode_info.atom_context);
        return 0;
@@ -1130,7 +1131,7 @@ static void radeon_check_arguments(struct radeon_device *rdev)
        if (radeon_vm_block_size == -1) {
 
                /* Total bits covered by PD + PTs */
-               unsigned bits = ilog2(radeon_vm_size) + 17;
+               unsigned bits = ilog2(radeon_vm_size) + 18;
 
                /* Make sure the PD is 4K in size up to 8GB address space.
                   Above that split equal between PD and PTs */
index 9a19e52cc655bf8b3c697a7116e52e81b8060096..6b670b0bc47bb9dca0238ef35dcff1cc2f686c34 100644 (file)
@@ -179,6 +179,9 @@ static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
                    (rdev->pdev->subsystem_vendor == 0x1734) &&
                    (rdev->pdev->subsystem_device == 0x1107))
                        use_bl = false;
+               /* disable native backlight control on older asics */
+               else if (rdev->family < CHIP_R600)
+                       use_bl = false;
                else
                        use_bl = true;
        }
index 7784911d78ef6fc54d6aeea23950f4585d3c74c4..00fc59762e0df3bba0758d1f18e90328e5726635 100644 (file)
@@ -185,6 +185,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
        if (rdev->flags & RADEON_IS_AGP)
                return false;
 
+       /*
+        * Older chips have a HW limitation, they can only generate 40 bits
+        * of address for "64-bit" MSIs which breaks on some platforms, notably
+        * IBM POWER servers, so we limit them
+        */
+       if (rdev->family < CHIP_BONAIRE) {
+               dev_info(rdev->dev, "radeon: MSI limited to 32-bit\n");
+               rdev->pdev->no_64bit_msi = 1;
+       }
+
        /* force MSI on */
        if (radeon_msi == 1)
                return true;
index 8309b11e674d8506bfeb3f05530407ede4b60642..03586763ee8616ae41d17f91bc4ad6d70ac7f646 100644 (file)
@@ -795,6 +795,8 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
 
        /* Get associated drm_crtc: */
        drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
+       if (!drmcrtc)
+               return -EINVAL;
 
        /* Helper routine in DRM core does all the work: */
        return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
index 99a960a4f30265c893a411763843a260d38e6a41..4c0d786d5c7a2a00fde32feeb81370574e494800 100644 (file)
@@ -213,6 +213,13 @@ int radeon_bo_create(struct radeon_device *rdev,
        if (!(rdev->flags & RADEON_IS_PCIE))
                bo->flags &= ~(RADEON_GEM_GTT_WC | RADEON_GEM_GTT_UC);
 
+#ifdef CONFIG_X86_32
+       /* XXX: Write-combined CPU mappings of GTT seem broken on 32-bit
+        * See https://bugs.freedesktop.org/show_bug.cgi?id=84627
+        */
+       bo->flags &= ~RADEON_GEM_GTT_WC;
+#endif
+
        radeon_ttm_placement_from_domain(bo, domain);
        /* Kernel allocation are uninterruptible */
        down_read(&rdev->pm.mclk_lock);
index 3d17af34afa73265eea6ed31210e265acae6eb1a..2456f69efd2310233fac5c75a314a9060abe1a17 100644 (file)
@@ -314,7 +314,7 @@ unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring
        }
 
        /* and then save the content of the ring */
-       *data = kmalloc_array(size, sizeof(uint32_t), GFP_KERNEL);
+       *data = drm_malloc_ab(size, sizeof(uint32_t));
        if (!*data) {
                mutex_unlock(&rdev->ring_lock);
                return 0;
@@ -356,7 +356,7 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
        }
 
        radeon_ring_unlock_commit(rdev, ring, false);
-       kfree(data);
+       drm_free_large(data);
        return 0;
 }
 
index 4532cc76a0a66094cd1cff8449f8957dd60152bf..dfde266529e2a787fd953a85bb12c4673e448d37 100644 (file)
@@ -132,8 +132,8 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev,
        struct radeon_cs_reloc *list;
        unsigned i, idx;
 
-       list = kmalloc_array(vm->max_pde_used + 2,
-                            sizeof(struct radeon_cs_reloc), GFP_KERNEL);
+       list = drm_malloc_ab(vm->max_pde_used + 2,
+                            sizeof(struct radeon_cs_reloc));
        if (!list)
                return NULL;
 
index 5f6db4629aaa4c04172fe092a0375a3a2a5d354f..9acb1c3c005b6ead68e940ba5443b88d3de0be0b 100644 (file)
@@ -879,6 +879,9 @@ void rs600_bandwidth_update(struct radeon_device *rdev)
        u32 d1mode_priority_a_cnt, d2mode_priority_a_cnt;
        /* FIXME: implement full support */
 
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        radeon_update_display_priority(rdev);
 
        if (rdev->mode_info.crtcs[0]->base.enabled)
index 3462b64369bfe6142a4c8acfaec09e0bb7d8826c..0a2d36e8110838d059b73663e5e055052741272c 100644 (file)
@@ -579,6 +579,9 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
        u32 d1mode_priority_a_cnt, d1mode_priority_b_cnt;
        u32 d2mode_priority_a_cnt, d2mode_priority_b_cnt;
 
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        radeon_update_display_priority(rdev);
 
        if (rdev->mode_info.crtcs[0]->base.enabled)
index 02f7710de4700f59ae21b98f49bfc04cda5383b3..9031f4b6982417462458b026f8c1503cde82397c 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "rs780d.h"
 #include "r600_dpm.h"
 #include "rs780_dpm.h"
index 8a477bf1fdb31529173234f8f30a0b4e3fb9c608..c55d653aaf5f6bcfb0b80d24ad1c42025d36e267 100644 (file)
@@ -1277,6 +1277,9 @@ void rv515_bandwidth_update(struct radeon_device *rdev)
        struct drm_display_mode *mode0 = NULL;
        struct drm_display_mode *mode1 = NULL;
 
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        radeon_update_display_priority(rdev);
 
        if (rdev->mode_info.crtcs[0]->base.enabled)
index e7045b08571567989dc9ac7a30d86cbda793cbf2..6a5c233361e9dbadbcb629c9583baf946e8abc7b 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "rv6xxd.h"
 #include "r600_dpm.h"
 #include "rv6xx_dpm.h"
index 3c76e1dcdf04d103583b3d3e050824a81a56baef..755a8f96fe465a81132da3efba82b67c8f5ebe35 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "rv770d.h"
 #include "r600_dpm.h"
 #include "rv770_dpm.h"
index eeea5b6a1775ee002f36682b7d092ab3b449d913..7d5083dc4acbad7d333766195586c3b5562a5f58 100644 (file)
@@ -2384,6 +2384,9 @@ void dce6_bandwidth_update(struct radeon_device *rdev)
        u32 num_heads = 0, lb_size;
        int i;
 
+       if (!rdev->mode_info.mode_config_initialized)
+               return;
+
        radeon_update_display_priority(rdev);
 
        for (i = 0; i < rdev->num_crtc; i++) {
index 9e4d5d7d348f280881f7065862990095e5cee9df..676e6c2ba90a3159f1c888c063837fca77647376 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "sid.h"
 #include "r600_dpm.h"
 #include "si_dpm.h"
@@ -2916,6 +2917,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
        bool disable_sclk_switching = false;
        u32 mclk, sclk;
        u16 vddc, vddci;
+       u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
        if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
@@ -2949,6 +2951,29 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
                }
        }
 
+       /* limit clocks to max supported clocks based on voltage dependency tables */
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+                                                       &max_sclk_vddc);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+                                                       &max_mclk_vddci);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+                                                       &max_mclk_vddc);
+
+       for (i = 0; i < ps->performance_level_count; i++) {
+               if (max_sclk_vddc) {
+                       if (ps->performance_levels[i].sclk > max_sclk_vddc)
+                               ps->performance_levels[i].sclk = max_sclk_vddc;
+               }
+               if (max_mclk_vddci) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddci)
+                               ps->performance_levels[i].mclk = max_mclk_vddci;
+               }
+               if (max_mclk_vddc) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddc)
+                               ps->performance_levels[i].mclk = max_mclk_vddc;
+               }
+       }
+
        /* XXX validate the min clocks required for display */
 
        if (disable_mclk_switching) {
@@ -6231,7 +6256,7 @@ static void si_parse_pplib_clock_info(struct radeon_device *rdev,
        if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) &&
            index == 0) {
                /* XXX disable for A0 tahiti */
-               si_pi->ulv.supported = true;
+               si_pi->ulv.supported = false;
                si_pi->ulv.pl = *pl;
                si_pi->ulv.one_pcie_lane_in_ulv = false;
                si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT;
index 3f0e8d7b8dbe3995a54862a48d25f812149a31fb..1f8a8833e1bef71639102608bac9add00a4ab77c 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "sumod.h"
 #include "r600_dpm.h"
 #include "cypress_dpm.h"
index 57f780053b3e4d2717a69b9e60e5aa5967fffc3d..b4ec5c4e7969dcf18f6f8fd60557a94ee3bdc357 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "drmP.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "trinityd.h"
 #include "r600_dpm.h"
 #include "trinity_dpm.h"
index 6553fd238685e459deb0676114bfd9cac04f7e50..054a79f143ae156b1dbbe4841b55e59bcb6d1b0a 100644 (file)
@@ -736,7 +736,6 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {
 
 static void tegra_crtc_disable(struct drm_crtc *crtc)
 {
-       struct tegra_dc *dc = to_tegra_dc(crtc);
        struct drm_device *drm = crtc->dev;
        struct drm_plane *plane;
 
@@ -752,7 +751,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
                }
        }
 
-       drm_vblank_off(drm, dc->pipe);
+       drm_crtc_vblank_off(crtc);
 }
 
 static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -841,8 +840,6 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
        u32 value;
        int err;
 
-       drm_vblank_pre_modeset(crtc->dev, dc->pipe);
-
        err = tegra_crtc_setup_clk(crtc, mode);
        if (err) {
                dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err);
@@ -896,6 +893,8 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc)
        unsigned int syncpt;
        unsigned long value;
 
+       drm_crtc_vblank_off(crtc);
+
        /* hardware initialization */
        reset_control_deassert(dc->rst);
        usleep_range(10000, 20000);
@@ -943,7 +942,7 @@ static void tegra_crtc_commit(struct drm_crtc *crtc)
        value = GENERAL_ACT_REQ | WIN_A_ACT_REQ;
        tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
 
-       drm_vblank_post_modeset(crtc->dev, dc->pipe);
+       drm_crtc_vblank_on(crtc);
 }
 
 static void tegra_crtc_load_lut(struct drm_crtc *crtc)
index 8f5cec67c47dd6b8976af0709bae49105b67ed49..d395b0bef73b0ce8afffa1d40fb9ea47022ac7fd 100644 (file)
@@ -709,6 +709,7 @@ out:
 
 static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
                                uint32_t mem_type,
+                               const struct ttm_place *place,
                                bool interruptible,
                                bool no_wait_gpu)
 {
@@ -720,8 +721,21 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
        spin_lock(&glob->lru_lock);
        list_for_each_entry(bo, &man->lru, lru) {
                ret = __ttm_bo_reserve(bo, false, true, false, NULL);
-               if (!ret)
+               if (!ret) {
+                       if (place && (place->fpfn || place->lpfn)) {
+                               /* Don't evict this BO if it's outside of the
+                                * requested placement range
+                                */
+                               if (place->fpfn >= (bo->mem.start + bo->mem.size) ||
+                                   (place->lpfn && place->lpfn <= bo->mem.start)) {
+                                       __ttm_bo_unreserve(bo);
+                                       ret = -EBUSY;
+                                       continue;
+                               }
+                       }
+
                        break;
+               }
        }
 
        if (ret) {
@@ -782,7 +796,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
                        return ret;
                if (mem->mm_node)
                        break;
-               ret = ttm_mem_evict_first(bdev, mem_type,
+               ret = ttm_mem_evict_first(bdev, mem_type, place,
                                          interruptible, no_wait_gpu);
                if (unlikely(ret != 0))
                        return ret;
@@ -994,9 +1008,9 @@ static bool ttm_bo_mem_compat(struct ttm_placement *placement,
 
        for (i = 0; i < placement->num_placement; i++) {
                const struct ttm_place *heap = &placement->placement[i];
-               if (mem->mm_node && heap->lpfn != 0 &&
+               if (mem->mm_node &&
                    (mem->start < heap->fpfn ||
-                    mem->start + mem->num_pages > heap->lpfn))
+                    (heap->lpfn != 0 && (mem->start + mem->num_pages) > heap->lpfn)))
                        continue;
 
                *new_flags = heap->flags;
@@ -1007,9 +1021,9 @@ static bool ttm_bo_mem_compat(struct ttm_placement *placement,
 
        for (i = 0; i < placement->num_busy_placement; i++) {
                const struct ttm_place *heap = &placement->busy_placement[i];
-               if (mem->mm_node && heap->lpfn != 0 &&
+               if (mem->mm_node &&
                    (mem->start < heap->fpfn ||
-                    mem->start + mem->num_pages > heap->lpfn))
+                    (heap->lpfn != 0 && (mem->start + mem->num_pages) > heap->lpfn)))
                        continue;
 
                *new_flags = heap->flags;
@@ -1233,7 +1247,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
        spin_lock(&glob->lru_lock);
        while (!list_empty(&man->lru)) {
                spin_unlock(&glob->lru_lock);
-               ret = ttm_mem_evict_first(bdev, mem_type, false, false);
+               ret = ttm_mem_evict_first(bdev, mem_type, NULL, false, false);
                if (ret) {
                        if (allow_errors) {
                                return ret;
index bfeb4b1f2acf4f58ead34a83344023524349a217..21e9b7f8dad0b89aedeabae661cef83e6879952d 100644 (file)
@@ -246,7 +246,8 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
        struct drm_hash_item *hash;
        int ret;
 
-       ret = drm_ht_find_item(&man->resources, user_key, &hash);
+       ret = drm_ht_find_item(&man->resources, user_key | (res_type << 24),
+                              &hash);
        if (likely(ret != 0))
                return -EINVAL;
 
index 7197af15731383c817728e155c09621c4c954fb0..25f3c250fd98635ff50a7249f40e691686519674 100644 (file)
@@ -688,7 +688,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
                goto out_err0;
        }
 
-       if (unlikely(dev_priv->prim_bb_mem < dev_priv->vram_size))
+       /*
+        * Limit back buffer size to VRAM size.  Remove this once
+        * screen targets are implemented.
+        */
+       if (dev_priv->prim_bb_mem > dev_priv->vram_size)
                dev_priv->prim_bb_mem = dev_priv->vram_size;
 
        mutex_unlock(&dev_priv->hw_mutex);
index d2bc2b03d4c60b3f12b14720943f5a835432d58e..941a7bc0b79190b7bcafe751cd7cac26b371911e 100644 (file)
@@ -187,7 +187,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
         * can do this since the caller in the drm core doesn't check anything
         * which is protected by any looks.
         */
-       drm_modeset_unlock(&crtc->mutex);
+       drm_modeset_unlock_crtc(crtc);
        drm_modeset_lock_all(dev_priv->dev);
 
        /* A lot of the code assumes this */
@@ -252,7 +252,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
        ret = 0;
 out:
        drm_modeset_unlock_all(dev_priv->dev);
-       drm_modeset_lock(&crtc->mutex, NULL);
+       drm_modeset_lock_crtc(crtc);
 
        return ret;
 }
@@ -273,7 +273,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
         * can do this since the caller in the drm core doesn't check anything
         * which is protected by any looks.
         */
-       drm_modeset_unlock(&crtc->mutex);
+       drm_modeset_unlock_crtc(crtc);
        drm_modeset_lock_all(dev_priv->dev);
 
        vmw_cursor_update_position(dev_priv, shown,
@@ -281,7 +281,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
                                   du->cursor_y + du->hotspot_y);
 
        drm_modeset_unlock_all(dev_priv->dev);
-       drm_modeset_lock(&crtc->mutex, NULL);
+       drm_modeset_lock_crtc(crtc);
 
        return 0;
 }
@@ -1950,6 +1950,14 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
                DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
        };
        int i;
+       u32 assumed_bpp = 2;
+
+       /*
+        * If using screen objects, then assume 32-bpp because that's what the
+        * SVGA device is assuming
+        */
+       if (dev_priv->sou_priv)
+               assumed_bpp = 4;
 
        /* Add preferred mode */
        {
@@ -1960,8 +1968,9 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
                mode->vdisplay = du->pref_height;
                vmw_guess_mode_timing(mode);
 
-               if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
-                                              mode->vdisplay)) {
+               if (vmw_kms_validate_mode_vram(dev_priv,
+                                               mode->hdisplay * assumed_bpp,
+                                               mode->vdisplay)) {
                        drm_mode_probed_add(connector, mode);
                } else {
                        drm_mode_destroy(dev, mode);
@@ -1983,7 +1992,8 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
                    bmode->vdisplay > max_height)
                        continue;
 
-               if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2,
+               if (!vmw_kms_validate_mode_vram(dev_priv,
+                                               bmode->hdisplay * assumed_bpp,
                                                bmode->vdisplay))
                        continue;
 
index 73bd9e2e42bc3c7dfbd249c0a1d3d4e1c78a19f9..3402033fa52a7225c0a91846eba5237af8d08142 100644 (file)
@@ -1659,6 +1659,7 @@ void hid_disconnect(struct hid_device *hdev)
                hdev->hiddev_disconnect(hdev);
        if (hdev->claimed & HID_CLAIMED_HIDRAW)
                hidraw_disconnect(hdev);
+       hdev->claimed = 0;
 }
 EXPORT_SYMBOL_GPL(hid_disconnect);
 
index 84c3cb15ccdd45fbc3f15e3803c70201d163ff09..8bf61d295ffd7efd638e1f14570508e9c8498f50 100644 (file)
@@ -946,6 +946,12 @@ static const char *keys[KEY_MAX + 1] = {
        [KEY_BRIGHTNESS_MIN] = "BrightnessMin",
        [KEY_BRIGHTNESS_MAX] = "BrightnessMax",
        [KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
+       [KEY_KBDINPUTASSIST_PREV] = "KbdInputAssistPrev",
+       [KEY_KBDINPUTASSIST_NEXT] = "KbdInputAssistNext",
+       [KEY_KBDINPUTASSIST_PREVGROUP] = "KbdInputAssistPrevGroup",
+       [KEY_KBDINPUTASSIST_NEXTGROUP] = "KbdInputAssistNextGroup",
+       [KEY_KBDINPUTASSIST_ACCEPT] = "KbdInputAssistAccept",
+       [KEY_KBDINPUTASSIST_CANCEL] = "KbdInputAssistCancel",
 };
 
 static const char *relatives[REL_MAX + 1] = {
index cd9c9e96cf0ef838618a95438afa0794f82b1eb5..7c863738e419969a9dd0115ca7321d884034ae59 100644 (file)
 
 #define USB_VENDOR_ID_ELAN             0x04f3
 #define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089
+#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B    0x009b
+#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103    0x0103
+#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F    0x016f
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
index 2df7fddbd119bc0cccb5f9cc2a6c4a01bbc9f7e8..725f22ca47fcb808401dc08120ad0366bb9d9d69 100644 (file)
@@ -695,7 +695,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        break;
 
                case 0x5b: /* TransducerSerialNumber */
-                       set_bit(MSC_SERIAL, input->mscbit);
+                       usage->type = EV_MSC;
+                       usage->code = MSC_SERIAL;
+                       bit = input->mscbit;
+                       max = MSC_MAX;
                        break;
 
                default:  goto unknown;
@@ -862,6 +865,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x28b: map_key_clear(KEY_FORWARDMAIL);     break;
                case 0x28c: map_key_clear(KEY_SEND);            break;
 
+               case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV);             break;
+               case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT);             break;
+               case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP);                break;
+               case 0x2ca: map_key_clear(KEY_KBDINPUTASSIST_NEXTGROUP);                break;
+               case 0x2cb: map_key_clear(KEY_KBDINPUTASSIST_ACCEPT);   break;
+               case 0x2cc: map_key_clear(KEY_KBDINPUTASSIST_CANCEL);   break;
+
                default:    goto ignore;
                }
                break;
index e6d8e18dae97e487cba5a1ff3e711425652aa7e1..6a58b6c723aa215408051e2b3c967205569a7b94 100644 (file)
@@ -640,9 +640,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
                                        ret = -ENOMEM;
                                        goto err_stop_hw;
                        }
-                       sd->hid_sensor_hub_client_devs[
-                               sd->hid_sensor_client_cnt].id =
-                                                       PLATFORM_DEVID_AUTO;
                        sd->hid_sensor_hub_client_devs[
                                sd->hid_sensor_client_cnt].name = name;
                        sd->hid_sensor_hub_client_devs[
@@ -659,8 +656,9 @@ static int sensor_hub_probe(struct hid_device *hdev,
        if (last_hsdev)
                last_hsdev->end_collection_index = i;
 
-       ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
-               sd->hid_sensor_client_cnt, NULL, 0, NULL);
+       ret = mfd_add_hotplug_devices(&hdev->dev,
+                       sd->hid_sensor_hub_client_devs,
+                       sd->hid_sensor_client_cnt);
        if (ret < 0)
                goto err_stop_hw;
 
index f3cb5b0a43454e7b27b2d8c0e3ddf817aa539e6f..552671ee7c5d7c6344fb92bca48f4f2d601b640e 100644 (file)
@@ -71,6 +71,9 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
index 5286d7ce1f9eb77a4a92902317411a7bda069490..6529c09c46f0fe99a02ddfbcd5a643954e1d6e22 100644 (file)
@@ -1028,11 +1028,11 @@ config SENSORS_LM93
          will be called lm93.
 
 config SENSORS_LM95234
-       tristate "National Semiconductor LM95234"
+       tristate "National Semiconductor LM95234 and compatibles"
        depends on I2C
        help
-         If you say yes here you get support for the LM95234 temperature
-         sensor.
+         If you say yes here you get support for the LM95233 and LM95234
+         temperature sensor chips.
 
          This driver can also be built as a module.  If so, the module
          will be called lm95234.
@@ -1048,10 +1048,11 @@ config SENSORS_LM95241
          will be called lm95241.
 
 config SENSORS_LM95245
-       tristate "National Semiconductor LM95245 sensor chip"
+       tristate "National Semiconductor LM95245 and compatibles"
        depends on I2C
        help
-         If you say yes here you get support for LM95245 sensor chip.
+         If you say yes here you get support for LM95235 and LM95245
+         temperature sensor chips.
 
          This driver can also be built as a module.  If so, the module
          will be called lm95245.
@@ -1117,12 +1118,23 @@ config SENSORS_NCT6775
        help
          If you say yes here you get support for the hardware monitoring
          functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D,
-         NCT6791D and compatible Super-I/O chips. This driver replaces the
-         w83627ehf driver for NCT6775F and NCT6776F.
+         NCT6791D, NCT6792D and compatible Super-I/O chips. This driver
+         replaces the w83627ehf driver for NCT6775F and NCT6776F.
 
          This driver can also be built as a module.  If so, the module
          will be called nct6775.
 
+config SENSORS_NCT7802
+       tristate "Nuvoton NCT7802Y"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the Nuvoton NCT7802Y
+         hardware monitoring chip.
+
+         This driver can also be built as a module.  If so, the module
+         will be called nct7802.
+
 config SENSORS_PCF8591
        tristate "Philips PCF8591 ADC/DAC"
        depends on I2C
@@ -1454,7 +1466,7 @@ config SENSORS_TMP401
        depends on I2C
        help
          If you say yes here you get support for Texas Instruments TMP401,
-         TMP411, TMP431, and TMP432 temperature sensor chips.
+         TMP411, TMP431, TMP432 and TMP435 temperature sensor chips.
 
          This driver can also be built as a module.  If so, the module
          will be called tmp401.
index c90a7611efaabc26c35c8b66cc90fbe50b4e9c96..67280643bcf009e5b4af58bcf61787f963f3c043 100644 (file)
@@ -118,6 +118,7 @@ obj-$(CONFIG_SENSORS_MCP3021)       += mcp3021.o
 obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
 obj-$(CONFIG_SENSORS_NCT6683)  += nct6683.o
 obj-$(CONFIG_SENSORS_NCT6775)  += nct6775.o
+obj-$(CONFIG_SENSORS_NCT7802)  += nct7802.o
 obj-$(CONFIG_SENSORS_NTC_THERMISTOR)   += ntc_thermistor.o
 obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)  += pc87427.o
index fcdbde4ec692f25c11f0a44b281a3770ede2d0c0..3057dfc7e3bc6cde853660579b01b4cab3530344 100644 (file)
@@ -234,7 +234,7 @@ static const struct pci_device_id fam15h_power_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
-       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, fam15h_power_id_table);
index 6aac695b1688beaf2adc5336bd842bb7993d2d09..9b55e673b67caf1365c7452ce51a22a37510af02 100644 (file)
@@ -1084,10 +1084,8 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (ret)
                goto clock_dis;
 
-       data->hwmon_dev = devm_hwmon_device_register_with_groups(dev,
-                                                                client->name,
-                                                                data,
-                                                                g762_groups);
+       data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+                                                           data, g762_groups);
        if (IS_ERR(data->hwmon_dev)) {
                ret = PTR_ERR(data->hwmon_dev);
                goto clock_dis;
index 4efa1734bdad8d60de7f359dd4e885fc44181c24..36abf814b8c77c57c0728beda6afac69b92cc802 100644 (file)
@@ -79,7 +79,7 @@ static ssize_t show_fan_alarm(struct device *dev,
 {
        struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
        struct gpio_fan_alarm *alarm = fan_data->alarm;
-       int value = gpio_get_value(alarm->gpio);
+       int value = gpio_get_value_cansleep(alarm->gpio);
 
        if (alarm->active_low)
                value = !value;
@@ -131,7 +131,7 @@ static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
        int i;
 
        for (i = 0; i < fan_data->num_ctrl; i++)
-               gpio_set_value(fan_data->ctrl[i], (ctrl_val >> i) & 1);
+               gpio_set_value_cansleep(fan_data->ctrl[i], (ctrl_val >> i) & 1);
 }
 
 static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
@@ -142,7 +142,7 @@ static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
        for (i = 0; i < fan_data->num_ctrl; i++) {
                int value;
 
-               value = gpio_get_value(fan_data->ctrl[i]);
+               value = gpio_get_value_cansleep(fan_data->ctrl[i]);
                ctrl_val |= (value << i);
        }
        return ctrl_val;
@@ -369,7 +369,8 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
                if (err)
                        return err;
 
-               err = gpio_direction_output(ctrl[i], gpio_get_value(ctrl[i]));
+               err = gpio_direction_output(ctrl[i],
+                                           gpio_get_value_cansleep(ctrl[i]));
                if (err)
                        return err;
        }
@@ -549,6 +550,14 @@ static int gpio_fan_probe(struct platform_device *pdev)
        return 0;
 }
 
+static void gpio_fan_shutdown(struct platform_device *pdev)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(&pdev->dev);
+
+       if (fan_data->ctrl)
+               set_fan_speed(fan_data, 0);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int gpio_fan_suspend(struct device *dev)
 {
@@ -580,6 +589,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
 
 static struct platform_driver gpio_fan_driver = {
        .probe          = gpio_fan_probe,
+       .shutdown       = gpio_fan_shutdown,
        .driver = {
                .name   = "gpio-fan",
                .pm     = GPIO_FAN_PM,
index d2bf2c97ae7094c03ff836f6debf2de8ca66677c..7c2c7be182f25df547af0316abbcb1b52e8258cd 100644 (file)
@@ -74,9 +74,6 @@ struct platform_data {
        u32 sensors_count; /* Total count of sensors from each group */
 };
 
-/* Platform device representing all the ibmpowernv sensors */
-static struct platform_device *pdevice;
-
 static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
                           char *buf)
 {
@@ -99,7 +96,7 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
        return sprintf(buf, "%u\n", x);
 }
 
-static int __init get_sensor_index_attr(const char *name, u32 *index,
+static int get_sensor_index_attr(const char *name, u32 *index,
                                        char *attr)
 {
        char *hash_pos = strchr(name, '#');
@@ -136,7 +133,7 @@ static int __init get_sensor_index_attr(const char *name, u32 *index,
  * which need to be mapped as fan2_input, temp1_max respectively before
  * populating them inside hwmon device class.
  */
-static int __init create_hwmon_attr_name(struct device *dev, enum sensors type,
+static int create_hwmon_attr_name(struct device *dev, enum sensors type,
                                         const char *node_name,
                                         char *hwmon_attr_name)
 {
@@ -172,7 +169,7 @@ static int __init create_hwmon_attr_name(struct device *dev, enum sensors type,
        return 0;
 }
 
-static int __init populate_attr_groups(struct platform_device *pdev)
+static int populate_attr_groups(struct platform_device *pdev)
 {
        struct platform_data *pdata = platform_get_drvdata(pdev);
        const struct attribute_group **pgroups = pdata->attr_groups;
@@ -180,11 +177,6 @@ static int __init populate_attr_groups(struct platform_device *pdev)
        enum sensors type;
 
        opal = of_find_node_by_path("/ibm,opal/sensors");
-       if (!opal) {
-               dev_err(&pdev->dev, "Opal node 'sensors' not found\n");
-               return -ENODEV;
-       }
-
        for_each_child_of_node(opal, np) {
                if (np->name == NULL)
                        continue;
@@ -221,7 +213,7 @@ static int __init populate_attr_groups(struct platform_device *pdev)
  * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max
  * etc..
  */
-static int __init create_device_attrs(struct platform_device *pdev)
+static int create_device_attrs(struct platform_device *pdev)
 {
        struct platform_data *pdata = platform_get_drvdata(pdev);
        const struct attribute_group **pgroups = pdata->attr_groups;
@@ -280,7 +272,7 @@ exit_put_node:
        return err;
 }
 
-static int __init ibmpowernv_probe(struct platform_device *pdev)
+static int ibmpowernv_probe(struct platform_device *pdev)
 {
        struct platform_data *pdata;
        struct device *hwmon_dev;
@@ -309,55 +301,25 @@ static int __init ibmpowernv_probe(struct platform_device *pdev)
        return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static struct platform_driver ibmpowernv_driver = {
-       .driver = {
-               .owner = THIS_MODULE,
-               .name = DRVNAME,
+static const struct platform_device_id opal_sensor_driver_ids[] = {
+       {
+               .name = "opal-sensor",
        },
+       { }
 };
+MODULE_DEVICE_TABLE(platform, opal_sensor_driver_ids);
 
-static int __init ibmpowernv_init(void)
-{
-       int err;
-
-       pdevice = platform_device_alloc(DRVNAME, 0);
-       if (!pdevice) {
-               pr_err("Device allocation failed\n");
-               err = -ENOMEM;
-               goto exit;
-       }
-
-       err = platform_device_add(pdevice);
-       if (err) {
-               pr_err("Device addition failed (%d)\n", err);
-               goto exit_device_put;
-       }
-
-       err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);
-       if (err) {
-               pr_err("Platfrom driver probe failed\n");
-               goto exit_device_del;
-       }
-
-       return 0;
-
-exit_device_del:
-       platform_device_del(pdevice);
-exit_device_put:
-       platform_device_put(pdevice);
-exit:
-       return err;
-}
+static struct platform_driver ibmpowernv_driver = {
+       .probe          = ibmpowernv_probe,
+       .id_table       = opal_sensor_driver_ids,
+       .driver         = {
+               .owner  = THIS_MODULE,
+               .name   = DRVNAME,
+       },
+};
 
-static void __exit ibmpowernv_exit(void)
-{
-       platform_driver_unregister(&ibmpowernv_driver);
-       platform_device_unregister(pdevice);
-}
+module_platform_driver(ibmpowernv_driver);
 
 MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
 MODULE_DESCRIPTION("IBM POWERNV platform sensors");
 MODULE_LICENSE("GPL");
-
-module_init(ibmpowernv_init);
-module_exit(ibmpowernv_exit);
index 14c82daab01975851da8e1255cf7b3430df5383c..980175628563a0987531a05afda3312bb20b7511 100644 (file)
@@ -63,7 +63,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
        struct iio_hwmon_state *st;
        struct sensor_device_attribute *a;
        int ret, i;
-       int in_i = 1, temp_i = 1, curr_i = 1;
+       int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1;
        enum iio_chan_type type;
        struct iio_channel *channels;
        const char *name = "iio_hwmon";
@@ -123,6 +123,11 @@ static int iio_hwmon_probe(struct platform_device *pdev)
                                                          "curr%d_input",
                                                          curr_i++);
                        break;
+               case IIO_HUMIDITYRELATIVE:
+                       a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
+                                                         "humidity%d_input",
+                                                         humidity_i++);
+                       break;
                default:
                        ret = -EINVAL;
                        goto error_release_channels;
index bfd3f3eeabcd90cd52ad4cdef5155f00195e2c26..e01feba909c3688ea152b75d6c23b645948632ec 100644 (file)
@@ -223,6 +223,7 @@ static int ina2xx_probe(struct i2c_client *client,
        struct device *hwmon_dev;
        long shunt = 10000; /* default shunt value 10mOhms */
        u32 val;
+       int ret;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
@@ -247,12 +248,25 @@ static int ina2xx_probe(struct i2c_client *client,
        data->config = &ina2xx_config[data->kind];
 
        /* device configuration */
-       i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
-                                    data->config->config_default);
-       /* set current LSB to 1mA, shunt is in uOhms */
-       /* (equation 13 in datasheet) */
-       i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
-                                    data->config->calibration_factor / shunt);
+       ret = i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
+                                          data->config->config_default);
+       if (ret < 0) {
+               dev_err(dev,
+                       "error writing to the config register: %d", ret);
+               return -ENODEV;
+       }
+
+       /*
+        * Set current LSB to 1mA, shunt is in uOhms
+        * (equation 13 in datasheet).
+        */
+       ret = i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
+                               data->config->calibration_factor / shunt);
+       if (ret < 0) {
+               dev_err(dev,
+                       "error writing to the calibration register: %d", ret);
+               return -ENODEV;
+       }
 
        data->client = client;
        mutex_init(&data->update_lock);
index d16dbb33a531792834a4ee2bd2dff078ec78f5c9..6753fd940c7623a0fbbd2790c7b7bf5af43f2a18 100644 (file)
@@ -44,6 +44,7 @@ enum lm75_type {              /* keep sorted in alphabetical order */
        g751,
        lm75,
        lm75a,
+       lm75b,
        max6625,
        max6626,
        mcp980x,
@@ -233,6 +234,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
                data->resolution = 9;
                data->sample_time = HZ / 2;
                break;
+       case lm75b:
+               data->resolution = 11;
+               data->sample_time = HZ / 4;
+               break;
        case max6625:
                data->resolution = 9;
                data->sample_time = HZ / 4;
@@ -322,6 +327,7 @@ static const struct i2c_device_id lm75_ids[] = {
        { "g751", g751, },
        { "lm75", lm75, },
        { "lm75a", lm75a, },
+       { "lm75b", lm75b, },
        { "max6625", max6625, },
        { "max6626", max6626, },
        { "mcp980x", mcp980x, },
@@ -409,6 +415,12 @@ static int lm75_detect(struct i2c_client *new_client,
                 || i2c_smbus_read_byte_data(new_client, 7) != os)
                        return -ENODEV;
        }
+       /*
+        * It is very unlikely that this is a LM75 if both
+        * hysteresis and temperature limit registers are 0.
+        */
+       if (hyst == 0 && os == 0)
+               return -ENODEV;
 
        /* Addresses cycling */
        for (i = 8; i <= 248; i += 40) {
index 411202bdaf6b6bf8c3eb0141ad7a62ecd7d4cfbe..8796de39ff9bbc07a2a66f9f33c30dcfa2e8d724 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Driver for Texas Instruments / National Semiconductor LM95234
  *
- * Copyright (c) 2013 Guenter Roeck <linux@roeck-us.net>
+ * Copyright (c) 2013, 2014 Guenter Roeck <linux@roeck-us.net>
  *
  * Derived from lm95241.c
  * Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com>
 
 #define DRVNAME "lm95234"
 
-static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
+enum chips { lm95233, lm95234 };
+
+static const unsigned short normal_i2c[] = {
+       0x18, 0x2a, 0x2b, 0x4d, 0x4e, I2C_CLIENT_END };
 
 /* LM95234 registers */
 #define LM95234_REG_MAN_ID             0xFE
@@ -53,11 +56,13 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
 #define LM95234_REG_TCRIT_HYST         0x5a
 
 #define NATSEMI_MAN_ID                 0x01
+#define LM95233_CHIP_ID                        0x89
 #define LM95234_CHIP_ID                        0x79
 
 /* Client data (each client gets its own) */
 struct lm95234_data {
        struct i2c_client *client;
+       const struct attribute_group *groups[3];
        struct mutex update_lock;
        unsigned long last_updated, interval;   /* in jiffies */
        bool valid;             /* false until following fields are valid */
@@ -564,35 +569,23 @@ static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset,
 static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
                   set_interval);
 
-static struct attribute *lm95234_attrs[] = {
+static struct attribute *lm95234_common_attrs[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp2_input.dev_attr.attr,
        &sensor_dev_attr_temp3_input.dev_attr.attr,
-       &sensor_dev_attr_temp4_input.dev_attr.attr,
-       &sensor_dev_attr_temp5_input.dev_attr.attr,
        &sensor_dev_attr_temp2_fault.dev_attr.attr,
        &sensor_dev_attr_temp3_fault.dev_attr.attr,
-       &sensor_dev_attr_temp4_fault.dev_attr.attr,
-       &sensor_dev_attr_temp5_fault.dev_attr.attr,
        &sensor_dev_attr_temp2_type.dev_attr.attr,
        &sensor_dev_attr_temp3_type.dev_attr.attr,
-       &sensor_dev_attr_temp4_type.dev_attr.attr,
-       &sensor_dev_attr_temp5_type.dev_attr.attr,
        &sensor_dev_attr_temp1_max.dev_attr.attr,
        &sensor_dev_attr_temp2_max.dev_attr.attr,
        &sensor_dev_attr_temp3_max.dev_attr.attr,
-       &sensor_dev_attr_temp4_max.dev_attr.attr,
-       &sensor_dev_attr_temp5_max.dev_attr.attr,
        &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
        &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
        &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
-       &sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
-       &sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
        &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
        &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
        &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
-       &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
-       &sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
        &sensor_dev_attr_temp2_crit.dev_attr.attr,
        &sensor_dev_attr_temp3_crit.dev_attr.attr,
        &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
@@ -601,18 +594,44 @@ static struct attribute *lm95234_attrs[] = {
        &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
        &sensor_dev_attr_temp2_offset.dev_attr.attr,
        &sensor_dev_attr_temp3_offset.dev_attr.attr,
+       &dev_attr_update_interval.attr,
+       NULL
+};
+
+static const struct attribute_group lm95234_common_group = {
+       .attrs = lm95234_common_attrs,
+};
+
+static struct attribute *lm95234_attrs[] = {
+       &sensor_dev_attr_temp4_input.dev_attr.attr,
+       &sensor_dev_attr_temp5_input.dev_attr.attr,
+       &sensor_dev_attr_temp4_fault.dev_attr.attr,
+       &sensor_dev_attr_temp5_fault.dev_attr.attr,
+       &sensor_dev_attr_temp4_type.dev_attr.attr,
+       &sensor_dev_attr_temp5_type.dev_attr.attr,
+       &sensor_dev_attr_temp4_max.dev_attr.attr,
+       &sensor_dev_attr_temp5_max.dev_attr.attr,
+       &sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
+       &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
        &sensor_dev_attr_temp4_offset.dev_attr.attr,
        &sensor_dev_attr_temp5_offset.dev_attr.attr,
-       &dev_attr_update_interval.attr,
        NULL
 };
-ATTRIBUTE_GROUPS(lm95234);
+
+static const struct attribute_group lm95234_group = {
+       .attrs = lm95234_attrs,
+};
 
 static int lm95234_detect(struct i2c_client *client,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int address = client->addr;
+       u8 config_mask, model_mask;
        int mfg_id, chip_id, val;
+       const char *name;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
@@ -622,15 +641,31 @@ static int lm95234_detect(struct i2c_client *client,
                return -ENODEV;
 
        chip_id = i2c_smbus_read_byte_data(client, LM95234_REG_CHIP_ID);
-       if (chip_id != LM95234_CHIP_ID)
+       switch (chip_id) {
+       case LM95233_CHIP_ID:
+               if (address != 0x18 && address != 0x2a && address != 0x2b)
+                       return -ENODEV;
+               config_mask = 0xbf;
+               model_mask = 0xf9;
+               name = "lm95233";
+               break;
+       case LM95234_CHIP_ID:
+               if (address != 0x18 && address != 0x4d && address != 0x4e)
+                       return -ENODEV;
+               config_mask = 0xbc;
+               model_mask = 0xe1;
+               name = "lm95234";
+               break;
+       default:
                return -ENODEV;
+       }
 
        val = i2c_smbus_read_byte_data(client, LM95234_REG_STATUS);
        if (val & 0x30)
                return -ENODEV;
 
        val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG);
-       if (val & 0xbc)
+       if (val & config_mask)
                return -ENODEV;
 
        val = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
@@ -638,14 +673,14 @@ static int lm95234_detect(struct i2c_client *client,
                return -ENODEV;
 
        val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
-       if (val & 0xe1)
+       if (val & model_mask)
                return -ENODEV;
 
        val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS);
-       if (val & 0xe1)
+       if (val & model_mask)
                return -ENODEV;
 
-       strlcpy(info->type, "lm95234", I2C_NAME_SIZE);
+       strlcpy(info->type, name, I2C_NAME_SIZE);
        return 0;
 }
 
@@ -698,15 +733,19 @@ static int lm95234_probe(struct i2c_client *client,
        if (err < 0)
                return err;
 
+       data->groups[0] = &lm95234_common_group;
+       if (id->driver_data == lm95234)
+               data->groups[1] = &lm95234_group;
+
        hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
-                                                          data,
-                                                          lm95234_groups);
+                                                          data, data->groups);
        return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /* Driver data (common to all clients) */
 static const struct i2c_device_id lm95234_id[] = {
-       { "lm95234", 0 },
+       { "lm95233", lm95233 },
+       { "lm95234", lm95234 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, lm95234_id);
@@ -725,5 +764,5 @@ static struct i2c_driver lm95234_driver = {
 module_i2c_driver(lm95234_driver);
 
 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
-MODULE_DESCRIPTION("LM95234 sensor driver");
+MODULE_DESCRIPTION("LM95233/LM95234 sensor driver");
 MODULE_LICENSE("GPL");
index 0ae0dfdafdff9814993113a142f24a5192fe094e..e7aef4561c83f82e32efaf98016c3393f5fd4628 100644 (file)
@@ -1,10 +1,8 @@
 /*
  * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com>
  *
- * The LM95245 is a sensor chip made by National Semiconductors.
+ * The LM95245 is a sensor chip made by TI / National Semiconductor.
  * It reports up to two temperatures (its own plus an external one).
- * Complete datasheet can be obtained from National's website at:
- *   http://www.national.com/ds.cgi/LM/LM95245.pdf
  *
  * This driver is based on lm95241.c
  *
@@ -34,8 +32,6 @@
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 
-#define DEVNAME "lm95245"
-
 static const unsigned short normal_i2c[] = {
        0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END };
 
@@ -98,7 +94,8 @@ static const unsigned short normal_i2c[] = {
 #define STATUS1_LOC            0x01
 
 #define MANUFACTURER_ID                0x01
-#define DEFAULT_REVISION       0xB3
+#define LM95235_REVISION       0xB1
+#define LM95245_REVISION       0xB3
 
 static const u8 lm95245_reg_address[] = {
        LM95245_REG_R_LOCAL_TEMPH_S,
@@ -427,17 +424,32 @@ static int lm95245_detect(struct i2c_client *new_client,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = new_client->adapter;
+       int address = new_client->addr;
+       const char *name;
+       int rev, id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       if (i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID)
-                       != MANUFACTURER_ID
-               || i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID)
-                       != DEFAULT_REVISION)
+       id = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID);
+       if (id != MANUFACTURER_ID)
                return -ENODEV;
 
-       strlcpy(info->type, DEVNAME, I2C_NAME_SIZE);
+       rev = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID);
+       switch (rev) {
+       case LM95235_REVISION:
+               if (address != 0x18 && address != 0x29 && address != 0x4c)
+                       return -ENODEV;
+               name = "lm95235";
+               break;
+       case LM95245_REVISION:
+               name = "lm95245";
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       strlcpy(info->type, name, I2C_NAME_SIZE);
        return 0;
 }
 
@@ -484,7 +496,8 @@ static int lm95245_probe(struct i2c_client *client,
 
 /* Driver data (common to all clients) */
 static const struct i2c_device_id lm95245_id[] = {
-       { DEVNAME, 0 },
+       { "lm95235", 0 },
+       { "lm95245", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, lm95245_id);
@@ -492,7 +505,7 @@ MODULE_DEVICE_TABLE(i2c, lm95245_id);
 static struct i2c_driver lm95245_driver = {
        .class          = I2C_CLASS_HWMON,
        .driver = {
-               .name   = DEVNAME,
+               .name   = "lm95245",
        },
        .probe          = lm95245_probe,
        .id_table       = lm95245_id,
@@ -503,5 +516,5 @@ static struct i2c_driver lm95245_driver = {
 module_i2c_driver(lm95245_driver);
 
 MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>");
-MODULE_DESCRIPTION("LM95245 sensor driver");
+MODULE_DESCRIPTION("LM95235/LM95245 sensor driver");
 MODULE_LICENSE("GPL");
index c92229d321c92c24c5686fd2a4beefd5d4baf6cf..afc6b58eaa625fa89a8c2022e9403699f539338e 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/err.h>
 
 #define DRV_NAME  "menf21bmc_hwmon"
 
index 504cbddbdd900336703506e55d0455cd6afc307d..dc0df57200cdaef276b5e7609b59fd95478b9a83 100644 (file)
@@ -38,6 +38,7 @@
  * nct6776f     9      5       3       6+3    0xc330 0xc1    0x5ca3
  * nct6779d    15      5       5       2+6    0xc560 0xc1    0x5ca3
  * nct6791d    15      6       6       2+6    0xc800 0xc1    0x5ca3
+ * nct6792d    15      6       6       2+6    0xc910 0xc1    0x5ca3
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -61,7 +62,7 @@
 
 #define USE_ALTERNATE
 
-enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791 };
+enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792 };
 
 /* used to set data->name = nct6775_device_names[data->sio_kind] */
 static const char * const nct6775_device_names[] = {
@@ -70,6 +71,7 @@ static const char * const nct6775_device_names[] = {
        "nct6776",
        "nct6779",
        "nct6791",
+       "nct6792",
 };
 
 static unsigned short force_id;
@@ -100,6 +102,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_NCT6776_ID         0xc330
 #define SIO_NCT6779_ID         0xc560
 #define SIO_NCT6791_ID         0xc800
+#define SIO_NCT6792_ID         0xc910
 #define SIO_ID_MASK            0xFFF0
 
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -529,6 +532,12 @@ static const s8 NCT6791_ALARM_BITS[] = {
        4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
        12, 9 };                        /* intrusion0, intrusion1 */
 
+/* NCT6792 specific data */
+
+static const u16 NCT6792_REG_TEMP_MON[] = {
+       0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d };
+static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = {
+       0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
 
 /* NCT6102D/NCT6106D specific data */
 
@@ -1043,13 +1052,14 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
                  reg == 0x73 || reg == 0x75 || reg == 0x77;
        case nct6779:
        case nct6791:
+       case nct6792:
                return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
                  ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
                  reg == 0x402 ||
                  reg == 0x63a || reg == 0x63c || reg == 0x63e ||
                  reg == 0x640 || reg == 0x642 ||
                  reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
-                 reg == 0x7b;
+                 reg == 0x7b || reg == 0x7d;
        }
        return false;
 }
@@ -1063,6 +1073,7 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
 static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
 {
        u8 bank = reg >> 8;
+
        if (data->bank != bank) {
                outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
                outb_p(bank, data->addr + DATA_REG_OFFSET);
@@ -1300,6 +1311,7 @@ static void nct6775_update_pwm(struct device *dev)
                if (!data->target_speed_tolerance[i] ||
                    data->pwm_enable[i] == speed_cruise) {
                        u8 t = fanmodecfg & 0x0f;
+
                        if (data->REG_TOLERANCE_H) {
                                t |= (nct6775_read_value(data,
                                      data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
@@ -1391,6 +1403,7 @@ static void nct6775_update_pwm_limits(struct device *dev)
                case nct6106:
                case nct6779:
                case nct6791:
+               case nct6792:
                        reg = nct6775_read_value(data,
                                        data->REG_CRITICAL_PWM_ENABLE[i]);
                        if (reg & data->CRITICAL_PWM_ENABLE_MASK)
@@ -1473,6 +1486,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev)
                data->alarms = 0;
                for (i = 0; i < NUM_REG_ALARM; i++) {
                        u8 alarm;
+
                        if (!data->REG_ALARM[i])
                                continue;
                        alarm = nct6775_read_value(data, data->REG_ALARM[i]);
@@ -1482,6 +1496,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev)
                data->beeps = 0;
                for (i = 0; i < NUM_REG_BEEP; i++) {
                        u8 beep;
+
                        if (!data->REG_BEEP[i])
                                continue;
                        beep = nct6775_read_value(data, data->REG_BEEP[i]);
@@ -1504,8 +1519,9 @@ show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-       int nr = sattr->nr;
        int index = sattr->index;
+       int nr = sattr->nr;
+
        return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
 }
 
@@ -1515,10 +1531,12 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
 {
        struct nct6775_data *data = dev_get_drvdata(dev);
        struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-       int nr = sattr->nr;
        int index = sattr->index;
+       int nr = sattr->nr;
        unsigned long val;
-       int err = kstrtoul(buf, 10, &val);
+       int err;
+
+       err = kstrtoul(buf, 10, &val);
        if (err < 0)
                return err;
        mutex_lock(&data->update_lock);
@@ -1535,6 +1553,7 @@ show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = data->ALARM_BITS[sattr->index];
+
        return sprintf(buf, "%u\n",
                       (unsigned int)((data->alarms >> nr) & 0x01));
 }
@@ -1570,6 +1589,7 @@ show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
        nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
        if (nr >= 0) {
                int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
+
                alarm = (data->alarms >> bit) & 0x01;
        }
        return sprintf(buf, "%u\n", alarm);
@@ -1595,8 +1615,9 @@ store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
        int nr = data->BEEP_BITS[sattr->index];
        int regindex = nr >> 3;
        unsigned long val;
+       int err;
 
-       int err = kstrtoul(buf, 10, &val);
+       err = kstrtoul(buf, 10, &val);
        if (err < 0)
                return err;
        if (val > 1)
@@ -1629,6 +1650,7 @@ show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
        nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
        if (nr >= 0) {
                int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
+
                beep = (data->beeps >> bit) & 0x01;
        }
        return sprintf(buf, "%u\n", beep);
@@ -1642,8 +1664,9 @@ store_temp_beep(struct device *dev, struct device_attribute *attr,
        struct nct6775_data *data = dev_get_drvdata(dev);
        int nr, bit, regindex;
        unsigned long val;
+       int err;
 
-       int err = kstrtoul(buf, 10, &val);
+       err = kstrtoul(buf, 10, &val);
        if (err < 0)
                return err;
        if (val > 1)
@@ -1715,6 +1738,7 @@ show_fan(struct device *dev, struct device_attribute *attr, char *buf)
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = sattr->index;
+
        return sprintf(buf, "%d\n", data->rpm[nr]);
 }
 
@@ -1724,6 +1748,7 @@ show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = sattr->index;
+
        return sprintf(buf, "%d\n",
                       data->fan_from_reg_min(data->fan_min[nr],
                                              data->fan_div[nr]));
@@ -1735,6 +1760,7 @@ show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = sattr->index;
+
        return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
 }
 
@@ -1746,9 +1772,9 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = sattr->index;
        unsigned long val;
-       int err;
        unsigned int reg;
        u8 new_div;
+       int err;
 
        err = kstrtoul(buf, 10, &val);
        if (err < 0)
@@ -1932,6 +1958,7 @@ show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = sattr->index;
+
        return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
 }
 
@@ -2008,6 +2035,7 @@ show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
        struct nct6775_data *data = nct6775_update_device(dev);
        struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
        int nr = sattr->index;
+
        return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
 }
 
@@ -2790,6 +2818,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
                case nct6106:
                case nct6779:
                case nct6791:
+               case nct6792:
                        nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
                                            val);
                        reg = nct6775_read_value(data,
@@ -2997,6 +3026,7 @@ static ssize_t
 show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct nct6775_data *data = dev_get_drvdata(dev);
+
        return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
 }
 
@@ -3202,7 +3232,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                pwm4pin = false;
                pwm5pin = false;
                pwm6pin = false;
-       } else {        /* NCT6779D or NCT6791D */
+       } else {        /* NCT6779D, NCT6791D, or NCT6792D */
                regval = superio_inb(sioreg, 0x1c);
 
                fan3pin = !(regval & (1 << 5));
@@ -3215,7 +3245,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
 
                fan4min = fan4pin;
 
-               if (data->kind == nct6791) {
+               if (data->kind == nct6791 || data->kind == nct6792) {
                        regval = superio_inb(sioreg, 0x2d);
                        fan6pin = (regval & (1 << 1));
                        pwm6pin = (regval & (1 << 0));
@@ -3588,6 +3618,7 @@ static int nct6775_probe(struct platform_device *pdev)
 
                break;
        case nct6791:
+       case nct6792:
                data->in_num = 15;
                data->pwm_num = 6;
                data->auto_pwm_num = 4;
@@ -3650,12 +3681,20 @@ static int nct6775_probe(struct platform_device *pdev)
                data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
                data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
                data->REG_ALARM = NCT6791_REG_ALARM;
-               data->REG_BEEP = NCT6776_REG_BEEP;
+               if (data->kind == nct6791)
+                       data->REG_BEEP = NCT6776_REG_BEEP;
+               else
+                       data->REG_BEEP = NCT6792_REG_BEEP;
 
                reg_temp = NCT6779_REG_TEMP;
-               reg_temp_mon = NCT6779_REG_TEMP_MON;
                num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
-               num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
+               if (data->kind == nct6791) {
+                       reg_temp_mon = NCT6779_REG_TEMP_MON;
+                       num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
+               } else {
+                       reg_temp_mon = NCT6792_REG_TEMP_MON;
+                       num_reg_temp_mon = ARRAY_SIZE(NCT6792_REG_TEMP_MON);
+               }
                reg_temp_over = NCT6779_REG_TEMP_OVER;
                reg_temp_hyst = NCT6779_REG_TEMP_HYST;
                reg_temp_config = NCT6779_REG_TEMP_CONFIG;
@@ -3854,6 +3893,7 @@ static int nct6775_probe(struct platform_device *pdev)
        case nct6106:
        case nct6779:
        case nct6791:
+       case nct6792:
                break;
        }
 
@@ -3885,6 +3925,7 @@ static int nct6775_probe(struct platform_device *pdev)
                        tmp |= 0x3e;
                        break;
                case nct6791:
+               case nct6792:
                        tmp |= 0x7e;
                        break;
                }
@@ -3972,7 +4013,7 @@ static int nct6775_resume(struct device *dev)
        mutex_lock(&data->update_lock);
        data->bank = 0xff;              /* Force initial bank selection */
 
-       if (data->kind == nct6791) {
+       if (data->kind == nct6791 || data->kind == nct6792) {
                err = superio_enter(data->sioreg);
                if (err)
                        goto abort;
@@ -4052,6 +4093,7 @@ static const char * const nct6775_sio_names[] __initconst = {
        "NCT6776D/F",
        "NCT6779D",
        "NCT6791D",
+       "NCT6792D",
 };
 
 /* nct6775_find() looks for a '627 in the Super-I/O config space */
@@ -4086,6 +4128,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
        case SIO_NCT6791_ID:
                sio_data->kind = nct6791;
                break;
+       case SIO_NCT6792_ID:
+               sio_data->kind = nct6792;
+               break;
        default:
                if (val != 0xffff)
                        pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -4111,7 +4156,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
                superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
        }
 
-       if (sio_data->kind == nct6791)
+       if (sio_data->kind == nct6791 || sio_data->kind == nct6792)
                nct6791_enable_io_mapping(sioaddr);
 
        superio_exit(sioaddr);
@@ -4221,7 +4266,7 @@ static void __exit sensors_nct6775_exit(void)
 }
 
 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
-MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D driver");
+MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D/NCT6792D driver");
 MODULE_LICENSE("GPL");
 
 module_init(sensors_nct6775_init);
diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c
new file mode 100644 (file)
index 0000000..ec56782
--- /dev/null
@@ -0,0 +1,860 @@
+/*
+ * nct7802 - Driver for Nuvoton NCT7802Y
+ *
+ * Copyright (C) 2014  Guenter Roeck <linux@roeck-us.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define DRVNAME "nct7802"
+
+static const u8 REG_VOLTAGE[5] = { 0x09, 0x0a, 0x0c, 0x0d, 0x0e };
+
+static const u8 REG_VOLTAGE_LIMIT_LSB[2][5] = {
+       { 0x40, 0x00, 0x42, 0x44, 0x46 },
+       { 0x3f, 0x00, 0x41, 0x43, 0x45 },
+};
+
+static const u8 REG_VOLTAGE_LIMIT_MSB[5] = { 0x48, 0x00, 0x47, 0x47, 0x48 };
+
+static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = {
+       { 0, 0, 4, 0, 4 },
+       { 2, 0, 6, 2, 6 },
+};
+
+#define REG_BANK               0x00
+#define REG_TEMP_LSB           0x05
+#define REG_TEMP_PECI_LSB      0x08
+#define REG_VOLTAGE_LOW                0x0f
+#define REG_FANCOUNT_LOW       0x13
+#define REG_START              0x21
+#define REG_MODE               0x22
+#define REG_PECI_ENABLE                0x23
+#define REG_FAN_ENABLE         0x24
+#define REG_VMON_ENABLE                0x25
+#define REG_VENDOR_ID          0xfd
+#define REG_CHIP_ID            0xfe
+#define REG_VERSION_ID         0xff
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct nct7802_data {
+       struct regmap *regmap;
+       struct mutex access_lock; /* for multi-byte read and write operations */
+};
+
+static int nct7802_read_temp(struct nct7802_data *data,
+                            u8 reg_temp, u8 reg_temp_low, int *temp)
+{
+       unsigned int t1, t2 = 0;
+       int err;
+
+       *temp = 0;
+
+       mutex_lock(&data->access_lock);
+       err = regmap_read(data->regmap, reg_temp, &t1);
+       if (err < 0)
+               goto abort;
+       t1 <<= 8;
+       if (reg_temp_low) {     /* 11 bit data */
+               err = regmap_read(data->regmap, reg_temp_low, &t2);
+               if (err < 0)
+                       goto abort;
+       }
+       t1 |= t2 & 0xe0;
+       *temp = (s16)t1 / 32 * 125;
+abort:
+       mutex_unlock(&data->access_lock);
+       return err;
+}
+
+static int nct7802_read_fan(struct nct7802_data *data, u8 reg_fan)
+{
+       unsigned int f1, f2;
+       int ret;
+
+       mutex_lock(&data->access_lock);
+       ret = regmap_read(data->regmap, reg_fan, &f1);
+       if (ret < 0)
+               goto abort;
+       ret = regmap_read(data->regmap, REG_FANCOUNT_LOW, &f2);
+       if (ret < 0)
+               goto abort;
+       ret = (f1 << 5) | (f2 >> 3);
+       /* convert fan count to rpm */
+       if (ret == 0x1fff)      /* maximum value, assume fan is stopped */
+               ret = 0;
+       else if (ret)
+               ret = DIV_ROUND_CLOSEST(1350000U, ret);
+abort:
+       mutex_unlock(&data->access_lock);
+       return ret;
+}
+
+static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low,
+                               u8 reg_fan_high)
+{
+       unsigned int f1, f2;
+       int ret;
+
+       mutex_lock(&data->access_lock);
+       ret = regmap_read(data->regmap, reg_fan_low, &f1);
+       if (ret < 0)
+               goto abort;
+       ret = regmap_read(data->regmap, reg_fan_high, &f2);
+       if (ret < 0)
+               goto abort;
+       ret = f1 | ((f2 & 0xf8) << 5);
+       /* convert fan count to rpm */
+       if (ret == 0x1fff)      /* maximum value, assume no limit */
+               ret = 0;
+       else if (ret)
+               ret = DIV_ROUND_CLOSEST(1350000U, ret);
+abort:
+       mutex_unlock(&data->access_lock);
+       return ret;
+}
+
+static int nct7802_write_fan_min(struct nct7802_data *data, u8 reg_fan_low,
+                                u8 reg_fan_high, unsigned int limit)
+{
+       int err;
+
+       if (limit)
+               limit = DIV_ROUND_CLOSEST(1350000U, limit);
+       else
+               limit = 0x1fff;
+       limit = clamp_val(limit, 0, 0x1fff);
+
+       mutex_lock(&data->access_lock);
+       err = regmap_write(data->regmap, reg_fan_low, limit & 0xff);
+       if (err < 0)
+               goto abort;
+
+       err = regmap_write(data->regmap, reg_fan_high, (limit & 0x1f00) >> 5);
+abort:
+       mutex_unlock(&data->access_lock);
+       return err;
+}
+
+static u8 nct7802_vmul[] = { 4, 2, 2, 2, 2 };
+
+static int nct7802_read_voltage(struct nct7802_data *data, int nr, int index)
+{
+       unsigned int v1, v2;
+       int ret;
+
+       mutex_lock(&data->access_lock);
+       if (index == 0) {       /* voltage */
+               ret = regmap_read(data->regmap, REG_VOLTAGE[nr], &v1);
+               if (ret < 0)
+                       goto abort;
+               ret = regmap_read(data->regmap, REG_VOLTAGE_LOW, &v2);
+               if (ret < 0)
+                       goto abort;
+               ret = ((v1 << 2) | (v2 >> 6)) * nct7802_vmul[nr];
+       }  else {       /* limit */
+               int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
+
+               ret = regmap_read(data->regmap,
+                                 REG_VOLTAGE_LIMIT_LSB[index - 1][nr], &v1);
+               if (ret < 0)
+                       goto abort;
+               ret = regmap_read(data->regmap, REG_VOLTAGE_LIMIT_MSB[nr],
+                                 &v2);
+               if (ret < 0)
+                       goto abort;
+               ret = (v1 | ((v2 << shift) & 0x300)) * nct7802_vmul[nr];
+       }
+abort:
+       mutex_unlock(&data->access_lock);
+       return ret;
+}
+
+static int nct7802_write_voltage(struct nct7802_data *data, int nr, int index,
+                                unsigned int voltage)
+{
+       int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
+       int err;
+
+       voltage = DIV_ROUND_CLOSEST(voltage, nct7802_vmul[nr]);
+       voltage = clamp_val(voltage, 0, 0x3ff);
+
+       mutex_lock(&data->access_lock);
+       err = regmap_write(data->regmap,
+                          REG_VOLTAGE_LIMIT_LSB[index - 1][nr],
+                          voltage & 0xff);
+       if (err < 0)
+               goto abort;
+
+       err = regmap_update_bits(data->regmap, REG_VOLTAGE_LIMIT_MSB[nr],
+                                0x0300 >> shift, (voltage & 0x0300) >> shift);
+abort:
+       mutex_unlock(&data->access_lock);
+       return err;
+}
+
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+                      char *buf)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       int voltage;
+
+       voltage = nct7802_read_voltage(data, sattr->nr, sattr->index);
+       if (voltage < 0)
+               return voltage;
+
+       return sprintf(buf, "%d\n", voltage);
+}
+
+static ssize_t store_in(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       int index = sattr->index;
+       int nr = sattr->nr;
+       unsigned long val;
+       int err;
+
+       err = kstrtoul(buf, 10, &val);
+       if (err < 0)
+               return err;
+
+       err = nct7802_write_voltage(data, nr, index, val);
+       return err ? : count;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       int err, temp;
+
+       err = nct7802_read_temp(data, sattr->nr, sattr->index, &temp);
+       if (err < 0)
+               return err;
+
+       return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t store_temp(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       int nr = sattr->nr;
+       long val;
+       int err;
+
+       err = kstrtol(buf, 10, &val);
+       if (err < 0)
+               return err;
+
+       val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+
+       err = regmap_write(data->regmap, nr, val & 0xff);
+       return err ? : count;
+}
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       int speed;
+
+       speed = nct7802_read_fan(data, sattr->index);
+       if (speed < 0)
+               return speed;
+
+       return sprintf(buf, "%d\n", speed);
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       int speed;
+
+       speed = nct7802_read_fan_min(data, sattr->nr, sattr->index);
+       if (speed < 0)
+               return speed;
+
+       return sprintf(buf, "%d\n", speed);
+}
+
+static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       unsigned long val;
+       int err;
+
+       err = kstrtoul(buf, 10, &val);
+       if (err < 0)
+               return err;
+
+       err = nct7802_write_fan_min(data, sattr->nr, sattr->index, val);
+       return err ? : count;
+}
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       int bit = sattr->index;
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(data->regmap, sattr->nr, &val);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%u\n", !!(val & (1 << bit)));
+}
+
+static ssize_t
+show_beep(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       unsigned int regval;
+       int err;
+
+       err = regmap_read(data->regmap, sattr->nr, &regval);
+       if (err)
+               return err;
+
+       return sprintf(buf, "%u\n", !!(regval & (1 << sattr->index)));
+}
+
+static ssize_t
+store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
+          size_t count)
+{
+       struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       unsigned long val;
+       int err;
+
+       err = kstrtoul(buf, 10, &val);
+       if (err < 0)
+               return err;
+       if (val > 1)
+               return -EINVAL;
+
+       err = regmap_update_bits(data->regmap, sattr->nr, 1 << sattr->index,
+                                val ? 1 << sattr->index : 0);
+       return err ? : count;
+}
+
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0x01,
+                           REG_TEMP_LSB);
+static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x31, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x30, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x3a, 0);
+
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0x02,
+                           REG_TEMP_LSB);
+static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x33, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x32, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x3b, 0);
+
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0x03,
+                           REG_TEMP_LSB);
+static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x35, 0);
+static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x34, 0);
+static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x3c, 0);
+
+static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 0x04, 0);
+static SENSOR_DEVICE_ATTR_2(temp4_min, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x37, 0);
+static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x36, 0);
+static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x3d, 0);
+
+static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 0x06,
+                           REG_TEMP_PECI_LSB);
+static SENSOR_DEVICE_ATTR_2(temp5_min, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x39, 0);
+static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x38, 0);
+static SENSOR_DEVICE_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp,
+                           store_temp, 0x3e, 0);
+
+static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 0x07,
+                           REG_TEMP_PECI_LSB);
+
+static SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO, show_alarm, NULL,
+                           0x18, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO, show_alarm, NULL,
+                           0x18, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO, show_alarm, NULL,
+                           0x18, 2);
+static SENSOR_DEVICE_ATTR_2(temp4_min_alarm, S_IRUGO, show_alarm, NULL,
+                           0x18, 3);
+static SENSOR_DEVICE_ATTR_2(temp5_min_alarm, S_IRUGO, show_alarm, NULL,
+                           0x18, 4);
+
+static SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
+                           0x19, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO, show_alarm, NULL,
+                           0x19, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO, show_alarm, NULL,
+                           0x19, 2);
+static SENSOR_DEVICE_ATTR_2(temp4_max_alarm, S_IRUGO, show_alarm, NULL,
+                           0x19, 3);
+static SENSOR_DEVICE_ATTR_2(temp5_max_alarm, S_IRUGO, show_alarm, NULL,
+                           0x19, 4);
+
+static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, show_alarm, NULL,
+                           0x1b, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO, show_alarm, NULL,
+                           0x1b, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, show_alarm, NULL,
+                           0x1b, 2);
+static SENSOR_DEVICE_ATTR_2(temp4_crit_alarm, S_IRUGO, show_alarm, NULL,
+                           0x1b, 3);
+static SENSOR_DEVICE_ATTR_2(temp5_crit_alarm, S_IRUGO, show_alarm, NULL,
+                           0x1b, 4);
+
+static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_alarm, NULL, 0x17, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_fault, S_IRUGO, show_alarm, NULL, 0x17, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_alarm, NULL, 0x17, 2);
+
+static SENSOR_DEVICE_ATTR_2(temp1_beep, S_IRUGO | S_IWUSR, show_beep,
+                           store_beep, 0x5c, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_beep, S_IRUGO | S_IWUSR, show_beep,
+                           store_beep, 0x5c, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_beep, S_IRUGO | S_IWUSR, show_beep,
+                           store_beep, 0x5c, 2);
+static SENSOR_DEVICE_ATTR_2(temp4_beep, S_IRUGO | S_IWUSR, show_beep,
+                           store_beep, 0x5c, 3);
+static SENSOR_DEVICE_ATTR_2(temp5_beep, S_IRUGO | S_IWUSR, show_beep,
+                           store_beep, 0x5c, 4);
+static SENSOR_DEVICE_ATTR_2(temp6_beep, S_IRUGO | S_IWUSR, show_beep,
+                           store_beep, 0x5c, 5);
+
+static struct attribute *nct7802_temp_attrs[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_min.dev_attr.attr,
+       &sensor_dev_attr_temp1_max.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp1_fault.dev_attr.attr,
+       &sensor_dev_attr_temp1_beep.dev_attr.attr,
+
+       &sensor_dev_attr_temp2_input.dev_attr.attr,             /* 9 */
+       &sensor_dev_attr_temp2_min.dev_attr.attr,
+       &sensor_dev_attr_temp2_max.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit.dev_attr.attr,
+       &sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp2_fault.dev_attr.attr,
+       &sensor_dev_attr_temp2_beep.dev_attr.attr,
+
+       &sensor_dev_attr_temp3_input.dev_attr.attr,             /* 18 */
+       &sensor_dev_attr_temp3_min.dev_attr.attr,
+       &sensor_dev_attr_temp3_max.dev_attr.attr,
+       &sensor_dev_attr_temp3_crit.dev_attr.attr,
+       &sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp3_fault.dev_attr.attr,
+       &sensor_dev_attr_temp3_beep.dev_attr.attr,
+
+       &sensor_dev_attr_temp4_input.dev_attr.attr,             /* 27 */
+       &sensor_dev_attr_temp4_min.dev_attr.attr,
+       &sensor_dev_attr_temp4_max.dev_attr.attr,
+       &sensor_dev_attr_temp4_crit.dev_attr.attr,
+       &sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp4_beep.dev_attr.attr,
+
+       &sensor_dev_attr_temp5_input.dev_attr.attr,             /* 35 */
+       &sensor_dev_attr_temp5_min.dev_attr.attr,
+       &sensor_dev_attr_temp5_max.dev_attr.attr,
+       &sensor_dev_attr_temp5_crit.dev_attr.attr,
+       &sensor_dev_attr_temp5_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
+       &sensor_dev_attr_temp5_beep.dev_attr.attr,
+
+       &sensor_dev_attr_temp6_input.dev_attr.attr,             /* 43 */
+       &sensor_dev_attr_temp6_beep.dev_attr.attr,
+
+       NULL
+};
+
+static umode_t nct7802_temp_is_visible(struct kobject *kobj,
+                                      struct attribute *attr, int index)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       unsigned int reg;
+       int err;
+
+       err = regmap_read(data->regmap, REG_MODE, &reg);
+       if (err < 0)
+               return 0;
+
+       if (index < 9 &&
+           (reg & 03) != 0x01 && (reg & 0x03) != 0x02)         /* RD1 */
+               return 0;
+       if (index >= 9 && index < 18 &&
+           (reg & 0x0c) != 0x04 && (reg & 0x0c) != 0x08)       /* RD2 */
+               return 0;
+       if (index >= 18 && index < 27 && (reg & 0x30) != 0x10)  /* RD3 */
+               return 0;
+       if (index >= 27 && index < 35)                          /* local */
+               return attr->mode;
+
+       err = regmap_read(data->regmap, REG_PECI_ENABLE, &reg);
+       if (err < 0)
+               return 0;
+
+       if (index >= 35 && index < 43 && !(reg & 0x01))         /* PECI 0 */
+               return 0;
+
+       if (index >= 0x43 && (!(reg & 0x02)))                   /* PECI 1 */
+               return 0;
+
+       return attr->mode;
+}
+
+static struct attribute_group nct7802_temp_group = {
+       .attrs = nct7802_temp_attrs,
+       .is_visible = nct7802_temp_is_visible,
+};
+
+static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, store_in,
+                           0, 1);
+static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, store_in,
+                           0, 2);
+static SENSOR_DEVICE_ATTR_2(in0_alarm, S_IRUGO, show_alarm, NULL, 0x1e, 3);
+static SENSOR_DEVICE_ATTR_2(in0_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
+                           0x5a, 3);
+
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, 0);
+
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, 0);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, store_in,
+                           2, 1);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, store_in,
+                           2, 2);
+static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_alarm, NULL, 0x1e, 0);
+static SENSOR_DEVICE_ATTR_2(in2_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
+                           0x5a, 0);
+
+static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, 0);
+static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, store_in,
+                           3, 1);
+static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, store_in,
+                           3, 2);
+static SENSOR_DEVICE_ATTR_2(in3_alarm, S_IRUGO, show_alarm, NULL, 0x1e, 1);
+static SENSOR_DEVICE_ATTR_2(in3_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
+                           0x5a, 1);
+
+static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, 0);
+static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, store_in,
+                           4, 1);
+static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, store_in,
+                           4, 2);
+static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, show_alarm, NULL, 0x1e, 2);
+static SENSOR_DEVICE_ATTR_2(in4_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
+                           0x5a, 2);
+
+static struct attribute *nct7802_in_attrs[] = {
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in0_min.dev_attr.attr,
+       &sensor_dev_attr_in0_max.dev_attr.attr,
+       &sensor_dev_attr_in0_alarm.dev_attr.attr,
+       &sensor_dev_attr_in0_beep.dev_attr.attr,
+
+       &sensor_dev_attr_in1_input.dev_attr.attr,       /* 5 */
+
+       &sensor_dev_attr_in2_input.dev_attr.attr,       /* 6 */
+       &sensor_dev_attr_in2_min.dev_attr.attr,
+       &sensor_dev_attr_in2_max.dev_attr.attr,
+       &sensor_dev_attr_in2_alarm.dev_attr.attr,
+       &sensor_dev_attr_in2_beep.dev_attr.attr,
+
+       &sensor_dev_attr_in3_input.dev_attr.attr,       /* 11 */
+       &sensor_dev_attr_in3_min.dev_attr.attr,
+       &sensor_dev_attr_in3_max.dev_attr.attr,
+       &sensor_dev_attr_in3_alarm.dev_attr.attr,
+       &sensor_dev_attr_in3_beep.dev_attr.attr,
+
+       &sensor_dev_attr_in4_input.dev_attr.attr,       /* 17 */
+       &sensor_dev_attr_in4_min.dev_attr.attr,
+       &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in4_alarm.dev_attr.attr,
+       &sensor_dev_attr_in4_beep.dev_attr.attr,
+
+       NULL,
+};
+
+static umode_t nct7802_in_is_visible(struct kobject *kobj,
+                                    struct attribute *attr, int index)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       unsigned int reg;
+       int err;
+
+       if (index < 6)                                          /* VCC, VCORE */
+               return attr->mode;
+
+       err = regmap_read(data->regmap, REG_MODE, &reg);
+       if (err < 0)
+               return 0;
+
+       if (index >= 6 && index < 11 && (reg & 0x03) != 0x03)   /* VSEN1 */
+               return 0;
+       if (index >= 11 && index < 17 && (reg & 0x0c) != 0x0c)  /* VSEN2 */
+               return 0;
+       if (index >= 17 && (reg & 0x30) != 0x30)                /* VSEN3 */
+               return 0;
+
+       return attr->mode;
+}
+
+static struct attribute_group nct7802_in_group = {
+       .attrs = nct7802_in_attrs,
+       .is_visible = nct7802_in_is_visible,
+};
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0x10);
+static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan_min,
+                           store_fan_min, 0x49, 0x4c);
+static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, show_alarm, NULL, 0x1a, 0);
+static SENSOR_DEVICE_ATTR_2(fan1_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
+                           0x5b, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 0x11);
+static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan_min,
+                           store_fan_min, 0x4a, 0x4d);
+static SENSOR_DEVICE_ATTR_2(fan2_alarm, S_IRUGO, show_alarm, NULL, 0x1a, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
+                           0x5b, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 0x12);
+static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan_min,
+                           store_fan_min, 0x4b, 0x4e);
+static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_alarm, NULL, 0x1a, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
+                           0x5b, 2);
+
+static struct attribute *nct7802_fan_attrs[] = {
+       &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_fan1_min.dev_attr.attr,
+       &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+       &sensor_dev_attr_fan1_beep.dev_attr.attr,
+       &sensor_dev_attr_fan2_input.dev_attr.attr,
+       &sensor_dev_attr_fan2_min.dev_attr.attr,
+       &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+       &sensor_dev_attr_fan2_beep.dev_attr.attr,
+       &sensor_dev_attr_fan3_input.dev_attr.attr,
+       &sensor_dev_attr_fan3_min.dev_attr.attr,
+       &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+       &sensor_dev_attr_fan3_beep.dev_attr.attr,
+
+       NULL
+};
+
+static umode_t nct7802_fan_is_visible(struct kobject *kobj,
+                                     struct attribute *attr, int index)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct nct7802_data *data = dev_get_drvdata(dev);
+       int fan = index / 4;    /* 4 attributes per fan */
+       unsigned int reg;
+       int err;
+
+       err = regmap_read(data->regmap, REG_FAN_ENABLE, &reg);
+       if (err < 0 || !(reg & (1 << fan)))
+               return 0;
+
+       return attr->mode;
+}
+
+static struct attribute_group nct7802_fan_group = {
+       .attrs = nct7802_fan_attrs,
+       .is_visible = nct7802_fan_is_visible,
+};
+
+static const struct attribute_group *nct7802_groups[] = {
+       &nct7802_temp_group,
+       &nct7802_in_group,
+       &nct7802_fan_group,
+       NULL
+};
+
+static int nct7802_detect(struct i2c_client *client,
+                         struct i2c_board_info *info)
+{
+       int reg;
+
+       /*
+        * Chip identification registers are only available in bank 0,
+        * so only attempt chip detection if bank 0 is selected
+        */
+       reg = i2c_smbus_read_byte_data(client, REG_BANK);
+       if (reg != 0x00)
+               return -ENODEV;
+
+       reg = i2c_smbus_read_byte_data(client, REG_VENDOR_ID);
+       if (reg != 0x50)
+               return -ENODEV;
+
+       reg = i2c_smbus_read_byte_data(client, REG_CHIP_ID);
+       if (reg != 0xc3)
+               return -ENODEV;
+
+       reg = i2c_smbus_read_byte_data(client, REG_VERSION_ID);
+       if (reg < 0 || (reg & 0xf0) != 0x20)
+               return -ENODEV;
+
+       /* Also validate lower bits of voltage and temperature registers */
+       reg = i2c_smbus_read_byte_data(client, REG_TEMP_LSB);
+       if (reg < 0 || (reg & 0x1f))
+               return -ENODEV;
+
+       reg = i2c_smbus_read_byte_data(client, REG_TEMP_PECI_LSB);
+       if (reg < 0 || (reg & 0x3f))
+               return -ENODEV;
+
+       reg = i2c_smbus_read_byte_data(client, REG_VOLTAGE_LOW);
+       if (reg < 0 || (reg & 0x3f))
+               return -ENODEV;
+
+       strlcpy(info->type, "nct7802", I2C_NAME_SIZE);
+       return 0;
+}
+
+static bool nct7802_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+       return reg != REG_BANK && reg <= 0x20;
+}
+
+static struct regmap_config nct7802_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .cache_type = REGCACHE_RBTREE,
+       .volatile_reg = nct7802_regmap_is_volatile,
+};
+
+static int nct7802_init_chip(struct nct7802_data *data)
+{
+       int err;
+
+       /* Enable ADC */
+       err = regmap_update_bits(data->regmap, REG_START, 0x01, 0x01);
+       if (err)
+               return err;
+
+       /* Enable local temperature sensor */
+       err = regmap_update_bits(data->regmap, REG_MODE, 0x40, 0x40);
+       if (err)
+               return err;
+
+       /* Enable Vcore and VCC voltage monitoring */
+       return regmap_update_bits(data->regmap, REG_VMON_ENABLE, 0x03, 0x03);
+}
+
+static int nct7802_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct device *dev = &client->dev;
+       struct nct7802_data *data;
+       struct device *hwmon_dev;
+       int ret;
+
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       data->regmap = devm_regmap_init_i2c(client, &nct7802_regmap_config);
+       if (IS_ERR(data->regmap))
+               return PTR_ERR(data->regmap);
+
+       mutex_init(&data->access_lock);
+
+       ret = nct7802_init_chip(data);
+       if (ret < 0)
+               return ret;
+
+       hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+                                                          data,
+                                                          nct7802_groups);
+       return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const unsigned short nct7802_address_list[] = {
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END
+};
+
+static const struct i2c_device_id nct7802_idtable[] = {
+       { "nct7802", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, nct7802_idtable);
+
+static struct i2c_driver nct7802_driver = {
+       .class = I2C_CLASS_HWMON,
+       .driver = {
+               .name = DRVNAME,
+       },
+       .detect = nct7802_detect,
+       .probe = nct7802_probe,
+       .id_table = nct7802_idtable,
+       .address_list = nct7802_address_list,
+};
+
+module_i2c_driver(nct7802_driver);
+
+MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
+MODULE_DESCRIPTION("NCT7802Y Hardware Monitoring Driver");
+MODULE_LICENSE("GPL v2");
index 6e1e4935fc6226c0ec8993f56f68e8dc6ebdab3f..a674cd83a4e2ecfb4e3fbf63f31539ca933ea02b 100644 (file)
@@ -47,15 +47,22 @@ config SENSORS_LM25066
          be called lm25066.
 
 config SENSORS_LTC2978
-       tristate "Linear Technologies LTC2974, LTC2978, LTC3880, and LTC3883"
+       tristate "Linear Technologies LTC2978 and compatibles"
        default n
        help
          If you say yes here you get hardware monitoring support for Linear
-         Technology LTC2974, LTC2978, LTC3880, and LTC3883.
+         Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
 
          This driver can also be built as a module. If so, the module will
          be called ltc2978.
 
+config SENSORS_LTC2978_REGULATOR
+       boolean "Regulator support for LTC2978 and compatibles"
+       depends on SENSORS_LTC2978 && REGULATOR
+       help
+         If you say yes here you get regulator support for Linear
+         Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
+
 config SENSORS_MAX16064
        tristate "Maxim MAX16064"
        default n
index e24ed521051a4a1f7b799849a5c5feee1fa6b369..0835050ec245ba67c65bd59f341b0f7eef2c3032 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/regulator/driver.h>
 #include "pmbus.h"
 
 enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 };
@@ -374,6 +375,19 @@ static const struct i2c_device_id ltc2978_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ltc2978_id);
 
+#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
+static const struct regulator_desc ltc2978_reg_desc[] = {
+       PMBUS_REGULATOR("vout", 0),
+       PMBUS_REGULATOR("vout", 1),
+       PMBUS_REGULATOR("vout", 2),
+       PMBUS_REGULATOR("vout", 3),
+       PMBUS_REGULATOR("vout", 4),
+       PMBUS_REGULATOR("vout", 5),
+       PMBUS_REGULATOR("vout", 6),
+       PMBUS_REGULATOR("vout", 7),
+};
+#endif /* CONFIG_SENSORS_LTC2978_REGULATOR */
+
 static int ltc2978_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
@@ -487,13 +501,36 @@ static int ltc2978_probe(struct i2c_client *client,
        default:
                return -ENODEV;
        }
+
+#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
+       info->num_regulators = info->pages;
+       info->reg_desc = ltc2978_reg_desc;
+       if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc)) {
+               dev_err(&client->dev, "num_regulators too large!");
+               info->num_regulators = ARRAY_SIZE(ltc2978_reg_desc);
+       }
+#endif
+
        return pmbus_do_probe(client, id, info);
 }
 
-/* This is the driver that will be inserted */
+#ifdef CONFIG_OF
+static const struct of_device_id ltc2978_of_match[] = {
+       { .compatible = "lltc,ltc2974" },
+       { .compatible = "lltc,ltc2977" },
+       { .compatible = "lltc,ltc2978" },
+       { .compatible = "lltc,ltc3880" },
+       { .compatible = "lltc,ltc3883" },
+       { .compatible = "lltc,ltm4676" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ltc2978_of_match);
+#endif
+
 static struct i2c_driver ltc2978_driver = {
        .driver = {
                   .name = "ltc2978",
+                  .of_match_table = of_match_ptr(ltc2978_of_match),
                   },
        .probe = ltc2978_probe,
        .remove = pmbus_do_remove,
index fa9beb3eb60ca2a33cc6150542dfcbbc90b84219..89a23ff836e71752bf113ad4f0c48da35af5e89a 100644 (file)
@@ -19,6 +19,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/regulator/driver.h>
+
 #ifndef PMBUS_H
 #define PMBUS_H
 
 #define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
 #define PMBUS_VIRT_STATUS_VMON         (PMBUS_VIRT_BASE + 35)
 
+/*
+ * OPERATION
+ */
+#define PB_OPERATION_CONTROL_ON                (1<<7)
+
 /*
  * CAPABILITY
  */
@@ -365,8 +372,27 @@ struct pmbus_driver_info {
         */
        int (*identify)(struct i2c_client *client,
                        struct pmbus_driver_info *info);
+
+       /* Regulator functionality, if supported by this chip driver. */
+       int num_regulators;
+       const struct regulator_desc *reg_desc;
 };
 
+/* Regulator ops */
+
+extern struct regulator_ops pmbus_regulator_ops;
+
+/* Macro for filling in array of struct regulator_desc */
+#define PMBUS_REGULATOR(_name, _id)                            \
+       [_id] = {                                               \
+               .name = (_name # _id),                          \
+               .id = (_id),                                    \
+               .of_match = of_match_ptr(_name # _id),          \
+               .regulators_node = of_match_ptr("regulators"),  \
+               .ops = &pmbus_regulator_ops,                    \
+               .owner = THIS_MODULE,                           \
+       }
+
 /* Function declarations */
 
 void pmbus_clear_cache(struct i2c_client *client);
@@ -375,6 +401,10 @@ int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
 int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
 int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
 int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
+int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg,
+                         u8 value);
+int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
+                          u8 mask, u8 value);
 void pmbus_clear_faults(struct i2c_client *client);
 bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
 bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
index 291d11fe93e792f50eab32bff2ce0783d97a75d8..f2e47c7dd808becd444512c74dc5738c9e544955 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/jiffies.h>
 #include <linux/i2c/pmbus.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
 #include "pmbus.h"
 
 /*
@@ -253,6 +255,37 @@ int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
 }
 EXPORT_SYMBOL_GPL(pmbus_read_byte_data);
 
+int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, u8 value)
+{
+       int rv;
+
+       rv = pmbus_set_page(client, page);
+       if (rv < 0)
+               return rv;
+
+       return i2c_smbus_write_byte_data(client, reg, value);
+}
+EXPORT_SYMBOL_GPL(pmbus_write_byte_data);
+
+int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
+                          u8 mask, u8 value)
+{
+       unsigned int tmp;
+       int rv;
+
+       rv = pmbus_read_byte_data(client, page, reg);
+       if (rv < 0)
+               return rv;
+
+       tmp = (rv & ~mask) | (value & mask);
+
+       if (tmp != rv)
+               rv = pmbus_write_byte_data(client, page, reg, tmp);
+
+       return rv;
+}
+EXPORT_SYMBOL_GPL(pmbus_update_byte_data);
+
 /*
  * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if
  * a device specific mapping function exists and calls it if necessary.
@@ -1727,6 +1760,84 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_REGULATOR)
+static int pmbus_regulator_is_enabled(struct regulator_dev *rdev)
+{
+       struct device *dev = rdev_get_dev(rdev);
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       u8 page = rdev_get_id(rdev);
+       int ret;
+
+       ret = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
+       if (ret < 0)
+               return ret;
+
+       return !!(ret & PB_OPERATION_CONTROL_ON);
+}
+
+static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable)
+{
+       struct device *dev = rdev_get_dev(rdev);
+       struct i2c_client *client = to_i2c_client(dev->parent);
+       u8 page = rdev_get_id(rdev);
+
+       return pmbus_update_byte_data(client, page, PMBUS_OPERATION,
+                                     PB_OPERATION_CONTROL_ON,
+                                     enable ? PB_OPERATION_CONTROL_ON : 0);
+}
+
+static int pmbus_regulator_enable(struct regulator_dev *rdev)
+{
+       return _pmbus_regulator_on_off(rdev, 1);
+}
+
+static int pmbus_regulator_disable(struct regulator_dev *rdev)
+{
+       return _pmbus_regulator_on_off(rdev, 0);
+}
+
+struct regulator_ops pmbus_regulator_ops = {
+       .enable = pmbus_regulator_enable,
+       .disable = pmbus_regulator_disable,
+       .is_enabled = pmbus_regulator_is_enabled,
+};
+EXPORT_SYMBOL_GPL(pmbus_regulator_ops);
+
+static int pmbus_regulator_register(struct pmbus_data *data)
+{
+       struct device *dev = data->dev;
+       const struct pmbus_driver_info *info = data->info;
+       const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
+       struct regulator_dev *rdev;
+       int i;
+
+       for (i = 0; i < info->num_regulators; i++) {
+               struct regulator_config config = { };
+
+               config.dev = dev;
+               config.driver_data = data;
+
+               if (pdata && pdata->reg_init_data)
+                       config.init_data = &pdata->reg_init_data[i];
+
+               rdev = devm_regulator_register(dev, &info->reg_desc[i],
+                                              &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(dev, "Failed to register %s regulator\n",
+                               info->reg_desc[i].name);
+                       return PTR_ERR(rdev);
+               }
+       }
+
+       return 0;
+}
+#else
+static int pmbus_regulator_register(struct pmbus_data *data)
+{
+       return 0;
+}
+#endif
+
 int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
                   struct pmbus_driver_info *info)
 {
@@ -1781,8 +1892,15 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
                dev_err(dev, "Failed to register hwmon device\n");
                goto out_kfree;
        }
+
+       ret = pmbus_regulator_register(data);
+       if (ret)
+               goto out_unregister;
+
        return 0;
 
+out_unregister:
+       hwmon_device_unregister(data->hwmon_dev);
 out_kfree:
        kfree(data->group.attrs);
        return ret;
index 823c877a1ec0952ce5fab7a465c79826f3442764..1991d9032c3843de2ffcd20b82f5790d22ce2684 100644 (file)
@@ -161,10 +161,17 @@ static int pwm_fan_suspend(struct device *dev)
 static int pwm_fan_resume(struct device *dev)
 {
        struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+       unsigned long duty;
+       int ret;
 
-       if (ctx->pwm_value)
-               return pwm_enable(ctx->pwm);
-       return 0;
+       if (ctx->pwm_value == 0)
+               return 0;
+
+       duty = DIV_ROUND_UP(ctx->pwm_value * (ctx->pwm->period - 1), MAX_PWM);
+       ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
+       if (ret)
+               return ret;
+       return pwm_enable(ctx->pwm);
 }
 #endif
 
index 7fa6e7d0b9b6f93ea634954cd1d71d0a67b1694b..99664ebc738d8003139135a89f07f97e3c6305e2 100644 (file)
 #include <linux/sysfs.h>
 
 /* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
+static const unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4c, 0x4d,
+       0x4e, 0x4f, I2C_CLIENT_END };
 
-enum chips { tmp401, tmp411, tmp431, tmp432 };
+enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 };
 
 /*
  * The TMP401 registers, note some registers have different addresses for
@@ -136,6 +137,7 @@ static const u8 TMP432_STATUS_REG[] = {
 #define TMP411C_DEVICE_ID                      0x10
 #define TMP431_DEVICE_ID                       0x31
 #define TMP432_DEVICE_ID                       0x32
+#define TMP435_DEVICE_ID                       0x35
 
 /*
  * Driver data (common to all clients)
@@ -146,6 +148,7 @@ static const struct i2c_device_id tmp401_id[] = {
        { "tmp411", tmp411 },
        { "tmp431", tmp431 },
        { "tmp432", tmp432 },
+       { "tmp435", tmp435 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, tmp401_id);
@@ -613,10 +616,10 @@ static const struct attribute_group tmp432_group = {
  * Begin non sysfs callback code (aka Real code)
  */
 
-static void tmp401_init_client(struct tmp401_data *data,
-                              struct i2c_client *client)
+static int tmp401_init_client(struct tmp401_data *data,
+                             struct i2c_client *client)
 {
-       int config, config_orig;
+       int config, config_orig, status = 0;
 
        /* Set the conversion rate to 2 Hz */
        i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
@@ -624,16 +627,18 @@ static void tmp401_init_client(struct tmp401_data *data,
 
        /* Start conversions (disable shutdown if necessary) */
        config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ);
-       if (config < 0) {
-               dev_warn(&client->dev, "Initialization failed!\n");
-               return;
-       }
+       if (config < 0)
+               return config;
 
        config_orig = config;
        config &= ~TMP401_CONFIG_SHUTDOWN;
 
        if (config != config_orig)
-               i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config);
+               status = i2c_smbus_write_byte_data(client,
+                                                  TMP401_CONFIG_WRITE,
+                                                  config);
+
+       return status;
 }
 
 static int tmp401_detect(struct i2c_client *client,
@@ -675,15 +680,18 @@ static int tmp401_detect(struct i2c_client *client,
                kind = tmp411;
                break;
        case TMP431_DEVICE_ID:
-               if (client->addr == 0x4e)
+               if (client->addr != 0x4c && client->addr != 0x4d)
                        return -ENODEV;
                kind = tmp431;
                break;
        case TMP432_DEVICE_ID:
-               if (client->addr == 0x4e)
+               if (client->addr != 0x4c && client->addr != 0x4d)
                        return -ENODEV;
                kind = tmp432;
                break;
+       case TMP435_DEVICE_ID:
+               kind = tmp435;
+               break;
        default:
                return -ENODEV;
        }
@@ -705,11 +713,13 @@ static int tmp401_detect(struct i2c_client *client,
 static int tmp401_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
-       const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" };
+       static const char * const names[] = {
+               "TMP401", "TMP411", "TMP431", "TMP432", "TMP435"
+       };
        struct device *dev = &client->dev;
        struct device *hwmon_dev;
        struct tmp401_data *data;
-       int groups = 0;
+       int groups = 0, status;
 
        data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);
        if (!data)
@@ -720,7 +730,9 @@ static int tmp401_probe(struct i2c_client *client,
        data->kind = id->driver_data;
 
        /* Initialize the TMP401 chip */
-       tmp401_init_client(data, client);
+       status = tmp401_init_client(data, client);
+       if (status < 0)
+               return status;
 
        /* Register sysfs hooks */
        data->groups[groups++] = &tmp401_group;
index 65ef9664d5da884cdec666a81228408e5240b381..899bede81b31b37e7a5ee4ec45d37afadb13971d 100644 (file)
     but WITHOUT 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.
  * ------------------------------------------------------------------------- */
 
 /* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki
index 8b10f88b13d9bd8c908997d3ebdde7de84718732..580dbf05c1487c46e7ef504c18cfc8f128ced4cc 100644 (file)
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- *  MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index 34370090b753f616ff56e8a67e8172210b05c2cd..270d84bfc2c68b526d6b8119afa67f4cb3c37543 100644 (file)
  *  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.
- *
  * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
  * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey
  * <mbailey@littlefeet-inc.com>
index 1ec703ee788d2cc2c3467917d989f6c1c3c16973..262ee801975b314ce661f257595b74026637af6d 100644 (file)
     This program is distributed in the hope that it will be useful,
     but WITHOUT 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.                                                 */
+    GNU General Public License for more details.                       */
 /* --------------------------------------------------------------------        */
 
 /* With some changes from Frodo Looijaard <frodol@dds.nl> */
index 917c3585f45bc16123a24e113e3847c17d011ca5..b4d135cc2f39be31e9b05ce2f0dbd1819cc8e2db 100644 (file)
@@ -881,6 +881,16 @@ config I2C_DIOLAN_U2C
          This driver can also be built as a module.  If so, the module
          will be called i2c-diolan-u2c.
 
+config I2C_DLN2
+       tristate "Diolan DLN-2 USB I2C adapter"
+       depends on MFD_DLN2
+       help
+        If you say yes to this option, support will be included for Diolan
+        DLN2, a USB to I2C interface.
+
+        This driver can also be built as a module.  If so, the module
+        will be called i2c-dln2.
+
 config I2C_PARPORT
        tristate "Parallel port adapter"
        depends on PARPORT
index 78d56c54ba2bcff56ddd101d1cec83142eb7c45e..cdac7f15eab5341a3526ad40ded1bb66afa4f4e7 100644 (file)
@@ -87,6 +87,7 @@ obj-$(CONFIG_I2C_RCAR)                += i2c-rcar.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_DIOLAN_U2C)   += i2c-diolan-u2c.o
+obj-$(CONFIG_I2C_DLN2)         += i2c-dln2.o
 obj-$(CONFIG_I2C_PARPORT)      += i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)        += i2c-parport-light.o
 obj-$(CONFIG_I2C_ROBOTFUZZ_OSIF)       += i2c-robotfuzz-osif.o
index 451e305f797133291ffbd48bceefaa8eb194d1ed..4f2d78868281ef7eda0e11bc03518f10089a2aff 100644 (file)
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 2fa21ce9682b9b64e0511794ec1e2d3f525ca0b5..45c5c488302282876032e4fc7da289af00d1e1e1 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 41fc6837fb8b5393f2193873c765d07d87a2e955..65e324054970b51aded8091d8f8b5a212fd49bc4 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
  
 /*
index a16f72891358124c6069ffbfd9eee537dfb2abf0..6c7113d990f882a758435eb78fc172510a6faed6 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 917d54588d95c14f966abd326e12467bea244342..e05a672db3e50aa3800cbb1d1db3af4c74ba9577 100644 (file)
@@ -434,7 +434,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
                }
        }
 
-       ret = wait_for_completion_io_timeout(&dev->cmd_complete,
+       ret = wait_for_completion_timeout(&dev->cmd_complete,
                                             dev->adapter.timeout);
        if (ret == 0) {
                dev_err(dev->dev, "controller timed out\n");
index 8762458ca7da1f09d5094f5f0490bd2bb22c3c2b..6f8c0756e350c707df7202c9f0b6062efda42759 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 #include <linux/delay.h>
index 63f3f03ecc9b069f899eccbe9524168bbef3656c..c604f4c3ac0dd53d036e28d839f81a87dbfea913 100644 (file)
 #define CDNS_I2C_DIVA_MAX      4
 #define CDNS_I2C_DIVB_MAX      64
 
+#define CDNS_I2C_TIMEOUT_MAX   0xFF
+
 #define cdns_i2c_readreg(offset)       readl_relaxed(id->membase + offset)
 #define cdns_i2c_writereg(val, offset) writel_relaxed(val, id->membase + offset)
 
@@ -852,6 +854,15 @@ static int cdns_i2c_probe(struct platform_device *pdev)
                goto err_clk_dis;
        }
 
+       /*
+        * Cadence I2C controller has a bug wherein it generates
+        * invalid read transaction after HW timeout in master receiver mode.
+        * HW timeout is not used by this driver and the interrupt is disabled.
+        * But the feature itself cannot be disabled. Hence maximum value
+        * is written to this register to reduce the chances of error.
+        */
+       cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
+
        dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n",
                 id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq);
 
index f3b89a4698b6192a24d031bab358796e51fbb767..5bdbc71698d0ec040bdecf6ad7d7ee9581e60706 100644 (file)
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/kernel.h>
index 4d96147191289680837e6710b8d7edfb5ecda73e..01f0cd87a4a5b6d40fb0c01b17d5d589cc2d4ac4 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ----------------------------------------------------------------------------
  *
  */
@@ -411,11 +407,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
        if (dev->cmd_err & DAVINCI_I2C_STR_NACK) {
                if (msg->flags & I2C_M_IGNORE_NAK)
                        return msg->len;
-               if (stop) {
-                       w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
-                       w |= DAVINCI_I2C_MDR_STP;
-                       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
-               }
+               w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
+               w |= DAVINCI_I2C_MDR_STP;
+               davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
                return -EREMOTEIO;
        }
        return -EIO;
index 3c20e4bd6dd1380238df20f06941828ec84aadd0..23628b7bfb8d8df208c6e434efb95e887dfad6e6 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ----------------------------------------------------------------------------
  *
  */
@@ -363,7 +359,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        }
 
        /* Configure Tx/Rx FIFO threshold levels */
-       dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL);
+       dw_writel(dev, dev->tx_fifo_depth / 2, DW_IC_TX_TL);
        dw_writel(dev, 0, DW_IC_RX_TL);
 
        /* configure the i2c master */
index d66b6cbc9edcbb742079612d336cc56e093b99c4..5a410ef17abd40c0ab7c7ece3ab3fa539adf1f95 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ----------------------------------------------------------------------------
  *
  */
index d31d313ab4f7694564012d3ad6d570a0c9f5f3a7..acb40f95db78f512c561f6d4d2b5b67479844811 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ----------------------------------------------------------------------------
  *
  */
index a7431150acf7c3da87e248e4e2f25fa3ffa16589..373dd4d477653f11d943ea49ad87c92a598636c5 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ----------------------------------------------------------------------------
  *
  */
diff --git a/drivers/i2c/busses/i2c-dln2.c b/drivers/i2c/busses/i2c-dln2.c
new file mode 100644 (file)
index 0000000..b3fb86a
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Driver for the Diolan DLN-2 USB-I2C adapter
+ *
+ * Copyright (c) 2014 Intel Corporation
+ *
+ * Derived from:
+ *  i2c-diolan-u2c.c
+ *  Copyright (c) 2010-2011 Ericsson AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/dln2.h>
+
+#define DLN2_I2C_MODULE_ID             0x03
+#define DLN2_I2C_CMD(cmd)              DLN2_CMD(cmd, DLN2_I2C_MODULE_ID)
+
+/* I2C commands */
+#define DLN2_I2C_GET_PORT_COUNT                DLN2_I2C_CMD(0x00)
+#define DLN2_I2C_ENABLE                        DLN2_I2C_CMD(0x01)
+#define DLN2_I2C_DISABLE               DLN2_I2C_CMD(0x02)
+#define DLN2_I2C_IS_ENABLED            DLN2_I2C_CMD(0x03)
+#define DLN2_I2C_WRITE                 DLN2_I2C_CMD(0x06)
+#define DLN2_I2C_READ                  DLN2_I2C_CMD(0x07)
+#define DLN2_I2C_SCAN_DEVICES          DLN2_I2C_CMD(0x08)
+#define DLN2_I2C_PULLUP_ENABLE         DLN2_I2C_CMD(0x09)
+#define DLN2_I2C_PULLUP_DISABLE                DLN2_I2C_CMD(0x0A)
+#define DLN2_I2C_PULLUP_IS_ENABLED     DLN2_I2C_CMD(0x0B)
+#define DLN2_I2C_TRANSFER              DLN2_I2C_CMD(0x0C)
+#define DLN2_I2C_SET_MAX_REPLY_COUNT   DLN2_I2C_CMD(0x0D)
+#define DLN2_I2C_GET_MAX_REPLY_COUNT   DLN2_I2C_CMD(0x0E)
+
+#define DLN2_I2C_MAX_XFER_SIZE         256
+#define DLN2_I2C_BUF_SIZE              (DLN2_I2C_MAX_XFER_SIZE + 16)
+
+struct dln2_i2c {
+       struct platform_device *pdev;
+       struct i2c_adapter adapter;
+       u8 port;
+       /*
+        * Buffer to hold the packet for read or write transfers. One is enough
+        * since we can't have multiple transfers in parallel on the i2c bus.
+        */
+       void *buf;
+};
+
+static int dln2_i2c_enable(struct dln2_i2c *dln2, bool enable)
+{
+       u16 cmd;
+       struct {
+               u8 port;
+       } tx;
+
+       tx.port = dln2->port;
+
+       if (enable)
+               cmd = DLN2_I2C_ENABLE;
+       else
+               cmd = DLN2_I2C_DISABLE;
+
+       return dln2_transfer_tx(dln2->pdev, cmd, &tx, sizeof(tx));
+}
+
+static int dln2_i2c_write(struct dln2_i2c *dln2, u8 addr,
+                         u8 *data, u16 data_len)
+{
+       int ret;
+       struct {
+               u8 port;
+               u8 addr;
+               u8 mem_addr_len;
+               __le32 mem_addr;
+               __le16 buf_len;
+               u8 buf[DLN2_I2C_MAX_XFER_SIZE];
+       } __packed *tx = dln2->buf;
+       unsigned len;
+
+       BUILD_BUG_ON(sizeof(*tx) > DLN2_I2C_BUF_SIZE);
+
+       tx->port = dln2->port;
+       tx->addr = addr;
+       tx->mem_addr_len = 0;
+       tx->mem_addr = 0;
+       tx->buf_len = cpu_to_le16(data_len);
+       memcpy(tx->buf, data, data_len);
+
+       len = sizeof(*tx) + data_len - DLN2_I2C_MAX_XFER_SIZE;
+       ret = dln2_transfer_tx(dln2->pdev, DLN2_I2C_WRITE, tx, len);
+       if (ret < 0)
+               return ret;
+
+       return data_len;
+}
+
+static int dln2_i2c_read(struct dln2_i2c *dln2, u16 addr, u8 *data,
+                        u16 data_len)
+{
+       int ret;
+       struct {
+               u8 port;
+               u8 addr;
+               u8 mem_addr_len;
+               __le32 mem_addr;
+               __le16 buf_len;
+       } __packed tx;
+       struct {
+               __le16 buf_len;
+               u8 buf[DLN2_I2C_MAX_XFER_SIZE];
+       } __packed *rx = dln2->buf;
+       unsigned rx_len = sizeof(*rx);
+
+       BUILD_BUG_ON(sizeof(*rx) > DLN2_I2C_BUF_SIZE);
+
+       tx.port = dln2->port;
+       tx.addr = addr;
+       tx.mem_addr_len = 0;
+       tx.mem_addr = 0;
+       tx.buf_len = cpu_to_le16(data_len);
+
+       ret = dln2_transfer(dln2->pdev, DLN2_I2C_READ, &tx, sizeof(tx),
+                           rx, &rx_len);
+       if (ret < 0)
+               return ret;
+       if (rx_len < sizeof(rx->buf_len) + data_len)
+               return -EPROTO;
+       if (le16_to_cpu(rx->buf_len) != data_len)
+               return -EPROTO;
+
+       memcpy(data, rx->buf, data_len);
+
+       return data_len;
+}
+
+static int dln2_i2c_xfer(struct i2c_adapter *adapter,
+                        struct i2c_msg *msgs, int num)
+{
+       struct dln2_i2c *dln2 = i2c_get_adapdata(adapter);
+       struct i2c_msg *pmsg;
+       struct device *dev = &dln2->adapter.dev;
+       int i;
+
+       for (i = 0; i < num; i++) {
+               int ret;
+
+               pmsg = &msgs[i];
+
+               if (pmsg->len > DLN2_I2C_MAX_XFER_SIZE) {
+                       dev_warn(dev, "maximum transfer size exceeded\n");
+                       return -EOPNOTSUPP;
+               }
+
+               if (pmsg->flags & I2C_M_RD) {
+                       ret = dln2_i2c_read(dln2, pmsg->addr, pmsg->buf,
+                                           pmsg->len);
+                       if (ret < 0)
+                               return ret;
+
+                       pmsg->len = ret;
+               } else {
+                       ret = dln2_i2c_write(dln2, pmsg->addr, pmsg->buf,
+                                            pmsg->len);
+                       if (ret != pmsg->len)
+                               return -EPROTO;
+               }
+       }
+
+       return num;
+}
+
+static u32 dln2_i2c_func(struct i2c_adapter *a)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
+               I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+               I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm dln2_i2c_usb_algorithm = {
+       .master_xfer = dln2_i2c_xfer,
+       .functionality = dln2_i2c_func,
+};
+
+static int dln2_i2c_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct dln2_i2c *dln2;
+       struct device *dev = &pdev->dev;
+       struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev);
+
+       dln2 = devm_kzalloc(dev, sizeof(*dln2), GFP_KERNEL);
+       if (!dln2)
+               return -ENOMEM;
+
+       dln2->buf = devm_kmalloc(dev, DLN2_I2C_BUF_SIZE, GFP_KERNEL);
+       if (!dln2->buf)
+               return -ENOMEM;
+
+       dln2->pdev = pdev;
+       dln2->port = pdata->port;
+
+       /* setup i2c adapter description */
+       dln2->adapter.owner = THIS_MODULE;
+       dln2->adapter.class = I2C_CLASS_HWMON;
+       dln2->adapter.algo = &dln2_i2c_usb_algorithm;
+       dln2->adapter.dev.parent = dev;
+       i2c_set_adapdata(&dln2->adapter, dln2);
+       snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d",
+                "dln2-i2c", dev_name(pdev->dev.parent), dln2->port);
+
+       platform_set_drvdata(pdev, dln2);
+
+       /* initialize the i2c interface */
+       ret = dln2_i2c_enable(dln2, true);
+       if (ret < 0) {
+               dev_err(dev, "failed to initialize adapter: %d\n", ret);
+               return ret;
+       }
+
+       /* and finally attach to i2c layer */
+       ret = i2c_add_adapter(&dln2->adapter);
+       if (ret < 0) {
+               dev_err(dev, "failed to add I2C adapter: %d\n", ret);
+               goto out_disable;
+       }
+
+       return 0;
+
+out_disable:
+       dln2_i2c_enable(dln2, false);
+
+       return ret;
+}
+
+static int dln2_i2c_remove(struct platform_device *pdev)
+{
+       struct dln2_i2c *dln2 = platform_get_drvdata(pdev);
+
+       i2c_del_adapter(&dln2->adapter);
+       dln2_i2c_enable(dln2, false);
+
+       return 0;
+}
+
+static struct platform_driver dln2_i2c_driver = {
+       .driver.name    = "dln2-i2c",
+       .probe          = dln2_i2c_probe,
+       .remove         = dln2_i2c_remove,
+};
+
+module_platform_driver(dln2_i2c_driver);
+
+MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>");
+MODULE_DESCRIPTION("Driver for the Diolan DLN2 I2C master interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dln2-i2c");
index a44ea13d143492ffd433a33148870e37f0a1450c..76e699f9ed9732cb910fd6092837d1ddf13c37c5 100644 (file)
@@ -9,10 +9,6 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  */
 
 #include <linux/module.h>
index 485497066ed7abca4df32b602b17f1e72b455a73..92e8c0ce16258111add80ecb60ce2ee37949309a 100644 (file)
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
+    GNU General Public License for more details.                            */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
index 14d2b76de25ff1da9a520236f110ce678a57bd43..b7864cf42a72c3d9a7d40008dd3fc1f0fa4c4cc8 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 #include <linux/kernel.h>
index 7cfc183b3d638adfcac780f750481fec622e738e..6ab4f1cb21f3fae717dfdfbf3b07e721d6e7254e 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index c48e46af670abec3314e63defc1662076c8008aa..e9fb7cf786120010d0c91a139612b4c59d90cadf 100644 (file)
  *     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.
- *
  * Author:
  *     Darius Augulis, Teltonika Inc.
  *
index 097e270955d0d2abce616dc81c07a1a7cf88668b..2d6929c2bd9270108195876ce42d8fe03a3fe304 100644 (file)
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+    GNU General Public License for more details.                            */
 /* ------------------------------------------------------------------------- */
 
 
index cf99dbf21fd100a5002aac1a6d98ddb20ab847c9..113293d275f670aa6fe8a33cc24889fb9bceaceb 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 3f6ecbfb9a56bf641e27d42b8e108116a9f99c5b..f2b0ff011631c9e920e042a1ec79b0b98126eb5b 100644 (file)
  * WITHOUT 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.
  * The full GNU General Public License is included in this distribution
  * in the file called LICENSE.GPL.
  *
index b170bdffb5de3aa273d27b97b567b13b27cff278..88eda09e73c0b31509427a784c5219655a49c2fb 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 /*
index ee3a76c7ae9757a544da330c3e8ce776e6291d26..70b3c91585097cd5623953f1a2ed97e45fdad01b 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 0dffb0e62c3b876f5898594868bc7ad59fcd8d74..277a2288d4a86285c3335ba19fdabf01cd85aa74 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/module.h>
@@ -926,14 +922,12 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                if (stat & OMAP_I2C_STAT_NACK) {
                        err |= OMAP_I2C_STAT_NACK;
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
-                       break;
                }
 
                if (stat & OMAP_I2C_STAT_AL) {
                        dev_err(dev->dev, "Arbitration lost\n");
                        err |= OMAP_I2C_STAT_AL;
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
-                       break;
                }
 
                /*
@@ -958,11 +952,13 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
                        if (dev->fifo_size)
                                num_bytes = dev->buf_len;
 
-                       omap_i2c_receive_data(dev, num_bytes, true);
-
-                       if (dev->errata & I2C_OMAP_ERRATA_I207)
+                       if (dev->errata & I2C_OMAP_ERRATA_I207) {
                                i2c_omap_errata_i207(dev, stat);
+                               num_bytes = (omap_i2c_read_reg(dev,
+                                       OMAP_I2C_BUFSTAT_REG) >> 8) & 0x3F;
+                       }
 
+                       omap_i2c_receive_data(dev, num_bytes, true);
                        omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
                        continue;
                }
index 62f55fe624cb3be72228decd9f03631f85d2e483..d1f625f923c75451033891bcdd18c0aab6843f8f 100644 (file)
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ------------------------------------------------------------------------ */
 
 #include <linux/kernel.h>
index a27aae2d6757195039a69cd192dda8774081b194..a1fac5aa9bae9b47e10fc6b723c66ac2ff2067b9 100644 (file)
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ------------------------------------------------------------------------ */
 
 #include <linux/kernel.h>
index e572f3aac0f79863a98d7c9c134ab6b038c36eec..4e129453680515888b8ca31f22dba490efc94d5d 100644 (file)
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ------------------------------------------------------------------------ */
 
 #define PORT_DATA      0
index 7a9dce43e1156afad3c8e906fa4b92df59586ac6..df1dbc92a0244c4eb989e88826c9f24235f35c7a 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
 #include <linux/module.h>
index 323f061a316378dfb827ee71af2eb5b2f578ed31..e0eb4ca0102e613130702757b7add12dd99bd05a 100644 (file)
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/kernel.h>
index a6f54ba27e2a5ff62bb24fca2982f13a2aed0aa3..67cbec6796a0eee50d0047e16a9db757f27836a9 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 8564768fee32eb24d7bfd92aec29d362ffe6cbdc..177834e2d84101283ad0afd288e75703e5d4aa12 100644 (file)
  *  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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/kernel.h>
index 01e967763c2a70ed92e15eb4e134ab84f621d42c..60a53c169ed2b3c8d3803411a310b752d8e1631b 100644 (file)
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
 */
 
 #include <linux/module.h>
index e3b0337faeb7f0b9ac4fe44546974605e047b4a0..65244774bfa343d464d0ad28d7503e886767f21c 100644 (file)
  * but WITHOUT 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>
index 8b5e79cb4468a87f01d073db574313529d0c7af1..4855188747c94e3cf3536579c544d01bf6c09b44 100644 (file)
  * but WITHOUT 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>
index 0fe505d7abe9b65e93882862e98ba586b2e73407..2b6219d86b0f31372ecceea15a6a8e29966f8eae 100644 (file)
  * but WITHOUT 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>
index 964e5c6f84abcecf0e3d82d795613c216489c54d..15ac8395dcd3ccac120f49cef28d508d62f552ba 100644 (file)
  * but WITHOUT 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>
index ac9bc33acef493cf07a1ed9546fcb7b236604dfd..7d58a40faf2dc8713d6cad4662c7adadf6a0a8a6 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /* Note: we assume there can only be one SIS5595 with one SMBus interface */
index c6366733008d15cd145a15aa62a90e4832304d1c..1e6805b5cef23e810d5437a943f01793acb56466 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 8dc2fc5f74ffc523d335dbeec95432034b63b867..44b904426073f6228bb9b014705d7aa0f4136088 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index 10855a0b7e7fe181c6fbc2ecb7baddbc1ef99f80..4c7fc2d47014f214c2a316189d75fb8869c0ae1d 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #include <linux/delay.h>
index f4a1ed757612851033dac49292138e4aaa266142..59b1d233ca7b2443992dca9a5b139f2db1dfb7c5 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 #include <linux/kernel.h>
index 6841200b6e5042d7313b1f09f68e13d5d2c0ca09..0ee2646f3b006bb7710cf9474ce2ccae366e4ef3 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
index ade9223912d3069c9236fa4a0b6f03327f2b4593..cc65ea0b818fe5cbf6c1c1c17c79304ba085e0aa 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
  *
  * This code was implemented by Mocean Laboratories AB when porting linux
  * to the automotive development board Russellville. The copyright holder
index ff3f5747e43b99123b5a3db733f4ac4c1925b394..5153354b1a6b8d151fd2265981175facfecb2baf 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index f24cc64e2e8c6a1288f0cdc0f38c545723057477..90e32295930332ec9fa92fd9f9ab153ee9b6e840 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index 2f90ac6a7f794ad8e79577a2c5e59ed853bf413f..f43b4e11647a28338235b1fcba1070ab2a34f91b 100644 (file)
     This program is distributed in the hope that it will be useful,
     but WITHOUT 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.                                                      */
+    GNU General Public License for more details.                            */
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
@@ -670,6 +665,9 @@ static int i2c_device_remove(struct device *dev)
                status = driver->remove(client);
        }
 
+       if (dev->of_node)
+               irq_dispose_mapping(client->irq);
+
        dev_pm_domain_detach(&client->dev, true);
        return status;
 }
index 18a8fd21d2c226741445fdc5bf12ed306e10ff7e..17700bfddcf58fc00f036de804dddeb22ed458f0 100644 (file)
  * but WITHOUT 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/rwsem.h>
index 80b47e8ce030cef7ff6f9ab9f058b15e63f7329e..71c7a3975b6287927c4bb666f433cf2787e20a54 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-    MA 02110-1301 USA.
 */
 
 /* Note that this is a complete rewrite of Simon Vogl's i2c-dev module.
index fc99f0d6b4a5b0d1f11d886e5bdb5abf23073b0f..9ebf9cb4ad7a90579e879a5b586bdf3e0c75c4cb 100644 (file)
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA.
  */
 
 #include <linux/kernel.h>
index d241aa295d96907d942c60290cfd89f54880330e..af2a94e1140ba064b038e4beb4e9c9a1dee1e0cd 100644 (file)
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 #define DEBUG 1
index 22c096ce39ad765c6a50d26ff80e77158fe3bbf6..513bd6d14293d80e5ce502080a092b5f970fe840 100644 (file)
@@ -44,6 +44,9 @@
 
 #define BMC150_ACCEL_REG_INT_STATUS_2          0x0B
 #define BMC150_ACCEL_ANY_MOTION_MASK           0x07
+#define BMC150_ACCEL_ANY_MOTION_BIT_X          BIT(0)
+#define BMC150_ACCEL_ANY_MOTION_BIT_Y          BIT(1)
+#define BMC150_ACCEL_ANY_MOTION_BIT_Z          BIT(2)
 #define BMC150_ACCEL_ANY_MOTION_BIT_SIGN       BIT(3)
 
 #define BMC150_ACCEL_REG_PMU_LPW               0x11
@@ -92,9 +95,9 @@
 #define BMC150_ACCEL_SLOPE_THRES_MASK          0xFF
 
 /* Slope duration in terms of number of samples */
-#define BMC150_ACCEL_DEF_SLOPE_DURATION        2
+#define BMC150_ACCEL_DEF_SLOPE_DURATION                1
 /* in terms of multiples of g's/LSB, based on range */
-#define BMC150_ACCEL_DEF_SLOPE_THRESHOLD       5
+#define BMC150_ACCEL_DEF_SLOPE_THRESHOLD       1
 
 #define BMC150_ACCEL_REG_XOUT_L                0x02
 
@@ -536,6 +539,9 @@ static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "Failed: bmc150_accel_set_power_state for %d\n", on);
+               if (on)
+                       pm_runtime_put_noidle(&data->client->dev);
+
                return ret;
        }
 
@@ -811,6 +817,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
 
        ret =  bmc150_accel_setup_any_motion_interrupt(data, state);
        if (ret < 0) {
+               bmc150_accel_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -846,7 +853,7 @@ static const struct attribute_group bmc150_accel_attrs_group = {
 
 static const struct iio_event_spec bmc150_accel_event = {
                .type = IIO_EV_TYPE_ROC,
-               .dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING,
+               .dir = IIO_EV_DIR_EITHER,
                .mask_separate = BIT(IIO_EV_INFO_VALUE) |
                                 BIT(IIO_EV_INFO_ENABLE) |
                                 BIT(IIO_EV_INFO_PERIOD)
@@ -1054,6 +1061,7 @@ static int bmc150_accel_data_rdy_trigger_set_state(struct iio_trigger *trig,
        else
                ret = bmc150_accel_setup_new_data_interrupt(data, state);
        if (ret < 0) {
+               bmc150_accel_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -1092,12 +1100,26 @@ static irqreturn_t bmc150_accel_event_handler(int irq, void *private)
        else
                dir = IIO_EV_DIR_RISING;
 
-       if (ret & BMC150_ACCEL_ANY_MOTION_MASK)
+       if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
+                                                       0,
+                                                       IIO_MOD_X,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y)
                iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
                                                        0,
-                                                       IIO_MOD_X_OR_Y_OR_Z,
+                                                       IIO_MOD_Y,
                                                        IIO_EV_TYPE_ROC,
-                                                       IIO_EV_DIR_EITHER),
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
+                                                       0,
+                                                       IIO_MOD_Z,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
                                                        data->timestamp);
 ack_intr_status:
        if (!data->dready_trigger_on)
@@ -1354,10 +1376,14 @@ static int bmc150_accel_runtime_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct bmc150_accel_data *data = iio_priv(indio_dev);
+       int ret;
 
        dev_dbg(&data->client->dev,  __func__);
+       ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
+       if (ret < 0)
+               return -EAGAIN;
 
-       return bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
+       return 0;
 }
 
 static int bmc150_accel_runtime_resume(struct device *dev)
index 98909a9e284e408756d3b21ed848d0d32b077bfc..320aa72c0349ecabeae7ea4a0bdb59d2c84cd63d 100644 (file)
@@ -269,6 +269,8 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
                return ret;
        }
 
+       ret &= ~(KXCJK1013_REG_CTRL1_BIT_GSEL0 |
+                KXCJK1013_REG_CTRL1_BIT_GSEL1);
        ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3);
        ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4);
 
@@ -894,7 +896,7 @@ static const struct attribute_group kxcjk1013_attrs_group = {
 
 static const struct iio_event_spec kxcjk1013_event = {
                .type = IIO_EV_TYPE_THRESH,
-               .dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING,
+               .dir = IIO_EV_DIR_EITHER,
                .mask_separate = BIT(IIO_EV_INFO_VALUE) |
                                 BIT(IIO_EV_INFO_ENABLE) |
                                 BIT(IIO_EV_INFO_PERIOD)
index 88bdc8f612e2ccf299550fa8367fb2ad251b29b1..bc4e787096e84c41ec04d3343a0a087f5620935f 100644 (file)
@@ -127,6 +127,14 @@ config AT91_ADC
        help
          Say yes here to build support for Atmel AT91 ADC.
 
+config AXP288_ADC
+       tristate "X-Powers AXP288 ADC driver"
+       depends on MFD_AXP20X
+       help
+         Say yes here to have support for X-Powers power management IC (PMIC) ADC
+         device. Depending on platform configuration, this general purpose ADC can
+         be used for sampling sensors such as thermal resistors.
+
 config EXYNOS_ADC
        tristate "Exynos ADC driver support"
        depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
index cb88a6a23b8fde707a9bd941b689132ddd4a4f1c..f30093f5b67a406cd17512b048d2e37e8e44c6e7 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AD799X) += ad799x.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
+obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_MAX1027) += max1027.o
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
new file mode 100644 (file)
index 0000000..08bcfb0
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * axp288_adc.c - X-Powers AXP288 PMIC ADC Driver
+ *
+ * Copyright (C) 2014 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 program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/kernel.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/platform_device.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+
+#define AXP288_ADC_EN_MASK             0xF1
+#define AXP288_ADC_TS_PIN_GPADC                0xF2
+#define AXP288_ADC_TS_PIN_ON           0xF3
+
+enum axp288_adc_id {
+       AXP288_ADC_TS,
+       AXP288_ADC_PMIC,
+       AXP288_ADC_GP,
+       AXP288_ADC_BATT_CHRG_I,
+       AXP288_ADC_BATT_DISCHRG_I,
+       AXP288_ADC_BATT_V,
+       AXP288_ADC_NR_CHAN,
+};
+
+struct axp288_adc_info {
+       int irq;
+       struct regmap *regmap;
+};
+
+static const struct iio_chan_spec const axp288_adc_channels[] = {
+       {
+               .indexed = 1,
+               .type = IIO_TEMP,
+               .channel = 0,
+               .address = AXP288_TS_ADC_H,
+               .datasheet_name = "TS_PIN",
+       }, {
+               .indexed = 1,
+               .type = IIO_TEMP,
+               .channel = 1,
+               .address = AXP288_PMIC_ADC_H,
+               .datasheet_name = "PMIC_TEMP",
+       }, {
+               .indexed = 1,
+               .type = IIO_TEMP,
+               .channel = 2,
+               .address = AXP288_GP_ADC_H,
+               .datasheet_name = "GPADC",
+       }, {
+               .indexed = 1,
+               .type = IIO_CURRENT,
+               .channel = 3,
+               .address = AXP20X_BATT_CHRG_I_H,
+               .datasheet_name = "BATT_CHG_I",
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+       }, {
+               .indexed = 1,
+               .type = IIO_CURRENT,
+               .channel = 4,
+               .address = AXP20X_BATT_DISCHRG_I_H,
+               .datasheet_name = "BATT_DISCHRG_I",
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+       }, {
+               .indexed = 1,
+               .type = IIO_VOLTAGE,
+               .channel = 5,
+               .address = AXP20X_BATT_V_H,
+               .datasheet_name = "BATT_V",
+               .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+       },
+};
+
+#define AXP288_ADC_MAP(_adc_channel_label, _consumer_dev_name, \
+               _consumer_channel)                              \
+       {                                                       \
+               .adc_channel_label = _adc_channel_label,        \
+               .consumer_dev_name = _consumer_dev_name,        \
+               .consumer_channel = _consumer_channel,          \
+       }
+
+/* for consumer drivers */
+static struct iio_map axp288_adc_default_maps[] = {
+       AXP288_ADC_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
+       AXP288_ADC_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
+       AXP288_ADC_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
+       AXP288_ADC_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"),
+       AXP288_ADC_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"),
+       AXP288_ADC_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"),
+       {},
+};
+
+static int axp288_adc_read_channel(int *val, unsigned long address,
+                               struct regmap *regmap)
+{
+       u8 buf[2];
+
+       if (regmap_bulk_read(regmap, address, buf, 2))
+               return -EIO;
+       *val = (buf[0] << 4) + ((buf[1] >> 4) & 0x0F);
+
+       return IIO_VAL_INT;
+}
+
+static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
+                               unsigned long address)
+{
+       /* channels other than GPADC do not need to switch TS pin */
+       if (address != AXP288_GP_ADC_H)
+               return 0;
+
+       return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
+}
+
+static int axp288_adc_read_raw(struct iio_dev *indio_dev,
+                       struct iio_chan_spec const *chan,
+                       int *val, int *val2, long mask)
+{
+       int ret;
+       struct axp288_adc_info *info = iio_priv(indio_dev);
+
+       mutex_lock(&indio_dev->mlock);
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
+                                       chan->address)) {
+                       dev_err(&indio_dev->dev, "GPADC mode\n");
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = axp288_adc_read_channel(val, chan->address, info->regmap);
+               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
+                                               chan->address))
+                       dev_err(&indio_dev->dev, "TS pin restore\n");
+               break;
+       case IIO_CHAN_INFO_PROCESSED:
+               ret = axp288_adc_read_channel(val, chan->address, info->regmap);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       mutex_unlock(&indio_dev->mlock);
+
+       return ret;
+}
+
+static int axp288_adc_set_state(struct regmap *regmap)
+{
+       /* ADC should be always enabled for internal FG to function */
+       if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
+               return -EIO;
+
+       return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
+}
+
+static const struct iio_info axp288_adc_iio_info = {
+       .read_raw = &axp288_adc_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int axp288_adc_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct axp288_adc_info *info;
+       struct iio_dev *indio_dev;
+       struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+
+       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       info = iio_priv(indio_dev);
+       info->irq = platform_get_irq(pdev, 0);
+       if (info->irq < 0) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return info->irq;
+       }
+       platform_set_drvdata(pdev, indio_dev);
+       info->regmap = axp20x->regmap;
+       /*
+        * Set ADC to enabled state at all time, including system suspend.
+        * otherwise internal fuel gauge functionality may be affected.
+        */
+       ret = axp288_adc_set_state(axp20x->regmap);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to enable ADC device\n");
+               return ret;
+       }
+
+       indio_dev->dev.parent = &pdev->dev;
+       indio_dev->name = pdev->name;
+       indio_dev->channels = axp288_adc_channels;
+       indio_dev->num_channels = ARRAY_SIZE(axp288_adc_channels);
+       indio_dev->info = &axp288_adc_iio_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       ret = iio_map_array_register(indio_dev, axp288_adc_default_maps);
+       if (ret < 0)
+               return ret;
+
+       ret = iio_device_register(indio_dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "unable to register iio device\n");
+               goto err_array_unregister;
+       }
+       return 0;
+
+err_array_unregister:
+       iio_map_array_unregister(indio_dev);
+
+       return ret;
+}
+
+static int axp288_adc_remove(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+       iio_device_unregister(indio_dev);
+       iio_map_array_unregister(indio_dev);
+
+       return 0;
+}
+
+static struct platform_device_id axp288_adc_id_table[] = {
+       { .name = "axp288_adc" },
+       {},
+};
+
+static struct platform_driver axp288_adc_driver = {
+       .probe = axp288_adc_probe,
+       .remove = axp288_adc_remove,
+       .id_table = axp288_adc_id_table,
+       .driver = {
+               .name = "axp288_adc",
+       },
+};
+
+MODULE_DEVICE_TABLE(platform, axp288_adc_id_table);
+
+module_platform_driver(axp288_adc_driver);
+
+MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@linux.intel.com>");
+MODULE_DESCRIPTION("X-Powers AXP288 ADC Driver");
+MODULE_LICENSE("GPL");
index b58d6302521f4d651359715331e83a5a416583a0..d095efe1ba149caa57136ec1f27f1c6caac10cd8 100644 (file)
@@ -152,6 +152,7 @@ static void men_z188_remove(struct mcb_device *dev)
 
 static const struct mcb_device_id men_z188_ids[] = {
        { .device = 0xbc },
+       { }
 };
 MODULE_DEVICE_TABLE(mcb, men_z188_ids);
 
index 1665c8e4b62b245c4301a93143b1912ec140466d..e18bc67822563e8d4245396c60bebe5b717ed244 100644 (file)
@@ -71,7 +71,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
                                goto st_sensors_free_memory;
                        }
 
-                       for (i = 0; i < n * num_data_channels; i++) {
+                       for (i = 0; i < n * byte_for_channel; i++) {
                                if (i < n)
                                        buf[i] = rx_array[i];
                                else
index 1f967e0d688e47a084f29e2b484621016ada7c3c..d2fa526740ca188e00926f42b733af91d4dcd9df 100644 (file)
@@ -67,6 +67,9 @@
 #define BMG160_REG_INT_EN_0            0x15
 #define BMG160_DATA_ENABLE_INT         BIT(7)
 
+#define BMG160_REG_INT_EN_1            0x16
+#define BMG160_INT1_BIT_OD             BIT(1)
+
 #define BMG160_REG_XOUT_L              0x02
 #define BMG160_AXIS_TO_REG(axis)       (BMG160_REG_XOUT_L + (axis * 2))
 
@@ -82,6 +85,9 @@
 
 #define BMG160_REG_INT_STATUS_2        0x0B
 #define BMG160_ANY_MOTION_MASK         0x07
+#define BMG160_ANY_MOTION_BIT_X                BIT(0)
+#define BMG160_ANY_MOTION_BIT_Y                BIT(1)
+#define BMG160_ANY_MOTION_BIT_Z                BIT(2)
 
 #define BMG160_REG_TEMP                0x08
 #define BMG160_TEMP_CENTER_VAL         23
@@ -222,6 +228,19 @@ static int bmg160_chip_init(struct bmg160_data *data)
        data->slope_thres = ret;
 
        /* Set default interrupt mode */
+       ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_EN_1);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error reading reg_int_en_1\n");
+               return ret;
+       }
+       ret &= ~BMG160_INT1_BIT_OD;
+       ret = i2c_smbus_write_byte_data(data->client,
+                                       BMG160_REG_INT_EN_1, ret);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "Error writing reg_int_en_1\n");
+               return ret;
+       }
+
        ret = i2c_smbus_write_byte_data(data->client,
                                        BMG160_REG_INT_RST_LATCH,
                                        BMG160_INT_MODE_LATCH_INT |
@@ -250,6 +269,9 @@ static int bmg160_set_power_state(struct bmg160_data *data, bool on)
        if (ret < 0) {
                dev_err(&data->client->dev,
                        "Failed: bmg160_set_power_state for %d\n", on);
+               if (on)
+                       pm_runtime_put_noidle(&data->client->dev);
+
                return ret;
        }
 #endif
@@ -705,6 +727,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
 
        ret =  bmg160_setup_any_motion_interrupt(data, state);
        if (ret < 0) {
+               bmg160_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -743,7 +766,7 @@ static const struct attribute_group bmg160_attrs_group = {
 
 static const struct iio_event_spec bmg160_event = {
                .type = IIO_EV_TYPE_ROC,
-               .dir = IIO_EV_DIR_RISING | IIO_EV_DIR_FALLING,
+               .dir = IIO_EV_DIR_EITHER,
                .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
                                       BIT(IIO_EV_INFO_ENABLE)
 };
@@ -871,6 +894,7 @@ static int bmg160_data_rdy_trigger_set_state(struct iio_trigger *trig,
        else
                ret = bmg160_setup_new_data_interrupt(data, state);
        if (ret < 0) {
+               bmg160_set_power_state(data, false);
                mutex_unlock(&data->mutex);
                return ret;
        }
@@ -908,10 +932,24 @@ static irqreturn_t bmg160_event_handler(int irq, void *private)
        else
                dir = IIO_EV_DIR_FALLING;
 
-       if (ret & BMG160_ANY_MOTION_MASK)
+       if (ret & BMG160_ANY_MOTION_BIT_X)
                iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
                                                        0,
-                                                       IIO_MOD_X_OR_Y_OR_Z,
+                                                       IIO_MOD_X,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMG160_ANY_MOTION_BIT_Y)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
+                                                       0,
+                                                       IIO_MOD_Y,
+                                                       IIO_EV_TYPE_ROC,
+                                                       dir),
+                                                       data->timestamp);
+       if (ret & BMG160_ANY_MOTION_BIT_Z)
+               iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
+                                                       0,
+                                                       IIO_MOD_Z,
                                                        IIO_EV_TYPE_ROC,
                                                        dir),
                                                        data->timestamp);
@@ -1169,8 +1207,15 @@ static int bmg160_runtime_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct bmg160_data *data = iio_priv(indio_dev);
+       int ret;
+
+       ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "set mode failed\n");
+               return -EAGAIN;
+       }
 
-       return bmg160_set_mode(data, BMG160_MODE_SUSPEND);
+       return 0;
 }
 
 static int bmg160_runtime_resume(struct device *dev)
index a15006efa1372e9c466c090a7b2bf409749da3e7..0763b86325738701175fef40030d33a2485d47f8 100644 (file)
@@ -230,9 +230,12 @@ static int tsl4531_resume(struct device *dev)
        return i2c_smbus_write_byte_data(to_i2c_client(dev), TSL4531_CONTROL,
                TSL4531_MODE_NORMAL);
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, tsl4531_resume);
+#define TSL4531_PM_OPS (&tsl4531_pm_ops)
+#else
+#define TSL4531_PM_OPS NULL
+#endif
 
 static const struct i2c_device_id tsl4531_id[] = {
        { "tsl4531", 0 },
@@ -243,7 +246,7 @@ MODULE_DEVICE_TABLE(i2c, tsl4531_id);
 static struct i2c_driver tsl4531_driver = {
        .driver = {
                .name   = TSL4531_DRV_NAME,
-               .pm     = &tsl4531_pm_ops,
+               .pm     = TSL4531_PM_OPS,
                .owner  = THIS_MODULE,
        },
        .probe  = tsl4531_probe,
index 5e780ef206f3c48774cb3f2d3a587ba0c6be1571..8349cc0fdf66b2c984f2592101a7fcd1613c4ce4 100644 (file)
@@ -330,7 +330,7 @@ static int as3935_probe(struct spi_device *spi)
                return -EINVAL;
        }
 
-       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(st));
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
        if (!indio_dev)
                return -ENOMEM;
 
index bda5994ceb68c910097c712f5d44306840eb8727..8b72cf392b34454abbeca0c5a1c8e17aca39ba13 100644 (file)
@@ -1173,18 +1173,24 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
                err = __mlx4_ib_create_flow(qp, flow_attr, domain, type[i],
                                            &mflow->reg_id[i]);
                if (err)
-                       goto err_free;
+                       goto err_create_flow;
                i++;
        }
 
        if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) {
                err = mlx4_ib_tunnel_steer_add(qp, flow_attr, &mflow->reg_id[i]);
                if (err)
-                       goto err_free;
+                       goto err_create_flow;
+               i++;
        }
 
        return &mflow->ibflow;
 
+err_create_flow:
+       while (i) {
+               (void)__mlx4_ib_destroy_flow(to_mdev(qp->device)->dev, mflow->reg_id[i]);
+               i--;
+       }
 err_free:
        kfree(mflow);
        return ERR_PTR(err);
index f42ab14105ac61f9b29e75ae2178b7aa199df6d1..20ca6a619476f065af6dbef57905897f717faf54 100644 (file)
@@ -911,7 +911,7 @@ static struct scsi_host_template iscsi_iser_sht = {
        .module                 = THIS_MODULE,
        .name                   = "iSCSI Initiator over iSER",
        .queuecommand           = iscsi_queuecommand,
-       .change_queue_depth     = iscsi_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
        .sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
        .max_sectors            = 1024,
        .cmd_per_lun            = ISER_DEF_CMD_PER_LUN,
@@ -922,6 +922,7 @@ static struct scsi_host_template iscsi_iser_sht = {
        .use_clustering         = DISABLE_CLUSTERING,
        .proc_name              = "iscsi_iser",
        .this_id                = -1,
+       .track_queue_depth      = 1,
 };
 
 static struct iscsi_transport iscsi_iser_transport = {
index 0bea5776bcbcc945166062d24dd70aedc9e9e06c..10641b7816f49e493dd2e1f091d0921d910c2475 100644 (file)
@@ -115,9 +115,12 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id,
        attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS;
        /*
         * FIXME: Use devattr.max_sge - 2 for max_send_sge as
-        * work-around for RDMA_READ..
+        * work-around for RDMA_READs with ConnectX-2.
+        *
+        * Also, still make sure to have at least two SGEs for
+        * outgoing control PDU responses.
         */
-       attr.cap.max_send_sge = device->dev_attr.max_sge - 2;
+       attr.cap.max_send_sge = max(2, device->dev_attr.max_sge - 2);
        isert_conn->max_sge = attr.cap.max_send_sge;
 
        attr.cap.max_recv_sge = 1;
@@ -225,12 +228,16 @@ isert_create_device_ib_res(struct isert_device *device)
        struct isert_cq_desc *cq_desc;
        struct ib_device_attr *dev_attr;
        int ret = 0, i, j;
+       int max_rx_cqe, max_tx_cqe;
 
        dev_attr = &device->dev_attr;
        ret = isert_query_device(ib_dev, dev_attr);
        if (ret)
                return ret;
 
+       max_rx_cqe = min(ISER_MAX_RX_CQ_LEN, dev_attr->max_cqe);
+       max_tx_cqe = min(ISER_MAX_TX_CQ_LEN, dev_attr->max_cqe);
+
        /* asign function handlers */
        if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS &&
            dev_attr->device_cap_flags & IB_DEVICE_SIGNATURE_HANDOVER) {
@@ -272,7 +279,7 @@ isert_create_device_ib_res(struct isert_device *device)
                                                isert_cq_rx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
-                                               ISER_MAX_RX_CQ_LEN, i);
+                                               max_rx_cqe, i);
                if (IS_ERR(device->dev_rx_cq[i])) {
                        ret = PTR_ERR(device->dev_rx_cq[i]);
                        device->dev_rx_cq[i] = NULL;
@@ -284,7 +291,7 @@ isert_create_device_ib_res(struct isert_device *device)
                                                isert_cq_tx_callback,
                                                isert_cq_event_callback,
                                                (void *)&cq_desc[i],
-                                               ISER_MAX_TX_CQ_LEN, i);
+                                               max_tx_cqe, i);
                if (IS_ERR(device->dev_tx_cq[i])) {
                        ret = PTR_ERR(device->dev_tx_cq[i]);
                        device->dev_tx_cq[i] = NULL;
@@ -803,14 +810,25 @@ wake_up:
        complete(&isert_conn->conn_wait);
 }
 
-static void
+static int
 isert_disconnected_handler(struct rdma_cm_id *cma_id, bool disconnect)
 {
-       struct isert_conn *isert_conn = (struct isert_conn *)cma_id->context;
+       struct isert_conn *isert_conn;
+
+       if (!cma_id->qp) {
+               struct isert_np *isert_np = cma_id->context;
+
+               isert_np->np_cm_id = NULL;
+               return -1;
+       }
+
+       isert_conn = (struct isert_conn *)cma_id->context;
 
        isert_conn->disconnect = disconnect;
        INIT_WORK(&isert_conn->conn_logout_work, isert_disconnect_work);
        schedule_work(&isert_conn->conn_logout_work);
+
+       return 0;
 }
 
 static int
@@ -825,6 +843,9 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        switch (event->event) {
        case RDMA_CM_EVENT_CONNECT_REQUEST:
                ret = isert_connect_request(cma_id, event);
+               if (ret)
+                       pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n",
+                               event->event, ret);
                break;
        case RDMA_CM_EVENT_ESTABLISHED:
                isert_connected_handler(cma_id);
@@ -834,7 +855,7 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        case RDMA_CM_EVENT_DEVICE_REMOVAL: /* FALLTHRU */
                disconnect = true;
        case RDMA_CM_EVENT_TIMEWAIT_EXIT:  /* FALLTHRU */
-               isert_disconnected_handler(cma_id, disconnect);
+               ret = isert_disconnected_handler(cma_id, disconnect);
                break;
        case RDMA_CM_EVENT_CONNECT_ERROR:
        default:
@@ -842,12 +863,6 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
                break;
        }
 
-       if (ret != 0) {
-               pr_err("isert_cma_handler failed RDMA_CM_EVENT: 0x%08x %d\n",
-                      event->event, ret);
-               dump_stack();
-       }
-
        return ret;
 }
 
@@ -2185,7 +2200,7 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                isert_cmd->tx_desc.num_sge = 2;
        }
 
-       isert_init_send_wr(isert_conn, isert_cmd, send_wr, true);
+       isert_init_send_wr(isert_conn, isert_cmd, send_wr, false);
 
        pr_debug("Posting SCSI Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n");
 
@@ -2871,7 +2886,7 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                                     &isert_cmd->tx_desc.iscsi_header);
                isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
                isert_init_send_wr(isert_conn, isert_cmd,
-                                  &isert_cmd->tx_desc.send_wr, true);
+                                  &isert_cmd->tx_desc.send_wr, false);
                isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr;
                wr->send_wr_num += 1;
        }
@@ -3140,7 +3155,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
 
 accept_wait:
        ret = down_interruptible(&isert_np->np_sem);
-       if (max_accept > 5)
+       if (ret || max_accept > 5)
                return -ENODEV;
 
        spin_lock_bh(&np->np_thread_lock);
@@ -3190,7 +3205,8 @@ isert_free_np(struct iscsi_np *np)
 {
        struct isert_np *isert_np = (struct isert_np *)np->np_context;
 
-       rdma_destroy_id(isert_np->np_cm_id);
+       if (isert_np->np_cm_id)
+               rdma_destroy_id(isert_np->np_cm_id);
 
        np->np_context = NULL;
        kfree(isert_np);
index 62d2a18e1b419225b312326690ec624563f5aa7b..5461924c9f10ef9311a8f11a5091170c4597281a 100644 (file)
@@ -123,10 +123,15 @@ MODULE_PARM_DESC(dev_loss_tmo,
                 " if fast_io_fail_tmo has not been set. \"off\" means that"
                 " this functionality is disabled.");
 
+static unsigned ch_count;
+module_param(ch_count, uint, 0444);
+MODULE_PARM_DESC(ch_count,
+                "Number of RDMA channels to use for communication with an SRP target. Using more than one channel improves performance if the HCA supports multiple completion vectors. The default value is the minimum of four times the number of online CPU sockets and the number of completion vectors supported by the HCA.");
+
 static void srp_add_one(struct ib_device *device);
 static void srp_remove_one(struct ib_device *device);
-static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
-static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
+static void srp_recv_completion(struct ib_cq *cq, void *ch_ptr);
+static void srp_send_completion(struct ib_cq *cq, void *ch_ptr);
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
 
 static struct scsi_transport_template *ib_srp_transport_template;
@@ -262,7 +267,7 @@ static int srp_init_qp(struct srp_target_port *target,
 
        ret = ib_find_pkey(target->srp_host->srp_dev->dev,
                           target->srp_host->port,
-                          be16_to_cpu(target->path.pkey),
+                          be16_to_cpu(target->pkey),
                           &attr->pkey_index);
        if (ret)
                goto out;
@@ -283,18 +288,23 @@ out:
        return ret;
 }
 
-static int srp_new_cm_id(struct srp_target_port *target)
+static int srp_new_cm_id(struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        struct ib_cm_id *new_cm_id;
 
        new_cm_id = ib_create_cm_id(target->srp_host->srp_dev->dev,
-                                   srp_cm_handler, target);
+                                   srp_cm_handler, ch);
        if (IS_ERR(new_cm_id))
                return PTR_ERR(new_cm_id);
 
-       if (target->cm_id)
-               ib_destroy_cm_id(target->cm_id);
-       target->cm_id = new_cm_id;
+       if (ch->cm_id)
+               ib_destroy_cm_id(ch->cm_id);
+       ch->cm_id = new_cm_id;
+       ch->path.sgid = target->sgid;
+       ch->path.dgid = target->orig_dgid;
+       ch->path.pkey = target->pkey;
+       ch->path.service_id = target->service_id;
 
        return 0;
 }
@@ -443,8 +453,44 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct srp_target_port *target)
                                  dev->max_pages_per_mr);
 }
 
-static int srp_create_target_ib(struct srp_target_port *target)
+/**
+ * srp_destroy_qp() - destroy an RDMA queue pair
+ * @ch: SRP RDMA channel.
+ *
+ * Change a queue pair into the error state and wait until all receive
+ * completions have been processed before destroying it. This avoids that
+ * the receive completion handler can access the queue pair while it is
+ * being destroyed.
+ */
+static void srp_destroy_qp(struct srp_rdma_ch *ch)
+{
+       struct srp_target_port *target = ch->target;
+       static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
+       static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID };
+       struct ib_recv_wr *bad_wr;
+       int ret;
+
+       /* Destroying a QP and reusing ch->done is only safe if not connected */
+       WARN_ON_ONCE(target->connected);
+
+       ret = ib_modify_qp(ch->qp, &attr, IB_QP_STATE);
+       WARN_ONCE(ret, "ib_cm_init_qp_attr() returned %d\n", ret);
+       if (ret)
+               goto out;
+
+       init_completion(&ch->done);
+       ret = ib_post_recv(ch->qp, &wr, &bad_wr);
+       WARN_ONCE(ret, "ib_post_recv() returned %d\n", ret);
+       if (ret == 0)
+               wait_for_completion(&ch->done);
+
+out:
+       ib_destroy_qp(ch->qp);
+}
+
+static int srp_create_ch_ib(struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_device *dev = target->srp_host->srp_dev;
        struct ib_qp_init_attr *init_attr;
        struct ib_cq *recv_cq, *send_cq;
@@ -458,15 +504,16 @@ static int srp_create_target_ib(struct srp_target_port *target)
        if (!init_attr)
                return -ENOMEM;
 
-       recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, target,
-                              target->queue_size, target->comp_vector);
+       /* + 1 for SRP_LAST_WR_ID */
+       recv_cq = ib_create_cq(dev->dev, srp_recv_completion, NULL, ch,
+                              target->queue_size + 1, ch->comp_vector);
        if (IS_ERR(recv_cq)) {
                ret = PTR_ERR(recv_cq);
                goto err;
        }
 
-       send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, target,
-                              m * target->queue_size, target->comp_vector);
+       send_cq = ib_create_cq(dev->dev, srp_send_completion, NULL, ch,
+                              m * target->queue_size, ch->comp_vector);
        if (IS_ERR(send_cq)) {
                ret = PTR_ERR(send_cq);
                goto err_recv_cq;
@@ -476,7 +523,7 @@ static int srp_create_target_ib(struct srp_target_port *target)
 
        init_attr->event_handler       = srp_qp_event;
        init_attr->cap.max_send_wr     = m * target->queue_size;
-       init_attr->cap.max_recv_wr     = target->queue_size;
+       init_attr->cap.max_recv_wr     = target->queue_size + 1;
        init_attr->cap.max_recv_sge    = 1;
        init_attr->cap.max_send_sge    = 1;
        init_attr->sq_sig_type         = IB_SIGNAL_REQ_WR;
@@ -502,9 +549,9 @@ static int srp_create_target_ib(struct srp_target_port *target)
                                     "FR pool allocation failed (%d)\n", ret);
                        goto err_qp;
                }
-               if (target->fr_pool)
-                       srp_destroy_fr_pool(target->fr_pool);
-               target->fr_pool = fr_pool;
+               if (ch->fr_pool)
+                       srp_destroy_fr_pool(ch->fr_pool);
+               ch->fr_pool = fr_pool;
        } else if (!dev->use_fast_reg && dev->has_fmr) {
                fmr_pool = srp_alloc_fmr_pool(target);
                if (IS_ERR(fmr_pool)) {
@@ -513,21 +560,21 @@ static int srp_create_target_ib(struct srp_target_port *target)
                                     "FMR pool allocation failed (%d)\n", ret);
                        goto err_qp;
                }
-               if (target->fmr_pool)
-                       ib_destroy_fmr_pool(target->fmr_pool);
-               target->fmr_pool = fmr_pool;
+               if (ch->fmr_pool)
+                       ib_destroy_fmr_pool(ch->fmr_pool);
+               ch->fmr_pool = fmr_pool;
        }
 
-       if (target->qp)
-               ib_destroy_qp(target->qp);
-       if (target->recv_cq)
-               ib_destroy_cq(target->recv_cq);
-       if (target->send_cq)
-               ib_destroy_cq(target->send_cq);
+       if (ch->qp)
+               srp_destroy_qp(ch);
+       if (ch->recv_cq)
+               ib_destroy_cq(ch->recv_cq);
+       if (ch->send_cq)
+               ib_destroy_cq(ch->send_cq);
 
-       target->qp = qp;
-       target->recv_cq = recv_cq;
-       target->send_cq = send_cq;
+       ch->qp = qp;
+       ch->recv_cq = recv_cq;
+       ch->send_cq = send_cq;
 
        kfree(init_attr);
        return 0;
@@ -548,93 +595,117 @@ err:
 
 /*
  * Note: this function may be called without srp_alloc_iu_bufs() having been
- * invoked. Hence the target->[rt]x_ring checks.
+ * invoked. Hence the ch->[rt]x_ring checks.
  */
-static void srp_free_target_ib(struct srp_target_port *target)
+static void srp_free_ch_ib(struct srp_target_port *target,
+                          struct srp_rdma_ch *ch)
 {
        struct srp_device *dev = target->srp_host->srp_dev;
        int i;
 
+       if (!ch->target)
+               return;
+
+       if (ch->cm_id) {
+               ib_destroy_cm_id(ch->cm_id);
+               ch->cm_id = NULL;
+       }
+
+       /* If srp_new_cm_id() succeeded but srp_create_ch_ib() not, return. */
+       if (!ch->qp)
+               return;
+
        if (dev->use_fast_reg) {
-               if (target->fr_pool)
-                       srp_destroy_fr_pool(target->fr_pool);
+               if (ch->fr_pool)
+                       srp_destroy_fr_pool(ch->fr_pool);
        } else {
-               if (target->fmr_pool)
-                       ib_destroy_fmr_pool(target->fmr_pool);
+               if (ch->fmr_pool)
+                       ib_destroy_fmr_pool(ch->fmr_pool);
        }
-       ib_destroy_qp(target->qp);
-       ib_destroy_cq(target->send_cq);
-       ib_destroy_cq(target->recv_cq);
+       srp_destroy_qp(ch);
+       ib_destroy_cq(ch->send_cq);
+       ib_destroy_cq(ch->recv_cq);
+
+       /*
+        * Avoid that the SCSI error handler tries to use this channel after
+        * it has been freed. The SCSI error handler can namely continue
+        * trying to perform recovery actions after scsi_remove_host()
+        * returned.
+        */
+       ch->target = NULL;
 
-       target->qp = NULL;
-       target->send_cq = target->recv_cq = NULL;
+       ch->qp = NULL;
+       ch->send_cq = ch->recv_cq = NULL;
 
-       if (target->rx_ring) {
+       if (ch->rx_ring) {
                for (i = 0; i < target->queue_size; ++i)
-                       srp_free_iu(target->srp_host, target->rx_ring[i]);
-               kfree(target->rx_ring);
-               target->rx_ring = NULL;
+                       srp_free_iu(target->srp_host, ch->rx_ring[i]);
+               kfree(ch->rx_ring);
+               ch->rx_ring = NULL;
        }
-       if (target->tx_ring) {
+       if (ch->tx_ring) {
                for (i = 0; i < target->queue_size; ++i)
-                       srp_free_iu(target->srp_host, target->tx_ring[i]);
-               kfree(target->tx_ring);
-               target->tx_ring = NULL;
+                       srp_free_iu(target->srp_host, ch->tx_ring[i]);
+               kfree(ch->tx_ring);
+               ch->tx_ring = NULL;
        }
 }
 
 static void srp_path_rec_completion(int status,
                                    struct ib_sa_path_rec *pathrec,
-                                   void *target_ptr)
+                                   void *ch_ptr)
 {
-       struct srp_target_port *target = target_ptr;
+       struct srp_rdma_ch *ch = ch_ptr;
+       struct srp_target_port *target = ch->target;
 
-       target->status = status;
+       ch->status = status;
        if (status)
                shost_printk(KERN_ERR, target->scsi_host,
                             PFX "Got failed path rec status %d\n", status);
        else
-               target->path = *pathrec;
-       complete(&target->done);
+               ch->path = *pathrec;
+       complete(&ch->done);
 }
 
-static int srp_lookup_path(struct srp_target_port *target)
+static int srp_lookup_path(struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        int ret;
 
-       target->path.numb_path = 1;
-
-       init_completion(&target->done);
-
-       target->path_query_id = ib_sa_path_rec_get(&srp_sa_client,
-                                                  target->srp_host->srp_dev->dev,
-                                                  target->srp_host->port,
-                                                  &target->path,
-                                                  IB_SA_PATH_REC_SERVICE_ID    |
-                                                  IB_SA_PATH_REC_DGID          |
-                                                  IB_SA_PATH_REC_SGID          |
-                                                  IB_SA_PATH_REC_NUMB_PATH     |
-                                                  IB_SA_PATH_REC_PKEY,
-                                                  SRP_PATH_REC_TIMEOUT_MS,
-                                                  GFP_KERNEL,
-                                                  srp_path_rec_completion,
-                                                  target, &target->path_query);
-       if (target->path_query_id < 0)
-               return target->path_query_id;
-
-       ret = wait_for_completion_interruptible(&target->done);
+       ch->path.numb_path = 1;
+
+       init_completion(&ch->done);
+
+       ch->path_query_id = ib_sa_path_rec_get(&srp_sa_client,
+                                              target->srp_host->srp_dev->dev,
+                                              target->srp_host->port,
+                                              &ch->path,
+                                              IB_SA_PATH_REC_SERVICE_ID |
+                                              IB_SA_PATH_REC_DGID       |
+                                              IB_SA_PATH_REC_SGID       |
+                                              IB_SA_PATH_REC_NUMB_PATH  |
+                                              IB_SA_PATH_REC_PKEY,
+                                              SRP_PATH_REC_TIMEOUT_MS,
+                                              GFP_KERNEL,
+                                              srp_path_rec_completion,
+                                              ch, &ch->path_query);
+       if (ch->path_query_id < 0)
+               return ch->path_query_id;
+
+       ret = wait_for_completion_interruptible(&ch->done);
        if (ret < 0)
                return ret;
 
-       if (target->status < 0)
+       if (ch->status < 0)
                shost_printk(KERN_WARNING, target->scsi_host,
                             PFX "Path record query failed\n");
 
-       return target->status;
+       return ch->status;
 }
 
-static int srp_send_req(struct srp_target_port *target)
+static int srp_send_req(struct srp_rdma_ch *ch, bool multich)
 {
+       struct srp_target_port *target = ch->target;
        struct {
                struct ib_cm_req_param param;
                struct srp_login_req   priv;
@@ -645,11 +716,11 @@ static int srp_send_req(struct srp_target_port *target)
        if (!req)
                return -ENOMEM;
 
-       req->param.primary_path               = &target->path;
+       req->param.primary_path               = &ch->path;
        req->param.alternate_path             = NULL;
        req->param.service_id                 = target->service_id;
-       req->param.qp_num                     = target->qp->qp_num;
-       req->param.qp_type                    = target->qp->qp_type;
+       req->param.qp_num                     = ch->qp->qp_num;
+       req->param.qp_type                    = ch->qp->qp_type;
        req->param.private_data               = &req->priv;
        req->param.private_data_len           = sizeof req->priv;
        req->param.flow_control               = 1;
@@ -673,6 +744,8 @@ static int srp_send_req(struct srp_target_port *target)
        req->priv.req_it_iu_len = cpu_to_be32(target->max_iu_len);
        req->priv.req_buf_fmt   = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
                                              SRP_BUF_FORMAT_INDIRECT);
+       req->priv.req_flags     = (multich ? SRP_MULTICHAN_MULTI :
+                                  SRP_MULTICHAN_SINGLE);
        /*
         * In the published SRP specification (draft rev. 16a), the
         * port identifier format is 8 bytes of ID extension followed
@@ -684,7 +757,7 @@ static int srp_send_req(struct srp_target_port *target)
         */
        if (target->io_class == SRP_REV10_IB_IO_CLASS) {
                memcpy(req->priv.initiator_port_id,
-                      &target->path.sgid.global.interface_id, 8);
+                      &target->sgid.global.interface_id, 8);
                memcpy(req->priv.initiator_port_id + 8,
                       &target->initiator_ext, 8);
                memcpy(req->priv.target_port_id,     &target->ioc_guid, 8);
@@ -693,7 +766,7 @@ static int srp_send_req(struct srp_target_port *target)
                memcpy(req->priv.initiator_port_id,
                       &target->initiator_ext, 8);
                memcpy(req->priv.initiator_port_id + 8,
-                      &target->path.sgid.global.interface_id, 8);
+                      &target->sgid.global.interface_id, 8);
                memcpy(req->priv.target_port_id,     &target->id_ext, 8);
                memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
        }
@@ -713,7 +786,7 @@ static int srp_send_req(struct srp_target_port *target)
                       &target->srp_host->srp_dev->dev->node_guid, 8);
        }
 
-       status = ib_send_cm_req(target->cm_id, &req->param);
+       status = ib_send_cm_req(ch->cm_id, &req->param);
 
        kfree(req);
 
@@ -754,28 +827,35 @@ static bool srp_change_conn_state(struct srp_target_port *target,
 
 static void srp_disconnect_target(struct srp_target_port *target)
 {
+       struct srp_rdma_ch *ch;
+       int i;
+
        if (srp_change_conn_state(target, false)) {
                /* XXX should send SRP_I_LOGOUT request */
 
-               if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
-                       shost_printk(KERN_DEBUG, target->scsi_host,
-                                    PFX "Sending CM DREQ failed\n");
+               for (i = 0; i < target->ch_count; i++) {
+                       ch = &target->ch[i];
+                       if (ch->cm_id && ib_send_cm_dreq(ch->cm_id, NULL, 0)) {
+                               shost_printk(KERN_DEBUG, target->scsi_host,
+                                            PFX "Sending CM DREQ failed\n");
+                       }
                }
        }
 }
 
-static void srp_free_req_data(struct srp_target_port *target)
+static void srp_free_req_data(struct srp_target_port *target,
+                             struct srp_rdma_ch *ch)
 {
        struct srp_device *dev = target->srp_host->srp_dev;
        struct ib_device *ibdev = dev->dev;
        struct srp_request *req;
        int i;
 
-       if (!target->req_ring)
+       if (!ch->target || !ch->req_ring)
                return;
 
        for (i = 0; i < target->req_ring_size; ++i) {
-               req = &target->req_ring[i];
+               req = &ch->req_ring[i];
                if (dev->use_fast_reg)
                        kfree(req->fr_list);
                else
@@ -789,12 +869,13 @@ static void srp_free_req_data(struct srp_target_port *target)
                kfree(req->indirect_desc);
        }
 
-       kfree(target->req_ring);
-       target->req_ring = NULL;
+       kfree(ch->req_ring);
+       ch->req_ring = NULL;
 }
 
-static int srp_alloc_req_data(struct srp_target_port *target)
+static int srp_alloc_req_data(struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_device *srp_dev = target->srp_host->srp_dev;
        struct ib_device *ibdev = srp_dev->dev;
        struct srp_request *req;
@@ -802,15 +883,13 @@ static int srp_alloc_req_data(struct srp_target_port *target)
        dma_addr_t dma_addr;
        int i, ret = -ENOMEM;
 
-       INIT_LIST_HEAD(&target->free_reqs);
-
-       target->req_ring = kzalloc(target->req_ring_size *
-                                  sizeof(*target->req_ring), GFP_KERNEL);
-       if (!target->req_ring)
+       ch->req_ring = kcalloc(target->req_ring_size, sizeof(*ch->req_ring),
+                              GFP_KERNEL);
+       if (!ch->req_ring)
                goto out;
 
        for (i = 0; i < target->req_ring_size; ++i) {
-               req = &target->req_ring[i];
+               req = &ch->req_ring[i];
                mr_list = kmalloc(target->cmd_sg_cnt * sizeof(void *),
                                  GFP_KERNEL);
                if (!mr_list)
@@ -834,8 +913,6 @@ static int srp_alloc_req_data(struct srp_target_port *target)
                        goto out;
 
                req->indirect_dma_addr = dma_addr;
-               req->index = i;
-               list_add_tail(&req->list, &target->free_reqs);
        }
        ret = 0;
 
@@ -860,6 +937,9 @@ static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
 
 static void srp_remove_target(struct srp_target_port *target)
 {
+       struct srp_rdma_ch *ch;
+       int i;
+
        WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
 
        srp_del_scsi_host_attr(target->scsi_host);
@@ -868,11 +948,18 @@ static void srp_remove_target(struct srp_target_port *target)
        scsi_remove_host(target->scsi_host);
        srp_stop_rport_timers(target->rport);
        srp_disconnect_target(target);
-       ib_destroy_cm_id(target->cm_id);
-       srp_free_target_ib(target);
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               srp_free_ch_ib(target, ch);
+       }
        cancel_work_sync(&target->tl_err_work);
        srp_rport_put(target->rport);
-       srp_free_req_data(target);
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               srp_free_req_data(target, ch);
+       }
+       kfree(target->ch);
+       target->ch = NULL;
 
        spin_lock(&target->srp_host->target_lock);
        list_del(&target->list);
@@ -898,25 +985,25 @@ static void srp_rport_delete(struct srp_rport *rport)
        srp_queue_remove_work(target);
 }
 
-static int srp_connect_target(struct srp_target_port *target)
+static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
 {
-       int retries = 3;
+       struct srp_target_port *target = ch->target;
        int ret;
 
-       WARN_ON_ONCE(target->connected);
+       WARN_ON_ONCE(!multich && target->connected);
 
        target->qp_in_error = false;
 
-       ret = srp_lookup_path(target);
+       ret = srp_lookup_path(ch);
        if (ret)
                return ret;
 
        while (1) {
-               init_completion(&target->done);
-               ret = srp_send_req(target);
+               init_completion(&ch->done);
+               ret = srp_send_req(ch, multich);
                if (ret)
                        return ret;
-               ret = wait_for_completion_interruptible(&target->done);
+               ret = wait_for_completion_interruptible(&ch->done);
                if (ret < 0)
                        return ret;
 
@@ -926,13 +1013,13 @@ static int srp_connect_target(struct srp_target_port *target)
                 * back, or SRP_DLID_REDIRECT if we get a lid/qp
                 * redirect REJ back.
                 */
-               switch (target->status) {
+               switch (ch->status) {
                case 0:
                        srp_change_conn_state(target, true);
                        return 0;
 
                case SRP_PORT_REDIRECT:
-                       ret = srp_lookup_path(target);
+                       ret = srp_lookup_path(ch);
                        if (ret)
                                return ret;
                        break;
@@ -941,27 +1028,18 @@ static int srp_connect_target(struct srp_target_port *target)
                        break;
 
                case SRP_STALE_CONN:
-                       /* Our current CM id was stale, and is now in timewait.
-                        * Try to reconnect with a new one.
-                        */
-                       if (!retries-- || srp_new_cm_id(target)) {
-                               shost_printk(KERN_ERR, target->scsi_host, PFX
-                                            "giving up on stale connection\n");
-                               target->status = -ECONNRESET;
-                               return target->status;
-                       }
-
                        shost_printk(KERN_ERR, target->scsi_host, PFX
-                                    "retrying stale connection\n");
-                       break;
+                                    "giving up on stale connection\n");
+                       ch->status = -ECONNRESET;
+                       return ch->status;
 
                default:
-                       return target->status;
+                       return ch->status;
                }
        }
 }
 
-static int srp_inv_rkey(struct srp_target_port *target, u32 rkey)
+static int srp_inv_rkey(struct srp_rdma_ch *ch, u32 rkey)
 {
        struct ib_send_wr *bad_wr;
        struct ib_send_wr wr = {
@@ -973,13 +1051,14 @@ static int srp_inv_rkey(struct srp_target_port *target, u32 rkey)
                .ex.invalidate_rkey = rkey,
        };
 
-       return ib_post_send(target->qp, &wr, &bad_wr);
+       return ib_post_send(ch->qp, &wr, &bad_wr);
 }
 
 static void srp_unmap_data(struct scsi_cmnd *scmnd,
-                          struct srp_target_port *target,
+                          struct srp_rdma_ch *ch,
                           struct srp_request *req)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_device *dev = target->srp_host->srp_dev;
        struct ib_device *ibdev = dev->dev;
        int i, res;
@@ -993,7 +1072,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
                struct srp_fr_desc **pfr;
 
                for (i = req->nmdesc, pfr = req->fr_list; i > 0; i--, pfr++) {
-                       res = srp_inv_rkey(target, (*pfr)->mr->rkey);
+                       res = srp_inv_rkey(ch, (*pfr)->mr->rkey);
                        if (res < 0) {
                                shost_printk(KERN_ERR, target->scsi_host, PFX
                                  "Queueing INV WR for rkey %#x failed (%d)\n",
@@ -1003,7 +1082,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
                        }
                }
                if (req->nmdesc)
-                       srp_fr_pool_put(target->fr_pool, req->fr_list,
+                       srp_fr_pool_put(ch->fr_pool, req->fr_list,
                                        req->nmdesc);
        } else {
                struct ib_pool_fmr **pfmr;
@@ -1018,7 +1097,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
 
 /**
  * srp_claim_req - Take ownership of the scmnd associated with a request.
- * @target: SRP target port.
+ * @ch: SRP RDMA channel.
  * @req: SRP request.
  * @sdev: If not NULL, only take ownership for this SCSI device.
  * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take
@@ -1027,14 +1106,14 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
  * Return value:
  * Either NULL or a pointer to the SCSI command the caller became owner of.
  */
-static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target,
+static struct scsi_cmnd *srp_claim_req(struct srp_rdma_ch *ch,
                                       struct srp_request *req,
                                       struct scsi_device *sdev,
                                       struct scsi_cmnd *scmnd)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&target->lock, flags);
+       spin_lock_irqsave(&ch->lock, flags);
        if (req->scmnd &&
            (!sdev || req->scmnd->device == sdev) &&
            (!scmnd || req->scmnd == scmnd)) {
@@ -1043,40 +1122,37 @@ static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target,
        } else {
                scmnd = NULL;
        }
-       spin_unlock_irqrestore(&target->lock, flags);
+       spin_unlock_irqrestore(&ch->lock, flags);
 
        return scmnd;
 }
 
 /**
  * srp_free_req() - Unmap data and add request to the free request list.
- * @target: SRP target port.
+ * @ch:     SRP RDMA channel.
  * @req:    Request to be freed.
  * @scmnd:  SCSI command associated with @req.
  * @req_lim_delta: Amount to be added to @target->req_lim.
  */
-static void srp_free_req(struct srp_target_port *target,
-                        struct srp_request *req, struct scsi_cmnd *scmnd,
-                        s32 req_lim_delta)
+static void srp_free_req(struct srp_rdma_ch *ch, struct srp_request *req,
+                        struct scsi_cmnd *scmnd, s32 req_lim_delta)
 {
        unsigned long flags;
 
-       srp_unmap_data(scmnd, target, req);
+       srp_unmap_data(scmnd, ch, req);
 
-       spin_lock_irqsave(&target->lock, flags);
-       target->req_lim += req_lim_delta;
-       list_add_tail(&req->list, &target->free_reqs);
-       spin_unlock_irqrestore(&target->lock, flags);
+       spin_lock_irqsave(&ch->lock, flags);
+       ch->req_lim += req_lim_delta;
+       spin_unlock_irqrestore(&ch->lock, flags);
 }
 
-static void srp_finish_req(struct srp_target_port *target,
-                          struct srp_request *req, struct scsi_device *sdev,
-                          int result)
+static void srp_finish_req(struct srp_rdma_ch *ch, struct srp_request *req,
+                          struct scsi_device *sdev, int result)
 {
-       struct scsi_cmnd *scmnd = srp_claim_req(target, req, sdev, NULL);
+       struct scsi_cmnd *scmnd = srp_claim_req(ch, req, sdev, NULL);
 
        if (scmnd) {
-               srp_free_req(target, req, scmnd, 0);
+               srp_free_req(ch, req, scmnd, 0);
                scmnd->result = result;
                scmnd->scsi_done(scmnd);
        }
@@ -1085,9 +1161,10 @@ static void srp_finish_req(struct srp_target_port *target,
 static void srp_terminate_io(struct srp_rport *rport)
 {
        struct srp_target_port *target = rport->lld_data;
+       struct srp_rdma_ch *ch;
        struct Scsi_Host *shost = target->scsi_host;
        struct scsi_device *sdev;
-       int i;
+       int i, j;
 
        /*
         * Invoking srp_terminate_io() while srp_queuecommand() is running
@@ -1096,9 +1173,15 @@ static void srp_terminate_io(struct srp_rport *rport)
        shost_for_each_device(sdev, shost)
                WARN_ON_ONCE(sdev->request_queue->request_fn_active);
 
-       for (i = 0; i < target->req_ring_size; ++i) {
-               struct srp_request *req = &target->req_ring[i];
-               srp_finish_req(target, req, NULL, DID_TRANSPORT_FAILFAST << 16);
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+
+               for (j = 0; j < target->req_ring_size; ++j) {
+                       struct srp_request *req = &ch->req_ring[j];
+
+                       srp_finish_req(ch, req, NULL,
+                                      DID_TRANSPORT_FAILFAST << 16);
+               }
        }
 }
 
@@ -1114,34 +1197,61 @@ static void srp_terminate_io(struct srp_rport *rport)
 static int srp_rport_reconnect(struct srp_rport *rport)
 {
        struct srp_target_port *target = rport->lld_data;
-       int i, ret;
+       struct srp_rdma_ch *ch;
+       int i, j, ret = 0;
+       bool multich = false;
 
        srp_disconnect_target(target);
+
+       if (target->state == SRP_TARGET_SCANNING)
+               return -ENODEV;
+
        /*
         * Now get a new local CM ID so that we avoid confusing the target in
         * case things are really fouled up. Doing so also ensures that all CM
         * callbacks will have finished before a new QP is allocated.
         */
-       ret = srp_new_cm_id(target);
-
-       for (i = 0; i < target->req_ring_size; ++i) {
-               struct srp_request *req = &target->req_ring[i];
-               srp_finish_req(target, req, NULL, DID_RESET << 16);
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               if (!ch->target)
+                       break;
+               ret += srp_new_cm_id(ch);
        }
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               if (!ch->target)
+                       break;
+               for (j = 0; j < target->req_ring_size; ++j) {
+                       struct srp_request *req = &ch->req_ring[j];
 
-       /*
-        * Whether or not creating a new CM ID succeeded, create a new
-        * QP. This guarantees that all callback functions for the old QP have
-        * finished before any send requests are posted on the new QP.
-        */
-       ret += srp_create_target_ib(target);
-
-       INIT_LIST_HEAD(&target->free_tx);
-       for (i = 0; i < target->queue_size; ++i)
-               list_add(&target->tx_ring[i]->list, &target->free_tx);
+                       srp_finish_req(ch, req, NULL, DID_RESET << 16);
+               }
+       }
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               if (!ch->target)
+                       break;
+               /*
+                * Whether or not creating a new CM ID succeeded, create a new
+                * QP. This guarantees that all completion callback function
+                * invocations have finished before request resetting starts.
+                */
+               ret += srp_create_ch_ib(ch);
 
-       if (ret == 0)
-               ret = srp_connect_target(target);
+               INIT_LIST_HEAD(&ch->free_tx);
+               for (j = 0; j < target->queue_size; ++j)
+                       list_add(&ch->tx_ring[j]->list, &ch->free_tx);
+       }
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               if (ret || !ch->target) {
+                       if (i > 1)
+                               ret = 0;
+                       break;
+               }
+               ret = srp_connect_ch(ch, multich);
+               multich = true;
+       }
 
        if (ret == 0)
                shost_printk(KERN_INFO, target->scsi_host,
@@ -1165,12 +1275,12 @@ static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr,
 }
 
 static int srp_map_finish_fmr(struct srp_map_state *state,
-                             struct srp_target_port *target)
+                             struct srp_rdma_ch *ch)
 {
        struct ib_pool_fmr *fmr;
        u64 io_addr = 0;
 
-       fmr = ib_fmr_pool_map_phys(target->fmr_pool, state->pages,
+       fmr = ib_fmr_pool_map_phys(ch->fmr_pool, state->pages,
                                   state->npages, io_addr);
        if (IS_ERR(fmr))
                return PTR_ERR(fmr);
@@ -1184,15 +1294,16 @@ static int srp_map_finish_fmr(struct srp_map_state *state,
 }
 
 static int srp_map_finish_fr(struct srp_map_state *state,
-                            struct srp_target_port *target)
+                            struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_device *dev = target->srp_host->srp_dev;
        struct ib_send_wr *bad_wr;
        struct ib_send_wr wr;
        struct srp_fr_desc *desc;
        u32 rkey;
 
-       desc = srp_fr_pool_get(target->fr_pool);
+       desc = srp_fr_pool_get(ch->fr_pool);
        if (!desc)
                return -ENOMEM;
 
@@ -1221,12 +1332,13 @@ static int srp_map_finish_fr(struct srp_map_state *state,
        srp_map_desc(state, state->base_dma_addr, state->dma_len,
                     desc->mr->rkey);
 
-       return ib_post_send(target->qp, &wr, &bad_wr);
+       return ib_post_send(ch->qp, &wr, &bad_wr);
 }
 
 static int srp_finish_mapping(struct srp_map_state *state,
-                             struct srp_target_port *target)
+                             struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        int ret = 0;
 
        if (state->npages == 0)
@@ -1237,8 +1349,8 @@ static int srp_finish_mapping(struct srp_map_state *state,
                             target->rkey);
        else
                ret = target->srp_host->srp_dev->use_fast_reg ?
-                       srp_map_finish_fr(state, target) :
-                       srp_map_finish_fmr(state, target);
+                       srp_map_finish_fr(state, ch) :
+                       srp_map_finish_fmr(state, ch);
 
        if (ret == 0) {
                state->npages = 0;
@@ -1258,10 +1370,11 @@ static void srp_map_update_start(struct srp_map_state *state,
 }
 
 static int srp_map_sg_entry(struct srp_map_state *state,
-                           struct srp_target_port *target,
+                           struct srp_rdma_ch *ch,
                            struct scatterlist *sg, int sg_index,
                            bool use_mr)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_device *dev = target->srp_host->srp_dev;
        struct ib_device *ibdev = dev->dev;
        dma_addr_t dma_addr = ib_sg_dma_address(ibdev, sg);
@@ -1290,7 +1403,7 @@ static int srp_map_sg_entry(struct srp_map_state *state,
         */
        if ((!dev->use_fast_reg && dma_addr & ~dev->mr_page_mask) ||
            dma_len > dev->mr_max_size) {
-               ret = srp_finish_mapping(state, target);
+               ret = srp_finish_mapping(state, ch);
                if (ret)
                        return ret;
 
@@ -1311,7 +1424,7 @@ static int srp_map_sg_entry(struct srp_map_state *state,
        while (dma_len) {
                unsigned offset = dma_addr & ~dev->mr_page_mask;
                if (state->npages == dev->max_pages_per_mr || offset != 0) {
-                       ret = srp_finish_mapping(state, target);
+                       ret = srp_finish_mapping(state, ch);
                        if (ret)
                                return ret;
 
@@ -1335,17 +1448,18 @@ static int srp_map_sg_entry(struct srp_map_state *state,
         */
        ret = 0;
        if (len != dev->mr_page_size) {
-               ret = srp_finish_mapping(state, target);
+               ret = srp_finish_mapping(state, ch);
                if (!ret)
                        srp_map_update_start(state, NULL, 0, 0);
        }
        return ret;
 }
 
-static int srp_map_sg(struct srp_map_state *state,
-                     struct srp_target_port *target, struct srp_request *req,
-                     struct scatterlist *scat, int count)
+static int srp_map_sg(struct srp_map_state *state, struct srp_rdma_ch *ch,
+                     struct srp_request *req, struct scatterlist *scat,
+                     int count)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_device *dev = target->srp_host->srp_dev;
        struct ib_device *ibdev = dev->dev;
        struct scatterlist *sg;
@@ -1356,14 +1470,14 @@ static int srp_map_sg(struct srp_map_state *state,
        state->pages    = req->map_page;
        if (dev->use_fast_reg) {
                state->next_fr = req->fr_list;
-               use_mr = !!target->fr_pool;
+               use_mr = !!ch->fr_pool;
        } else {
                state->next_fmr = req->fmr_list;
-               use_mr = !!target->fmr_pool;
+               use_mr = !!ch->fmr_pool;
        }
 
        for_each_sg(scat, sg, count, i) {
-               if (srp_map_sg_entry(state, target, sg, i, use_mr)) {
+               if (srp_map_sg_entry(state, ch, sg, i, use_mr)) {
                        /*
                         * Memory registration failed, so backtrack to the
                         * first unmapped entry and continue on without using
@@ -1385,7 +1499,7 @@ backtrack:
                }
        }
 
-       if (use_mr && srp_finish_mapping(state, target))
+       if (use_mr && srp_finish_mapping(state, ch))
                goto backtrack;
 
        req->nmdesc = state->nmdesc;
@@ -1393,9 +1507,10 @@ backtrack:
        return 0;
 }
 
-static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
                        struct srp_request *req)
 {
+       struct srp_target_port *target = ch->target;
        struct scatterlist *scat;
        struct srp_cmd *cmd = req->cmd->buf;
        int len, nents, count;
@@ -1457,7 +1572,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
                                   target->indirect_size, DMA_TO_DEVICE);
 
        memset(&state, 0, sizeof(state));
-       srp_map_sg(&state, target, req, scat, count);
+       srp_map_sg(&state, ch, req, scat, count);
 
        /* We've mapped the request, now pull as much of the indirect
         * descriptor table as we can into the command buffer. If this
@@ -1518,20 +1633,20 @@ map_complete:
 /*
  * Return an IU and possible credit to the free pool
  */
-static void srp_put_tx_iu(struct srp_target_port *target, struct srp_iu *iu,
+static void srp_put_tx_iu(struct srp_rdma_ch *ch, struct srp_iu *iu,
                          enum srp_iu_type iu_type)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&target->lock, flags);
-       list_add(&iu->list, &target->free_tx);
+       spin_lock_irqsave(&ch->lock, flags);
+       list_add(&iu->list, &ch->free_tx);
        if (iu_type != SRP_IU_RSP)
-               ++target->req_lim;
-       spin_unlock_irqrestore(&target->lock, flags);
+               ++ch->req_lim;
+       spin_unlock_irqrestore(&ch->lock, flags);
 }
 
 /*
- * Must be called with target->lock held to protect req_lim and free_tx.
+ * Must be called with ch->lock held to protect req_lim and free_tx.
  * If IU is not sent, it must be returned using srp_put_tx_iu().
  *
  * Note:
@@ -1543,35 +1658,36 @@ static void srp_put_tx_iu(struct srp_target_port *target, struct srp_iu *iu,
  * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
  *   one unanswered SRP request to an initiator.
  */
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
+static struct srp_iu *__srp_get_tx_iu(struct srp_rdma_ch *ch,
                                      enum srp_iu_type iu_type)
 {
+       struct srp_target_port *target = ch->target;
        s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
        struct srp_iu *iu;
 
-       srp_send_completion(target->send_cq, target);
+       srp_send_completion(ch->send_cq, ch);
 
-       if (list_empty(&target->free_tx))
+       if (list_empty(&ch->free_tx))
                return NULL;
 
        /* Initiator responses to target requests do not consume credits */
        if (iu_type != SRP_IU_RSP) {
-               if (target->req_lim <= rsv) {
+               if (ch->req_lim <= rsv) {
                        ++target->zero_req_lim;
                        return NULL;
                }
 
-               --target->req_lim;
+               --ch->req_lim;
        }
 
-       iu = list_first_entry(&target->free_tx, struct srp_iu, list);
+       iu = list_first_entry(&ch->free_tx, struct srp_iu, list);
        list_del(&iu->list);
        return iu;
 }
 
-static int srp_post_send(struct srp_target_port *target,
-                        struct srp_iu *iu, int len)
+static int srp_post_send(struct srp_rdma_ch *ch, struct srp_iu *iu, int len)
 {
+       struct srp_target_port *target = ch->target;
        struct ib_sge list;
        struct ib_send_wr wr, *bad_wr;
 
@@ -1586,11 +1702,12 @@ static int srp_post_send(struct srp_target_port *target,
        wr.opcode     = IB_WR_SEND;
        wr.send_flags = IB_SEND_SIGNALED;
 
-       return ib_post_send(target->qp, &wr, &bad_wr);
+       return ib_post_send(ch->qp, &wr, &bad_wr);
 }
 
-static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
+static int srp_post_recv(struct srp_rdma_ch *ch, struct srp_iu *iu)
 {
+       struct srp_target_port *target = ch->target;
        struct ib_recv_wr wr, *bad_wr;
        struct ib_sge list;
 
@@ -1603,35 +1720,39 @@ static int srp_post_recv(struct srp_target_port *target, struct srp_iu *iu)
        wr.sg_list  = &list;
        wr.num_sge  = 1;
 
-       return ib_post_recv(target->qp, &wr, &bad_wr);
+       return ib_post_recv(ch->qp, &wr, &bad_wr);
 }
 
-static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
+static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_request *req;
        struct scsi_cmnd *scmnd;
        unsigned long flags;
 
        if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) {
-               spin_lock_irqsave(&target->lock, flags);
-               target->req_lim += be32_to_cpu(rsp->req_lim_delta);
-               spin_unlock_irqrestore(&target->lock, flags);
+               spin_lock_irqsave(&ch->lock, flags);
+               ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
+               spin_unlock_irqrestore(&ch->lock, flags);
 
-               target->tsk_mgmt_status = -1;
+               ch->tsk_mgmt_status = -1;
                if (be32_to_cpu(rsp->resp_data_len) >= 4)
-                       target->tsk_mgmt_status = rsp->data[3];
-               complete(&target->tsk_mgmt_done);
+                       ch->tsk_mgmt_status = rsp->data[3];
+               complete(&ch->tsk_mgmt_done);
        } else {
-               req = &target->req_ring[rsp->tag];
-               scmnd = srp_claim_req(target, req, NULL, NULL);
+               scmnd = scsi_host_find_tag(target->scsi_host, rsp->tag);
+               if (scmnd) {
+                       req = (void *)scmnd->host_scribble;
+                       scmnd = srp_claim_req(ch, req, NULL, scmnd);
+               }
                if (!scmnd) {
                        shost_printk(KERN_ERR, target->scsi_host,
-                                    "Null scmnd for RSP w/tag %016llx\n",
-                                    (unsigned long long) rsp->tag);
+                                    "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n",
+                                    rsp->tag, ch - target->ch, ch->qp->qp_num);
 
-                       spin_lock_irqsave(&target->lock, flags);
-                       target->req_lim += be32_to_cpu(rsp->req_lim_delta);
-                       spin_unlock_irqrestore(&target->lock, flags);
+                       spin_lock_irqsave(&ch->lock, flags);
+                       ch->req_lim += be32_to_cpu(rsp->req_lim_delta);
+                       spin_unlock_irqrestore(&ch->lock, flags);
 
                        return;
                }
@@ -1653,7 +1774,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
                else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOOVER))
                        scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_out_res_cnt));
 
-               srp_free_req(target, req, scmnd,
+               srp_free_req(ch, req, scmnd,
                             be32_to_cpu(rsp->req_lim_delta));
 
                scmnd->host_scribble = NULL;
@@ -1661,18 +1782,19 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
        }
 }
 
-static int srp_response_common(struct srp_target_port *target, s32 req_delta,
+static int srp_response_common(struct srp_rdma_ch *ch, s32 req_delta,
                               void *rsp, int len)
 {
+       struct srp_target_port *target = ch->target;
        struct ib_device *dev = target->srp_host->srp_dev->dev;
        unsigned long flags;
        struct srp_iu *iu;
        int err;
 
-       spin_lock_irqsave(&target->lock, flags);
-       target->req_lim += req_delta;
-       iu = __srp_get_tx_iu(target, SRP_IU_RSP);
-       spin_unlock_irqrestore(&target->lock, flags);
+       spin_lock_irqsave(&ch->lock, flags);
+       ch->req_lim += req_delta;
+       iu = __srp_get_tx_iu(ch, SRP_IU_RSP);
+       spin_unlock_irqrestore(&ch->lock, flags);
 
        if (!iu) {
                shost_printk(KERN_ERR, target->scsi_host, PFX
@@ -1684,17 +1806,17 @@ static int srp_response_common(struct srp_target_port *target, s32 req_delta,
        memcpy(iu->buf, rsp, len);
        ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
 
-       err = srp_post_send(target, iu, len);
+       err = srp_post_send(ch, iu, len);
        if (err) {
                shost_printk(KERN_ERR, target->scsi_host, PFX
                             "unable to post response: %d\n", err);
-               srp_put_tx_iu(target, iu, SRP_IU_RSP);
+               srp_put_tx_iu(ch, iu, SRP_IU_RSP);
        }
 
        return err;
 }
 
-static void srp_process_cred_req(struct srp_target_port *target,
+static void srp_process_cred_req(struct srp_rdma_ch *ch,
                                 struct srp_cred_req *req)
 {
        struct srp_cred_rsp rsp = {
@@ -1703,14 +1825,15 @@ static void srp_process_cred_req(struct srp_target_port *target,
        };
        s32 delta = be32_to_cpu(req->req_lim_delta);
 
-       if (srp_response_common(target, delta, &rsp, sizeof rsp))
-               shost_printk(KERN_ERR, target->scsi_host, PFX
+       if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
+               shost_printk(KERN_ERR, ch->target->scsi_host, PFX
                             "problems processing SRP_CRED_REQ\n");
 }
 
-static void srp_process_aer_req(struct srp_target_port *target,
+static void srp_process_aer_req(struct srp_rdma_ch *ch,
                                struct srp_aer_req *req)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_aer_rsp rsp = {
                .opcode = SRP_AER_RSP,
                .tag = req->tag,
@@ -1720,19 +1843,20 @@ static void srp_process_aer_req(struct srp_target_port *target,
        shost_printk(KERN_ERR, target->scsi_host, PFX
                     "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
 
-       if (srp_response_common(target, delta, &rsp, sizeof rsp))
+       if (srp_response_common(ch, delta, &rsp, sizeof(rsp)))
                shost_printk(KERN_ERR, target->scsi_host, PFX
                             "problems processing SRP_AER_REQ\n");
 }
 
-static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
+static void srp_handle_recv(struct srp_rdma_ch *ch, struct ib_wc *wc)
 {
+       struct srp_target_port *target = ch->target;
        struct ib_device *dev = target->srp_host->srp_dev->dev;
        struct srp_iu *iu = (struct srp_iu *) (uintptr_t) wc->wr_id;
        int res;
        u8 opcode;
 
-       ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
+       ib_dma_sync_single_for_cpu(dev, iu->dma, ch->max_ti_iu_len,
                                   DMA_FROM_DEVICE);
 
        opcode = *(u8 *) iu->buf;
@@ -1746,15 +1870,15 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 
        switch (opcode) {
        case SRP_RSP:
-               srp_process_rsp(target, iu->buf);
+               srp_process_rsp(ch, iu->buf);
                break;
 
        case SRP_CRED_REQ:
-               srp_process_cred_req(target, iu->buf);
+               srp_process_cred_req(ch, iu->buf);
                break;
 
        case SRP_AER_REQ:
-               srp_process_aer_req(target, iu->buf);
+               srp_process_aer_req(ch, iu->buf);
                break;
 
        case SRP_T_LOGOUT:
@@ -1769,10 +1893,10 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
                break;
        }
 
-       ib_dma_sync_single_for_device(dev, iu->dma, target->max_ti_iu_len,
+       ib_dma_sync_single_for_device(dev, iu->dma, ch->max_ti_iu_len,
                                      DMA_FROM_DEVICE);
 
-       res = srp_post_recv(target, iu);
+       res = srp_post_recv(ch, iu);
        if (res != 0)
                shost_printk(KERN_ERR, target->scsi_host,
                             PFX "Recv failed with error code %d\n", res);
@@ -1795,8 +1919,15 @@ static void srp_tl_err_work(struct work_struct *work)
 }
 
 static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status,
-                             bool send_err, struct srp_target_port *target)
+                             bool send_err, struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
+
+       if (wr_id == SRP_LAST_WR_ID) {
+               complete(&ch->done);
+               return;
+       }
+
        if (target->connected && !target->qp_in_error) {
                if (wr_id & LOCAL_INV_WR_ID_MASK) {
                        shost_printk(KERN_ERR, target->scsi_host, PFX
@@ -1817,33 +1948,33 @@ static void srp_handle_qp_err(u64 wr_id, enum ib_wc_status wc_status,
        target->qp_in_error = true;
 }
 
-static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
+static void srp_recv_completion(struct ib_cq *cq, void *ch_ptr)
 {
-       struct srp_target_port *target = target_ptr;
+       struct srp_rdma_ch *ch = ch_ptr;
        struct ib_wc wc;
 
        ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
        while (ib_poll_cq(cq, 1, &wc) > 0) {
                if (likely(wc.status == IB_WC_SUCCESS)) {
-                       srp_handle_recv(target, &wc);
+                       srp_handle_recv(ch, &wc);
                } else {
-                       srp_handle_qp_err(wc.wr_id, wc.status, false, target);
+                       srp_handle_qp_err(wc.wr_id, wc.status, false, ch);
                }
        }
 }
 
-static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
+static void srp_send_completion(struct ib_cq *cq, void *ch_ptr)
 {
-       struct srp_target_port *target = target_ptr;
+       struct srp_rdma_ch *ch = ch_ptr;
        struct ib_wc wc;
        struct srp_iu *iu;
 
        while (ib_poll_cq(cq, 1, &wc) > 0) {
                if (likely(wc.status == IB_WC_SUCCESS)) {
                        iu = (struct srp_iu *) (uintptr_t) wc.wr_id;
-                       list_add(&iu->list, &target->free_tx);
+                       list_add(&iu->list, &ch->free_tx);
                } else {
-                       srp_handle_qp_err(wc.wr_id, wc.status, true, target);
+                       srp_handle_qp_err(wc.wr_id, wc.status, true, ch);
                }
        }
 }
@@ -1852,11 +1983,14 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
 {
        struct srp_target_port *target = host_to_target(shost);
        struct srp_rport *rport = target->rport;
+       struct srp_rdma_ch *ch;
        struct srp_request *req;
        struct srp_iu *iu;
        struct srp_cmd *cmd;
        struct ib_device *dev;
        unsigned long flags;
+       u32 tag;
+       u16 idx;
        int len, ret;
        const bool in_scsi_eh = !in_interrupt() && current == shost->ehandler;
 
@@ -1873,15 +2007,22 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
        if (unlikely(scmnd->result))
                goto err;
 
-       spin_lock_irqsave(&target->lock, flags);
-       iu = __srp_get_tx_iu(target, SRP_IU_CMD);
-       if (!iu)
-               goto err_unlock;
+       WARN_ON_ONCE(scmnd->request->tag < 0);
+       tag = blk_mq_unique_tag(scmnd->request);
+       ch = &target->ch[blk_mq_unique_tag_to_hwq(tag)];
+       idx = blk_mq_unique_tag_to_tag(tag);
+       WARN_ONCE(idx >= target->req_ring_size, "%s: tag %#x: idx %d >= %d\n",
+                 dev_name(&shost->shost_gendev), tag, idx,
+                 target->req_ring_size);
 
-       req = list_first_entry(&target->free_reqs, struct srp_request, list);
-       list_del(&req->list);
-       spin_unlock_irqrestore(&target->lock, flags);
+       spin_lock_irqsave(&ch->lock, flags);
+       iu = __srp_get_tx_iu(ch, SRP_IU_CMD);
+       spin_unlock_irqrestore(&ch->lock, flags);
 
+       if (!iu)
+               goto err;
+
+       req = &ch->req_ring[idx];
        dev = target->srp_host->srp_dev->dev;
        ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_iu_len,
                                   DMA_TO_DEVICE);
@@ -1893,13 +2034,13 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
 
        cmd->opcode = SRP_CMD;
        cmd->lun    = cpu_to_be64((u64) scmnd->device->lun << 48);
-       cmd->tag    = req->index;
+       cmd->tag    = tag;
        memcpy(cmd->cdb, scmnd->cmnd, scmnd->cmd_len);
 
        req->scmnd    = scmnd;
        req->cmd      = iu;
 
-       len = srp_map_data(scmnd, target, req);
+       len = srp_map_data(scmnd, ch, req);
        if (len < 0) {
                shost_printk(KERN_ERR, target->scsi_host,
                             PFX "Failed to map data (%d)\n", len);
@@ -1917,7 +2058,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
        ib_dma_sync_single_for_device(dev, iu->dma, target->max_iu_len,
                                      DMA_TO_DEVICE);
 
-       if (srp_post_send(target, iu, len)) {
+       if (srp_post_send(ch, iu, len)) {
                shost_printk(KERN_ERR, target->scsi_host, PFX "Send failed\n");
                goto err_unmap;
        }
@@ -1931,10 +2072,10 @@ unlock_rport:
        return ret;
 
 err_unmap:
-       srp_unmap_data(scmnd, target, req);
+       srp_unmap_data(scmnd, ch, req);
 
 err_iu:
-       srp_put_tx_iu(target, iu, SRP_IU_CMD);
+       srp_put_tx_iu(ch, iu, SRP_IU_CMD);
 
        /*
         * Avoid that the loops that iterate over the request ring can
@@ -1942,12 +2083,6 @@ err_iu:
         */
        req->scmnd = NULL;
 
-       spin_lock_irqsave(&target->lock, flags);
-       list_add(&req->list, &target->free_reqs);
-
-err_unlock:
-       spin_unlock_irqrestore(&target->lock, flags);
-
 err:
        if (scmnd->result) {
                scmnd->scsi_done(scmnd);
@@ -1961,53 +2096,54 @@ err:
 
 /*
  * Note: the resources allocated in this function are freed in
- * srp_free_target_ib().
+ * srp_free_ch_ib().
  */
-static int srp_alloc_iu_bufs(struct srp_target_port *target)
+static int srp_alloc_iu_bufs(struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        int i;
 
-       target->rx_ring = kzalloc(target->queue_size * sizeof(*target->rx_ring),
-                                 GFP_KERNEL);
-       if (!target->rx_ring)
+       ch->rx_ring = kcalloc(target->queue_size, sizeof(*ch->rx_ring),
+                             GFP_KERNEL);
+       if (!ch->rx_ring)
                goto err_no_ring;
-       target->tx_ring = kzalloc(target->queue_size * sizeof(*target->tx_ring),
-                                 GFP_KERNEL);
-       if (!target->tx_ring)
+       ch->tx_ring = kcalloc(target->queue_size, sizeof(*ch->tx_ring),
+                             GFP_KERNEL);
+       if (!ch->tx_ring)
                goto err_no_ring;
 
        for (i = 0; i < target->queue_size; ++i) {
-               target->rx_ring[i] = srp_alloc_iu(target->srp_host,
-                                                 target->max_ti_iu_len,
-                                                 GFP_KERNEL, DMA_FROM_DEVICE);
-               if (!target->rx_ring[i])
+               ch->rx_ring[i] = srp_alloc_iu(target->srp_host,
+                                             ch->max_ti_iu_len,
+                                             GFP_KERNEL, DMA_FROM_DEVICE);
+               if (!ch->rx_ring[i])
                        goto err;
        }
 
        for (i = 0; i < target->queue_size; ++i) {
-               target->tx_ring[i] = srp_alloc_iu(target->srp_host,
-                                                 target->max_iu_len,
-                                                 GFP_KERNEL, DMA_TO_DEVICE);
-               if (!target->tx_ring[i])
+               ch->tx_ring[i] = srp_alloc_iu(target->srp_host,
+                                             target->max_iu_len,
+                                             GFP_KERNEL, DMA_TO_DEVICE);
+               if (!ch->tx_ring[i])
                        goto err;
 
-               list_add(&target->tx_ring[i]->list, &target->free_tx);
+               list_add(&ch->tx_ring[i]->list, &ch->free_tx);
        }
 
        return 0;
 
 err:
        for (i = 0; i < target->queue_size; ++i) {
-               srp_free_iu(target->srp_host, target->rx_ring[i]);
-               srp_free_iu(target->srp_host, target->tx_ring[i]);
+               srp_free_iu(target->srp_host, ch->rx_ring[i]);
+               srp_free_iu(target->srp_host, ch->tx_ring[i]);
        }
 
 
 err_no_ring:
-       kfree(target->tx_ring);
-       target->tx_ring = NULL;
-       kfree(target->rx_ring);
-       target->rx_ring = NULL;
+       kfree(ch->tx_ring);
+       ch->tx_ring = NULL;
+       kfree(ch->rx_ring);
+       ch->rx_ring = NULL;
 
        return -ENOMEM;
 }
@@ -2041,23 +2177,24 @@ static uint32_t srp_compute_rq_tmo(struct ib_qp_attr *qp_attr, int attr_mask)
 
 static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
                               struct srp_login_rsp *lrsp,
-                              struct srp_target_port *target)
+                              struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        struct ib_qp_attr *qp_attr = NULL;
        int attr_mask = 0;
        int ret;
        int i;
 
        if (lrsp->opcode == SRP_LOGIN_RSP) {
-               target->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
-               target->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
+               ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
+               ch->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
 
                /*
                 * Reserve credits for task management so we don't
                 * bounce requests back to the SCSI mid-layer.
                 */
                target->scsi_host->can_queue
-                       = min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
+                       = min(ch->req_lim - SRP_TSK_MGMT_SQ_SIZE,
                              target->scsi_host->can_queue);
                target->scsi_host->cmd_per_lun
                        = min_t(int, target->scsi_host->can_queue,
@@ -2069,8 +2206,8 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
                goto error;
        }
 
-       if (!target->rx_ring) {
-               ret = srp_alloc_iu_bufs(target);
+       if (!ch->rx_ring) {
+               ret = srp_alloc_iu_bufs(ch);
                if (ret)
                        goto error;
        }
@@ -2085,13 +2222,14 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
        if (ret)
                goto error_free;
 
-       ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
+       ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
        if (ret)
                goto error_free;
 
        for (i = 0; i < target->queue_size; i++) {
-               struct srp_iu *iu = target->rx_ring[i];
-               ret = srp_post_recv(target, iu);
+               struct srp_iu *iu = ch->rx_ring[i];
+
+               ret = srp_post_recv(ch, iu);
                if (ret)
                        goto error_free;
        }
@@ -2103,7 +2241,7 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
 
        target->rq_tmo_jiffies = srp_compute_rq_tmo(qp_attr, attr_mask);
 
-       ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
+       ret = ib_modify_qp(ch->qp, qp_attr, attr_mask);
        if (ret)
                goto error_free;
 
@@ -2113,13 +2251,14 @@ error_free:
        kfree(qp_attr);
 
 error:
-       target->status = ret;
+       ch->status = ret;
 }
 
 static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
                               struct ib_cm_event *event,
-                              struct srp_target_port *target)
+                              struct srp_rdma_ch *ch)
 {
+       struct srp_target_port *target = ch->target;
        struct Scsi_Host *shost = target->scsi_host;
        struct ib_class_port_info *cpi;
        int opcode;
@@ -2127,12 +2266,12 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
        switch (event->param.rej_rcvd.reason) {
        case IB_CM_REJ_PORT_CM_REDIRECT:
                cpi = event->param.rej_rcvd.ari;
-               target->path.dlid = cpi->redirect_lid;
-               target->path.pkey = cpi->redirect_pkey;
+               ch->path.dlid = cpi->redirect_lid;
+               ch->path.pkey = cpi->redirect_pkey;
                cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;
-               memcpy(target->path.dgid.raw, cpi->redirect_gid, 16);
+               memcpy(ch->path.dgid.raw, cpi->redirect_gid, 16);
 
-               target->status = target->path.dlid ?
+               ch->status = ch->path.dlid ?
                        SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;
                break;
 
@@ -2143,26 +2282,26 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
                         * reject reason code 25 when they mean 24
                         * (port redirect).
                         */
-                       memcpy(target->path.dgid.raw,
+                       memcpy(ch->path.dgid.raw,
                               event->param.rej_rcvd.ari, 16);
 
                        shost_printk(KERN_DEBUG, shost,
                                     PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",
-                                    (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix),
-                                    (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id));
+                                    be64_to_cpu(ch->path.dgid.global.subnet_prefix),
+                                    be64_to_cpu(ch->path.dgid.global.interface_id));
 
-                       target->status = SRP_PORT_REDIRECT;
+                       ch->status = SRP_PORT_REDIRECT;
                } else {
                        shost_printk(KERN_WARNING, shost,
                                     "  REJ reason: IB_CM_REJ_PORT_REDIRECT\n");
-                       target->status = -ECONNRESET;
+                       ch->status = -ECONNRESET;
                }
                break;
 
        case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:
                shost_printk(KERN_WARNING, shost,
                            "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");
-               target->status = -ECONNRESET;
+               ch->status = -ECONNRESET;
                break;
 
        case IB_CM_REJ_CONSUMER_DEFINED:
@@ -2177,30 +2316,31 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
                        else
                                shost_printk(KERN_WARNING, shost, PFX
                                             "SRP LOGIN from %pI6 to %pI6 REJECTED, reason 0x%08x\n",
-                                            target->path.sgid.raw,
-                                            target->orig_dgid, reason);
+                                            target->sgid.raw,
+                                            target->orig_dgid.raw, reason);
                } else
                        shost_printk(KERN_WARNING, shost,
                                     "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"
                                     " opcode 0x%02x\n", opcode);
-               target->status = -ECONNRESET;
+               ch->status = -ECONNRESET;
                break;
 
        case IB_CM_REJ_STALE_CONN:
                shost_printk(KERN_WARNING, shost, "  REJ reason: stale connection\n");
-               target->status = SRP_STALE_CONN;
+               ch->status = SRP_STALE_CONN;
                break;
 
        default:
                shost_printk(KERN_WARNING, shost, "  REJ reason 0x%x\n",
                             event->param.rej_rcvd.reason);
-               target->status = -ECONNRESET;
+               ch->status = -ECONNRESET;
        }
 }
 
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 {
-       struct srp_target_port *target = cm_id->context;
+       struct srp_rdma_ch *ch = cm_id->context;
+       struct srp_target_port *target = ch->target;
        int comp = 0;
 
        switch (event->event) {
@@ -2208,19 +2348,19 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
                shost_printk(KERN_DEBUG, target->scsi_host,
                             PFX "Sending CM REQ failed\n");
                comp = 1;
-               target->status = -ECONNRESET;
+               ch->status = -ECONNRESET;
                break;
 
        case IB_CM_REP_RECEIVED:
                comp = 1;
-               srp_cm_rep_handler(cm_id, event->private_data, target);
+               srp_cm_rep_handler(cm_id, event->private_data, ch);
                break;
 
        case IB_CM_REJ_RECEIVED:
                shost_printk(KERN_DEBUG, target->scsi_host, PFX "REJ received\n");
                comp = 1;
 
-               srp_cm_rej_handler(cm_id, event, target);
+               srp_cm_rej_handler(cm_id, event, ch);
                break;
 
        case IB_CM_DREQ_RECEIVED:
@@ -2238,7 +2378,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
                             PFX "connection closed\n");
                comp = 1;
 
-               target->status = 0;
+               ch->status = 0;
                break;
 
        case IB_CM_MRA_RECEIVED:
@@ -2253,65 +2393,30 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
        }
 
        if (comp)
-               complete(&target->done);
+               complete(&ch->done);
 
        return 0;
 }
 
-/**
- * srp_change_queue_type - changing device queue tag type
- * @sdev: scsi device struct
- * @tag_type: requested tag type
- *
- * Returns queue tag type.
- */
-static int
-srp_change_queue_type(struct scsi_device *sdev, int tag_type)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag_type);
-               if (tag_type)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag_type = 0;
-
-       return tag_type;
-}
-
 /**
  * srp_change_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
- * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
- * (see include/scsi/scsi_host.h for definition)
  *
  * Returns queue depth.
  */
 static int
-srp_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+srp_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-       struct Scsi_Host *shost = sdev->host;
-       int max_depth;
-       if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) {
-               max_depth = shost->can_queue;
-               if (!sdev->tagged_supported)
-                       max_depth = 1;
-               if (qdepth > max_depth)
-                       qdepth = max_depth;
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-       } else if (reason == SCSI_QDEPTH_QFULL)
-               scsi_track_queue_full(sdev, qdepth);
-       else
-               return -EOPNOTSUPP;
-
-       return sdev->queue_depth;
+       if (!sdev->tagged_supported)
+               qdepth = 1;
+       return scsi_change_queue_depth(sdev, qdepth);
 }
 
-static int srp_send_tsk_mgmt(struct srp_target_port *target,
-                            u64 req_tag, unsigned int lun, u8 func)
+static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag,
+                            unsigned int lun, u8 func)
 {
+       struct srp_target_port *target = ch->target;
        struct srp_rport *rport = target->rport;
        struct ib_device *dev = target->srp_host->srp_dev->dev;
        struct srp_iu *iu;
@@ -2320,16 +2425,16 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
        if (!target->connected || target->qp_in_error)
                return -1;
 
-       init_completion(&target->tsk_mgmt_done);
+       init_completion(&ch->tsk_mgmt_done);
 
        /*
-        * Lock the rport mutex to avoid that srp_create_target_ib() is
+        * Lock the rport mutex to avoid that srp_create_ch_ib() is
         * invoked while a task management function is being sent.
         */
        mutex_lock(&rport->mutex);
-       spin_lock_irq(&target->lock);
-       iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT);
-       spin_unlock_irq(&target->lock);
+       spin_lock_irq(&ch->lock);
+       iu = __srp_get_tx_iu(ch, SRP_IU_TSK_MGMT);
+       spin_unlock_irq(&ch->lock);
 
        if (!iu) {
                mutex_unlock(&rport->mutex);
@@ -2350,15 +2455,15 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 
        ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
                                      DMA_TO_DEVICE);
-       if (srp_post_send(target, iu, sizeof *tsk_mgmt)) {
-               srp_put_tx_iu(target, iu, SRP_IU_TSK_MGMT);
+       if (srp_post_send(ch, iu, sizeof(*tsk_mgmt))) {
+               srp_put_tx_iu(ch, iu, SRP_IU_TSK_MGMT);
                mutex_unlock(&rport->mutex);
 
                return -1;
        }
        mutex_unlock(&rport->mutex);
 
-       if (!wait_for_completion_timeout(&target->tsk_mgmt_done,
+       if (!wait_for_completion_timeout(&ch->tsk_mgmt_done,
                                         msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))
                return -1;
 
@@ -2369,20 +2474,32 @@ static int srp_abort(struct scsi_cmnd *scmnd)
 {
        struct srp_target_port *target = host_to_target(scmnd->device->host);
        struct srp_request *req = (struct srp_request *) scmnd->host_scribble;
+       u32 tag;
+       u16 ch_idx;
+       struct srp_rdma_ch *ch;
        int ret;
 
        shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n");
 
-       if (!req || !srp_claim_req(target, req, NULL, scmnd))
+       if (!req)
+               return SUCCESS;
+       tag = blk_mq_unique_tag(scmnd->request);
+       ch_idx = blk_mq_unique_tag_to_hwq(tag);
+       if (WARN_ON_ONCE(ch_idx >= target->ch_count))
                return SUCCESS;
-       if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun,
+       ch = &target->ch[ch_idx];
+       if (!srp_claim_req(ch, req, NULL, scmnd))
+               return SUCCESS;
+       shost_printk(KERN_ERR, target->scsi_host,
+                    "Sending SRP abort for tag %#x\n", tag);
+       if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun,
                              SRP_TSK_ABORT_TASK) == 0)
                ret = SUCCESS;
        else if (target->rport->state == SRP_RPORT_LOST)
                ret = FAST_IO_FAIL;
        else
                ret = FAILED;
-       srp_free_req(target, req, scmnd, 0);
+       srp_free_req(ch, req, scmnd, 0);
        scmnd->result = DID_ABORT << 16;
        scmnd->scsi_done(scmnd);
 
@@ -2392,19 +2509,25 @@ static int srp_abort(struct scsi_cmnd *scmnd)
 static int srp_reset_device(struct scsi_cmnd *scmnd)
 {
        struct srp_target_port *target = host_to_target(scmnd->device->host);
+       struct srp_rdma_ch *ch;
        int i;
 
        shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
 
-       if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun,
+       ch = &target->ch[0];
+       if (srp_send_tsk_mgmt(ch, SRP_TAG_NO_REQ, scmnd->device->lun,
                              SRP_TSK_LUN_RESET))
                return FAILED;
-       if (target->tsk_mgmt_status)
+       if (ch->tsk_mgmt_status)
                return FAILED;
 
-       for (i = 0; i < target->req_ring_size; ++i) {
-               struct srp_request *req = &target->req_ring[i];
-               srp_finish_req(target, req, scmnd->device, DID_RESET << 16);
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               for (i = 0; i < target->req_ring_size; ++i) {
+                       struct srp_request *req = &ch->req_ring[i];
+
+                       srp_finish_req(ch, req, scmnd->device, DID_RESET << 16);
+               }
        }
 
        return SUCCESS;
@@ -2466,7 +2589,7 @@ static ssize_t show_pkey(struct device *dev, struct device_attribute *attr,
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
 
-       return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey));
+       return sprintf(buf, "0x%04x\n", be16_to_cpu(target->pkey));
 }
 
 static ssize_t show_sgid(struct device *dev, struct device_attribute *attr,
@@ -2474,15 +2597,16 @@ static ssize_t show_sgid(struct device *dev, struct device_attribute *attr,
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
 
-       return sprintf(buf, "%pI6\n", target->path.sgid.raw);
+       return sprintf(buf, "%pI6\n", target->sgid.raw);
 }
 
 static ssize_t show_dgid(struct device *dev, struct device_attribute *attr,
                         char *buf)
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
+       struct srp_rdma_ch *ch = &target->ch[0];
 
-       return sprintf(buf, "%pI6\n", target->path.dgid.raw);
+       return sprintf(buf, "%pI6\n", ch->path.dgid.raw);
 }
 
 static ssize_t show_orig_dgid(struct device *dev,
@@ -2490,15 +2614,21 @@ static ssize_t show_orig_dgid(struct device *dev,
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
 
-       return sprintf(buf, "%pI6\n", target->orig_dgid);
+       return sprintf(buf, "%pI6\n", target->orig_dgid.raw);
 }
 
 static ssize_t show_req_lim(struct device *dev,
                            struct device_attribute *attr, char *buf)
 {
        struct srp_target_port *target = host_to_target(class_to_shost(dev));
+       struct srp_rdma_ch *ch;
+       int i, req_lim = INT_MAX;
 
-       return sprintf(buf, "%d\n", target->req_lim);
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               req_lim = min(req_lim, ch->req_lim);
+       }
+       return sprintf(buf, "%d\n", req_lim);
 }
 
 static ssize_t show_zero_req_lim(struct device *dev,
@@ -2525,6 +2655,14 @@ static ssize_t show_local_ib_device(struct device *dev,
        return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
 }
 
+static ssize_t show_ch_count(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+       return sprintf(buf, "%d\n", target->ch_count);
+}
+
 static ssize_t show_comp_vector(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -2568,6 +2706,7 @@ static DEVICE_ATTR(req_lim,         S_IRUGO, show_req_lim,         NULL);
 static DEVICE_ATTR(zero_req_lim,    S_IRUGO, show_zero_req_lim,           NULL);
 static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
 static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
+static DEVICE_ATTR(ch_count,        S_IRUGO, show_ch_count,        NULL);
 static DEVICE_ATTR(comp_vector,     S_IRUGO, show_comp_vector,     NULL);
 static DEVICE_ATTR(tl_retry_count,  S_IRUGO, show_tl_retry_count,  NULL);
 static DEVICE_ATTR(cmd_sg_entries,  S_IRUGO, show_cmd_sg_entries,  NULL);
@@ -2585,6 +2724,7 @@ static struct device_attribute *srp_host_attrs[] = {
        &dev_attr_zero_req_lim,
        &dev_attr_local_ib_port,
        &dev_attr_local_ib_device,
+       &dev_attr_ch_count,
        &dev_attr_comp_vector,
        &dev_attr_tl_retry_count,
        &dev_attr_cmd_sg_entries,
@@ -2600,7 +2740,7 @@ static struct scsi_host_template srp_template = {
        .info                           = srp_target_info,
        .queuecommand                   = srp_queuecommand,
        .change_queue_depth             = srp_change_queue_depth,
-       .change_queue_type              = srp_change_queue_type,
+       .change_queue_type              = scsi_change_queue_type,
        .eh_abort_handler               = srp_abort,
        .eh_device_reset_handler        = srp_reset_device,
        .eh_host_reset_handler          = srp_reset_host,
@@ -2610,14 +2750,28 @@ static struct scsi_host_template srp_template = {
        .this_id                        = -1,
        .cmd_per_lun                    = SRP_DEFAULT_CMD_SQ_SIZE,
        .use_clustering                 = ENABLE_CLUSTERING,
-       .shost_attrs                    = srp_host_attrs
+       .shost_attrs                    = srp_host_attrs,
+       .use_blk_tags                   = 1,
+       .track_queue_depth              = 1,
 };
 
+static int srp_sdev_count(struct Scsi_Host *host)
+{
+       struct scsi_device *sdev;
+       int c = 0;
+
+       shost_for_each_device(sdev, host)
+               c++;
+
+       return c;
+}
+
 static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
 {
        struct srp_rport_identifiers ids;
        struct srp_rport *rport;
 
+       target->state = SRP_TARGET_SCANNING;
        sprintf(target->target_name, "SRP.T10:%016llX",
                 (unsigned long long) be64_to_cpu(target->id_ext));
 
@@ -2640,11 +2794,26 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
        list_add_tail(&target->list, &host->target_list);
        spin_unlock(&host->target_lock);
 
-       target->state = SRP_TARGET_LIVE;
-
        scsi_scan_target(&target->scsi_host->shost_gendev,
                         0, target->scsi_id, SCAN_WILD_CARD, 0);
 
+       if (!target->connected || target->qp_in_error) {
+               shost_printk(KERN_INFO, target->scsi_host,
+                            PFX "SCSI scan failed - removing SCSI host\n");
+               srp_queue_remove_work(target);
+               goto out;
+       }
+
+       pr_debug(PFX "%s: SCSI scan succeeded - detected %d LUNs\n",
+                dev_name(&target->scsi_host->shost_gendev),
+                srp_sdev_count(target->scsi_host));
+
+       spin_lock_irq(&target->lock);
+       if (target->state == SRP_TARGET_SCANNING)
+               target->state = SRP_TARGET_LIVE;
+       spin_unlock_irq(&target->lock);
+
+out:
        return 0;
 }
 
@@ -2801,11 +2970,15 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
                        }
 
                        for (i = 0; i < 16; ++i) {
-                               strlcpy(dgid, p + i * 2, 3);
-                               target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16);
+                               strlcpy(dgid, p + i * 2, sizeof(dgid));
+                               if (sscanf(dgid, "%hhx",
+                                          &target->orig_dgid.raw[i]) < 1) {
+                                       ret = -EINVAL;
+                                       kfree(p);
+                                       goto out;
+                               }
                        }
                        kfree(p);
-                       memcpy(target->orig_dgid, target->path.dgid.raw, 16);
                        break;
 
                case SRP_OPT_PKEY:
@@ -2813,7 +2986,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
                                pr_warn("bad P_Key parameter '%s'\n", p);
                                goto out;
                        }
-                       target->path.pkey = cpu_to_be16(token);
+                       target->pkey = cpu_to_be16(token);
                        break;
 
                case SRP_OPT_SERVICE_ID:
@@ -2823,7 +2996,6 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
                                goto out;
                        }
                        target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16));
-                       target->path.service_id = target->service_id;
                        kfree(p);
                        break;
 
@@ -2960,9 +3132,11 @@ static ssize_t srp_create_target(struct device *dev,
                container_of(dev, struct srp_host, dev);
        struct Scsi_Host *target_host;
        struct srp_target_port *target;
+       struct srp_rdma_ch *ch;
        struct srp_device *srp_dev = host->srp_dev;
        struct ib_device *ibdev = srp_dev->dev;
-       int ret;
+       int ret, node_idx, node, cpu, i;
+       bool multich = false;
 
        target_host = scsi_host_alloc(&srp_template,
                                      sizeof (struct srp_target_port));
@@ -2988,12 +3162,22 @@ static ssize_t srp_create_target(struct device *dev,
        target->tl_retry_count  = 7;
        target->queue_size      = SRP_DEFAULT_QUEUE_SIZE;
 
+       /*
+        * Avoid that the SCSI host can be removed by srp_remove_target()
+        * before this function returns.
+        */
+       scsi_host_get(target->scsi_host);
+
        mutex_lock(&host->add_target_mutex);
 
        ret = srp_parse_options(buf, target);
        if (ret)
                goto err;
 
+       ret = scsi_init_shared_tag_map(target_host, target_host->can_queue);
+       if (ret)
+               goto err;
+
        target->req_ring_size = target->queue_size - SRP_TSK_MGMT_SQ_SIZE;
 
        if (!srp_conn_unique(target->srp_host, target)) {
@@ -3022,59 +3206,115 @@ static ssize_t srp_create_target(struct device *dev,
        INIT_WORK(&target->tl_err_work, srp_tl_err_work);
        INIT_WORK(&target->remove_work, srp_remove_work);
        spin_lock_init(&target->lock);
-       INIT_LIST_HEAD(&target->free_tx);
-       ret = srp_alloc_req_data(target);
+       ret = ib_query_gid(ibdev, host->port, 0, &target->sgid);
        if (ret)
-               goto err_free_mem;
+               goto err;
 
-       ret = ib_query_gid(ibdev, host->port, 0, &target->path.sgid);
-       if (ret)
-               goto err_free_mem;
+       ret = -ENOMEM;
+       target->ch_count = max_t(unsigned, num_online_nodes(),
+                                min(ch_count ? :
+                                    min(4 * num_online_nodes(),
+                                        ibdev->num_comp_vectors),
+                                    num_online_cpus()));
+       target->ch = kcalloc(target->ch_count, sizeof(*target->ch),
+                            GFP_KERNEL);
+       if (!target->ch)
+               goto err;
 
-       ret = srp_create_target_ib(target);
-       if (ret)
-               goto err_free_mem;
+       node_idx = 0;
+       for_each_online_node(node) {
+               const int ch_start = (node_idx * target->ch_count /
+                                     num_online_nodes());
+               const int ch_end = ((node_idx + 1) * target->ch_count /
+                                   num_online_nodes());
+               const int cv_start = (node_idx * ibdev->num_comp_vectors /
+                                     num_online_nodes() + target->comp_vector)
+                                    % ibdev->num_comp_vectors;
+               const int cv_end = ((node_idx + 1) * ibdev->num_comp_vectors /
+                                   num_online_nodes() + target->comp_vector)
+                                  % ibdev->num_comp_vectors;
+               int cpu_idx = 0;
+
+               for_each_online_cpu(cpu) {
+                       if (cpu_to_node(cpu) != node)
+                               continue;
+                       if (ch_start + cpu_idx >= ch_end)
+                               continue;
+                       ch = &target->ch[ch_start + cpu_idx];
+                       ch->target = target;
+                       ch->comp_vector = cv_start == cv_end ? cv_start :
+                               cv_start + cpu_idx % (cv_end - cv_start);
+                       spin_lock_init(&ch->lock);
+                       INIT_LIST_HEAD(&ch->free_tx);
+                       ret = srp_new_cm_id(ch);
+                       if (ret)
+                               goto err_disconnect;
 
-       ret = srp_new_cm_id(target);
-       if (ret)
-               goto err_free_ib;
+                       ret = srp_create_ch_ib(ch);
+                       if (ret)
+                               goto err_disconnect;
 
-       ret = srp_connect_target(target);
-       if (ret) {
-               shost_printk(KERN_ERR, target->scsi_host,
-                            PFX "Connection failed\n");
-               goto err_cm_id;
+                       ret = srp_alloc_req_data(ch);
+                       if (ret)
+                               goto err_disconnect;
+
+                       ret = srp_connect_ch(ch, multich);
+                       if (ret) {
+                               shost_printk(KERN_ERR, target->scsi_host,
+                                            PFX "Connection %d/%d failed\n",
+                                            ch_start + cpu_idx,
+                                            target->ch_count);
+                               if (node_idx == 0 && cpu_idx == 0) {
+                                       goto err_disconnect;
+                               } else {
+                                       srp_free_ch_ib(target, ch);
+                                       srp_free_req_data(target, ch);
+                                       target->ch_count = ch - target->ch;
+                                       break;
+                               }
+                       }
+
+                       multich = true;
+                       cpu_idx++;
+               }
+               node_idx++;
        }
 
+       target->scsi_host->nr_hw_queues = target->ch_count;
+
        ret = srp_add_target(host, target);
        if (ret)
                goto err_disconnect;
 
-       shost_printk(KERN_DEBUG, target->scsi_host, PFX
-                    "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
-                    be64_to_cpu(target->id_ext),
-                    be64_to_cpu(target->ioc_guid),
-                    be16_to_cpu(target->path.pkey),
-                    be64_to_cpu(target->service_id),
-                    target->path.sgid.raw, target->path.dgid.raw);
+       if (target->state != SRP_TARGET_REMOVED) {
+               shost_printk(KERN_DEBUG, target->scsi_host, PFX
+                            "new target: id_ext %016llx ioc_guid %016llx pkey %04x service_id %016llx sgid %pI6 dgid %pI6\n",
+                            be64_to_cpu(target->id_ext),
+                            be64_to_cpu(target->ioc_guid),
+                            be16_to_cpu(target->pkey),
+                            be64_to_cpu(target->service_id),
+                            target->sgid.raw, target->orig_dgid.raw);
+       }
 
        ret = count;
 
 out:
        mutex_unlock(&host->add_target_mutex);
+
+       scsi_host_put(target->scsi_host);
+
        return ret;
 
 err_disconnect:
        srp_disconnect_target(target);
 
-err_cm_id:
-       ib_destroy_cm_id(target->cm_id);
-
-err_free_ib:
-       srp_free_target_ib(target);
+       for (i = 0; i < target->ch_count; i++) {
+               ch = &target->ch[i];
+               srp_free_ch_ib(target, ch);
+               srp_free_req_data(target, ch);
+       }
 
-err_free_mem:
-       srp_free_req_data(target);
+       kfree(target->ch);
 
 err:
        scsi_host_put(target_host);
index e46ecb15aa0df5cb5d992fac271bb047774a3676..a611556406ac05bb1a4befbc870f510880fce2fe 100644 (file)
@@ -70,9 +70,12 @@ enum {
 
        LOCAL_INV_WR_ID_MASK    = 1,
        FAST_REG_WR_ID_MASK     = 2,
+
+       SRP_LAST_WR_ID          = 0xfffffffcU,
 };
 
 enum srp_target_state {
+       SRP_TARGET_SCANNING,
        SRP_TARGET_LIVE,
        SRP_TARGET_REMOVED,
 };
@@ -115,7 +118,6 @@ struct srp_host {
 };
 
 struct srp_request {
-       struct list_head        list;
        struct scsi_cmnd       *scmnd;
        struct srp_iu          *cmd;
        union {
@@ -126,24 +128,62 @@ struct srp_request {
        struct srp_direct_buf  *indirect_desc;
        dma_addr_t              indirect_dma_addr;
        short                   nmdesc;
-       short                   index;
 };
 
-struct srp_target_port {
+/**
+ * struct srp_rdma_ch
+ * @comp_vector: Completion vector used by this RDMA channel.
+ */
+struct srp_rdma_ch {
        /* These are RW in the hot path, and commonly used together */
        struct list_head        free_tx;
-       struct list_head        free_reqs;
        spinlock_t              lock;
        s32                     req_lim;
 
        /* These are read-only in the hot path */
-       struct ib_cq           *send_cq ____cacheline_aligned_in_smp;
+       struct srp_target_port *target ____cacheline_aligned_in_smp;
+       struct ib_cq           *send_cq;
        struct ib_cq           *recv_cq;
        struct ib_qp           *qp;
        union {
                struct ib_fmr_pool     *fmr_pool;
                struct srp_fr_pool     *fr_pool;
        };
+
+       /* Everything above this point is used in the hot path of
+        * command processing. Try to keep them packed into cachelines.
+        */
+
+       struct completion       done;
+       int                     status;
+
+       struct ib_sa_path_rec   path;
+       struct ib_sa_query     *path_query;
+       int                     path_query_id;
+
+       struct ib_cm_id        *cm_id;
+       struct srp_iu         **tx_ring;
+       struct srp_iu         **rx_ring;
+       struct srp_request     *req_ring;
+       int                     max_ti_iu_len;
+       int                     comp_vector;
+
+       struct completion       tsk_mgmt_done;
+       u8                      tsk_mgmt_status;
+};
+
+/**
+ * struct srp_target_port
+ * @comp_vector: Completion vector used by the first RDMA channel created for
+ *   this target port.
+ */
+struct srp_target_port {
+       /* read and written in the hot path */
+       spinlock_t              lock;
+
+       /* read only in the hot path */
+       struct srp_rdma_ch      *ch;
+       u32                     ch_count;
        u32                     lkey;
        u32                     rkey;
        enum srp_target_state   state;
@@ -152,10 +192,8 @@ struct srp_target_port {
        unsigned int            indirect_size;
        bool                    allow_ext_sg;
 
-       /* Everything above this point is used in the hot path of
-        * command processing. Try to keep them packed into cachelines.
-        */
-
+       /* other member variables */
+       union ib_gid            sgid;
        __be64                  id_ext;
        __be64                  ioc_guid;
        __be64                  service_id;
@@ -172,34 +210,19 @@ struct srp_target_port {
        int                     comp_vector;
        int                     tl_retry_count;
 
-       struct ib_sa_path_rec   path;
-       __be16                  orig_dgid[8];
-       struct ib_sa_query     *path_query;
-       int                     path_query_id;
+       union ib_gid            orig_dgid;
+       __be16                  pkey;
 
        u32                     rq_tmo_jiffies;
        bool                    connected;
 
-       struct ib_cm_id        *cm_id;
-
-       int                     max_ti_iu_len;
-
        int                     zero_req_lim;
 
-       struct srp_iu          **tx_ring;
-       struct srp_iu          **rx_ring;
-       struct srp_request      *req_ring;
-
        struct work_struct      tl_err_work;
        struct work_struct      remove_work;
 
        struct list_head        list;
-       struct completion       done;
-       int                     status;
        bool                    qp_in_error;
-
-       struct completion       tsk_mgmt_done;
-       u8                      tsk_mgmt_status;
 };
 
 struct srp_iu {
index 7206547c13ce0dc8dda59458658d843d64520327..dc829682701ad1dbae8375eb2ff9a2c97feea48f 100644 (file)
@@ -2092,6 +2092,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
        if (!qp_init)
                goto out;
 
+retry:
        ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
                              ch->rq_size + srp_sq_size, 0);
        if (IS_ERR(ch->cq)) {
@@ -2115,6 +2116,13 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
        ch->qp = ib_create_qp(sdev->pd, qp_init);
        if (IS_ERR(ch->qp)) {
                ret = PTR_ERR(ch->qp);
+               if (ret == -ENOMEM) {
+                       srp_sq_size /= 2;
+                       if (srp_sq_size >= MIN_SRPT_SQ_SIZE) {
+                               ib_destroy_cq(ch->cq);
+                               goto retry;
+                       }
+               }
                printk(KERN_ERR "failed to create_qp ret= %d\n", ret);
                goto err_destroy_cq;
        }
index bc203485716d870205a22d38add99ad6c1a9ea1e..8afa28e4570ed099bb3fb9fc4b2d7e1c1a5ba9d6 100644 (file)
@@ -421,7 +421,7 @@ static int evdev_open(struct inode *inode, struct file *file)
 
  err_free_client:
        evdev_detach_client(evdev, client);
-       kfree(client);
+       kvfree(client);
        return error;
 }
 
index 2ed7905a068fc9033e8998e547bd7d750b1fedb9..fc55f0d15b70118a3a5be5fc221f151475f014e3 100644 (file)
@@ -1179,9 +1179,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
                }
 
                ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
-               usb_fill_bulk_urb(xpad->bulk_out, udev,
-                               usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
-                               xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
+               if (usb_endpoint_is_bulk_out(ep_irq_in)) {
+                       usb_fill_bulk_urb(xpad->bulk_out, udev,
+                                         usb_sndbulkpipe(udev,
+                                                         ep_irq_in->bEndpointAddress),
+                                         xpad->bdata, XPAD_PKT_LEN,
+                                         xpad_bulk_out, xpad);
+               } else {
+                       usb_fill_int_urb(xpad->bulk_out, udev,
+                                        usb_sndintpipe(udev,
+                                                       ep_irq_in->bEndpointAddress),
+                                        xpad->bdata, XPAD_PKT_LEN,
+                                        xpad_bulk_out, xpad, 0);
+               }
 
                /*
                 * Submit the int URB immediately rather than waiting for open
index 62abe2c166707c080e7f68cf1f5305e2955ee1c5..f8502bb291767c539d1a204ed34bc09d3e90c4b0 100644 (file)
@@ -70,7 +70,7 @@ static int opencores_kbd_probe(struct platform_device *pdev)
 
        opencores_kbd->addr = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(opencores_kbd->addr))
-               error = PTR_ERR(opencores_kbd->addr);
+               return PTR_ERR(opencores_kbd->addr);
 
        input->name = pdev->name;
        input->phys = "opencores-kbd/input0";
index c6727dda68f2901e10305ca15135def55c1e5675..ef5e67fb567e701365767a9949dd3ea722e4f260 100644 (file)
@@ -86,7 +86,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
                .max_cols               = 8,
                .max_rows               = 12,
                .col_gpios              = 0x0000ff,     /* GPIO 0 - 7*/
-               .row_gpios              = 0x1fef00,     /* GPIO 8-14, 16-20 */
+               .row_gpios              = 0x1f7f00,     /* GPIO 8-14, 16-20 */
        },
        [STMPE2403] = {
                .auto_increment         = true,
index 719410feb84bf9521e94fad32d299e890c1b210b..afed8e2b2f9449751f79ed219fa432e99e4c90e1 100644 (file)
@@ -1381,7 +1381,7 @@ static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev,
        pcu->ofn_reg_addr = value;
        mutex_unlock(&pcu->cmd_mutex);
 
-       return error ?: count;
+       return count;
 }
 
 static DEVICE_ATTR(reg_addr, S_IRUGO | S_IWUSR,
index 7b1fde93799ee771b638cd128fe3908a07ec82ef..ef6a9d650d69d92459212311eb5f4f81006e40d3 100644 (file)
@@ -194,7 +194,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
                                       struct ff_effect *effect)
 {
        struct max77693_haptic *haptic = input_get_drvdata(dev);
-       uint64_t period_mag_multi;
+       u64 period_mag_multi;
 
        haptic->magnitude = effect->u.rumble.strong_magnitude;
        if (!haptic->magnitude)
@@ -205,8 +205,7 @@ static int max77693_haptic_play_effect(struct input_dev *dev, void *data,
         * The formula to convert magnitude to pwm_duty as follows:
         * - pwm_duty = (magnitude * pwm_period) / MAX_MAGNITUDE(0xFFFF)
         */
-       period_mag_multi = (int64_t)(haptic->pwm_dev->period *
-                                               haptic->magnitude);
+       period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude;
        haptic->pwm_duty = (unsigned int)(period_mag_multi >>
                                                MAX_MAGNITUDE_SHIFT);
 
index 73560475356841ad2474e612fd8917ea6416407e..e097f1ab427fe720b58c194dd582c958f442d36a 100644 (file)
@@ -55,7 +55,7 @@ static int soc_button_lookup_gpio(struct device *dev, int acpi_index)
        struct gpio_desc *desc;
        int gpio;
 
-       desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index);
+       desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index, GPIOD_ASIS);
        if (IS_ERR(desc))
                return PTR_ERR(desc);
 
index fb3b63b2f85c3615619452ef9ee2e6f0528d8245..8400a1a34d87569a5d81febffb75e97d91365ee5 100644 (file)
@@ -85,6 +85,7 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, pwr);
+       device_init_wakeup(&pdev->dev, true);
 
        return 0;
 }
index 2b0ae8cc8e51bc3ca52622f66e5909b537bd0153..d125a019383f10155dcafb88903f47e0f5297080 100644 (file)
@@ -1156,7 +1156,13 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
 
-       if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
+       /*
+        * Check if we are dealing with a bare PS/2 packet, presumably from
+        * a device connected to the external PS/2 port. Because bare PS/2
+        * protocol does not have enough constant bits to self-synchronize
+        * properly we only do this if the device is fully synchronized.
+        */
+       if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) {
                if (psmouse->pktcnt == 3) {
                        alps_report_bare_ps2_packet(psmouse, psmouse->packet,
                                                    true);
@@ -1180,12 +1186,27 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
        }
 
        /* Bytes 2 - pktsize should have 0 in the highest bit */
-       if ((priv->proto_version < ALPS_PROTO_V5) &&
+       if (priv->proto_version < ALPS_PROTO_V5 &&
            psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
            (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
                psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
                            psmouse->pktcnt - 1,
                            psmouse->packet[psmouse->pktcnt - 1]);
+
+               if (priv->proto_version == ALPS_PROTO_V3 &&
+                   psmouse->pktcnt == psmouse->pktsize) {
+                       /*
+                        * Some Dell boxes, such as Latitude E6440 or E7440
+                        * with closed lid, quite often smash last byte of
+                        * otherwise valid packet with 0xff. Given that the
+                        * next packet is very likely to be valid let's
+                        * report PSMOUSE_FULL_PACKET but not process data,
+                        * rather than reporting PSMOUSE_BAD_DATA and
+                        * filling the logs.
+                        */
+                       return PSMOUSE_FULL_PACKET;
+               }
+
                return PSMOUSE_BAD_DATA;
        }
 
@@ -2389,6 +2410,9 @@ int alps_init(struct psmouse *psmouse)
        /* We are having trouble resyncing ALPS touchpads so disable it for now */
        psmouse->resync_time = 0;
 
+       /* Allow 2 invalid packets without resetting device */
+       psmouse->resetafter = psmouse->pktsize * 2;
+
        return 0;
 
 init_fail:
index 06fc6e76ffbe0cf725053b8a1bdb3faaefa1c629..f2b97802640755aacfcde04005b125717cb63818 100644 (file)
@@ -428,14 +428,6 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
        int x, y;
        u32 t;
 
-       if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev,
-                         !tp_dev,
-                         psmouse_fmt("Unexpected trackpoint message\n"))) {
-               if (etd->debug == 1)
-                       elantech_packet_dump(psmouse);
-               return;
-       }
-
        t = get_unaligned_le32(&packet[0]);
 
        switch (t & ~7U) {
@@ -563,6 +555,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
        } else {
                input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
                input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
+               input_report_key(dev, BTN_MIDDLE, packet[0] & 0x04);
        }
 
        input_mt_report_pointer_emulation(dev, true);
@@ -792,6 +785,9 @@ static int elantech_packet_check_v4(struct psmouse *psmouse)
        unsigned char packet_type = packet[3] & 0x03;
        bool sanity_check;
 
+       if (etd->tp_dev && (packet[3] & 0x0f) == 0x06)
+               return PACKET_TRACKPOINT;
+
        /*
         * Sanity check based on the constant bits of a packet.
         * The constant bits change depending on the value of
@@ -877,10 +873,19 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 
        case 4:
                packet_type = elantech_packet_check_v4(psmouse);
-               if (packet_type == PACKET_UNKNOWN)
+               switch (packet_type) {
+               case PACKET_UNKNOWN:
                        return PSMOUSE_BAD_DATA;
 
-               elantech_report_absolute_v4(psmouse, packet_type);
+               case PACKET_TRACKPOINT:
+                       elantech_report_trackpoint(psmouse, packet_type);
+                       break;
+
+               default:
+                       elantech_report_absolute_v4(psmouse, packet_type);
+                       break;
+               }
+
                break;
        }
 
@@ -1119,6 +1124,22 @@ static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
        }
 }
 
+/*
+ * Some hw_version 4 models do have a middle button
+ */
+static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+       {
+               /* Fujitsu H730 has a middle button */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
+               },
+       },
+#endif
+       { }
+};
+
 /*
  * Set the appropriate event bits for the input subsystem
  */
@@ -1138,6 +1159,8 @@ static int elantech_set_input_params(struct psmouse *psmouse)
        __clear_bit(EV_REL, dev->evbit);
 
        __set_bit(BTN_LEFT, dev->keybit);
+       if (dmi_check_system(elantech_dmi_has_middle_button))
+               __set_bit(BTN_MIDDLE, dev->keybit);
        __set_bit(BTN_RIGHT, dev->keybit);
 
        __set_bit(BTN_TOUCH, dev->keybit);
@@ -1299,6 +1322,7 @@ ELANTECH_INT_ATTR(reg_25, 0x25);
 ELANTECH_INT_ATTR(reg_26, 0x26);
 ELANTECH_INT_ATTR(debug, 0);
 ELANTECH_INT_ATTR(paritycheck, 0);
+ELANTECH_INT_ATTR(crc_enabled, 0);
 
 static struct attribute *elantech_attrs[] = {
        &psmouse_attr_reg_07.dattr.attr,
@@ -1313,6 +1337,7 @@ static struct attribute *elantech_attrs[] = {
        &psmouse_attr_reg_26.dattr.attr,
        &psmouse_attr_debug.dattr.attr,
        &psmouse_attr_paritycheck.dattr.attr,
+       &psmouse_attr_crc_enabled.dattr.attr,
        NULL
 };
 
@@ -1438,6 +1463,22 @@ static int elantech_reconnect(struct psmouse *psmouse)
        return 0;
 }
 
+/*
+ * Some hw_version 4 models do not work with crc_disabled
+ */
+static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+       {
+               /* Fujitsu H730 does not work with crc_enabled == 0 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H730"),
+               },
+       },
+#endif
+       { }
+};
+
 /*
  * Some hw_version 3 models go into error state when we try to set
  * bit 3 and/or bit 1 of r10.
@@ -1513,7 +1554,8 @@ static int elantech_set_properties(struct elantech_data *etd)
         * The signatures of v3 and v4 packets change depending on the
         * value of this hardware flag.
         */
-       etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
+       etd->crc_enabled = (etd->fw_version & 0x4000) == 0x4000 ||
+                          dmi_check_system(elantech_dmi_force_crc_enabled);
 
        /* Enable real hardware resolution on hw_version 3 ? */
        etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table);
index 26994f6a2b2ae7abe3f04a953eab9004b25d40d1..95a3a6e2faf6f29aef187485a0c832f6595121ff 100644 (file)
@@ -1536,16 +1536,9 @@ static int psmouse_reconnect(struct serio *serio)
 {
        struct psmouse *psmouse = serio_get_drvdata(serio);
        struct psmouse *parent = NULL;
-       struct serio_driver *drv = serio->drv;
        unsigned char type;
        int rc = -1;
 
-       if (!drv || !psmouse) {
-               psmouse_dbg(psmouse,
-                           "reconnect request, but serio is disconnected, ignoring...\n");
-               return -1;
-       }
-
        mutex_lock(&psmouse_mutex);
 
        if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
index 9031a0a28ea4f2cf0c086036334e975a3fdbdf35..f9472920d986368f7aa83eb7d0621489d774b050 100644 (file)
@@ -135,14 +135,18 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
                1232, 5710, 1156, 4696
        },
        {
-               (const char * const []){"LEN0034", "LEN0036", "LEN2002",
-                                       "LEN2004", NULL},
+               (const char * const []){"LEN0034", "LEN0036", "LEN0039",
+                                       "LEN2002", "LEN2004", NULL},
                1024, 5112, 2024, 4832
        },
        {
                (const char * const []){"LEN2001", NULL},
                1024, 5022, 2508, 4832
        },
+       {
+               (const char * const []){"LEN2006", NULL},
+               1264, 5675, 1171, 4688
+       },
        { }
 };
 
@@ -163,6 +167,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
        "LEN0036", /* T440 */
        "LEN0037",
        "LEN0038",
+       "LEN0039", /* T440s */
        "LEN0041",
        "LEN0042", /* Yoga */
        "LEN0045",
index 38298232124fc10de191e26f51add23662040def..abd494411e69cc46bc39e826bef82d22b5e8b478 100644 (file)
@@ -128,7 +128,7 @@ static void vsxxxaa_drop_bytes(struct vsxxxaa *mouse, int num)
        if (num >= mouse->count) {
                mouse->count = 0;
        } else {
-               memmove(mouse->buf, mouse->buf + num - 1, BUFLEN - num);
+               memmove(mouse->buf, mouse->buf + num, BUFLEN - num);
                mouse->count -= num;
        }
 }
index cce69d6b95871107e9540363a15256f360ef8723..58781c8a8aecc0a089d835bee20707d318a3ac14 100644 (file)
@@ -37,7 +37,7 @@ static irqreturn_t altera_ps2_rxint(int irq, void *dev_id)
 {
        struct ps2if *ps2if = dev_id;
        unsigned int status;
-       int handled = IRQ_NONE;
+       irqreturn_t handled = IRQ_NONE;
 
        while ((status = readl(ps2if->base)) & 0xffff0000) {
                serio_interrupt(ps2if->io, status & 0xff, 0);
@@ -74,7 +74,7 @@ static void altera_ps2_close(struct serio *io)
 {
        struct ps2if *ps2if = io->port_data;
 
-       writel(0, ps2if->base); /* disable rx irq */
+       writel(0, ps2if->base + 4); /* disable rx irq */
 }
 
 /*
index a0bcbb64d06d8eebc98ec147987cd75b875db251..faeeb1372462e40a9759313101267e8c230e2fcb 100644 (file)
@@ -207,17 +207,282 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
 };
 
 /*
- * Some laptops do implement active multiplexing mode correctly;
- * unfortunately they are in minority.
+ * Some Fujitsu notebooks are having trouble with touchpads if
+ * active multiplexing mode is activated. Luckily they don't have
+ * external PS/2 ports so we can safely disable it.
+ * ... apparently some Toshibas don't like MUX mode either and
+ * die horrible death on reboot.
  */
-static const struct dmi_system_id __initconst i8042_dmi_mux_table[] = {
+static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
+       {
+               /* Fujitsu Lifebook P7010/P7010D */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
+               },
+       },
+       {
+               /* Fujitsu Lifebook P7010 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
+               },
+       },
+       {
+               /* Fujitsu Lifebook P5020D */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
+               },
+       },
+       {
+               /* Fujitsu Lifebook S2000 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
+               },
+       },
+       {
+               /* Fujitsu Lifebook S6230 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
+               },
+       },
+       {
+               /* Fujitsu T70H */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
+               },
+       },
+       {
+               /* Fujitsu-Siemens Lifebook T3010 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"),
+               },
+       },
+       {
+               /* Fujitsu-Siemens Lifebook E4010 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
+               },
+       },
+       {
+               /* Fujitsu-Siemens Amilo Pro 2010 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"),
+               },
+       },
+       {
+               /* Fujitsu-Siemens Amilo Pro 2030 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),
+               },
+       },
+       {
+               /*
+                * No data is coming from the touchscreen unless KBC
+                * is in legacy mode.
+                */
+               /* Panasonic CF-29 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+               },
+       },
+       {
+               /*
+                * HP Pavilion DV4017EA -
+                * errors on MUX ports are reported without raising AUXDATA
+                * causing "spurious NAK" messages.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
+               },
+       },
+       {
+               /*
+                * HP Pavilion ZT1000 -
+                * like DV4017EA does not raise AUXERR for errors on MUX ports.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+               },
+       },
+       {
+               /*
+                * HP Pavilion DV4270ca -
+                * like DV4017EA does not raise AUXERR for errors on MUX ports.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"),
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
+               },
+       },
+       {
+               /* Sharp Actius MM20 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
+               },
+       },
+       {
+               /* Sony Vaio FS-115b */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
+               },
+       },
+       {
+               /*
+                * Sony Vaio FZ-240E -
+                * reset and GET ID commands issued via KBD port are
+                * sometimes being delivered to AUX3.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
+               },
+       },
        {
                /*
-                * Panasonic CF-18 needs to be in MUX mode since the
-                * touchscreen is on serio3 and it also has touchpad.
+                * Most (all?) VAIOs do not have external PS/2 ports nor
+                * they implement active multiplexing properly, and
+                * MUX discovery usually messes up keyboard/touchpad.
                 */
                .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+                       DMI_MATCH(DMI_BOARD_NAME, "VAIO"),
+               },
+       },
+       {
+               /* Amoi M636/A737 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),
+               },
+       },
+       {
+               /* Lenovo 3000 n100 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
+               },
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
+               },
+       },
+       {
+               /* Acer Aspire 5710 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"),
+               },
+       },
+       {
+               /* Gericom Bellagio */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
+               },
+       },
+       {
+               /* IBM 2656 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
+               },
+       },
+       {
+               /* Dell XPS M1530 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
+               },
+       },
+       {
+               /* Compal HEL80I */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
+               },
+       },
+       {
+               /* Dell Vostro 1510 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
+               },
+       },
+       {
+               /* Acer Aspire 5536 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+               },
+       },
+       {
+               /* Dell Vostro V13 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+               },
+       },
+       {
+               /* Newer HP Pavilion dv4 models */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+               },
+       },
+       {
+               /* Asus X450LCP */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
+               },
+       },
+       {
+               /* Avatar AVIU-145A6 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
                },
        },
        { }
@@ -363,6 +628,22 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
                },
        },
+       {
+               /* Fujitsu A544 laptop */
+               /* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"),
+               },
+       },
+       {
+               /* Fujitsu AH544 laptop */
+               /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),
+               },
+       },
        {
                /* Fujitsu U574 laptop */
                /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
@@ -740,8 +1021,8 @@ static int __init i8042_platform_init(void)
        if (dmi_check_system(i8042_dmi_noloop_table))
                i8042_noloop = true;
 
-       if (dmi_check_system(i8042_dmi_mux_table))
-               i8042_nomux = false;
+       if (dmi_check_system(i8042_dmi_nomux_table))
+               i8042_nomux = true;
 
        if (dmi_check_system(i8042_dmi_notimeout_table))
                i8042_notimeout = true;
index 9a97c2b10926c953e937a6a5a2a99e87e7215182..f5a98af3b325c1f3257759e31a450c67b2fa00a5 100644 (file)
@@ -39,7 +39,7 @@ static bool i8042_noaux;
 module_param_named(noaux, i8042_noaux, bool, 0);
 MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");
 
-static bool i8042_nomux = true;
+static bool i8042_nomux;
 module_param_named(nomux, i8042_nomux, bool, 0);
 MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing controller is present.");
 
index d0ef91fc87d1cc67838056a77b5539fe10eef4ed..b1ae779959682aded357ce3d9f0e99f288c49c63 100644 (file)
  * Documentation/input/input-programming.txt for more details.
  */
 
-static int abs_x[3] = {350, 3900, 5};
+static int abs_x[3] = {150, 4000, 5};
 module_param_array(abs_x, int, NULL, 0);
 MODULE_PARM_DESC(abs_x, "Touchscreen absolute X min, max, fuzz");
 
-static int abs_y[3] = {320, 3750, 40};
+static int abs_y[3] = {200, 4000, 40};
 module_param_array(abs_y, int, NULL, 0);
 MODULE_PARM_DESC(abs_y, "Touchscreen absolute Y min, max, fuzz");
 
index dd5112265cc9f20d138ae7d70afedbc8476ffacf..6dbfbc20949168ec32bb3536d998648bb1f63fe2 100644 (file)
@@ -163,14 +163,14 @@ config TEGRA_IOMMU_GART
          hardware included on Tegra SoCs.
 
 config TEGRA_IOMMU_SMMU
-       bool "Tegra SMMU IOMMU Support"
-       depends on ARCH_TEGRA && TEGRA_AHB
+       bool "NVIDIA Tegra SMMU Support"
+       depends on ARCH_TEGRA
+       depends on TEGRA_AHB
+       depends on TEGRA_MC
        select IOMMU_API
        help
-         Enables support for remapping discontiguous physical memory
-         shared with the operating system into contiguous I/O virtual
-         space through the SMMU (System Memory Management Unit)
-         hardware included on Tegra SoCs.
+         This driver supports the IOMMU hardware (SMMU) found on NVIDIA Tegra
+         SoCs (Tegra30 up to Tegra124).
 
 config EXYNOS_IOMMU
        bool "Exynos IOMMU Support"
index 505a9adac2d51f560617ae36c7a2f53a58f906b6..2d84c9edf3b88e4017c2ba34cb83a2a96d638274 100644 (file)
@@ -3424,6 +3424,7 @@ static const struct iommu_ops amd_iommu_ops = {
        .detach_dev = amd_iommu_detach_device,
        .map = amd_iommu_map,
        .unmap = amd_iommu_unmap,
+       .map_sg = default_iommu_map_sg,
        .iova_to_phys = amd_iommu_iova_to_phys,
        .pgsize_bitmap  = AMD_IOMMU_PGSIZES,
 };
index 60558f794922f9c7c0b5f690b195fd133c1a730a..e393ae01b5d28316bce3fde017635bbe653aef21 100644 (file)
@@ -1652,6 +1652,7 @@ static const struct iommu_ops arm_smmu_ops = {
        .detach_dev     = arm_smmu_detach_dev,
        .map            = arm_smmu_map,
        .unmap          = arm_smmu_unmap,
+       .map_sg         = default_iommu_map_sg,
        .iova_to_phys   = arm_smmu_iova_to_phys,
        .add_device     = arm_smmu_add_device,
        .remove_device  = arm_smmu_remove_device,
index 74233186f6f7b0311cb2c712a2890f91ada9e458..28372b85d8da5576db75403bc88f9a1437564bfa 100644 (file)
@@ -1178,6 +1178,7 @@ static const struct iommu_ops exynos_iommu_ops = {
        .detach_dev = exynos_iommu_detach_device,
        .map = exynos_iommu_map,
        .unmap = exynos_iommu_unmap,
+       .map_sg = default_iommu_map_sg,
        .iova_to_phys = exynos_iommu_iova_to_phys,
        .add_device = exynos_iommu_add_device,
        .remove_device = exynos_iommu_remove_device,
index a27d6cb1a793edb5559e09ee49c993817ff8ebc0..02cd26a17fe071f18591d10f8ece0e2d91686381 100644 (file)
@@ -4467,6 +4467,7 @@ static const struct iommu_ops intel_iommu_ops = {
        .detach_dev     = intel_iommu_detach_device,
        .map            = intel_iommu_map,
        .unmap          = intel_iommu_unmap,
+       .map_sg         = default_iommu_map_sg,
        .iova_to_phys   = intel_iommu_iova_to_phys,
        .add_device     = intel_iommu_add_device,
        .remove_device  = intel_iommu_remove_device,
index ed8b04867b1fce059f2fd0ee3c242e161cdb1e52..02e4313e937c3f281d8077a20e60e9c616da4c18 100644 (file)
@@ -818,7 +818,15 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
                kfree(nb);
                return err;
        }
-       return bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
+
+       err = bus_for_each_dev(bus, NULL, &cb, add_iommu_group);
+       if (err) {
+               bus_unregister_notifier(bus, nb);
+               kfree(nb);
+               return err;
+       }
+
+       return 0;
 }
 
 /**
@@ -836,13 +844,19 @@ static int iommu_bus_init(struct bus_type *bus, const struct iommu_ops *ops)
  */
 int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops)
 {
+       int err;
+
        if (bus->iommu_ops != NULL)
                return -EBUSY;
 
        bus->iommu_ops = ops;
 
        /* Do IOMMU specific setup for this bus-type */
-       return iommu_bus_init(bus, ops);
+       err = iommu_bus_init(bus, ops);
+       if (err)
+               bus->iommu_ops = NULL;
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(bus_set_iommu);
 
@@ -1124,6 +1138,38 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
 }
 EXPORT_SYMBOL_GPL(iommu_unmap);
 
+size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+                        struct scatterlist *sg, unsigned int nents, int prot)
+{
+       struct scatterlist *s;
+       size_t mapped = 0;
+       unsigned int i;
+       int ret;
+
+       for_each_sg(sg, s, nents, i) {
+               phys_addr_t phys = page_to_phys(sg_page(s));
+
+               /* We are mapping on page boundarys, so offset must be 0 */
+               if (s->offset)
+                       goto out_err;
+
+               ret = iommu_map(domain, iova + mapped, phys, s->length, prot);
+               if (ret)
+                       goto out_err;
+
+               mapped += s->length;
+       }
+
+       return mapped;
+
+out_err:
+       /* undo mappings already done */
+       iommu_unmap(domain, iova, mapped);
+
+       return 0;
+
+}
+EXPORT_SYMBOL_GPL(default_iommu_map_sg);
 
 int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,
                               phys_addr_t paddr, u64 size, int prot)
index 7dab5cbcc775414e5d8e20b48cedf6fed439a7d3..e509c58eee92ac9ccfda3ea13d7f0617cb900af1 100644 (file)
@@ -1127,6 +1127,7 @@ static const struct iommu_ops ipmmu_ops = {
        .detach_dev = ipmmu_detach_device,
        .map = ipmmu_map,
        .unmap = ipmmu_unmap,
+       .map_sg = default_iommu_map_sg,
        .iova_to_phys = ipmmu_iova_to_phys,
        .add_device = ipmmu_add_device,
        .remove_device = ipmmu_remove_device,
index 6e3dcc289d59d49c2cec89a4c0abcba19c3b01bd..1c7b78ecf3e307718fe52af9d5fa32b5f2a8ff22 100644 (file)
@@ -681,6 +681,7 @@ static const struct iommu_ops msm_iommu_ops = {
        .detach_dev = msm_iommu_detach_dev,
        .map = msm_iommu_map,
        .unmap = msm_iommu_unmap,
+       .map_sg = default_iommu_map_sg,
        .iova_to_phys = msm_iommu_iova_to_phys,
        .pgsize_bitmap = MSM_IOMMU_PGSIZES,
 };
index 36278870e84a7b1d7350772beb2c8e2aee11fa40..18003c0444541bdbee5915eee228e7d8e2c87731 100644 (file)
@@ -1288,6 +1288,7 @@ static const struct iommu_ops omap_iommu_ops = {
        .detach_dev     = omap_iommu_detach_dev,
        .map            = omap_iommu_map,
        .unmap          = omap_iommu_unmap,
+       .map_sg         = default_iommu_map_sg,
        .iova_to_phys   = omap_iommu_iova_to_phys,
        .add_device     = omap_iommu_add_device,
        .remove_device  = omap_iommu_remove_device,
index 1333e6fb3405a34513068f1ca3f4be02d99d5120..f1b00774e4de980511cf741895a219059f52d6fa 100644 (file)
@@ -361,6 +361,7 @@ static const struct iommu_ops shmobile_iommu_ops = {
        .detach_dev = shmobile_iommu_detach_device,
        .map = shmobile_iommu_map,
        .unmap = shmobile_iommu_unmap,
+       .map_sg = default_iommu_map_sg,
        .iova_to_phys = shmobile_iommu_iova_to_phys,
        .add_device = shmobile_iommu_add_device,
        .pgsize_bitmap = SZ_1M | SZ_64K | SZ_4K,
index 3afdf43f732ac0df57e0893d37a71f1c2ca6d201..6e134c7c227fced6a0c186f3e403fc6d9e1d49f7 100644 (file)
 /*
- * IOMMU API for SMMU in Tegra30
+ * Copyright (C) 2011-2014 NVIDIA CORPORATION.  All rights reserved.
  *
- * Copyright (c) 2011-2013, NVIDIA CORPORATION.  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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * This program is free software; you can 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)    "%s(): " fmt, __func__
-
 #include <linux/err.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/device.h>
-#include <linux/sched.h>
 #include <linux/iommu.h>
-#include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/of.h>
-#include <linux/of_iommu.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
 
 #include <soc/tegra/ahb.h>
+#include <soc/tegra/mc.h>
 
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-
-enum smmu_hwgrp {
-       HWGRP_AFI,
-       HWGRP_AVPC,
-       HWGRP_DC,
-       HWGRP_DCB,
-       HWGRP_EPP,
-       HWGRP_G2,
-       HWGRP_HC,
-       HWGRP_HDA,
-       HWGRP_ISP,
-       HWGRP_MPE,
-       HWGRP_NV,
-       HWGRP_NV2,
-       HWGRP_PPCS,
-       HWGRP_SATA,
-       HWGRP_VDE,
-       HWGRP_VI,
-
-       HWGRP_COUNT,
-
-       HWGRP_END = ~0,
-};
+struct tegra_smmu {
+       void __iomem *regs;
+       struct device *dev;
 
-#define HWG_AFI                (1 << HWGRP_AFI)
-#define HWG_AVPC       (1 << HWGRP_AVPC)
-#define HWG_DC         (1 << HWGRP_DC)
-#define HWG_DCB                (1 << HWGRP_DCB)
-#define HWG_EPP                (1 << HWGRP_EPP)
-#define HWG_G2         (1 << HWGRP_G2)
-#define HWG_HC         (1 << HWGRP_HC)
-#define HWG_HDA                (1 << HWGRP_HDA)
-#define HWG_ISP                (1 << HWGRP_ISP)
-#define HWG_MPE                (1 << HWGRP_MPE)
-#define HWG_NV         (1 << HWGRP_NV)
-#define HWG_NV2                (1 << HWGRP_NV2)
-#define HWG_PPCS       (1 << HWGRP_PPCS)
-#define HWG_SATA       (1 << HWGRP_SATA)
-#define HWG_VDE                (1 << HWGRP_VDE)
-#define HWG_VI         (1 << HWGRP_VI)
-
-/* bitmap of the page sizes currently supported */
-#define SMMU_IOMMU_PGSIZES     (SZ_4K)
-
-#define SMMU_CONFIG                            0x10
-#define SMMU_CONFIG_DISABLE                    0
-#define SMMU_CONFIG_ENABLE                     1
-
-/* REVISIT: To support multiple MCs */
-enum {
-       _MC = 0,
-};
+       struct tegra_mc *mc;
+       const struct tegra_smmu_soc *soc;
 
-enum {
-       _TLB = 0,
-       _PTC,
-};
+       unsigned long *asids;
+       struct mutex lock;
 
-#define SMMU_CACHE_CONFIG_BASE                 0x14
-#define __SMMU_CACHE_CONFIG(mc, cache)         (SMMU_CACHE_CONFIG_BASE + 4 * cache)
-#define SMMU_CACHE_CONFIG(cache)               __SMMU_CACHE_CONFIG(_MC, cache)
-
-#define SMMU_CACHE_CONFIG_STATS_SHIFT          31
-#define SMMU_CACHE_CONFIG_STATS_ENABLE         (1 << SMMU_CACHE_CONFIG_STATS_SHIFT)
-#define SMMU_CACHE_CONFIG_STATS_TEST_SHIFT     30
-#define SMMU_CACHE_CONFIG_STATS_TEST           (1 << SMMU_CACHE_CONFIG_STATS_TEST_SHIFT)
-
-#define SMMU_TLB_CONFIG_HIT_UNDER_MISS__ENABLE (1 << 29)
-#define SMMU_TLB_CONFIG_ACTIVE_LINES__VALUE    0x10
-#define SMMU_TLB_CONFIG_RESET_VAL              0x20000010
-
-#define SMMU_PTC_CONFIG_CACHE__ENABLE          (1 << 29)
-#define SMMU_PTC_CONFIG_INDEX_MAP__PATTERN     0x3f
-#define SMMU_PTC_CONFIG_RESET_VAL              0x2000003f
-
-#define SMMU_PTB_ASID                          0x1c
-#define SMMU_PTB_ASID_CURRENT_SHIFT            0
-
-#define SMMU_PTB_DATA                          0x20
-#define SMMU_PTB_DATA_RESET_VAL                        0
-#define SMMU_PTB_DATA_ASID_NONSECURE_SHIFT     29
-#define SMMU_PTB_DATA_ASID_WRITABLE_SHIFT      30
-#define SMMU_PTB_DATA_ASID_READABLE_SHIFT      31
-
-#define SMMU_TLB_FLUSH                         0x30
-#define SMMU_TLB_FLUSH_VA_MATCH_ALL            0
-#define SMMU_TLB_FLUSH_VA_MATCH_SECTION                2
-#define SMMU_TLB_FLUSH_VA_MATCH_GROUP          3
-#define SMMU_TLB_FLUSH_ASID_SHIFT              29
-#define SMMU_TLB_FLUSH_ASID_MATCH_DISABLE      0
-#define SMMU_TLB_FLUSH_ASID_MATCH_ENABLE       1
-#define SMMU_TLB_FLUSH_ASID_MATCH_SHIFT                31
-
-#define SMMU_PTC_FLUSH                         0x34
-#define SMMU_PTC_FLUSH_TYPE_ALL                        0
-#define SMMU_PTC_FLUSH_TYPE_ADR                        1
-#define SMMU_PTC_FLUSH_ADR_SHIFT               4
-
-#define SMMU_ASID_SECURITY                     0x38
-
-#define SMMU_STATS_CACHE_COUNT_BASE            0x1f0
-
-#define SMMU_STATS_CACHE_COUNT(mc, cache, hitmiss)             \
-       (SMMU_STATS_CACHE_COUNT_BASE + 8 * cache + 4 * hitmiss)
-
-#define SMMU_TRANSLATION_ENABLE_0              0x228
-#define SMMU_TRANSLATION_ENABLE_1              0x22c
-#define SMMU_TRANSLATION_ENABLE_2              0x230
-
-#define SMMU_AFI_ASID  0x238   /* PCIE */
-#define SMMU_AVPC_ASID 0x23c   /* AVP */
-#define SMMU_DC_ASID   0x240   /* Display controller */
-#define SMMU_DCB_ASID  0x244   /* Display controller B */
-#define SMMU_EPP_ASID  0x248   /* Encoder pre-processor */
-#define SMMU_G2_ASID   0x24c   /* 2D engine */
-#define SMMU_HC_ASID   0x250   /* Host1x */
-#define SMMU_HDA_ASID  0x254   /* High-def audio */
-#define SMMU_ISP_ASID  0x258   /* Image signal processor */
-#define SMMU_MPE_ASID  0x264   /* MPEG encoder */
-#define SMMU_NV_ASID   0x268   /* (3D) */
-#define SMMU_NV2_ASID  0x26c   /* (3D) */
-#define SMMU_PPCS_ASID 0x270   /* AHB */
-#define SMMU_SATA_ASID 0x278   /* SATA */
-#define SMMU_VDE_ASID  0x27c   /* Video decoder */
-#define SMMU_VI_ASID   0x280   /* Video input */
-
-#define SMMU_PDE_NEXT_SHIFT            28
-
-#define SMMU_TLB_FLUSH_VA_SECTION__MASK                0xffc00000
-#define SMMU_TLB_FLUSH_VA_SECTION__SHIFT       12 /* right shift */
-#define SMMU_TLB_FLUSH_VA_GROUP__MASK          0xffffc000
-#define SMMU_TLB_FLUSH_VA_GROUP__SHIFT         12 /* right shift */
-#define SMMU_TLB_FLUSH_VA(iova, which) \
-       ((((iova) & SMMU_TLB_FLUSH_VA_##which##__MASK) >> \
-               SMMU_TLB_FLUSH_VA_##which##__SHIFT) |   \
-       SMMU_TLB_FLUSH_VA_MATCH_##which)
-#define SMMU_PTB_ASID_CUR(n)   \
-               ((n) << SMMU_PTB_ASID_CURRENT_SHIFT)
-#define SMMU_TLB_FLUSH_ASID_MATCH_disable              \
-               (SMMU_TLB_FLUSH_ASID_MATCH_DISABLE <<   \
-                       SMMU_TLB_FLUSH_ASID_MATCH_SHIFT)
-#define SMMU_TLB_FLUSH_ASID_MATCH__ENABLE              \
-               (SMMU_TLB_FLUSH_ASID_MATCH_ENABLE <<    \
-                       SMMU_TLB_FLUSH_ASID_MATCH_SHIFT)
-
-#define SMMU_PAGE_SHIFT 12
-#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT)
-#define SMMU_PAGE_MASK ((1 << SMMU_PAGE_SHIFT) - 1)
-
-#define SMMU_PDIR_COUNT        1024
-#define SMMU_PDIR_SIZE (sizeof(unsigned long) * SMMU_PDIR_COUNT)
-#define SMMU_PTBL_COUNT        1024
-#define SMMU_PTBL_SIZE (sizeof(unsigned long) * SMMU_PTBL_COUNT)
-#define SMMU_PDIR_SHIFT        12
-#define SMMU_PDE_SHIFT 12
-#define SMMU_PTE_SHIFT 12
-#define SMMU_PFN_MASK  0x000fffff
-
-#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
-#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(pdn)  ((pdn) << 22)
-
-#define _READABLE      (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)
-#define _WRITABLE      (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT)
-#define _NONSECURE     (1 << SMMU_PTB_DATA_ASID_NONSECURE_SHIFT)
-#define _PDE_NEXT      (1 << SMMU_PDE_NEXT_SHIFT)
-#define _MASK_ATTR     (_READABLE | _WRITABLE | _NONSECURE)
-
-#define _PDIR_ATTR     (_READABLE | _WRITABLE | _NONSECURE)
-
-#define _PDE_ATTR      (_READABLE | _WRITABLE | _NONSECURE)
-#define _PDE_ATTR_N    (_PDE_ATTR | _PDE_NEXT)
-#define _PDE_VACANT(pdn)       (((pdn) << 10) | _PDE_ATTR)
-
-#define _PTE_ATTR      (_READABLE | _WRITABLE | _NONSECURE)
-#define _PTE_VACANT(addr)      (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR)
-
-#define SMMU_MK_PDIR(page, attr)       \
-               ((page_to_phys(page) >> SMMU_PDIR_SHIFT) | (attr))
-#define SMMU_MK_PDE(page, attr)                \
-               (unsigned long)((page_to_phys(page) >> SMMU_PDE_SHIFT) | (attr))
-#define SMMU_EX_PTBL_PAGE(pde)         \
-               pfn_to_page((unsigned long)(pde) & SMMU_PFN_MASK)
-#define SMMU_PFN_TO_PTE(pfn, attr)     (unsigned long)((pfn) | (attr))
-
-#define SMMU_ASID_ENABLE(asid) ((asid) | (1 << 31))
-#define SMMU_ASID_DISABLE      0
-#define SMMU_ASID_ASID(n)      ((n) & ~SMMU_ASID_ENABLE(0))
-
-#define NUM_SMMU_REG_BANKS     3
-
-#define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1)
-#define smmu_client_disable_hwgrp(c)   smmu_client_set_hwgrp(c, 0, 0)
-#define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1)
-#define __smmu_client_disable_hwgrp(c) __smmu_client_set_hwgrp(c, 0, 0)
-
-#define HWGRP_INIT(client) [HWGRP_##client] = SMMU_##client##_ASID
-
-static const u32 smmu_hwgrp_asid_reg[] = {
-       HWGRP_INIT(AFI),
-       HWGRP_INIT(AVPC),
-       HWGRP_INIT(DC),
-       HWGRP_INIT(DCB),
-       HWGRP_INIT(EPP),
-       HWGRP_INIT(G2),
-       HWGRP_INIT(HC),
-       HWGRP_INIT(HDA),
-       HWGRP_INIT(ISP),
-       HWGRP_INIT(MPE),
-       HWGRP_INIT(NV),
-       HWGRP_INIT(NV2),
-       HWGRP_INIT(PPCS),
-       HWGRP_INIT(SATA),
-       HWGRP_INIT(VDE),
-       HWGRP_INIT(VI),
+       struct list_head list;
 };
-#define HWGRP_ASID_REG(x) (smmu_hwgrp_asid_reg[x])
 
-/*
- * Per client for address space
- */
-struct smmu_client {
-       struct device           *dev;
-       struct list_head        list;
-       struct smmu_as          *as;
-       u32                     hwgrp;
+struct tegra_smmu_as {
+       struct iommu_domain *domain;
+       struct tegra_smmu *smmu;
+       unsigned int use_count;
+       struct page *count;
+       struct page *pd;
+       unsigned id;
+       u32 attr;
 };
 
-/*
- * Per address space
- */
-struct smmu_as {
-       struct smmu_device      *smmu;  /* back pointer to container */
-       unsigned int            asid;
-       spinlock_t              lock;   /* for pagetable */
-       struct page             *pdir_page;
-       unsigned long           pdir_attr;
-       unsigned long           pde_attr;
-       unsigned long           pte_attr;
-       unsigned int            *pte_count;
-
-       struct list_head        client;
-       spinlock_t              client_lock; /* for client list */
-};
+static inline void smmu_writel(struct tegra_smmu *smmu, u32 value,
+                              unsigned long offset)
+{
+       writel(value, smmu->regs + offset);
+}
 
-struct smmu_debugfs_info {
-       struct smmu_device *smmu;
-       int mc;
-       int cache;
-};
+static inline u32 smmu_readl(struct tegra_smmu *smmu, unsigned long offset)
+{
+       return readl(smmu->regs + offset);
+}
 
-/*
- * Per SMMU device - IOMMU device
- */
-struct smmu_device {
-       void __iomem    *regbase;       /* register offset base */
-       void __iomem    **regs;         /* register block start address array */
-       void __iomem    **rege;         /* register block end address array */
-       int             nregs;          /* number of register blocks */
-
-       unsigned long   iovmm_base;     /* remappable base address */
-       unsigned long   page_count;     /* total remappable size */
-       spinlock_t      lock;
-       char            *name;
-       struct device   *dev;
-       struct page *avp_vector_page;   /* dummy page shared by all AS's */
+#define SMMU_CONFIG 0x010
+#define  SMMU_CONFIG_ENABLE (1 << 0)
 
-       /*
-        * Register image savers for suspend/resume
-        */
-       unsigned long translation_enable_0;
-       unsigned long translation_enable_1;
-       unsigned long translation_enable_2;
-       unsigned long asid_security;
+#define SMMU_TLB_CONFIG 0x14
+#define  SMMU_TLB_CONFIG_HIT_UNDER_MISS (1 << 29)
+#define  SMMU_TLB_CONFIG_ROUND_ROBIN_ARBITRATION (1 << 28)
+#define  SMMU_TLB_CONFIG_ACTIVE_LINES(x) ((x) & 0x3f)
 
-       struct dentry *debugfs_root;
-       struct smmu_debugfs_info *debugfs_info;
+#define SMMU_PTC_CONFIG 0x18
+#define  SMMU_PTC_CONFIG_ENABLE (1 << 29)
+#define  SMMU_PTC_CONFIG_REQ_LIMIT(x) (((x) & 0x0f) << 24)
+#define  SMMU_PTC_CONFIG_INDEX_MAP(x) ((x) & 0x3f)
 
-       struct device_node *ahb;
+#define SMMU_PTB_ASID 0x01c
+#define  SMMU_PTB_ASID_VALUE(x) ((x) & 0x7f)
 
-       int             num_as;
-       struct smmu_as  as[0];          /* Run-time allocated array */
-};
+#define SMMU_PTB_DATA 0x020
+#define  SMMU_PTB_DATA_VALUE(page, attr) (page_to_phys(page) >> 12 | (attr))
 
-static struct smmu_device *smmu_handle; /* unique for a system */
+#define SMMU_MK_PDE(page, attr) (page_to_phys(page) >> SMMU_PTE_SHIFT | (attr))
 
-/*
- *     SMMU register accessors
- */
-static bool inline smmu_valid_reg(struct smmu_device *smmu,
-                                 void __iomem *addr)
-{
-       int i;
+#define SMMU_TLB_FLUSH 0x030
+#define  SMMU_TLB_FLUSH_VA_MATCH_ALL     (0 << 0)
+#define  SMMU_TLB_FLUSH_VA_MATCH_SECTION (2 << 0)
+#define  SMMU_TLB_FLUSH_VA_MATCH_GROUP   (3 << 0)
+#define  SMMU_TLB_FLUSH_ASID(x)          (((x) & 0x7f) << 24)
+#define  SMMU_TLB_FLUSH_VA_SECTION(addr) ((((addr) & 0xffc00000) >> 12) | \
+                                         SMMU_TLB_FLUSH_VA_MATCH_SECTION)
+#define  SMMU_TLB_FLUSH_VA_GROUP(addr)   ((((addr) & 0xffffc000) >> 12) | \
+                                         SMMU_TLB_FLUSH_VA_MATCH_GROUP)
+#define  SMMU_TLB_FLUSH_ASID_MATCH       (1 << 31)
 
-       for (i = 0; i < smmu->nregs; i++) {
-               if (addr < smmu->regs[i])
-                       break;
-               if (addr <= smmu->rege[i])
-                       return true;
-       }
+#define SMMU_PTC_FLUSH 0x034
+#define  SMMU_PTC_FLUSH_TYPE_ALL (0 << 0)
+#define  SMMU_PTC_FLUSH_TYPE_ADR (1 << 0)
 
-       return false;
-}
+#define SMMU_PTC_FLUSH_HI 0x9b8
+#define  SMMU_PTC_FLUSH_HI_MASK 0x3
 
-static inline u32 smmu_read(struct smmu_device *smmu, size_t offs)
-{
-       void __iomem *addr = smmu->regbase + offs;
+/* per-SWGROUP SMMU_*_ASID register */
+#define SMMU_ASID_ENABLE (1 << 31)
+#define SMMU_ASID_MASK 0x7f
+#define SMMU_ASID_VALUE(x) ((x) & SMMU_ASID_MASK)
 
-       BUG_ON(!smmu_valid_reg(smmu, addr));
+/* page table definitions */
+#define SMMU_NUM_PDE 1024
+#define SMMU_NUM_PTE 1024
 
-       return readl(addr);
-}
+#define SMMU_SIZE_PD (SMMU_NUM_PDE * 4)
+#define SMMU_SIZE_PT (SMMU_NUM_PTE * 4)
 
-static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs)
-{
-       void __iomem *addr = smmu->regbase + offs;
+#define SMMU_PDE_SHIFT 22
+#define SMMU_PTE_SHIFT 12
 
-       BUG_ON(!smmu_valid_reg(smmu, addr));
+#define SMMU_PFN_MASK 0x000fffff
 
-       writel(val, addr);
-}
+#define SMMU_PD_READABLE       (1 << 31)
+#define SMMU_PD_WRITABLE       (1 << 30)
+#define SMMU_PD_NONSECURE      (1 << 29)
 
-#define VA_PAGE_TO_PA(va, page)        \
-       (page_to_phys(page) + ((unsigned long)(va) & ~PAGE_MASK))
+#define SMMU_PDE_READABLE      (1 << 31)
+#define SMMU_PDE_WRITABLE      (1 << 30)
+#define SMMU_PDE_NONSECURE     (1 << 29)
+#define SMMU_PDE_NEXT          (1 << 28)
 
-#define FLUSH_CPU_DCACHE(va, page, size)       \
-       do {    \
-               unsigned long _pa_ = VA_PAGE_TO_PA(va, page);           \
-               __cpuc_flush_dcache_area((void *)(va), (size_t)(size)); \
-               outer_flush_range(_pa_, _pa_+(size_t)(size));           \
-       } while (0)
+#define SMMU_PTE_READABLE      (1 << 31)
+#define SMMU_PTE_WRITABLE      (1 << 30)
+#define SMMU_PTE_NONSECURE     (1 << 29)
 
-/*
- * Any interaction between any block on PPSB and a block on APB or AHB
- * must have these read-back barriers to ensure the APB/AHB bus
- * transaction is complete before initiating activity on the PPSB
- * block.
- */
-#define FLUSH_SMMU_REGS(smmu)  smmu_read(smmu, SMMU_CONFIG)
+#define SMMU_PDE_ATTR          (SMMU_PDE_READABLE | SMMU_PDE_WRITABLE | \
+                                SMMU_PDE_NONSECURE)
+#define SMMU_PTE_ATTR          (SMMU_PTE_READABLE | SMMU_PTE_WRITABLE | \
+                                SMMU_PTE_NONSECURE)
 
-#define smmu_client_hwgrp(c) (u32)((c)->dev->platform_data)
-
-static int __smmu_client_set_hwgrp(struct smmu_client *c,
-                                  unsigned long map, int on)
+static inline void smmu_flush_ptc(struct tegra_smmu *smmu, struct page *page,
+                                 unsigned long offset)
 {
-       int i;
-       struct smmu_as *as = c->as;
-       u32 val, offs, mask = SMMU_ASID_ENABLE(as->asid);
-       struct smmu_device *smmu = as->smmu;
-
-       WARN_ON(!on && map);
-       if (on && !map)
-               return -EINVAL;
-       if (!on)
-               map = smmu_client_hwgrp(c);
-
-       for_each_set_bit(i, &map, HWGRP_COUNT) {
-               offs = HWGRP_ASID_REG(i);
-               val = smmu_read(smmu, offs);
-               if (on) {
-                       if (WARN_ON(val & mask))
-                               goto err_hw_busy;
-                       val |= mask;
-               } else {
-                       WARN_ON((val & mask) == mask);
-                       val &= ~mask;
+       phys_addr_t phys = page ? page_to_phys(page) : 0;
+       u32 value;
+
+       if (page) {
+               offset &= ~(smmu->mc->soc->atom_size - 1);
+
+               if (smmu->mc->soc->num_address_bits > 32) {
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+                       value = (phys >> 32) & SMMU_PTC_FLUSH_HI_MASK;
+#else
+                       value = 0;
+#endif
+                       smmu_writel(smmu, value, SMMU_PTC_FLUSH_HI);
                }
-               smmu_write(smmu, val, offs);
-       }
-       FLUSH_SMMU_REGS(smmu);
-       c->hwgrp = map;
-       return 0;
 
-err_hw_busy:
-       for_each_set_bit(i, &map, HWGRP_COUNT) {
-               offs = HWGRP_ASID_REG(i);
-               val = smmu_read(smmu, offs);
-               val &= ~mask;
-               smmu_write(smmu, val, offs);
+               value = (phys + offset) | SMMU_PTC_FLUSH_TYPE_ADR;
+       } else {
+               value = SMMU_PTC_FLUSH_TYPE_ALL;
        }
-       return -EBUSY;
+
+       smmu_writel(smmu, value, SMMU_PTC_FLUSH);
 }
 
-static int smmu_client_set_hwgrp(struct smmu_client *c, u32 map, int on)
+static inline void smmu_flush_tlb(struct tegra_smmu *smmu)
 {
-       u32 val;
-       unsigned long flags;
-       struct smmu_as *as = c->as;
-       struct smmu_device *smmu = as->smmu;
-
-       spin_lock_irqsave(&smmu->lock, flags);
-       val = __smmu_client_set_hwgrp(c, map, on);
-       spin_unlock_irqrestore(&smmu->lock, flags);
-       return val;
+       smmu_writel(smmu, SMMU_TLB_FLUSH_VA_MATCH_ALL, SMMU_TLB_FLUSH);
 }
 
-/*
- * Flush all TLB entries and all PTC entries
- * Caller must lock smmu
- */
-static void smmu_flush_regs(struct smmu_device *smmu, int enable)
+static inline void smmu_flush_tlb_asid(struct tegra_smmu *smmu,
+                                      unsigned long asid)
 {
-       u32 val;
-
-       smmu_write(smmu, SMMU_PTC_FLUSH_TYPE_ALL, SMMU_PTC_FLUSH);
-       FLUSH_SMMU_REGS(smmu);
-       val = SMMU_TLB_FLUSH_VA_MATCH_ALL |
-               SMMU_TLB_FLUSH_ASID_MATCH_disable;
-       smmu_write(smmu, val, SMMU_TLB_FLUSH);
+       u32 value;
 
-       if (enable)
-               smmu_write(smmu, SMMU_CONFIG_ENABLE, SMMU_CONFIG);
-       FLUSH_SMMU_REGS(smmu);
+       value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
+               SMMU_TLB_FLUSH_VA_MATCH_ALL;
+       smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
-static int smmu_setup_regs(struct smmu_device *smmu)
+static inline void smmu_flush_tlb_section(struct tegra_smmu *smmu,
+                                         unsigned long asid,
+                                         unsigned long iova)
 {
-       int i;
-       u32 val;
+       u32 value;
 
-       for (i = 0; i < smmu->num_as; i++) {
-               struct smmu_as *as = &smmu->as[i];
-               struct smmu_client *c;
-
-               smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
-               val = as->pdir_page ?
-                       SMMU_MK_PDIR(as->pdir_page, as->pdir_attr) :
-                       SMMU_PTB_DATA_RESET_VAL;
-               smmu_write(smmu, val, SMMU_PTB_DATA);
-
-               list_for_each_entry(c, &as->client, list)
-                       __smmu_client_set_hwgrp(c, c->hwgrp, 1);
-       }
-
-       smmu_write(smmu, smmu->translation_enable_0, SMMU_TRANSLATION_ENABLE_0);
-       smmu_write(smmu, smmu->translation_enable_1, SMMU_TRANSLATION_ENABLE_1);
-       smmu_write(smmu, smmu->translation_enable_2, SMMU_TRANSLATION_ENABLE_2);
-       smmu_write(smmu, smmu->asid_security, SMMU_ASID_SECURITY);
-       smmu_write(smmu, SMMU_TLB_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_TLB));
-       smmu_write(smmu, SMMU_PTC_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_PTC));
-
-       smmu_flush_regs(smmu, 1);
-
-       return tegra_ahb_enable_smmu(smmu->ahb);
+       value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
+               SMMU_TLB_FLUSH_VA_SECTION(iova);
+       smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
-static void flush_ptc_and_tlb(struct smmu_device *smmu,
-                     struct smmu_as *as, dma_addr_t iova,
-                     unsigned long *pte, struct page *page, int is_pde)
+static inline void smmu_flush_tlb_group(struct tegra_smmu *smmu,
+                                       unsigned long asid,
+                                       unsigned long iova)
 {
-       u32 val;
-       unsigned long tlb_flush_va = is_pde
-               ?  SMMU_TLB_FLUSH_VA(iova, SECTION)
-               :  SMMU_TLB_FLUSH_VA(iova, GROUP);
-
-       val = SMMU_PTC_FLUSH_TYPE_ADR | VA_PAGE_TO_PA(pte, page);
-       smmu_write(smmu, val, SMMU_PTC_FLUSH);
-       FLUSH_SMMU_REGS(smmu);
-       val = tlb_flush_va |
-               SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
-               (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
-       smmu_write(smmu, val, SMMU_TLB_FLUSH);
-       FLUSH_SMMU_REGS(smmu);
-}
+       u32 value;
 
-static void free_ptbl(struct smmu_as *as, dma_addr_t iova)
-{
-       unsigned long pdn = SMMU_ADDR_TO_PDN(iova);
-       unsigned long *pdir = (unsigned long *)page_address(as->pdir_page);
-
-       if (pdir[pdn] != _PDE_VACANT(pdn)) {
-               dev_dbg(as->smmu->dev, "pdn: %lx\n", pdn);
-
-               ClearPageReserved(SMMU_EX_PTBL_PAGE(pdir[pdn]));
-               __free_page(SMMU_EX_PTBL_PAGE(pdir[pdn]));
-               pdir[pdn] = _PDE_VACANT(pdn);
-               FLUSH_CPU_DCACHE(&pdir[pdn], as->pdir_page, sizeof pdir[pdn]);
-               flush_ptc_and_tlb(as->smmu, as, iova, &pdir[pdn],
-                                 as->pdir_page, 1);
-       }
+       value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
+               SMMU_TLB_FLUSH_VA_GROUP(iova);
+       smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
-static void free_pdir(struct smmu_as *as)
+static inline void smmu_flush(struct tegra_smmu *smmu)
 {
-       unsigned addr;
-       int count;
-       struct device *dev = as->smmu->dev;
-
-       if (!as->pdir_page)
-               return;
-
-       addr = as->smmu->iovmm_base;
-       count = as->smmu->page_count;
-       while (count-- > 0) {
-               free_ptbl(as, addr);
-               addr += SMMU_PAGE_SIZE * SMMU_PTBL_COUNT;
-       }
-       ClearPageReserved(as->pdir_page);
-       __free_page(as->pdir_page);
-       as->pdir_page = NULL;
-       devm_kfree(dev, as->pte_count);
-       as->pte_count = NULL;
+       smmu_readl(smmu, SMMU_CONFIG);
 }
 
-/*
- * Maps PTBL for given iova and returns the PTE address
- * Caller must unmap the mapped PTBL returned in *ptbl_page_p
- */
-static unsigned long *locate_pte(struct smmu_as *as,
-                                dma_addr_t iova, bool allocate,
-                                struct page **ptbl_page_p,
-                                unsigned int **count)
+static int tegra_smmu_alloc_asid(struct tegra_smmu *smmu, unsigned int *idp)
 {
-       unsigned long ptn = SMMU_ADDR_TO_PFN(iova);
-       unsigned long pdn = SMMU_ADDR_TO_PDN(iova);
-       unsigned long *pdir = page_address(as->pdir_page);
-       unsigned long *ptbl;
-
-       if (pdir[pdn] != _PDE_VACANT(pdn)) {
-               /* Mapped entry table already exists */
-               *ptbl_page_p = SMMU_EX_PTBL_PAGE(pdir[pdn]);
-               ptbl = page_address(*ptbl_page_p);
-       } else if (!allocate) {
-               return NULL;
-       } else {
-               int pn;
-               unsigned long addr = SMMU_PDN_TO_ADDR(pdn);
+       unsigned long id;
 
-               /* Vacant - allocate a new page table */
-               dev_dbg(as->smmu->dev, "New PTBL pdn: %lx\n", pdn);
+       mutex_lock(&smmu->lock);
 
-               *ptbl_page_p = alloc_page(GFP_ATOMIC);
-               if (!*ptbl_page_p) {
-                       dev_err(as->smmu->dev,
-                               "failed to allocate smmu_device page table\n");
-                       return NULL;
-               }
-               SetPageReserved(*ptbl_page_p);
-               ptbl = (unsigned long *)page_address(*ptbl_page_p);
-               for (pn = 0; pn < SMMU_PTBL_COUNT;
-                    pn++, addr += SMMU_PAGE_SIZE) {
-                       ptbl[pn] = _PTE_VACANT(addr);
-               }
-               FLUSH_CPU_DCACHE(ptbl, *ptbl_page_p, SMMU_PTBL_SIZE);
-               pdir[pdn] = SMMU_MK_PDE(*ptbl_page_p,
-                                       as->pde_attr | _PDE_NEXT);
-               FLUSH_CPU_DCACHE(&pdir[pdn], as->pdir_page, sizeof pdir[pdn]);
-               flush_ptc_and_tlb(as->smmu, as, iova, &pdir[pdn],
-                                 as->pdir_page, 1);
+       id = find_first_zero_bit(smmu->asids, smmu->soc->num_asids);
+       if (id >= smmu->soc->num_asids) {
+               mutex_unlock(&smmu->lock);
+               return -ENOSPC;
        }
-       *count = &as->pte_count[pdn];
 
-       return &ptbl[ptn % SMMU_PTBL_COUNT];
+       set_bit(id, smmu->asids);
+       *idp = id;
+
+       mutex_unlock(&smmu->lock);
+       return 0;
 }
 
-#ifdef CONFIG_SMMU_SIG_DEBUG
-static void put_signature(struct smmu_as *as,
-                         dma_addr_t iova, unsigned long pfn)
+static void tegra_smmu_free_asid(struct tegra_smmu *smmu, unsigned int id)
 {
-       struct page *page;
-       unsigned long *vaddr;
-
-       page = pfn_to_page(pfn);
-       vaddr = page_address(page);
-       if (!vaddr)
-               return;
-
-       vaddr[0] = iova;
-       vaddr[1] = pfn << PAGE_SHIFT;
-       FLUSH_CPU_DCACHE(vaddr, page, sizeof(vaddr[0]) * 2);
+       mutex_lock(&smmu->lock);
+       clear_bit(id, smmu->asids);
+       mutex_unlock(&smmu->lock);
 }
-#else
-static inline void put_signature(struct smmu_as *as,
-                                unsigned long addr, unsigned long pfn)
+
+static bool tegra_smmu_capable(enum iommu_cap cap)
 {
+       return false;
 }
-#endif
 
-/*
- * Caller must not hold as->lock
- */
-static int alloc_pdir(struct smmu_as *as)
+static int tegra_smmu_domain_init(struct iommu_domain *domain)
 {
-       unsigned long *pdir, flags;
-       int pdn, err = 0;
-       u32 val;
-       struct smmu_device *smmu = as->smmu;
-       struct page *page;
-       unsigned int *cnt;
+       struct tegra_smmu_as *as;
+       unsigned int i;
+       uint32_t *pd;
 
-       /*
-        * do the allocation, then grab as->lock
-        */
-       cnt = devm_kzalloc(smmu->dev,
-                          sizeof(cnt[0]) * SMMU_PDIR_COUNT,
-                          GFP_KERNEL);
-       page = alloc_page(GFP_KERNEL | __GFP_DMA);
+       as = kzalloc(sizeof(*as), GFP_KERNEL);
+       if (!as)
+               return -ENOMEM;
 
-       spin_lock_irqsave(&as->lock, flags);
+       as->attr = SMMU_PD_READABLE | SMMU_PD_WRITABLE | SMMU_PD_NONSECURE;
+       as->domain = domain;
 
-       if (as->pdir_page) {
-               /* We raced, free the redundant */
-               err = -EAGAIN;
-               goto err_out;
+       as->pd = alloc_page(GFP_KERNEL | __GFP_DMA);
+       if (!as->pd) {
+               kfree(as);
+               return -ENOMEM;
        }
 
-       if (!page || !cnt) {
-               dev_err(smmu->dev, "failed to allocate at %s\n", __func__);
-               err = -ENOMEM;
-               goto err_out;
+       as->count = alloc_page(GFP_KERNEL);
+       if (!as->count) {
+               __free_page(as->pd);
+               kfree(as);
+               return -ENOMEM;
        }
 
-       as->pdir_page = page;
-       as->pte_count = cnt;
+       /* clear PDEs */
+       pd = page_address(as->pd);
+       SetPageReserved(as->pd);
 
-       SetPageReserved(as->pdir_page);
-       pdir = page_address(as->pdir_page);
+       for (i = 0; i < SMMU_NUM_PDE; i++)
+               pd[i] = 0;
 
-       for (pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++)
-               pdir[pdn] = _PDE_VACANT(pdn);
-       FLUSH_CPU_DCACHE(pdir, as->pdir_page, SMMU_PDIR_SIZE);
-       val = SMMU_PTC_FLUSH_TYPE_ADR | VA_PAGE_TO_PA(pdir, as->pdir_page);
-       smmu_write(smmu, val, SMMU_PTC_FLUSH);
-       FLUSH_SMMU_REGS(as->smmu);
-       val = SMMU_TLB_FLUSH_VA_MATCH_ALL |
-               SMMU_TLB_FLUSH_ASID_MATCH__ENABLE |
-               (as->asid << SMMU_TLB_FLUSH_ASID_SHIFT);
-       smmu_write(smmu, val, SMMU_TLB_FLUSH);
-       FLUSH_SMMU_REGS(as->smmu);
+       /* clear PDE usage counters */
+       pd = page_address(as->count);
+       SetPageReserved(as->count);
 
-       spin_unlock_irqrestore(&as->lock, flags);
-
-       return 0;
+       for (i = 0; i < SMMU_NUM_PDE; i++)
+               pd[i] = 0;
 
-err_out:
-       spin_unlock_irqrestore(&as->lock, flags);
+       domain->priv = as;
 
-       devm_kfree(smmu->dev, cnt);
-       if (page)
-               __free_page(page);
-       return err;
+       return 0;
 }
 
-static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova)
+static void tegra_smmu_domain_destroy(struct iommu_domain *domain)
 {
-       unsigned long *pte;
-       struct page *page;
-       unsigned int *count;
+       struct tegra_smmu_as *as = domain->priv;
 
-       pte = locate_pte(as, iova, false, &page, &count);
-       if (WARN_ON(!pte))
-               return;
+       /* TODO: free page directory and page tables */
+       ClearPageReserved(as->pd);
 
-       if (WARN_ON(*pte == _PTE_VACANT(iova)))
-               return;
-
-       *pte = _PTE_VACANT(iova);
-       FLUSH_CPU_DCACHE(pte, page, sizeof(*pte));
-       flush_ptc_and_tlb(as->smmu, as, iova, pte, page, 0);
-       if (!--(*count))
-               free_ptbl(as, iova);
+       kfree(as);
 }
 
-static void __smmu_iommu_map_pfn(struct smmu_as *as, dma_addr_t iova,
-                                unsigned long pfn)
+static const struct tegra_smmu_swgroup *
+tegra_smmu_find_swgroup(struct tegra_smmu *smmu, unsigned int swgroup)
 {
-       struct smmu_device *smmu = as->smmu;
-       unsigned long *pte;
-       unsigned int *count;
-       struct page *page;
+       const struct tegra_smmu_swgroup *group = NULL;
+       unsigned int i;
 
-       pte = locate_pte(as, iova, true, &page, &count);
-       if (WARN_ON(!pte))
-               return;
+       for (i = 0; i < smmu->soc->num_swgroups; i++) {
+               if (smmu->soc->swgroups[i].swgroup == swgroup) {
+                       group = &smmu->soc->swgroups[i];
+                       break;
+               }
+       }
 
-       if (*pte == _PTE_VACANT(iova))
-               (*count)++;
-       *pte = SMMU_PFN_TO_PTE(pfn, as->pte_attr);
-       if (unlikely((*pte == _PTE_VACANT(iova))))
-               (*count)--;
-       FLUSH_CPU_DCACHE(pte, page, sizeof(*pte));
-       flush_ptc_and_tlb(smmu, as, iova, pte, page, 0);
-       put_signature(as, iova, pfn);
+       return group;
 }
 
-static int smmu_iommu_map(struct iommu_domain *domain, unsigned long iova,
-                         phys_addr_t pa, size_t bytes, int prot)
+static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup,
+                             unsigned int asid)
 {
-       struct smmu_as *as = domain->priv;
-       unsigned long pfn = __phys_to_pfn(pa);
-       unsigned long flags;
+       const struct tegra_smmu_swgroup *group;
+       unsigned int i;
+       u32 value;
 
-       dev_dbg(as->smmu->dev, "[%d] %08lx:%pa\n", as->asid, iova, &pa);
+       for (i = 0; i < smmu->soc->num_clients; i++) {
+               const struct tegra_mc_client *client = &smmu->soc->clients[i];
 
-       if (!pfn_valid(pfn))
-               return -ENOMEM;
-
-       spin_lock_irqsave(&as->lock, flags);
-       __smmu_iommu_map_pfn(as, iova, pfn);
-       spin_unlock_irqrestore(&as->lock, flags);
-       return 0;
-}
-
-static size_t smmu_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
-                              size_t bytes)
-{
-       struct smmu_as *as = domain->priv;
-       unsigned long flags;
+               if (client->swgroup != swgroup)
+                       continue;
 
-       dev_dbg(as->smmu->dev, "[%d] %08lx\n", as->asid, iova);
+               value = smmu_readl(smmu, client->smmu.reg);
+               value |= BIT(client->smmu.bit);
+               smmu_writel(smmu, value, client->smmu.reg);
+       }
 
-       spin_lock_irqsave(&as->lock, flags);
-       __smmu_iommu_unmap(as, iova);
-       spin_unlock_irqrestore(&as->lock, flags);
-       return SMMU_PAGE_SIZE;
+       group = tegra_smmu_find_swgroup(smmu, swgroup);
+       if (group) {
+               value = smmu_readl(smmu, group->reg);
+               value &= ~SMMU_ASID_MASK;
+               value |= SMMU_ASID_VALUE(asid);
+               value |= SMMU_ASID_ENABLE;
+               smmu_writel(smmu, value, group->reg);
+       }
 }
 
-static phys_addr_t smmu_iommu_iova_to_phys(struct iommu_domain *domain,
-                                          dma_addr_t iova)
+static void tegra_smmu_disable(struct tegra_smmu *smmu, unsigned int swgroup,
+                              unsigned int asid)
 {
-       struct smmu_as *as = domain->priv;
-       unsigned long *pte;
-       unsigned int *count;
-       struct page *page;
-       unsigned long pfn;
-       unsigned long flags;
+       const struct tegra_smmu_swgroup *group;
+       unsigned int i;
+       u32 value;
 
-       spin_lock_irqsave(&as->lock, flags);
+       group = tegra_smmu_find_swgroup(smmu, swgroup);
+       if (group) {
+               value = smmu_readl(smmu, group->reg);
+               value &= ~SMMU_ASID_MASK;
+               value |= SMMU_ASID_VALUE(asid);
+               value &= ~SMMU_ASID_ENABLE;
+               smmu_writel(smmu, value, group->reg);
+       }
 
-       pte = locate_pte(as, iova, true, &page, &count);
-       pfn = *pte & SMMU_PFN_MASK;
-       WARN_ON(!pfn_valid(pfn));
-       dev_dbg(as->smmu->dev,
-               "iova:%08llx pfn:%08lx asid:%d\n", (unsigned long long)iova,
-                pfn, as->asid);
+       for (i = 0; i < smmu->soc->num_clients; i++) {
+               const struct tegra_mc_client *client = &smmu->soc->clients[i];
 
-       spin_unlock_irqrestore(&as->lock, flags);
-       return PFN_PHYS(pfn);
-}
+               if (client->swgroup != swgroup)
+                       continue;
 
-static bool smmu_iommu_capable(enum iommu_cap cap)
-{
-       return false;
+               value = smmu_readl(smmu, client->smmu.reg);
+               value &= ~BIT(client->smmu.bit);
+               smmu_writel(smmu, value, client->smmu.reg);
+       }
 }
 
-static int smmu_iommu_attach_dev(struct iommu_domain *domain,
-                                struct device *dev)
+static int tegra_smmu_as_prepare(struct tegra_smmu *smmu,
+                                struct tegra_smmu_as *as)
 {
-       struct smmu_as *as = domain->priv;
-       struct smmu_device *smmu = as->smmu;
-       struct smmu_client *client, *c;
-       u32 map;
+       u32 value;
        int err;
 
-       client = devm_kzalloc(smmu->dev, sizeof(*c), GFP_KERNEL);
-       if (!client)
-               return -ENOMEM;
-       client->dev = dev;
-       client->as = as;
-       map = (unsigned long)dev->platform_data;
-       if (!map)
-               return -EINVAL;
-
-       err = smmu_client_enable_hwgrp(client, map);
-       if (err)
-               goto err_hwgrp;
-
-       spin_lock(&as->client_lock);
-       list_for_each_entry(c, &as->client, list) {
-               if (c->dev == dev) {
-                       dev_err(smmu->dev,
-                               "%s is already attached\n", dev_name(c->dev));
-                       err = -EINVAL;
-                       goto err_client;
-               }
+       if (as->use_count > 0) {
+               as->use_count++;
+               return 0;
        }
-       list_add(&client->list, &as->client);
-       spin_unlock(&as->client_lock);
 
-       /*
-        * Reserve "page zero" for AVP vectors using a common dummy
-        * page.
-        */
-       if (map & HWG_AVPC) {
-               struct page *page;
+       err = tegra_smmu_alloc_asid(smmu, &as->id);
+       if (err < 0)
+               return err;
 
-               page = as->smmu->avp_vector_page;
-               __smmu_iommu_map_pfn(as, 0, page_to_pfn(page));
+       smmu->soc->ops->flush_dcache(as->pd, 0, SMMU_SIZE_PD);
+       smmu_flush_ptc(smmu, as->pd, 0);
+       smmu_flush_tlb_asid(smmu, as->id);
 
-               pr_info("Reserve \"page zero\" for AVP vectors using a common dummy\n");
-       }
+       smmu_writel(smmu, as->id & 0x7f, SMMU_PTB_ASID);
+       value = SMMU_PTB_DATA_VALUE(as->pd, as->attr);
+       smmu_writel(smmu, value, SMMU_PTB_DATA);
+       smmu_flush(smmu);
 
-       dev_dbg(smmu->dev, "%s is attached\n", dev_name(dev));
-       return 0;
+       as->smmu = smmu;
+       as->use_count++;
 
-err_client:
-       smmu_client_disable_hwgrp(client);
-       spin_unlock(&as->client_lock);
-err_hwgrp:
-       devm_kfree(smmu->dev, client);
-       return err;
+       return 0;
 }
 
-static void smmu_iommu_detach_dev(struct iommu_domain *domain,
-                                 struct device *dev)
+static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu,
+                                   struct tegra_smmu_as *as)
 {
-       struct smmu_as *as = domain->priv;
-       struct smmu_device *smmu = as->smmu;
-       struct smmu_client *c;
-
-       spin_lock(&as->client_lock);
-
-       list_for_each_entry(c, &as->client, list) {
-               if (c->dev == dev) {
-                       smmu_client_disable_hwgrp(c);
-                       list_del(&c->list);
-                       devm_kfree(smmu->dev, c);
-                       c->as = NULL;
-                       dev_dbg(smmu->dev,
-                               "%s is detached\n", dev_name(c->dev));
-                       goto out;
-               }
-       }
-       dev_err(smmu->dev, "Couldn't find %s\n", dev_name(dev));
-out:
-       spin_unlock(&as->client_lock);
+       if (--as->use_count > 0)
+               return;
+
+       tegra_smmu_free_asid(smmu, as->id);
+       as->smmu = NULL;
 }
 
-static int smmu_iommu_domain_init(struct iommu_domain *domain)
+static int tegra_smmu_attach_dev(struct iommu_domain *domain,
+                                struct device *dev)
 {
-       int i, err = -EAGAIN;
-       unsigned long flags;
-       struct smmu_as *as;
-       struct smmu_device *smmu = smmu_handle;
+       struct tegra_smmu *smmu = dev->archdata.iommu;
+       struct tegra_smmu_as *as = domain->priv;
+       struct device_node *np = dev->of_node;
+       struct of_phandle_args args;
+       unsigned int index = 0;
+       int err = 0;
 
-       /* Look for a free AS with lock held */
-       for  (i = 0; i < smmu->num_as; i++) {
-               as = &smmu->as[i];
+       while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
+                                          &args)) {
+               unsigned int swgroup = args.args[0];
 
-               if (as->pdir_page)
+               if (args.np != smmu->dev->of_node) {
+                       of_node_put(args.np);
                        continue;
+               }
 
-               err = alloc_pdir(as);
-               if (!err)
-                       goto found;
+               of_node_put(args.np);
 
-               if (err != -EAGAIN)
-                       break;
+               err = tegra_smmu_as_prepare(smmu, as);
+               if (err < 0)
+                       return err;
+
+               tegra_smmu_enable(smmu, swgroup, as->id);
+               index++;
        }
-       if (i == smmu->num_as)
-               dev_err(smmu->dev,  "no free AS\n");
-       return err;
 
-found:
-       spin_lock_irqsave(&smmu->lock, flags);
+       if (index == 0)
+               return -ENODEV;
 
-       /* Update PDIR register */
-       smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
-       smmu_write(smmu,
-                  SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA);
-       FLUSH_SMMU_REGS(smmu);
+       return 0;
+}
 
-       spin_unlock_irqrestore(&smmu->lock, flags);
+static void tegra_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
+{
+       struct tegra_smmu_as *as = domain->priv;
+       struct device_node *np = dev->of_node;
+       struct tegra_smmu *smmu = as->smmu;
+       struct of_phandle_args args;
+       unsigned int index = 0;
 
-       domain->priv = as;
+       while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
+                                          &args)) {
+               unsigned int swgroup = args.args[0];
 
-       domain->geometry.aperture_start = smmu->iovmm_base;
-       domain->geometry.aperture_end   = smmu->iovmm_base +
-               smmu->page_count * SMMU_PAGE_SIZE - 1;
-       domain->geometry.force_aperture = true;
+               if (args.np != smmu->dev->of_node) {
+                       of_node_put(args.np);
+                       continue;
+               }
 
-       dev_dbg(smmu->dev, "smmu_as@%p\n", as);
+               of_node_put(args.np);
 
-       return 0;
+               tegra_smmu_disable(smmu, swgroup, as->id);
+               tegra_smmu_as_unprepare(smmu, as);
+               index++;
+       }
 }
 
-static void smmu_iommu_domain_destroy(struct iommu_domain *domain)
+static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova,
+                      struct page **pagep)
 {
-       struct smmu_as *as = domain->priv;
-       struct smmu_device *smmu = as->smmu;
-       unsigned long flags;
+       u32 *pd = page_address(as->pd), *pt, *count;
+       u32 pde = (iova >> SMMU_PDE_SHIFT) & 0x3ff;
+       u32 pte = (iova >> SMMU_PTE_SHIFT) & 0x3ff;
+       struct tegra_smmu *smmu = as->smmu;
+       struct page *page;
+       unsigned int i;
+
+       if (pd[pde] == 0) {
+               page = alloc_page(GFP_KERNEL | __GFP_DMA);
+               if (!page)
+                       return NULL;
 
-       spin_lock_irqsave(&as->lock, flags);
+               pt = page_address(page);
+               SetPageReserved(page);
 
-       if (as->pdir_page) {
-               spin_lock(&smmu->lock);
-               smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
-               smmu_write(smmu, SMMU_PTB_DATA_RESET_VAL, SMMU_PTB_DATA);
-               FLUSH_SMMU_REGS(smmu);
-               spin_unlock(&smmu->lock);
+               for (i = 0; i < SMMU_NUM_PTE; i++)
+                       pt[i] = 0;
 
-               free_pdir(as);
-       }
+               smmu->soc->ops->flush_dcache(page, 0, SMMU_SIZE_PT);
 
-       if (!list_empty(&as->client)) {
-               struct smmu_client *c;
+               pd[pde] = SMMU_MK_PDE(page, SMMU_PDE_ATTR | SMMU_PDE_NEXT);
 
-               list_for_each_entry(c, &as->client, list)
-                       smmu_iommu_detach_dev(domain, c->dev);
+               smmu->soc->ops->flush_dcache(as->pd, pde << 2, 4);
+               smmu_flush_ptc(smmu, as->pd, pde << 2);
+               smmu_flush_tlb_section(smmu, as->id, iova);
+               smmu_flush(smmu);
+       } else {
+               page = pfn_to_page(pd[pde] & SMMU_PFN_MASK);
+               pt = page_address(page);
        }
 
-       spin_unlock_irqrestore(&as->lock, flags);
+       *pagep = page;
 
-       domain->priv = NULL;
-       dev_dbg(smmu->dev, "smmu_as@%p\n", as);
-}
+       /* Keep track of entries in this page table. */
+       count = page_address(as->count);
+       if (pt[pte] == 0)
+               count[pde]++;
 
-static const struct iommu_ops smmu_iommu_ops = {
-       .capable        = smmu_iommu_capable,
-       .domain_init    = smmu_iommu_domain_init,
-       .domain_destroy = smmu_iommu_domain_destroy,
-       .attach_dev     = smmu_iommu_attach_dev,
-       .detach_dev     = smmu_iommu_detach_dev,
-       .map            = smmu_iommu_map,
-       .unmap          = smmu_iommu_unmap,
-       .iova_to_phys   = smmu_iommu_iova_to_phys,
-       .pgsize_bitmap  = SMMU_IOMMU_PGSIZES,
-};
-
-/* Should be in the order of enum */
-static const char * const smmu_debugfs_mc[] = { "mc", };
-static const char * const smmu_debugfs_cache[] = {  "tlb", "ptc", };
+       return &pt[pte];
+}
 
-static ssize_t smmu_debugfs_stats_write(struct file *file,
-                                       const char __user *buffer,
-                                       size_t count, loff_t *pos)
+static void as_put_pte(struct tegra_smmu_as *as, dma_addr_t iova)
 {
-       struct smmu_debugfs_info *info;
-       struct smmu_device *smmu;
-       int i;
-       enum {
-               _OFF = 0,
-               _ON,
-               _RESET,
-       };
-       const char * const command[] = {
-               [_OFF]          = "off",
-               [_ON]           = "on",
-               [_RESET]        = "reset",
-       };
-       char str[] = "reset";
-       u32 val;
-       size_t offs;
+       u32 pde = (iova >> SMMU_PDE_SHIFT) & 0x3ff;
+       u32 pte = (iova >> SMMU_PTE_SHIFT) & 0x3ff;
+       u32 *count = page_address(as->count);
+       u32 *pd = page_address(as->pd), *pt;
+       struct page *page;
 
-       count = min_t(size_t, count, sizeof(str));
-       if (copy_from_user(str, buffer, count))
-               return -EINVAL;
+       page = pfn_to_page(pd[pde] & SMMU_PFN_MASK);
+       pt = page_address(page);
 
-       for (i = 0; i < ARRAY_SIZE(command); i++)
-               if (strncmp(str, command[i],
-                           strlen(command[i])) == 0)
-                       break;
+       /*
+        * When no entries in this page table are used anymore, return the
+        * memory page to the system.
+        */
+       if (pt[pte] != 0) {
+               if (--count[pde] == 0) {
+                       ClearPageReserved(page);
+                       __free_page(page);
+                       pd[pde] = 0;
+               }
 
-       if (i == ARRAY_SIZE(command))
-               return -EINVAL;
-
-       info = file_inode(file)->i_private;
-       smmu = info->smmu;
-
-       offs = SMMU_CACHE_CONFIG(info->cache);
-       val = smmu_read(smmu, offs);
-       switch (i) {
-       case _OFF:
-               val &= ~SMMU_CACHE_CONFIG_STATS_ENABLE;
-               val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
-               smmu_write(smmu, val, offs);
-               break;
-       case _ON:
-               val |= SMMU_CACHE_CONFIG_STATS_ENABLE;
-               val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
-               smmu_write(smmu, val, offs);
-               break;
-       case _RESET:
-               val |= SMMU_CACHE_CONFIG_STATS_TEST;
-               smmu_write(smmu, val, offs);
-               val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
-               smmu_write(smmu, val, offs);
-               break;
-       default:
-               BUG();
-               break;
+               pt[pte] = 0;
        }
-
-       dev_dbg(smmu->dev, "%s() %08x, %08x @%08x\n", __func__,
-               val, smmu_read(smmu, offs), offs);
-
-       return count;
 }
 
-static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
+static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova,
+                         phys_addr_t paddr, size_t size, int prot)
 {
-       struct smmu_debugfs_info *info = s->private;
-       struct smmu_device *smmu = info->smmu;
-       int i;
-       const char * const stats[] = { "hit", "miss", };
+       struct tegra_smmu_as *as = domain->priv;
+       struct tegra_smmu *smmu = as->smmu;
+       unsigned long offset;
+       struct page *page;
+       u32 *pte;
 
+       pte = as_get_pte(as, iova, &page);
+       if (!pte)
+               return -ENOMEM;
 
-       for (i = 0; i < ARRAY_SIZE(stats); i++) {
-               u32 val;
-               size_t offs;
+       *pte = __phys_to_pfn(paddr) | SMMU_PTE_ATTR;
+       offset = offset_in_page(pte);
 
-               offs = SMMU_STATS_CACHE_COUNT(info->mc, info->cache, i);
-               val = smmu_read(smmu, offs);
-               seq_printf(s, "%s:%08x ", stats[i], val);
+       smmu->soc->ops->flush_dcache(page, offset, 4);
+       smmu_flush_ptc(smmu, page, offset);
+       smmu_flush_tlb_group(smmu, as->id, iova);
+       smmu_flush(smmu);
 
-               dev_dbg(smmu->dev, "%s() %s %08x @%08x\n", __func__,
-                       stats[i], val, offs);
-       }
-       seq_printf(s, "\n");
        return 0;
 }
 
-static int smmu_debugfs_stats_open(struct inode *inode, struct file *file)
+static size_t tegra_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
+                              size_t size)
 {
-       return single_open(file, smmu_debugfs_stats_show, inode->i_private);
-}
+       struct tegra_smmu_as *as = domain->priv;
+       struct tegra_smmu *smmu = as->smmu;
+       unsigned long offset;
+       struct page *page;
+       u32 *pte;
 
-static const struct file_operations smmu_debugfs_stats_fops = {
-       .open           = smmu_debugfs_stats_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = smmu_debugfs_stats_write,
-};
+       pte = as_get_pte(as, iova, &page);
+       if (!pte)
+               return 0;
 
-static void smmu_debugfs_delete(struct smmu_device *smmu)
-{
-       debugfs_remove_recursive(smmu->debugfs_root);
-       kfree(smmu->debugfs_info);
+       offset = offset_in_page(pte);
+       as_put_pte(as, iova);
+
+       smmu->soc->ops->flush_dcache(page, offset, 4);
+       smmu_flush_ptc(smmu, page, offset);
+       smmu_flush_tlb_group(smmu, as->id, iova);
+       smmu_flush(smmu);
+
+       return size;
 }
 
-static void smmu_debugfs_create(struct smmu_device *smmu)
+static phys_addr_t tegra_smmu_iova_to_phys(struct iommu_domain *domain,
+                                          dma_addr_t iova)
 {
-       int i;
-       size_t bytes;
-       struct dentry *root;
-
-       bytes = ARRAY_SIZE(smmu_debugfs_mc) * ARRAY_SIZE(smmu_debugfs_cache) *
-               sizeof(*smmu->debugfs_info);
-       smmu->debugfs_info = kmalloc(bytes, GFP_KERNEL);
-       if (!smmu->debugfs_info)
-               return;
-
-       root = debugfs_create_dir(dev_name(smmu->dev), NULL);
-       if (!root)
-               goto err_out;
-       smmu->debugfs_root = root;
-
-       for (i = 0; i < ARRAY_SIZE(smmu_debugfs_mc); i++) {
-               int j;
-               struct dentry *mc;
-
-               mc = debugfs_create_dir(smmu_debugfs_mc[i], root);
-               if (!mc)
-                       goto err_out;
-
-               for (j = 0; j < ARRAY_SIZE(smmu_debugfs_cache); j++) {
-                       struct dentry *cache;
-                       struct smmu_debugfs_info *info;
-
-                       info = smmu->debugfs_info;
-                       info += i * ARRAY_SIZE(smmu_debugfs_mc) + j;
-                       info->smmu = smmu;
-                       info->mc = i;
-                       info->cache = j;
-
-                       cache = debugfs_create_file(smmu_debugfs_cache[j],
-                                                   S_IWUGO | S_IRUGO, mc,
-                                                   (void *)info,
-                                                   &smmu_debugfs_stats_fops);
-                       if (!cache)
-                               goto err_out;
-               }
-       }
+       struct tegra_smmu_as *as = domain->priv;
+       struct page *page;
+       unsigned long pfn;
+       u32 *pte;
 
-       return;
+       pte = as_get_pte(as, iova, &page);
+       pfn = *pte & SMMU_PFN_MASK;
 
-err_out:
-       smmu_debugfs_delete(smmu);
+       return PFN_PHYS(pfn);
 }
 
-static int tegra_smmu_suspend(struct device *dev)
+static struct tegra_smmu *tegra_smmu_find(struct device_node *np)
 {
-       struct smmu_device *smmu = dev_get_drvdata(dev);
+       struct platform_device *pdev;
+       struct tegra_mc *mc;
 
-       smmu->translation_enable_0 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_0);
-       smmu->translation_enable_1 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_1);
-       smmu->translation_enable_2 = smmu_read(smmu, SMMU_TRANSLATION_ENABLE_2);
-       smmu->asid_security = smmu_read(smmu, SMMU_ASID_SECURITY);
-       return 0;
+       pdev = of_find_device_by_node(np);
+       if (!pdev)
+               return NULL;
+
+       mc = platform_get_drvdata(pdev);
+       if (!mc)
+               return NULL;
+
+       return mc->smmu;
 }
 
-static int tegra_smmu_resume(struct device *dev)
+static int tegra_smmu_add_device(struct device *dev)
 {
-       struct smmu_device *smmu = dev_get_drvdata(dev);
-       unsigned long flags;
-       int err;
+       struct device_node *np = dev->of_node;
+       struct of_phandle_args args;
+       unsigned int index = 0;
 
-       spin_lock_irqsave(&smmu->lock, flags);
-       err = smmu_setup_regs(smmu);
-       spin_unlock_irqrestore(&smmu->lock, flags);
-       return err;
+       while (of_parse_phandle_with_args(np, "iommus", "#iommu-cells", index,
+                                         &args) == 0) {
+               struct tegra_smmu *smmu;
+
+               smmu = tegra_smmu_find(args.np);
+               if (smmu) {
+                       /*
+                        * Only a single IOMMU master interface is currently
+                        * supported by the Linux kernel, so abort after the
+                        * first match.
+                        */
+                       dev->archdata.iommu = smmu;
+                       break;
+               }
+
+               index++;
+       }
+
+       return 0;
 }
 
-static int tegra_smmu_probe(struct platform_device *pdev)
+static void tegra_smmu_remove_device(struct device *dev)
 {
-       struct smmu_device *smmu;
-       struct device *dev = &pdev->dev;
-       int i, asids, err = 0;
-       dma_addr_t uninitialized_var(base);
-       size_t bytes, uninitialized_var(size);
+       dev->archdata.iommu = NULL;
+}
 
-       if (smmu_handle)
-               return -EIO;
+static const struct iommu_ops tegra_smmu_ops = {
+       .capable = tegra_smmu_capable,
+       .domain_init = tegra_smmu_domain_init,
+       .domain_destroy = tegra_smmu_domain_destroy,
+       .attach_dev = tegra_smmu_attach_dev,
+       .detach_dev = tegra_smmu_detach_dev,
+       .add_device = tegra_smmu_add_device,
+       .remove_device = tegra_smmu_remove_device,
+       .map = tegra_smmu_map,
+       .unmap = tegra_smmu_unmap,
+       .map_sg = default_iommu_map_sg,
+       .iova_to_phys = tegra_smmu_iova_to_phys,
 
-       BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT);
+       .pgsize_bitmap = SZ_4K,
+};
 
-       if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids))
-               return -ENODEV;
+static void tegra_smmu_ahb_enable(void)
+{
+       static const struct of_device_id ahb_match[] = {
+               { .compatible = "nvidia,tegra30-ahb", },
+               { }
+       };
+       struct device_node *ahb;
 
-       bytes = sizeof(*smmu) + asids * sizeof(*smmu->as);
-       smmu = devm_kzalloc(dev, bytes, GFP_KERNEL);
-       if (!smmu) {
-               dev_err(dev, "failed to allocate smmu_device\n");
-               return -ENOMEM;
+       ahb = of_find_matching_node(NULL, ahb_match);
+       if (ahb) {
+               tegra_ahb_enable_smmu(ahb);
+               of_node_put(ahb);
        }
+}
 
-       smmu->nregs = pdev->num_resources;
-       smmu->regs = devm_kzalloc(dev, 2 * smmu->nregs * sizeof(*smmu->regs),
-                                 GFP_KERNEL);
-       smmu->rege = smmu->regs + smmu->nregs;
-       if (!smmu->regs)
-               return -ENOMEM;
-       for (i = 0; i < smmu->nregs; i++) {
-               struct resource *res;
-
-               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               smmu->regs[i] = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(smmu->regs[i]))
-                       return PTR_ERR(smmu->regs[i]);
-               smmu->rege[i] = smmu->regs[i] + resource_size(res) - 1;
-       }
-       /* Same as "mc" 1st regiter block start address */
-       smmu->regbase = (void __iomem *)((u32)smmu->regs[0] & PAGE_MASK);
+struct tegra_smmu *tegra_smmu_probe(struct device *dev,
+                                   const struct tegra_smmu_soc *soc,
+                                   struct tegra_mc *mc)
+{
+       struct tegra_smmu *smmu;
+       size_t size;
+       u32 value;
+       int err;
 
-       err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size);
-       if (err)
-               return -ENODEV;
+       /* This can happen on Tegra20 which doesn't have an SMMU */
+       if (!soc)
+               return NULL;
 
-       if (size & SMMU_PAGE_MASK)
-               return -EINVAL;
+       smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
+       if (!smmu)
+               return ERR_PTR(-ENOMEM);
 
-       size >>= SMMU_PAGE_SHIFT;
-       if (!size)
-               return -EINVAL;
+       /*
+        * This is a bit of a hack. Ideally we'd want to simply return this
+        * value. However the IOMMU registration process will attempt to add
+        * all devices to the IOMMU when bus_set_iommu() is called. In order
+        * not to rely on global variables to track the IOMMU instance, we
+        * set it here so that it can be looked up from the .add_device()
+        * callback via the IOMMU device's .drvdata field.
+        */
+       mc->smmu = smmu;
 
-       smmu->ahb = of_parse_phandle(dev->of_node, "nvidia,ahb", 0);
-       if (!smmu->ahb)
-               return -ENODEV;
+       size = BITS_TO_LONGS(soc->num_asids) * sizeof(long);
 
-       smmu->dev = dev;
-       smmu->num_as = asids;
-       smmu->iovmm_base = base;
-       smmu->page_count = size;
-
-       smmu->translation_enable_0 = ~0;
-       smmu->translation_enable_1 = ~0;
-       smmu->translation_enable_2 = ~0;
-       smmu->asid_security = 0;
-
-       for (i = 0; i < smmu->num_as; i++) {
-               struct smmu_as *as = &smmu->as[i];
-
-               as->smmu = smmu;
-               as->asid = i;
-               as->pdir_attr = _PDIR_ATTR;
-               as->pde_attr = _PDE_ATTR;
-               as->pte_attr = _PTE_ATTR;
-
-               spin_lock_init(&as->lock);
-               spin_lock_init(&as->client_lock);
-               INIT_LIST_HEAD(&as->client);
-       }
-       spin_lock_init(&smmu->lock);
-       err = smmu_setup_regs(smmu);
-       if (err)
-               return err;
-       platform_set_drvdata(pdev, smmu);
+       smmu->asids = devm_kzalloc(dev, size, GFP_KERNEL);
+       if (!smmu->asids)
+               return ERR_PTR(-ENOMEM);
 
-       smmu->avp_vector_page = alloc_page(GFP_KERNEL);
-       if (!smmu->avp_vector_page)
-               return -ENOMEM;
+       mutex_init(&smmu->lock);
 
-       smmu_debugfs_create(smmu);
-       smmu_handle = smmu;
-       bus_set_iommu(&platform_bus_type, &smmu_iommu_ops);
-       return 0;
-}
+       smmu->regs = mc->regs;
+       smmu->soc = soc;
+       smmu->dev = dev;
+       smmu->mc = mc;
 
-static int tegra_smmu_remove(struct platform_device *pdev)
-{
-       struct smmu_device *smmu = platform_get_drvdata(pdev);
-       int i;
+       value = SMMU_PTC_CONFIG_ENABLE | SMMU_PTC_CONFIG_INDEX_MAP(0x3f);
 
-       smmu_debugfs_delete(smmu);
+       if (soc->supports_request_limit)
+               value |= SMMU_PTC_CONFIG_REQ_LIMIT(8);
 
-       smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG);
-       for (i = 0; i < smmu->num_as; i++)
-               free_pdir(&smmu->as[i]);
-       __free_page(smmu->avp_vector_page);
-       smmu_handle = NULL;
-       return 0;
-}
+       smmu_writel(smmu, value, SMMU_PTC_CONFIG);
 
-static const struct dev_pm_ops tegra_smmu_pm_ops = {
-       .suspend        = tegra_smmu_suspend,
-       .resume         = tegra_smmu_resume,
-};
+       value = SMMU_TLB_CONFIG_HIT_UNDER_MISS |
+               SMMU_TLB_CONFIG_ACTIVE_LINES(0x20);
 
-static const struct of_device_id tegra_smmu_of_match[] = {
-       { .compatible = "nvidia,tegra30-smmu", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, tegra_smmu_of_match);
-
-static struct platform_driver tegra_smmu_driver = {
-       .probe          = tegra_smmu_probe,
-       .remove         = tegra_smmu_remove,
-       .driver = {
-               .owner  = THIS_MODULE,
-               .name   = "tegra-smmu",
-               .pm     = &tegra_smmu_pm_ops,
-               .of_match_table = tegra_smmu_of_match,
-       },
-};
+       if (soc->supports_round_robin_arbitration)
+               value |= SMMU_TLB_CONFIG_ROUND_ROBIN_ARBITRATION;
 
-static int tegra_smmu_init(void)
-{
-       return platform_driver_register(&tegra_smmu_driver);
-}
+       smmu_writel(smmu, value, SMMU_TLB_CONFIG);
 
-static void __exit tegra_smmu_exit(void)
-{
-       platform_driver_unregister(&tegra_smmu_driver);
-}
+       smmu_flush_ptc(smmu, NULL, 0);
+       smmu_flush_tlb(smmu);
+       smmu_writel(smmu, SMMU_CONFIG_ENABLE, SMMU_CONFIG);
+       smmu_flush(smmu);
+
+       tegra_smmu_ahb_enable();
 
-subsys_initcall(tegra_smmu_init);
-module_exit(tegra_smmu_exit);
+       err = bus_set_iommu(&platform_bus_type, &tegra_smmu_ops);
+       if (err < 0)
+               return ERR_PTR(err);
 
-MODULE_DESCRIPTION("IOMMU API for SMMU in Tegra30");
-MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
-MODULE_ALIAS("platform:tegra-smmu");
-MODULE_LICENSE("GPL v2");
+       return smmu;
+}
index 9e630f29ac6b647bcc7bc05871367ffe5880b305..a3fd2b37ddb6cba8deb6adfa9cc45e2cf4824e56 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/of_pci.h>
 #include <linux/irqdomain.h>
 #include <linux/slab.h>
+#include <linux/syscore_ops.h>
 #include <linux/msi.h>
 #include <asm/mach/arch.h>
 #include <asm/exception.h>
@@ -43,6 +44,7 @@
 #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS    (0x34)
 #define ARMADA_370_XP_INT_SOURCE_CTL(irq)      (0x100 + irq*4)
 #define ARMADA_370_XP_INT_SOURCE_CPU_MASK      0xF
+#define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid)  ((BIT(0) | BIT(8)) << cpuid)
 
 #define ARMADA_370_XP_CPU_INTACK_OFFS          (0x44)
 #define ARMADA_375_PPI_CAUSE                   (0x10)
@@ -66,6 +68,7 @@
 static void __iomem *per_cpu_int_base;
 static void __iomem *main_int_base;
 static struct irq_domain *armada_370_xp_mpic_domain;
+static u32 doorbell_mask_reg;
 #ifdef CONFIG_PCI_MSI
 static struct irq_domain *armada_370_xp_msi_domain;
 static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
@@ -406,19 +409,29 @@ static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
                                                  struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_get_chip(irq);
-       unsigned long irqmap, irqn;
+       unsigned long irqmap, irqn, irqsrc, cpuid;
        unsigned int cascade_irq;
 
        chained_irq_enter(chip, desc);
 
        irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE);
-
-       if (irqmap & BIT(0)) {
-               armada_370_xp_handle_msi_irq(NULL, true);
-               irqmap &= ~BIT(0);
-       }
+       cpuid = cpu_logical_map(smp_processor_id());
 
        for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
+               irqsrc = readl_relaxed(main_int_base +
+                                      ARMADA_370_XP_INT_SOURCE_CTL(irqn));
+
+               /* Check if the interrupt is not masked on current CPU.
+                * Test IRQ (0-1) and FIQ (8-9) mask bits.
+                */
+               if (!(irqsrc & ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid)))
+                       continue;
+
+               if (irqn == 1) {
+                       armada_370_xp_handle_msi_irq(NULL, true);
+                       continue;
+               }
+
                cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn);
                generic_handle_irq(cascade_irq);
        }
@@ -474,6 +487,54 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
        } while (1);
 }
 
+static int armada_370_xp_mpic_suspend(void)
+{
+       doorbell_mask_reg = readl(per_cpu_int_base +
+                                 ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+       return 0;
+}
+
+static void armada_370_xp_mpic_resume(void)
+{
+       int nirqs;
+       irq_hw_number_t irq;
+
+       /* Re-enable interrupts */
+       nirqs = (readl(main_int_base + ARMADA_370_XP_INT_CONTROL) >> 2) & 0x3ff;
+       for (irq = 0; irq < nirqs; irq++) {
+               struct irq_data *data;
+               int virq;
+
+               virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq);
+               if (virq == 0)
+                       continue;
+
+               if (irq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
+                       writel(irq, per_cpu_int_base +
+                              ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+               else
+                       writel(irq, main_int_base +
+                              ARMADA_370_XP_INT_SET_ENABLE_OFFS);
+
+               data = irq_get_irq_data(virq);
+               if (!irqd_irq_disabled(data))
+                       armada_370_xp_irq_unmask(data);
+       }
+
+       /* Reconfigure doorbells for IPIs and MSIs */
+       writel(doorbell_mask_reg,
+              per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+       if (doorbell_mask_reg & IPI_DOORBELL_MASK)
+               writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+       if (doorbell_mask_reg & PCI_MSI_DOORBELL_MASK)
+               writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+}
+
+struct syscore_ops armada_370_xp_mpic_syscore_ops = {
+       .suspend        = armada_370_xp_mpic_suspend,
+       .resume         = armada_370_xp_mpic_resume,
+};
+
 static int __init armada_370_xp_mpic_of_init(struct device_node *node,
                                             struct device_node *parent)
 {
@@ -530,6 +591,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
                                        armada_370_xp_mpic_handle_cascade_irq);
        }
 
+       register_syscore_ops(&armada_370_xp_mpic_syscore_ops);
+
        return 0;
 }
 
index 656cfe336837e9e22a4b7d03629744fd0a2ad35a..d111ac779c4058e94c6051536cdb7fb5d2d34863 100644 (file)
@@ -243,8 +243,9 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node,
        }
 
        ret = irq_alloc_domain_generic_chips(domain, 32, 1, name,
-                                            handle_level_irq, 0, 0,
-                                            IRQCHIP_SKIP_SET_WAKE);
+                                            handle_fasteoi_irq,
+                                            IRQ_NOREQUEST | IRQ_NOPROBE |
+                                            IRQ_NOAUTOEN, 0, 0);
        if (ret)
                goto err_domain_remove;
 
@@ -256,7 +257,6 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node,
                gc->unused = 0;
                gc->wake_enabled = ~0;
                gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK;
-               gc->chip_types[0].handler = handle_fasteoi_irq;
                gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
                gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
                gc->chip_types[0].chip.irq_shutdown = aic_common_shutdown;
index e7c6155b23b814048de958f7a7b338c3cb604a32..8eec8e1201d9dfd349cc7bcb557a0001cdda13c0 100644 (file)
@@ -102,9 +102,9 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn,
        unsigned int idx;
 
        parent_irq = irq_of_parse_and_map(dn, irq);
-       if (parent_irq < 0) {
+       if (!parent_irq) {
                pr_err("failed to map interrupt %d\n", irq);
-               return parent_irq;
+               return -EINVAL;
        }
 
        /* For multiple parent IRQs with multiple words, this looks like:
index 4aa653a0ac72205788f6be0f83b20000d0a7faaa..313c2c64498a2753ff0340ae5e5905ac2bca8ce8 100644 (file)
@@ -139,9 +139,9 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np,
        writel(0xffffffff, data->base + CPU_CLEAR);
 
        data->parent_irq = irq_of_parse_and_map(np, 0);
-       if (data->parent_irq < 0) {
+       if (!data->parent_irq) {
                pr_err("failed to find parent interrupt\n");
-               ret = data->parent_irq;
+               ret = -EINVAL;
                goto out_unmap;
        }
 
index 38493ff28fa56b2ca4b19f8bd3fa6d153b21016e..7f9be0785c6a552fe573d61192c7ed2a5b4f1c21 100644 (file)
@@ -1041,6 +1041,8 @@ gic_of_init(struct device_node *node, struct device_node *parent)
        return 0;
 }
 IRQCHIP_DECLARE(gic_400, "arm,gic-400", gic_of_init);
+IRQCHIP_DECLARE(arm11mp_gic, "arm,arm11mp-gic", gic_of_init);
+IRQCHIP_DECLARE(arm1176jzf_dc_gic, "arm,arm1176jzf-devchip-gic", gic_of_init);
 IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
 IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
 IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
index aa29198fca3e2b2c892268eb2549444b1beb499c..7440c58b8e6fd3f729e6fb3381750648c145a6c4 100644 (file)
@@ -9,26 +9,21 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/device.h>
+#include <linux/err.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
 #include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/device.h>
 #include <linux/timer.h>
-#include <linux/err.h>
-#include <linux/ctype.h>
-#include <linux/leds.h>
 #include "leds.h"
 
 static struct class *leds_class;
 
-static void led_update_brightness(struct led_classdev *led_cdev)
-{
-       if (led_cdev->brightness_get)
-               led_cdev->brightness = led_cdev->brightness_get(led_cdev);
-}
-
 static ssize_t brightness_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -59,14 +54,14 @@ static ssize_t brightness_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(brightness);
 
-static ssize_t led_max_brightness_show(struct device *dev,
+static ssize_t max_brightness_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
        struct led_classdev *led_cdev = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", led_cdev->max_brightness);
 }
-static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL);
+static DEVICE_ATTR_RO(max_brightness);
 
 #ifdef CONFIG_LEDS_TRIGGERS
 static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
index 71b40d3bf77604e32829f391b6e804bbeefb0cf1..aaa8eba9099f4cf1932bae96a4081cc273214876 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/leds.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/rwsem.h>
-#include <linux/leds.h>
 #include "leds.h"
 
 DECLARE_RWSEM(leds_list_lock);
@@ -126,3 +127,19 @@ void led_set_brightness(struct led_classdev *led_cdev,
        __led_set_brightness(led_cdev, brightness);
 }
 EXPORT_SYMBOL(led_set_brightness);
+
+int led_update_brightness(struct led_classdev *led_cdev)
+{
+       int ret = 0;
+
+       if (led_cdev->brightness_get) {
+               ret = led_cdev->brightness_get(led_cdev);
+               if (ret >= 0) {
+                       led_cdev->brightness = ret;
+                       return 0;
+               }
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(led_update_brightness);
index 1c4ed5510f356a1be0ae7782d8600198b91e6e78..75717ba68ae0b7a491995aaacef8c7b778c71aea 100644 (file)
@@ -7,9 +7,9 @@
  * Free Software Foundation.
  */
 #include <linux/err.h>
+#include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/leds.h>
 
 /**
  * gpio_led_register_device - register a gpio-led device
@@ -28,6 +28,9 @@ struct platform_device *__init gpio_led_register_device(
        struct platform_device *ret;
        struct gpio_led_platform_data _pdata = *pdata;
 
+       if (!pdata->num_leds)
+               return ERR_PTR(-EINVAL);
+
        _pdata.leds = kmemdup(pdata->leds,
                        pdata->num_leds * sizeof(*pdata->leds), GFP_KERNEL);
        if (!_pdata.leds)
index 57ff20fecf57e16e9963db1692206b923593258f..b4518c8751c8df91f2848626d2043ebc5ef3eff6 100644 (file)
  * published by the Free Software Foundation.
  *
  */
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
+#include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/kernel.h>
 #include <linux/leds.h>
+#include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
-#include <linux/module.h>
-#include <linux/err.h>
 
 struct gpio_led_data {
        struct led_classdev cdev;
@@ -36,7 +36,7 @@ struct gpio_led_data {
 
 static void gpio_led_work(struct work_struct *work)
 {
-       struct gpio_led_data    *led_dat =
+       struct gpio_led_data *led_dat =
                container_of(work, struct gpio_led_data, work);
 
        if (led_dat->blinking) {
@@ -235,14 +235,12 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 }
 #endif /* CONFIG_OF_GPIO */
 
-
 static int gpio_led_probe(struct platform_device *pdev)
 {
        struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct gpio_leds_priv *priv;
        int i, ret = 0;
 
-
        if (pdata && pdata->num_leds) {
                priv = devm_kzalloc(&pdev->dev,
                                sizeof_gpio_leds_priv(pdata->num_leds),
index 8e1abdcd4c9d9789c207258c82ff9f33daa3a0df..53144fb9616702d3024bb505c1278b613bb02221 100644 (file)
@@ -335,7 +335,8 @@ static int lp3944_configure(struct i2c_client *client,
                        }
 
                        /* to expose the default value to userspace */
-                       led->ldev.brightness = led->status;
+                       led->ldev.brightness =
+                                       (enum led_brightness) led->status;
 
                        /* Set the default led status */
                        err = lp3944_led_set(led, led->status);
index 35812e3a37f24edfd4a7694e40c705b0ea6054f6..c86c41826476ca48b3fa6f58e0a41db869418cf8 100644 (file)
@@ -48,7 +48,7 @@ static void gpio_trig_work(struct work_struct *work)
        if (!gpio_data->gpio)
                return;
 
-       tmp = gpio_get_value(gpio_data->gpio);
+       tmp = gpio_get_value_cansleep(gpio_data->gpio);
        if (gpio_data->inverted)
                tmp = !tmp;
 
index 6d184dbcaca81cfaeef3aca1f786036b98001bdb..94ed7cefb14d3c7ac979e8181a4902cf3d56c608 100644 (file)
@@ -1,3 +1,7 @@
+# Generic MAILBOX API
+
+obj-$(CONFIG_MAILBOX)          += mailbox.o
+
 obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)   += omap-mailbox.o
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
new file mode 100644 (file)
index 0000000..afcb430
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * Mailbox: Common code for Mailbox controllers and users
+ *
+ * Copyright (C) 2013-2014 Linaro Ltd.
+ * Author: Jassi Brar <jassisinghbrar@gmail.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/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox_controller.h>
+
+#define TXDONE_BY_IRQ  BIT(0) /* controller has remote RTR irq */
+#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
+#define TXDONE_BY_ACK  BIT(2) /* S/W ACK recevied by Client ticks the TX */
+
+static LIST_HEAD(mbox_cons);
+static DEFINE_MUTEX(con_mutex);
+
+static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
+{
+       int idx;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chan->lock, flags);
+
+       /* See if there is any space left */
+       if (chan->msg_count == MBOX_TX_QUEUE_LEN) {
+               spin_unlock_irqrestore(&chan->lock, flags);
+               return -ENOBUFS;
+       }
+
+       idx = chan->msg_free;
+       chan->msg_data[idx] = mssg;
+       chan->msg_count++;
+
+       if (idx == MBOX_TX_QUEUE_LEN - 1)
+               chan->msg_free = 0;
+       else
+               chan->msg_free++;
+
+       spin_unlock_irqrestore(&chan->lock, flags);
+
+       return idx;
+}
+
+static void msg_submit(struct mbox_chan *chan)
+{
+       unsigned count, idx;
+       unsigned long flags;
+       void *data;
+       int err;
+
+       spin_lock_irqsave(&chan->lock, flags);
+
+       if (!chan->msg_count || chan->active_req)
+               goto exit;
+
+       count = chan->msg_count;
+       idx = chan->msg_free;
+       if (idx >= count)
+               idx -= count;
+       else
+               idx += MBOX_TX_QUEUE_LEN - count;
+
+       data = chan->msg_data[idx];
+
+       /* Try to submit a message to the MBOX controller */
+       err = chan->mbox->ops->send_data(chan, data);
+       if (!err) {
+               chan->active_req = data;
+               chan->msg_count--;
+       }
+exit:
+       spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+static void tx_tick(struct mbox_chan *chan, int r)
+{
+       unsigned long flags;
+       void *mssg;
+
+       spin_lock_irqsave(&chan->lock, flags);
+       mssg = chan->active_req;
+       chan->active_req = NULL;
+       spin_unlock_irqrestore(&chan->lock, flags);
+
+       /* Submit next message */
+       msg_submit(chan);
+
+       /* Notify the client */
+       if (mssg && chan->cl->tx_done)
+               chan->cl->tx_done(chan->cl, mssg, r);
+
+       if (chan->cl->tx_block)
+               complete(&chan->tx_complete);
+}
+
+static void poll_txdone(unsigned long data)
+{
+       struct mbox_controller *mbox = (struct mbox_controller *)data;
+       bool txdone, resched = false;
+       int i;
+
+       for (i = 0; i < mbox->num_chans; i++) {
+               struct mbox_chan *chan = &mbox->chans[i];
+
+               if (chan->active_req && chan->cl) {
+                       resched = true;
+                       txdone = chan->mbox->ops->last_tx_done(chan);
+                       if (txdone)
+                               tx_tick(chan, 0);
+               }
+       }
+
+       if (resched)
+               mod_timer(&mbox->poll, jiffies +
+                               msecs_to_jiffies(mbox->txpoll_period));
+}
+
+/**
+ * mbox_chan_received_data - A way for controller driver to push data
+ *                             received from remote to the upper layer.
+ * @chan: Pointer to the mailbox channel on which RX happened.
+ * @mssg: Client specific message typecasted as void *
+ *
+ * After startup and before shutdown any data received on the chan
+ * is passed on to the API via atomic mbox_chan_received_data().
+ * The controller should ACK the RX only after this call returns.
+ */
+void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)
+{
+       /* No buffering the received data */
+       if (chan->cl->rx_callback)
+               chan->cl->rx_callback(chan->cl, mssg);
+}
+EXPORT_SYMBOL_GPL(mbox_chan_received_data);
+
+/**
+ * mbox_chan_txdone - A way for controller driver to notify the
+ *                     framework that the last TX has completed.
+ * @chan: Pointer to the mailbox chan on which TX happened.
+ * @r: Status of last TX - OK or ERROR
+ *
+ * The controller that has IRQ for TX ACK calls this atomic API
+ * to tick the TX state machine. It works only if txdone_irq
+ * is set by the controller.
+ */
+void mbox_chan_txdone(struct mbox_chan *chan, int r)
+{
+       if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) {
+               dev_err(chan->mbox->dev,
+                      "Controller can't run the TX ticker\n");
+               return;
+       }
+
+       tx_tick(chan, r);
+}
+EXPORT_SYMBOL_GPL(mbox_chan_txdone);
+
+/**
+ * mbox_client_txdone - The way for a client to run the TX state machine.
+ * @chan: Mailbox channel assigned to this client.
+ * @r: Success status of last transmission.
+ *
+ * The client/protocol had received some 'ACK' packet and it notifies
+ * the API that the last packet was sent successfully. This only works
+ * if the controller can't sense TX-Done.
+ */
+void mbox_client_txdone(struct mbox_chan *chan, int r)
+{
+       if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) {
+               dev_err(chan->mbox->dev, "Client can't run the TX ticker\n");
+               return;
+       }
+
+       tx_tick(chan, r);
+}
+EXPORT_SYMBOL_GPL(mbox_client_txdone);
+
+/**
+ * mbox_client_peek_data - A way for client driver to pull data
+ *                     received from remote by the controller.
+ * @chan: Mailbox channel assigned to this client.
+ *
+ * A poke to controller driver for any received data.
+ * The data is actually passed onto client via the
+ * mbox_chan_received_data()
+ * The call can be made from atomic context, so the controller's
+ * implementation of peek_data() must not sleep.
+ *
+ * Return: True, if controller has, and is going to push after this,
+ *          some data.
+ *         False, if controller doesn't have any data to be read.
+ */
+bool mbox_client_peek_data(struct mbox_chan *chan)
+{
+       if (chan->mbox->ops->peek_data)
+               return chan->mbox->ops->peek_data(chan);
+
+       return false;
+}
+EXPORT_SYMBOL_GPL(mbox_client_peek_data);
+
+/**
+ * mbox_send_message - For client to submit a message to be
+ *                             sent to the remote.
+ * @chan: Mailbox channel assigned to this client.
+ * @mssg: Client specific message typecasted.
+ *
+ * For client to submit data to the controller destined for a remote
+ * processor. If the client had set 'tx_block', the call will return
+ * either when the remote receives the data or when 'tx_tout' millisecs
+ * run out.
+ *  In non-blocking mode, the requests are buffered by the API and a
+ * non-negative token is returned for each queued request. If the request
+ * is not queued, a negative token is returned. Upon failure or successful
+ * TX, the API calls 'tx_done' from atomic context, from which the client
+ * could submit yet another request.
+ * The pointer to message should be preserved until it is sent
+ * over the chan, i.e, tx_done() is made.
+ * This function could be called from atomic context as it simply
+ * queues the data and returns a token against the request.
+ *
+ * Return: Non-negative integer for successful submission (non-blocking mode)
+ *     or transmission over chan (blocking mode).
+ *     Negative value denotes failure.
+ */
+int mbox_send_message(struct mbox_chan *chan, void *mssg)
+{
+       int t;
+
+       if (!chan || !chan->cl)
+               return -EINVAL;
+
+       t = add_to_rbuf(chan, mssg);
+       if (t < 0) {
+               dev_err(chan->mbox->dev, "Try increasing MBOX_TX_QUEUE_LEN\n");
+               return t;
+       }
+
+       msg_submit(chan);
+
+       if (chan->txdone_method == TXDONE_BY_POLL)
+               poll_txdone((unsigned long)chan->mbox);
+
+       if (chan->cl->tx_block && chan->active_req) {
+               unsigned long wait;
+               int ret;
+
+               if (!chan->cl->tx_tout) /* wait forever */
+                       wait = msecs_to_jiffies(3600000);
+               else
+                       wait = msecs_to_jiffies(chan->cl->tx_tout);
+
+               ret = wait_for_completion_timeout(&chan->tx_complete, wait);
+               if (ret == 0) {
+                       t = -EIO;
+                       tx_tick(chan, -EIO);
+               }
+       }
+
+       return t;
+}
+EXPORT_SYMBOL_GPL(mbox_send_message);
+
+/**
+ * mbox_request_channel - Request a mailbox channel.
+ * @cl: Identity of the client requesting the channel.
+ * @index: Index of mailbox specifier in 'mboxes' property.
+ *
+ * The Client specifies its requirements and capabilities while asking for
+ * a mailbox channel. It can't be called from atomic context.
+ * The channel is exclusively allocated and can't be used by another
+ * client before the owner calls mbox_free_channel.
+ * After assignment, any packet received on this channel will be
+ * handed over to the client via the 'rx_callback'.
+ * The framework holds reference to the client, so the mbox_client
+ * structure shouldn't be modified until the mbox_free_channel returns.
+ *
+ * Return: Pointer to the channel assigned to the client if successful.
+ *             ERR_PTR for request failure.
+ */
+struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
+{
+       struct device *dev = cl->dev;
+       struct mbox_controller *mbox;
+       struct of_phandle_args spec;
+       struct mbox_chan *chan;
+       unsigned long flags;
+       int ret;
+
+       if (!dev || !dev->of_node) {
+               pr_debug("%s: No owner device node\n", __func__);
+               return ERR_PTR(-ENODEV);
+       }
+
+       mutex_lock(&con_mutex);
+
+       if (of_parse_phandle_with_args(dev->of_node, "mboxes",
+                                      "#mbox-cells", index, &spec)) {
+               dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__);
+               mutex_unlock(&con_mutex);
+               return ERR_PTR(-ENODEV);
+       }
+
+       chan = NULL;
+       list_for_each_entry(mbox, &mbox_cons, node)
+               if (mbox->dev->of_node == spec.np) {
+                       chan = mbox->of_xlate(mbox, &spec);
+                       break;
+               }
+
+       of_node_put(spec.np);
+
+       if (!chan || chan->cl || !try_module_get(mbox->dev->driver->owner)) {
+               dev_dbg(dev, "%s: mailbox not free\n", __func__);
+               mutex_unlock(&con_mutex);
+               return ERR_PTR(-EBUSY);
+       }
+
+       spin_lock_irqsave(&chan->lock, flags);
+       chan->msg_free = 0;
+       chan->msg_count = 0;
+       chan->active_req = NULL;
+       chan->cl = cl;
+       init_completion(&chan->tx_complete);
+
+       if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
+               chan->txdone_method |= TXDONE_BY_ACK;
+
+       spin_unlock_irqrestore(&chan->lock, flags);
+
+       ret = chan->mbox->ops->startup(chan);
+       if (ret) {
+               dev_err(dev, "Unable to startup the chan (%d)\n", ret);
+               mbox_free_channel(chan);
+               chan = ERR_PTR(ret);
+       }
+
+       mutex_unlock(&con_mutex);
+       return chan;
+}
+EXPORT_SYMBOL_GPL(mbox_request_channel);
+
+/**
+ * mbox_free_channel - The client relinquishes control of a mailbox
+ *                     channel by this call.
+ * @chan: The mailbox channel to be freed.
+ */
+void mbox_free_channel(struct mbox_chan *chan)
+{
+       unsigned long flags;
+
+       if (!chan || !chan->cl)
+               return;
+
+       chan->mbox->ops->shutdown(chan);
+
+       /* The queued TX requests are simply aborted, no callbacks are made */
+       spin_lock_irqsave(&chan->lock, flags);
+       chan->cl = NULL;
+       chan->active_req = NULL;
+       if (chan->txdone_method == (TXDONE_BY_POLL | TXDONE_BY_ACK))
+               chan->txdone_method = TXDONE_BY_POLL;
+
+       module_put(chan->mbox->dev->driver->owner);
+       spin_unlock_irqrestore(&chan->lock, flags);
+}
+EXPORT_SYMBOL_GPL(mbox_free_channel);
+
+static struct mbox_chan *
+of_mbox_index_xlate(struct mbox_controller *mbox,
+                   const struct of_phandle_args *sp)
+{
+       int ind = sp->args[0];
+
+       if (ind >= mbox->num_chans)
+               return NULL;
+
+       return &mbox->chans[ind];
+}
+
+/**
+ * mbox_controller_register - Register the mailbox controller
+ * @mbox:      Pointer to the mailbox controller.
+ *
+ * The controller driver registers its communication channels
+ */
+int mbox_controller_register(struct mbox_controller *mbox)
+{
+       int i, txdone;
+
+       /* Sanity check */
+       if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans)
+               return -EINVAL;
+
+       if (mbox->txdone_irq)
+               txdone = TXDONE_BY_IRQ;
+       else if (mbox->txdone_poll)
+               txdone = TXDONE_BY_POLL;
+       else /* It has to be ACK then */
+               txdone = TXDONE_BY_ACK;
+
+       if (txdone == TXDONE_BY_POLL) {
+               mbox->poll.function = &poll_txdone;
+               mbox->poll.data = (unsigned long)mbox;
+               init_timer(&mbox->poll);
+       }
+
+       for (i = 0; i < mbox->num_chans; i++) {
+               struct mbox_chan *chan = &mbox->chans[i];
+
+               chan->cl = NULL;
+               chan->mbox = mbox;
+               chan->txdone_method = txdone;
+               spin_lock_init(&chan->lock);
+       }
+
+       if (!mbox->of_xlate)
+               mbox->of_xlate = of_mbox_index_xlate;
+
+       mutex_lock(&con_mutex);
+       list_add_tail(&mbox->node, &mbox_cons);
+       mutex_unlock(&con_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mbox_controller_register);
+
+/**
+ * mbox_controller_unregister - Unregister the mailbox controller
+ * @mbox:      Pointer to the mailbox controller.
+ */
+void mbox_controller_unregister(struct mbox_controller *mbox)
+{
+       int i;
+
+       if (!mbox)
+               return;
+
+       mutex_lock(&con_mutex);
+
+       list_del(&mbox->node);
+
+       for (i = 0; i < mbox->num_chans; i++)
+               mbox_free_channel(&mbox->chans[i]);
+
+       if (mbox->txdone_poll)
+               del_timer_sync(&mbox->poll);
+
+       mutex_unlock(&con_mutex);
+}
+EXPORT_SYMBOL_GPL(mbox_controller_unregister);
index d873cbae2fbb86acb6d9ad2ba02842d4144ac2b6..f3755e0aa935c96a3aa0b0d3e4122b82e8cfe241 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 
-#include <linux/mailbox.h>
+#include <linux/pl320-ipc.h>
 
 #define IPCMxSOURCE(m)         ((m) * 0x40)
 #define IPCMxDSET(m)           (((m) * 0x40) + 0x004)
index f752d12081ffe31a4a6b62b25654d66a54756ee4..be065300e93c8d16d2a5cc5c7753224932e27836 100644 (file)
 
 /*----------------------------------------------------------------*/
 
-struct bucket {
-       spinlock_t lock;
-       struct hlist_head cells;
-};
+#define MIN_CELLS 1024
 
 struct dm_bio_prison {
+       spinlock_t lock;
        mempool_t *cell_pool;
-
-       unsigned nr_buckets;
-       unsigned hash_mask;
-       struct bucket *buckets;
+       struct rb_root cells;
 };
 
-/*----------------------------------------------------------------*/
-
-static uint32_t calc_nr_buckets(unsigned nr_cells)
-{
-       uint32_t n = 128;
-
-       nr_cells /= 4;
-       nr_cells = min(nr_cells, 8192u);
-
-       while (n < nr_cells)
-               n <<= 1;
-
-       return n;
-}
-
 static struct kmem_cache *_cell_cache;
 
-static void init_bucket(struct bucket *b)
-{
-       spin_lock_init(&b->lock);
-       INIT_HLIST_HEAD(&b->cells);
-}
+/*----------------------------------------------------------------*/
 
 /*
  * @nr_cells should be the number of cells you want in use _concurrently_.
  * Don't confuse it with the number of distinct keys.
  */
-struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells)
+struct dm_bio_prison *dm_bio_prison_create(void)
 {
-       unsigned i;
-       uint32_t nr_buckets = calc_nr_buckets(nr_cells);
-       size_t len = sizeof(struct dm_bio_prison) +
-               (sizeof(struct bucket) * nr_buckets);
-       struct dm_bio_prison *prison = kmalloc(len, GFP_KERNEL);
+       struct dm_bio_prison *prison = kmalloc(sizeof(*prison), GFP_KERNEL);
 
        if (!prison)
                return NULL;
 
-       prison->cell_pool = mempool_create_slab_pool(nr_cells, _cell_cache);
+       spin_lock_init(&prison->lock);
+
+       prison->cell_pool = mempool_create_slab_pool(MIN_CELLS, _cell_cache);
        if (!prison->cell_pool) {
                kfree(prison);
                return NULL;
        }
 
-       prison->nr_buckets = nr_buckets;
-       prison->hash_mask = nr_buckets - 1;
-       prison->buckets = (struct bucket *) (prison + 1);
-       for (i = 0; i < nr_buckets; i++)
-               init_bucket(prison->buckets + i);
+       prison->cells = RB_ROOT;
 
        return prison;
 }
@@ -101,68 +71,73 @@ void dm_bio_prison_free_cell(struct dm_bio_prison *prison,
 }
 EXPORT_SYMBOL_GPL(dm_bio_prison_free_cell);
 
-static uint32_t hash_key(struct dm_bio_prison *prison, struct dm_cell_key *key)
+static void __setup_new_cell(struct dm_cell_key *key,
+                            struct bio *holder,
+                            struct dm_bio_prison_cell *cell)
 {
-       const unsigned long BIG_PRIME = 4294967291UL;
-       uint64_t hash = key->block * BIG_PRIME;
-
-       return (uint32_t) (hash & prison->hash_mask);
+       memcpy(&cell->key, key, sizeof(cell->key));
+       cell->holder = holder;
+       bio_list_init(&cell->bios);
 }
 
-static int keys_equal(struct dm_cell_key *lhs, struct dm_cell_key *rhs)
+static int cmp_keys(struct dm_cell_key *lhs,
+                   struct dm_cell_key *rhs)
 {
-              return (lhs->virtual == rhs->virtual) &&
-                      (lhs->dev == rhs->dev) &&
-                      (lhs->block == rhs->block);
-}
+       if (lhs->virtual < rhs->virtual)
+               return -1;
 
-static struct bucket *get_bucket(struct dm_bio_prison *prison,
-                                struct dm_cell_key *key)
-{
-       return prison->buckets + hash_key(prison, key);
-}
+       if (lhs->virtual > rhs->virtual)
+               return 1;
 
-static struct dm_bio_prison_cell *__search_bucket(struct bucket *b,
-                                                 struct dm_cell_key *key)
-{
-       struct dm_bio_prison_cell *cell;
+       if (lhs->dev < rhs->dev)
+               return -1;
 
-       hlist_for_each_entry(cell, &b->cells, list)
-               if (keys_equal(&cell->key, key))
-                       return cell;
+       if (lhs->dev > rhs->dev)
+               return 1;
 
-       return NULL;
-}
+       if (lhs->block_end <= rhs->block_begin)
+               return -1;
 
-static void __setup_new_cell(struct bucket *b,
-                            struct dm_cell_key *key,
-                            struct bio *holder,
-                            struct dm_bio_prison_cell *cell)
-{
-       memcpy(&cell->key, key, sizeof(cell->key));
-       cell->holder = holder;
-       bio_list_init(&cell->bios);
-       hlist_add_head(&cell->list, &b->cells);
+       if (lhs->block_begin >= rhs->block_end)
+               return 1;
+
+       return 0;
 }
 
-static int __bio_detain(struct bucket *b,
+static int __bio_detain(struct dm_bio_prison *prison,
                        struct dm_cell_key *key,
                        struct bio *inmate,
                        struct dm_bio_prison_cell *cell_prealloc,
                        struct dm_bio_prison_cell **cell_result)
 {
-       struct dm_bio_prison_cell *cell;
-
-       cell = __search_bucket(b, key);
-       if (cell) {
-               if (inmate)
-                       bio_list_add(&cell->bios, inmate);
-               *cell_result = cell;
-               return 1;
+       int r;
+       struct rb_node **new = &prison->cells.rb_node, *parent = NULL;
+
+       while (*new) {
+               struct dm_bio_prison_cell *cell =
+                       container_of(*new, struct dm_bio_prison_cell, node);
+
+               r = cmp_keys(key, &cell->key);
+
+               parent = *new;
+               if (r < 0)
+                       new = &((*new)->rb_left);
+               else if (r > 0)
+                       new = &((*new)->rb_right);
+               else {
+                       if (inmate)
+                               bio_list_add(&cell->bios, inmate);
+                       *cell_result = cell;
+                       return 1;
+               }
        }
 
-       __setup_new_cell(b, key, inmate, cell_prealloc);
+       __setup_new_cell(key, inmate, cell_prealloc);
        *cell_result = cell_prealloc;
+
+       rb_link_node(&cell_prealloc->node, parent, new);
+       rb_insert_color(&cell_prealloc->node, &prison->cells);
+
        return 0;
 }
 
@@ -174,11 +149,10 @@ static int bio_detain(struct dm_bio_prison *prison,
 {
        int r;
        unsigned long flags;
-       struct bucket *b = get_bucket(prison, key);
 
-       spin_lock_irqsave(&b->lock, flags);
-       r = __bio_detain(b, key, inmate, cell_prealloc, cell_result);
-       spin_unlock_irqrestore(&b->lock, flags);
+       spin_lock_irqsave(&prison->lock, flags);
+       r = __bio_detain(prison, key, inmate, cell_prealloc, cell_result);
+       spin_unlock_irqrestore(&prison->lock, flags);
 
        return r;
 }
@@ -205,10 +179,11 @@ EXPORT_SYMBOL_GPL(dm_get_cell);
 /*
  * @inmates must have been initialised prior to this call
  */
-static void __cell_release(struct dm_bio_prison_cell *cell,
+static void __cell_release(struct dm_bio_prison *prison,
+                          struct dm_bio_prison_cell *cell,
                           struct bio_list *inmates)
 {
-       hlist_del(&cell->list);
+       rb_erase(&cell->node, &prison->cells);
 
        if (inmates) {
                if (cell->holder)
@@ -222,21 +197,21 @@ void dm_cell_release(struct dm_bio_prison *prison,
                     struct bio_list *bios)
 {
        unsigned long flags;
-       struct bucket *b = get_bucket(prison, &cell->key);
 
-       spin_lock_irqsave(&b->lock, flags);
-       __cell_release(cell, bios);
-       spin_unlock_irqrestore(&b->lock, flags);
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release(prison, cell, bios);
+       spin_unlock_irqrestore(&prison->lock, flags);
 }
 EXPORT_SYMBOL_GPL(dm_cell_release);
 
 /*
  * Sometimes we don't want the holder, just the additional bios.
  */
-static void __cell_release_no_holder(struct dm_bio_prison_cell *cell,
+static void __cell_release_no_holder(struct dm_bio_prison *prison,
+                                    struct dm_bio_prison_cell *cell,
                                     struct bio_list *inmates)
 {
-       hlist_del(&cell->list);
+       rb_erase(&cell->node, &prison->cells);
        bio_list_merge(inmates, &cell->bios);
 }
 
@@ -245,11 +220,10 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
                               struct bio_list *inmates)
 {
        unsigned long flags;
-       struct bucket *b = get_bucket(prison, &cell->key);
 
-       spin_lock_irqsave(&b->lock, flags);
-       __cell_release_no_holder(cell, inmates);
-       spin_unlock_irqrestore(&b->lock, flags);
+       spin_lock_irqsave(&prison->lock, flags);
+       __cell_release_no_holder(prison, cell, inmates);
+       spin_unlock_irqrestore(&prison->lock, flags);
 }
 EXPORT_SYMBOL_GPL(dm_cell_release_no_holder);
 
@@ -267,6 +241,20 @@ void dm_cell_error(struct dm_bio_prison *prison,
 }
 EXPORT_SYMBOL_GPL(dm_cell_error);
 
+void dm_cell_visit_release(struct dm_bio_prison *prison,
+                          void (*visit_fn)(void *, struct dm_bio_prison_cell *),
+                          void *context,
+                          struct dm_bio_prison_cell *cell)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&prison->lock, flags);
+       visit_fn(context, cell);
+       rb_erase(&cell->node, &prison->cells);
+       spin_unlock_irqrestore(&prison->lock, flags);
+}
+EXPORT_SYMBOL_GPL(dm_cell_visit_release);
+
 /*----------------------------------------------------------------*/
 
 #define DEFERRED_SET_SIZE 64
index 6805a142b750ee594d5ca2bda987d49a09787b39..74cf01144b1fc9c12777f669e1cf6e5e23422d44 100644 (file)
@@ -10,8 +10,8 @@
 #include "persistent-data/dm-block-manager.h" /* FIXME: for dm_block_t */
 #include "dm-thin-metadata.h" /* FIXME: for dm_thin_id */
 
-#include <linux/list.h>
 #include <linux/bio.h>
+#include <linux/rbtree.h>
 
 /*----------------------------------------------------------------*/
 
  */
 struct dm_bio_prison;
 
-/* FIXME: this needs to be more abstract */
+/*
+ * Keys define a range of blocks within either a virtual or physical
+ * device.
+ */
 struct dm_cell_key {
        int virtual;
        dm_thin_id dev;
-       dm_block_t block;
+       dm_block_t block_begin, block_end;
 };
 
 /*
@@ -35,13 +38,15 @@ struct dm_cell_key {
  * themselves.
  */
 struct dm_bio_prison_cell {
-       struct hlist_node list;
+       struct list_head user_list;     /* for client use */
+       struct rb_node node;
+
        struct dm_cell_key key;
        struct bio *holder;
        struct bio_list bios;
 };
 
-struct dm_bio_prison *dm_bio_prison_create(unsigned nr_cells);
+struct dm_bio_prison *dm_bio_prison_create(void);
 void dm_bio_prison_destroy(struct dm_bio_prison *prison);
 
 /*
@@ -57,7 +62,7 @@ void dm_bio_prison_free_cell(struct dm_bio_prison *prison,
                             struct dm_bio_prison_cell *cell);
 
 /*
- * Creates, or retrieves a cell for the given key.
+ * Creates, or retrieves a cell that overlaps the given key.
  *
  * Returns 1 if pre-existing cell returned, zero if new cell created using
  * @cell_prealloc.
@@ -68,7 +73,8 @@ int dm_get_cell(struct dm_bio_prison *prison,
                struct dm_bio_prison_cell **cell_result);
 
 /*
- * An atomic op that combines retrieving a cell, and adding a bio to it.
+ * An atomic op that combines retrieving or creating a cell, and adding a
+ * bio to it.
  *
  * Returns 1 if the cell was already held, 0 if @inmate is the new holder.
  */
@@ -87,6 +93,14 @@ void dm_cell_release_no_holder(struct dm_bio_prison *prison,
 void dm_cell_error(struct dm_bio_prison *prison,
                   struct dm_bio_prison_cell *cell, int error);
 
+/*
+ * Visits the cell and then releases.  Guarantees no new inmates are
+ * inserted between the visit and release.
+ */
+void dm_cell_visit_release(struct dm_bio_prison *prison,
+                          void (*visit_fn)(void *, struct dm_bio_prison_cell *),
+                          void *context, struct dm_bio_prison_cell *cell);
+
 /*----------------------------------------------------------------*/
 
 /*
index 825ca1f87639aae4bf1c0f60567bc163c75b338b..c33b49792b8730134c7fced9ffc96531747f900d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/vmalloc.h>
 #include <linux/shrinker.h>
 #include <linux/module.h>
+#include <linux/rbtree.h>
 
 #define DM_MSG_PREFIX "bufio"
 
 /*
  * Check buffer ages in this interval (seconds)
  */
-#define DM_BUFIO_WORK_TIMER_SECS       10
+#define DM_BUFIO_WORK_TIMER_SECS       30
 
 /*
  * Free buffers when they are older than this (seconds)
  */
-#define DM_BUFIO_DEFAULT_AGE_SECS      60
+#define DM_BUFIO_DEFAULT_AGE_SECS      300
 
 /*
- * The number of bvec entries that are embedded directly in the buffer.
- * If the chunk size is larger, dm-io is used to do the io.
+ * The nr of bytes of cached data to keep around.
  */
-#define DM_BUFIO_INLINE_VECS           16
+#define DM_BUFIO_DEFAULT_RETAIN_BYTES   (256 * 1024)
 
 /*
- * Buffer hash
+ * The number of bvec entries that are embedded directly in the buffer.
+ * If the chunk size is larger, dm-io is used to do the io.
  */
-#define DM_BUFIO_HASH_BITS     20
-#define DM_BUFIO_HASH(block) \
-       ((((block) >> DM_BUFIO_HASH_BITS) ^ (block)) & \
-        ((1 << DM_BUFIO_HASH_BITS) - 1))
+#define DM_BUFIO_INLINE_VECS           16
 
 /*
  * Don't try to use kmem_cache_alloc for blocks larger than this.
@@ -106,7 +104,7 @@ struct dm_bufio_client {
 
        unsigned minimum_buffers;
 
-       struct hlist_head *cache_hash;
+       struct rb_root buffer_tree;
        wait_queue_head_t free_buffer_wait;
 
        int async_write_error;
@@ -135,7 +133,7 @@ enum data_mode {
 };
 
 struct dm_buffer {
-       struct hlist_node hash_list;
+       struct rb_node node;
        struct list_head lru_list;
        sector_t block;
        void *data;
@@ -223,6 +221,7 @@ static DEFINE_SPINLOCK(param_spinlock);
  * Buffers are freed after this timeout
  */
 static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
+static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
 
 static unsigned long dm_bufio_peak_allocated;
 static unsigned long dm_bufio_allocated_kmem_cache;
@@ -253,6 +252,53 @@ static LIST_HEAD(dm_bufio_all_clients);
  */
 static DEFINE_MUTEX(dm_bufio_clients_lock);
 
+/*----------------------------------------------------------------
+ * A red/black tree acts as an index for all the buffers.
+ *--------------------------------------------------------------*/
+static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
+{
+       struct rb_node *n = c->buffer_tree.rb_node;
+       struct dm_buffer *b;
+
+       while (n) {
+               b = container_of(n, struct dm_buffer, node);
+
+               if (b->block == block)
+                       return b;
+
+               n = (b->block < block) ? n->rb_left : n->rb_right;
+       }
+
+       return NULL;
+}
+
+static void __insert(struct dm_bufio_client *c, struct dm_buffer *b)
+{
+       struct rb_node **new = &c->buffer_tree.rb_node, *parent = NULL;
+       struct dm_buffer *found;
+
+       while (*new) {
+               found = container_of(*new, struct dm_buffer, node);
+
+               if (found->block == b->block) {
+                       BUG_ON(found != b);
+                       return;
+               }
+
+               parent = *new;
+               new = (found->block < b->block) ?
+                       &((*new)->rb_left) : &((*new)->rb_right);
+       }
+
+       rb_link_node(&b->node, parent, new);
+       rb_insert_color(&b->node, &c->buffer_tree);
+}
+
+static void __remove(struct dm_bufio_client *c, struct dm_buffer *b)
+{
+       rb_erase(&b->node, &c->buffer_tree);
+}
+
 /*----------------------------------------------------------------*/
 
 static void adjust_total_allocated(enum data_mode data_mode, long diff)
@@ -434,7 +480,7 @@ static void __link_buffer(struct dm_buffer *b, sector_t block, int dirty)
        b->block = block;
        b->list_mode = dirty;
        list_add(&b->lru_list, &c->lru[dirty]);
-       hlist_add_head(&b->hash_list, &c->cache_hash[DM_BUFIO_HASH(block)]);
+       __insert(b->c, b);
        b->last_accessed = jiffies;
 }
 
@@ -448,7 +494,7 @@ static void __unlink_buffer(struct dm_buffer *b)
        BUG_ON(!c->n_buffers[b->list_mode]);
 
        c->n_buffers[b->list_mode]--;
-       hlist_del(&b->hash_list);
+       __remove(b->c, b);
        list_del(&b->lru_list);
 }
 
@@ -532,6 +578,19 @@ static void use_dmio(struct dm_buffer *b, int rw, sector_t block,
                end_io(&b->bio, r);
 }
 
+static void inline_endio(struct bio *bio, int error)
+{
+       bio_end_io_t *end_fn = bio->bi_private;
+
+       /*
+        * Reset the bio to free any attached resources
+        * (e.g. bio integrity profiles).
+        */
+       bio_reset(bio);
+
+       end_fn(bio, error);
+}
+
 static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
                           bio_end_io_t *end_io)
 {
@@ -543,7 +602,12 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block,
        b->bio.bi_max_vecs = DM_BUFIO_INLINE_VECS;
        b->bio.bi_iter.bi_sector = block << b->c->sectors_per_block_bits;
        b->bio.bi_bdev = b->c->bdev;
-       b->bio.bi_end_io = end_io;
+       b->bio.bi_end_io = inline_endio;
+       /*
+        * Use of .bi_private isn't a problem here because
+        * the dm_buffer's inline bio is local to bufio.
+        */
+       b->bio.bi_private = end_io;
 
        /*
         * We assume that if len >= PAGE_SIZE ptr is page-aligned.
@@ -887,23 +951,6 @@ static void __check_watermark(struct dm_bufio_client *c,
                __write_dirty_buffers_async(c, 1, write_list);
 }
 
-/*
- * Find a buffer in the hash.
- */
-static struct dm_buffer *__find(struct dm_bufio_client *c, sector_t block)
-{
-       struct dm_buffer *b;
-
-       hlist_for_each_entry(b, &c->cache_hash[DM_BUFIO_HASH(block)],
-                            hash_list) {
-               dm_bufio_cond_resched();
-               if (b->block == block)
-                       return b;
-       }
-
-       return NULL;
-}
-
 /*----------------------------------------------------------------
  * Getting a buffer
  *--------------------------------------------------------------*/
@@ -1433,45 +1480,52 @@ static void drop_buffers(struct dm_bufio_client *c)
 }
 
 /*
- * Test if the buffer is unused and too old, and commit it.
- * At if noio is set, we must not do any I/O because we hold
- * dm_bufio_clients_lock and we would risk deadlock if the I/O gets rerouted to
- * different bufio client.
+ * We may not be able to evict this buffer if IO pending or the client
+ * is still using it.  Caller is expected to know buffer is too old.
+ *
+ * And if GFP_NOFS is used, we must not do any I/O because we hold
+ * dm_bufio_clients_lock and we would risk deadlock if the I/O gets
+ * rerouted to different bufio client.
  */
-static int __cleanup_old_buffer(struct dm_buffer *b, gfp_t gfp,
-                               unsigned long max_jiffies)
+static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp)
 {
-       if (jiffies - b->last_accessed < max_jiffies)
-               return 0;
-
-       if (!(gfp & __GFP_IO)) {
+       if (!(gfp & __GFP_FS)) {
                if (test_bit(B_READING, &b->state) ||
                    test_bit(B_WRITING, &b->state) ||
                    test_bit(B_DIRTY, &b->state))
-                       return 0;
+                       return false;
        }
 
        if (b->hold_count)
-               return 0;
+               return false;
 
        __make_buffer_clean(b);
        __unlink_buffer(b);
        __free_buffer_wake(b);
 
-       return 1;
+       return true;
 }
 
-static long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
-                  gfp_t gfp_mask)
+static unsigned get_retain_buffers(struct dm_bufio_client *c)
+{
+        unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes);
+        return retain_bytes / c->block_size;
+}
+
+static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
+                           gfp_t gfp_mask)
 {
        int l;
        struct dm_buffer *b, *tmp;
-       long freed = 0;
+       unsigned long freed = 0;
+       unsigned long count = nr_to_scan;
+       unsigned retain_target = get_retain_buffers(c);
 
        for (l = 0; l < LIST_SIZE; l++) {
                list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) {
-                       freed += __cleanup_old_buffer(b, gfp_mask, 0);
-                       if (!--nr_to_scan)
+                       if (__try_evict_buffer(b, gfp_mask))
+                               freed++;
+                       if (!--nr_to_scan || ((count - freed) <= retain_target))
                                return freed;
                        dm_bufio_cond_resched();
                }
@@ -1486,7 +1540,7 @@ dm_bufio_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
        unsigned long freed;
 
        c = container_of(shrink, struct dm_bufio_client, shrinker);
-       if (sc->gfp_mask & __GFP_IO)
+       if (sc->gfp_mask & __GFP_FS)
                dm_bufio_lock(c);
        else if (!dm_bufio_trylock(c))
                return SHRINK_STOP;
@@ -1503,7 +1557,7 @@ dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
        unsigned long count;
 
        c = container_of(shrink, struct dm_bufio_client, shrinker);
-       if (sc->gfp_mask & __GFP_IO)
+       if (sc->gfp_mask & __GFP_FS)
                dm_bufio_lock(c);
        else if (!dm_bufio_trylock(c))
                return 0;
@@ -1533,11 +1587,7 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
                r = -ENOMEM;
                goto bad_client;
        }
-       c->cache_hash = vmalloc(sizeof(struct hlist_head) << DM_BUFIO_HASH_BITS);
-       if (!c->cache_hash) {
-               r = -ENOMEM;
-               goto bad_hash;
-       }
+       c->buffer_tree = RB_ROOT;
 
        c->bdev = bdev;
        c->block_size = block_size;
@@ -1556,9 +1606,6 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
                c->n_buffers[i] = 0;
        }
 
-       for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
-               INIT_HLIST_HEAD(&c->cache_hash[i]);
-
        mutex_init(&c->lock);
        INIT_LIST_HEAD(&c->reserved_buffers);
        c->need_reserved_buffers = reserved_buffers;
@@ -1632,8 +1679,6 @@ bad_cache:
        }
        dm_io_client_destroy(c->dm_io);
 bad_dm_io:
-       vfree(c->cache_hash);
-bad_hash:
        kfree(c);
 bad_client:
        return ERR_PTR(r);
@@ -1660,9 +1705,7 @@ void dm_bufio_client_destroy(struct dm_bufio_client *c)
 
        mutex_unlock(&dm_bufio_clients_lock);
 
-       for (i = 0; i < 1 << DM_BUFIO_HASH_BITS; i++)
-               BUG_ON(!hlist_empty(&c->cache_hash[i]));
-
+       BUG_ON(!RB_EMPTY_ROOT(&c->buffer_tree));
        BUG_ON(c->need_reserved_buffers);
 
        while (!list_empty(&c->reserved_buffers)) {
@@ -1680,36 +1723,60 @@ void dm_bufio_client_destroy(struct dm_bufio_client *c)
                BUG_ON(c->n_buffers[i]);
 
        dm_io_client_destroy(c->dm_io);
-       vfree(c->cache_hash);
        kfree(c);
 }
 EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
 
-static void cleanup_old_buffers(void)
+static unsigned get_max_age_hz(void)
 {
-       unsigned long max_age = ACCESS_ONCE(dm_bufio_max_age);
-       struct dm_bufio_client *c;
+       unsigned max_age = ACCESS_ONCE(dm_bufio_max_age);
 
-       if (max_age > ULONG_MAX / HZ)
-               max_age = ULONG_MAX / HZ;
+       if (max_age > UINT_MAX / HZ)
+               max_age = UINT_MAX / HZ;
 
-       mutex_lock(&dm_bufio_clients_lock);
-       list_for_each_entry(c, &dm_bufio_all_clients, client_list) {
-               if (!dm_bufio_trylock(c))
-                       continue;
+       return max_age * HZ;
+}
 
-               while (!list_empty(&c->lru[LIST_CLEAN])) {
-                       struct dm_buffer *b;
-                       b = list_entry(c->lru[LIST_CLEAN].prev,
-                                      struct dm_buffer, lru_list);
-                       if (!__cleanup_old_buffer(b, 0, max_age * HZ))
-                               break;
-                       dm_bufio_cond_resched();
-               }
+static bool older_than(struct dm_buffer *b, unsigned long age_hz)
+{
+       return (jiffies - b->last_accessed) >= age_hz;
+}
+
+static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz)
+{
+       struct dm_buffer *b, *tmp;
+       unsigned retain_target = get_retain_buffers(c);
+       unsigned count;
+
+       dm_bufio_lock(c);
+
+       count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
+       list_for_each_entry_safe_reverse(b, tmp, &c->lru[LIST_CLEAN], lru_list) {
+               if (count <= retain_target)
+                       break;
+
+               if (!older_than(b, age_hz))
+                       break;
+
+               if (__try_evict_buffer(b, 0))
+                       count--;
 
-               dm_bufio_unlock(c);
                dm_bufio_cond_resched();
        }
+
+       dm_bufio_unlock(c);
+}
+
+static void cleanup_old_buffers(void)
+{
+       unsigned long max_age_hz = get_max_age_hz();
+       struct dm_bufio_client *c;
+
+       mutex_lock(&dm_bufio_clients_lock);
+
+       list_for_each_entry(c, &dm_bufio_all_clients, client_list)
+               __evict_old_buffers(c, max_age_hz);
+
        mutex_unlock(&dm_bufio_clients_lock);
 }
 
@@ -1834,6 +1901,9 @@ MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache");
 module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
 
+module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory");
+
 module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(peak_allocated_bytes, "Tracks the maximum allocated memory");
 
index aac0e2df06bec4c2412a8ff27787e0d89b6a6c4f..bed4ad4e1b7c037c107813eabb87d6bb4650b9b1 100644 (file)
@@ -19,6 +19,7 @@
 
 typedef dm_block_t __bitwise__ dm_oblock_t;
 typedef uint32_t __bitwise__ dm_cblock_t;
+typedef dm_block_t __bitwise__ dm_dblock_t;
 
 static inline dm_oblock_t to_oblock(dm_block_t b)
 {
@@ -40,4 +41,14 @@ static inline uint32_t from_cblock(dm_cblock_t b)
        return (__force uint32_t) b;
 }
 
+static inline dm_dblock_t to_dblock(dm_block_t b)
+{
+       return (__force dm_dblock_t) b;
+}
+
+static inline dm_block_t from_dblock(dm_dblock_t b)
+{
+       return (__force dm_block_t) b;
+}
+
 #endif /* DM_CACHE_BLOCK_TYPES_H */
index 06709257adde39e84c3ddd2aa0def729b974ba73..9fc616c2755ed752a50930e1095df8a7a34303f2 100644 (file)
@@ -109,7 +109,7 @@ struct dm_cache_metadata {
        dm_block_t discard_root;
 
        sector_t discard_block_size;
-       dm_oblock_t discard_nr_blocks;
+       dm_dblock_t discard_nr_blocks;
 
        sector_t data_block_size;
        dm_cblock_t cache_blocks;
@@ -329,7 +329,7 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
        disk_super->hint_root = cpu_to_le64(cmd->hint_root);
        disk_super->discard_root = cpu_to_le64(cmd->discard_root);
        disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size);
-       disk_super->discard_nr_blocks = cpu_to_le64(from_oblock(cmd->discard_nr_blocks));
+       disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks));
        disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE);
        disk_super->data_block_size = cpu_to_le32(cmd->data_block_size);
        disk_super->cache_blocks = cpu_to_le32(0);
@@ -528,7 +528,7 @@ static void read_superblock_fields(struct dm_cache_metadata *cmd,
        cmd->hint_root = le64_to_cpu(disk_super->hint_root);
        cmd->discard_root = le64_to_cpu(disk_super->discard_root);
        cmd->discard_block_size = le64_to_cpu(disk_super->discard_block_size);
-       cmd->discard_nr_blocks = to_oblock(le64_to_cpu(disk_super->discard_nr_blocks));
+       cmd->discard_nr_blocks = to_dblock(le64_to_cpu(disk_super->discard_nr_blocks));
        cmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
        cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks));
        strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name));
@@ -626,7 +626,7 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
        disk_super->hint_root = cpu_to_le64(cmd->hint_root);
        disk_super->discard_root = cpu_to_le64(cmd->discard_root);
        disk_super->discard_block_size = cpu_to_le64(cmd->discard_block_size);
-       disk_super->discard_nr_blocks = cpu_to_le64(from_oblock(cmd->discard_nr_blocks));
+       disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks));
        disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks));
        strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name));
        disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]);
@@ -797,15 +797,15 @@ out:
 
 int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
                                   sector_t discard_block_size,
-                                  dm_oblock_t new_nr_entries)
+                                  dm_dblock_t new_nr_entries)
 {
        int r;
 
        down_write(&cmd->root_lock);
        r = dm_bitset_resize(&cmd->discard_info,
                             cmd->discard_root,
-                            from_oblock(cmd->discard_nr_blocks),
-                            from_oblock(new_nr_entries),
+                            from_dblock(cmd->discard_nr_blocks),
+                            from_dblock(new_nr_entries),
                             false, &cmd->discard_root);
        if (!r) {
                cmd->discard_block_size = discard_block_size;
@@ -818,28 +818,28 @@ int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
        return r;
 }
 
-static int __set_discard(struct dm_cache_metadata *cmd, dm_oblock_t b)
+static int __set_discard(struct dm_cache_metadata *cmd, dm_dblock_t b)
 {
        return dm_bitset_set_bit(&cmd->discard_info, cmd->discard_root,
-                                from_oblock(b), &cmd->discard_root);
+                                from_dblock(b), &cmd->discard_root);
 }
 
-static int __clear_discard(struct dm_cache_metadata *cmd, dm_oblock_t b)
+static int __clear_discard(struct dm_cache_metadata *cmd, dm_dblock_t b)
 {
        return dm_bitset_clear_bit(&cmd->discard_info, cmd->discard_root,
-                                  from_oblock(b), &cmd->discard_root);
+                                  from_dblock(b), &cmd->discard_root);
 }
 
-static int __is_discarded(struct dm_cache_metadata *cmd, dm_oblock_t b,
+static int __is_discarded(struct dm_cache_metadata *cmd, dm_dblock_t b,
                          bool *is_discarded)
 {
        return dm_bitset_test_bit(&cmd->discard_info, cmd->discard_root,
-                                 from_oblock(b), &cmd->discard_root,
+                                 from_dblock(b), &cmd->discard_root,
                                  is_discarded);
 }
 
 static int __discard(struct dm_cache_metadata *cmd,
-                    dm_oblock_t dblock, bool discard)
+                    dm_dblock_t dblock, bool discard)
 {
        int r;
 
@@ -852,7 +852,7 @@ static int __discard(struct dm_cache_metadata *cmd,
 }
 
 int dm_cache_set_discard(struct dm_cache_metadata *cmd,
-                        dm_oblock_t dblock, bool discard)
+                        dm_dblock_t dblock, bool discard)
 {
        int r;
 
@@ -870,8 +870,8 @@ static int __load_discards(struct dm_cache_metadata *cmd,
        dm_block_t b;
        bool discard;
 
-       for (b = 0; b < from_oblock(cmd->discard_nr_blocks); b++) {
-               dm_oblock_t dblock = to_oblock(b);
+       for (b = 0; b < from_dblock(cmd->discard_nr_blocks); b++) {
+               dm_dblock_t dblock = to_dblock(b);
 
                if (cmd->clean_when_opened) {
                        r = __is_discarded(cmd, dblock, &discard);
index 7383c90ccdb809e72d904e4a14a642a3d34e1ed1..4ecc403be28370cce26052236b3d954ec0280a3f 100644 (file)
@@ -70,14 +70,14 @@ dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd);
 
 int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
                                   sector_t discard_block_size,
-                                  dm_oblock_t new_nr_entries);
+                                  dm_dblock_t new_nr_entries);
 
 typedef int (*load_discard_fn)(void *context, sector_t discard_block_size,
-                              dm_oblock_t dblock, bool discarded);
+                              dm_dblock_t dblock, bool discarded);
 int dm_cache_load_discards(struct dm_cache_metadata *cmd,
                           load_discard_fn fn, void *context);
 
-int dm_cache_set_discard(struct dm_cache_metadata *cmd, dm_oblock_t dblock, bool discard);
+int dm_cache_set_discard(struct dm_cache_metadata *cmd, dm_dblock_t dblock, bool discard);
 
 int dm_cache_remove_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock);
 int dm_cache_insert_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock, dm_oblock_t oblock);
index 0e385e40909e74fcde4da4ee5d785149101ad9cb..13f547a4eeb61f2715845090b8e2e5ce311c73d1 100644 (file)
@@ -181,24 +181,30 @@ static void queue_shift_down(struct queue *q)
  * Gives us the oldest entry of the lowest popoulated level.  If the first
  * level is emptied then we shift down one level.
  */
-static struct list_head *queue_pop(struct queue *q)
+static struct list_head *queue_peek(struct queue *q)
 {
        unsigned level;
-       struct list_head *r;
 
        for (level = 0; level < NR_QUEUE_LEVELS; level++)
-               if (!list_empty(q->qs + level)) {
-                       r = q->qs[level].next;
-                       list_del(r);
+               if (!list_empty(q->qs + level))
+                       return q->qs[level].next;
 
-                       /* have we just emptied the bottom level? */
-                       if (level == 0 && list_empty(q->qs))
-                               queue_shift_down(q);
+       return NULL;
+}
 
-                       return r;
-               }
+static struct list_head *queue_pop(struct queue *q)
+{
+       struct list_head *r = queue_peek(q);
 
-       return NULL;
+       if (r) {
+               list_del(r);
+
+               /* have we just emptied the bottom level? */
+               if (list_empty(q->qs))
+                       queue_shift_down(q);
+       }
+
+       return r;
 }
 
 static struct list_head *list_pop(struct list_head *lh)
@@ -383,13 +389,6 @@ struct mq_policy {
        unsigned generation;
        unsigned generation_period; /* in lookups (will probably change) */
 
-       /*
-        * Entries in the pre_cache whose hit count passes the promotion
-        * threshold move to the cache proper.  Working out the correct
-        * value for the promotion_threshold is crucial to this policy.
-        */
-       unsigned promote_threshold;
-
        unsigned discard_promote_adjustment;
        unsigned read_promote_adjustment;
        unsigned write_promote_adjustment;
@@ -406,6 +405,7 @@ struct mq_policy {
 #define DEFAULT_DISCARD_PROMOTE_ADJUSTMENT 1
 #define DEFAULT_READ_PROMOTE_ADJUSTMENT 4
 #define DEFAULT_WRITE_PROMOTE_ADJUSTMENT 8
+#define DISCOURAGE_DEMOTING_DIRTY_THRESHOLD 128
 
 /*----------------------------------------------------------------*/
 
@@ -518,6 +518,12 @@ static struct entry *pop(struct mq_policy *mq, struct queue *q)
        return e;
 }
 
+static struct entry *peek(struct queue *q)
+{
+       struct list_head *h = queue_peek(q);
+       return h ? container_of(h, struct entry, list) : NULL;
+}
+
 /*
  * Has this entry already been updated?
  */
@@ -570,10 +576,6 @@ static void check_generation(struct mq_policy *mq)
                                        break;
                        }
                }
-
-               mq->promote_threshold = nr ? total / nr : 1;
-               if (mq->promote_threshold * nr < total)
-                       mq->promote_threshold++;
        }
 }
 
@@ -640,6 +642,30 @@ static int demote_cblock(struct mq_policy *mq, dm_oblock_t *oblock)
        return 0;
 }
 
+/*
+ * Entries in the pre_cache whose hit count passes the promotion
+ * threshold move to the cache proper.  Working out the correct
+ * value for the promotion_threshold is crucial to this policy.
+ */
+static unsigned promote_threshold(struct mq_policy *mq)
+{
+       struct entry *e;
+
+       if (any_free_cblocks(mq))
+               return 0;
+
+       e = peek(&mq->cache_clean);
+       if (e)
+               return e->hit_count;
+
+       e = peek(&mq->cache_dirty);
+       if (e)
+               return e->hit_count + DISCOURAGE_DEMOTING_DIRTY_THRESHOLD;
+
+       /* This should never happen */
+       return 0;
+}
+
 /*
  * We modify the basic promotion_threshold depending on the specific io.
  *
@@ -653,7 +679,7 @@ static unsigned adjusted_promote_threshold(struct mq_policy *mq,
                                           bool discarded_oblock, int data_dir)
 {
        if (data_dir == READ)
-               return mq->promote_threshold + mq->read_promote_adjustment;
+               return promote_threshold(mq) + mq->read_promote_adjustment;
 
        if (discarded_oblock && (any_free_cblocks(mq) || any_clean_cblocks(mq))) {
                /*
@@ -663,7 +689,7 @@ static unsigned adjusted_promote_threshold(struct mq_policy *mq,
                return mq->discard_promote_adjustment;
        }
 
-       return mq->promote_threshold + mq->write_promote_adjustment;
+       return promote_threshold(mq) + mq->write_promote_adjustment;
 }
 
 static bool should_promote(struct mq_policy *mq, struct entry *e,
@@ -839,7 +865,8 @@ static int map(struct mq_policy *mq, dm_oblock_t oblock,
        if (e && in_cache(mq, e))
                r = cache_entry_found(mq, e, result);
 
-       else if (iot_pattern(&mq->tracker) == PATTERN_SEQUENTIAL)
+       else if (mq->tracker.thresholds[PATTERN_SEQUENTIAL] &&
+                iot_pattern(&mq->tracker) == PATTERN_SEQUENTIAL)
                result->op = POLICY_MISS;
 
        else if (e)
@@ -1230,7 +1257,6 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
        mq->tick = 0;
        mq->hit_count = 0;
        mq->generation = 0;
-       mq->promote_threshold = 0;
        mq->discard_promote_adjustment = DEFAULT_DISCARD_PROMOTE_ADJUSTMENT;
        mq->read_promote_adjustment = DEFAULT_READ_PROMOTE_ADJUSTMENT;
        mq->write_promote_adjustment = DEFAULT_WRITE_PROMOTE_ADJUSTMENT;
@@ -1265,7 +1291,7 @@ bad_pre_cache_init:
 
 static struct dm_cache_policy_type mq_policy_type = {
        .name = "mq",
-       .version = {1, 2, 0},
+       .version = {1, 3, 0},
        .hint_size = 4,
        .owner = THIS_MODULE,
        .create = mq_create
@@ -1273,7 +1299,7 @@ static struct dm_cache_policy_type mq_policy_type = {
 
 static struct dm_cache_policy_type default_policy_type = {
        .name = "default",
-       .version = {1, 2, 0},
+       .version = {1, 3, 0},
        .hint_size = 4,
        .owner = THIS_MODULE,
        .create = mq_create,
index 7130505c242550f3321448094e5b110987ca5969..1e96d7889f51eaa08b7d65b04c1a43e063931708 100644 (file)
@@ -95,7 +95,6 @@ static void dm_unhook_bio(struct dm_hook_info *h, struct bio *bio)
 
 /*----------------------------------------------------------------*/
 
-#define PRISON_CELLS 1024
 #define MIGRATION_POOL_SIZE 128
 #define COMMIT_PERIOD HZ
 #define MIGRATION_COUNT_WINDOW 10
@@ -237,8 +236,9 @@ struct cache {
        /*
         * origin_blocks entries, discarded if set.
         */
-       dm_oblock_t discard_nr_blocks;
+       dm_dblock_t discard_nr_blocks;
        unsigned long *discard_bitset;
+       uint32_t discard_block_size; /* a power of 2 times sectors per block */
 
        /*
         * Rather than reconstructing the table line for the status we just
@@ -310,6 +310,7 @@ struct dm_cache_migration {
        dm_cblock_t cblock;
 
        bool err:1;
+       bool discard:1;
        bool writeback:1;
        bool demote:1;
        bool promote:1;
@@ -433,11 +434,12 @@ static void prealloc_put_cell(struct prealloc *p, struct dm_bio_prison_cell *cel
 
 /*----------------------------------------------------------------*/
 
-static void build_key(dm_oblock_t oblock, struct dm_cell_key *key)
+static void build_key(dm_oblock_t begin, dm_oblock_t end, struct dm_cell_key *key)
 {
        key->virtual = 0;
        key->dev = 0;
-       key->block = from_oblock(oblock);
+       key->block_begin = from_oblock(begin);
+       key->block_end = from_oblock(end);
 }
 
 /*
@@ -447,15 +449,15 @@ static void build_key(dm_oblock_t oblock, struct dm_cell_key *key)
  */
 typedef void (*cell_free_fn)(void *context, struct dm_bio_prison_cell *cell);
 
-static int bio_detain(struct cache *cache, dm_oblock_t oblock,
-                     struct bio *bio, struct dm_bio_prison_cell *cell_prealloc,
-                     cell_free_fn free_fn, void *free_context,
-                     struct dm_bio_prison_cell **cell_result)
+static int bio_detain_range(struct cache *cache, dm_oblock_t oblock_begin, dm_oblock_t oblock_end,
+                           struct bio *bio, struct dm_bio_prison_cell *cell_prealloc,
+                           cell_free_fn free_fn, void *free_context,
+                           struct dm_bio_prison_cell **cell_result)
 {
        int r;
        struct dm_cell_key key;
 
-       build_key(oblock, &key);
+       build_key(oblock_begin, oblock_end, &key);
        r = dm_bio_detain(cache->prison, &key, bio, cell_prealloc, cell_result);
        if (r)
                free_fn(free_context, cell_prealloc);
@@ -463,6 +465,16 @@ static int bio_detain(struct cache *cache, dm_oblock_t oblock,
        return r;
 }
 
+static int bio_detain(struct cache *cache, dm_oblock_t oblock,
+                     struct bio *bio, struct dm_bio_prison_cell *cell_prealloc,
+                     cell_free_fn free_fn, void *free_context,
+                     struct dm_bio_prison_cell **cell_result)
+{
+       dm_oblock_t end = to_oblock(from_oblock(oblock) + 1ULL);
+       return bio_detain_range(cache, oblock, end, bio,
+                               cell_prealloc, free_fn, free_context, cell_result);
+}
+
 static int get_cell(struct cache *cache,
                    dm_oblock_t oblock,
                    struct prealloc *structs,
@@ -474,7 +486,7 @@ static int get_cell(struct cache *cache,
 
        cell_prealloc = prealloc_get_cell(structs);
 
-       build_key(oblock, &key);
+       build_key(oblock, to_oblock(from_oblock(oblock) + 1ULL), &key);
        r = dm_get_cell(cache->prison, &key, cell_prealloc, cell_result);
        if (r)
                prealloc_put_cell(structs, cell_prealloc);
@@ -524,33 +536,57 @@ static dm_block_t block_div(dm_block_t b, uint32_t n)
        return b;
 }
 
-static void set_discard(struct cache *cache, dm_oblock_t b)
+static dm_block_t oblocks_per_dblock(struct cache *cache)
+{
+       dm_block_t oblocks = cache->discard_block_size;
+
+       if (block_size_is_power_of_two(cache))
+               oblocks >>= cache->sectors_per_block_shift;
+       else
+               oblocks = block_div(oblocks, cache->sectors_per_block);
+
+       return oblocks;
+}
+
+static dm_dblock_t oblock_to_dblock(struct cache *cache, dm_oblock_t oblock)
+{
+       return to_dblock(block_div(from_oblock(oblock),
+                                  oblocks_per_dblock(cache)));
+}
+
+static dm_oblock_t dblock_to_oblock(struct cache *cache, dm_dblock_t dblock)
+{
+       return to_oblock(from_dblock(dblock) * oblocks_per_dblock(cache));
+}
+
+static void set_discard(struct cache *cache, dm_dblock_t b)
 {
        unsigned long flags;
 
+       BUG_ON(from_dblock(b) >= from_dblock(cache->discard_nr_blocks));
        atomic_inc(&cache->stats.discard_count);
 
        spin_lock_irqsave(&cache->lock, flags);
-       set_bit(from_oblock(b), cache->discard_bitset);
+       set_bit(from_dblock(b), cache->discard_bitset);
        spin_unlock_irqrestore(&cache->lock, flags);
 }
 
-static void clear_discard(struct cache *cache, dm_oblock_t b)
+static void clear_discard(struct cache *cache, dm_dblock_t b)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&cache->lock, flags);
-       clear_bit(from_oblock(b), cache->discard_bitset);
+       clear_bit(from_dblock(b), cache->discard_bitset);
        spin_unlock_irqrestore(&cache->lock, flags);
 }
 
-static bool is_discarded(struct cache *cache, dm_oblock_t b)
+static bool is_discarded(struct cache *cache, dm_dblock_t b)
 {
        int r;
        unsigned long flags;
 
        spin_lock_irqsave(&cache->lock, flags);
-       r = test_bit(from_oblock(b), cache->discard_bitset);
+       r = test_bit(from_dblock(b), cache->discard_bitset);
        spin_unlock_irqrestore(&cache->lock, flags);
 
        return r;
@@ -562,7 +598,8 @@ static bool is_discarded_oblock(struct cache *cache, dm_oblock_t b)
        unsigned long flags;
 
        spin_lock_irqsave(&cache->lock, flags);
-       r = test_bit(from_oblock(b), cache->discard_bitset);
+       r = test_bit(from_dblock(oblock_to_dblock(cache, b)),
+                    cache->discard_bitset);
        spin_unlock_irqrestore(&cache->lock, flags);
 
        return r;
@@ -687,7 +724,7 @@ static void remap_to_origin_clear_discard(struct cache *cache, struct bio *bio,
        check_if_tick_bio_needed(cache, bio);
        remap_to_origin(cache, bio);
        if (bio_data_dir(bio) == WRITE)
-               clear_discard(cache, oblock);
+               clear_discard(cache, oblock_to_dblock(cache, oblock));
 }
 
 static void remap_to_cache_dirty(struct cache *cache, struct bio *bio,
@@ -697,7 +734,7 @@ static void remap_to_cache_dirty(struct cache *cache, struct bio *bio,
        remap_to_cache(cache, bio, cblock);
        if (bio_data_dir(bio) == WRITE) {
                set_dirty(cache, oblock, cblock);
-               clear_discard(cache, oblock);
+               clear_discard(cache, oblock_to_dblock(cache, oblock));
        }
 }
 
@@ -951,10 +988,14 @@ static void migration_success_post_commit(struct dm_cache_migration *mg)
                }
 
        } else {
-               clear_dirty(cache, mg->new_oblock, mg->cblock);
-               if (mg->requeue_holder)
+               if (mg->requeue_holder) {
+                       clear_dirty(cache, mg->new_oblock, mg->cblock);
                        cell_defer(cache, mg->new_ocell, true);
-               else {
+               } else {
+                       /*
+                        * The block was promoted via an overwrite, so it's dirty.
+                        */
+                       set_dirty(cache, mg->new_oblock, mg->cblock);
                        bio_endio(mg->new_ocell->holder, 0);
                        cell_defer(cache, mg->new_ocell, false);
                }
@@ -978,7 +1019,7 @@ static void copy_complete(int read_err, unsigned long write_err, void *context)
        wake_worker(cache);
 }
 
-static void issue_copy_real(struct dm_cache_migration *mg)
+static void issue_copy(struct dm_cache_migration *mg)
 {
        int r;
        struct dm_io_region o_region, c_region;
@@ -1057,11 +1098,46 @@ static void avoid_copy(struct dm_cache_migration *mg)
        migration_success_pre_commit(mg);
 }
 
-static void issue_copy(struct dm_cache_migration *mg)
+static void calc_discard_block_range(struct cache *cache, struct bio *bio,
+                                    dm_dblock_t *b, dm_dblock_t *e)
+{
+       sector_t sb = bio->bi_iter.bi_sector;
+       sector_t se = bio_end_sector(bio);
+
+       *b = to_dblock(dm_sector_div_up(sb, cache->discard_block_size));
+
+       if (se - sb < cache->discard_block_size)
+               *e = *b;
+       else
+               *e = to_dblock(block_div(se, cache->discard_block_size));
+}
+
+static void issue_discard(struct dm_cache_migration *mg)
+{
+       dm_dblock_t b, e;
+       struct bio *bio = mg->new_ocell->holder;
+
+       calc_discard_block_range(mg->cache, bio, &b, &e);
+       while (b != e) {
+               set_discard(mg->cache, b);
+               b = to_dblock(from_dblock(b) + 1);
+       }
+
+       bio_endio(bio, 0);
+       cell_defer(mg->cache, mg->new_ocell, false);
+       free_migration(mg);
+}
+
+static void issue_copy_or_discard(struct dm_cache_migration *mg)
 {
        bool avoid;
        struct cache *cache = mg->cache;
 
+       if (mg->discard) {
+               issue_discard(mg);
+               return;
+       }
+
        if (mg->writeback || mg->demote)
                avoid = !is_dirty(cache, mg->cblock) ||
                        is_discarded_oblock(cache, mg->old_oblock);
@@ -1070,13 +1146,14 @@ static void issue_copy(struct dm_cache_migration *mg)
 
                avoid = is_discarded_oblock(cache, mg->new_oblock);
 
-               if (!avoid && bio_writes_complete_block(cache, bio)) {
+               if (writeback_mode(&cache->features) &&
+                   !avoid && bio_writes_complete_block(cache, bio)) {
                        issue_overwrite(mg, bio);
                        return;
                }
        }
 
-       avoid ? avoid_copy(mg) : issue_copy_real(mg);
+       avoid ? avoid_copy(mg) : issue_copy(mg);
 }
 
 static void complete_migration(struct dm_cache_migration *mg)
@@ -1161,6 +1238,7 @@ static void promote(struct cache *cache, struct prealloc *structs,
        struct dm_cache_migration *mg = prealloc_get_migration(structs);
 
        mg->err = false;
+       mg->discard = false;
        mg->writeback = false;
        mg->demote = false;
        mg->promote = true;
@@ -1184,6 +1262,7 @@ static void writeback(struct cache *cache, struct prealloc *structs,
        struct dm_cache_migration *mg = prealloc_get_migration(structs);
 
        mg->err = false;
+       mg->discard = false;
        mg->writeback = true;
        mg->demote = false;
        mg->promote = false;
@@ -1209,6 +1288,7 @@ static void demote_then_promote(struct cache *cache, struct prealloc *structs,
        struct dm_cache_migration *mg = prealloc_get_migration(structs);
 
        mg->err = false;
+       mg->discard = false;
        mg->writeback = false;
        mg->demote = true;
        mg->promote = true;
@@ -1237,6 +1317,7 @@ static void invalidate(struct cache *cache, struct prealloc *structs,
        struct dm_cache_migration *mg = prealloc_get_migration(structs);
 
        mg->err = false;
+       mg->discard = false;
        mg->writeback = false;
        mg->demote = true;
        mg->promote = false;
@@ -1253,6 +1334,26 @@ static void invalidate(struct cache *cache, struct prealloc *structs,
        quiesce_migration(mg);
 }
 
+static void discard(struct cache *cache, struct prealloc *structs,
+                   struct dm_bio_prison_cell *cell)
+{
+       struct dm_cache_migration *mg = prealloc_get_migration(structs);
+
+       mg->err = false;
+       mg->discard = true;
+       mg->writeback = false;
+       mg->demote = false;
+       mg->promote = false;
+       mg->requeue_holder = false;
+       mg->invalidate = false;
+       mg->cache = cache;
+       mg->old_ocell = NULL;
+       mg->new_ocell = cell;
+       mg->start_jiffies = jiffies;
+
+       quiesce_migration(mg);
+}
+
 /*----------------------------------------------------------------
  * bio processing
  *--------------------------------------------------------------*/
@@ -1286,31 +1387,27 @@ static void process_flush_bio(struct cache *cache, struct bio *bio)
        issue(cache, bio);
 }
 
-/*
- * People generally discard large parts of a device, eg, the whole device
- * when formatting.  Splitting these large discards up into cache block
- * sized ios and then quiescing (always neccessary for discard) takes too
- * long.
- *
- * We keep it simple, and allow any size of discard to come in, and just
- * mark off blocks on the discard bitset.  No passdown occurs!
- *
- * To implement passdown we need to change the bio_prison such that a cell
- * can have a key that spans many blocks.
- */
-static void process_discard_bio(struct cache *cache, struct bio *bio)
+static void process_discard_bio(struct cache *cache, struct prealloc *structs,
+                               struct bio *bio)
 {
-       dm_block_t start_block = dm_sector_div_up(bio->bi_iter.bi_sector,
-                                                 cache->sectors_per_block);
-       dm_block_t end_block = bio_end_sector(bio);
-       dm_block_t b;
+       int r;
+       dm_dblock_t b, e;
+       struct dm_bio_prison_cell *cell_prealloc, *new_ocell;
 
-       end_block = block_div(end_block, cache->sectors_per_block);
+       calc_discard_block_range(cache, bio, &b, &e);
+       if (b == e) {
+               bio_endio(bio, 0);
+               return;
+       }
 
-       for (b = start_block; b < end_block; b++)
-               set_discard(cache, to_oblock(b));
+       cell_prealloc = prealloc_get_cell(structs);
+       r = bio_detain_range(cache, dblock_to_oblock(cache, b), dblock_to_oblock(cache, e), bio, cell_prealloc,
+                            (cell_free_fn) prealloc_put_cell,
+                            structs, &new_ocell);
+       if (r > 0)
+               return;
 
-       bio_endio(bio, 0);
+       discard(cache, structs, new_ocell);
 }
 
 static bool spare_migration_bandwidth(struct cache *cache)
@@ -1340,9 +1437,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
        dm_oblock_t block = get_bio_block(cache, bio);
        struct dm_bio_prison_cell *cell_prealloc, *old_ocell, *new_ocell;
        struct policy_result lookup_result;
-       bool discarded_block = is_discarded_oblock(cache, block);
        bool passthrough = passthrough_mode(&cache->features);
-       bool can_migrate = !passthrough && (discarded_block || spare_migration_bandwidth(cache));
+       bool discarded_block, can_migrate;
 
        /*
         * Check to see if that block is currently migrating.
@@ -1354,6 +1450,9 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
        if (r > 0)
                return;
 
+       discarded_block = is_discarded_oblock(cache, block);
+       can_migrate = !passthrough && (discarded_block || spare_migration_bandwidth(cache));
+
        r = policy_map(cache->policy, block, true, can_migrate, discarded_block,
                       bio, &lookup_result);
 
@@ -1500,7 +1599,7 @@ static void process_deferred_bios(struct cache *cache)
                if (bio->bi_rw & REQ_FLUSH)
                        process_flush_bio(cache, bio);
                else if (bio->bi_rw & REQ_DISCARD)
-                       process_discard_bio(cache, bio);
+                       process_discard_bio(cache, &structs, bio);
                else
                        process_bio(cache, &structs, bio);
        }
@@ -1715,7 +1814,7 @@ static void do_worker(struct work_struct *ws)
                        process_invalidation_requests(cache);
                }
 
-               process_migrations(cache, &cache->quiesced_migrations, issue_copy);
+               process_migrations(cache, &cache->quiesced_migrations, issue_copy_or_discard);
                process_migrations(cache, &cache->completed_migrations, complete_migration);
 
                if (commit_if_needed(cache)) {
@@ -2180,6 +2279,45 @@ static int create_cache_policy(struct cache *cache, struct cache_args *ca,
        return 0;
 }
 
+/*
+ * We want the discard block size to be at least the size of the cache
+ * block size and have no more than 2^14 discard blocks across the origin.
+ */
+#define MAX_DISCARD_BLOCKS (1 << 14)
+
+static bool too_many_discard_blocks(sector_t discard_block_size,
+                                   sector_t origin_size)
+{
+       (void) sector_div(origin_size, discard_block_size);
+
+       return origin_size > MAX_DISCARD_BLOCKS;
+}
+
+static sector_t calculate_discard_block_size(sector_t cache_block_size,
+                                            sector_t origin_size)
+{
+       sector_t discard_block_size = cache_block_size;
+
+       if (origin_size)
+               while (too_many_discard_blocks(discard_block_size, origin_size))
+                       discard_block_size *= 2;
+
+       return discard_block_size;
+}
+
+static void set_cache_size(struct cache *cache, dm_cblock_t size)
+{
+       dm_block_t nr_blocks = from_cblock(size);
+
+       if (nr_blocks > (1 << 20) && cache->cache_size != size)
+               DMWARN_LIMIT("You have created a cache device with a lot of individual cache blocks (%llu)\n"
+                            "All these mappings can consume a lot of kernel memory, and take some time to read/write.\n"
+                            "Please consider increasing the cache block size to reduce the overall cache block count.",
+                            (unsigned long long) nr_blocks);
+
+       cache->cache_size = size;
+}
+
 #define DEFAULT_MIGRATION_THRESHOLD 2048
 
 static int cache_create(struct cache_args *ca, struct cache **result)
@@ -2204,8 +2342,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        ti->num_discard_bios = 1;
        ti->discards_supported = true;
        ti->discard_zeroes_data_unsupported = true;
-       /* Discard bios must be split on a block boundary */
-       ti->split_discard_bios = true;
+       ti->split_discard_bios = false;
 
        cache->features = ca->features;
        ti->per_bio_data_size = get_per_bio_data_size(cache);
@@ -2235,10 +2372,10 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
                cache->sectors_per_block_shift = -1;
                cache_size = block_div(cache_size, ca->block_size);
-               cache->cache_size = to_cblock(cache_size);
+               set_cache_size(cache, to_cblock(cache_size));
        } else {
                cache->sectors_per_block_shift = __ffs(ca->block_size);
-               cache->cache_size = to_cblock(ca->cache_sectors >> cache->sectors_per_block_shift);
+               set_cache_size(cache, to_cblock(ca->cache_sectors >> cache->sectors_per_block_shift));
        }
 
        r = create_cache_policy(cache, ca, error);
@@ -2303,13 +2440,17 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        }
        clear_bitset(cache->dirty_bitset, from_cblock(cache->cache_size));
 
-       cache->discard_nr_blocks = cache->origin_blocks;
-       cache->discard_bitset = alloc_bitset(from_oblock(cache->discard_nr_blocks));
+       cache->discard_block_size =
+               calculate_discard_block_size(cache->sectors_per_block,
+                                            cache->origin_sectors);
+       cache->discard_nr_blocks = to_dblock(dm_sector_div_up(cache->origin_sectors,
+                                                             cache->discard_block_size));
+       cache->discard_bitset = alloc_bitset(from_dblock(cache->discard_nr_blocks));
        if (!cache->discard_bitset) {
                *error = "could not allocate discard bitset";
                goto bad;
        }
-       clear_bitset(cache->discard_bitset, from_oblock(cache->discard_nr_blocks));
+       clear_bitset(cache->discard_bitset, from_dblock(cache->discard_nr_blocks));
 
        cache->copier = dm_kcopyd_client_create(&dm_kcopyd_throttle);
        if (IS_ERR(cache->copier)) {
@@ -2327,7 +2468,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        INIT_DELAYED_WORK(&cache->waker, do_waker);
        cache->last_commit_jiffies = jiffies;
 
-       cache->prison = dm_bio_prison_create(PRISON_CELLS);
+       cache->prison = dm_bio_prison_create();
        if (!cache->prison) {
                *error = "could not create bio prison";
                goto bad;
@@ -2549,11 +2690,11 @@ static int __cache_map(struct cache *cache, struct bio *bio, struct dm_bio_priso
 static int cache_map(struct dm_target *ti, struct bio *bio)
 {
        int r;
-       struct dm_bio_prison_cell *cell;
+       struct dm_bio_prison_cell *cell = NULL;
        struct cache *cache = ti->private;
 
        r = __cache_map(cache, bio, &cell);
-       if (r == DM_MAPIO_REMAPPED) {
+       if (r == DM_MAPIO_REMAPPED && cell) {
                inc_ds(cache, bio, cell);
                cell_defer(cache, cell, false);
        }
@@ -2599,16 +2740,16 @@ static int write_discard_bitset(struct cache *cache)
 {
        unsigned i, r;
 
-       r = dm_cache_discard_bitset_resize(cache->cmd, cache->sectors_per_block,
-                                          cache->origin_blocks);
+       r = dm_cache_discard_bitset_resize(cache->cmd, cache->discard_block_size,
+                                          cache->discard_nr_blocks);
        if (r) {
                DMERR("could not resize on-disk discard bitset");
                return r;
        }
 
-       for (i = 0; i < from_oblock(cache->discard_nr_blocks); i++) {
-               r = dm_cache_set_discard(cache->cmd, to_oblock(i),
-                                        is_discarded(cache, to_oblock(i)));
+       for (i = 0; i < from_dblock(cache->discard_nr_blocks); i++) {
+               r = dm_cache_set_discard(cache->cmd, to_dblock(i),
+                                        is_discarded(cache, to_dblock(i)));
                if (r)
                        return r;
        }
@@ -2680,15 +2821,86 @@ static int load_mapping(void *context, dm_oblock_t oblock, dm_cblock_t cblock,
        return 0;
 }
 
+/*
+ * The discard block size in the on disk metadata is not
+ * neccessarily the same as we're currently using.  So we have to
+ * be careful to only set the discarded attribute if we know it
+ * covers a complete block of the new size.
+ */
+struct discard_load_info {
+       struct cache *cache;
+
+       /*
+        * These blocks are sized using the on disk dblock size, rather
+        * than the current one.
+        */
+       dm_block_t block_size;
+       dm_block_t discard_begin, discard_end;
+};
+
+static void discard_load_info_init(struct cache *cache,
+                                  struct discard_load_info *li)
+{
+       li->cache = cache;
+       li->discard_begin = li->discard_end = 0;
+}
+
+static void set_discard_range(struct discard_load_info *li)
+{
+       sector_t b, e;
+
+       if (li->discard_begin == li->discard_end)
+               return;
+
+       /*
+        * Convert to sectors.
+        */
+       b = li->discard_begin * li->block_size;
+       e = li->discard_end * li->block_size;
+
+       /*
+        * Then convert back to the current dblock size.
+        */
+       b = dm_sector_div_up(b, li->cache->discard_block_size);
+       sector_div(e, li->cache->discard_block_size);
+
+       /*
+        * The origin may have shrunk, so we need to check we're still in
+        * bounds.
+        */
+       if (e > from_dblock(li->cache->discard_nr_blocks))
+               e = from_dblock(li->cache->discard_nr_blocks);
+
+       for (; b < e; b++)
+               set_discard(li->cache, to_dblock(b));
+}
+
 static int load_discard(void *context, sector_t discard_block_size,
-                       dm_oblock_t oblock, bool discard)
+                       dm_dblock_t dblock, bool discard)
 {
-       struct cache *cache = context;
+       struct discard_load_info *li = context;
 
-       if (discard)
-               set_discard(cache, oblock);
-       else
-               clear_discard(cache, oblock);
+       li->block_size = discard_block_size;
+
+       if (discard) {
+               if (from_dblock(dblock) == li->discard_end)
+                       /*
+                        * We're already in a discard range, just extend it.
+                        */
+                       li->discard_end = li->discard_end + 1ULL;
+
+               else {
+                       /*
+                        * Emit the old range and start a new one.
+                        */
+                       set_discard_range(li);
+                       li->discard_begin = from_dblock(dblock);
+                       li->discard_end = li->discard_begin + 1ULL;
+               }
+       } else {
+               set_discard_range(li);
+               li->discard_begin = li->discard_end = 0;
+       }
 
        return 0;
 }
@@ -2730,7 +2942,7 @@ static int resize_cache_dev(struct cache *cache, dm_cblock_t new_size)
                return r;
        }
 
-       cache->cache_size = new_size;
+       set_cache_size(cache, new_size);
 
        return 0;
 }
@@ -2772,11 +2984,22 @@ static int cache_preresume(struct dm_target *ti)
        }
 
        if (!cache->loaded_discards) {
-               r = dm_cache_load_discards(cache->cmd, load_discard, cache);
+               struct discard_load_info li;
+
+               /*
+                * The discard bitset could have been resized, or the
+                * discard block size changed.  To be safe we start by
+                * setting every dblock to not discarded.
+                */
+               clear_bitset(cache->discard_bitset, from_dblock(cache->discard_nr_blocks));
+
+               discard_load_info_init(cache, &li);
+               r = dm_cache_load_discards(cache->cmd, load_discard, &li);
                if (r) {
                        DMERR("could not load origin discards");
                        return r;
                }
+               set_discard_range(&li);
 
                cache->loaded_discards = true;
        }
@@ -3079,8 +3302,9 @@ static void set_discard_limits(struct cache *cache, struct queue_limits *limits)
        /*
         * FIXME: these limits may be incompatible with the cache device
         */
-       limits->max_discard_sectors = cache->sectors_per_block;
-       limits->discard_granularity = cache->sectors_per_block << SECTOR_SHIFT;
+       limits->max_discard_sectors = min_t(sector_t, cache->discard_block_size * 1024,
+                                           cache->origin_sectors);
+       limits->discard_granularity = cache->discard_block_size << SECTOR_SHIFT;
 }
 
 static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
@@ -3104,7 +3328,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type cache_target = {
        .name = "cache",
-       .version = {1, 5, 0},
+       .version = {1, 6, 0},
        .module = THIS_MODULE,
        .ctr = cache_ctr,
        .dtr = cache_dtr,
index fc93b9330af4f7195768b67525fd504dd8701395..08981be7baa183dbe963b6e38cd4866f34e278a7 100644 (file)
@@ -705,7 +705,7 @@ static int crypt_iv_tcw_whitening(struct crypt_config *cc,
        for (i = 0; i < ((1 << SECTOR_SHIFT) / 8); i++)
                crypto_xor(data + i * 8, buf, 8);
 out:
-       memset(buf, 0, sizeof(buf));
+       memzero_explicit(buf, sizeof(buf));
        return r;
 }
 
index 0be9381365d7a7fb6b7672d91246b88677ff489e..73f791bb9ea4f06bd6c45da8356ba476a3ef76c3 100644 (file)
@@ -684,11 +684,14 @@ static void __dev_status(struct mapped_device *md, struct dm_ioctl *param)
        int srcu_idx;
 
        param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG |
-                         DM_ACTIVE_PRESENT_FLAG);
+                         DM_ACTIVE_PRESENT_FLAG | DM_INTERNAL_SUSPEND_FLAG);
 
        if (dm_suspended_md(md))
                param->flags |= DM_SUSPEND_FLAG;
 
+       if (dm_suspended_internally_md(md))
+               param->flags |= DM_INTERNAL_SUSPEND_FLAG;
+
        if (dm_test_deferred_remove_flag(md))
                param->flags |= DM_DEFERRED_REMOVE;
 
index 4857fa4a5484ba8e4ae743f2e8d4a48205229875..07c0fa0fa284fbdc9e86673c219f99cd07a35f77 100644 (file)
@@ -789,8 +789,7 @@ struct dm_raid_superblock {
        __le32 layout;
        __le32 stripe_sectors;
 
-       __u8 pad[452];          /* Round struct to 512 bytes. */
-                               /* Always set to 0 when writing. */
+       /* Remainder of a logical block is zero-filled when writing (see super_sync()). */
 } __packed;
 
 static int read_disk_sb(struct md_rdev *rdev, int size)
@@ -827,7 +826,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
                    test_bit(Faulty, &(rs->dev[i].rdev.flags)))
                        failed_devices |= (1ULL << i);
 
-       memset(sb, 0, sizeof(*sb));
+       memset(sb + 1, 0, rdev->sb_size - sizeof(*sb));
 
        sb->magic = cpu_to_le32(DM_RAID_MAGIC);
        sb->features = cpu_to_le32(0);  /* No features yet */
@@ -862,7 +861,11 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
        uint64_t events_sb, events_refsb;
 
        rdev->sb_start = 0;
-       rdev->sb_size = sizeof(*sb);
+       rdev->sb_size = bdev_logical_block_size(rdev->meta_bdev);
+       if (rdev->sb_size < sizeof(*sb) || rdev->sb_size > PAGE_SIZE) {
+               DMERR("superblock size of a logical block is no longer valid");
+               return -EINVAL;
+       }
 
        ret = read_disk_sb(rdev, rdev->sb_size);
        if (ret)
@@ -1169,8 +1172,12 @@ static void configure_discard_support(struct dm_target *ti, struct raid_set *rs)
        raid456 = (rs->md.level == 4 || rs->md.level == 5 || rs->md.level == 6);
 
        for (i = 0; i < rs->md.raid_disks; i++) {
-               struct request_queue *q = bdev_get_queue(rs->dev[i].rdev.bdev);
+               struct request_queue *q;
+
+               if (!rs->dev[i].rdev.bdev)
+                       continue;
 
+               q = bdev_get_queue(rs->dev[i].rdev.bdev);
                if (!q || !blk_queue_discard(q))
                        return;
 
index 87f86c77b0940256aff09a4e26de8805d52b9dde..f478a4c96d2f55cb2cf75abe50bfc2ce365c2a8e 100644 (file)
@@ -824,7 +824,7 @@ static int message_stats_create(struct mapped_device *md,
                return 1;
 
        id = dm_stats_create(dm_get_stats(md), start, end, step, program_id, aux_data,
-                            dm_internal_suspend, dm_internal_resume, md);
+                            dm_internal_suspend_fast, dm_internal_resume_fast, md);
        if (id < 0)
                return id;
 
index d1600d2aa2e2e6983643ef0ef864195f858d4f9d..f8b37d4c05d8c301658a42c116110d1b63fc9323 100644 (file)
@@ -159,8 +159,10 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                sc->stripes_shift = __ffs(stripes);
 
        r = dm_set_target_max_io_len(ti, chunk_size);
-       if (r)
+       if (r) {
+               kfree(sc);
                return r;
+       }
 
        ti->num_flush_bios = stripes;
        ti->num_discard_bios = stripes;
index b2bd1ebf4562902aba2b747c742a5f4da3f659e1..3afae9e062f842687855fb11ec9b0cca3b1c8580 100644 (file)
@@ -1521,18 +1521,32 @@ fmode_t dm_table_get_mode(struct dm_table *t)
 }
 EXPORT_SYMBOL(dm_table_get_mode);
 
-static void suspend_targets(struct dm_table *t, unsigned postsuspend)
+enum suspend_mode {
+       PRESUSPEND,
+       PRESUSPEND_UNDO,
+       POSTSUSPEND,
+};
+
+static void suspend_targets(struct dm_table *t, enum suspend_mode mode)
 {
        int i = t->num_targets;
        struct dm_target *ti = t->targets;
 
        while (i--) {
-               if (postsuspend) {
+               switch (mode) {
+               case PRESUSPEND:
+                       if (ti->type->presuspend)
+                               ti->type->presuspend(ti);
+                       break;
+               case PRESUSPEND_UNDO:
+                       if (ti->type->presuspend_undo)
+                               ti->type->presuspend_undo(ti);
+                       break;
+               case POSTSUSPEND:
                        if (ti->type->postsuspend)
                                ti->type->postsuspend(ti);
-               } else if (ti->type->presuspend)
-                       ti->type->presuspend(ti);
-
+                       break;
+               }
                ti++;
        }
 }
@@ -1542,7 +1556,15 @@ void dm_table_presuspend_targets(struct dm_table *t)
        if (!t)
                return;
 
-       suspend_targets(t, 0);
+       suspend_targets(t, PRESUSPEND);
+}
+
+void dm_table_presuspend_undo_targets(struct dm_table *t)
+{
+       if (!t)
+               return;
+
+       suspend_targets(t, PRESUSPEND_UNDO);
 }
 
 void dm_table_postsuspend_targets(struct dm_table *t)
@@ -1550,7 +1572,7 @@ void dm_table_postsuspend_targets(struct dm_table *t)
        if (!t)
                return;
 
-       suspend_targets(t, 1);
+       suspend_targets(t, POSTSUSPEND);
 }
 
 int dm_table_resume_targets(struct dm_table *t)
index e9d33ad59df5e21a9fcdae85e96a27ccb93156cd..43adbb863f5a9e5426dc0641f8c12ba696b09e10 100644 (file)
@@ -1384,42 +1384,38 @@ static bool __snapshotted_since(struct dm_thin_device *td, uint32_t time)
 }
 
 int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
-                      int can_block, struct dm_thin_lookup_result *result)
+                      int can_issue_io, struct dm_thin_lookup_result *result)
 {
-       int r = -EINVAL;
-       uint64_t block_time = 0;
+       int r;
        __le64 value;
        struct dm_pool_metadata *pmd = td->pmd;
        dm_block_t keys[2] = { td->id, block };
        struct dm_btree_info *info;
 
-       if (can_block) {
-               down_read(&pmd->root_lock);
-               info = &pmd->info;
-       } else if (down_read_trylock(&pmd->root_lock))
-               info = &pmd->nb_info;
-       else
-               return -EWOULDBLOCK;
-
        if (pmd->fail_io)
-               goto out;
+               return -EINVAL;
 
-       r = dm_btree_lookup(info, pmd->root, keys, &value);
-       if (!r)
-               block_time = le64_to_cpu(value);
+       down_read(&pmd->root_lock);
 
-out:
-       up_read(&pmd->root_lock);
+       if (can_issue_io) {
+               info = &pmd->info;
+       } else
+               info = &pmd->nb_info;
 
+       r = dm_btree_lookup(info, pmd->root, keys, &value);
        if (!r) {
+               uint64_t block_time = 0;
                dm_block_t exception_block;
                uint32_t exception_time;
+
+               block_time = le64_to_cpu(value);
                unpack_block_time(block_time, &exception_block,
                                  &exception_time);
                result->block = exception_block;
                result->shared = __snapshotted_since(td, exception_time);
        }
 
+       up_read(&pmd->root_lock);
        return r;
 }
 
@@ -1813,3 +1809,8 @@ bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd)
 
        return needs_check;
 }
+
+void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd)
+{
+       dm_tm_issue_prefetches(pmd->tm);
+}
index e3c857db195a7453d192f5f55cfb766a046a789a..921d15ee56a0c687bd09e54846d90f2bbb082c86 100644 (file)
@@ -139,12 +139,12 @@ struct dm_thin_lookup_result {
 
 /*
  * Returns:
- *   -EWOULDBLOCK iff @can_block is set and would block.
+ *   -EWOULDBLOCK iff @can_issue_io is set and would issue IO
  *   -ENODATA iff that mapping is not present.
  *   0 success
  */
 int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
-                      int can_block, struct dm_thin_lookup_result *result);
+                      int can_issue_io, struct dm_thin_lookup_result *result);
 
 /*
  * Obtain an unused block.
@@ -213,6 +213,11 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
 int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd);
 bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd);
 
+/*
+ * Issue any prefetches that may be useful.
+ */
+void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd);
+
 /*----------------------------------------------------------------*/
 
 #endif
index 4843801173fe11a99519b59dd808e46e02425ee4..8735543eacdb9ae0961ed841c3f8e81628100520 100644 (file)
 #include <linux/device-mapper.h>
 #include <linux/dm-io.h>
 #include <linux/dm-kcopyd.h>
+#include <linux/log2.h>
 #include <linux/list.h>
 #include <linux/rculist.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/sort.h>
 #include <linux/rbtree.h>
 
 #define        DM_MSG_PREFIX   "thin"
@@ -25,7 +27,6 @@
  */
 #define ENDIO_HOOK_POOL_SIZE 1024
 #define MAPPING_POOL_SIZE 1024
-#define PRISON_CELLS 1024
 #define COMMIT_PERIOD HZ
 #define NO_SPACE_TIMEOUT_SECS 60
 
@@ -114,7 +115,8 @@ static void build_data_key(struct dm_thin_device *td,
 {
        key->virtual = 0;
        key->dev = dm_thin_dev_id(td);
-       key->block = b;
+       key->block_begin = b;
+       key->block_end = b + 1ULL;
 }
 
 static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
@@ -122,7 +124,55 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,
 {
        key->virtual = 1;
        key->dev = dm_thin_dev_id(td);
-       key->block = b;
+       key->block_begin = b;
+       key->block_end = b + 1ULL;
+}
+
+/*----------------------------------------------------------------*/
+
+#define THROTTLE_THRESHOLD (1 * HZ)
+
+struct throttle {
+       struct rw_semaphore lock;
+       unsigned long threshold;
+       bool throttle_applied;
+};
+
+static void throttle_init(struct throttle *t)
+{
+       init_rwsem(&t->lock);
+       t->throttle_applied = false;
+}
+
+static void throttle_work_start(struct throttle *t)
+{
+       t->threshold = jiffies + THROTTLE_THRESHOLD;
+}
+
+static void throttle_work_update(struct throttle *t)
+{
+       if (!t->throttle_applied && jiffies > t->threshold) {
+               down_write(&t->lock);
+               t->throttle_applied = true;
+       }
+}
+
+static void throttle_work_complete(struct throttle *t)
+{
+       if (t->throttle_applied) {
+               t->throttle_applied = false;
+               up_write(&t->lock);
+       }
+}
+
+static void throttle_lock(struct throttle *t)
+{
+       down_read(&t->lock);
+}
+
+static void throttle_unlock(struct throttle *t)
+{
+       up_read(&t->lock);
 }
 
 /*----------------------------------------------------------------*/
@@ -155,8 +205,11 @@ struct pool_features {
 
 struct thin_c;
 typedef void (*process_bio_fn)(struct thin_c *tc, struct bio *bio);
+typedef void (*process_cell_fn)(struct thin_c *tc, struct dm_bio_prison_cell *cell);
 typedef void (*process_mapping_fn)(struct dm_thin_new_mapping *m);
 
+#define CELL_SORT_ARRAY_SIZE 8192
+
 struct pool {
        struct list_head list;
        struct dm_target *ti;   /* Only set if a pool target is bound */
@@ -171,11 +224,13 @@ struct pool {
 
        struct pool_features pf;
        bool low_water_triggered:1;     /* A dm event has been sent */
+       bool suspended:1;
 
        struct dm_bio_prison *prison;
        struct dm_kcopyd_client *copier;
 
        struct workqueue_struct *wq;
+       struct throttle throttle;
        struct work_struct worker;
        struct delayed_work waker;
        struct delayed_work no_space_timeout;
@@ -198,8 +253,13 @@ struct pool {
        process_bio_fn process_bio;
        process_bio_fn process_discard;
 
+       process_cell_fn process_cell;
+       process_cell_fn process_discard_cell;
+
        process_mapping_fn process_prepared_mapping;
        process_mapping_fn process_prepared_discard;
+
+       struct dm_bio_prison_cell *cell_sort_array[CELL_SORT_ARRAY_SIZE];
 };
 
 static enum pool_mode get_pool_mode(struct pool *pool);
@@ -232,8 +292,11 @@ struct thin_c {
 
        struct pool *pool;
        struct dm_thin_device *td;
+       struct mapped_device *thin_md;
+
        bool requeue_mode:1;
        spinlock_t lock;
+       struct list_head deferred_cells;
        struct bio_list deferred_bio_list;
        struct bio_list retry_on_resume_list;
        struct rb_root sort_bio_list; /* sorted list of deferred bios */
@@ -290,6 +353,15 @@ static void cell_release(struct pool *pool,
        dm_bio_prison_free_cell(pool->prison, cell);
 }
 
+static void cell_visit_release(struct pool *pool,
+                              void (*fn)(void *, struct dm_bio_prison_cell *),
+                              void *context,
+                              struct dm_bio_prison_cell *cell)
+{
+       dm_cell_visit_release(pool->prison, fn, context, cell);
+       dm_bio_prison_free_cell(pool->prison, cell);
+}
+
 static void cell_release_no_holder(struct pool *pool,
                                   struct dm_bio_prison_cell *cell,
                                   struct bio_list *bios)
@@ -298,19 +370,6 @@ static void cell_release_no_holder(struct pool *pool,
        dm_bio_prison_free_cell(pool->prison, cell);
 }
 
-static void cell_defer_no_holder_no_free(struct thin_c *tc,
-                                        struct dm_bio_prison_cell *cell)
-{
-       struct pool *pool = tc->pool;
-       unsigned long flags;
-
-       spin_lock_irqsave(&tc->lock, flags);
-       dm_cell_release_no_holder(pool->prison, cell, &tc->deferred_bio_list);
-       spin_unlock_irqrestore(&tc->lock, flags);
-
-       wake_worker(pool);
-}
-
 static void cell_error_with_code(struct pool *pool,
                                 struct dm_bio_prison_cell *cell, int error_code)
 {
@@ -323,6 +382,16 @@ static void cell_error(struct pool *pool, struct dm_bio_prison_cell *cell)
        cell_error_with_code(pool, cell, -EIO);
 }
 
+static void cell_success(struct pool *pool, struct dm_bio_prison_cell *cell)
+{
+       cell_error_with_code(pool, cell, 0);
+}
+
+static void cell_requeue(struct pool *pool, struct dm_bio_prison_cell *cell)
+{
+       cell_error_with_code(pool, cell, DM_ENDIO_REQUEUE);
+}
+
 /*----------------------------------------------------------------*/
 
 /*
@@ -393,44 +462,65 @@ struct dm_thin_endio_hook {
        struct rb_node rb_node;
 };
 
-static void requeue_bio_list(struct thin_c *tc, struct bio_list *master)
+static void __merge_bio_list(struct bio_list *bios, struct bio_list *master)
+{
+       bio_list_merge(bios, master);
+       bio_list_init(master);
+}
+
+static void error_bio_list(struct bio_list *bios, int error)
 {
        struct bio *bio;
+
+       while ((bio = bio_list_pop(bios)))
+               bio_endio(bio, error);
+}
+
+static void error_thin_bio_list(struct thin_c *tc, struct bio_list *master, int error)
+{
        struct bio_list bios;
        unsigned long flags;
 
        bio_list_init(&bios);
 
        spin_lock_irqsave(&tc->lock, flags);
-       bio_list_merge(&bios, master);
-       bio_list_init(master);
+       __merge_bio_list(&bios, master);
        spin_unlock_irqrestore(&tc->lock, flags);
 
-       while ((bio = bio_list_pop(&bios)))
-               bio_endio(bio, DM_ENDIO_REQUEUE);
+       error_bio_list(&bios, error);
 }
 
-static void requeue_io(struct thin_c *tc)
+static void requeue_deferred_cells(struct thin_c *tc)
 {
-       requeue_bio_list(tc, &tc->deferred_bio_list);
-       requeue_bio_list(tc, &tc->retry_on_resume_list);
+       struct pool *pool = tc->pool;
+       unsigned long flags;
+       struct list_head cells;
+       struct dm_bio_prison_cell *cell, *tmp;
+
+       INIT_LIST_HEAD(&cells);
+
+       spin_lock_irqsave(&tc->lock, flags);
+       list_splice_init(&tc->deferred_cells, &cells);
+       spin_unlock_irqrestore(&tc->lock, flags);
+
+       list_for_each_entry_safe(cell, tmp, &cells, user_list)
+               cell_requeue(pool, cell);
 }
 
-static void error_thin_retry_list(struct thin_c *tc)
+static void requeue_io(struct thin_c *tc)
 {
-       struct bio *bio;
-       unsigned long flags;
        struct bio_list bios;
+       unsigned long flags;
 
        bio_list_init(&bios);
 
        spin_lock_irqsave(&tc->lock, flags);
-       bio_list_merge(&bios, &tc->retry_on_resume_list);
-       bio_list_init(&tc->retry_on_resume_list);
+       __merge_bio_list(&bios, &tc->deferred_bio_list);
+       __merge_bio_list(&bios, &tc->retry_on_resume_list);
        spin_unlock_irqrestore(&tc->lock, flags);
 
-       while ((bio = bio_list_pop(&bios)))
-               bio_io_error(bio);
+       error_bio_list(&bios, DM_ENDIO_REQUEUE);
+       requeue_deferred_cells(tc);
 }
 
 static void error_retry_list(struct pool *pool)
@@ -439,7 +529,7 @@ static void error_retry_list(struct pool *pool)
 
        rcu_read_lock();
        list_for_each_entry_rcu(tc, &pool->active_thins, list)
-               error_thin_retry_list(tc);
+               error_thin_bio_list(tc, &tc->retry_on_resume_list, -EIO);
        rcu_read_unlock();
 }
 
@@ -629,33 +719,75 @@ static void overwrite_endio(struct bio *bio, int err)
  */
 
 /*
- * This sends the bios in the cell back to the deferred_bios list.
+ * This sends the bios in the cell, except the original holder, back
+ * to the deferred_bios list.
  */
-static void cell_defer(struct thin_c *tc, struct dm_bio_prison_cell *cell)
+static void cell_defer_no_holder(struct thin_c *tc, struct dm_bio_prison_cell *cell)
 {
        struct pool *pool = tc->pool;
        unsigned long flags;
 
        spin_lock_irqsave(&tc->lock, flags);
-       cell_release(pool, cell, &tc->deferred_bio_list);
+       cell_release_no_holder(pool, cell, &tc->deferred_bio_list);
        spin_unlock_irqrestore(&tc->lock, flags);
 
        wake_worker(pool);
 }
 
-/*
- * Same as cell_defer above, except it omits the original holder of the cell.
- */
-static void cell_defer_no_holder(struct thin_c *tc, struct dm_bio_prison_cell *cell)
+static void thin_defer_bio(struct thin_c *tc, struct bio *bio);
+
+struct remap_info {
+       struct thin_c *tc;
+       struct bio_list defer_bios;
+       struct bio_list issue_bios;
+};
+
+static void __inc_remap_and_issue_cell(void *context,
+                                      struct dm_bio_prison_cell *cell)
 {
-       struct pool *pool = tc->pool;
-       unsigned long flags;
+       struct remap_info *info = context;
+       struct bio *bio;
 
-       spin_lock_irqsave(&tc->lock, flags);
-       cell_release_no_holder(pool, cell, &tc->deferred_bio_list);
-       spin_unlock_irqrestore(&tc->lock, flags);
+       while ((bio = bio_list_pop(&cell->bios))) {
+               if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA))
+                       bio_list_add(&info->defer_bios, bio);
+               else {
+                       inc_all_io_entry(info->tc->pool, bio);
 
-       wake_worker(pool);
+                       /*
+                        * We can't issue the bios with the bio prison lock
+                        * held, so we add them to a list to issue on
+                        * return from this function.
+                        */
+                       bio_list_add(&info->issue_bios, bio);
+               }
+       }
+}
+
+static void inc_remap_and_issue_cell(struct thin_c *tc,
+                                    struct dm_bio_prison_cell *cell,
+                                    dm_block_t block)
+{
+       struct bio *bio;
+       struct remap_info info;
+
+       info.tc = tc;
+       bio_list_init(&info.defer_bios);
+       bio_list_init(&info.issue_bios);
+
+       /*
+        * We have to be careful to inc any bios we're about to issue
+        * before the cell is released, and avoid a race with new bios
+        * being added to the cell.
+        */
+       cell_visit_release(tc->pool, __inc_remap_and_issue_cell,
+                          &info, cell);
+
+       while ((bio = bio_list_pop(&info.defer_bios)))
+               thin_defer_bio(tc, bio);
+
+       while ((bio = bio_list_pop(&info.issue_bios)))
+               remap_and_issue(info.tc, bio, block);
 }
 
 static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
@@ -706,10 +838,13 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         * the bios in the cell.
         */
        if (bio) {
-               cell_defer_no_holder(tc, m->cell);
+               inc_remap_and_issue_cell(tc, m->cell, m->data_block);
                bio_endio(bio, 0);
-       } else
-               cell_defer(tc, m->cell);
+       } else {
+               inc_all_io_entry(tc->pool, m->cell->holder);
+               remap_and_issue(tc, m->cell->holder, m->data_block);
+               inc_remap_and_issue_cell(tc, m->cell, m->data_block);
+       }
 
 out:
        list_del(&m->list);
@@ -842,6 +977,20 @@ static void ll_zero(struct thin_c *tc, struct dm_thin_new_mapping *m,
        }
 }
 
+static void remap_and_issue_overwrite(struct thin_c *tc, struct bio *bio,
+                                     dm_block_t data_block,
+                                     struct dm_thin_new_mapping *m)
+{
+       struct pool *pool = tc->pool;
+       struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
+
+       h->overwrite_mapping = m;
+       m->bio = bio;
+       save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
+       inc_all_io_entry(pool, bio);
+       remap_and_issue(tc, bio, data_block);
+}
+
 /*
  * A partial copy also needs to zero the uncopied region.
  */
@@ -876,15 +1025,9 @@ static void schedule_copy(struct thin_c *tc, dm_block_t virt_block,
         * If the whole block of data is being overwritten, we can issue the
         * bio immediately. Otherwise we use kcopyd to clone the data first.
         */
-       if (io_overwrites_block(pool, bio)) {
-               struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
-
-               h->overwrite_mapping = m;
-               m->bio = bio;
-               save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
-               inc_all_io_entry(pool, bio);
-               remap_and_issue(tc, bio, data_dest);
-       } else {
+       if (io_overwrites_block(pool, bio))
+               remap_and_issue_overwrite(tc, bio, data_dest, m);
+       else {
                struct dm_io_region from, to;
 
                from.bdev = origin->bdev;
@@ -953,16 +1096,10 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block,
        if (!pool->pf.zero_new_blocks)
                process_prepared_mapping(m);
 
-       else if (io_overwrites_block(pool, bio)) {
-               struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
-
-               h->overwrite_mapping = m;
-               m->bio = bio;
-               save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio);
-               inc_all_io_entry(pool, bio);
-               remap_and_issue(tc, bio, data_block);
+       else if (io_overwrites_block(pool, bio))
+               remap_and_issue_overwrite(tc, bio, data_block, m);
 
-       else
+       else
                ll_zero(tc, m,
                        data_block * pool->sectors_per_block,
                        (data_block + 1) * pool->sectors_per_block);
@@ -1134,29 +1271,25 @@ static void retry_bios_on_resume(struct pool *pool, struct dm_bio_prison_cell *c
        bio_list_init(&bios);
        cell_release(pool, cell, &bios);
 
-       error = should_error_unserviceable_bio(pool);
-       if (error)
-               while ((bio = bio_list_pop(&bios)))
-                       bio_endio(bio, error);
-       else
-               while ((bio = bio_list_pop(&bios)))
-                       retry_on_resume(bio);
+       while ((bio = bio_list_pop(&bios)))
+               retry_on_resume(bio);
 }
 
-static void process_discard(struct thin_c *tc, struct bio *bio)
+static void process_discard_cell(struct thin_c *tc, struct dm_bio_prison_cell *cell)
 {
        int r;
-       unsigned long flags;
+       struct bio *bio = cell->holder;
        struct pool *pool = tc->pool;
-       struct dm_bio_prison_cell *cell, *cell2;
-       struct dm_cell_key key, key2;
+       struct dm_bio_prison_cell *cell2;
+       struct dm_cell_key key2;
        dm_block_t block = get_bio_block(tc, bio);
        struct dm_thin_lookup_result lookup_result;
        struct dm_thin_new_mapping *m;
 
-       build_virtual_key(tc->td, block, &key);
-       if (bio_detain(tc->pool, &key, bio, &cell))
+       if (tc->requeue_mode) {
+               cell_requeue(pool, cell);
                return;
+       }
 
        r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
        switch (r) {
@@ -1187,12 +1320,9 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
                        m->cell2 = cell2;
                        m->bio = bio;
 
-                       if (!dm_deferred_set_add_work(pool->all_io_ds, &m->list)) {
-                               spin_lock_irqsave(&pool->lock, flags);
-                               list_add_tail(&m->list, &pool->prepared_discards);
-                               spin_unlock_irqrestore(&pool->lock, flags);
-                               wake_worker(pool);
-                       }
+                       if (!dm_deferred_set_add_work(pool->all_io_ds, &m->list))
+                               pool->process_prepared_discard(m);
+
                } else {
                        inc_all_io_entry(pool, bio);
                        cell_defer_no_holder(tc, cell);
@@ -1227,6 +1357,19 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
        }
 }
 
+static void process_discard_bio(struct thin_c *tc, struct bio *bio)
+{
+       struct dm_bio_prison_cell *cell;
+       struct dm_cell_key key;
+       dm_block_t block = get_bio_block(tc, bio);
+
+       build_virtual_key(tc->td, block, &key);
+       if (bio_detain(tc->pool, &key, bio, &cell))
+               return;
+
+       process_discard_cell(tc, cell);
+}
+
 static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
                          struct dm_cell_key *key,
                          struct dm_thin_lookup_result *lookup_result,
@@ -1255,11 +1398,53 @@ static void break_sharing(struct thin_c *tc, struct bio *bio, dm_block_t block,
        }
 }
 
+static void __remap_and_issue_shared_cell(void *context,
+                                         struct dm_bio_prison_cell *cell)
+{
+       struct remap_info *info = context;
+       struct bio *bio;
+
+       while ((bio = bio_list_pop(&cell->bios))) {
+               if ((bio_data_dir(bio) == WRITE) ||
+                   (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)))
+                       bio_list_add(&info->defer_bios, bio);
+               else {
+                       struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));;
+
+                       h->shared_read_entry = dm_deferred_entry_inc(info->tc->pool->shared_read_ds);
+                       inc_all_io_entry(info->tc->pool, bio);
+                       bio_list_add(&info->issue_bios, bio);
+               }
+       }
+}
+
+static void remap_and_issue_shared_cell(struct thin_c *tc,
+                                       struct dm_bio_prison_cell *cell,
+                                       dm_block_t block)
+{
+       struct bio *bio;
+       struct remap_info info;
+
+       info.tc = tc;
+       bio_list_init(&info.defer_bios);
+       bio_list_init(&info.issue_bios);
+
+       cell_visit_release(tc->pool, __remap_and_issue_shared_cell,
+                          &info, cell);
+
+       while ((bio = bio_list_pop(&info.defer_bios)))
+               thin_defer_bio(tc, bio);
+
+       while ((bio = bio_list_pop(&info.issue_bios)))
+               remap_and_issue(tc, bio, block);
+}
+
 static void process_shared_bio(struct thin_c *tc, struct bio *bio,
                               dm_block_t block,
-                              struct dm_thin_lookup_result *lookup_result)
+                              struct dm_thin_lookup_result *lookup_result,
+                              struct dm_bio_prison_cell *virt_cell)
 {
-       struct dm_bio_prison_cell *cell;
+       struct dm_bio_prison_cell *data_cell;
        struct pool *pool = tc->pool;
        struct dm_cell_key key;
 
@@ -1268,19 +1453,23 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio,
         * of being broken so we have nothing further to do here.
         */
        build_data_key(tc->td, lookup_result->block, &key);
-       if (bio_detain(pool, &key, bio, &cell))
+       if (bio_detain(pool, &key, bio, &data_cell)) {
+               cell_defer_no_holder(tc, virt_cell);
                return;
+       }
 
-       if (bio_data_dir(bio) == WRITE && bio->bi_iter.bi_size)
-               break_sharing(tc, bio, block, &key, lookup_result, cell);
-       else {
+       if (bio_data_dir(bio) == WRITE && bio->bi_iter.bi_size) {
+               break_sharing(tc, bio, block, &key, lookup_result, data_cell);
+               cell_defer_no_holder(tc, virt_cell);
+       } else {
                struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
 
                h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds);
                inc_all_io_entry(pool, bio);
-               cell_defer_no_holder(tc, cell);
-
                remap_and_issue(tc, bio, lookup_result->block);
+
+               remap_and_issue_shared_cell(tc, data_cell, lookup_result->block);
+               remap_and_issue_shared_cell(tc, virt_cell, lookup_result->block);
        }
 }
 
@@ -1333,34 +1522,28 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block
        }
 }
 
-static void process_bio(struct thin_c *tc, struct bio *bio)
+static void process_cell(struct thin_c *tc, struct dm_bio_prison_cell *cell)
 {
        int r;
        struct pool *pool = tc->pool;
+       struct bio *bio = cell->holder;
        dm_block_t block = get_bio_block(tc, bio);
-       struct dm_bio_prison_cell *cell;
-       struct dm_cell_key key;
        struct dm_thin_lookup_result lookup_result;
 
-       /*
-        * If cell is already occupied, then the block is already
-        * being provisioned so we have nothing further to do here.
-        */
-       build_virtual_key(tc->td, block, &key);
-       if (bio_detain(pool, &key, bio, &cell))
+       if (tc->requeue_mode) {
+               cell_requeue(pool, cell);
                return;
+       }
 
        r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
        switch (r) {
        case 0:
-               if (lookup_result.shared) {
-                       process_shared_bio(tc, bio, block, &lookup_result);
-                       cell_defer_no_holder(tc, cell); /* FIXME: pass this cell into process_shared? */
-               } else {
+               if (lookup_result.shared)
+                       process_shared_bio(tc, bio, block, &lookup_result, cell);
+               else {
                        inc_all_io_entry(pool, bio);
-                       cell_defer_no_holder(tc, cell);
-
                        remap_and_issue(tc, bio, lookup_result.block);
+                       inc_remap_and_issue_cell(tc, cell, lookup_result.block);
                }
                break;
 
@@ -1394,7 +1577,26 @@ static void process_bio(struct thin_c *tc, struct bio *bio)
        }
 }
 
-static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
+static void process_bio(struct thin_c *tc, struct bio *bio)
+{
+       struct pool *pool = tc->pool;
+       dm_block_t block = get_bio_block(tc, bio);
+       struct dm_bio_prison_cell *cell;
+       struct dm_cell_key key;
+
+       /*
+        * If cell is already occupied, then the block is already
+        * being provisioned so we have nothing further to do here.
+        */
+       build_virtual_key(tc->td, block, &key);
+       if (bio_detain(pool, &key, bio, &cell))
+               return;
+
+       process_cell(tc, cell);
+}
+
+static void __process_bio_read_only(struct thin_c *tc, struct bio *bio,
+                                   struct dm_bio_prison_cell *cell)
 {
        int r;
        int rw = bio_data_dir(bio);
@@ -1404,15 +1606,21 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
        r = dm_thin_find_block(tc->td, block, 1, &lookup_result);
        switch (r) {
        case 0:
-               if (lookup_result.shared && (rw == WRITE) && bio->bi_iter.bi_size)
+               if (lookup_result.shared && (rw == WRITE) && bio->bi_iter.bi_size) {
                        handle_unserviceable_bio(tc->pool, bio);
-               else {
+                       if (cell)
+                               cell_defer_no_holder(tc, cell);
+               } else {
                        inc_all_io_entry(tc->pool, bio);
                        remap_and_issue(tc, bio, lookup_result.block);
+                       if (cell)
+                               inc_remap_and_issue_cell(tc, cell, lookup_result.block);
                }
                break;
 
        case -ENODATA:
+               if (cell)
+                       cell_defer_no_holder(tc, cell);
                if (rw != READ) {
                        handle_unserviceable_bio(tc->pool, bio);
                        break;
@@ -1431,11 +1639,23 @@ static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
        default:
                DMERR_LIMIT("%s: dm_thin_find_block() failed: error = %d",
                            __func__, r);
+               if (cell)
+                       cell_defer_no_holder(tc, cell);
                bio_io_error(bio);
                break;
        }
 }
 
+static void process_bio_read_only(struct thin_c *tc, struct bio *bio)
+{
+       __process_bio_read_only(tc, bio, NULL);
+}
+
+static void process_cell_read_only(struct thin_c *tc, struct dm_bio_prison_cell *cell)
+{
+       __process_bio_read_only(tc, cell->holder, cell);
+}
+
 static void process_bio_success(struct thin_c *tc, struct bio *bio)
 {
        bio_endio(bio, 0);
@@ -1446,6 +1666,16 @@ static void process_bio_fail(struct thin_c *tc, struct bio *bio)
        bio_io_error(bio);
 }
 
+static void process_cell_success(struct thin_c *tc, struct dm_bio_prison_cell *cell)
+{
+       cell_success(tc->pool, cell);
+}
+
+static void process_cell_fail(struct thin_c *tc, struct dm_bio_prison_cell *cell)
+{
+       cell_error(tc->pool, cell);
+}
+
 /*
  * FIXME: should we also commit due to size of transaction, measured in
  * metadata blocks?
@@ -1527,9 +1757,10 @@ static void process_thin_deferred_bios(struct thin_c *tc)
        struct bio *bio;
        struct bio_list bios;
        struct blk_plug plug;
+       unsigned count = 0;
 
        if (tc->requeue_mode) {
-               requeue_bio_list(tc, &tc->deferred_bio_list);
+               error_thin_bio_list(tc, &tc->deferred_bio_list, DM_ENDIO_REQUEUE);
                return;
        }
 
@@ -1568,10 +1799,97 @@ static void process_thin_deferred_bios(struct thin_c *tc)
                        pool->process_discard(tc, bio);
                else
                        pool->process_bio(tc, bio);
+
+               if ((count++ & 127) == 0) {
+                       throttle_work_update(&pool->throttle);
+                       dm_pool_issue_prefetches(pool->pmd);
+               }
        }
        blk_finish_plug(&plug);
 }
 
+static int cmp_cells(const void *lhs, const void *rhs)
+{
+       struct dm_bio_prison_cell *lhs_cell = *((struct dm_bio_prison_cell **) lhs);
+       struct dm_bio_prison_cell *rhs_cell = *((struct dm_bio_prison_cell **) rhs);
+
+       BUG_ON(!lhs_cell->holder);
+       BUG_ON(!rhs_cell->holder);
+
+       if (lhs_cell->holder->bi_iter.bi_sector < rhs_cell->holder->bi_iter.bi_sector)
+               return -1;
+
+       if (lhs_cell->holder->bi_iter.bi_sector > rhs_cell->holder->bi_iter.bi_sector)
+               return 1;
+
+       return 0;
+}
+
+static unsigned sort_cells(struct pool *pool, struct list_head *cells)
+{
+       unsigned count = 0;
+       struct dm_bio_prison_cell *cell, *tmp;
+
+       list_for_each_entry_safe(cell, tmp, cells, user_list) {
+               if (count >= CELL_SORT_ARRAY_SIZE)
+                       break;
+
+               pool->cell_sort_array[count++] = cell;
+               list_del(&cell->user_list);
+       }
+
+       sort(pool->cell_sort_array, count, sizeof(cell), cmp_cells, NULL);
+
+       return count;
+}
+
+static void process_thin_deferred_cells(struct thin_c *tc)
+{
+       struct pool *pool = tc->pool;
+       unsigned long flags;
+       struct list_head cells;
+       struct dm_bio_prison_cell *cell;
+       unsigned i, j, count;
+
+       INIT_LIST_HEAD(&cells);
+
+       spin_lock_irqsave(&tc->lock, flags);
+       list_splice_init(&tc->deferred_cells, &cells);
+       spin_unlock_irqrestore(&tc->lock, flags);
+
+       if (list_empty(&cells))
+               return;
+
+       do {
+               count = sort_cells(tc->pool, &cells);
+
+               for (i = 0; i < count; i++) {
+                       cell = pool->cell_sort_array[i];
+                       BUG_ON(!cell->holder);
+
+                       /*
+                        * If we've got no free new_mapping structs, and processing
+                        * this bio might require one, we pause until there are some
+                        * prepared mappings to process.
+                        */
+                       if (ensure_next_mapping(pool)) {
+                               for (j = i; j < count; j++)
+                                       list_add(&pool->cell_sort_array[j]->user_list, &cells);
+
+                               spin_lock_irqsave(&tc->lock, flags);
+                               list_splice(&cells, &tc->deferred_cells);
+                               spin_unlock_irqrestore(&tc->lock, flags);
+                               return;
+                       }
+
+                       if (cell->holder->bi_rw & REQ_DISCARD)
+                               pool->process_discard_cell(tc, cell);
+                       else
+                               pool->process_cell(tc, cell);
+               }
+       } while (!list_empty(&cells));
+}
+
 static void thin_get(struct thin_c *tc);
 static void thin_put(struct thin_c *tc);
 
@@ -1620,6 +1938,7 @@ static void process_deferred_bios(struct pool *pool)
 
        tc = get_first_thin(pool);
        while (tc) {
+               process_thin_deferred_cells(tc);
                process_thin_deferred_bios(tc);
                tc = get_next_thin(pool, tc);
        }
@@ -1653,9 +1972,15 @@ static void do_worker(struct work_struct *ws)
 {
        struct pool *pool = container_of(ws, struct pool, worker);
 
+       throttle_work_start(&pool->throttle);
+       dm_pool_issue_prefetches(pool->pmd);
+       throttle_work_update(&pool->throttle);
        process_prepared(pool, &pool->prepared_mappings, &pool->process_prepared_mapping);
+       throttle_work_update(&pool->throttle);
        process_prepared(pool, &pool->prepared_discards, &pool->process_prepared_discard);
+       throttle_work_update(&pool->throttle);
        process_deferred_bios(pool);
+       throttle_work_complete(&pool->throttle);
 }
 
 /*
@@ -1792,6 +2117,8 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                dm_pool_metadata_read_only(pool->pmd);
                pool->process_bio = process_bio_fail;
                pool->process_discard = process_bio_fail;
+               pool->process_cell = process_cell_fail;
+               pool->process_discard_cell = process_cell_fail;
                pool->process_prepared_mapping = process_prepared_mapping_fail;
                pool->process_prepared_discard = process_prepared_discard_fail;
 
@@ -1804,6 +2131,8 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                dm_pool_metadata_read_only(pool->pmd);
                pool->process_bio = process_bio_read_only;
                pool->process_discard = process_bio_success;
+               pool->process_cell = process_cell_read_only;
+               pool->process_discard_cell = process_cell_success;
                pool->process_prepared_mapping = process_prepared_mapping_fail;
                pool->process_prepared_discard = process_prepared_discard_passdown;
 
@@ -1822,7 +2151,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                if (old_mode != new_mode)
                        notify_of_pool_mode_change(pool, "out-of-data-space");
                pool->process_bio = process_bio_read_only;
-               pool->process_discard = process_discard;
+               pool->process_discard = process_discard_bio;
+               pool->process_cell = process_cell_read_only;
+               pool->process_discard_cell = process_discard_cell;
                pool->process_prepared_mapping = process_prepared_mapping;
                pool->process_prepared_discard = process_prepared_discard_passdown;
 
@@ -1835,7 +2166,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                        notify_of_pool_mode_change(pool, "write");
                dm_pool_metadata_read_write(pool->pmd);
                pool->process_bio = process_bio;
-               pool->process_discard = process_discard;
+               pool->process_discard = process_discard_bio;
+               pool->process_cell = process_cell;
+               pool->process_discard_cell = process_discard_cell;
                pool->process_prepared_mapping = process_prepared_mapping;
                pool->process_prepared_discard = process_prepared_discard;
                break;
@@ -1895,6 +2228,29 @@ static void thin_defer_bio(struct thin_c *tc, struct bio *bio)
        wake_worker(pool);
 }
 
+static void thin_defer_bio_with_throttle(struct thin_c *tc, struct bio *bio)
+{
+       struct pool *pool = tc->pool;
+
+       throttle_lock(&pool->throttle);
+       thin_defer_bio(tc, bio);
+       throttle_unlock(&pool->throttle);
+}
+
+static void thin_defer_cell(struct thin_c *tc, struct dm_bio_prison_cell *cell)
+{
+       unsigned long flags;
+       struct pool *pool = tc->pool;
+
+       throttle_lock(&pool->throttle);
+       spin_lock_irqsave(&tc->lock, flags);
+       list_add_tail(&cell->user_list, &tc->deferred_cells);
+       spin_unlock_irqrestore(&tc->lock, flags);
+       throttle_unlock(&pool->throttle);
+
+       wake_worker(pool);
+}
+
 static void thin_hook_bio(struct thin_c *tc, struct bio *bio)
 {
        struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));
@@ -1915,8 +2271,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
        dm_block_t block = get_bio_block(tc, bio);
        struct dm_thin_device *td = tc->td;
        struct dm_thin_lookup_result result;
-       struct dm_bio_prison_cell cell1, cell2;
-       struct dm_bio_prison_cell *cell_result;
+       struct dm_bio_prison_cell *virt_cell, *data_cell;
        struct dm_cell_key key;
 
        thin_hook_bio(tc, bio);
@@ -1932,10 +2287,18 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
        }
 
        if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)) {
-               thin_defer_bio(tc, bio);
+               thin_defer_bio_with_throttle(tc, bio);
                return DM_MAPIO_SUBMITTED;
        }
 
+       /*
+        * We must hold the virtual cell before doing the lookup, otherwise
+        * there's a race with discard.
+        */
+       build_virtual_key(tc->td, block, &key);
+       if (bio_detain(tc->pool, &key, bio, &virt_cell))
+               return DM_MAPIO_SUBMITTED;
+
        r = dm_thin_find_block(td, block, 0, &result);
 
        /*
@@ -1958,23 +2321,19 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
                         * More distant ancestors are irrelevant. The
                         * shared flag will be set in their case.
                         */
-                       thin_defer_bio(tc, bio);
+                       thin_defer_cell(tc, virt_cell);
                        return DM_MAPIO_SUBMITTED;
                }
 
-               build_virtual_key(tc->td, block, &key);
-               if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1, &cell_result))
-                       return DM_MAPIO_SUBMITTED;
-
                build_data_key(tc->td, result.block, &key);
-               if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2, &cell_result)) {
-                       cell_defer_no_holder_no_free(tc, &cell1);
+               if (bio_detain(tc->pool, &key, bio, &data_cell)) {
+                       cell_defer_no_holder(tc, virt_cell);
                        return DM_MAPIO_SUBMITTED;
                }
 
                inc_all_io_entry(tc->pool, bio);
-               cell_defer_no_holder_no_free(tc, &cell2);
-               cell_defer_no_holder_no_free(tc, &cell1);
+               cell_defer_no_holder(tc, data_cell);
+               cell_defer_no_holder(tc, virt_cell);
 
                remap(tc, bio, result.block);
                return DM_MAPIO_REMAPPED;
@@ -1986,16 +2345,13 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
                         * of doing so.
                         */
                        handle_unserviceable_bio(tc->pool, bio);
+                       cell_defer_no_holder(tc, virt_cell);
                        return DM_MAPIO_SUBMITTED;
                }
                /* fall through */
 
        case -EWOULDBLOCK:
-               /*
-                * In future, the failed dm_thin_find_block above could
-                * provide the hint to load the metadata into cache.
-                */
-               thin_defer_bio(tc, bio);
+               thin_defer_cell(tc, virt_cell);
                return DM_MAPIO_SUBMITTED;
 
        default:
@@ -2005,6 +2361,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
                 * pool is switched to fail-io mode.
                 */
                bio_io_error(bio);
+               cell_defer_no_holder(tc, virt_cell);
                return DM_MAPIO_SUBMITTED;
        }
 }
@@ -2185,7 +2542,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
                pool->sectors_per_block_shift = __ffs(block_size);
        pool->low_water_blocks = 0;
        pool_features_init(&pool->pf);
-       pool->prison = dm_bio_prison_create(PRISON_CELLS);
+       pool->prison = dm_bio_prison_create();
        if (!pool->prison) {
                *error = "Error creating pool's bio prison";
                err_p = ERR_PTR(-ENOMEM);
@@ -2211,6 +2568,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
                goto bad_wq;
        }
 
+       throttle_init(&pool->throttle);
        INIT_WORK(&pool->worker, do_worker);
        INIT_DELAYED_WORK(&pool->waker, do_waker);
        INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
@@ -2220,6 +2578,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        INIT_LIST_HEAD(&pool->prepared_discards);
        INIT_LIST_HEAD(&pool->active_thins);
        pool->low_water_triggered = false;
+       pool->suspended = true;
 
        pool->shared_read_ds = dm_deferred_set_create();
        if (!pool->shared_read_ds) {
@@ -2756,20 +3115,77 @@ static int pool_preresume(struct dm_target *ti)
        return 0;
 }
 
+static void pool_suspend_active_thins(struct pool *pool)
+{
+       struct thin_c *tc;
+
+       /* Suspend all active thin devices */
+       tc = get_first_thin(pool);
+       while (tc) {
+               dm_internal_suspend_noflush(tc->thin_md);
+               tc = get_next_thin(pool, tc);
+       }
+}
+
+static void pool_resume_active_thins(struct pool *pool)
+{
+       struct thin_c *tc;
+
+       /* Resume all active thin devices */
+       tc = get_first_thin(pool);
+       while (tc) {
+               dm_internal_resume(tc->thin_md);
+               tc = get_next_thin(pool, tc);
+       }
+}
+
 static void pool_resume(struct dm_target *ti)
 {
        struct pool_c *pt = ti->private;
        struct pool *pool = pt->pool;
        unsigned long flags;
 
+       /*
+        * Must requeue active_thins' bios and then resume
+        * active_thins _before_ clearing 'suspend' flag.
+        */
+       requeue_bios(pool);
+       pool_resume_active_thins(pool);
+
        spin_lock_irqsave(&pool->lock, flags);
        pool->low_water_triggered = false;
+       pool->suspended = false;
        spin_unlock_irqrestore(&pool->lock, flags);
-       requeue_bios(pool);
 
        do_waker(&pool->waker.work);
 }
 
+static void pool_presuspend(struct dm_target *ti)
+{
+       struct pool_c *pt = ti->private;
+       struct pool *pool = pt->pool;
+       unsigned long flags;
+
+       spin_lock_irqsave(&pool->lock, flags);
+       pool->suspended = true;
+       spin_unlock_irqrestore(&pool->lock, flags);
+
+       pool_suspend_active_thins(pool);
+}
+
+static void pool_presuspend_undo(struct dm_target *ti)
+{
+       struct pool_c *pt = ti->private;
+       struct pool *pool = pt->pool;
+       unsigned long flags;
+
+       pool_resume_active_thins(pool);
+
+       spin_lock_irqsave(&pool->lock, flags);
+       pool->suspended = false;
+       spin_unlock_irqrestore(&pool->lock, flags);
+}
+
 static void pool_postsuspend(struct dm_target *ti)
 {
        struct pool_c *pt = ti->private;
@@ -2941,7 +3357,6 @@ static int process_release_metadata_snap_mesg(unsigned argc, char **argv, struct
  *   create_thin       <dev_id>
  *   create_snap       <dev_id> <origin_id>
  *   delete            <dev_id>
- *   trim              <dev_id> <new_size_in_sectors>
  *   set_transaction_id <current_trans_id> <new_trans_id>
  *   reserve_metadata_snap
  *   release_metadata_snap
@@ -3169,15 +3584,35 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct pool_c *pt = ti->private;
        struct pool *pool = pt->pool;
-       uint64_t io_opt_sectors = limits->io_opt >> SECTOR_SHIFT;
+       sector_t io_opt_sectors = limits->io_opt >> SECTOR_SHIFT;
+
+       /*
+        * If max_sectors is smaller than pool->sectors_per_block adjust it
+        * to the highest possible power-of-2 factor of pool->sectors_per_block.
+        * This is especially beneficial when the pool's data device is a RAID
+        * device that has a full stripe width that matches pool->sectors_per_block
+        * -- because even though partial RAID stripe-sized IOs will be issued to a
+        *    single RAID stripe; when aggregated they will end on a full RAID stripe
+        *    boundary.. which avoids additional partial RAID stripe writes cascading
+        */
+       if (limits->max_sectors < pool->sectors_per_block) {
+               while (!is_factor(pool->sectors_per_block, limits->max_sectors)) {
+                       if ((limits->max_sectors & (limits->max_sectors - 1)) == 0)
+                               limits->max_sectors--;
+                       limits->max_sectors = rounddown_pow_of_two(limits->max_sectors);
+               }
+       }
 
        /*
         * If the system-determined stacked limits are compatible with the
         * pool's blocksize (io_opt is a factor) do not override them.
         */
        if (io_opt_sectors < pool->sectors_per_block ||
-           do_div(io_opt_sectors, pool->sectors_per_block)) {
-               blk_limits_io_min(limits, pool->sectors_per_block << SECTOR_SHIFT);
+           !is_factor(io_opt_sectors, pool->sectors_per_block)) {
+               if (is_factor(pool->sectors_per_block, limits->max_sectors))
+                       blk_limits_io_min(limits, limits->max_sectors << SECTOR_SHIFT);
+               else
+                       blk_limits_io_min(limits, pool->sectors_per_block << SECTOR_SHIFT);
                blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
        }
 
@@ -3206,11 +3641,13 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 13, 0},
+       .version = {1, 14, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
        .map = pool_map,
+       .presuspend = pool_presuspend,
+       .presuspend_undo = pool_presuspend_undo,
        .postsuspend = pool_postsuspend,
        .preresume = pool_preresume,
        .resume = pool_resume,
@@ -3240,14 +3677,14 @@ static void thin_dtr(struct dm_target *ti)
        struct thin_c *tc = ti->private;
        unsigned long flags;
 
-       thin_put(tc);
-       wait_for_completion(&tc->can_destroy);
-
        spin_lock_irqsave(&tc->pool->lock, flags);
        list_del_rcu(&tc->list);
        spin_unlock_irqrestore(&tc->pool->lock, flags);
        synchronize_rcu();
 
+       thin_put(tc);
+       wait_for_completion(&tc->can_destroy);
+
        mutex_lock(&dm_thin_pool_table.mutex);
 
        __pool_dec(tc->pool);
@@ -3294,7 +3731,9 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
                r = -ENOMEM;
                goto out_unlock;
        }
+       tc->thin_md = dm_table_get_md(ti->table);
        spin_lock_init(&tc->lock);
+       INIT_LIST_HEAD(&tc->deferred_cells);
        bio_list_init(&tc->deferred_bio_list);
        bio_list_init(&tc->retry_on_resume_list);
        tc->sort_bio_list = RB_ROOT;
@@ -3339,18 +3778,18 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
        if (get_pool_mode(tc->pool) == PM_FAIL) {
                ti->error = "Couldn't open thin device, Pool is in fail mode";
                r = -EINVAL;
-               goto bad_thin_open;
+               goto bad_pool;
        }
 
        r = dm_pool_open_thin_device(tc->pool->pmd, tc->dev_id, &tc->td);
        if (r) {
                ti->error = "Couldn't open thin internal device";
-               goto bad_thin_open;
+               goto bad_pool;
        }
 
        r = dm_set_target_max_io_len(ti, tc->pool->sectors_per_block);
        if (r)
-               goto bad_target_max_io_len;
+               goto bad;
 
        ti->num_flush_bios = 1;
        ti->flush_supported = true;
@@ -3365,14 +3804,16 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
                ti->split_discard_bios = true;
        }
 
-       dm_put(pool_md);
-
        mutex_unlock(&dm_thin_pool_table.mutex);
 
-       atomic_set(&tc->refcount, 1);
-       init_completion(&tc->can_destroy);
-
        spin_lock_irqsave(&tc->pool->lock, flags);
+       if (tc->pool->suspended) {
+               spin_unlock_irqrestore(&tc->pool->lock, flags);
+               mutex_lock(&dm_thin_pool_table.mutex); /* reacquire for __pool_dec */
+               ti->error = "Unable to activate thin device while pool is suspended";
+               r = -EINVAL;
+               goto bad;
+       }
        list_add_tail_rcu(&tc->list, &tc->pool->active_thins);
        spin_unlock_irqrestore(&tc->pool->lock, flags);
        /*
@@ -3383,11 +3824,16 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
         */
        synchronize_rcu();
 
+       dm_put(pool_md);
+
+       atomic_set(&tc->refcount, 1);
+       init_completion(&tc->can_destroy);
+
        return 0;
 
-bad_target_max_io_len:
+bad:
        dm_pool_close_thin_device(tc->td);
-bad_thin_open:
+bad_pool:
        __pool_dec(tc->pool);
 bad_pool_lookup:
        dm_put(pool_md);
@@ -3533,6 +3979,21 @@ err:
        DMEMIT("Error");
 }
 
+static int thin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+                     struct bio_vec *biovec, int max_size)
+{
+       struct thin_c *tc = ti->private;
+       struct request_queue *q = bdev_get_queue(tc->pool_dev->bdev);
+
+       if (!q->merge_bvec_fn)
+               return max_size;
+
+       bvm->bi_bdev = tc->pool_dev->bdev;
+       bvm->bi_sector = dm_target_offset(ti, bvm->bi_sector);
+
+       return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
 static int thin_iterate_devices(struct dm_target *ti,
                                iterate_devices_callout_fn fn, void *data)
 {
@@ -3557,7 +4018,7 @@ static int thin_iterate_devices(struct dm_target *ti,
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 13, 0},
+       .version = {1, 14, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
@@ -3567,6 +4028,7 @@ static struct target_type thin_target = {
        .presuspend = thin_presuspend,
        .postsuspend = thin_postsuspend,
        .status = thin_status,
+       .merge = thin_merge,
        .iterate_devices = thin_iterate_devices,
 };
 
index 58f3927fd7cc98dda4113571fab3e607842e15f3..8f37ed215b19a1c42876eb350c90866e2d390d26 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/idr.h>
 #include <linux/hdreg.h>
 #include <linux/delay.h>
+#include <linux/wait.h>
 
 #include <trace/events/block.h>
 
@@ -117,6 +118,7 @@ EXPORT_SYMBOL_GPL(dm_get_rq_mapinfo);
 #define DMF_NOFLUSH_SUSPENDING 5
 #define DMF_MERGE_IS_OPTIONAL 6
 #define DMF_DEFERRED_REMOVE 7
+#define DMF_SUSPENDED_INTERNALLY 8
 
 /*
  * A dummy definition to make RCU happy.
@@ -140,7 +142,7 @@ struct mapped_device {
         * Use dm_get_live_table{_fast} or take suspend_lock for
         * dereference.
         */
-       struct dm_table *map;
+       struct dm_table __rcu *map;
 
        struct list_head table_devices;
        struct mutex table_devices_lock;
@@ -525,14 +527,15 @@ retry:
                goto out;
 
        tgt = dm_table_get_target(map, 0);
+       if (!tgt->type->ioctl)
+               goto out;
 
        if (dm_suspended_md(md)) {
                r = -EAGAIN;
                goto out;
        }
 
-       if (tgt->type->ioctl)
-               r = tgt->type->ioctl(tgt, cmd, arg);
+       r = tgt->type->ioctl(tgt, cmd, arg);
 
 out:
        dm_put_live_table(md, srcu_idx);
@@ -1607,9 +1610,9 @@ static int dm_merge_bvec(struct request_queue *q,
         * Find maximum amount of I/O that won't need splitting
         */
        max_sectors = min(max_io_len(bvm->bi_sector, ti),
-                         (sector_t) BIO_MAX_SECTORS);
+                         (sector_t) queue_max_sectors(q));
        max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size;
-       if (max_size < 0)
+       if (unlikely(max_size < 0)) /* this shouldn't _ever_ happen */
                max_size = 0;
 
        /*
@@ -1621,10 +1624,10 @@ static int dm_merge_bvec(struct request_queue *q,
                max_size = ti->type->merge(ti, bvm, biovec, max_size);
        /*
         * If the target doesn't support merge method and some of the devices
-        * provided their merge_bvec method (we know this by looking at
-        * queue_max_hw_sectors), then we can't allow bios with multiple vector
-        * entries.  So always set max_size to 0, and the code below allows
-        * just one page.
+        * provided their merge_bvec method (we know this by looking for the
+        * max_hw_sectors that dm_set_device_limits may set), then we can't
+        * allow bios with multiple vector entries.  So always set max_size
+        * to 0, and the code below allows just one page.
         */
        else if (queue_max_hw_sectors(q) <= PAGE_SIZE >> 9)
                max_size = 0;
@@ -2332,7 +2335,7 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
 
        merge_is_optional = dm_table_merge_is_optional(t);
 
-       old_map = md->map;
+       old_map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
        rcu_assign_pointer(md->map, t);
        md->immutable_target_type = dm_table_get_immutable_target_type(t);
 
@@ -2341,7 +2344,8 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
                set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
        else
                clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
-       dm_sync_table(md);
+       if (old_map)
+               dm_sync_table(md);
 
        return old_map;
 }
@@ -2351,7 +2355,7 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
  */
 static struct dm_table *__unbind(struct mapped_device *md)
 {
-       struct dm_table *map = md->map;
+       struct dm_table *map = rcu_dereference_protected(md->map, 1);
 
        if (!map)
                return NULL;
@@ -2716,36 +2720,18 @@ static void unlock_fs(struct mapped_device *md)
 }
 
 /*
- * We need to be able to change a mapping table under a mounted
- * filesystem.  For example we might want to move some data in
- * the background.  Before the table can be swapped with
- * dm_bind_table, dm_suspend must be called to flush any in
- * flight bios and ensure that any further io gets deferred.
- */
-/*
- * Suspend mechanism in request-based dm.
+ * If __dm_suspend returns 0, the device is completely quiescent
+ * now. There is no request-processing activity. All new requests
+ * are being added to md->deferred list.
  *
- * 1. Flush all I/Os by lock_fs() if needed.
- * 2. Stop dispatching any I/O by stopping the request_queue.
- * 3. Wait for all in-flight I/Os to be completed or requeued.
- *
- * To abort suspend, start the request_queue.
+ * Caller must hold md->suspend_lock
  */
-int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
+static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
+                       unsigned suspend_flags, int interruptible)
 {
-       struct dm_table *map = NULL;
-       int r = 0;
-       int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0;
-       int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0;
-
-       mutex_lock(&md->suspend_lock);
-
-       if (dm_suspended_md(md)) {
-               r = -EINVAL;
-               goto out_unlock;
-       }
-
-       map = md->map;
+       bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
+       bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
+       int r;
 
        /*
         * DMF_NOFLUSH_SUSPENDING must be set before presuspend.
@@ -2754,7 +2740,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
        if (noflush)
                set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
 
-       /* This does not get reverted if there's an error later. */
+       /*
+        * This gets reverted if there's an error later and the targets
+        * provide the .presuspend_undo hook.
+        */
        dm_table_presuspend_targets(map);
 
        /*
@@ -2765,8 +2754,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
         */
        if (!noflush && do_lockfs) {
                r = lock_fs(md);
-               if (r)
-                       goto out_unlock;
+               if (r) {
+                       dm_table_presuspend_undo_targets(map);
+                       return r;
+               }
        }
 
        /*
@@ -2782,7 +2773,8 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
         * flush_workqueue(md->wq).
         */
        set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
-       synchronize_srcu(&md->io_barrier);
+       if (map)
+               synchronize_srcu(&md->io_barrier);
 
        /*
         * Stop md->queue before flushing md->wq in case request-based
@@ -2798,11 +2790,12 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
         * We call dm_wait_for_completion to wait for all existing requests
         * to finish.
         */
-       r = dm_wait_for_completion(md, TASK_INTERRUPTIBLE);
+       r = dm_wait_for_completion(md, interruptible);
 
        if (noflush)
                clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
-       synchronize_srcu(&md->io_barrier);
+       if (map)
+               synchronize_srcu(&md->io_barrier);
 
        /* were we interrupted ? */
        if (r < 0) {
@@ -2812,14 +2805,56 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
                        start_queue(md->queue);
 
                unlock_fs(md);
-               goto out_unlock; /* pushback list is already flushed, so skip flush */
+               dm_table_presuspend_undo_targets(map);
+               /* pushback list is already flushed, so skip flush */
        }
 
-       /*
-        * If dm_wait_for_completion returned 0, the device is completely
-        * quiescent now. There is no request-processing activity. All new
-        * requests are being added to md->deferred list.
-        */
+       return r;
+}
+
+/*
+ * We need to be able to change a mapping table under a mounted
+ * filesystem.  For example we might want to move some data in
+ * the background.  Before the table can be swapped with
+ * dm_bind_table, dm_suspend must be called to flush any in
+ * flight bios and ensure that any further io gets deferred.
+ */
+/*
+ * Suspend mechanism in request-based dm.
+ *
+ * 1. Flush all I/Os by lock_fs() if needed.
+ * 2. Stop dispatching any I/O by stopping the request_queue.
+ * 3. Wait for all in-flight I/Os to be completed or requeued.
+ *
+ * To abort suspend, start the request_queue.
+ */
+int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
+{
+       struct dm_table *map = NULL;
+       int r = 0;
+
+retry:
+       mutex_lock_nested(&md->suspend_lock, SINGLE_DEPTH_NESTING);
+
+       if (dm_suspended_md(md)) {
+               r = -EINVAL;
+               goto out_unlock;
+       }
+
+       if (dm_suspended_internally_md(md)) {
+               /* already internally suspended, wait for internal resume */
+               mutex_unlock(&md->suspend_lock);
+               r = wait_on_bit(&md->flags, DMF_SUSPENDED_INTERNALLY, TASK_INTERRUPTIBLE);
+               if (r)
+                       return r;
+               goto retry;
+       }
+
+       map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
+
+       r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE);
+       if (r)
+               goto out_unlock;
 
        set_bit(DMF_SUSPENDED, &md->flags);
 
@@ -2830,22 +2865,13 @@ out_unlock:
        return r;
 }
 
-int dm_resume(struct mapped_device *md)
+static int __dm_resume(struct mapped_device *md, struct dm_table *map)
 {
-       int r = -EINVAL;
-       struct dm_table *map = NULL;
-
-       mutex_lock(&md->suspend_lock);
-       if (!dm_suspended_md(md))
-               goto out;
-
-       map = md->map;
-       if (!map || !dm_table_get_size(map))
-               goto out;
-
-       r = dm_table_resume_targets(map);
-       if (r)
-               goto out;
+       if (map) {
+               int r = dm_table_resume_targets(map);
+               if (r)
+                       return r;
+       }
 
        dm_queue_flush(md);
 
@@ -2859,6 +2885,37 @@ int dm_resume(struct mapped_device *md)
 
        unlock_fs(md);
 
+       return 0;
+}
+
+int dm_resume(struct mapped_device *md)
+{
+       int r = -EINVAL;
+       struct dm_table *map = NULL;
+
+retry:
+       mutex_lock_nested(&md->suspend_lock, SINGLE_DEPTH_NESTING);
+
+       if (!dm_suspended_md(md))
+               goto out;
+
+       if (dm_suspended_internally_md(md)) {
+               /* already internally suspended, wait for internal resume */
+               mutex_unlock(&md->suspend_lock);
+               r = wait_on_bit(&md->flags, DMF_SUSPENDED_INTERNALLY, TASK_INTERRUPTIBLE);
+               if (r)
+                       return r;
+               goto retry;
+       }
+
+       map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
+       if (!map || !dm_table_get_size(map))
+               goto out;
+
+       r = __dm_resume(md, map);
+       if (r)
+               goto out;
+
        clear_bit(DMF_SUSPENDED, &md->flags);
 
        r = 0;
@@ -2872,15 +2929,80 @@ out:
  * Internal suspend/resume works like userspace-driven suspend. It waits
  * until all bios finish and prevents issuing new bios to the target drivers.
  * It may be used only from the kernel.
- *
- * Internal suspend holds md->suspend_lock, which prevents interaction with
- * userspace-driven suspend.
  */
 
-void dm_internal_suspend(struct mapped_device *md)
+static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_flags)
 {
-       mutex_lock(&md->suspend_lock);
+       struct dm_table *map = NULL;
+
+       if (dm_suspended_internally_md(md))
+               return; /* nested internal suspend */
+
+       if (dm_suspended_md(md)) {
+               set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
+               return; /* nest suspend */
+       }
+
+       map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
+
+       /*
+        * Using TASK_UNINTERRUPTIBLE because only NOFLUSH internal suspend is
+        * supported.  Properly supporting a TASK_INTERRUPTIBLE internal suspend
+        * would require changing .presuspend to return an error -- avoid this
+        * until there is a need for more elaborate variants of internal suspend.
+        */
+       (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE);
+
+       set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
+
+       dm_table_postsuspend_targets(map);
+}
+
+static void __dm_internal_resume(struct mapped_device *md)
+{
+       if (!dm_suspended_internally_md(md))
+               return; /* resume from nested internal suspend */
+
        if (dm_suspended_md(md))
+               goto done; /* resume from nested suspend */
+
+       /*
+        * NOTE: existing callers don't need to call dm_table_resume_targets
+        * (which may fail -- so best to avoid it for now by passing NULL map)
+        */
+       (void) __dm_resume(md, NULL);
+
+done:
+       clear_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
+       smp_mb__after_atomic();
+       wake_up_bit(&md->flags, DMF_SUSPENDED_INTERNALLY);
+}
+
+void dm_internal_suspend_noflush(struct mapped_device *md)
+{
+       mutex_lock(&md->suspend_lock);
+       __dm_internal_suspend(md, DM_SUSPEND_NOFLUSH_FLAG);
+       mutex_unlock(&md->suspend_lock);
+}
+EXPORT_SYMBOL_GPL(dm_internal_suspend_noflush);
+
+void dm_internal_resume(struct mapped_device *md)
+{
+       mutex_lock(&md->suspend_lock);
+       __dm_internal_resume(md);
+       mutex_unlock(&md->suspend_lock);
+}
+EXPORT_SYMBOL_GPL(dm_internal_resume);
+
+/*
+ * Fast variants of internal suspend/resume hold md->suspend_lock,
+ * which prevents interaction with userspace-driven suspend.
+ */
+
+void dm_internal_suspend_fast(struct mapped_device *md)
+{
+       mutex_lock(&md->suspend_lock);
+       if (dm_suspended_md(md) || dm_suspended_internally_md(md))
                return;
 
        set_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags);
@@ -2889,9 +3011,9 @@ void dm_internal_suspend(struct mapped_device *md)
        dm_wait_for_completion(md, TASK_UNINTERRUPTIBLE);
 }
 
-void dm_internal_resume(struct mapped_device *md)
+void dm_internal_resume_fast(struct mapped_device *md)
 {
-       if (dm_suspended_md(md))
+       if (dm_suspended_md(md) || dm_suspended_internally_md(md))
                goto done;
 
        dm_queue_flush(md);
@@ -2977,6 +3099,11 @@ int dm_suspended_md(struct mapped_device *md)
        return test_bit(DMF_SUSPENDED, &md->flags);
 }
 
+int dm_suspended_internally_md(struct mapped_device *md)
+{
+       return test_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
+}
+
 int dm_test_deferred_remove_flag(struct mapped_device *md)
 {
        return test_bit(DMF_DEFERRED_REMOVE, &md->flags);
index 988c7fb7b145bb48338bd4e9bc44fbd06f740bd8..84b0f9e4ba6ca14aa4885935ddad8a7a7f8255cc 100644 (file)
@@ -65,6 +65,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
                               struct queue_limits *limits);
 struct list_head *dm_table_get_devices(struct dm_table *t);
 void dm_table_presuspend_targets(struct dm_table *t);
+void dm_table_presuspend_undo_targets(struct dm_table *t);
 void dm_table_postsuspend_targets(struct dm_table *t);
 int dm_table_resume_targets(struct dm_table *t);
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
@@ -128,6 +129,15 @@ int dm_deleting_md(struct mapped_device *md);
  */
 int dm_suspended_md(struct mapped_device *md);
 
+/*
+ * Internal suspend and resume methods.
+ */
+int dm_suspended_internally_md(struct mapped_device *md);
+void dm_internal_suspend_fast(struct mapped_device *md);
+void dm_internal_resume_fast(struct mapped_device *md);
+void dm_internal_suspend_noflush(struct mapped_device *md);
+void dm_internal_resume(struct mapped_device *md);
+
 /*
  * Test if the device is scheduled for deferred remove.
  */
index 4dfa15da9cb8344da4aae1fd28a78f05d84d8563..9233c71138f18a62a4c175d7acf9c3b8fd03a3d5 100644 (file)
@@ -5121,6 +5121,7 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
                printk("md: %s still in use.\n",mdname(mddev));
                if (did_freeze) {
                        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+                       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        md_wakeup_thread(mddev->thread);
                }
                err = -EBUSY;
@@ -5135,6 +5136,8 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
                mddev->ro = 1;
                set_disk_ro(mddev->gendisk, 1);
                clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+               md_wakeup_thread(mddev->thread);
                sysfs_notify_dirent_safe(mddev->sysfs_state);
                err = 0;
        }
@@ -5178,6 +5181,7 @@ static int do_md_stop(struct mddev *mddev, int mode,
                mutex_unlock(&mddev->open_mutex);
                if (did_freeze) {
                        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+                       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        md_wakeup_thread(mddev->thread);
                }
                return -EBUSY;
index 1d75b1dc1e2e2fcdd24a3be8cf9f0168efacd51e..e64b61ad0ef34fc42fdf8b8066bbe71965108493 100644 (file)
@@ -645,8 +645,10 @@ static int array_resize(struct dm_array_info *info, dm_block_t root,
        int r;
        struct resize resize;
 
-       if (old_size == new_size)
+       if (old_size == new_size) {
+               *new_root = root;
                return 0;
+       }
 
        resize.info = info;
        resize.root = root;
index 37d367bb9aa8976653d5bbc80b29d0dfbf037372..bf2b80d5c4707a64210b5e57deb785069dc7d921 100644 (file)
@@ -42,6 +42,12 @@ struct btree_node {
 } __packed;
 
 
+/*
+ * Locks a block using the btree node validator.
+ */
+int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
+                struct dm_block **result);
+
 void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
                  struct dm_btree_value_type *vt);
 
index cf9fd676ae444ad29f8fb6f6ef58d85706438092..1b5e13ec7f96a670ed7a9b5b472a5d2ee95a7dff 100644 (file)
@@ -92,7 +92,7 @@ struct dm_block_validator btree_node_validator = {
 
 /*----------------------------------------------------------------*/
 
-static int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
+int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
                 struct dm_block **result)
 {
        return dm_tm_read_lock(info->tm, b, &btree_node_validator, result);
index 416060c2570981d5035376fc02b100f3b6430e5b..200ac12a1d407b5c648c7271a995a022ac8e7efc 100644 (file)
@@ -847,22 +847,26 @@ EXPORT_SYMBOL_GPL(dm_btree_find_lowest_key);
  * FIXME: We shouldn't use a recursive algorithm when we have limited stack
  * space.  Also this only works for single level trees.
  */
-static int walk_node(struct ro_spine *s, dm_block_t block,
+static int walk_node(struct dm_btree_info *info, dm_block_t block,
                     int (*fn)(void *context, uint64_t *keys, void *leaf),
                     void *context)
 {
        int r;
        unsigned i, nr;
+       struct dm_block *node;
        struct btree_node *n;
        uint64_t keys;
 
-       r = ro_step(s, block);
-       n = ro_node(s);
+       r = bn_read_lock(info, block, &node);
+       if (r)
+               return r;
+
+       n = dm_block_data(node);
 
        nr = le32_to_cpu(n->header.nr_entries);
        for (i = 0; i < nr; i++) {
                if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) {
-                       r = walk_node(s, value64(n, i), fn, context);
+                       r = walk_node(info, value64(n, i), fn, context);
                        if (r)
                                goto out;
                } else {
@@ -874,7 +878,7 @@ static int walk_node(struct ro_spine *s, dm_block_t block,
        }
 
 out:
-       ro_pop(s);
+       dm_tm_unlock(info->tm, node);
        return r;
 }
 
@@ -882,15 +886,7 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
                  int (*fn)(void *context, uint64_t *keys, void *leaf),
                  void *context)
 {
-       int r;
-       struct ro_spine spine;
-
        BUG_ON(info->levels > 1);
-
-       init_ro_spine(&spine, info);
-       r = walk_node(&spine, root, fn, context);
-       exit_ro_spine(&spine);
-
-       return r;
+       return walk_node(info, root, fn, context);
 }
 EXPORT_SYMBOL_GPL(dm_btree_walk);
index 786b689bdfc7fe0c42d9a651a2369ffadcdc2382..e8a9042988871c2fcfb12b8a85c20b8c8a4629c3 100644 (file)
@@ -564,7 +564,9 @@ static int sm_bootstrap_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count
 {
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
-       return smm->ll.nr_blocks;
+       *count = smm->ll.nr_blocks;
+
+       return 0;
 }
 
 static int sm_bootstrap_get_nr_free(struct dm_space_map *sm, dm_block_t *count)
@@ -581,7 +583,9 @@ static int sm_bootstrap_get_count(struct dm_space_map *sm, dm_block_t b,
 {
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
-       return b < smm->begin ? 1 : 0;
+       *result = (b < smm->begin) ? 1 : 0;
+
+       return 0;
 }
 
 static int sm_bootstrap_count_is_more_than_one(struct dm_space_map *sm,
index 3bc30a0ae3d6084a2e08b356ac40c9082c6d5c62..9cb797d800cf8de36479130708a4a58e12e64a23 100644 (file)
@@ -10,6 +10,8 @@
 #include "dm-persistent-data-internal.h"
 
 #include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/hash.h>
 #include <linux/slab.h>
 #include <linux/device-mapper.h>
 
 
 /*----------------------------------------------------------------*/
 
+#define PREFETCH_SIZE 128
+#define PREFETCH_BITS 7
+#define PREFETCH_SENTINEL ((dm_block_t) -1ULL)
+
+struct prefetch_set {
+       struct mutex lock;
+       dm_block_t blocks[PREFETCH_SIZE];
+};
+
+static unsigned prefetch_hash(dm_block_t b)
+{
+       return hash_64(b, PREFETCH_BITS);
+}
+
+static void prefetch_wipe(struct prefetch_set *p)
+{
+       unsigned i;
+       for (i = 0; i < PREFETCH_SIZE; i++)
+               p->blocks[i] = PREFETCH_SENTINEL;
+}
+
+static void prefetch_init(struct prefetch_set *p)
+{
+       mutex_init(&p->lock);
+       prefetch_wipe(p);
+}
+
+static void prefetch_add(struct prefetch_set *p, dm_block_t b)
+{
+       unsigned h = prefetch_hash(b);
+
+       mutex_lock(&p->lock);
+       if (p->blocks[h] == PREFETCH_SENTINEL)
+               p->blocks[h] = b;
+
+       mutex_unlock(&p->lock);
+}
+
+static void prefetch_issue(struct prefetch_set *p, struct dm_block_manager *bm)
+{
+       unsigned i;
+
+       mutex_lock(&p->lock);
+
+       for (i = 0; i < PREFETCH_SIZE; i++)
+               if (p->blocks[i] != PREFETCH_SENTINEL) {
+                       dm_bm_prefetch(bm, p->blocks[i]);
+                       p->blocks[i] = PREFETCH_SENTINEL;
+               }
+
+       mutex_unlock(&p->lock);
+}
+
+/*----------------------------------------------------------------*/
+
 struct shadow_info {
        struct hlist_node hlist;
        dm_block_t where;
@@ -37,6 +94,8 @@ struct dm_transaction_manager {
 
        spinlock_t lock;
        struct hlist_head buckets[DM_HASH_SIZE];
+
+       struct prefetch_set prefetches;
 };
 
 /*----------------------------------------------------------------*/
@@ -117,6 +176,8 @@ static struct dm_transaction_manager *dm_tm_create(struct dm_block_manager *bm,
        for (i = 0; i < DM_HASH_SIZE; i++)
                INIT_HLIST_HEAD(tm->buckets + i);
 
+       prefetch_init(&tm->prefetches);
+
        return tm;
 }
 
@@ -268,8 +329,14 @@ int dm_tm_read_lock(struct dm_transaction_manager *tm, dm_block_t b,
                    struct dm_block_validator *v,
                    struct dm_block **blk)
 {
-       if (tm->is_clone)
-               return dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+       if (tm->is_clone) {
+               int r = dm_bm_read_try_lock(tm->real->bm, b, v, blk);
+
+               if (r == -EWOULDBLOCK)
+                       prefetch_add(&tm->real->prefetches, b);
+
+               return r;
+       }
 
        return dm_bm_read_lock(tm->bm, b, v, blk);
 }
@@ -317,6 +384,12 @@ struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm)
        return tm->bm;
 }
 
+void dm_tm_issue_prefetches(struct dm_transaction_manager *tm)
+{
+       prefetch_issue(&tm->prefetches, tm->bm);
+}
+EXPORT_SYMBOL_GPL(dm_tm_issue_prefetches);
+
 /*----------------------------------------------------------------*/
 
 static int dm_tm_create_internal(struct dm_block_manager *bm,
index 2772ed2a781a5de107e13d275f21b2ad1d98c7ea..2e0d4d66fb1bafe15d3d70e8d41635320cc36308 100644 (file)
@@ -108,6 +108,13 @@ int dm_tm_ref(struct dm_transaction_manager *tm, dm_block_t b,
 
 struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm);
 
+/*
+ * If you're using a non-blocking clone the tm will build up a list of
+ * requested blocks that weren't in core.  This call will request those
+ * blocks to be prefetched.
+ */
+void dm_tm_issue_prefetches(struct dm_transaction_manager *tm);
+
 /*
  * A little utility that ties the knot by producing a transaction manager
  * that has a space map managed by the transaction manager...
index 97afee672d07e228a350d63c88b148234e5032cb..4418119cf70788e174921c048d6d9cc7feafdc49 100644 (file)
@@ -364,6 +364,9 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
                goto out;
        }
 
+       /* create a nice device name */
+       sprintf(dev->name, "saa7146 (%d)", saa7146_num);
+
        DEB_EE("pci:%p\n", pci);
 
        err = pci_enable_device(pci);
@@ -438,9 +441,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
 
        /* the rest + print status message */
 
-       /* create a nice device name */
-       sprintf(dev->name, "saa7146 (%d)", saa7146_num);
-
        pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
                dev->mem, dev->revision, pci->irq,
                pci->subsystem_vendor, pci->subsystem_device);
index b8579ee68bd603567fa8a8827b279683f00a7928..2cf30576bf39cca0b4ec889ca22705d0f2a185aa 100644 (file)
@@ -962,6 +962,11 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
        case SYS_ATSC:
                c->modulation = VSB_8;
                break;
+       case SYS_ISDBS:
+               c->symbol_rate = 28860000;
+               c->rolloff = ROLLOFF_35;
+               c->bandwidth_hz = c->symbol_rate / 100 * 135;
+               break;
        default:
                c->modulation = QAM_AUTO;
                break;
@@ -2072,6 +2077,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
                break;
        case SYS_DVBS:
        case SYS_TURBO:
+       case SYS_ISDBS:
                rolloff = 135;
                break;
        case SYS_DVBS2:
index 335daeff91b941d97854d74292435f977e3cc2a5..9d0d0347758f66b178f49c3db5387ba678fa30aa 100644 (file)
@@ -864,6 +864,13 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
        memcpy(&state->frontend.ops, &ds3000_ops,
                        sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
+
+       /*
+        * Some devices like T480 starts with voltage on. Be sure
+        * to turn voltage off during init, as this can otherwise
+        * interfere with Unicable SCR systems.
+        */
+       ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF);
        return &state->frontend;
 
 error3:
index 9b684d5c8f91971edc28f0ddeebdafbc0225da50..15bf4318cb744408683ca5f69189e6d1e5a38307 100644 (file)
@@ -266,7 +266,7 @@ int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221,
        return s->status;
 }
 
-int sp2_init(struct sp2 *s)
+static int sp2_init(struct sp2 *s)
 {
        int ret = 0;
        u8 buf;
@@ -348,7 +348,7 @@ err:
        return ret;
 }
 
-int sp2_exit(struct i2c_client *client)
+static int sp2_exit(struct i2c_client *client)
 {
        struct sp2 *s;
 
index d9905fb52f847132e5baa1fa530bad11afb99693..b35d65c9cc059c3ee4ba4482c9cd629be07bd1b3 100644 (file)
@@ -216,32 +216,30 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe)
        c->delivery_system = SYS_ISDBS;
 
        layers = 0;
-       ret = reg_read(state, 0xe8, val, 3);
+       ret = reg_read(state, 0xe6, val, 5);
        if (ret == 0) {
-               int slots;
                u8 v;
 
+               c->stream_id = val[0] << 8 | val[1];
+
                /* high/single layer */
-               v = (val[0] & 0x70) >> 4;
+               v = (val[2] & 0x70) >> 4;
                c->modulation = (v == 7) ? PSK_8 : QPSK;
                c->fec_inner = fec_conv_sat[v];
                c->layer[0].fec = c->fec_inner;
                c->layer[0].modulation = c->modulation;
-               c->layer[0].segment_count = val[1] & 0x3f; /* slots */
+               c->layer[0].segment_count = val[3] & 0x3f; /* slots */
 
                /* low layer */
-               v = (val[0] & 0x07);
+               v = (val[2] & 0x07);
                c->layer[1].fec = fec_conv_sat[v];
                if (v == 0)  /* no low layer */
                        c->layer[1].segment_count = 0;
                else
-                       c->layer[1].segment_count = val[2] & 0x3f; /* slots */
+                       c->layer[1].segment_count = val[4] & 0x3f; /* slots */
                /* actually, BPSK if v==1, but not defined in fe_modulation_t */
                c->layer[1].modulation = QPSK;
                layers = (v > 0) ? 2 : 1;
-
-               slots =  c->layer[0].segment_count +  c->layer[1].segment_count;
-               c->symbol_rate = 28860000 * slots / 48;
        }
 
        /* statistics */
@@ -363,7 +361,7 @@ static int tc90522t_get_frontend(struct dvb_frontend *fe)
                u8 v;
 
                c->isdbt_partial_reception = val[0] & 0x01;
-               c->isdbt_sb_mode = (val[0] & 0xc0) == 0x01;
+               c->isdbt_sb_mode = (val[0] & 0xc0) == 0x40;
 
                /* layer A */
                v = (val[2] & 0x78) >> 3;
index 932ed9be9ff3d756fb35948e8183e09faaa60c34..b10aaeda2bb4599576849a8a5b786dcc2542aa49 100644 (file)
@@ -2190,7 +2190,7 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev,
                ret = smiapp_set_compose(subdev, fh, sel);
                break;
        default:
-               BUG();
+               ret = -EINVAL;
        }
 
        mutex_unlock(&sensor->mutex);
index 331eddac7222ae7f62fb757148f90c8881b5ef4c..3bd386c371f74ab260b00cac9dcfaa9eadecc962 100644 (file)
@@ -1078,7 +1078,7 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
        for (line = 0; line < lines; line++) {
                while (offset && offset >= sg_dma_len(sg)) {
                        offset -= sg_dma_len(sg);
-                       sg++;
+                       sg = sg_next(sg);
                }
 
                if (lpi && line > 0 && !(line % lpi))
@@ -1101,14 +1101,14 @@ static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
                        *(rp++) = cpu_to_le32(0); /* bits 63-32 */
                        todo -= (sg_dma_len(sg)-offset);
                        offset = 0;
-                       sg++;
+                       sg = sg_next(sg);
                        while (todo > sg_dma_len(sg)) {
                                *(rp++) = cpu_to_le32(RISC_WRITE|
                                                    sg_dma_len(sg));
                                *(rp++) = cpu_to_le32(sg_dma_address(sg));
                                *(rp++) = cpu_to_le32(0); /* bits 63-32 */
                                todo -= sg_dma_len(sg);
-                               sg++;
+                               sg = sg_next(sg);
                        }
                        *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
                        *(rp++) = cpu_to_le32(sg_dma_address(sg));
index 13734b8c791724e8a84dc27cd5949aeaf6a3b1ca..4cb90317ff45c2bd1b5b57f5b6e0024c3b8bc29b 100644 (file)
@@ -1600,6 +1600,7 @@ 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(&info, 0, sizeof(struct i2c_board_info));
@@ -1635,6 +1636,7 @@ static int dvb_register(struct cx23885_tsport *port)
                /* port c - terrestrial/cable */
                case 2:
                        /* attach frontend */
+                       memset(&si2168_config, 0, sizeof(si2168_config));
                        si2168_config.i2c_adapter = &adapter;
                        si2168_config.fe = &fe0->dvb.frontend;
                        si2168_config.ts_mode = SI2168_TS_SERIAL;
@@ -1654,6 +1656,7 @@ static int dvb_register(struct cx23885_tsport *port)
                        port->i2c_client_demod = client_demod;
 
                        /* attach tuner */
+                       memset(&si2157_config, 0, sizeof(si2157_config));
                        si2157_config.fe = fe0->dvb.frontend;
                        memset(&info, 0, sizeof(struct i2c_board_info));
                        strlcpy(info.type, "si2157", I2C_NAME_SIZE);
index 172583d736fef31c30ab7338405e3d221d17211b..8cbe6b49f4c238de365b0a231eef8f4dff2425ff 100644 (file)
@@ -105,11 +105,8 @@ static irqreturn_t solo_isr(int irq, void *data)
        if (!status)
                return IRQ_NONE;
 
-       if (status & ~solo_dev->irq_mask) {
-               solo_reg_write(solo_dev, SOLO_IRQ_STAT,
-                              status & ~solo_dev->irq_mask);
-               status &= solo_dev->irq_mask;
-       }
+       /* Acknowledge all interrupts immediately */
+       solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
 
        if (status & SOLO_IRQ_PCI_ERR)
                solo_p2m_error_isr(solo_dev);
@@ -132,9 +129,6 @@ static irqreturn_t solo_isr(int irq, void *data)
        if (status & SOLO_IRQ_G723)
                solo_g723_isr(solo_dev);
 
-       /* Clear all interrupts handled */
-       solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
-
        return IRQ_HANDLED;
 }
 
index 5425ba1e320d9a2c6bbaa5dd8686ee31372b63c7..95d5d520204884aba7ea0d874376e9136a9f0759 100644 (file)
@@ -1,7 +1,6 @@
 config VIDEO_TW68
        tristate "Techwell tw68x Video For Linux"
        depends on VIDEO_DEV && PCI && VIDEO_V4L2
-       select I2C_ALGOBIT
        select VIDEOBUF2_DMA_SG
        ---help---
          Support for Techwell tw68xx based frame grabber boards.
index a6fb48cf7aaed62fb7b845395d7349bb46916c34..63f0b64057cbf88146a83091bb8b70ccc1857b72 100644 (file)
@@ -306,7 +306,7 @@ static int tw68_initdev(struct pci_dev *pci_dev,
 
        /* get irq */
        err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw68_irq,
-                         IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+                         IRQF_SHARED, dev->name, dev);
        if (err < 0) {
                pr_err("%s: can't get IRQ %d\n",
                       dev->name, pci_dev->irq);
index bee9074ebc138b28a0b12bc38c398d720eadb463..3aac88f1d54ae518a37998c1eb92dfb32020c158 100644 (file)
@@ -166,7 +166,7 @@ config VIDEO_MEM2MEM_DEINTERLACE
 config VIDEO_SAMSUNG_S5P_G2D
        tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver"
        depends on VIDEO_DEV && VIDEO_V4L2
-       depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
+       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
        depends on HAS_DMA
        select VIDEOBUF2_DMA_CONTIG
        select V4L2_MEM2MEM_DEV
@@ -178,7 +178,7 @@ config VIDEO_SAMSUNG_S5P_G2D
 config VIDEO_SAMSUNG_S5P_JPEG
        tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
        depends on VIDEO_DEV && VIDEO_V4L2
-       depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
+       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
        depends on HAS_DMA
        select VIDEOBUF2_DMA_CONTIG
        select V4L2_MEM2MEM_DEV
@@ -189,7 +189,7 @@ config VIDEO_SAMSUNG_S5P_JPEG
 config VIDEO_SAMSUNG_S5P_MFC
        tristate "Samsung S5P MFC Video Codec"
        depends on VIDEO_DEV && VIDEO_V4L2
-       depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
+       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
        depends on HAS_DMA
        select VIDEOBUF2_DMA_CONTIG
        default n
index 77c95123774409ac491d45d8db465fdb9c72360b..b7b2e472240ad504c30018487bc7712691f3ef17 100644 (file)
@@ -2,7 +2,7 @@
 config VIDEO_SAMSUNG_EXYNOS4_IS
        bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver"
        depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-       depends on (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST)
+       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
        depends on OF && COMMON_CLK
        help
          Say Y here to enable camera host interface devices for
index b70fd996d7946e5a1761fc684362972b4f5899c6..aee92d908e49e457ee7baffe41634155ab069da5 100644 (file)
@@ -832,6 +832,7 @@ err:
        return -ENXIO;
 }
 
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
 static int fimc_m2m_suspend(struct fimc_dev *fimc)
 {
        unsigned long flags;
@@ -870,6 +871,7 @@ static int fimc_m2m_resume(struct fimc_dev *fimc)
 
        return 0;
 }
+#endif /* CONFIG_PM_RUNTIME || CONFIG_PM_SLEEP */
 
 static const struct of_device_id fimc_of_match[];
 
index e525a7c8d885770c7f0e85e3219a387f432a13c2..6fcc7f072acea885816d30c95068c77942b17fde 100644 (file)
@@ -893,7 +893,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
                               unsigned long buffer, unsigned long size,
                               struct s5p_jpeg_ctx *ctx)
 {
-       int c, components, notfound;
+       int c, components = 0, notfound;
        unsigned int height, width, word, subsampling = 0;
        long length;
        struct s5p_jpeg_buffer jpeg_buffer;
@@ -2632,6 +2632,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
 static int s5p_jpeg_runtime_suspend(struct device *dev)
 {
        struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
@@ -2681,7 +2682,9 @@ static int s5p_jpeg_runtime_resume(struct device *dev)
 
        return 0;
 }
+#endif /* CONFIG_PM_RUNTIME || CONFIG_PM_SLEEP */
 
+#ifdef CONFIG_PM_SLEEP
 static int s5p_jpeg_suspend(struct device *dev)
 {
        if (pm_runtime_suspended(dev))
@@ -2697,6 +2700,7 @@ static int s5p_jpeg_resume(struct device *dev)
 
        return s5p_jpeg_runtime_resume(dev);
 }
+#endif
 
 static const struct dev_pm_ops s5p_jpeg_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(s5p_jpeg_suspend, s5p_jpeg_resume)
index a9d56f8936b4e576d2e4552b1d86323d15801da5..beb180e71ba0e1022611dc3bdb1eacc9e14478f4 100644 (file)
@@ -9,7 +9,7 @@
 config VIDEO_SAMSUNG_S5P_TV
        bool "Samsung TV driver for S5P platform"
        depends on PM_RUNTIME
-       depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
+       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
        default n
        ---help---
          Say Y here to enable selecting the TV output devices for
index d71139a2ae0049526aa810512553d56942025307..c3090932f06d56cde74f3f2ed409325b3aff1d36 100644 (file)
@@ -1,8 +1,11 @@
 config VIDEO_VIVID
        tristate "Virtual Video Test Driver"
-       depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
+       depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FB
        select FONT_SUPPORT
        select FONT_8x16
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
        select VIDEOBUF2_VMALLOC
        default n
        ---help---
index 2c61a62ab48b9845a0c4a16df29e40736762df40..686c3c2ad05bcdb1fb9e28246f78cccdef514872 100644 (file)
@@ -100,11 +100,9 @@ MODULE_PARM_DESC(ccs_out_mode, " output crop/compose/scale mode:\n"
                           "\t\t    bit 0=crop, 1=compose, 2=scale,\n"
                           "\t\t    -1=user-controlled (default)");
 
-static unsigned multiplanar[VIVID_MAX_DEVS];
+static unsigned multiplanar[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 1 };
 module_param_array(multiplanar, uint, NULL, 0444);
-MODULE_PARM_DESC(multiplanar, " 0 (default) is alternating single and multiplanar devices,\n"
-                             "\t\t    1 is single planar devices,\n"
-                             "\t\t    2 is multiplanar devices");
+MODULE_PARM_DESC(multiplanar, " 1 (default) creates a single planar device, 2 creates a multiplanar device.");
 
 /* Default: video + vbi-cap (raw and sliced) + radio rx + radio tx + sdr + vbi-out + vid-out */
 static unsigned node_types[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 0x1d3d };
@@ -669,10 +667,7 @@ static int __init vivid_create_instance(int inst)
        /* start detecting feature set */
 
        /* do we use single- or multi-planar? */
-       if (multiplanar[inst] == 0)
-               dev->multiplanar = inst & 1;
-       else
-               dev->multiplanar = multiplanar[inst] > 1;
+       dev->multiplanar = multiplanar[inst] > 1;
        v4l2_info(&dev->v4l2_dev, "using %splanar format API\n",
                        dev->multiplanar ? "multi" : "single ");
 
index 0c6fa53fa64614f34090e076717c43e094150230..cbcd6250e7b2afc3feec4456337700e3ae11b300 100644 (file)
@@ -136,7 +136,7 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
                tpg->black_line[plane] = vzalloc(max_w * pixelsz);
                if (!tpg->black_line[plane])
                        return -ENOMEM;
-               tpg->random_line[plane] = vzalloc(max_w * pixelsz);
+               tpg->random_line[plane] = vzalloc(max_w * 2 * pixelsz);
                if (!tpg->random_line[plane])
                        return -ENOMEM;
        }
index 6f28f6e02ea57e947a2a8805ccccee4cfaa30cc2..704397f3c106b6419ed7a3c88b8dcb2f7ae3a902 100644 (file)
@@ -1256,7 +1256,7 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
                fmerr("Unable to read firmware(%s) content\n", fw_name);
                return ret;
        }
-       fmdbg("Firmware(%s) length : %d bytes\n", fw_name, fw_entry->size);
+       fmdbg("Firmware(%s) length : %zu bytes\n", fw_name, fw_entry->size);
 
        fw_data = (void *)fw_entry->data;
        fw_len = fw_entry->size;
index b8837dd39bb2a52740a36765d69d75af464f51fa..65f80b8b9f7ab922b39f3e02d8b878c097bae1fb 100644 (file)
@@ -1678,7 +1678,8 @@ static void imon_incoming_packet(struct imon_context *ictx,
                if (press_type == 0)
                        rc_keyup(ictx->rdev);
                else {
-                       if (ictx->rc_type == RC_BIT_RC6_MCE)
+                       if (ictx->rc_type == RC_BIT_RC6_MCE ||
+                           ictx->rc_type == RC_BIT_OTHER)
                                rc_keydown(ictx->rdev,
                                           ictx->rc_type == RC_BIT_RC6_MCE ? RC_TYPE_RC6_MCE : RC_TYPE_OTHER,
                                           ictx->rc_scancode, ictx->rc_toggle);
index 08bbd4f508cd283b54167a2010366b00d5c2ddc0..b0df62961c1403c4acd439c46254a15b3981cac7 100644 (file)
@@ -297,7 +297,7 @@ static int hix5hd2_ir_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int hix5hd2_ir_suspend(struct device *dev)
 {
        struct hix5hd2_ir_priv *priv = dev_get_drvdata(dev);
index 2ef763928ca440076951e9658174ec88e6ba1833..84fa6e9b59a1acd9360364fbd30ca0a4e00d3a56 100644 (file)
@@ -53,7 +53,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
        u32 scancode;
        enum rc_type protocol;
 
-       if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
+       if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ)))
                return 0;
 
        if (!is_timing_event(ev)) {
index f1f098e22f7ea9f19b458223f226d5e73077bb2d..d16bc67af732251998fb280b86d887835cf39e1b 100644 (file)
@@ -259,8 +259,8 @@ again:
                        case 32:
                                if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
                                        protocol = RC_TYPE_RC6_MCE;
-                                       scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
                                        toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
+                                       scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
                                } else {
                                        protocol = RC_BIT_RC6_6A_32;
                                        toggle = 0;
index e8fff2add265ca303c70abf605357ec7836439f1..b732ac6a26d8065cc26ecb3a648ced999db71367 100644 (file)
@@ -262,7 +262,6 @@ int ir_raw_event_register(struct rc_dev *dev)
                return -ENOMEM;
 
        dev->raw->dev = dev;
-       dev->enabled_protocols = ~0;
        dev->change_protocol = change_protocol;
        rc = kfifo_alloc(&dev->raw->kfifo,
                         sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
index a7991c7d010af0bc487db2fb6a8ca94bb08723ad..8d3b74c5a71766b5c79eceecc6b68d9a9b93ff0f 100644 (file)
@@ -1421,6 +1421,8 @@ int rc_register_device(struct rc_dev *dev)
 
        if (dev->change_protocol) {
                u64 rc_type = (1 << rc_map->rc_type);
+               if (dev->driver_type == RC_DRIVER_IR_RAW)
+                       rc_type |= RC_BIT_LIRC;
                rc = dev->change_protocol(dev, &rc_type);
                if (rc < 0)
                        goto out_raw;
index e44c8aba6074c0667181d9e7a7daab2f7db4d1bc..803a0e63d47eef2ee40e1fb1ce7fbec21cd7d9ab 100644 (file)
@@ -1333,9 +1333,9 @@ static int xc5000_release(struct dvb_frontend *fe)
 
        if (priv) {
                cancel_delayed_work(&priv->timer_sleep);
-               hybrid_tuner_release_state(priv);
                if (priv->firmware)
                        release_firmware(priv->firmware);
+               hybrid_tuner_release_state(priv);
        }
 
        mutex_unlock(&xc5000_list_mutex);
index 00758c83eec733475be5596818a5347868cde089..1896ab218b117beaaa229848b0b9c72f32da5e0b 100644 (file)
@@ -193,8 +193,8 @@ static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val,
        return af9035_wr_regs(d, reg, &val, 1);
 }
 
-static int af9035_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
-               void *platform_data, struct i2c_adapter *adapter)
+static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
+               u8 addr, void *platform_data, struct i2c_adapter *adapter)
 {
        int ret, num;
        struct state *state = d_to_priv(d);
@@ -221,7 +221,7 @@ static int af9035_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
                goto err;
        }
 
-       request_module(board_info.type);
+       request_module("%s", board_info.type);
 
        /* register I2C device */
        client = i2c_new_device(adapter, &board_info);
index d3c5f230e97a7272f69e7cbba367c3a18c9cbe8b..ae917c042a52e7737a74e536328906014dbe34aa 100644 (file)
@@ -630,8 +630,8 @@ error:
        return ret;
 }
 
-static int anysee_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
-               void *platform_data)
+static int anysee_add_i2c_dev(struct dvb_usb_device *d, const char *type,
+               u8 addr, void *platform_data)
 {
        int ret, num;
        struct anysee_state *state = d_to_priv(d);
@@ -659,7 +659,7 @@ static int anysee_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
                goto err;
        }
 
-       request_module(board_info.type);
+       request_module("%s", board_info.type);
 
        /* register I2C device */
        client = i2c_new_device(adapter, &board_info);
index b5e52fe7957aff0d047abb1f89caab275fcb1afd..901cf2b952d786a80bfed6a60d2b28cd49328ce9 100644 (file)
@@ -504,7 +504,7 @@ EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
 int em28xx_audio_setup(struct em28xx *dev)
 {
        int vid1, vid2, feat, cfg;
-       u32 vid;
+       u32 vid = 0;
        u8 i2s_samplerates;
 
        if (dev->chip_id == CHIP_ID_EM2870 ||
index 581f6dad4ca9deef0fa5a0820372238b8a4e3bbd..23f8f6afa2e061a783ee9fa5c0d244c9c6018dcf 100644 (file)
@@ -712,8 +712,10 @@ static int em28xx_ir_init(struct em28xx *dev)
        em28xx_info("Registering input extension\n");
 
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+       if (!ir)
+               return -ENOMEM;
        rc = rc_allocate_device();
-       if (!ir || !rc)
+       if (!rc)
                goto error;
 
        /* record handles to ourself */
index 328b5ba47a0a20b1f93ade77a74c0c9fb4e06cfe..fd1fa412e09462362d8b4520ee64c6bb1d2979e5 100644 (file)
@@ -932,7 +932,7 @@ static int hackrf_set_bandwidth(struct hackrf_dev *dev)
        dev->bandwidth->val = bandwidth;
        dev->bandwidth->cur.val = bandwidth;
 
-       dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth_lut[i].freq);
+       dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth);
 
        u16tmp = 0;
        u16tmp |= ((bandwidth >> 0) & 0xff) << 0;
index ccc00099b26144e4bd1c5b99cbfccbf266a50ad7..1c0dbf428a3af83c4460e51615232fd96a2180ab 100644 (file)
@@ -632,7 +632,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
                        break;
                case V4L2_PIX_FMT_JPEG:
                case V4L2_PIX_FMT_MJPEG:
-                       buf->vb.v4l2_buf.length = jpgsize;
+                       vb2_set_plane_payload(&buf->vb, 0, jpgsize);
                        memcpy(vbuf, tmpbuf, jpgsize);
                        break;
                case V4L2_PIX_FMT_YUV422P:
index 68bc9615660efaf584bc1361b54706a5ef2b4df1..9bfa041e33161be93333ad0133acc1adbb957b4e 100644 (file)
@@ -446,6 +446,7 @@ static int usbvision_v4l2_close(struct file *file)
        if (usbvision->remove_pending) {
                printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
+               return 0;
        }
        mutex_unlock(&usbvision->v4l2_lock);
 
@@ -1221,6 +1222,7 @@ static int usbvision_radio_close(struct file *file)
        if (usbvision->remove_pending) {
                printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
+               return err_code;
        }
 
        mutex_unlock(&usbvision->v4l2_lock);
index 60a8e2c3631e0b155b241e624092ccef271ae030..378ae02e593b93a19bb9010a23f62175029bbefd 100644 (file)
@@ -318,7 +318,6 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
        stream->ctrl = probe;
        stream->cur_format = format;
        stream->cur_frame = frame;
-       stream->frame_size = fmt->fmt.pix.sizeimage;
 
 done:
        mutex_unlock(&stream->mutex);
index 9ace520bb079792b840d8aff38b68945fef0eeb0..df81b9c4faf12ae0e00f6267d380d76608b4c8ba 100644 (file)
@@ -1143,7 +1143,7 @@ static int uvc_video_encode_data(struct uvc_streaming *stream,
 static void uvc_video_validate_buffer(const struct uvc_streaming *stream,
                                      struct uvc_buffer *buf)
 {
-       if (stream->frame_size != buf->bytesused &&
+       if (stream->ctrl.dwMaxVideoFrameSize != buf->bytesused &&
            !(stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED))
                buf->error = 1;
 }
index 6f676c29ec09fd997b8833d78df1b8b72fdf0d91..864ada74036033fea9c2956ac4980b646163bbc0 100644 (file)
@@ -457,7 +457,6 @@ struct uvc_streaming {
        struct uvc_format *def_format;
        struct uvc_format *cur_format;
        struct uvc_frame *cur_frame;
-       size_t frame_size;
 
        /* Protect access to ctrl, cur_format, cur_frame and hardware video
         * probe control.
index bf80f0f7dfb853ab367887fb76cfc1d0be6c907e..e02353e340dd78d07d0750b05af0533ffad35dae 100644 (file)
@@ -305,6 +305,15 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
        /* Try to remap memory */
        size = vma->vm_end - vma->vm_start;
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       /* the "vm_pgoff" is just used in v4l2 to find the
+        * corresponding buffer data structure which is allocated
+        * earlier and it does not mean the offset from the physical
+        * buffer start address as usual. So set it to 0 to pass
+        * the sanity check in vm_iomap_memory().
+        */
+       vma->vm_pgoff = 0;
+
        retval = vm_iomap_memory(vma, mem->dma_handle, size);
        if (retval) {
                dev_err(q->dev, "mmap: remap failed with error %d. ",
index 6d91c27fd4c8f325f29b7d21f5e93a89cff59691..191383d8c94d6e1d8e6d67bfc3e0ec5494b1d323 100644 (file)
@@ -41,6 +41,14 @@ config TI_EMIF
          parameters and other settings during frequency, voltage and
          temperature changes
 
+config OMAP_GPMC
+       bool
+       help
+         This driver is for the General Purpose Memory Controller (GPMC)
+         present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows
+         interfacing to a variety of asynchronous as well as synchronous
+         memory drives like NOR, NAND, OneNAND, SRAM.
+
 config MVEBU_DEVBUS
        bool "Marvell EBU Device Bus Controller"
        default y
@@ -61,16 +69,6 @@ config TEGRA20_MC
          analysis, especially for IOMMU/GART(Graphics Address
          Relocation Table) module.
 
-config TEGRA30_MC
-       bool "Tegra30 Memory Controller(MC) driver"
-       default y
-       depends on ARCH_TEGRA_3x_SOC
-       help
-         This driver is for the Memory Controller(MC) module available
-         in Tegra30 SoCs, mainly for a address translation fault
-         analysis, especially for IOMMU/SMMU(System Memory Management
-         Unit) module.
-
 config FSL_CORENET_CF
        tristate "Freescale CoreNet Error Reporting"
        depends on FSL_SOC_BOOKE
@@ -85,4 +83,6 @@ config FSL_IFC
        bool
        depends on FSL_SOC
 
+source "drivers/memory/tegra/Kconfig"
+
 endif
index c32d31981be314518d16c8933177937e97841545..6b6548124473350a453b8982e341e4bb27264458 100644 (file)
@@ -8,8 +8,10 @@ endif
 obj-$(CONFIG_ATMEL_SDRAMC)     += atmel-sdramc.o
 obj-$(CONFIG_TI_AEMIF)         += ti-aemif.o
 obj-$(CONFIG_TI_EMIF)          += emif.o
+obj-$(CONFIG_OMAP_GPMC)                += omap-gpmc.o
 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_TEGRA30_MC)       += tegra30-mc.o
+
+obj-$(CONFIG_TEGRA_MC)         += tegra/
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
new file mode 100644 (file)
index 0000000..ffc5e60
--- /dev/null
@@ -0,0 +1,2092 @@
+/*
+ * GPMC support functions
+ *
+ * Copyright (C) 2005-2006 Nokia Corporation
+ *
+ * Author: Juha Yrjola
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@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.
+ */
+#undef DEBUG
+
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_mtd.h>
+#include <linux/of_device.h>
+#include <linux/omap-gpmc.h>
+#include <linux/mtd/nand.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/platform_data/mtd-nand-omap2.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
+
+#include <asm/mach-types.h>
+
+#define        DEVICE_NAME             "omap-gpmc"
+
+/* GPMC register offsets */
+#define GPMC_REVISION          0x00
+#define GPMC_SYSCONFIG         0x10
+#define GPMC_SYSSTATUS         0x14
+#define GPMC_IRQSTATUS         0x18
+#define GPMC_IRQENABLE         0x1c
+#define GPMC_TIMEOUT_CONTROL   0x40
+#define GPMC_ERR_ADDRESS       0x44
+#define GPMC_ERR_TYPE          0x48
+#define GPMC_CONFIG            0x50
+#define GPMC_STATUS            0x54
+#define GPMC_PREFETCH_CONFIG1  0x1e0
+#define GPMC_PREFETCH_CONFIG2  0x1e4
+#define GPMC_PREFETCH_CONTROL  0x1ec
+#define GPMC_PREFETCH_STATUS   0x1f0
+#define GPMC_ECC_CONFIG                0x1f4
+#define GPMC_ECC_CONTROL       0x1f8
+#define GPMC_ECC_SIZE_CONFIG   0x1fc
+#define GPMC_ECC1_RESULT        0x200
+#define GPMC_ECC_BCH_RESULT_0   0x240   /* not available on OMAP2 */
+#define        GPMC_ECC_BCH_RESULT_1   0x244   /* not available on OMAP2 */
+#define        GPMC_ECC_BCH_RESULT_2   0x248   /* not available on OMAP2 */
+#define        GPMC_ECC_BCH_RESULT_3   0x24c   /* not available on OMAP2 */
+#define        GPMC_ECC_BCH_RESULT_4   0x300   /* not available on OMAP2 */
+#define        GPMC_ECC_BCH_RESULT_5   0x304   /* not available on OMAP2 */
+#define        GPMC_ECC_BCH_RESULT_6   0x308   /* not available on OMAP2 */
+
+/* GPMC ECC control settings */
+#define GPMC_ECC_CTRL_ECCCLEAR         0x100
+#define GPMC_ECC_CTRL_ECCDISABLE       0x000
+#define GPMC_ECC_CTRL_ECCREG1          0x001
+#define GPMC_ECC_CTRL_ECCREG2          0x002
+#define GPMC_ECC_CTRL_ECCREG3          0x003
+#define GPMC_ECC_CTRL_ECCREG4          0x004
+#define GPMC_ECC_CTRL_ECCREG5          0x005
+#define GPMC_ECC_CTRL_ECCREG6          0x006
+#define GPMC_ECC_CTRL_ECCREG7          0x007
+#define GPMC_ECC_CTRL_ECCREG8          0x008
+#define GPMC_ECC_CTRL_ECCREG9          0x009
+
+#define GPMC_CONFIG_LIMITEDADDRESS             BIT(1)
+
+#define        GPMC_CONFIG2_CSEXTRADELAY               BIT(7)
+#define        GPMC_CONFIG3_ADVEXTRADELAY              BIT(7)
+#define        GPMC_CONFIG4_OEEXTRADELAY               BIT(7)
+#define        GPMC_CONFIG4_WEEXTRADELAY               BIT(23)
+#define        GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN        BIT(6)
+#define        GPMC_CONFIG6_CYCLE2CYCLESAMECSEN        BIT(7)
+
+#define GPMC_CS0_OFFSET                0x60
+#define GPMC_CS_SIZE           0x30
+#define        GPMC_BCH_SIZE           0x10
+
+#define GPMC_MEM_END           0x3FFFFFFF
+
+#define GPMC_CHUNK_SHIFT       24              /* 16 MB */
+#define GPMC_SECTION_SHIFT     28              /* 128 MB */
+
+#define CS_NUM_SHIFT           24
+#define ENABLE_PREFETCH                (0x1 << 7)
+#define DMA_MPU_MODE           2
+
+#define        GPMC_REVISION_MAJOR(l)          ((l >> 4) & 0xf)
+#define        GPMC_REVISION_MINOR(l)          (l & 0xf)
+
+#define        GPMC_HAS_WR_ACCESS              0x1
+#define        GPMC_HAS_WR_DATA_MUX_BUS        0x2
+#define        GPMC_HAS_MUX_AAD                0x4
+
+#define GPMC_NR_WAITPINS               4
+
+#define GPMC_CS_CONFIG1                0x00
+#define GPMC_CS_CONFIG2                0x04
+#define GPMC_CS_CONFIG3                0x08
+#define GPMC_CS_CONFIG4                0x0c
+#define GPMC_CS_CONFIG5                0x10
+#define GPMC_CS_CONFIG6                0x14
+#define GPMC_CS_CONFIG7                0x18
+#define GPMC_CS_NAND_COMMAND   0x1c
+#define GPMC_CS_NAND_ADDRESS   0x20
+#define GPMC_CS_NAND_DATA      0x24
+
+/* Control Commands */
+#define GPMC_CONFIG_RDY_BSY    0x00000001
+#define GPMC_CONFIG_DEV_SIZE   0x00000002
+#define GPMC_CONFIG_DEV_TYPE   0x00000003
+#define GPMC_SET_IRQ_STATUS    0x00000004
+
+#define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
+#define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
+#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
+#define GPMC_CONFIG1_READTYPE_SYNC      (1 << 29)
+#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28)
+#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
+#define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+#define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+#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_PIN_SEL(val)  ((val & 3) << 16)
+#define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
+#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(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_TIME_PARA_GRAN     (1 << 4)
+#define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
+#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
+#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
+#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
+#define GPMC_CONFIG7_CSVALID           (1 << 6)
+
+#define GPMC_DEVICETYPE_NOR            0
+#define GPMC_DEVICETYPE_NAND           2
+#define GPMC_CONFIG_WRITEPROTECT       0x00000010
+#define WR_RD_PIN_MONITORING           0x00600000
+
+#define GPMC_ENABLE_IRQ                0x0000000d
+
+/* ECC commands */
+#define GPMC_ECC_READ          0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE         1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN       2 /* Reset before syndrom is read back */
+
+/* XXX: Only NAND irq has been considered,currently these are the only ones used
+ */
+#define        GPMC_NR_IRQ             2
+
+struct gpmc_cs_data {
+       const char *name;
+
+#define GPMC_CS_RESERVED       (1 << 0)
+       u32 flags;
+
+       struct resource mem;
+};
+
+struct gpmc_client_irq {
+       unsigned                irq;
+       u32                     bitmask;
+};
+
+/* Structure to save gpmc cs context */
+struct gpmc_cs_config {
+       u32 config1;
+       u32 config2;
+       u32 config3;
+       u32 config4;
+       u32 config5;
+       u32 config6;
+       u32 config7;
+       int is_valid;
+};
+
+/*
+ * Structure to save/restore gpmc context
+ * to support core off on OMAP3
+ */
+struct omap3_gpmc_regs {
+       u32 sysconfig;
+       u32 irqenable;
+       u32 timeout_ctrl;
+       u32 config;
+       u32 prefetch_config1;
+       u32 prefetch_config2;
+       u32 prefetch_control;
+       struct gpmc_cs_config cs_context[GPMC_CS_NUM];
+};
+
+static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
+static struct irq_chip gpmc_irq_chip;
+static int gpmc_irq_start;
+
+static struct resource gpmc_mem_root;
+static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM];
+static DEFINE_SPINLOCK(gpmc_mem_lock);
+/* Define chip-selects as reserved by default until probe completes */
+static unsigned int gpmc_cs_num = GPMC_CS_NUM;
+static unsigned int gpmc_nr_waitpins;
+static struct device *gpmc_dev;
+static int gpmc_irq;
+static resource_size_t phys_base, mem_size;
+static unsigned gpmc_capability;
+static void __iomem *gpmc_base;
+
+static struct clk *gpmc_l3_clk;
+
+static irqreturn_t gpmc_handle_irq(int irq, void *dev);
+
+static void gpmc_write_reg(int idx, u32 val)
+{
+       writel_relaxed(val, gpmc_base + idx);
+}
+
+static u32 gpmc_read_reg(int idx)
+{
+       return readl_relaxed(gpmc_base + idx);
+}
+
+void gpmc_cs_write_reg(int cs, int idx, u32 val)
+{
+       void __iomem *reg_addr;
+
+       reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+       writel_relaxed(val, reg_addr);
+}
+
+static u32 gpmc_cs_read_reg(int cs, int idx)
+{
+       void __iomem *reg_addr;
+
+       reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+       return readl_relaxed(reg_addr);
+}
+
+/* TODO: Add support for gpmc_fck to clock framework and use it */
+static unsigned long gpmc_get_fclk_period(void)
+{
+       unsigned long rate = clk_get_rate(gpmc_l3_clk);
+
+       rate /= 1000;
+       rate = 1000000000 / rate;       /* In picoseconds */
+
+       return rate;
+}
+
+static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+{
+       unsigned long tick_ps;
+
+       /* Calculate in picosecs to yield more exact results */
+       tick_ps = gpmc_get_fclk_period();
+
+       return (time_ns * 1000 + tick_ps - 1) / tick_ps;
+}
+
+static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
+{
+       unsigned long tick_ps;
+
+       /* Calculate in picosecs to yield more exact results */
+       tick_ps = gpmc_get_fclk_period();
+
+       return (time_ps + tick_ps - 1) / tick_ps;
+}
+
+unsigned int gpmc_ticks_to_ns(unsigned int ticks)
+{
+       return ticks * gpmc_get_fclk_period() / 1000;
+}
+
+static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
+{
+       return ticks * gpmc_get_fclk_period();
+}
+
+static unsigned int gpmc_round_ps_to_ticks(unsigned int time_ps)
+{
+       unsigned long ticks = gpmc_ps_to_ticks(time_ps);
+
+       return ticks * gpmc_get_fclk_period();
+}
+
+static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
+{
+       u32 l;
+
+       l = gpmc_cs_read_reg(cs, reg);
+       if (value)
+               l |= mask;
+       else
+               l &= ~mask;
+       gpmc_cs_write_reg(cs, reg, l);
+}
+
+static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
+{
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
+                          GPMC_CONFIG1_TIME_PARA_GRAN,
+                          p->time_para_granularity);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
+                          GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
+                          GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+                          GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+                          GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+                          GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
+                          p->cycle2cyclesamecsen);
+       gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+                          GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
+                          p->cycle2cyclediffcsen);
+}
+
+#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)
+{
+       u32 l;
+       int nr_bits, max_value, mask;
+
+       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;
+       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);
+       } else {
+               pr_info("gpmc,%s = <%u>\n", name, l);
+       }
+
+       return l;
+}
+
+#define GPMC_PRINT_CONFIG(cs, config) \
+       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)
+#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)
+#define GPMC_GET_TICKS(reg, st, end, field) \
+       get_gpmc_timing_reg(cs, (reg), (st), (end), 0, 0, 0, field)
+
+static void gpmc_show_regs(int cs, const char *desc)
+{
+       pr_info("gpmc cs%i %s:\n", cs, desc);
+       GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG1);
+       GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG2);
+       GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG3);
+       GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG4);
+       GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG5);
+       GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG6);
+}
+
+/*
+ * Note that gpmc,wait-pin handing wrongly assumes bit 8 is available,
+ * see commit c9fb809.
+ */
+static void gpmc_cs_show_timings(int cs, const char *desc)
+{
+       gpmc_show_regs(cs, 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(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_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");
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 30, 30, "burst-read");
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 31, 31, "burst-wrap");
+
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG2,  7,  7, "cs-extra-delay");
+
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG3,  7,  7, "adv-extra-delay");
+
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4, 23, 23, "we-extra-delay");
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4,  7,  7, "oe-extra-delay");
+
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6,  7,  7, "cycle2cycle-samecsen");
+       GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6,  6,  6, "cycle2cycle-diffcsen");
+
+       pr_info("gpmc cs%i timings configuration:\n", cs);
+       GPMC_GET_TICKS(GPMC_CS_CONFIG2,  0,  3, "cs-on-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG2,  8, 12, "cs-rd-off-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG2, 16, 20, "cs-wr-off-ns");
+
+       GPMC_GET_TICKS(GPMC_CS_CONFIG3,  0,  3, "adv-on-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG3,  8, 12, "adv-rd-off-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG3, 16, 20, "adv-wr-off-ns");
+
+       GPMC_GET_TICKS(GPMC_CS_CONFIG4,  0,  3, "oe-on-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG4,  8, 12, "oe-off-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG4, 16, 19, "we-on-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG4, 24, 28, "we-off-ns");
+
+       GPMC_GET_TICKS(GPMC_CS_CONFIG5,  0,  4, "rd-cycle-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG5,  8, 12, "wr-cycle-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG5, 16, 20, "access-ns");
+
+       GPMC_GET_TICKS(GPMC_CS_CONFIG5, 24, 27, "page-burst-access-ns");
+
+       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(GPMC_CS_CONFIG6, 16, 19, "wr-data-mux-bus-ns");
+       GPMC_GET_TICKS(GPMC_CS_CONFIG6, 24, 28, "wr-access-ns");
+}
+#else
+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)
+{
+       u32 l;
+       int ticks, mask, nr_bits;
+
+       if (time == 0)
+               ticks = 0;
+       else
+               ticks = gpmc_ns_to_ticks(time);
+       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);
+
+               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,
+                       (l >> st_bit) & mask, time);
+#endif
+       l &= ~(mask << st_bit);
+       l |= ticks << st_bit;
+       gpmc_cs_write_reg(cs, reg, l);
+
+       return 0;
+}
+
+#define GPMC_SET_ONE(reg, st, end, field) \
+       if (set_gpmc_timing_reg(cs, (reg), (st), (end),         \
+                       t->field, #field) < 0)                  \
+               return -1
+
+int gpmc_calc_divider(unsigned int sync_clk)
+{
+       int div;
+       u32 l;
+
+       l = sync_clk + (gpmc_get_fclk_period() - 1);
+       div = l / gpmc_get_fclk_period();
+       if (div > 4)
+               return -1;
+       if (div <= 0)
+               div = 1;
+
+       return div;
+}
+
+int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
+{
+       int div;
+       u32 l;
+
+       gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings");
+       div = gpmc_calc_divider(t->sync_clk);
+       if (div < 0)
+               return div;
+
+       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);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG3,  0,  3, adv_on);
+       GPMC_SET_ONE(GPMC_CS_CONFIG3,  8, 12, adv_rd_off);
+       GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG4,  0,  3, oe_on);
+       GPMC_SET_ONE(GPMC_CS_CONFIG4,  8, 12, oe_off);
+       GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on);
+       GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG5,  0,  4, rd_cycle);
+       GPMC_SET_ONE(GPMC_CS_CONFIG5,  8, 12, wr_cycle);
+       GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access);
+
+       GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
+
+       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)) {
+#ifdef DEBUG
+               printk(KERN_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");
+
+       return 0;
+}
+
+static int gpmc_cs_set_memconf(int cs, u32 base, u32 size)
+{
+       u32 l;
+       u32 mask;
+
+       /*
+        * Ensure that base address is aligned on a
+        * boundary equal to or greater than size.
+        */
+       if (base & (size - 1))
+               return -EINVAL;
+
+       mask = (1 << GPMC_SECTION_SHIFT) - size;
+       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_CSVALID;
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+
+       return 0;
+}
+
+static void gpmc_cs_enable_mem(int cs)
+{
+       u32 l;
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       l |= GPMC_CONFIG7_CSVALID;
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_disable_mem(int cs)
+{
+       u32 l;
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       l &= ~GPMC_CONFIG7_CSVALID;
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+{
+       u32 l;
+       u32 mask;
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       *base = (l & 0x3f) << GPMC_CHUNK_SHIFT;
+       mask = (l >> 8) & 0x0f;
+       *size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT);
+}
+
+static int gpmc_cs_mem_enabled(int cs)
+{
+       u32 l;
+
+       l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+       return l & GPMC_CONFIG7_CSVALID;
+}
+
+static void gpmc_cs_set_reserved(int cs, int reserved)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+       gpmc->flags |= GPMC_CS_RESERVED;
+}
+
+static bool gpmc_cs_reserved(int cs)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+       return gpmc->flags & GPMC_CS_RESERVED;
+}
+
+static void gpmc_cs_set_name(int cs, const char *name)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+       gpmc->name = name;
+}
+
+const char *gpmc_cs_get_name(int cs)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+       return gpmc->name;
+}
+
+static unsigned long gpmc_mem_align(unsigned long size)
+{
+       int order;
+
+       size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1);
+       order = GPMC_CHUNK_SHIFT - 1;
+       do {
+               size >>= 1;
+               order++;
+       } while (size);
+       size = 1 << order;
+       return size;
+}
+
+static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+       struct resource *res = &gpmc->mem;
+       int r;
+
+       size = gpmc_mem_align(size);
+       spin_lock(&gpmc_mem_lock);
+       res->start = base;
+       res->end = base + size - 1;
+       r = request_resource(&gpmc_mem_root, res);
+       spin_unlock(&gpmc_mem_lock);
+
+       return r;
+}
+
+static int gpmc_cs_delete_mem(int cs)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+       struct resource *res = &gpmc->mem;
+       int r;
+
+       spin_lock(&gpmc_mem_lock);
+       r = release_resource(res);
+       res->start = 0;
+       res->end = 0;
+       spin_unlock(&gpmc_mem_lock);
+
+       return r;
+}
+
+/**
+ * gpmc_cs_remap - remaps a chip-select physical base address
+ * @cs:                chip-select to remap
+ * @base:      physical base address to re-map chip-select to
+ *
+ * Re-maps a chip-select to a new physical base address specified by
+ * "base". Returns 0 on success and appropriate negative error code
+ * on failure.
+ */
+static int gpmc_cs_remap(int cs, u32 base)
+{
+       int ret;
+       u32 old_base, size;
+
+       if (cs > gpmc_cs_num) {
+               pr_err("%s: requested chip-select is disabled\n", __func__);
+               return -ENODEV;
+       }
+
+       /*
+        * Make sure we ignore any device offsets from the GPMC partition
+        * allocated for the chip select and that the new base confirms
+        * to the GPMC 16MB minimum granularity.
+        */ 
+       base &= ~(SZ_16M - 1);
+
+       gpmc_cs_get_memconf(cs, &old_base, &size);
+       if (base == old_base)
+               return 0;
+
+       ret = gpmc_cs_delete_mem(cs);
+       if (ret < 0)
+               return ret;
+
+       ret = gpmc_cs_insert_mem(cs, base, size);
+       if (ret < 0)
+               return ret;
+
+       ret = gpmc_cs_set_memconf(cs, base, size);
+
+       return ret;
+}
+
+int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+       struct resource *res = &gpmc->mem;
+       int r = -1;
+
+       if (cs > gpmc_cs_num) {
+               pr_err("%s: requested chip-select is disabled\n", __func__);
+               return -ENODEV;
+       }
+       size = gpmc_mem_align(size);
+       if (size > (1 << GPMC_SECTION_SHIFT))
+               return -ENOMEM;
+
+       spin_lock(&gpmc_mem_lock);
+       if (gpmc_cs_reserved(cs)) {
+               r = -EBUSY;
+               goto out;
+       }
+       if (gpmc_cs_mem_enabled(cs))
+               r = adjust_resource(res, res->start & ~(size - 1), size);
+       if (r < 0)
+               r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+                                     size, NULL, NULL);
+       if (r < 0)
+               goto out;
+
+       /* Disable CS while changing base address and size mask */
+       gpmc_cs_disable_mem(cs);
+
+       r = gpmc_cs_set_memconf(cs, res->start, resource_size(res));
+       if (r < 0) {
+               release_resource(res);
+               goto out;
+       }
+
+       /* Enable CS */
+       gpmc_cs_enable_mem(cs);
+       *base = res->start;
+       gpmc_cs_set_reserved(cs, 1);
+out:
+       spin_unlock(&gpmc_mem_lock);
+       return r;
+}
+EXPORT_SYMBOL(gpmc_cs_request);
+
+void gpmc_cs_free(int cs)
+{
+       struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+       struct resource *res = &gpmc->mem;
+
+       spin_lock(&gpmc_mem_lock);
+       if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
+               printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
+               BUG();
+               spin_unlock(&gpmc_mem_lock);
+               return;
+       }
+       gpmc_cs_disable_mem(cs);
+       if (res->flags)
+               release_resource(res);
+       gpmc_cs_set_reserved(cs, 0);
+       spin_unlock(&gpmc_mem_lock);
+}
+EXPORT_SYMBOL(gpmc_cs_free);
+
+/**
+ * gpmc_configure - write request to configure gpmc
+ * @cmd: command type
+ * @wval: value to write
+ * @return status of the operation
+ */
+int gpmc_configure(int cmd, int wval)
+{
+       u32 regval;
+
+       switch (cmd) {
+       case GPMC_ENABLE_IRQ:
+               gpmc_write_reg(GPMC_IRQENABLE, wval);
+               break;
+
+       case GPMC_SET_IRQ_STATUS:
+               gpmc_write_reg(GPMC_IRQSTATUS, wval);
+               break;
+
+       case GPMC_CONFIG_WP:
+               regval = gpmc_read_reg(GPMC_CONFIG);
+               if (wval)
+                       regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
+               else
+                       regval |= GPMC_CONFIG_WRITEPROTECT;  /* WP is OFF */
+               gpmc_write_reg(GPMC_CONFIG, regval);
+               break;
+
+       default:
+               pr_err("%s: command not supported\n", __func__);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(gpmc_configure);
+
+void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
+{
+       int i;
+
+       reg->gpmc_status = gpmc_base + GPMC_STATUS;
+       reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
+                               GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
+       reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET +
+                               GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
+       reg->gpmc_nand_data = gpmc_base + GPMC_CS0_OFFSET +
+                               GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
+       reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1;
+       reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2;
+       reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL;
+       reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS;
+       reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG;
+       reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
+       reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
+       reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
+
+       for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) {
+               reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 +
+                                          GPMC_BCH_SIZE * i;
+               reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 +
+                                          GPMC_BCH_SIZE * i;
+               reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 +
+                                          GPMC_BCH_SIZE * i;
+               reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
+                                          GPMC_BCH_SIZE * i;
+               reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
+                                          i * GPMC_BCH_SIZE;
+               reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
+                                          i * GPMC_BCH_SIZE;
+               reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
+                                          i * GPMC_BCH_SIZE;
+       }
+}
+
+int gpmc_get_client_irq(unsigned irq_config)
+{
+       int i;
+
+       if (hweight32(irq_config) > 1)
+               return 0;
+
+       for (i = 0; i < GPMC_NR_IRQ; i++)
+               if (gpmc_client_irq[i].bitmask & irq_config)
+                       return gpmc_client_irq[i].irq;
+
+       return 0;
+}
+
+static int gpmc_irq_endis(unsigned irq, bool endis)
+{
+       int i;
+       u32 regval;
+
+       for (i = 0; i < GPMC_NR_IRQ; i++)
+               if (irq == gpmc_client_irq[i].irq) {
+                       regval = gpmc_read_reg(GPMC_IRQENABLE);
+                       if (endis)
+                               regval |= gpmc_client_irq[i].bitmask;
+                       else
+                               regval &= ~gpmc_client_irq[i].bitmask;
+                       gpmc_write_reg(GPMC_IRQENABLE, regval);
+                       break;
+               }
+
+       return 0;
+}
+
+static void gpmc_irq_disable(struct irq_data *p)
+{
+       gpmc_irq_endis(p->irq, false);
+}
+
+static void gpmc_irq_enable(struct irq_data *p)
+{
+       gpmc_irq_endis(p->irq, true);
+}
+
+static void gpmc_irq_noop(struct irq_data *data) { }
+
+static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
+
+static int gpmc_setup_irq(void)
+{
+       int i;
+       u32 regval;
+
+       if (!gpmc_irq)
+               return -EINVAL;
+
+       gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
+       if (gpmc_irq_start < 0) {
+               pr_err("irq_alloc_descs failed\n");
+               return gpmc_irq_start;
+       }
+
+       gpmc_irq_chip.name = "gpmc";
+       gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret;
+       gpmc_irq_chip.irq_enable = gpmc_irq_enable;
+       gpmc_irq_chip.irq_disable = gpmc_irq_disable;
+       gpmc_irq_chip.irq_shutdown = gpmc_irq_noop;
+       gpmc_irq_chip.irq_ack = gpmc_irq_noop;
+       gpmc_irq_chip.irq_mask = gpmc_irq_noop;
+       gpmc_irq_chip.irq_unmask = gpmc_irq_noop;
+
+       gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE;
+       gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT;
+
+       for (i = 0; i < GPMC_NR_IRQ; i++) {
+               gpmc_client_irq[i].irq = gpmc_irq_start + i;
+               irq_set_chip_and_handler(gpmc_client_irq[i].irq,
+                                       &gpmc_irq_chip, handle_simple_irq);
+               set_irq_flags(gpmc_client_irq[i].irq,
+                               IRQF_VALID | IRQF_NOAUTOEN);
+       }
+
+       /* Disable interrupts */
+       gpmc_write_reg(GPMC_IRQENABLE, 0);
+
+       /* clear interrupts */
+       regval = gpmc_read_reg(GPMC_IRQSTATUS);
+       gpmc_write_reg(GPMC_IRQSTATUS, regval);
+
+       return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL);
+}
+
+static int gpmc_free_irq(void)
+{
+       int i;
+
+       if (gpmc_irq)
+               free_irq(gpmc_irq, NULL);
+
+       for (i = 0; i < GPMC_NR_IRQ; i++) {
+               irq_set_handler(gpmc_client_irq[i].irq, NULL);
+               irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip);
+               irq_modify_status(gpmc_client_irq[i].irq, 0, 0);
+       }
+
+       irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ);
+
+       return 0;
+}
+
+static void gpmc_mem_exit(void)
+{
+       int cs;
+
+       for (cs = 0; cs < gpmc_cs_num; cs++) {
+               if (!gpmc_cs_mem_enabled(cs))
+                       continue;
+               gpmc_cs_delete_mem(cs);
+       }
+
+}
+
+static void gpmc_mem_init(void)
+{
+       int cs;
+
+       /*
+        * The first 1MB of GPMC address space is typically mapped to
+        * the internal ROM. Never allocate the first page, to
+        * facilitate bug detection; even if we didn't boot from ROM.
+        */
+       gpmc_mem_root.start = SZ_1M;
+       gpmc_mem_root.end = GPMC_MEM_END;
+
+       /* Reserve all regions that has been set up by bootloader */
+       for (cs = 0; cs < gpmc_cs_num; cs++) {
+               u32 base, size;
+
+               if (!gpmc_cs_mem_enabled(cs))
+                       continue;
+               gpmc_cs_get_memconf(cs, &base, &size);
+               if (gpmc_cs_insert_mem(cs, base, size)) {
+                       pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n",
+                               __func__, cs, base, base + size);
+                       gpmc_cs_disable_mem(cs);
+               }
+       }
+}
+
+static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
+{
+       u32 temp;
+       int div;
+
+       div = gpmc_calc_divider(sync_clk);
+       temp = gpmc_ps_to_ticks(time_ps);
+       temp = (temp + div - 1) / div;
+       return gpmc_ticks_to_ps(temp * div);
+}
+
+/* XXX: can the cycles be avoided ? */
+static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
+                                      struct gpmc_device_timings *dev_t,
+                                      bool mux)
+{
+       u32 temp;
+
+       /* adv_rd_off */
+       temp = dev_t->t_avdp_r;
+       /* XXX: mux check required ? */
+       if (mux) {
+               /* XXX: t_avdp not to be required for sync, only added for tusb
+                * this indirectly necessitates requirement of t_avdp_r and
+                * t_avdp_w instead of having a single t_avdp
+                */
+               temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_avdh);
+               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+       }
+       gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
+
+       /* oe_on */
+       temp = dev_t->t_oeasu; /* XXX: remove this ? */
+       if (mux) {
+               temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_ach);
+               temp = max_t(u32, temp, gpmc_t->adv_rd_off +
+                               gpmc_ticks_to_ps(dev_t->cyc_aavdh_oe));
+       }
+       gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
+
+       /* access */
+       /* XXX: any scope for improvement ?, by combining oe_on
+        * and clk_activation, need to check whether
+        * access = clk_activation + round to sync clk ?
+        */
+       temp = max_t(u32, dev_t->t_iaa, dev_t->cyc_iaa * gpmc_t->sync_clk);
+       temp += gpmc_t->clk_activation;
+       if (dev_t->cyc_oe)
+               temp = max_t(u32, temp, gpmc_t->oe_on +
+                               gpmc_ticks_to_ps(dev_t->cyc_oe));
+       gpmc_t->access = gpmc_round_ps_to_ticks(temp);
+
+       gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
+       gpmc_t->cs_rd_off = gpmc_t->oe_off;
+
+       /* rd_cycle */
+       temp = max_t(u32, dev_t->t_cez_r, dev_t->t_oez);
+       temp = gpmc_round_ps_to_sync_clk(temp, gpmc_t->sync_clk) +
+                                                       gpmc_t->access;
+       /* XXX: barter t_ce_rdyz with t_cez_r ? */
+       if (dev_t->t_ce_rdyz)
+               temp = max_t(u32, temp, gpmc_t->cs_rd_off + dev_t->t_ce_rdyz);
+       gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
+
+       return 0;
+}
+
+static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
+                                       struct gpmc_device_timings *dev_t,
+                                       bool mux)
+{
+       u32 temp;
+
+       /* adv_wr_off */
+       temp = dev_t->t_avdp_w;
+       if (mux) {
+               temp = max_t(u32, temp,
+                       gpmc_t->clk_activation + dev_t->t_avdh);
+               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+       }
+       gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
+
+       /* wr_data_mux_bus */
+       temp = max_t(u32, dev_t->t_weasu,
+                       gpmc_t->clk_activation + dev_t->t_rdyo);
+       /* XXX: shouldn't mux be kept as a whole for wr_data_mux_bus ?,
+        * and in that case remember to handle we_on properly
+        */
+       if (mux) {
+               temp = max_t(u32, temp,
+                       gpmc_t->adv_wr_off + dev_t->t_aavdh);
+               temp = max_t(u32, temp, gpmc_t->adv_wr_off +
+                               gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
+       }
+       gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
+
+       /* we_on */
+       if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
+               gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
+       else
+               gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
+
+       /* wr_access */
+       /* XXX: gpmc_capability check reqd ? , even if not, will not harm */
+       gpmc_t->wr_access = gpmc_t->access;
+
+       /* we_off */
+       temp = gpmc_t->we_on + dev_t->t_wpl;
+       temp = max_t(u32, temp,
+                       gpmc_t->wr_access + gpmc_ticks_to_ps(1));
+       temp = max_t(u32, temp,
+               gpmc_t->we_on + gpmc_ticks_to_ps(dev_t->cyc_wpl));
+       gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
+
+       gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
+                                                       dev_t->t_wph);
+
+       /* wr_cycle */
+       temp = gpmc_round_ps_to_sync_clk(dev_t->t_cez_w, gpmc_t->sync_clk);
+       temp += gpmc_t->wr_access;
+       /* XXX: barter t_ce_rdyz with t_cez_w ? */
+       if (dev_t->t_ce_rdyz)
+               temp = max_t(u32, temp,
+                                gpmc_t->cs_wr_off + dev_t->t_ce_rdyz);
+       gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
+
+       return 0;
+}
+
+static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
+                                       struct gpmc_device_timings *dev_t,
+                                       bool mux)
+{
+       u32 temp;
+
+       /* adv_rd_off */
+       temp = dev_t->t_avdp_r;
+       if (mux)
+               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+       gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
+
+       /* oe_on */
+       temp = dev_t->t_oeasu;
+       if (mux)
+               temp = max_t(u32, temp,
+                       gpmc_t->adv_rd_off + dev_t->t_aavdh);
+       gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
+
+       /* access */
+       temp = max_t(u32, dev_t->t_iaa, /* XXX: remove t_iaa in async ? */
+                               gpmc_t->oe_on + dev_t->t_oe);
+       temp = max_t(u32, temp,
+                               gpmc_t->cs_on + dev_t->t_ce);
+       temp = max_t(u32, temp,
+                               gpmc_t->adv_on + dev_t->t_aa);
+       gpmc_t->access = gpmc_round_ps_to_ticks(temp);
+
+       gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
+       gpmc_t->cs_rd_off = gpmc_t->oe_off;
+
+       /* rd_cycle */
+       temp = max_t(u32, dev_t->t_rd_cycle,
+                       gpmc_t->cs_rd_off + dev_t->t_cez_r);
+       temp = max_t(u32, temp, gpmc_t->oe_off + dev_t->t_oez);
+       gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
+
+       return 0;
+}
+
+static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
+                                        struct gpmc_device_timings *dev_t,
+                                        bool mux)
+{
+       u32 temp;
+
+       /* adv_wr_off */
+       temp = dev_t->t_avdp_w;
+       if (mux)
+               temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
+       gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
+
+       /* wr_data_mux_bus */
+       temp = dev_t->t_weasu;
+       if (mux) {
+               temp = max_t(u32, temp, gpmc_t->adv_wr_off + dev_t->t_aavdh);
+               temp = max_t(u32, temp, gpmc_t->adv_wr_off +
+                               gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
+       }
+       gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
+
+       /* we_on */
+       if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
+               gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
+       else
+               gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
+
+       /* we_off */
+       temp = gpmc_t->we_on + dev_t->t_wpl;
+       gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
+
+       gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
+                                                       dev_t->t_wph);
+
+       /* wr_cycle */
+       temp = max_t(u32, dev_t->t_wr_cycle,
+                               gpmc_t->cs_wr_off + dev_t->t_cez_w);
+       gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
+
+       return 0;
+}
+
+static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
+                       struct gpmc_device_timings *dev_t)
+{
+       u32 temp;
+
+       gpmc_t->sync_clk = gpmc_calc_divider(dev_t->clk) *
+                                               gpmc_get_fclk_period();
+
+       gpmc_t->page_burst_access = gpmc_round_ps_to_sync_clk(
+                                       dev_t->t_bacc,
+                                       gpmc_t->sync_clk);
+
+       temp = max_t(u32, dev_t->t_ces, dev_t->t_avds);
+       gpmc_t->clk_activation = gpmc_round_ps_to_ticks(temp);
+
+       if (gpmc_calc_divider(gpmc_t->sync_clk) != 1)
+               return 0;
+
+       if (dev_t->ce_xdelay)
+               gpmc_t->bool_timings.cs_extra_delay = true;
+       if (dev_t->avd_xdelay)
+               gpmc_t->bool_timings.adv_extra_delay = true;
+       if (dev_t->oe_xdelay)
+               gpmc_t->bool_timings.oe_extra_delay = true;
+       if (dev_t->we_xdelay)
+               gpmc_t->bool_timings.we_extra_delay = true;
+
+       return 0;
+}
+
+static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
+                                   struct gpmc_device_timings *dev_t,
+                                   bool sync)
+{
+       u32 temp;
+
+       /* cs_on */
+       gpmc_t->cs_on = gpmc_round_ps_to_ticks(dev_t->t_ceasu);
+
+       /* adv_on */
+       temp = dev_t->t_avdasu;
+       if (dev_t->t_ce_avd)
+               temp = max_t(u32, temp,
+                               gpmc_t->cs_on + dev_t->t_ce_avd);
+       gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
+
+       if (sync)
+               gpmc_calc_sync_common_timings(gpmc_t, dev_t);
+
+       return 0;
+}
+
+/* TODO: remove this function once all peripherals are confirmed to
+ * work with generic timing. Simultaneously gpmc_cs_set_timings()
+ * has to be modified to handle timings in ps instead of ns
+*/
+static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
+{
+       t->cs_on /= 1000;
+       t->cs_rd_off /= 1000;
+       t->cs_wr_off /= 1000;
+       t->adv_on /= 1000;
+       t->adv_rd_off /= 1000;
+       t->adv_wr_off /= 1000;
+       t->we_on /= 1000;
+       t->we_off /= 1000;
+       t->oe_on /= 1000;
+       t->oe_off /= 1000;
+       t->page_burst_access /= 1000;
+       t->access /= 1000;
+       t->rd_cycle /= 1000;
+       t->wr_cycle /= 1000;
+       t->bus_turnaround /= 1000;
+       t->cycle2cycle_delay /= 1000;
+       t->wait_monitoring /= 1000;
+       t->clk_activation /= 1000;
+       t->wr_access /= 1000;
+       t->wr_data_mux_bus /= 1000;
+}
+
+int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+                     struct gpmc_settings *gpmc_s,
+                     struct gpmc_device_timings *dev_t)
+{
+       bool mux = false, sync = false;
+
+       if (gpmc_s) {
+               mux = gpmc_s->mux_add_data ? true : false;
+               sync = (gpmc_s->sync_read || gpmc_s->sync_write);
+       }
+
+       memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+       gpmc_calc_common_timings(gpmc_t, dev_t, sync);
+
+       if (gpmc_s && gpmc_s->sync_read)
+               gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux);
+       else
+               gpmc_calc_async_read_timings(gpmc_t, dev_t, mux);
+
+       if (gpmc_s && gpmc_s->sync_write)
+               gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux);
+       else
+               gpmc_calc_async_write_timings(gpmc_t, dev_t, mux);
+
+       /* TODO: remove, see function definition */
+       gpmc_convert_ps_to_ns(gpmc_t);
+
+       return 0;
+}
+
+/**
+ * gpmc_cs_program_settings - programs non-timing related settings
+ * @cs:                GPMC chip-select to program
+ * @p:         pointer to GPMC settings structure
+ *
+ * Programs non-timing related settings for a GPMC chip-select, such as
+ * bus-width, burst configuration, etc. Function should be called once
+ * for each chip-select that is being used and must be called before
+ * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
+ * register will be initialised to zero by this function. Returns 0 on
+ * success and appropriate negative error code on failure.
+ */
+int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
+{
+       u32 config1;
+
+       if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) {
+               pr_err("%s: invalid width %d!", __func__, p->device_width);
+               return -EINVAL;
+       }
+
+       /* Address-data multiplexing not supported for NAND devices */
+       if (p->device_nand && p->mux_add_data) {
+               pr_err("%s: invalid configuration!\n", __func__);
+               return -EINVAL;
+       }
+
+       if ((p->mux_add_data > GPMC_MUX_AD) ||
+           ((p->mux_add_data == GPMC_MUX_AAD) &&
+            !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
+               pr_err("%s: invalid multiplex configuration!\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+       if (p->burst_read || p->burst_write) {
+               switch (p->burst_len) {
+               case GPMC_BURST_4:
+               case GPMC_BURST_8:
+               case GPMC_BURST_16:
+                       break;
+               default:
+                       pr_err("%s: invalid page/burst-length (%d)\n",
+                              __func__, p->burst_len);
+                       return -EINVAL;
+               }
+       }
+
+       if (p->wait_pin > gpmc_nr_waitpins) {
+               pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+               return -EINVAL;
+       }
+
+       config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+       if (p->sync_read)
+               config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+       if (p->sync_write)
+               config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+       if (p->wait_on_read)
+               config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+       if (p->wait_on_write)
+               config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+       if (p->wait_on_read || p->wait_on_write)
+               config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+       if (p->device_nand)
+               config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+       if (p->mux_add_data)
+               config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+       if (p->burst_read)
+               config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+       if (p->burst_write)
+               config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+       if (p->burst_read || p->burst_write) {
+               config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+               config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+       }
+
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id gpmc_dt_ids[] = {
+       { .compatible = "ti,omap2420-gpmc" },
+       { .compatible = "ti,omap2430-gpmc" },
+       { .compatible = "ti,omap3430-gpmc" },   /* omap3430 & omap3630 */
+       { .compatible = "ti,omap4430-gpmc" },   /* omap4430 & omap4460 & omap543x */
+       { .compatible = "ti,am3352-gpmc" },     /* am335x devices */
+       { }
+};
+MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
+
+/**
+ * gpmc_read_settings_dt - read gpmc settings from device-tree
+ * @np:                pointer to device-tree node for a gpmc child device
+ * @p:         pointer to gpmc settings structure
+ *
+ * Reads the GPMC settings for a GPMC child device from device-tree and
+ * stores them in the GPMC settings structure passed. The GPMC settings
+ * structure is initialised to zero by this function and so any
+ * previously stored settings will be cleared.
+ */
+void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
+{
+       memset(p, 0, sizeof(struct gpmc_settings));
+
+       p->sync_read = of_property_read_bool(np, "gpmc,sync-read");
+       p->sync_write = of_property_read_bool(np, "gpmc,sync-write");
+       of_property_read_u32(np, "gpmc,device-width", &p->device_width);
+       of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
+
+       if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
+               p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap");
+               p->burst_read = of_property_read_bool(np, "gpmc,burst-read");
+               p->burst_write = of_property_read_bool(np, "gpmc,burst-write");
+               if (!p->burst_read && !p->burst_write)
+                       pr_warn("%s: page/burst-length set but not used!\n",
+                               __func__);
+       }
+
+       if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
+               p->wait_on_read = of_property_read_bool(np,
+                                                       "gpmc,wait-on-read");
+               p->wait_on_write = of_property_read_bool(np,
+                                                        "gpmc,wait-on-write");
+               if (!p->wait_on_read && !p->wait_on_write)
+                       pr_debug("%s: rd/wr wait monitoring not enabled!\n",
+                                __func__);
+       }
+}
+
+static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
+                                               struct gpmc_timings *gpmc_t)
+{
+       struct gpmc_bool_timings *p;
+
+       if (!np || !gpmc_t)
+               return;
+
+       memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+       /* minimum clock period for syncronous mode */
+       of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk);
+
+       /* chip select timtings */
+       of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on);
+       of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off);
+       of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off);
+
+       /* ADV signal timings */
+       of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on);
+       of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off);
+       of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off);
+
+       /* WE signal timings */
+       of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on);
+       of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off);
+
+       /* OE signal timings */
+       of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on);
+       of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off);
+
+       /* access and cycle timings */
+       of_property_read_u32(np, "gpmc,page-burst-access-ns",
+                            &gpmc_t->page_burst_access);
+       of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access);
+       of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle);
+       of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle);
+       of_property_read_u32(np, "gpmc,bus-turnaround-ns",
+                            &gpmc_t->bus_turnaround);
+       of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns",
+                            &gpmc_t->cycle2cycle_delay);
+       of_property_read_u32(np, "gpmc,wait-monitoring-ns",
+                            &gpmc_t->wait_monitoring);
+       of_property_read_u32(np, "gpmc,clk-activation-ns",
+                            &gpmc_t->clk_activation);
+
+       /* only applicable to OMAP3+ */
+       of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access);
+       of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns",
+                            &gpmc_t->wr_data_mux_bus);
+
+       /* bool timing parameters */
+       p = &gpmc_t->bool_timings;
+
+       p->cycle2cyclediffcsen =
+               of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen");
+       p->cycle2cyclesamecsen =
+               of_property_read_bool(np, "gpmc,cycle2cycle-samecsen");
+       p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay");
+       p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay");
+       p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay");
+       p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay");
+       p->time_para_granularity =
+               of_property_read_bool(np, "gpmc,time-para-granularity");
+}
+
+#if IS_ENABLED(CONFIG_MTD_NAND)
+
+static const char * const nand_xfer_types[] = {
+       [NAND_OMAP_PREFETCH_POLLED]             = "prefetch-polled",
+       [NAND_OMAP_POLLED]                      = "polled",
+       [NAND_OMAP_PREFETCH_DMA]                = "prefetch-dma",
+       [NAND_OMAP_PREFETCH_IRQ]                = "prefetch-irq",
+};
+
+static int gpmc_probe_nand_child(struct platform_device *pdev,
+                                struct device_node *child)
+{
+       u32 val;
+       const char *s;
+       struct gpmc_timings gpmc_t;
+       struct omap_nand_platform_data *gpmc_nand_data;
+
+       if (of_property_read_u32(child, "reg", &val) < 0) {
+               dev_err(&pdev->dev, "%s has no 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+
+       gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
+                                     GFP_KERNEL);
+       if (!gpmc_nand_data)
+               return -ENOMEM;
+
+       gpmc_nand_data->cs = val;
+       gpmc_nand_data->of_node = child;
+
+       /* Detect availability of ELM module */
+       gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
+       if (gpmc_nand_data->elm_of_node == NULL)
+               gpmc_nand_data->elm_of_node =
+                                       of_parse_phandle(child, "elm_id", 0);
+
+       /* select ecc-scheme for NAND */
+       if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
+               pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
+               return -ENODEV;
+       }
+
+       if (!strcmp(s, "sw"))
+               gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
+       else if (!strcmp(s, "ham1") ||
+                !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
+               gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_HAM1_CODE_HW;
+       else if (!strcmp(s, "bch4"))
+               if (gpmc_nand_data->elm_of_node)
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH4_CODE_HW;
+               else
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
+       else if (!strcmp(s, "bch8"))
+               if (gpmc_nand_data->elm_of_node)
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH8_CODE_HW;
+               else
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+       else if (!strcmp(s, "bch16"))
+               if (gpmc_nand_data->elm_of_node)
+                       gpmc_nand_data->ecc_opt =
+                               OMAP_ECC_BCH16_CODE_HW;
+               else
+                       pr_err("%s: BCH16 requires ELM support\n", __func__);
+       else
+               pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
+
+       /* select data transfer mode for NAND controller */
+       if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
+               for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
+                       if (!strcasecmp(s, nand_xfer_types[val])) {
+                               gpmc_nand_data->xfer_type = val;
+                               break;
+                       }
+
+       gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child);
+
+       val = of_get_nand_bus_width(child);
+       if (val == 16)
+               gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
+
+       gpmc_read_timings_dt(child, &gpmc_t);
+       gpmc_nand_init(gpmc_nand_data, &gpmc_t);
+
+       return 0;
+}
+#else
+static int gpmc_probe_nand_child(struct platform_device *pdev,
+                                struct device_node *child)
+{
+       return 0;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_MTD_ONENAND)
+static int gpmc_probe_onenand_child(struct platform_device *pdev,
+                                struct device_node *child)
+{
+       u32 val;
+       struct omap_onenand_platform_data *gpmc_onenand_data;
+
+       if (of_property_read_u32(child, "reg", &val) < 0) {
+               dev_err(&pdev->dev, "%s has no 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+
+       gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data),
+                                        GFP_KERNEL);
+       if (!gpmc_onenand_data)
+               return -ENOMEM;
+
+       gpmc_onenand_data->cs = val;
+       gpmc_onenand_data->of_node = child;
+       gpmc_onenand_data->dma_channel = -1;
+
+       if (!of_property_read_u32(child, "dma-channel", &val))
+               gpmc_onenand_data->dma_channel = val;
+
+       gpmc_onenand_init(gpmc_onenand_data);
+
+       return 0;
+}
+#else
+static int gpmc_probe_onenand_child(struct platform_device *pdev,
+                                   struct device_node *child)
+{
+       return 0;
+}
+#endif
+
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev:      pointer to gpmc platform device
+ * @child:     pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_child(struct platform_device *pdev,
+                               struct device_node *child)
+{
+       struct gpmc_settings gpmc_s;
+       struct gpmc_timings gpmc_t;
+       struct resource res;
+       unsigned long base;
+       const char *name;
+       int ret, cs;
+       u32 val;
+
+       if (of_property_read_u32(child, "reg", &cs) < 0) {
+               dev_err(&pdev->dev, "%s has no 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+
+       if (of_address_to_resource(child, 0, &res) < 0) {
+               dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+
+       /*
+        * Check if we have multiple instances of the same device
+        * on a single chip select. If so, use the already initialized
+        * timings.
+        */
+       name = gpmc_cs_get_name(cs);
+       if (name && child->name && of_node_cmp(child->name, name) == 0)
+                       goto no_timings;
+
+       ret = gpmc_cs_request(cs, resource_size(&res), &base);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
+               return ret;
+       }
+       gpmc_cs_set_name(cs, child->name);
+
+       gpmc_read_settings_dt(child, &gpmc_s);
+       gpmc_read_timings_dt(child, &gpmc_t);
+
+       /*
+        * For some GPMC devices we still need to rely on the bootloader
+        * timings because the devices can be connected via FPGA.
+        * REVISIT: Add timing support from slls644g.pdf.
+        */
+       if (!gpmc_t.cs_rd_off) {
+               WARN(1, "enable GPMC debug to configure .dts timings for CS%i\n",
+                       cs);
+               gpmc_cs_show_timings(cs,
+                                    "please add GPMC bootloader timings to .dts");
+               goto no_timings;
+       }
+
+       /* CS must be disabled while making changes to gpmc configuration */
+       gpmc_cs_disable_mem(cs);
+
+       /*
+        * FIXME: gpmc_cs_request() will map the CS to an arbitary
+        * location in the gpmc address space. When booting with
+        * device-tree we want the NOR flash to be mapped to the
+        * location specified in the device-tree blob. So remap the
+        * CS to this location. Once DT migration is complete should
+        * just make gpmc_cs_request() map a specific address.
+        */
+       ret = gpmc_cs_remap(cs, res.start);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n",
+                       cs, &res.start);
+               goto err;
+       }
+
+       ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+       if (ret < 0)
+               goto err;
+
+       ret = gpmc_cs_program_settings(cs, &gpmc_s);
+       if (ret < 0)
+               goto err;
+
+       ret = gpmc_cs_set_timings(cs, &gpmc_t);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n",
+                       child->name);
+               goto err;
+       }
+
+       /* Clear limited address i.e. enable A26-A11 */
+       val = gpmc_read_reg(GPMC_CONFIG);
+       val &= ~GPMC_CONFIG_LIMITEDADDRESS;
+       gpmc_write_reg(GPMC_CONFIG, val);
+
+       /* Enable CS region */
+       gpmc_cs_enable_mem(cs);
+
+no_timings:
+       if (of_platform_device_create(child, NULL, &pdev->dev))
+               return 0;
+
+       dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
+       ret = -ENODEV;
+
+err:
+       gpmc_cs_free(cs);
+
+       return ret;
+}
+
+static int gpmc_probe_dt(struct platform_device *pdev)
+{
+       int ret;
+       struct device_node *child;
+       const struct of_device_id *of_id =
+               of_match_device(gpmc_dt_ids, &pdev->dev);
+
+       if (!of_id)
+               return 0;
+
+       ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-cs",
+                                  &gpmc_cs_num);
+       if (ret < 0) {
+               pr_err("%s: number of chip-selects not defined\n", __func__);
+               return ret;
+       } else if (gpmc_cs_num < 1) {
+               pr_err("%s: all chip-selects are disabled\n", __func__);
+               return -EINVAL;
+       } else if (gpmc_cs_num > GPMC_CS_NUM) {
+               pr_err("%s: number of supported chip-selects cannot be > %d\n",
+                                        __func__, GPMC_CS_NUM);
+               return -EINVAL;
+       }
+
+       ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
+                                  &gpmc_nr_waitpins);
+       if (ret < 0) {
+               pr_err("%s: number of wait pins not found!\n", __func__);
+               return ret;
+       }
+
+       for_each_available_child_of_node(pdev->dev.of_node, child) {
+
+               if (!child->name)
+                       continue;
+
+               if (of_node_cmp(child->name, "nand") == 0)
+                       ret = gpmc_probe_nand_child(pdev, child);
+               else if (of_node_cmp(child->name, "onenand") == 0)
+                       ret = gpmc_probe_onenand_child(pdev, child);
+               else if (of_node_cmp(child->name, "ethernet") == 0 ||
+                        of_node_cmp(child->name, "nor") == 0 ||
+                        of_node_cmp(child->name, "uart") == 0)
+                       ret = gpmc_probe_generic_child(pdev, child);
+
+               if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
+                        __func__, child->full_name))
+                       of_node_put(child);
+       }
+
+       return 0;
+}
+#else
+static int gpmc_probe_dt(struct platform_device *pdev)
+{
+       return 0;
+}
+#endif
+
+static int gpmc_probe(struct platform_device *pdev)
+{
+       int rc;
+       u32 l;
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL)
+               return -ENOENT;
+
+       phys_base = res->start;
+       mem_size = resource_size(res);
+
+       gpmc_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(gpmc_base))
+               return PTR_ERR(gpmc_base);
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL)
+               dev_warn(&pdev->dev, "Failed to get resource: irq\n");
+       else
+               gpmc_irq = res->start;
+
+       gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck");
+       if (IS_ERR(gpmc_l3_clk)) {
+               dev_err(&pdev->dev, "Failed to get GPMC fck\n");
+               gpmc_irq = 0;
+               return PTR_ERR(gpmc_l3_clk);
+       }
+
+       if (!clk_get_rate(gpmc_l3_clk)) {
+               dev_err(&pdev->dev, "Invalid GPMC fck clock rate\n");
+               return -EINVAL;
+       }
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+
+       gpmc_dev = &pdev->dev;
+
+       l = gpmc_read_reg(GPMC_REVISION);
+
+       /*
+        * FIXME: Once device-tree migration is complete the below flags
+        * should be populated based upon the device-tree compatible
+        * string. For now just use the IP revision. OMAP3+ devices have
+        * the wr_access and wr_data_mux_bus register fields. OMAP4+
+        * devices support the addr-addr-data multiplex protocol.
+        *
+        * GPMC IP revisions:
+        * - OMAP24xx                   = 2.0
+        * - OMAP3xxx                   = 5.0
+        * - OMAP44xx/54xx/AM335x       = 6.0
+        */
+       if (GPMC_REVISION_MAJOR(l) > 0x4)
+               gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
+       if (GPMC_REVISION_MAJOR(l) > 0x5)
+               gpmc_capability |= GPMC_HAS_MUX_AAD;
+       dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
+                GPMC_REVISION_MINOR(l));
+
+       gpmc_mem_init();
+
+       if (gpmc_setup_irq() < 0)
+               dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
+
+       if (!pdev->dev.of_node) {
+               gpmc_cs_num      = GPMC_CS_NUM;
+               gpmc_nr_waitpins = GPMC_NR_WAITPINS;
+       }
+
+       rc = gpmc_probe_dt(pdev);
+       if (rc < 0) {
+               pm_runtime_put_sync(&pdev->dev);
+               dev_err(gpmc_dev, "failed to probe DT parameters\n");
+               return rc;
+       }
+
+       return 0;
+}
+
+static int gpmc_remove(struct platform_device *pdev)
+{
+       gpmc_free_irq();
+       gpmc_mem_exit();
+       pm_runtime_put_sync(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       gpmc_dev = NULL;
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int gpmc_suspend(struct device *dev)
+{
+       omap3_gpmc_save_context();
+       pm_runtime_put_sync(dev);
+       return 0;
+}
+
+static int gpmc_resume(struct device *dev)
+{
+       pm_runtime_get_sync(dev);
+       omap3_gpmc_restore_context();
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(gpmc_pm_ops, gpmc_suspend, gpmc_resume);
+
+static struct platform_driver gpmc_driver = {
+       .probe          = gpmc_probe,
+       .remove         = gpmc_remove,
+       .driver         = {
+               .name   = DEVICE_NAME,
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(gpmc_dt_ids),
+               .pm     = &gpmc_pm_ops,
+       },
+};
+
+static __init int gpmc_init(void)
+{
+       return platform_driver_register(&gpmc_driver);
+}
+
+static __exit void gpmc_exit(void)
+{
+       platform_driver_unregister(&gpmc_driver);
+
+}
+
+postcore_initcall(gpmc_init);
+module_exit(gpmc_exit);
+
+static irqreturn_t gpmc_handle_irq(int irq, void *dev)
+{
+       int i;
+       u32 regval;
+
+       regval = gpmc_read_reg(GPMC_IRQSTATUS);
+
+       if (!regval)
+               return IRQ_NONE;
+
+       for (i = 0; i < GPMC_NR_IRQ; i++)
+               if (regval & gpmc_client_irq[i].bitmask)
+                       generic_handle_irq(gpmc_client_irq[i].irq);
+
+       gpmc_write_reg(GPMC_IRQSTATUS, regval);
+
+       return IRQ_HANDLED;
+}
+
+static struct omap3_gpmc_regs gpmc_context;
+
+void omap3_gpmc_save_context(void)
+{
+       int i;
+
+       gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
+       gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE);
+       gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
+       gpmc_context.config = gpmc_read_reg(GPMC_CONFIG);
+       gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
+       gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
+       gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
+       for (i = 0; i < gpmc_cs_num; i++) {
+               gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
+               if (gpmc_context.cs_context[i].is_valid) {
+                       gpmc_context.cs_context[i].config1 =
+                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG1);
+                       gpmc_context.cs_context[i].config2 =
+                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG2);
+                       gpmc_context.cs_context[i].config3 =
+                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG3);
+                       gpmc_context.cs_context[i].config4 =
+                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG4);
+                       gpmc_context.cs_context[i].config5 =
+                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG5);
+                       gpmc_context.cs_context[i].config6 =
+                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG6);
+                       gpmc_context.cs_context[i].config7 =
+                               gpmc_cs_read_reg(i, GPMC_CS_CONFIG7);
+               }
+       }
+}
+
+void omap3_gpmc_restore_context(void)
+{
+       int i;
+
+       gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig);
+       gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable);
+       gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl);
+       gpmc_write_reg(GPMC_CONFIG, gpmc_context.config);
+       gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
+       gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
+       gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
+       for (i = 0; i < gpmc_cs_num; i++) {
+               if (gpmc_context.cs_context[i].is_valid) {
+                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
+                               gpmc_context.cs_context[i].config1);
+                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG2,
+                               gpmc_context.cs_context[i].config2);
+                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG3,
+                               gpmc_context.cs_context[i].config3);
+                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG4,
+                               gpmc_context.cs_context[i].config4);
+                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG5,
+                               gpmc_context.cs_context[i].config5);
+                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG6,
+                               gpmc_context.cs_context[i].config6);
+                       gpmc_cs_write_reg(i, GPMC_CS_CONFIG7,
+                               gpmc_context.cs_context[i].config7);
+               }
+       }
+}
diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
new file mode 100644 (file)
index 0000000..5710876
--- /dev/null
@@ -0,0 +1,7 @@
+config TEGRA_MC
+       bool "NVIDIA Tegra Memory Controller support"
+       default y
+       depends on ARCH_TEGRA
+       help
+         This driver supports the Memory Controller (MC) hardware found on
+         NVIDIA Tegra SoCs.
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
new file mode 100644 (file)
index 0000000..0d9f497
--- /dev/null
@@ -0,0 +1,7 @@
+tegra-mc-y := mc.o
+
+tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC)  += tegra30.o
+tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o
+tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
+
+obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
new file mode 100644 (file)
index 0000000..fe3c44e
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2014 NVIDIA CORPORATION.  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.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "mc.h"
+
+#define MC_INTSTATUS 0x000
+#define  MC_INT_DECERR_MTS (1 << 16)
+#define  MC_INT_SECERR_SEC (1 << 13)
+#define  MC_INT_DECERR_VPR (1 << 12)
+#define  MC_INT_INVALID_APB_ASID_UPDATE (1 << 11)
+#define  MC_INT_INVALID_SMMU_PAGE (1 << 10)
+#define  MC_INT_ARBITRATION_EMEM (1 << 9)
+#define  MC_INT_SECURITY_VIOLATION (1 << 8)
+#define  MC_INT_DECERR_EMEM (1 << 6)
+
+#define MC_INTMASK 0x004
+
+#define MC_ERR_STATUS 0x08
+#define  MC_ERR_STATUS_TYPE_SHIFT 28
+#define  MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE (6 << MC_ERR_STATUS_TYPE_SHIFT)
+#define  MC_ERR_STATUS_TYPE_MASK (0x7 << MC_ERR_STATUS_TYPE_SHIFT)
+#define  MC_ERR_STATUS_READABLE (1 << 27)
+#define  MC_ERR_STATUS_WRITABLE (1 << 26)
+#define  MC_ERR_STATUS_NONSECURE (1 << 25)
+#define  MC_ERR_STATUS_ADR_HI_SHIFT 20
+#define  MC_ERR_STATUS_ADR_HI_MASK 0x3
+#define  MC_ERR_STATUS_SECURITY (1 << 17)
+#define  MC_ERR_STATUS_RW (1 << 16)
+#define  MC_ERR_STATUS_CLIENT_MASK 0x7f
+
+#define MC_ERR_ADR 0x0c
+
+#define MC_EMEM_ARB_CFG 0x90
+#define  MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x)  (((x) & 0x1ff) << 0)
+#define  MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK        0x1ff
+#define MC_EMEM_ARB_MISC0 0xd8
+
+static const struct of_device_id tegra_mc_of_match[] = {
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+       { .compatible = "nvidia,tegra30-mc", .data = &tegra30_mc_soc },
+#endif
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+       { .compatible = "nvidia,tegra114-mc", .data = &tegra114_mc_soc },
+#endif
+#ifdef CONFIG_ARCH_TEGRA_124_SOC
+       { .compatible = "nvidia,tegra124-mc", .data = &tegra124_mc_soc },
+#endif
+       { }
+};
+MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
+
+static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
+{
+       unsigned long long tick;
+       unsigned int i;
+       u32 value;
+
+       /* compute the number of MC clock cycles per tick */
+       tick = mc->tick * clk_get_rate(mc->clk);
+       do_div(tick, NSEC_PER_SEC);
+
+       value = readl(mc->regs + MC_EMEM_ARB_CFG);
+       value &= ~MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK;
+       value |= MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(tick);
+       writel(value, mc->regs + MC_EMEM_ARB_CFG);
+
+       /* write latency allowance defaults */
+       for (i = 0; i < mc->soc->num_clients; i++) {
+               const struct tegra_mc_la *la = &mc->soc->clients[i].la;
+               u32 value;
+
+               value = readl(mc->regs + la->reg);
+               value &= ~(la->mask << la->shift);
+               value |= (la->def & la->mask) << la->shift;
+               writel(value, mc->regs + la->reg);
+       }
+
+       return 0;
+}
+
+static const char *const status_names[32] = {
+       [ 1] = "External interrupt",
+       [ 6] = "EMEM address decode error",
+       [ 8] = "Security violation",
+       [ 9] = "EMEM arbitration error",
+       [10] = "Page fault",
+       [11] = "Invalid APB ASID update",
+       [12] = "VPR violation",
+       [13] = "Secure carveout violation",
+       [16] = "MTS carveout violation",
+};
+
+static const char *const error_names[8] = {
+       [2] = "EMEM decode error",
+       [3] = "TrustZone violation",
+       [4] = "Carveout violation",
+       [6] = "SMMU translation error",
+};
+
+static irqreturn_t tegra_mc_irq(int irq, void *data)
+{
+       struct tegra_mc *mc = data;
+       unsigned long status, mask;
+       unsigned int bit;
+
+       /* mask all interrupts to avoid flooding */
+       status = mc_readl(mc, MC_INTSTATUS);
+       mask = mc_readl(mc, MC_INTMASK);
+
+       for_each_set_bit(bit, &status, 32) {
+               const char *error = status_names[bit] ?: "unknown";
+               const char *client = "unknown", *desc;
+               const char *direction, *secure;
+               phys_addr_t addr = 0;
+               unsigned int i;
+               char perm[7];
+               u8 id, type;
+               u32 value;
+
+               value = mc_readl(mc, MC_ERR_STATUS);
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+               if (mc->soc->num_address_bits > 32) {
+                       addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) &
+                               MC_ERR_STATUS_ADR_HI_MASK);
+                       addr <<= 32;
+               }
+#endif
+
+               if (value & MC_ERR_STATUS_RW)
+                       direction = "write";
+               else
+                       direction = "read";
+
+               if (value & MC_ERR_STATUS_SECURITY)
+                       secure = "secure ";
+               else
+                       secure = "";
+
+               id = value & MC_ERR_STATUS_CLIENT_MASK;
+
+               for (i = 0; i < mc->soc->num_clients; i++) {
+                       if (mc->soc->clients[i].id == id) {
+                               client = mc->soc->clients[i].name;
+                               break;
+                       }
+               }
+
+               type = (value & MC_ERR_STATUS_TYPE_MASK) >>
+                      MC_ERR_STATUS_TYPE_SHIFT;
+               desc = error_names[type];
+
+               switch (value & MC_ERR_STATUS_TYPE_MASK) {
+               case MC_ERR_STATUS_TYPE_INVALID_SMMU_PAGE:
+                       perm[0] = ' ';
+                       perm[1] = '[';
+
+                       if (value & MC_ERR_STATUS_READABLE)
+                               perm[2] = 'R';
+                       else
+                               perm[2] = '-';
+
+                       if (value & MC_ERR_STATUS_WRITABLE)
+                               perm[3] = 'W';
+                       else
+                               perm[3] = '-';
+
+                       if (value & MC_ERR_STATUS_NONSECURE)
+                               perm[4] = '-';
+                       else
+                               perm[4] = 'S';
+
+                       perm[5] = ']';
+                       perm[6] = '\0';
+                       break;
+
+               default:
+                       perm[0] = '\0';
+                       break;
+               }
+
+               value = mc_readl(mc, MC_ERR_ADR);
+               addr |= value;
+
+               dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s%s)\n",
+                                   client, secure, direction, &addr, error,
+                                   desc, perm);
+       }
+
+       /* clear interrupts */
+       mc_writel(mc, status, MC_INTSTATUS);
+
+       return IRQ_HANDLED;
+}
+
+static int tegra_mc_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       struct resource *res;
+       struct tegra_mc *mc;
+       u32 value;
+       int err;
+
+       match = of_match_node(tegra_mc_of_match, pdev->dev.of_node);
+       if (!match)
+               return -ENODEV;
+
+       mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
+       if (!mc)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mc);
+       mc->soc = match->data;
+       mc->dev = &pdev->dev;
+
+       /* length of MC tick in nanoseconds */
+       mc->tick = 30;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       mc->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mc->regs))
+               return PTR_ERR(mc->regs);
+
+       mc->clk = devm_clk_get(&pdev->dev, "mc");
+       if (IS_ERR(mc->clk)) {
+               dev_err(&pdev->dev, "failed to get MC clock: %ld\n",
+                       PTR_ERR(mc->clk));
+               return PTR_ERR(mc->clk);
+       }
+
+       err = tegra_mc_setup_latency_allowance(mc);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to setup latency allowance: %d\n",
+                       err);
+               return err;
+       }
+
+       if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
+               mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
+               if (IS_ERR(mc->smmu)) {
+                       dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
+                               PTR_ERR(mc->smmu));
+                       return PTR_ERR(mc->smmu);
+               }
+       }
+
+       mc->irq = platform_get_irq(pdev, 0);
+       if (mc->irq < 0) {
+               dev_err(&pdev->dev, "interrupt not specified\n");
+               return mc->irq;
+       }
+
+       err = devm_request_irq(&pdev->dev, mc->irq, tegra_mc_irq, IRQF_SHARED,
+                              dev_name(&pdev->dev), mc);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq,
+                       err);
+               return err;
+       }
+
+       value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+               MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
+               MC_INT_ARBITRATION_EMEM | MC_INT_SECURITY_VIOLATION |
+               MC_INT_DECERR_EMEM;
+       mc_writel(mc, value, MC_INTMASK);
+
+       return 0;
+}
+
+static struct platform_driver tegra_mc_driver = {
+       .driver = {
+               .name = "tegra-mc",
+               .of_match_table = tegra_mc_of_match,
+               .suppress_bind_attrs = true,
+       },
+       .prevent_deferred_probe = true,
+       .probe = tegra_mc_probe,
+};
+
+static int tegra_mc_init(void)
+{
+       return platform_driver_register(&tegra_mc_driver);
+}
+arch_initcall(tegra_mc_init);
+
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra Memory Controller driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
new file mode 100644 (file)
index 0000000..d5d2114
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 NVIDIA CORPORATION.  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 MEMORY_TEGRA_MC_H
+#define MEMORY_TEGRA_MC_H
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+#include <soc/tegra/mc.h>
+
+static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset)
+{
+       return readl(mc->regs + offset);
+}
+
+static inline void mc_writel(struct tegra_mc *mc, u32 value,
+                            unsigned long offset)
+{
+       writel(value, mc->regs + offset);
+}
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+extern const struct tegra_mc_soc tegra30_mc_soc;
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+extern const struct tegra_mc_soc tegra114_mc_soc;
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_124_SOC
+extern const struct tegra_mc_soc tegra124_mc_soc;
+#endif
+
+#endif /* MEMORY_TEGRA_MC_H */
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
new file mode 100644 (file)
index 0000000..511e9a2
--- /dev/null
@@ -0,0 +1,948 @@
+/*
+ * Copyright (C) 2014 NVIDIA CORPORATION.  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.
+ */
+
+#include <linux/of.h>
+#include <linux/mm.h>
+
+#include <asm/cacheflush.h>
+
+#include <dt-bindings/memory/tegra114-mc.h>
+
+#include "mc.h"
+
+static const struct tegra_mc_client tegra114_mc_clients[] = {
+       {
+               .id = 0x00,
+               .name = "ptcr",
+               .swgroup = TEGRA_SWGROUP_PTC,
+       }, {
+               .id = 0x01,
+               .name = "display0a",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x2e8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x02,
+               .name = "display0ab",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 2,
+               },
+               .la = {
+                       .reg = 0x2f4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x03,
+               .name = "display0b",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 3,
+               },
+               .la = {
+                       .reg = 0x2e8,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x04,
+               .name = "display0bb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x2f4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x05,
+               .name = "display0c",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 5,
+               },
+               .la = {
+                       .reg = 0x2ec,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x06,
+               .name = "display0cb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 6,
+               },
+               .la = {
+                       .reg = 0x2f8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x09,
+               .name = "eppup",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 9,
+               },
+               .la = {
+                       .reg = 0x300,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x33,
+               },
+       }, {
+               .id = 0x0a,
+               .name = "g2pr",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 10,
+               },
+               .la = {
+                       .reg = 0x308,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x09,
+               },
+       }, {
+               .id = 0x0b,
+               .name = "g2sr",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 11,
+               },
+               .la = {
+                       .reg = 0x308,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x09,
+               },
+       }, {
+               .id = 0x0f,
+               .name = "avpcarm7r",
+               .swgroup = TEGRA_SWGROUP_AVPC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 15,
+               },
+               .la = {
+                       .reg = 0x2e4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x10,
+               .name = "displayhc",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 16,
+               },
+               .la = {
+                       .reg = 0x2f0,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x68,
+               },
+       }, {
+               .id = 0x11,
+               .name = "displayhcb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 17,
+               },
+               .la = {
+                       .reg = 0x2fc,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x68,
+               },
+       }, {
+               .id = 0x12,
+               .name = "fdcdrd",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 18,
+               },
+               .la = {
+                       .reg = 0x334,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0c,
+               },
+       }, {
+               .id = 0x13,
+               .name = "fdcdrd2",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 19,
+               },
+               .la = {
+                       .reg = 0x33c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0c,
+               },
+       }, {
+               .id = 0x14,
+               .name = "g2dr",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 20,
+               },
+               .la = {
+                       .reg = 0x30c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0a,
+               },
+       }, {
+               .id = 0x15,
+               .name = "hdar",
+               .swgroup = TEGRA_SWGROUP_HDA,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x318,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x16,
+               .name = "host1xdmar",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 22,
+               },
+               .la = {
+                       .reg = 0x310,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x17,
+               .name = "host1xr",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 23,
+               },
+               .la = {
+                       .reg = 0x310,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xa5,
+               },
+       }, {
+               .id = 0x18,
+               .name = "idxsrd",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 24,
+               },
+               .la = {
+                       .reg = 0x334,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0b,
+               },
+       }, {
+               .id = 0x1c,
+               .name = "msencsrd",
+               .swgroup = TEGRA_SWGROUP_MSENC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 28,
+               },
+               .la = {
+                       .reg = 0x328,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x1d,
+               .name = "ppcsahbdmar",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 29,
+               },
+               .la = {
+                       .reg = 0x344,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x1e,
+               .name = "ppcsahbslvr",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 30,
+               },
+               .la = {
+                       .reg = 0x344,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xe8,
+               },
+       }, {
+               .id = 0x20,
+               .name = "texl2srd",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 0,
+               },
+               .la = {
+                       .reg = 0x338,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0c,
+               },
+       }, {
+               .id = 0x22,
+               .name = "vdebsevr",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 2,
+               },
+               .la = {
+                       .reg = 0x354,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x23,
+               .name = "vdember",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 3,
+               },
+               .la = {
+                       .reg = 0x354,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x24,
+               .name = "vdemcer",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x358,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xb8,
+               },
+       }, {
+               .id = 0x25,
+               .name = "vdetper",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 5,
+               },
+               .la = {
+                       .reg = 0x358,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xee,
+               },
+       }, {
+               .id = 0x26,
+               .name = "mpcorelpr",
+               .swgroup = TEGRA_SWGROUP_MPCORELP,
+               .la = {
+                       .reg = 0x324,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x27,
+               .name = "mpcorer",
+               .swgroup = TEGRA_SWGROUP_MPCORE,
+               .la = {
+                       .reg = 0x320,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x28,
+               .name = "eppu",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 8,
+               },
+               .la = {
+                       .reg = 0x300,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x33,
+               },
+       }, {
+               .id = 0x29,
+               .name = "eppv",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 9,
+               },
+               .la = {
+                       .reg = 0x304,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x6c,
+               },
+       }, {
+               .id = 0x2a,
+               .name = "eppy",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 10,
+               },
+               .la = {
+                       .reg = 0x304,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x6c,
+               },
+       }, {
+               .id = 0x2b,
+               .name = "msencswr",
+               .swgroup = TEGRA_SWGROUP_MSENC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 11,
+               },
+               .la = {
+                       .reg = 0x328,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x2c,
+               .name = "viwsb",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 12,
+               },
+               .la = {
+                       .reg = 0x364,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x47,
+               },
+       }, {
+               .id = 0x2d,
+               .name = "viwu",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 13,
+               },
+               .la = {
+                       .reg = 0x368,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x2e,
+               .name = "viwv",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 14,
+               },
+               .la = {
+                       .reg = 0x368,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x2f,
+               .name = "viwy",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 15,
+               },
+               .la = {
+                       .reg = 0x36c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x47,
+               },
+       }, {
+               .id = 0x30,
+               .name = "g2dw",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 16,
+               },
+               .la = {
+                       .reg = 0x30c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x9,
+               },
+       }, {
+               .id = 0x32,
+               .name = "avpcarm7w",
+               .swgroup = TEGRA_SWGROUP_AVPC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 18,
+               },
+               .la = {
+                       .reg = 0x2e4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0e,
+               },
+       }, {
+               .id = 0x33,
+               .name = "fdcdwr",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 19,
+               },
+               .la = {
+                       .reg = 0x338,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x34,
+               .name = "fdcwr2",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 20,
+               },
+               .la = {
+                       .reg = 0x340,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x35,
+               .name = "hdaw",
+               .swgroup = TEGRA_SWGROUP_HDA,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x318,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x36,
+               .name = "host1xw",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 22,
+               },
+               .la = {
+                       .reg = 0x314,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x25,
+               },
+       }, {
+               .id = 0x37,
+               .name = "ispw",
+               .swgroup = TEGRA_SWGROUP_ISP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 23,
+               },
+               .la = {
+                       .reg = 0x31c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x38,
+               .name = "mpcorelpw",
+               .swgroup = TEGRA_SWGROUP_MPCORELP,
+               .la = {
+                       .reg = 0x324,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x39,
+               .name = "mpcorew",
+               .swgroup = TEGRA_SWGROUP_MPCORE,
+               .la = {
+                       .reg = 0x320,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0e,
+               },
+       }, {
+               .id = 0x3b,
+               .name = "ppcsahbdmaw",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 27,
+               },
+               .la = {
+                       .reg = 0x348,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xa5,
+               },
+       }, {
+               .id = 0x3c,
+               .name = "ppcsahbslvw",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 28,
+               },
+               .la = {
+                       .reg = 0x348,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xe8,
+               },
+       }, {
+               .id = 0x3e,
+               .name = "vdebsevw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 30,
+               },
+               .la = {
+                       .reg = 0x35c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x3f,
+               .name = "vdedbgw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 31,
+               },
+               .la = {
+                       .reg = 0x35c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x40,
+               .name = "vdembew",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 0,
+               },
+               .la = {
+                       .reg = 0x360,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x89,
+               },
+       }, {
+               .id = 0x41,
+               .name = "vdetpmw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x360,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x59,
+               },
+       }, {
+               .id = 0x4a,
+               .name = "xusb_hostr",
+               .swgroup = TEGRA_SWGROUP_XUSB_HOST,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 10,
+               },
+               .la = {
+                       .reg = 0x37c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xa5,
+               },
+       }, {
+               .id = 0x4b,
+               .name = "xusb_hostw",
+               .swgroup = TEGRA_SWGROUP_XUSB_HOST,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 11,
+               },
+               .la = {
+                       .reg = 0x37c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xa5,
+               },
+       }, {
+               .id = 0x4c,
+               .name = "xusb_devr",
+               .swgroup = TEGRA_SWGROUP_XUSB_DEV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 12,
+               },
+               .la = {
+                       .reg = 0x380,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xa5,
+               },
+       }, {
+               .id = 0x4d,
+               .name = "xusb_devw",
+               .swgroup = TEGRA_SWGROUP_XUSB_DEV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 13,
+               },
+               .la = {
+                       .reg = 0x380,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xa5,
+               },
+       }, {
+               .id = 0x4e,
+               .name = "fdcdwr3",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 14,
+               },
+               .la = {
+                       .reg = 0x388,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x4f,
+               .name = "fdcdrd3",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 15,
+               },
+               .la = {
+                       .reg = 0x384,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0c,
+               },
+       }, {
+               .id = 0x50,
+               .name = "fdcwr4",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 16,
+               },
+               .la = {
+                       .reg = 0x388,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x51,
+               .name = "fdcrd4",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 17,
+               },
+               .la = {
+                       .reg = 0x384,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0c,
+               },
+       }, {
+               .id = 0x52,
+               .name = "emucifr",
+               .swgroup = TEGRA_SWGROUP_EMUCIF,
+               .la = {
+                       .reg = 0x38c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x53,
+               .name = "emucifw",
+               .swgroup = TEGRA_SWGROUP_EMUCIF,
+               .la = {
+                       .reg = 0x38c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0e,
+               },
+       }, {
+               .id = 0x54,
+               .name = "tsecsrd",
+               .swgroup = TEGRA_SWGROUP_TSEC,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 20,
+               },
+               .la = {
+                       .reg = 0x390,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x55,
+               .name = "tsecswr",
+               .swgroup = TEGRA_SWGROUP_TSEC,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x390,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       },
+};
+
+static const struct tegra_smmu_swgroup tegra114_swgroups[] = {
+       { .swgroup = TEGRA_SWGROUP_DC,        .reg = 0x240 },
+       { .swgroup = TEGRA_SWGROUP_DCB,       .reg = 0x244 },
+       { .swgroup = TEGRA_SWGROUP_EPP,       .reg = 0x248 },
+       { .swgroup = TEGRA_SWGROUP_G2,        .reg = 0x24c },
+       { .swgroup = TEGRA_SWGROUP_AVPC,      .reg = 0x23c },
+       { .swgroup = TEGRA_SWGROUP_NV,        .reg = 0x268 },
+       { .swgroup = TEGRA_SWGROUP_HDA,       .reg = 0x254 },
+       { .swgroup = TEGRA_SWGROUP_HC,        .reg = 0x250 },
+       { .swgroup = TEGRA_SWGROUP_MSENC,     .reg = 0x264 },
+       { .swgroup = TEGRA_SWGROUP_PPCS,      .reg = 0x270 },
+       { .swgroup = TEGRA_SWGROUP_VDE,       .reg = 0x27c },
+       { .swgroup = TEGRA_SWGROUP_VI,        .reg = 0x280 },
+       { .swgroup = TEGRA_SWGROUP_ISP,       .reg = 0x258 },
+       { .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 },
+       { .swgroup = TEGRA_SWGROUP_XUSB_DEV,  .reg = 0x28c },
+       { .swgroup = TEGRA_SWGROUP_TSEC,      .reg = 0x294 },
+};
+
+static void tegra114_flush_dcache(struct page *page, unsigned long offset,
+                                 size_t size)
+{
+       phys_addr_t phys = page_to_phys(page) + offset;
+       void *virt = page_address(page) + offset;
+
+       __cpuc_flush_dcache_area(virt, size);
+       outer_flush_range(phys, phys + size);
+}
+
+static const struct tegra_smmu_ops tegra114_smmu_ops = {
+       .flush_dcache = tegra114_flush_dcache,
+};
+
+static const struct tegra_smmu_soc tegra114_smmu_soc = {
+       .clients = tegra114_mc_clients,
+       .num_clients = ARRAY_SIZE(tegra114_mc_clients),
+       .swgroups = tegra114_swgroups,
+       .num_swgroups = ARRAY_SIZE(tegra114_swgroups),
+       .supports_round_robin_arbitration = false,
+       .supports_request_limit = false,
+       .num_asids = 4,
+       .ops = &tegra114_smmu_ops,
+};
+
+const struct tegra_mc_soc tegra114_mc_soc = {
+       .clients = tegra114_mc_clients,
+       .num_clients = ARRAY_SIZE(tegra114_mc_clients),
+       .num_address_bits = 32,
+       .atom_size = 32,
+       .smmu = &tegra114_smmu_soc,
+};
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
new file mode 100644 (file)
index 0000000..278d40b
--- /dev/null
@@ -0,0 +1,995 @@
+/*
+ * Copyright (C) 2014 NVIDIA CORPORATION.  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.
+ */
+
+#include <linux/of.h>
+#include <linux/mm.h>
+
+#include <asm/cacheflush.h>
+
+#include <dt-bindings/memory/tegra124-mc.h>
+
+#include "mc.h"
+
+static const struct tegra_mc_client tegra124_mc_clients[] = {
+       {
+               .id = 0x00,
+               .name = "ptcr",
+               .swgroup = TEGRA_SWGROUP_PTC,
+       }, {
+               .id = 0x01,
+               .name = "display0a",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x2e8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xc2,
+               },
+       }, {
+               .id = 0x02,
+               .name = "display0ab",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 2,
+               },
+               .la = {
+                       .reg = 0x2f4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xc6,
+               },
+       }, {
+               .id = 0x03,
+               .name = "display0b",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 3,
+               },
+               .la = {
+                       .reg = 0x2e8,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x04,
+               .name = "display0bb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x2f4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x05,
+               .name = "display0c",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 5,
+               },
+               .la = {
+                       .reg = 0x2ec,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x06,
+               .name = "display0cb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 6,
+               },
+               .la = {
+                       .reg = 0x2f8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x0e,
+               .name = "afir",
+               .swgroup = TEGRA_SWGROUP_AFI,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 14,
+               },
+               .la = {
+                       .reg = 0x2e0,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x13,
+               },
+       }, {
+               .id = 0x0f,
+               .name = "avpcarm7r",
+               .swgroup = TEGRA_SWGROUP_AVPC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 15,
+               },
+               .la = {
+                       .reg = 0x2e4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x10,
+               .name = "displayhc",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 16,
+               },
+               .la = {
+                       .reg = 0x2f0,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x11,
+               .name = "displayhcb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 17,
+               },
+               .la = {
+                       .reg = 0x2fc,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x15,
+               .name = "hdar",
+               .swgroup = TEGRA_SWGROUP_HDA,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x318,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x24,
+               },
+       }, {
+               .id = 0x16,
+               .name = "host1xdmar",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 22,
+               },
+               .la = {
+                       .reg = 0x310,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x1e,
+               },
+       }, {
+               .id = 0x17,
+               .name = "host1xr",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 23,
+               },
+               .la = {
+                       .reg = 0x310,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x1c,
+               .name = "msencsrd",
+               .swgroup = TEGRA_SWGROUP_MSENC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 28,
+               },
+               .la = {
+                       .reg = 0x328,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x23,
+               },
+       }, {
+               .id = 0x1d,
+               .name = "ppcsahbdmar",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 29,
+               },
+               .la = {
+                       .reg = 0x344,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x49,
+               },
+       }, {
+               .id = 0x1e,
+               .name = "ppcsahbslvr",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 30,
+               },
+               .la = {
+                       .reg = 0x344,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x1a,
+               },
+       }, {
+               .id = 0x1f,
+               .name = "satar",
+               .swgroup = TEGRA_SWGROUP_SATA,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 31,
+               },
+               .la = {
+                       .reg = 0x350,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x65,
+               },
+       }, {
+               .id = 0x22,
+               .name = "vdebsevr",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 2,
+               },
+               .la = {
+                       .reg = 0x354,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4f,
+               },
+       }, {
+               .id = 0x23,
+               .name = "vdember",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 3,
+               },
+               .la = {
+                       .reg = 0x354,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x3d,
+               },
+       }, {
+               .id = 0x24,
+               .name = "vdemcer",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x358,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x66,
+               },
+       }, {
+               .id = 0x25,
+               .name = "vdetper",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 5,
+               },
+               .la = {
+                       .reg = 0x358,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xa5,
+               },
+       }, {
+               .id = 0x26,
+               .name = "mpcorelpr",
+               .swgroup = TEGRA_SWGROUP_MPCORELP,
+               .la = {
+                       .reg = 0x324,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x27,
+               .name = "mpcorer",
+               .swgroup = TEGRA_SWGROUP_MPCORE,
+               .la = {
+                       .reg = 0x320,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x2b,
+               .name = "msencswr",
+               .swgroup = TEGRA_SWGROUP_MSENC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 11,
+               },
+               .la = {
+                       .reg = 0x328,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x31,
+               .name = "afiw",
+               .swgroup = TEGRA_SWGROUP_AFI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 17,
+               },
+               .la = {
+                       .reg = 0x2e0,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x32,
+               .name = "avpcarm7w",
+               .swgroup = TEGRA_SWGROUP_AVPC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 18,
+               },
+               .la = {
+                       .reg = 0x2e4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x35,
+               .name = "hdaw",
+               .swgroup = TEGRA_SWGROUP_HDA,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x318,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x36,
+               .name = "host1xw",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 22,
+               },
+               .la = {
+                       .reg = 0x314,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x38,
+               .name = "mpcorelpw",
+               .swgroup = TEGRA_SWGROUP_MPCORELP,
+               .la = {
+                       .reg = 0x324,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x39,
+               .name = "mpcorew",
+               .swgroup = TEGRA_SWGROUP_MPCORE,
+               .la = {
+                       .reg = 0x320,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x3b,
+               .name = "ppcsahbdmaw",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 27,
+               },
+               .la = {
+                       .reg = 0x348,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x3c,
+               .name = "ppcsahbslvw",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 28,
+               },
+               .la = {
+                       .reg = 0x348,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x3d,
+               .name = "sataw",
+               .swgroup = TEGRA_SWGROUP_SATA,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 29,
+               },
+               .la = {
+                       .reg = 0x350,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x65,
+               },
+       }, {
+               .id = 0x3e,
+               .name = "vdebsevw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 30,
+               },
+               .la = {
+                       .reg = 0x35c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x3f,
+               .name = "vdedbgw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 31,
+               },
+               .la = {
+                       .reg = 0x35c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x40,
+               .name = "vdembew",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 0,
+               },
+               .la = {
+                       .reg = 0x360,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x41,
+               .name = "vdetpmw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x360,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x44,
+               .name = "ispra",
+               .swgroup = TEGRA_SWGROUP_ISP2,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x370,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x18,
+               },
+       }, {
+               .id = 0x46,
+               .name = "ispwa",
+               .swgroup = TEGRA_SWGROUP_ISP2,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 6,
+               },
+               .la = {
+                       .reg = 0x374,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x47,
+               .name = "ispwb",
+               .swgroup = TEGRA_SWGROUP_ISP2,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 7,
+               },
+               .la = {
+                       .reg = 0x374,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x4a,
+               .name = "xusb_hostr",
+               .swgroup = TEGRA_SWGROUP_XUSB_HOST,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 10,
+               },
+               .la = {
+                       .reg = 0x37c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x39,
+               },
+       }, {
+               .id = 0x4b,
+               .name = "xusb_hostw",
+               .swgroup = TEGRA_SWGROUP_XUSB_HOST,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 11,
+               },
+               .la = {
+                       .reg = 0x37c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x4c,
+               .name = "xusb_devr",
+               .swgroup = TEGRA_SWGROUP_XUSB_DEV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 12,
+               },
+               .la = {
+                       .reg = 0x380,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x39,
+               },
+       }, {
+               .id = 0x4d,
+               .name = "xusb_devw",
+               .swgroup = TEGRA_SWGROUP_XUSB_DEV,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 13,
+               },
+               .la = {
+                       .reg = 0x380,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x4e,
+               .name = "isprab",
+               .swgroup = TEGRA_SWGROUP_ISP2B,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 14,
+               },
+               .la = {
+                       .reg = 0x384,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x18,
+               },
+       }, {
+               .id = 0x50,
+               .name = "ispwab",
+               .swgroup = TEGRA_SWGROUP_ISP2B,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 16,
+               },
+               .la = {
+                       .reg = 0x388,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x51,
+               .name = "ispwbb",
+               .swgroup = TEGRA_SWGROUP_ISP2B,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 17,
+               },
+               .la = {
+                       .reg = 0x388,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x54,
+               .name = "tsecsrd",
+               .swgroup = TEGRA_SWGROUP_TSEC,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 20,
+               },
+               .la = {
+                       .reg = 0x390,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x9b,
+               },
+       }, {
+               .id = 0x55,
+               .name = "tsecswr",
+               .swgroup = TEGRA_SWGROUP_TSEC,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x390,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x56,
+               .name = "a9avpscr",
+               .swgroup = TEGRA_SWGROUP_A9AVP,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 22,
+               },
+               .la = {
+                       .reg = 0x3a4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x57,
+               .name = "a9avpscw",
+               .swgroup = TEGRA_SWGROUP_A9AVP,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 23,
+               },
+               .la = {
+                       .reg = 0x3a4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x58,
+               .name = "gpusrd",
+               .swgroup = TEGRA_SWGROUP_GPU,
+               .smmu = {
+                       /* read-only */
+                       .reg = 0x230,
+                       .bit = 24,
+               },
+               .la = {
+                       .reg = 0x3c8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x1a,
+               },
+       }, {
+               .id = 0x59,
+               .name = "gpuswr",
+               .swgroup = TEGRA_SWGROUP_GPU,
+               .smmu = {
+                       /* read-only */
+                       .reg = 0x230,
+                       .bit = 25,
+               },
+               .la = {
+                       .reg = 0x3c8,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x5a,
+               .name = "displayt",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 26,
+               },
+               .la = {
+                       .reg = 0x2f0,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x60,
+               .name = "sdmmcra",
+               .swgroup = TEGRA_SWGROUP_SDMMC1A,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 0,
+               },
+               .la = {
+                       .reg = 0x3b8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x49,
+               },
+       }, {
+               .id = 0x61,
+               .name = "sdmmcraa",
+               .swgroup = TEGRA_SWGROUP_SDMMC2A,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x3bc,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x49,
+               },
+       }, {
+               .id = 0x62,
+               .name = "sdmmcr",
+               .swgroup = TEGRA_SWGROUP_SDMMC3A,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 2,
+               },
+               .la = {
+                       .reg = 0x3c0,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x49,
+               },
+       }, {
+               .id = 0x63,
+               .swgroup = TEGRA_SWGROUP_SDMMC4A,
+               .name = "sdmmcrab",
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 3,
+               },
+               .la = {
+                       .reg = 0x3c4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x49,
+               },
+       }, {
+               .id = 0x64,
+               .name = "sdmmcwa",
+               .swgroup = TEGRA_SWGROUP_SDMMC1A,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x3b8,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x65,
+               .name = "sdmmcwaa",
+               .swgroup = TEGRA_SWGROUP_SDMMC2A,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 5,
+               },
+               .la = {
+                       .reg = 0x3bc,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x66,
+               .name = "sdmmcw",
+               .swgroup = TEGRA_SWGROUP_SDMMC3A,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 6,
+               },
+               .la = {
+                       .reg = 0x3c0,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x67,
+               .name = "sdmmcwab",
+               .swgroup = TEGRA_SWGROUP_SDMMC4A,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 7,
+               },
+               .la = {
+                       .reg = 0x3c4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x6c,
+               .name = "vicsrd",
+               .swgroup = TEGRA_SWGROUP_VIC,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 12,
+               },
+               .la = {
+                       .reg = 0x394,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x1a,
+               },
+       }, {
+               .id = 0x6d,
+               .name = "vicswr",
+               .swgroup = TEGRA_SWGROUP_VIC,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 13,
+               },
+               .la = {
+                       .reg = 0x394,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x72,
+               .name = "viw",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 18,
+               },
+               .la = {
+                       .reg = 0x398,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x73,
+               .name = "displayd",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x234,
+                       .bit = 19,
+               },
+               .la = {
+                       .reg = 0x3c8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       },
+};
+
+static const struct tegra_smmu_swgroup tegra124_swgroups[] = {
+       { .swgroup = TEGRA_SWGROUP_DC,        .reg = 0x240 },
+       { .swgroup = TEGRA_SWGROUP_DCB,       .reg = 0x244 },
+       { .swgroup = TEGRA_SWGROUP_AFI,       .reg = 0x238 },
+       { .swgroup = TEGRA_SWGROUP_AVPC,      .reg = 0x23c },
+       { .swgroup = TEGRA_SWGROUP_HDA,       .reg = 0x254 },
+       { .swgroup = TEGRA_SWGROUP_HC,        .reg = 0x250 },
+       { .swgroup = TEGRA_SWGROUP_MSENC,     .reg = 0x264 },
+       { .swgroup = TEGRA_SWGROUP_PPCS,      .reg = 0x270 },
+       { .swgroup = TEGRA_SWGROUP_SATA,      .reg = 0x274 },
+       { .swgroup = TEGRA_SWGROUP_VDE,       .reg = 0x27c },
+       { .swgroup = TEGRA_SWGROUP_ISP2,      .reg = 0x258 },
+       { .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 },
+       { .swgroup = TEGRA_SWGROUP_XUSB_DEV,  .reg = 0x28c },
+       { .swgroup = TEGRA_SWGROUP_ISP2B,     .reg = 0xaa4 },
+       { .swgroup = TEGRA_SWGROUP_TSEC,      .reg = 0x294 },
+       { .swgroup = TEGRA_SWGROUP_A9AVP,     .reg = 0x290 },
+       { .swgroup = TEGRA_SWGROUP_GPU,       .reg = 0xaac },
+       { .swgroup = TEGRA_SWGROUP_SDMMC1A,   .reg = 0xa94 },
+       { .swgroup = TEGRA_SWGROUP_SDMMC2A,   .reg = 0xa98 },
+       { .swgroup = TEGRA_SWGROUP_SDMMC3A,   .reg = 0xa9c },
+       { .swgroup = TEGRA_SWGROUP_SDMMC4A,   .reg = 0xaa0 },
+       { .swgroup = TEGRA_SWGROUP_VIC,       .reg = 0x284 },
+       { .swgroup = TEGRA_SWGROUP_VI,        .reg = 0x280 },
+};
+
+#ifdef CONFIG_ARCH_TEGRA_124_SOC
+static void tegra124_flush_dcache(struct page *page, unsigned long offset,
+                                 size_t size)
+{
+       phys_addr_t phys = page_to_phys(page) + offset;
+       void *virt = page_address(page) + offset;
+
+       __cpuc_flush_dcache_area(virt, size);
+       outer_flush_range(phys, phys + size);
+}
+
+static const struct tegra_smmu_ops tegra124_smmu_ops = {
+       .flush_dcache = tegra124_flush_dcache,
+};
+
+static const struct tegra_smmu_soc tegra124_smmu_soc = {
+       .clients = tegra124_mc_clients,
+       .num_clients = ARRAY_SIZE(tegra124_mc_clients),
+       .swgroups = tegra124_swgroups,
+       .num_swgroups = ARRAY_SIZE(tegra124_swgroups),
+       .supports_round_robin_arbitration = true,
+       .supports_request_limit = true,
+       .num_asids = 128,
+       .ops = &tegra124_smmu_ops,
+};
+
+const struct tegra_mc_soc tegra124_mc_soc = {
+       .clients = tegra124_mc_clients,
+       .num_clients = ARRAY_SIZE(tegra124_mc_clients),
+       .num_address_bits = 34,
+       .atom_size = 32,
+       .smmu = &tegra124_smmu_soc,
+};
+#endif /* CONFIG_ARCH_TEGRA_124_SOC */
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
new file mode 100644 (file)
index 0000000..71fe937
--- /dev/null
@@ -0,0 +1,970 @@
+/*
+ * Copyright (C) 2014 NVIDIA CORPORATION.  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.
+ */
+
+#include <linux/of.h>
+#include <linux/mm.h>
+
+#include <asm/cacheflush.h>
+
+#include <dt-bindings/memory/tegra30-mc.h>
+
+#include "mc.h"
+
+static const struct tegra_mc_client tegra30_mc_clients[] = {
+       {
+               .id = 0x00,
+               .name = "ptcr",
+               .swgroup = TEGRA_SWGROUP_PTC,
+       }, {
+               .id = 0x01,
+               .name = "display0a",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x2e8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x02,
+               .name = "display0ab",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 2,
+               },
+               .la = {
+                       .reg = 0x2f4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x03,
+               .name = "display0b",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 3,
+               },
+               .la = {
+                       .reg = 0x2e8,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x04,
+               .name = "display0bb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x2f4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x05,
+               .name = "display0c",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 5,
+               },
+               .la = {
+                       .reg = 0x2ec,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x06,
+               .name = "display0cb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 6,
+               },
+               .la = {
+                       .reg = 0x2f8,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x07,
+               .name = "display1b",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 7,
+               },
+               .la = {
+                       .reg = 0x2ec,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x08,
+               .name = "display1bb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 8,
+               },
+               .la = {
+                       .reg = 0x2f8,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x4e,
+               },
+       }, {
+               .id = 0x09,
+               .name = "eppup",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 9,
+               },
+               .la = {
+                       .reg = 0x300,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x17,
+               },
+       }, {
+               .id = 0x0a,
+               .name = "g2pr",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 10,
+               },
+               .la = {
+                       .reg = 0x308,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x09,
+               },
+       }, {
+               .id = 0x0b,
+               .name = "g2sr",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 11,
+               },
+               .la = {
+                       .reg = 0x308,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x09,
+               },
+       }, {
+               .id = 0x0c,
+               .name = "mpeunifbr",
+               .swgroup = TEGRA_SWGROUP_MPE,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 12,
+               },
+               .la = {
+                       .reg = 0x328,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x0d,
+               .name = "viruv",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 13,
+               },
+               .la = {
+                       .reg = 0x364,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x2c,
+               },
+       }, {
+               .id = 0x0e,
+               .name = "afir",
+               .swgroup = TEGRA_SWGROUP_AFI,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 14,
+               },
+               .la = {
+                       .reg = 0x2e0,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x0f,
+               .name = "avpcarm7r",
+               .swgroup = TEGRA_SWGROUP_AVPC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 15,
+               },
+               .la = {
+                       .reg = 0x2e4,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x10,
+               .name = "displayhc",
+               .swgroup = TEGRA_SWGROUP_DC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 16,
+               },
+               .la = {
+                       .reg = 0x2f0,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x11,
+               .name = "displayhcb",
+               .swgroup = TEGRA_SWGROUP_DCB,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 17,
+               },
+               .la = {
+                       .reg = 0x2fc,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x12,
+               .name = "fdcdrd",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 18,
+               },
+               .la = {
+                       .reg = 0x334,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0a,
+               },
+       }, {
+               .id = 0x13,
+               .name = "fdcdrd2",
+               .swgroup = TEGRA_SWGROUP_NV2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 19,
+               },
+               .la = {
+                       .reg = 0x33c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0a,
+               },
+       }, {
+               .id = 0x14,
+               .name = "g2dr",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 20,
+               },
+               .la = {
+                       .reg = 0x30c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x0a,
+               },
+       }, {
+               .id = 0x15,
+               .name = "hdar",
+               .swgroup = TEGRA_SWGROUP_HDA,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x318,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x16,
+               .name = "host1xdmar",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 22,
+               },
+               .la = {
+                       .reg = 0x310,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x05,
+               },
+       }, {
+               .id = 0x17,
+               .name = "host1xr",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 23,
+               },
+               .la = {
+                       .reg = 0x310,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x50,
+               },
+       }, {
+               .id = 0x18,
+               .name = "idxsrd",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 24,
+               },
+               .la = {
+                       .reg = 0x334,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x13,
+               },
+       }, {
+               .id = 0x19,
+               .name = "idxsrd2",
+               .swgroup = TEGRA_SWGROUP_NV2,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 25,
+               },
+               .la = {
+                       .reg = 0x33c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x13,
+               },
+       }, {
+               .id = 0x1a,
+               .name = "mpe_ipred",
+               .swgroup = TEGRA_SWGROUP_MPE,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 26,
+               },
+               .la = {
+                       .reg = 0x328,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x80,
+               },
+       }, {
+               .id = 0x1b,
+               .name = "mpeamemrd",
+               .swgroup = TEGRA_SWGROUP_MPE,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 27,
+               },
+               .la = {
+                       .reg = 0x32c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x42,
+               },
+       }, {
+               .id = 0x1c,
+               .name = "mpecsrd",
+               .swgroup = TEGRA_SWGROUP_MPE,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 28,
+               },
+               .la = {
+                       .reg = 0x32c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x1d,
+               .name = "ppcsahbdmar",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 29,
+               },
+               .la = {
+                       .reg = 0x344,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x1e,
+               .name = "ppcsahbslvr",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 30,
+               },
+               .la = {
+                       .reg = 0x344,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x12,
+               },
+       }, {
+               .id = 0x1f,
+               .name = "satar",
+               .swgroup = TEGRA_SWGROUP_SATA,
+               .smmu = {
+                       .reg = 0x228,
+                       .bit = 31,
+               },
+               .la = {
+                       .reg = 0x350,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x33,
+               },
+       }, {
+               .id = 0x20,
+               .name = "texsrd",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 0,
+               },
+               .la = {
+                       .reg = 0x338,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x13,
+               },
+       }, {
+               .id = 0x21,
+               .name = "texsrd2",
+               .swgroup = TEGRA_SWGROUP_NV2,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x340,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x13,
+               },
+       }, {
+               .id = 0x22,
+               .name = "vdebsevr",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 2,
+               },
+               .la = {
+                       .reg = 0x354,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x23,
+               .name = "vdember",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 3,
+               },
+               .la = {
+                       .reg = 0x354,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xd0,
+               },
+       }, {
+               .id = 0x24,
+               .name = "vdemcer",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 4,
+               },
+               .la = {
+                       .reg = 0x358,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x2a,
+               },
+       }, {
+               .id = 0x25,
+               .name = "vdetper",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 5,
+               },
+               .la = {
+                       .reg = 0x358,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x74,
+               },
+       }, {
+               .id = 0x26,
+               .name = "mpcorelpr",
+               .swgroup = TEGRA_SWGROUP_MPCORELP,
+               .la = {
+                       .reg = 0x324,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x27,
+               .name = "mpcorer",
+               .swgroup = TEGRA_SWGROUP_MPCORE,
+               .la = {
+                       .reg = 0x320,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x04,
+               },
+       }, {
+               .id = 0x28,
+               .name = "eppu",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 8,
+               },
+               .la = {
+                       .reg = 0x300,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x6c,
+               },
+       }, {
+               .id = 0x29,
+               .name = "eppv",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 9,
+               },
+               .la = {
+                       .reg = 0x304,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x6c,
+               },
+       }, {
+               .id = 0x2a,
+               .name = "eppy",
+               .swgroup = TEGRA_SWGROUP_EPP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 10,
+               },
+               .la = {
+                       .reg = 0x304,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x6c,
+               },
+       }, {
+               .id = 0x2b,
+               .name = "mpeunifbw",
+               .swgroup = TEGRA_SWGROUP_MPE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 11,
+               },
+               .la = {
+                       .reg = 0x330,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x13,
+               },
+       }, {
+               .id = 0x2c,
+               .name = "viwsb",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 12,
+               },
+               .la = {
+                       .reg = 0x364,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x12,
+               },
+       }, {
+               .id = 0x2d,
+               .name = "viwu",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 13,
+               },
+               .la = {
+                       .reg = 0x368,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xb2,
+               },
+       }, {
+               .id = 0x2e,
+               .name = "viwv",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 14,
+               },
+               .la = {
+                       .reg = 0x368,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xb2,
+               },
+       }, {
+               .id = 0x2f,
+               .name = "viwy",
+               .swgroup = TEGRA_SWGROUP_VI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 15,
+               },
+               .la = {
+                       .reg = 0x36c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x12,
+               },
+       }, {
+               .id = 0x30,
+               .name = "g2dw",
+               .swgroup = TEGRA_SWGROUP_G2,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 16,
+               },
+               .la = {
+                       .reg = 0x30c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x9,
+               },
+       }, {
+               .id = 0x31,
+               .name = "afiw",
+               .swgroup = TEGRA_SWGROUP_AFI,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 17,
+               },
+               .la = {
+                       .reg = 0x2e0,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0c,
+               },
+       }, {
+               .id = 0x32,
+               .name = "avpcarm7w",
+               .swgroup = TEGRA_SWGROUP_AVPC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 18,
+               },
+               .la = {
+                       .reg = 0x2e4,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0e,
+               },
+       }, {
+               .id = 0x33,
+               .name = "fdcdwr",
+               .swgroup = TEGRA_SWGROUP_NV,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 19,
+               },
+               .la = {
+                       .reg = 0x338,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0a,
+               },
+       }, {
+               .id = 0x34,
+               .name = "fdcwr2",
+               .swgroup = TEGRA_SWGROUP_NV2,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 20,
+               },
+               .la = {
+                       .reg = 0x340,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0a,
+               },
+       }, {
+               .id = 0x35,
+               .name = "hdaw",
+               .swgroup = TEGRA_SWGROUP_HDA,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 21,
+               },
+               .la = {
+                       .reg = 0x318,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x36,
+               .name = "host1xw",
+               .swgroup = TEGRA_SWGROUP_HC,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 22,
+               },
+               .la = {
+                       .reg = 0x314,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x37,
+               .name = "ispw",
+               .swgroup = TEGRA_SWGROUP_ISP,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 23,
+               },
+               .la = {
+                       .reg = 0x31c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x38,
+               .name = "mpcorelpw",
+               .swgroup = TEGRA_SWGROUP_MPCORELP,
+               .la = {
+                       .reg = 0x324,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0e,
+               },
+       }, {
+               .id = 0x39,
+               .name = "mpcorew",
+               .swgroup = TEGRA_SWGROUP_MPCORE,
+               .la = {
+                       .reg = 0x320,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x0e,
+               },
+       }, {
+               .id = 0x3a,
+               .name = "mpecswr",
+               .swgroup = TEGRA_SWGROUP_MPE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 26,
+               },
+               .la = {
+                       .reg = 0x330,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x3b,
+               .name = "ppcsahbdmaw",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 27,
+               },
+               .la = {
+                       .reg = 0x348,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x10,
+               },
+       }, {
+               .id = 0x3c,
+               .name = "ppcsahbslvw",
+               .swgroup = TEGRA_SWGROUP_PPCS,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 28,
+               },
+               .la = {
+                       .reg = 0x348,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x06,
+               },
+       }, {
+               .id = 0x3d,
+               .name = "sataw",
+               .swgroup = TEGRA_SWGROUP_SATA,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 29,
+               },
+               .la = {
+                       .reg = 0x350,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x33,
+               },
+       }, {
+               .id = 0x3e,
+               .name = "vdebsevw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 30,
+               },
+               .la = {
+                       .reg = 0x35c,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x3f,
+               .name = "vdedbgw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x22c,
+                       .bit = 31,
+               },
+               .la = {
+                       .reg = 0x35c,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0xff,
+               },
+       }, {
+               .id = 0x40,
+               .name = "vdembew",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 0,
+               },
+               .la = {
+                       .reg = 0x360,
+                       .shift = 0,
+                       .mask = 0xff,
+                       .def = 0x42,
+               },
+       }, {
+               .id = 0x41,
+               .name = "vdetpmw",
+               .swgroup = TEGRA_SWGROUP_VDE,
+               .smmu = {
+                       .reg = 0x230,
+                       .bit = 1,
+               },
+               .la = {
+                       .reg = 0x360,
+                       .shift = 16,
+                       .mask = 0xff,
+                       .def = 0x2a,
+               },
+       },
+};
+
+static const struct tegra_smmu_swgroup tegra30_swgroups[] = {
+       { .swgroup = TEGRA_SWGROUP_DC,   .reg = 0x240 },
+       { .swgroup = TEGRA_SWGROUP_DCB,  .reg = 0x244 },
+       { .swgroup = TEGRA_SWGROUP_EPP,  .reg = 0x248 },
+       { .swgroup = TEGRA_SWGROUP_G2,   .reg = 0x24c },
+       { .swgroup = TEGRA_SWGROUP_MPE,  .reg = 0x264 },
+       { .swgroup = TEGRA_SWGROUP_VI,   .reg = 0x280 },
+       { .swgroup = TEGRA_SWGROUP_AFI,  .reg = 0x238 },
+       { .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c },
+       { .swgroup = TEGRA_SWGROUP_NV,   .reg = 0x268 },
+       { .swgroup = TEGRA_SWGROUP_NV2,  .reg = 0x26c },
+       { .swgroup = TEGRA_SWGROUP_HDA,  .reg = 0x254 },
+       { .swgroup = TEGRA_SWGROUP_HC,   .reg = 0x250 },
+       { .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 },
+       { .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x278 },
+       { .swgroup = TEGRA_SWGROUP_VDE,  .reg = 0x27c },
+       { .swgroup = TEGRA_SWGROUP_ISP,  .reg = 0x258 },
+};
+
+static void tegra30_flush_dcache(struct page *page, unsigned long offset,
+                                size_t size)
+{
+       phys_addr_t phys = page_to_phys(page) + offset;
+       void *virt = page_address(page) + offset;
+
+       __cpuc_flush_dcache_area(virt, size);
+       outer_flush_range(phys, phys + size);
+}
+
+static const struct tegra_smmu_ops tegra30_smmu_ops = {
+       .flush_dcache = tegra30_flush_dcache,
+};
+
+static const struct tegra_smmu_soc tegra30_smmu_soc = {
+       .clients = tegra30_mc_clients,
+       .num_clients = ARRAY_SIZE(tegra30_mc_clients),
+       .swgroups = tegra30_swgroups,
+       .num_swgroups = ARRAY_SIZE(tegra30_swgroups),
+       .supports_round_robin_arbitration = false,
+       .supports_request_limit = false,
+       .num_asids = 4,
+       .ops = &tegra30_smmu_ops,
+};
+
+const struct tegra_mc_soc tegra30_mc_soc = {
+       .clients = tegra30_mc_clients,
+       .num_clients = ARRAY_SIZE(tegra30_mc_clients),
+       .num_address_bits = 32,
+       .atom_size = 16,
+       .smmu = &tegra30_smmu_soc,
+};
diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c
deleted file mode 100644 (file)
index ef79345..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Tegra30 Memory Controller
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  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, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ratelimit.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#define DRV_NAME "tegra30-mc"
-
-#define MC_INTSTATUS                   0x0
-#define MC_INTMASK                     0x4
-
-#define MC_INT_ERR_SHIFT               6
-#define MC_INT_ERR_MASK                        (0x1f << MC_INT_ERR_SHIFT)
-#define MC_INT_DECERR_EMEM             BIT(MC_INT_ERR_SHIFT)
-#define MC_INT_SECURITY_VIOLATION      BIT(MC_INT_ERR_SHIFT + 2)
-#define MC_INT_ARBITRATION_EMEM                BIT(MC_INT_ERR_SHIFT + 3)
-#define MC_INT_INVALID_SMMU_PAGE       BIT(MC_INT_ERR_SHIFT + 4)
-
-#define MC_ERR_STATUS                  0x8
-#define MC_ERR_ADR                     0xc
-
-#define MC_ERR_TYPE_SHIFT              28
-#define MC_ERR_TYPE_MASK               (7 << MC_ERR_TYPE_SHIFT)
-#define MC_ERR_TYPE_DECERR_EMEM                2
-#define MC_ERR_TYPE_SECURITY_TRUSTZONE 3
-#define MC_ERR_TYPE_SECURITY_CARVEOUT  4
-#define MC_ERR_TYPE_INVALID_SMMU_PAGE  6
-
-#define MC_ERR_INVALID_SMMU_PAGE_SHIFT 25
-#define MC_ERR_INVALID_SMMU_PAGE_MASK  (7 << MC_ERR_INVALID_SMMU_PAGE_SHIFT)
-#define MC_ERR_RW_SHIFT                        16
-#define MC_ERR_RW                      BIT(MC_ERR_RW_SHIFT)
-#define MC_ERR_SECURITY                        BIT(MC_ERR_RW_SHIFT + 1)
-
-#define SECURITY_VIOLATION_TYPE                BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
-
-#define MC_EMEM_ARB_CFG                        0x90
-#define MC_EMEM_ARB_OUTSTANDING_REQ    0x94
-#define MC_EMEM_ARB_TIMING_RCD         0x98
-#define MC_EMEM_ARB_TIMING_RP          0x9c
-#define MC_EMEM_ARB_TIMING_RC          0xa0
-#define MC_EMEM_ARB_TIMING_RAS         0xa4
-#define MC_EMEM_ARB_TIMING_FAW         0xa8
-#define MC_EMEM_ARB_TIMING_RRD         0xac
-#define MC_EMEM_ARB_TIMING_RAP2PRE     0xb0
-#define MC_EMEM_ARB_TIMING_WAP2PRE     0xb4
-#define MC_EMEM_ARB_TIMING_R2R         0xb8
-#define MC_EMEM_ARB_TIMING_W2W         0xbc
-#define MC_EMEM_ARB_TIMING_R2W         0xc0
-#define MC_EMEM_ARB_TIMING_W2R         0xc4
-
-#define MC_EMEM_ARB_DA_TURNS           0xd0
-#define MC_EMEM_ARB_DA_COVERS          0xd4
-#define MC_EMEM_ARB_MISC0              0xd8
-#define MC_EMEM_ARB_MISC1              0xdc
-
-#define MC_EMEM_ARB_RING3_THROTTLE     0xe4
-#define MC_EMEM_ARB_OVERRIDE           0xe8
-
-#define MC_TIMING_CONTROL              0xfc
-
-#define MC_CLIENT_ID_MASK              0x7f
-
-#define NUM_MC_REG_BANKS               4
-
-struct tegra30_mc {
-       void __iomem *regs[NUM_MC_REG_BANKS];
-       struct device *dev;
-       u32 ctx[0];
-};
-
-static inline u32 mc_readl(struct tegra30_mc *mc, u32 offs)
-{
-       u32 val = 0;
-
-       if (offs < 0x10)
-               val = readl(mc->regs[0] + offs);
-       else if (offs < 0x1f0)
-               val = readl(mc->regs[1] + offs - 0x3c);
-       else if (offs < 0x228)
-               val = readl(mc->regs[2] + offs - 0x200);
-       else if (offs < 0x400)
-               val = readl(mc->regs[3] + offs - 0x284);
-
-       return val;
-}
-
-static inline void mc_writel(struct tegra30_mc *mc, u32 val, u32 offs)
-{
-       if (offs < 0x10)
-               writel(val, mc->regs[0] + offs);
-       else if (offs < 0x1f0)
-               writel(val, mc->regs[1] + offs - 0x3c);
-       else if (offs < 0x228)
-               writel(val, mc->regs[2] + offs - 0x200);
-       else if (offs < 0x400)
-               writel(val, mc->regs[3] + offs - 0x284);
-}
-
-static const char * const tegra30_mc_client[] = {
-       "csr_ptcr",
-       "cbr_display0a",
-       "cbr_display0ab",
-       "cbr_display0b",
-       "cbr_display0bb",
-       "cbr_display0c",
-       "cbr_display0cb",
-       "cbr_display1b",
-       "cbr_display1bb",
-       "cbr_eppup",
-       "cbr_g2pr",
-       "cbr_g2sr",
-       "cbr_mpeunifbr",
-       "cbr_viruv",
-       "csr_afir",
-       "csr_avpcarm7r",
-       "csr_displayhc",
-       "csr_displayhcb",
-       "csr_fdcdrd",
-       "csr_fdcdrd2",
-       "csr_g2dr",
-       "csr_hdar",
-       "csr_host1xdmar",
-       "csr_host1xr",
-       "csr_idxsrd",
-       "csr_idxsrd2",
-       "csr_mpe_ipred",
-       "csr_mpeamemrd",
-       "csr_mpecsrd",
-       "csr_ppcsahbdmar",
-       "csr_ppcsahbslvr",
-       "csr_satar",
-       "csr_texsrd",
-       "csr_texsrd2",
-       "csr_vdebsevr",
-       "csr_vdember",
-       "csr_vdemcer",
-       "csr_vdetper",
-       "csr_mpcorelpr",
-       "csr_mpcorer",
-       "cbw_eppu",
-       "cbw_eppv",
-       "cbw_eppy",
-       "cbw_mpeunifbw",
-       "cbw_viwsb",
-       "cbw_viwu",
-       "cbw_viwv",
-       "cbw_viwy",
-       "ccw_g2dw",
-       "csw_afiw",
-       "csw_avpcarm7w",
-       "csw_fdcdwr",
-       "csw_fdcdwr2",
-       "csw_hdaw",
-       "csw_host1xw",
-       "csw_ispw",
-       "csw_mpcorelpw",
-       "csw_mpcorew",
-       "csw_mpecswr",
-       "csw_ppcsahbdmaw",
-       "csw_ppcsahbslvw",
-       "csw_sataw",
-       "csw_vdebsevw",
-       "csw_vdedbgw",
-       "csw_vdembew",
-       "csw_vdetpmw",
-};
-
-static void tegra30_mc_decode(struct tegra30_mc *mc, int n)
-{
-       u32 err, addr;
-       const char * const mc_int_err[] = {
-               "MC_DECERR",
-               "Unknown",
-               "MC_SECURITY_ERR",
-               "MC_ARBITRATION_EMEM",
-               "MC_SMMU_ERR",
-       };
-       const char * const err_type[] = {
-               "Unknown",
-               "Unknown",
-               "DECERR_EMEM",
-               "SECURITY_TRUSTZONE",
-               "SECURITY_CARVEOUT",
-               "Unknown",
-               "INVALID_SMMU_PAGE",
-               "Unknown",
-       };
-       char attr[6];
-       int cid, perm, type, idx;
-       const char *client = "Unknown";
-
-       idx = n - MC_INT_ERR_SHIFT;
-       if ((idx < 0) || (idx >= ARRAY_SIZE(mc_int_err)) || (idx == 1)) {
-               dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n",
-                                   BIT(n));
-               return;
-       }
-
-       err = mc_readl(mc, MC_ERR_STATUS);
-
-       type = (err & MC_ERR_TYPE_MASK) >> MC_ERR_TYPE_SHIFT;
-       perm = (err & MC_ERR_INVALID_SMMU_PAGE_MASK) >>
-               MC_ERR_INVALID_SMMU_PAGE_SHIFT;
-       if (type == MC_ERR_TYPE_INVALID_SMMU_PAGE)
-               sprintf(attr, "%c-%c-%c",
-                       (perm & BIT(2)) ? 'R' : '-',
-                       (perm & BIT(1)) ? 'W' : '-',
-                       (perm & BIT(0)) ? 'S' : '-');
-       else
-               attr[0] = '\0';
-
-       cid = err & MC_CLIENT_ID_MASK;
-       if (cid < ARRAY_SIZE(tegra30_mc_client))
-               client = tegra30_mc_client[cid];
-
-       addr = mc_readl(mc, MC_ERR_ADR);
-
-       dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s %s %s)\n",
-                          mc_int_err[idx], err, addr, client,
-                          (err & MC_ERR_SECURITY) ? "secure" : "non-secure",
-                          (err & MC_ERR_RW) ? "write" : "read",
-                          err_type[type], attr);
-}
-
-static const u32 tegra30_mc_ctx[] = {
-       MC_EMEM_ARB_CFG,
-       MC_EMEM_ARB_OUTSTANDING_REQ,
-       MC_EMEM_ARB_TIMING_RCD,
-       MC_EMEM_ARB_TIMING_RP,
-       MC_EMEM_ARB_TIMING_RC,
-       MC_EMEM_ARB_TIMING_RAS,
-       MC_EMEM_ARB_TIMING_FAW,
-       MC_EMEM_ARB_TIMING_RRD,
-       MC_EMEM_ARB_TIMING_RAP2PRE,
-       MC_EMEM_ARB_TIMING_WAP2PRE,
-       MC_EMEM_ARB_TIMING_R2R,
-       MC_EMEM_ARB_TIMING_W2W,
-       MC_EMEM_ARB_TIMING_R2W,
-       MC_EMEM_ARB_TIMING_W2R,
-       MC_EMEM_ARB_DA_TURNS,
-       MC_EMEM_ARB_DA_COVERS,
-       MC_EMEM_ARB_MISC0,
-       MC_EMEM_ARB_MISC1,
-       MC_EMEM_ARB_RING3_THROTTLE,
-       MC_EMEM_ARB_OVERRIDE,
-       MC_INTMASK,
-};
-
-#ifdef CONFIG_PM
-static int tegra30_mc_suspend(struct device *dev)
-{
-       int i;
-       struct tegra30_mc *mc = dev_get_drvdata(dev);
-
-       for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
-               mc->ctx[i] = mc_readl(mc, tegra30_mc_ctx[i]);
-       return 0;
-}
-
-static int tegra30_mc_resume(struct device *dev)
-{
-       int i;
-       struct tegra30_mc *mc = dev_get_drvdata(dev);
-
-       for (i = 0; i < ARRAY_SIZE(tegra30_mc_ctx); i++)
-               mc_writel(mc, mc->ctx[i], tegra30_mc_ctx[i]);
-
-       mc_writel(mc, 1, MC_TIMING_CONTROL);
-       /* Read-back to ensure that write reached */
-       mc_readl(mc, MC_TIMING_CONTROL);
-       return 0;
-}
-#endif
-
-static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm,
-                           tegra30_mc_suspend,
-                           tegra30_mc_resume, NULL);
-
-static const struct of_device_id tegra30_mc_of_match[] = {
-       { .compatible = "nvidia,tegra30-mc", },
-       {},
-};
-
-static irqreturn_t tegra30_mc_isr(int irq, void *data)
-{
-       u32 stat, mask, bit;
-       struct tegra30_mc *mc = data;
-
-       stat = mc_readl(mc, MC_INTSTATUS);
-       mask = mc_readl(mc, MC_INTMASK);
-       mask &= stat;
-       if (!mask)
-               return IRQ_NONE;
-       while ((bit = ffs(mask)) != 0) {
-               tegra30_mc_decode(mc, bit - 1);
-               mask &= ~BIT(bit - 1);
-       }
-
-       mc_writel(mc, stat, MC_INTSTATUS);
-       return IRQ_HANDLED;
-}
-
-static int tegra30_mc_probe(struct platform_device *pdev)
-{
-       struct resource *irq;
-       struct tegra30_mc *mc;
-       size_t bytes;
-       int err, i;
-       u32 intmask;
-
-       bytes = sizeof(*mc) + sizeof(u32) * ARRAY_SIZE(tegra30_mc_ctx);
-       mc = devm_kzalloc(&pdev->dev, bytes, GFP_KERNEL);
-       if (!mc)
-               return -ENOMEM;
-       mc->dev = &pdev->dev;
-
-       for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
-               struct resource *res;
-
-               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               mc->regs[i] = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(mc->regs[i]))
-                       return PTR_ERR(mc->regs[i]);
-       }
-
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!irq)
-               return -ENODEV;
-       err = devm_request_irq(&pdev->dev, irq->start, tegra30_mc_isr,
-                              IRQF_SHARED, dev_name(&pdev->dev), mc);
-       if (err)
-               return -ENODEV;
-
-       platform_set_drvdata(pdev, mc);
-
-       intmask = MC_INT_INVALID_SMMU_PAGE |
-               MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
-       mc_writel(mc, intmask, MC_INTMASK);
-       return 0;
-}
-
-static struct platform_driver tegra30_mc_driver = {
-       .probe = tegra30_mc_probe,
-       .driver = {
-               .name = DRV_NAME,
-               .owner = THIS_MODULE,
-               .of_match_table = tegra30_mc_of_match,
-               .pm = &tegra30_mc_pm,
-       },
-};
-module_platform_driver(tegra30_mc_driver);
-
-MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
-MODULE_DESCRIPTION("Tegra30 MC driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
index 0707fa2c701b543ef597d4797e77b8272c658ca4..5bdaae15a74257d9c252abed3b15ae5ce5cde69a 100644 (file)
@@ -1994,6 +1994,7 @@ static struct scsi_host_template mptsas_driver_template = {
        .cmd_per_lun                    = 7,
        .use_clustering                 = ENABLE_CLUSTERING,
        .shost_attrs                    = mptscsih_host_attrs,
+       .use_blk_tags                   = 1,
 };
 
 static int mptsas_get_linkerrors(struct sas_phy *phy)
index e7dcb25833697e05a8d00742eac640dfd338f71d..6c9fc11efb87221dc2994c63babe8664809c9821 100644 (file)
@@ -2311,26 +2311,21 @@ mptscsih_slave_destroy(struct scsi_device *sdev)
  *     mptscsih_change_queue_depth - This function will set a devices queue depth
  *     @sdev: per scsi_device pointer
  *     @qdepth: requested queue depth
- *     @reason: calling context
  *
  *     Adding support for new 'change_queue_depth' api.
 */
 int
-mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
+mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
        MPT_SCSI_HOST           *hd = shost_priv(sdev->host);
        VirtTarget              *vtarget;
        struct scsi_target      *starget;
        int                     max_depth;
-       int                     tagged;
        MPT_ADAPTER             *ioc = hd->ioc;
 
        starget = scsi_target(sdev);
        vtarget = starget->hostdata;
 
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (ioc->bus_type == SPI) {
                if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
                        max_depth = 1;
@@ -2347,13 +2342,8 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 
        if (qdepth > max_depth)
                qdepth = max_depth;
-       if (qdepth == 1)
-               tagged = 0;
-       else
-               tagged = MSG_SIMPLE_TAG;
 
-       scsi_adjust_queue_depth(sdev, tagged, qdepth);
-       return sdev->queue_depth;
+       return scsi_change_queue_depth(sdev, qdepth);
 }
 
 /*
@@ -2397,12 +2387,10 @@ mptscsih_slave_configure(struct scsi_device *sdev)
                    ioc->name, vtarget->negoFlags, vtarget->maxOffset,
                    vtarget->minSyncFactor));
 
-       mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH,
-                                   SCSI_QDEPTH_DEFAULT);
+       mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
        dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-               "tagged %d, simple %d, ordered %d\n",
-               ioc->name,sdev->tagged_supported, sdev->simple_tags,
-               sdev->ordered_tags));
+               "tagged %d, simple %d\n",
+               ioc->name,sdev->tagged_supported, sdev->simple_tags));
 
        blk_queue_dma_alignment (sdev->request_queue, 512 - 1);
 
index e1b1a198a62aaa98d3c559c189e46a9bc200da3d..2baeefd9be7a20f78c024b4596c37c52d676cead 100644 (file)
@@ -128,8 +128,7 @@ extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_F
 extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
-extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth,
-                                      int reason);
+extern int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth);
 extern u8 mptscsih_raid_id_to_num(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, u8 channel, u8 id);
 extern struct device_attribute *mptscsih_host_attrs[];
index 1456ea70bbc7c5286af3190792e954a3610d85cd..2e6b7311fabc896f082aae33779025fb7fa93b69 100644 (file)
@@ -59,6 +59,17 @@ config MFD_AAT2870_CORE
          additional drivers must be enabled in order to use the
          functionality of the device.
 
+config MFD_ATMEL_HLCDC
+       tristate "Atmel HLCDC (High-end LCD Controller)"
+       select MFD_CORE
+       select REGMAP_MMIO
+       depends on OF
+       help
+         If you say yes here you get support for the HLCDC block.
+         This driver provides common support for accessing the device,
+         additional drivers must be enabled in order to use the
+         functionality of the device.
+
 config MFD_BCM590XX
        tristate "Broadcom BCM590xx PMUs"
        select MFD_CORE
@@ -74,7 +85,8 @@ config MFD_AXP20X
        select REGMAP_IRQ
        depends on I2C=y
        help
-         If you say Y here you get support for the X-Powers AXP202 and AXP209.
+         If you say Y here you get support for the X-Powers AXP202, AXP209 and
+         AXP288 power management IC (PMIC).
          This driver include only the core APIs. You have to select individual
          components like regulators or the PEK (Power Enable Key) under the
          corresponding menus.
@@ -183,6 +195,16 @@ config MFD_DA9063
          Additional drivers must be enabled in order to use the functionality
          of the device.
 
+config MFD_DLN2
+       tristate "Diolan DLN2 support"
+       select MFD_CORE
+       depends on USB
+       help
+         This adds support for Diolan USB-I2C/SPI/GPIO Master Adapter
+         DLN-2. Additional drivers such as I2C_DLN2, GPIO_DLN2,
+         etc. must be enabled in order to use the functionality of
+         the device.
+
 config MFD_MC13XXX
        tristate
        depends on (SPI_MASTER || I2C)
@@ -655,7 +677,6 @@ config MFD_SEC_CORE
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
-       select REGULATOR
        help
         Support for the Samsung Electronics MFD series.
         This driver provides common support for accessing the device,
index 8bd54b1253af5f6fd836146173daec0ce11ceafe..53467e21138118e881928944d5ae5651d3ca10cc 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_MFD_CROS_EC)     += cros_ec.o
 obj-$(CONFIG_MFD_CROS_EC_I2C)  += cros_ec_i2c.o
 obj-$(CONFIG_MFD_CROS_EC_SPI)  += cros_ec_spi.o
 
-rtsx_pci-objs                  := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
+rtsx_pci-objs                  := rtsx_pcr.o rtsx_gops.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
 obj-$(CONFIG_MFD_RTSX_PCI)     += rtsx_pci.o
 obj-$(CONFIG_MFD_RTSX_USB)     += rtsx_usb.o
 
@@ -157,6 +157,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090)     += tps65090.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_ATMEL_HLCDC)  += atmel-hlcdc.o
 obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
 obj-$(CONFIG_MFD_PALMAS)       += palmas.o
 obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
@@ -174,6 +175,7 @@ obj-$(CONFIG_MFD_STW481X)   += stw481x.o
 obj-$(CONFIG_MFD_IPAQ_MICRO)   += ipaq-micro.o
 obj-$(CONFIG_MFD_MENF21BMC)    += menf21bmc.o
 obj-$(CONFIG_MFD_HI6421_PMIC)  += hi6421-pmic-core.o
+obj-$(CONFIG_MFD_DLN2)         += dln2.o
 
 intel-soc-pmic-objs            := intel_soc_pmic_core.o intel_soc_pmic_crc.o
 obj-$(CONFIG_INTEL_SOC_PMIC)   += intel-soc-pmic.o
index 8e0dae59844d494cd4e2c79904779b8f0a3c0acf..94dbcdd2a1ff78d636caa43d62ae9d18a46f6fc6 100644 (file)
@@ -85,63 +85,6 @@ shutdown:
        }
 }
 
-/*
- * Use the AB WD to reset the platform. It will perform a hard
- * reset instead of a soft reset. Write the reset reason to
- * the AB before reset, which can be read upon restart.
- */
-void ab8500_restart(char mode, const char *cmd)
-{
-       struct ab8500_platform_data *plat;
-       struct ab8500_sysctrl_platform_data *pdata;
-       u16 reason = 0;
-       u8 val;
-
-       if (sysctrl_dev == NULL) {
-               pr_err("%s: sysctrl not initialized\n", __func__);
-               return;
-       }
-
-       plat = dev_get_platdata(sysctrl_dev->parent);
-       pdata = plat->sysctrl;
-       if (pdata && pdata->reboot_reason_code)
-               reason = pdata->reboot_reason_code(cmd);
-       else
-               pr_warn("[%s] No reboot reason set. Default reason %d\n",
-                       __func__, reason);
-
-       /*
-        * Disable RTC alarm, just a precaution so that no alarm
-        * is running when WD reset is executed.
-        */
-       abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC,
-               RTC_CTRL , &val);
-       abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
-               RTC_CTRL , (val & ~RTC_ALARM_ENABLE));
-
-       /*
-        * Android is not using the RTC alarm registers during reboot
-        * so we borrow them for writing the reason of reset
-        */
-
-       /* reason[8 LSB] */
-       val = reason & 0xFF;
-       abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
-               AB8500_ALARM_MIN_LOW , val);
-
-       /* reason[8 MSB] */
-       val = (reason>>8) & 0xFF;
-       abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
-               AB8500_ALARM_MIN_MID , val);
-
-       /* Setting WD timeout to 0 */
-       ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0);
-
-       /* Setting the parameters to AB8500 WD*/
-       ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD |
-               AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD));
-}
-
 static inline bool valid_bank(u8 bank)
 {
        return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
index 5145d78bf07e0ddfa9556716408eb29bfcb7b132..8ef58bcff193e8c6c1f7e61872326cb545afdff2 100644 (file)
@@ -75,7 +75,9 @@ static int arizona_spi_probe(struct spi_device *spi)
 static int arizona_spi_remove(struct spi_device *spi)
 {
        struct arizona *arizona = spi_get_drvdata(spi);
+
        arizona_dev_exit(arizona);
+
        return 0;
 }
 
diff --git a/drivers/mfd/atmel-hlcdc.c b/drivers/mfd/atmel-hlcdc.c
new file mode 100644 (file)
index 0000000..cfd58f4
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ * Copyright (C) 2014 Atmel
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * 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/clk.h>
+#include <linux/mfd/atmel-hlcdc.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define ATMEL_HLCDC_REG_MAX            (0x4000 - 0x4)
+
+static const struct mfd_cell atmel_hlcdc_cells[] = {
+       {
+               .name = "atmel-hlcdc-pwm",
+               .of_compatible = "atmel,hlcdc-pwm",
+       },
+       {
+               .name = "atmel-hlcdc-dc",
+               .of_compatible = "atmel,hlcdc-display-controller",
+       },
+};
+
+static const struct regmap_config atmel_hlcdc_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = ATMEL_HLCDC_REG_MAX,
+};
+
+static int atmel_hlcdc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct atmel_hlcdc *hlcdc;
+       struct resource *res;
+       void __iomem *regs;
+
+       hlcdc = devm_kzalloc(dev, sizeof(*hlcdc), GFP_KERNEL);
+       if (!hlcdc)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
+
+       hlcdc->irq = platform_get_irq(pdev, 0);
+       if (hlcdc->irq < 0)
+               return hlcdc->irq;
+
+       hlcdc->periph_clk = devm_clk_get(dev, "periph_clk");
+       if (IS_ERR(hlcdc->periph_clk)) {
+               dev_err(dev, "failed to get peripheral clock\n");
+               return PTR_ERR(hlcdc->periph_clk);
+       }
+
+       hlcdc->sys_clk = devm_clk_get(dev, "sys_clk");
+       if (IS_ERR(hlcdc->sys_clk)) {
+               dev_err(dev, "failed to get system clock\n");
+               return PTR_ERR(hlcdc->sys_clk);
+       }
+
+       hlcdc->slow_clk = devm_clk_get(dev, "slow_clk");
+       if (IS_ERR(hlcdc->slow_clk)) {
+               dev_err(dev, "failed to get slow clock\n");
+               return PTR_ERR(hlcdc->slow_clk);
+       }
+
+       hlcdc->regmap = devm_regmap_init_mmio(dev, regs,
+                                             &atmel_hlcdc_regmap_config);
+       if (IS_ERR(hlcdc->regmap))
+               return PTR_ERR(hlcdc->regmap);
+
+       dev_set_drvdata(dev, hlcdc);
+
+       return mfd_add_devices(dev, -1, atmel_hlcdc_cells,
+                              ARRAY_SIZE(atmel_hlcdc_cells),
+                              NULL, 0, NULL);
+}
+
+static int atmel_hlcdc_remove(struct platform_device *pdev)
+{
+       mfd_remove_devices(&pdev->dev);
+
+       return 0;
+}
+
+static const struct of_device_id atmel_hlcdc_match[] = {
+       { .compatible = "atmel,sama5d3-hlcdc" },
+       { /* sentinel */ },
+};
+
+static struct platform_driver atmel_hlcdc_driver = {
+       .probe = atmel_hlcdc_probe,
+       .remove = atmel_hlcdc_remove,
+       .driver = {
+               .name = "atmel-hlcdc",
+               .of_match_table = atmel_hlcdc_match,
+       },
+};
+module_platform_driver(atmel_hlcdc_driver);
+
+MODULE_ALIAS("platform:atmel-hlcdc");
+MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
+MODULE_DESCRIPTION("Atmel HLCDC driver");
+MODULE_LICENSE("GPL v2");
index 6231adbb295d6afd876de989db2a97f314a96cb8..c522ee22b1c05eb7530e6e288ed4f5bf9589cfb8 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * axp20x.c - MFD core driver for the X-Powers AXP202 and AXP209
+ * axp20x.c - MFD core driver for the X-Powers' Power Management ICs
  *
- * AXP20x comprises an adaptive USB-Compatible PWM charger, 2 BUCK DC-DC
- * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
- * as well as configurable GPIOs.
+ * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
+ * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
+ * as well as configurable GPIOs.
  *
  * Author: Carlo Caione <carlo@caione.org>
  *
 #include <linux/mfd/core.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/acpi.h>
 
 #define AXP20X_OFF     0x80
 
+static const char const *axp20x_model_names[] = {
+       "AXP202",
+       "AXP209",
+       "AXP288",
+};
+
 static const struct regmap_range axp20x_writeable_ranges[] = {
        regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
        regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
@@ -47,6 +54,25 @@ static const struct regmap_access_table axp20x_volatile_table = {
        .n_yes_ranges   = ARRAY_SIZE(axp20x_volatile_ranges),
 };
 
+static const struct regmap_range axp288_writeable_ranges[] = {
+       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
+       regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
+};
+
+static const struct regmap_range axp288_volatile_ranges[] = {
+       regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
+};
+
+static const struct regmap_access_table axp288_writeable_table = {
+       .yes_ranges     = axp288_writeable_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(axp288_writeable_ranges),
+};
+
+static const struct regmap_access_table axp288_volatile_table = {
+       .yes_ranges     = axp288_volatile_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(axp288_volatile_ranges),
+};
+
 static struct resource axp20x_pek_resources[] = {
        {
                .name   = "PEK_DBR",
@@ -61,6 +87,39 @@ static struct resource axp20x_pek_resources[] = {
        },
 };
 
+static struct resource axp288_battery_resources[] = {
+       {
+               .start = AXP288_IRQ_QWBTU,
+               .end   = AXP288_IRQ_QWBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WBTU,
+               .end   = AXP288_IRQ_WBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_QWBTO,
+               .end   = AXP288_IRQ_QWBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WBTO,
+               .end   = AXP288_IRQ_WBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WL2,
+               .end   = AXP288_IRQ_WL2,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_WL1,
+               .end   = AXP288_IRQ_WL1,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
 static const struct regmap_config axp20x_regmap_config = {
        .reg_bits       = 8,
        .val_bits       = 8,
@@ -70,47 +129,96 @@ static const struct regmap_config axp20x_regmap_config = {
        .cache_type     = REGCACHE_RBTREE,
 };
 
-#define AXP20X_IRQ(_irq, _off, _mask) \
-       [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
+static const struct regmap_config axp288_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .wr_table       = &axp288_writeable_table,
+       .volatile_table = &axp288_volatile_table,
+       .max_register   = AXP288_FG_TUNE5,
+       .cache_type     = REGCACHE_RBTREE,
+};
+
+#define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)                   \
+       [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
 
 static const struct regmap_irq axp20x_regmap_irqs[] = {
-       AXP20X_IRQ(ACIN_OVER_V,         0, 7),
-       AXP20X_IRQ(ACIN_PLUGIN,         0, 6),
-       AXP20X_IRQ(ACIN_REMOVAL,        0, 5),
-       AXP20X_IRQ(VBUS_OVER_V,         0, 4),
-       AXP20X_IRQ(VBUS_PLUGIN,         0, 3),
-       AXP20X_IRQ(VBUS_REMOVAL,        0, 2),
-       AXP20X_IRQ(VBUS_V_LOW,          0, 1),
-       AXP20X_IRQ(BATT_PLUGIN,         1, 7),
-       AXP20X_IRQ(BATT_REMOVAL,        1, 6),
-       AXP20X_IRQ(BATT_ENT_ACT_MODE,   1, 5),
-       AXP20X_IRQ(BATT_EXIT_ACT_MODE,  1, 4),
-       AXP20X_IRQ(CHARG,               1, 3),
-       AXP20X_IRQ(CHARG_DONE,          1, 2),
-       AXP20X_IRQ(BATT_TEMP_HIGH,      1, 1),
-       AXP20X_IRQ(BATT_TEMP_LOW,       1, 0),
-       AXP20X_IRQ(DIE_TEMP_HIGH,       2, 7),
-       AXP20X_IRQ(CHARG_I_LOW,         2, 6),
-       AXP20X_IRQ(DCDC1_V_LONG,        2, 5),
-       AXP20X_IRQ(DCDC2_V_LONG,        2, 4),
-       AXP20X_IRQ(DCDC3_V_LONG,        2, 3),
-       AXP20X_IRQ(PEK_SHORT,           2, 1),
-       AXP20X_IRQ(PEK_LONG,            2, 0),
-       AXP20X_IRQ(N_OE_PWR_ON,         3, 7),
-       AXP20X_IRQ(N_OE_PWR_OFF,        3, 6),
-       AXP20X_IRQ(VBUS_VALID,          3, 5),
-       AXP20X_IRQ(VBUS_NOT_VALID,      3, 4),
-       AXP20X_IRQ(VBUS_SESS_VALID,     3, 3),
-       AXP20X_IRQ(VBUS_SESS_END,       3, 2),
-       AXP20X_IRQ(LOW_PWR_LVL1,        3, 1),
-       AXP20X_IRQ(LOW_PWR_LVL2,        3, 0),
-       AXP20X_IRQ(TIMER,               4, 7),
-       AXP20X_IRQ(PEK_RIS_EDGE,        4, 6),
-       AXP20X_IRQ(PEK_FAL_EDGE,        4, 5),
-       AXP20X_IRQ(GPIO3_INPUT,         4, 3),
-       AXP20X_IRQ(GPIO2_INPUT,         4, 2),
-       AXP20X_IRQ(GPIO1_INPUT,         4, 1),
-       AXP20X_IRQ(GPIO0_INPUT,         4, 0),
+       INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V,            0, 7),
+       INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN,            0, 6),
+       INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL,           0, 5),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V,            0, 4),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN,            0, 3),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL,           0, 2),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW,             0, 1),
+       INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN,            1, 7),
+       INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL,           1, 6),
+       INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE,      1, 5),
+       INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE,     1, 4),
+       INIT_REGMAP_IRQ(AXP20X, CHARG,                  1, 3),
+       INIT_REGMAP_IRQ(AXP20X, CHARG_DONE,             1, 2),
+       INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH,         1, 1),
+       INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW,          1, 0),
+       INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH,          2, 7),
+       INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW,            2, 6),
+       INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG,           2, 5),
+       INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG,           2, 4),
+       INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG,           2, 3),
+       INIT_REGMAP_IRQ(AXP20X, PEK_SHORT,              2, 1),
+       INIT_REGMAP_IRQ(AXP20X, PEK_LONG,               2, 0),
+       INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON,            3, 7),
+       INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF,           3, 6),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_VALID,             3, 5),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID,         3, 4),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID,        3, 3),
+       INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END,          3, 2),
+       INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1,           3, 1),
+       INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2,           3, 0),
+       INIT_REGMAP_IRQ(AXP20X, TIMER,                  4, 7),
+       INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE,           4, 6),
+       INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE,           4, 5),
+       INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT,            4, 3),
+       INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT,            4, 2),
+       INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT,            4, 1),
+       INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT,            4, 0),
+};
+
+/* some IRQs are compatible with axp20x models */
+static const struct regmap_irq axp288_regmap_irqs[] = {
+       INIT_REGMAP_IRQ(AXP288, VBUS_FALL,              0, 2),
+       INIT_REGMAP_IRQ(AXP288, VBUS_RISE,              0, 3),
+       INIT_REGMAP_IRQ(AXP288, OV,                     0, 4),
+
+       INIT_REGMAP_IRQ(AXP288, DONE,                   1, 2),
+       INIT_REGMAP_IRQ(AXP288, CHARGING,               1, 3),
+       INIT_REGMAP_IRQ(AXP288, SAFE_QUIT,              1, 4),
+       INIT_REGMAP_IRQ(AXP288, SAFE_ENTER,             1, 5),
+       INIT_REGMAP_IRQ(AXP288, ABSENT,                 1, 6),
+       INIT_REGMAP_IRQ(AXP288, APPEND,                 1, 7),
+
+       INIT_REGMAP_IRQ(AXP288, QWBTU,                  2, 0),
+       INIT_REGMAP_IRQ(AXP288, WBTU,                   2, 1),
+       INIT_REGMAP_IRQ(AXP288, QWBTO,                  2, 2),
+       INIT_REGMAP_IRQ(AXP288, WBTO,                   2, 3),
+       INIT_REGMAP_IRQ(AXP288, QCBTU,                  2, 4),
+       INIT_REGMAP_IRQ(AXP288, CBTU,                   2, 5),
+       INIT_REGMAP_IRQ(AXP288, QCBTO,                  2, 6),
+       INIT_REGMAP_IRQ(AXP288, CBTO,                   2, 7),
+
+       INIT_REGMAP_IRQ(AXP288, WL2,                    3, 0),
+       INIT_REGMAP_IRQ(AXP288, WL1,                    3, 1),
+       INIT_REGMAP_IRQ(AXP288, GPADC,                  3, 2),
+       INIT_REGMAP_IRQ(AXP288, OT,                     3, 7),
+
+       INIT_REGMAP_IRQ(AXP288, GPIO0,                  4, 0),
+       INIT_REGMAP_IRQ(AXP288, GPIO1,                  4, 1),
+       INIT_REGMAP_IRQ(AXP288, POKO,                   4, 2),
+       INIT_REGMAP_IRQ(AXP288, POKL,                   4, 3),
+       INIT_REGMAP_IRQ(AXP288, POKS,                   4, 4),
+       INIT_REGMAP_IRQ(AXP288, POKN,                   4, 5),
+       INIT_REGMAP_IRQ(AXP288, POKP,                   4, 6),
+       INIT_REGMAP_IRQ(AXP288, TIMER,                  4, 7),
+
+       INIT_REGMAP_IRQ(AXP288, MV_CHNG,                5, 0),
+       INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG,            5, 1),
 };
 
 static const struct of_device_id axp20x_of_match[] = {
@@ -128,16 +236,39 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
 
+static const struct acpi_device_id axp20x_acpi_match[] = {
+       {
+               .id = "INT33F4",
+               .driver_data = AXP288_ID,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match);
+
 static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
        .name                   = "axp20x_irq_chip",
        .status_base            = AXP20X_IRQ1_STATE,
        .ack_base               = AXP20X_IRQ1_STATE,
        .mask_base              = AXP20X_IRQ1_EN,
-       .num_regs               = 5,
+       .mask_invert            = true,
+       .init_ack_masked        = true,
        .irqs                   = axp20x_regmap_irqs,
        .num_irqs               = ARRAY_SIZE(axp20x_regmap_irqs),
+       .num_regs               = 5,
+
+};
+
+static const struct regmap_irq_chip axp288_regmap_irq_chip = {
+       .name                   = "axp288_irq_chip",
+       .status_base            = AXP20X_IRQ1_STATE,
+       .ack_base               = AXP20X_IRQ1_STATE,
+       .mask_base              = AXP20X_IRQ1_EN,
        .mask_invert            = true,
        .init_ack_masked        = true,
+       .irqs                   = axp288_regmap_irqs,
+       .num_irqs               = ARRAY_SIZE(axp288_regmap_irqs),
+       .num_regs               = 6,
+
 };
 
 static struct mfd_cell axp20x_cells[] = {
@@ -150,36 +281,155 @@ static struct mfd_cell axp20x_cells[] = {
        },
 };
 
+static struct resource axp288_adc_resources[] = {
+       {
+               .name  = "GPADC",
+               .start = AXP288_IRQ_GPADC,
+               .end   = AXP288_IRQ_GPADC,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource axp288_charger_resources[] = {
+       {
+               .start = AXP288_IRQ_OV,
+               .end   = AXP288_IRQ_OV,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_DONE,
+               .end   = AXP288_IRQ_DONE,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_CHARGING,
+               .end   = AXP288_IRQ_CHARGING,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_SAFE_QUIT,
+               .end   = AXP288_IRQ_SAFE_QUIT,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_SAFE_ENTER,
+               .end   = AXP288_IRQ_SAFE_ENTER,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_QCBTU,
+               .end   = AXP288_IRQ_QCBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_CBTU,
+               .end   = AXP288_IRQ_CBTU,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_QCBTO,
+               .end   = AXP288_IRQ_QCBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = AXP288_IRQ_CBTO,
+               .end   = AXP288_IRQ_CBTO,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct mfd_cell axp288_cells[] = {
+       {
+               .name = "axp288_adc",
+               .num_resources = ARRAY_SIZE(axp288_adc_resources),
+               .resources = axp288_adc_resources,
+       },
+       {
+               .name = "axp288_charger",
+               .num_resources = ARRAY_SIZE(axp288_charger_resources),
+               .resources = axp288_charger_resources,
+       },
+       {
+               .name = "axp288_battery",
+               .num_resources = ARRAY_SIZE(axp288_battery_resources),
+               .resources = axp288_battery_resources,
+       },
+};
+
 static struct axp20x_dev *axp20x_pm_power_off;
 static void axp20x_power_off(void)
 {
+       if (axp20x_pm_power_off->variant == AXP288_ID)
+               return;
+
        regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
                     AXP20X_OFF);
 }
 
+static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev)
+{
+       const struct acpi_device_id *acpi_id;
+       const struct of_device_id *of_id;
+
+       if (dev->of_node) {
+               of_id = of_match_device(axp20x_of_match, dev);
+               if (!of_id) {
+                       dev_err(dev, "Unable to match OF ID\n");
+                       return -ENODEV;
+               }
+               axp20x->variant = (long) of_id->data;
+       } else {
+               acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
+               if (!acpi_id || !acpi_id->driver_data) {
+                       dev_err(dev, "Unable to match ACPI ID and data\n");
+                       return -ENODEV;
+               }
+               axp20x->variant = (long) acpi_id->driver_data;
+       }
+
+       switch (axp20x->variant) {
+       case AXP202_ID:
+       case AXP209_ID:
+               axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
+               axp20x->cells = axp20x_cells;
+               axp20x->regmap_cfg = &axp20x_regmap_config;
+               axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
+               break;
+       case AXP288_ID:
+               axp20x->cells = axp288_cells;
+               axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
+               axp20x->regmap_cfg = &axp288_regmap_config;
+               axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
+               break;
+       default:
+               dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
+               return -EINVAL;
+       }
+       dev_info(dev, "AXP20x variant %s found\n",
+               axp20x_model_names[axp20x->variant]);
+
+       return 0;
+}
+
 static int axp20x_i2c_probe(struct i2c_client *i2c,
                         const struct i2c_device_id *id)
 {
        struct axp20x_dev *axp20x;
-       const struct of_device_id *of_id;
        int ret;
 
        axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
        if (!axp20x)
                return -ENOMEM;
 
-       of_id = of_match_device(axp20x_of_match, &i2c->dev);
-       if (!of_id) {
-               dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
-               return -ENODEV;
-       }
-       axp20x->variant = (long) of_id->data;
+       ret = axp20x_match_device(axp20x, &i2c->dev);
+       if (ret)
+               return ret;
 
        axp20x->i2c_client = i2c;
        axp20x->dev = &i2c->dev;
        dev_set_drvdata(axp20x->dev, axp20x);
 
-       axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
+       axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg);
        if (IS_ERR(axp20x->regmap)) {
                ret = PTR_ERR(axp20x->regmap);
                dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
@@ -188,15 +438,15 @@ static int axp20x_i2c_probe(struct i2c_client *i2c,
 
        ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq,
                                  IRQF_ONESHOT | IRQF_SHARED, -1,
-                                 &axp20x_regmap_irq_chip,
+                                 axp20x->regmap_irq_chip,
                                  &axp20x->regmap_irqc);
        if (ret) {
                dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
                return ret;
        }
 
-       ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
-                             ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
+       ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
+                       axp20x->nr_cells, NULL, 0, NULL);
 
        if (ret) {
                dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
@@ -234,6 +484,7 @@ static struct i2c_driver axp20x_i2c_driver = {
                .name   = "axp20x",
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(axp20x_of_match),
+               .acpi_match_table = ACPI_PTR(axp20x_acpi_match),
        },
        .probe          = axp20x_i2c_probe,
        .remove         = axp20x_i2c_remove,
index 93db8bb8c8f0fd8d4ea86a36cedd541f4ecdc45a..f38bc98a3c57a60633b268bdee67136b58962918 100644 (file)
@@ -118,7 +118,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
                da9063->irq_base = pdata->irq_base;
        } else {
                da9063->flags = 0;
-               da9063->irq_base = 0;
+               da9063->irq_base = -1;
        }
        da9063->chip_irq = irq;
 
@@ -168,6 +168,8 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
                return ret;
        }
 
+       da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
+
        ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
                              ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
                              NULL);
index 193cf168ba84d1b08cfb2d419202f80025f61954..a8204730f01cc4f65d1a03385c58dd13089a615d 100644 (file)
@@ -3150,23 +3150,28 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu");
        if (!res) {
                dev_err(&pdev->dev, "no prcmu memory region provided\n");
-               return -ENOENT;
+               return -EINVAL;
        }
        prcmu_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!prcmu_base) {
                dev_err(&pdev->dev,
                        "failed to ioremap prcmu register memory\n");
-               return -ENOENT;
+               return -ENOMEM;
        }
        init_prcm_registers();
        dbx500_fw_version_init(pdev, pdata->version_offset);
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
        if (!res) {
                dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
-               return -ENOENT;
+               return -EINVAL;
        }
        tcdm_base = devm_ioremap(&pdev->dev, res->start,
                        resource_size(res));
+       if (!tcdm_base) {
+               dev_err(&pdev->dev,
+                       "failed to ioremap prcmu-tcdm register memory\n");
+               return -ENOMEM;
+       }
 
        /* Clean up the mailbox interrupts after pre-kernel code. */
        writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
@@ -3174,15 +3179,14 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq <= 0) {
                dev_err(&pdev->dev, "no prcmu irq provided\n");
-               return -ENOENT;
+               return irq;
        }
 
        err = request_threaded_irq(irq, prcmu_irq_handler,
                prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
        if (err < 0) {
                pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
-               err = -EBUSY;
-               goto no_irq_return;
+               return err;
        }
 
        db8500_irq_init(np);
@@ -3206,7 +3210,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
                if (err) {
                        mfd_remove_devices(&pdev->dev);
                        pr_err("prcmu: Failed to add subdevices\n");
-                       goto no_irq_return;
+                       return err;
                }
        }
 
@@ -3214,12 +3218,10 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
        if (err) {
                mfd_remove_devices(&pdev->dev);
                pr_err("prcmu: Failed to add ab8500 subdevice\n");
-               goto no_irq_return;
+               return err;
        }
 
        pr_info("DB8500 PRCMU initialized\n");
-
-no_irq_return:
        return err;
 }
 static const struct of_device_id db8500_prcmu_match[] = {
diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
new file mode 100644 (file)
index 0000000..6d49685
--- /dev/null
@@ -0,0 +1,781 @@
+/*
+ * Driver for the Diolan DLN-2 USB adapter
+ *
+ * Copyright (c) 2014 Intel Corporation
+ *
+ * Derived from:
+ *  i2c-diolan-u2c.c
+ *  Copyright (c) 2010-2011 Ericsson AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/dln2.h>
+#include <linux/rculist.h>
+
+struct dln2_header {
+       __le16 size;
+       __le16 id;
+       __le16 echo;
+       __le16 handle;
+};
+
+struct dln2_response {
+       struct dln2_header hdr;
+       __le16 result;
+};
+
+#define DLN2_GENERIC_MODULE_ID         0x00
+#define DLN2_GENERIC_CMD(cmd)          DLN2_CMD(cmd, DLN2_GENERIC_MODULE_ID)
+#define CMD_GET_DEVICE_VER             DLN2_GENERIC_CMD(0x30)
+#define CMD_GET_DEVICE_SN              DLN2_GENERIC_CMD(0x31)
+
+#define DLN2_HW_ID                     0x200
+#define DLN2_USB_TIMEOUT               200     /* in ms */
+#define DLN2_MAX_RX_SLOTS              16
+#define DLN2_MAX_URBS                  16
+#define DLN2_RX_BUF_SIZE               512
+
+enum dln2_handle {
+       DLN2_HANDLE_EVENT = 0,          /* don't change, hardware defined */
+       DLN2_HANDLE_CTRL,
+       DLN2_HANDLE_GPIO,
+       DLN2_HANDLE_I2C,
+       DLN2_HANDLE_SPI,
+       DLN2_HANDLES
+};
+
+/*
+ * Receive context used between the receive demultiplexer and the transfer
+ * routine. While sending a request the transfer routine will look for a free
+ * receive context and use it to wait for a response and to receive the URB and
+ * thus the response data.
+ */
+struct dln2_rx_context {
+       /* completion used to wait for a response */
+       struct completion done;
+
+       /* if non-NULL the URB contains the response */
+       struct urb *urb;
+
+       /* if true then this context is used to wait for a response */
+       bool in_use;
+};
+
+/*
+ * Receive contexts for a particular DLN2 module (i2c, gpio, etc.). We use the
+ * handle header field to identify the module in dln2_dev.mod_rx_slots and then
+ * the echo header field to index the slots field and find the receive context
+ * for a particular request.
+ */
+struct dln2_mod_rx_slots {
+       /* RX slots bitmap */
+       DECLARE_BITMAP(bmap, DLN2_MAX_RX_SLOTS);
+
+       /* used to wait for a free RX slot */
+       wait_queue_head_t wq;
+
+       /* used to wait for an RX operation to complete */
+       struct dln2_rx_context slots[DLN2_MAX_RX_SLOTS];
+
+       /* avoid races between alloc/free_rx_slot and dln2_rx_transfer */
+       spinlock_t lock;
+};
+
+struct dln2_dev {
+       struct usb_device *usb_dev;
+       struct usb_interface *interface;
+       u8 ep_in;
+       u8 ep_out;
+
+       struct urb *rx_urb[DLN2_MAX_URBS];
+       void *rx_buf[DLN2_MAX_URBS];
+
+       struct dln2_mod_rx_slots mod_rx_slots[DLN2_HANDLES];
+
+       struct list_head event_cb_list;
+       spinlock_t event_cb_lock;
+
+       bool disconnect;
+       int active_transfers;
+       wait_queue_head_t disconnect_wq;
+       spinlock_t disconnect_lock;
+};
+
+struct dln2_event_cb_entry {
+       struct list_head list;
+       u16 id;
+       struct platform_device *pdev;
+       dln2_event_cb_t callback;
+};
+
+int dln2_register_event_cb(struct platform_device *pdev, u16 id,
+                          dln2_event_cb_t event_cb)
+{
+       struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent);
+       struct dln2_event_cb_entry *i, *entry;
+       unsigned long flags;
+       int ret = 0;
+
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+
+       entry->id = id;
+       entry->callback = event_cb;
+       entry->pdev = pdev;
+
+       spin_lock_irqsave(&dln2->event_cb_lock, flags);
+
+       list_for_each_entry(i, &dln2->event_cb_list, list) {
+               if (i->id == id) {
+                       ret = -EBUSY;
+                       break;
+               }
+       }
+
+       if (!ret)
+               list_add_rcu(&entry->list, &dln2->event_cb_list);
+
+       spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
+
+       if (ret)
+               kfree(entry);
+
+       return ret;
+}
+EXPORT_SYMBOL(dln2_register_event_cb);
+
+void dln2_unregister_event_cb(struct platform_device *pdev, u16 id)
+{
+       struct dln2_dev *dln2 = dev_get_drvdata(pdev->dev.parent);
+       struct dln2_event_cb_entry *i;
+       unsigned long flags;
+       bool found = false;
+
+       spin_lock_irqsave(&dln2->event_cb_lock, flags);
+
+       list_for_each_entry(i, &dln2->event_cb_list, list) {
+               if (i->id == id) {
+                       list_del_rcu(&i->list);
+                       found = true;
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
+
+       if (found) {
+               synchronize_rcu();
+               kfree(i);
+       }
+}
+EXPORT_SYMBOL(dln2_unregister_event_cb);
+
+/*
+ * Returns true if a valid transfer slot is found. In this case the URB must not
+ * be resubmitted immediately in dln2_rx as we need the data when dln2_transfer
+ * is woke up. It will be resubmitted there.
+ */
+static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
+                                  u16 handle, u16 rx_slot)
+{
+       struct device *dev = &dln2->interface->dev;
+       struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
+       struct dln2_rx_context *rxc;
+       bool valid_slot = false;
+
+       if (rx_slot >= DLN2_MAX_RX_SLOTS)
+               goto out;
+
+       rxc = &rxs->slots[rx_slot];
+
+       /*
+        * No need to disable interrupts as this lock is not taken in interrupt
+        * context elsewhere in this driver. This function (or its callers) are
+        * also not exported to other modules.
+        */
+       spin_lock(&rxs->lock);
+       if (rxc->in_use && !rxc->urb) {
+               rxc->urb = urb;
+               complete(&rxc->done);
+               valid_slot = true;
+       }
+       spin_unlock(&rxs->lock);
+
+out:
+       if (!valid_slot)
+               dev_warn(dev, "bad/late response %d/%d\n", handle, rx_slot);
+
+       return valid_slot;
+}
+
+static void dln2_run_event_callbacks(struct dln2_dev *dln2, u16 id, u16 echo,
+                                    void *data, int len)
+{
+       struct dln2_event_cb_entry *i;
+
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(i, &dln2->event_cb_list, list) {
+               if (i->id == id) {
+                       i->callback(i->pdev, echo, data, len);
+                       break;
+               }
+       }
+
+       rcu_read_unlock();
+}
+
+static void dln2_rx(struct urb *urb)
+{
+       struct dln2_dev *dln2 = urb->context;
+       struct dln2_header *hdr = urb->transfer_buffer;
+       struct device *dev = &dln2->interface->dev;
+       u16 id, echo, handle, size;
+       u8 *data;
+       int len;
+       int err;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+       case -EPIPE:
+               /* this urb is terminated, clean up */
+               dev_dbg(dev, "urb shutting down with status %d\n", urb->status);
+               return;
+       default:
+               dev_dbg(dev, "nonzero urb status received %d\n", urb->status);
+               goto out;
+       }
+
+       if (urb->actual_length < sizeof(struct dln2_header)) {
+               dev_err(dev, "short response: %d\n", urb->actual_length);
+               goto out;
+       }
+
+       handle = le16_to_cpu(hdr->handle);
+       id = le16_to_cpu(hdr->id);
+       echo = le16_to_cpu(hdr->echo);
+       size = le16_to_cpu(hdr->size);
+
+       if (size != urb->actual_length) {
+               dev_err(dev, "size mismatch: handle %x cmd %x echo %x size %d actual %d\n",
+                       handle, id, echo, size, urb->actual_length);
+               goto out;
+       }
+
+       if (handle >= DLN2_HANDLES) {
+               dev_warn(dev, "invalid handle %d\n", handle);
+               goto out;
+       }
+
+       data = urb->transfer_buffer + sizeof(struct dln2_header);
+       len = urb->actual_length - sizeof(struct dln2_header);
+
+       if (handle == DLN2_HANDLE_EVENT) {
+               dln2_run_event_callbacks(dln2, id, echo, data, len);
+       } else {
+               /* URB will be re-submitted in _dln2_transfer (free_rx_slot) */
+               if (dln2_transfer_complete(dln2, urb, handle, echo))
+                       return;
+       }
+
+out:
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err < 0)
+               dev_err(dev, "failed to resubmit RX URB: %d\n", err);
+}
+
+static void *dln2_prep_buf(u16 handle, u16 cmd, u16 echo, const void *obuf,
+                          int *obuf_len, gfp_t gfp)
+{
+       int len;
+       void *buf;
+       struct dln2_header *hdr;
+
+       len = *obuf_len + sizeof(*hdr);
+       buf = kmalloc(len, gfp);
+       if (!buf)
+               return NULL;
+
+       hdr = (struct dln2_header *)buf;
+       hdr->id = cpu_to_le16(cmd);
+       hdr->size = cpu_to_le16(len);
+       hdr->echo = cpu_to_le16(echo);
+       hdr->handle = cpu_to_le16(handle);
+
+       memcpy(buf + sizeof(*hdr), obuf, *obuf_len);
+
+       *obuf_len = len;
+
+       return buf;
+}
+
+static int dln2_send_wait(struct dln2_dev *dln2, u16 handle, u16 cmd, u16 echo,
+                         const void *obuf, int obuf_len)
+{
+       int ret = 0;
+       int len = obuf_len;
+       void *buf;
+       int actual;
+
+       buf = dln2_prep_buf(handle, cmd, echo, obuf, &len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = usb_bulk_msg(dln2->usb_dev,
+                          usb_sndbulkpipe(dln2->usb_dev, dln2->ep_out),
+                          buf, len, &actual, DLN2_USB_TIMEOUT);
+
+       kfree(buf);
+
+       return ret;
+}
+
+static bool find_free_slot(struct dln2_dev *dln2, u16 handle, int *slot)
+{
+       struct dln2_mod_rx_slots *rxs;
+       unsigned long flags;
+
+       if (dln2->disconnect) {
+               *slot = -ENODEV;
+               return true;
+       }
+
+       rxs = &dln2->mod_rx_slots[handle];
+
+       spin_lock_irqsave(&rxs->lock, flags);
+
+       *slot = find_first_zero_bit(rxs->bmap, DLN2_MAX_RX_SLOTS);
+
+       if (*slot < DLN2_MAX_RX_SLOTS) {
+               struct dln2_rx_context *rxc = &rxs->slots[*slot];
+
+               set_bit(*slot, rxs->bmap);
+               rxc->in_use = true;
+       }
+
+       spin_unlock_irqrestore(&rxs->lock, flags);
+
+       return *slot < DLN2_MAX_RX_SLOTS;
+}
+
+static int alloc_rx_slot(struct dln2_dev *dln2, u16 handle)
+{
+       int ret;
+       int slot;
+
+       /*
+        * No need to timeout here, the wait is bounded by the timeout in
+        * _dln2_transfer.
+        */
+       ret = wait_event_interruptible(dln2->mod_rx_slots[handle].wq,
+                                      find_free_slot(dln2, handle, &slot));
+       if (ret < 0)
+               return ret;
+
+       return slot;
+}
+
+static void free_rx_slot(struct dln2_dev *dln2, u16 handle, int slot)
+{
+       struct dln2_mod_rx_slots *rxs;
+       struct urb *urb = NULL;
+       unsigned long flags;
+       struct dln2_rx_context *rxc;
+
+       rxs = &dln2->mod_rx_slots[handle];
+
+       spin_lock_irqsave(&rxs->lock, flags);
+
+       clear_bit(slot, rxs->bmap);
+
+       rxc = &rxs->slots[slot];
+       rxc->in_use = false;
+       urb = rxc->urb;
+       rxc->urb = NULL;
+       reinit_completion(&rxc->done);
+
+       spin_unlock_irqrestore(&rxs->lock, flags);
+
+       if (urb) {
+               int err;
+               struct device *dev = &dln2->interface->dev;
+
+               err = usb_submit_urb(urb, GFP_KERNEL);
+               if (err < 0)
+                       dev_err(dev, "failed to resubmit RX URB: %d\n", err);
+       }
+
+       wake_up_interruptible(&rxs->wq);
+}
+
+static int _dln2_transfer(struct dln2_dev *dln2, u16 handle, u16 cmd,
+                         const void *obuf, unsigned obuf_len,
+                         void *ibuf, unsigned *ibuf_len)
+{
+       int ret = 0;
+       int rx_slot;
+       struct dln2_response *rsp;
+       struct dln2_rx_context *rxc;
+       struct device *dev = &dln2->interface->dev;
+       const unsigned long timeout = DLN2_USB_TIMEOUT * HZ / 1000;
+       struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
+       int size;
+
+       spin_lock(&dln2->disconnect_lock);
+       if (!dln2->disconnect)
+               dln2->active_transfers++;
+       else
+               ret = -ENODEV;
+       spin_unlock(&dln2->disconnect_lock);
+
+       if (ret)
+               return ret;
+
+       rx_slot = alloc_rx_slot(dln2, handle);
+       if (rx_slot < 0) {
+               ret = rx_slot;
+               goto out_decr;
+       }
+
+       ret = dln2_send_wait(dln2, handle, cmd, rx_slot, obuf, obuf_len);
+       if (ret < 0) {
+               dev_err(dev, "USB write failed: %d\n", ret);
+               goto out_free_rx_slot;
+       }
+
+       rxc = &rxs->slots[rx_slot];
+
+       ret = wait_for_completion_interruptible_timeout(&rxc->done, timeout);
+       if (ret <= 0) {
+               if (!ret)
+                       ret = -ETIMEDOUT;
+               goto out_free_rx_slot;
+       } else {
+               ret = 0;
+       }
+
+       if (dln2->disconnect) {
+               ret = -ENODEV;
+               goto out_free_rx_slot;
+       }
+
+       /* if we got here we know that the response header has been checked */
+       rsp = rxc->urb->transfer_buffer;
+       size = le16_to_cpu(rsp->hdr.size);
+
+       if (size < sizeof(*rsp)) {
+               ret = -EPROTO;
+               goto out_free_rx_slot;
+       }
+
+       if (le16_to_cpu(rsp->result) > 0x80) {
+               dev_dbg(dev, "%d received response with error %d\n",
+                       handle, le16_to_cpu(rsp->result));
+               ret = -EREMOTEIO;
+               goto out_free_rx_slot;
+       }
+
+       if (!ibuf)
+               goto out_free_rx_slot;
+
+       if (*ibuf_len > size - sizeof(*rsp))
+               *ibuf_len = size - sizeof(*rsp);
+
+       memcpy(ibuf, rsp + 1, *ibuf_len);
+
+out_free_rx_slot:
+       free_rx_slot(dln2, handle, rx_slot);
+out_decr:
+       spin_lock(&dln2->disconnect_lock);
+       dln2->active_transfers--;
+       spin_unlock(&dln2->disconnect_lock);
+       if (dln2->disconnect)
+               wake_up(&dln2->disconnect_wq);
+
+       return ret;
+}
+
+int dln2_transfer(struct platform_device *pdev, u16 cmd,
+                 const void *obuf, unsigned obuf_len,
+                 void *ibuf, unsigned *ibuf_len)
+{
+       struct dln2_platform_data *dln2_pdata;
+       struct dln2_dev *dln2;
+       u16 handle;
+
+       dln2 = dev_get_drvdata(pdev->dev.parent);
+       dln2_pdata = dev_get_platdata(&pdev->dev);
+       handle = dln2_pdata->handle;
+
+       return _dln2_transfer(dln2, handle, cmd, obuf, obuf_len, ibuf,
+                             ibuf_len);
+}
+EXPORT_SYMBOL(dln2_transfer);
+
+static int dln2_check_hw(struct dln2_dev *dln2)
+{
+       int ret;
+       __le32 hw_type;
+       int len = sizeof(hw_type);
+
+       ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_VER,
+                            NULL, 0, &hw_type, &len);
+       if (ret < 0)
+               return ret;
+       if (len < sizeof(hw_type))
+               return -EREMOTEIO;
+
+       if (le32_to_cpu(hw_type) != DLN2_HW_ID) {
+               dev_err(&dln2->interface->dev, "Device ID 0x%x not supported\n",
+                       le32_to_cpu(hw_type));
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int dln2_print_serialno(struct dln2_dev *dln2)
+{
+       int ret;
+       __le32 serial_no;
+       int len = sizeof(serial_no);
+       struct device *dev = &dln2->interface->dev;
+
+       ret = _dln2_transfer(dln2, DLN2_HANDLE_CTRL, CMD_GET_DEVICE_SN, NULL, 0,
+                            &serial_no, &len);
+       if (ret < 0)
+               return ret;
+       if (len < sizeof(serial_no))
+               return -EREMOTEIO;
+
+       dev_info(dev, "Diolan DLN2 serial %u\n", le32_to_cpu(serial_no));
+
+       return 0;
+}
+
+static int dln2_hw_init(struct dln2_dev *dln2)
+{
+       int ret;
+
+       ret = dln2_check_hw(dln2);
+       if (ret < 0)
+               return ret;
+
+       return dln2_print_serialno(dln2);
+}
+
+static void dln2_free_rx_urbs(struct dln2_dev *dln2)
+{
+       int i;
+
+       for (i = 0; i < DLN2_MAX_URBS; i++) {
+               usb_kill_urb(dln2->rx_urb[i]);
+               usb_free_urb(dln2->rx_urb[i]);
+               kfree(dln2->rx_buf[i]);
+       }
+}
+
+static void dln2_free(struct dln2_dev *dln2)
+{
+       dln2_free_rx_urbs(dln2);
+       usb_put_dev(dln2->usb_dev);
+       kfree(dln2);
+}
+
+static int dln2_setup_rx_urbs(struct dln2_dev *dln2,
+                             struct usb_host_interface *hostif)
+{
+       int i;
+       int ret;
+       const int rx_max_size = DLN2_RX_BUF_SIZE;
+       struct device *dev = &dln2->interface->dev;
+
+       for (i = 0; i < DLN2_MAX_URBS; i++) {
+               dln2->rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL);
+               if (!dln2->rx_buf[i])
+                       return -ENOMEM;
+
+               dln2->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
+               if (!dln2->rx_urb[i])
+                       return -ENOMEM;
+
+               usb_fill_bulk_urb(dln2->rx_urb[i], dln2->usb_dev,
+                                 usb_rcvbulkpipe(dln2->usb_dev, dln2->ep_in),
+                                 dln2->rx_buf[i], rx_max_size, dln2_rx, dln2);
+
+               ret = usb_submit_urb(dln2->rx_urb[i], GFP_KERNEL);
+               if (ret < 0) {
+                       dev_err(dev, "failed to submit RX URB: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static struct dln2_platform_data dln2_pdata_gpio = {
+       .handle = DLN2_HANDLE_GPIO,
+};
+
+/* Only one I2C port seems to be supported on current hardware */
+static struct dln2_platform_data dln2_pdata_i2c = {
+       .handle = DLN2_HANDLE_I2C,
+       .port = 0,
+};
+
+/* Only one SPI port supported */
+static struct dln2_platform_data dln2_pdata_spi = {
+       .handle = DLN2_HANDLE_SPI,
+       .port = 0,
+};
+
+static const struct mfd_cell dln2_devs[] = {
+       {
+               .name = "dln2-gpio",
+               .platform_data = &dln2_pdata_gpio,
+               .pdata_size = sizeof(struct dln2_platform_data),
+       },
+       {
+               .name = "dln2-i2c",
+               .platform_data = &dln2_pdata_i2c,
+               .pdata_size = sizeof(struct dln2_platform_data),
+       },
+       {
+               .name = "dln2-spi",
+               .platform_data = &dln2_pdata_spi,
+               .pdata_size = sizeof(struct dln2_platform_data),
+       },
+};
+
+static void dln2_disconnect(struct usb_interface *interface)
+{
+       struct dln2_dev *dln2 = usb_get_intfdata(interface);
+       int i, j;
+
+       /* don't allow starting new transfers */
+       spin_lock(&dln2->disconnect_lock);
+       dln2->disconnect = true;
+       spin_unlock(&dln2->disconnect_lock);
+
+       /* cancel in progress transfers */
+       for (i = 0; i < DLN2_HANDLES; i++) {
+               struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[i];
+               unsigned long flags;
+
+               spin_lock_irqsave(&rxs->lock, flags);
+
+               /* cancel all response waiters */
+               for (j = 0; j < DLN2_MAX_RX_SLOTS; j++) {
+                       struct dln2_rx_context *rxc = &rxs->slots[j];
+
+                       if (rxc->in_use)
+                               complete(&rxc->done);
+               }
+
+               spin_unlock_irqrestore(&rxs->lock, flags);
+       }
+
+       /* wait for transfers to end */
+       wait_event(dln2->disconnect_wq, !dln2->active_transfers);
+
+       mfd_remove_devices(&interface->dev);
+
+       dln2_free(dln2);
+}
+
+static int dln2_probe(struct usb_interface *interface,
+                     const struct usb_device_id *usb_id)
+{
+       struct usb_host_interface *hostif = interface->cur_altsetting;
+       struct device *dev = &interface->dev;
+       struct dln2_dev *dln2;
+       int ret;
+       int i, j;
+
+       if (hostif->desc.bInterfaceNumber != 0 ||
+           hostif->desc.bNumEndpoints < 2)
+               return -ENODEV;
+
+       dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL);
+       if (!dln2)
+               return -ENOMEM;
+
+       dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
+       dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
+       dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface));
+       dln2->interface = interface;
+       usb_set_intfdata(interface, dln2);
+       init_waitqueue_head(&dln2->disconnect_wq);
+
+       for (i = 0; i < DLN2_HANDLES; i++) {
+               init_waitqueue_head(&dln2->mod_rx_slots[i].wq);
+               spin_lock_init(&dln2->mod_rx_slots[i].lock);
+               for (j = 0; j < DLN2_MAX_RX_SLOTS; j++)
+                       init_completion(&dln2->mod_rx_slots[i].slots[j].done);
+       }
+
+       spin_lock_init(&dln2->event_cb_lock);
+       spin_lock_init(&dln2->disconnect_lock);
+       INIT_LIST_HEAD(&dln2->event_cb_list);
+
+       ret = dln2_setup_rx_urbs(dln2, hostif);
+       if (ret)
+               goto out_cleanup;
+
+       ret = dln2_hw_init(dln2);
+       if (ret < 0) {
+               dev_err(dev, "failed to initialize hardware\n");
+               goto out_cleanup;
+       }
+
+       ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs));
+       if (ret != 0) {
+               dev_err(dev, "failed to add mfd devices to core\n");
+               goto out_cleanup;
+       }
+
+       return 0;
+
+out_cleanup:
+       dln2_free(dln2);
+
+       return ret;
+}
+
+static const struct usb_device_id dln2_table[] = {
+       { USB_DEVICE(0xa257, 0x2013) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(usb, dln2_table);
+
+static struct usb_driver dln2_driver = {
+       .name = "dln2",
+       .probe = dln2_probe,
+       .disconnect = dln2_disconnect,
+       .id_table = dln2_table,
+};
+
+module_usb_driver(dln2_driver);
+
+MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>");
+MODULE_DESCRIPTION("Core driver for the Diolan DLN2 interface adapter");
+MODULE_LICENSE("GPL v2");
index c980da479a358ac810929bf07737a1eb516516d1..5c38df35a84d0e649882304811874e26f045ddda 100644 (file)
@@ -193,11 +193,7 @@ static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
-       ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
-       if (ret)
-               mfd_remove_devices(&dev->dev);
-
-       return ret;
+       return mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
 }
 
 static void lpc_sch_remove(struct pci_dev *dev)
index de96b7fb1f6d8e94c95230e090a0e415e281cbaa..3bf8def82f1ef7225e22ec9c1da69a6e4f8e1413 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * max14577.c - mfd core driver for the Maxim 14577/77836
  *
- * Copyright (C) 2014 Samsung Electrnoics
+ * Copyright (C) 2014 Samsung Electronics
  * Chanwoo Choi <cw00.choi@samsung.com>
  * Krzysztof Kozlowski <k.kozlowski@samsung.com>
  *
index cf008f45968c77fad5cf64677adf1adc77c77b46..a159593e27a0c42dd751ad24ae38026b6694c885 100644 (file)
 
 static const struct mfd_cell max77693_devs[] = {
        { .name = "max77693-pmic", },
-       { .name = "max77693-charger", },
+       {
+               .name = "max77693-charger",
+               .of_compatible = "maxim,max77693-charger",
+       },
        { .name = "max77693-muic", },
-       { .name = "max77693-haptic", },
+       {
+               .name = "max77693-haptic",
+               .of_compatible = "maxim,max77693-haptic",
+       },
        {
                .name = "max77693-flash",
                .of_compatible = "maxim,max77693-flash",
@@ -147,6 +153,12 @@ static const struct regmap_irq_chip max77693_muic_irq_chip = {
        .num_irqs               = ARRAY_SIZE(max77693_muic_irqs),
 };
 
+static const struct regmap_config max77693_regmap_haptic_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = MAX77693_HAPTIC_REG_END,
+};
+
 static int max77693_i2c_probe(struct i2c_client *i2c,
                              const struct i2c_device_id *id)
 {
@@ -196,6 +208,15 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
        }
        i2c_set_clientdata(max77693->haptic, max77693);
 
+       max77693->regmap_haptic = devm_regmap_init_i2c(max77693->haptic,
+                                       &max77693_regmap_haptic_config);
+       if (IS_ERR(max77693->regmap_haptic)) {
+               ret = PTR_ERR(max77693->regmap_haptic);
+               dev_err(max77693->dev,
+                       "failed to initialize haptic register map: %d\n", ret);
+               goto err_regmap;
+       }
+
        /*
         * Initialize register map for MUIC device because use regmap-muic
         * instance of MUIC device when irq of max77693 is initialized
@@ -207,7 +228,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
                ret = PTR_ERR(max77693->regmap_muic);
                dev_err(max77693->dev,
                        "failed to allocate register map: %d\n", ret);
-               goto err_regmap_muic;
+               goto err_regmap;
        }
 
        ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
@@ -217,7 +238,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
                                &max77693->irq_data_led);
        if (ret) {
                dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
-               goto err_regmap_muic;
+               goto err_regmap;
        }
 
        ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
@@ -240,7 +261,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
                goto err_irq_charger;
        }
 
-       ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
+       ret = regmap_add_irq_chip(max77693->regmap_muic, max77693->irq,
                                IRQF_ONESHOT | IRQF_SHARED |
                                IRQF_TRIGGER_FALLING, 0,
                                &max77693_muic_irq_chip,
@@ -250,6 +271,17 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
                goto err_irq_muic;
        }
 
+       /* Unmask interrupts from all blocks in interrupt source register */
+       ret = regmap_update_bits(max77693->regmap,
+                               MAX77693_PMIC_REG_INTSRC_MASK,
+                               SRC_IRQ_ALL, (unsigned int)~SRC_IRQ_ALL);
+       if (ret < 0) {
+               dev_err(max77693->dev,
+                       "Could not unmask interrupts in INTSRC: %d\n",
+                       ret);
+               goto err_intsrc;
+       }
+
        pm_runtime_set_active(max77693->dev);
 
        ret = mfd_add_devices(max77693->dev, -1, max77693_devs,
@@ -261,6 +293,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
 
 err_mfd:
        mfd_remove_devices(max77693->dev);
+err_intsrc:
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_muic);
 err_irq_muic:
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_charger);
@@ -268,7 +301,7 @@ err_irq_charger:
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
 err_irq_topsys:
        regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
-err_regmap_muic:
+err_regmap:
        i2c_unregister_device(max77693->haptic);
 err_i2c_haptic:
        i2c_unregister_device(max77693->muic);
index f3338fe9d0691832ba9e13b984bf7aa428e65339..2a87f69be53db0a4ca1951fd7cbc3d7733e44007 100644 (file)
@@ -125,9 +125,15 @@ static int mfd_add_device(struct device *parent, int id,
        struct platform_device *pdev;
        struct device_node *np = NULL;
        int ret = -ENOMEM;
+       int platform_id;
        int r;
 
-       pdev = platform_device_alloc(cell->name, id + cell->id);
+       if (id < 0)
+               platform_id = id;
+       else
+               platform_id = id + cell->id;
+
+       pdev = platform_device_alloc(cell->name, platform_id);
        if (!pdev)
                goto fail_alloc;
 
index 9c8eec80ceed53bef339da4c9778ea224c1b9c99..32407404d838f20c26977cee722c3876ccf9fd59 100644 (file)
@@ -130,6 +130,12 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
 
 static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
 {
+       int err;
+
+       err = rtsx_gops_pm_reset(pcr);
+       if (err < 0)
+               return err;
+
        /* Optimize RX sensitivity */
        return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
 }
index 573de7bfcced0be23098434759a16505291f0e75..cf425cc959d5dfb64b1bf6179ceb64e03b051d28 100644 (file)
@@ -130,6 +130,10 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
 {
        int err;
 
+       err = rtsx_gops_pm_reset(pcr);
+       if (err < 0)
+               return err;
+
        err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV,
                        PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED |
                        PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN |
diff --git a/drivers/mfd/rtsx_gops.c b/drivers/mfd/rtsx_gops.c
new file mode 100644 (file)
index 0000000..b1a98c6
--- /dev/null
@@ -0,0 +1,37 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, 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/>.
+ *
+ * Author:
+ *   Micky Ching <micky_ching@realsil.com.cn>
+ */
+
+#include <linux/mfd/rtsx_pci.h>
+#include "rtsx_pcr.h"
+
+int rtsx_gops_pm_reset(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       /* init aspm */
+       rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0x00);
+       err = rtsx_pci_update_cfg_byte(pcr, LCTLR, ~LCTLR_ASPM_CTL_MASK, 0x00);
+       if (err < 0)
+               return err;
+
+       /* reset PM_CTRL3 before send buffer cmd */
+       return rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
+}
index f2643c221d345ebca0b7a9ff3266443ac1f0801b..30f7ca89a0e68619319f69dcebb12037f6e4af92 100644 (file)
@@ -947,6 +947,7 @@ static void rtsx_pci_idle_work(struct work_struct *work)
        mutex_unlock(&pcr->pcr_mutex);
 }
 
+#ifdef CONFIG_PM
 static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state)
 {
        if (pcr->ops->turn_off_led)
@@ -961,6 +962,7 @@ static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state)
        if (pcr->ops->force_power_down)
                pcr->ops->force_power_down(pcr, pm_state);
 }
+#endif
 
 static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
 {
index 07e4c2ebf05a23dbd5543ce220d41a00eccf3956..fe2bbb67defcd24fddfa0842b7584b4daad0dcb4 100644 (file)
@@ -72,4 +72,7 @@ do {                                                                  \
        pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
 } while (0)
 
+/* generic operations */
+int rtsx_gops_pm_reset(struct rtsx_pcr *pcr);
+
 #endif
index 9cf98d142d9acff26ba0ada4b3f3e2107a8218e8..dbdd0faeb6ce500678d9dc4f014504560693bded 100644 (file)
@@ -647,8 +647,8 @@ static int rtsx_usb_probe(struct usb_interface *intf,
        /* initialize USB SG transfer timer */
        setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
 
-       ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells,
-                       ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL);
+       ret = mfd_add_hotplug_devices(&intf->dev, rtsx_usb_cells,
+                                     ARRAY_SIZE(rtsx_usb_cells));
        if (ret)
                goto out_init_fail;
 
index dba7e2b6f8e9d949c7c3de18299625448ecd86d8..0a7bc43db4e47fe961ff6502c8972b280dbc1825 100644 (file)
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/s2mpa01.h>
 #include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s5m8763.h>
 #include <linux/mfd/samsung/s5m8767.h>
-#include <linux/regulator/machine.h>
 #include <linux/regmap.h>
 
 static const struct mfd_cell s5m8751_devs[] = {
@@ -74,6 +74,15 @@ static const struct mfd_cell s2mps11_devs[] = {
        }
 };
 
+static const struct mfd_cell s2mps13_devs[] = {
+       { .name = "s2mps13-pmic", },
+       { .name = "s2mps13-rtc", },
+       {
+               .name = "s2mps13-clk",
+               .of_compatible = "samsung,s2mps13-clk",
+       },
+};
+
 static const struct mfd_cell s2mps14_devs[] = {
        {
                .name = "s2mps14-pmic",
@@ -107,6 +116,9 @@ static const struct of_device_id sec_dt_match[] = {
        }, {
                .compatible = "samsung,s2mps11-pmic",
                .data = (void *)S2MPS11X,
+       }, {
+               .compatible = "samsung,s2mps13-pmic",
+               .data = (void *)S2MPS13X,
        }, {
                .compatible = "samsung,s2mps14-pmic",
                .data = (void *)S2MPS14X,
@@ -194,6 +206,15 @@ static const struct regmap_config s2mps11_regmap_config = {
        .cache_type = REGCACHE_FLAT,
 };
 
+static const struct regmap_config s2mps13_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+
+       .max_register = S2MPS13_REG_LDODSCH5,
+       .volatile_reg = s2mps11_volatile,
+       .cache_type = REGCACHE_FLAT,
+};
+
 static const struct regmap_config s2mps14_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -325,6 +346,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        case S2MPS11X:
                regmap = &s2mps11_regmap_config;
                break;
+       case S2MPS13X:
+               regmap = &s2mps13_regmap_config;
+               break;
        case S2MPS14X:
                regmap = &s2mps14_regmap_config;
                break;
@@ -378,6 +402,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
                sec_devs = s2mps11_devs;
                num_sec_devs = ARRAY_SIZE(s2mps11_devs);
                break;
+       case S2MPS13X:
+               sec_devs = s2mps13_devs;
+               num_sec_devs = ARRAY_SIZE(s2mps13_devs);
+               break;
        case S2MPS14X:
                sec_devs = s2mps14_devs;
                num_sec_devs = ARRAY_SIZE(s2mps14_devs);
@@ -432,15 +460,6 @@ static int sec_pmic_suspend(struct device *dev)
         */
        disable_irq(sec_pmic->irq);
 
-       switch (sec_pmic->device_type) {
-       case S2MPS14X:
-       case S2MPU02:
-               regulator_suspend_prepare(PM_SUSPEND_MEM);
-               break;
-       default:
-               break;
-       }
-
        return 0;
 }
 
index f9a57869e3ece6f842ce7f99fd176d1cfea796b7..ba86a918c2dace19be14235f484f380a970d667e 100644 (file)
@@ -389,14 +389,22 @@ static const struct regmap_irq_chip s2mps11_irq_chip = {
        .ack_base = S2MPS11_REG_INT1,
 };
 
+#define S2MPS1X_IRQ_CHIP_COMMON_DATA           \
+       .irqs = s2mps14_irqs,                   \
+       .num_irqs = ARRAY_SIZE(s2mps14_irqs),   \
+       .num_regs = 3,                          \
+       .status_base = S2MPS14_REG_INT1,        \
+       .mask_base = S2MPS14_REG_INT1M,         \
+       .ack_base = S2MPS14_REG_INT1            \
+
+static const struct regmap_irq_chip s2mps13_irq_chip = {
+       .name = "s2mps13",
+       S2MPS1X_IRQ_CHIP_COMMON_DATA,
+};
+
 static const struct regmap_irq_chip s2mps14_irq_chip = {
        .name = "s2mps14",
-       .irqs = s2mps14_irqs,
-       .num_irqs = ARRAY_SIZE(s2mps14_irqs),
-       .num_regs = 3,
-       .status_base = S2MPS14_REG_INT1,
-       .mask_base = S2MPS14_REG_INT1M,
-       .ack_base = S2MPS14_REG_INT1,
+       S2MPS1X_IRQ_CHIP_COMMON_DATA,
 };
 
 static const struct regmap_irq_chip s2mpu02_irq_chip = {
@@ -452,6 +460,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
        case S2MPS11X:
                sec_irq_chip = &s2mps11_irq_chip;
                break;
+       case S2MPS13X:
+               sec_irq_chip = &s2mps13_irq_chip;
+               break;
        case S2MPS14X:
                sec_irq_chip = &s2mps14_irq_chip;
                break;
index 2d045f26f193eb0e96ecf32ee1cc1f07b39ca99c..bee0abf82040001664c07e82c646e0e3e5afc259 100644 (file)
@@ -269,7 +269,7 @@ int stmpe_remove(struct stmpe *stmpe);
 #define STMPE24XX_REG_CHIP_ID          0x80
 #define STMPE24XX_REG_IEGPIOR_LSB      0x18
 #define STMPE24XX_REG_ISGPIOR_MSB      0x19
-#define STMPE24XX_REG_GPMR_LSB         0xA5
+#define STMPE24XX_REG_GPMR_LSB         0xA4
 #define STMPE24XX_REG_GPSR_LSB         0x85
 #define STMPE24XX_REG_GPCR_LSB         0x88
 #define STMPE24XX_REG_GPDR_LSB         0x8B
index ca15878ce5c09ea8c9f2f20c8634c0613ee2cb61..72373b1138857769a56f510600ef0a221591808a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/list.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
+#include <linux/slab.h>
 
 static struct platform_driver syscon_driver;
 
+static DEFINE_SPINLOCK(syscon_list_slock);
+static LIST_HEAD(syscon_list);
+
 struct syscon {
+       struct device_node *np;
        struct regmap *regmap;
+       struct list_head list;
+};
+
+static struct regmap_config syscon_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
 };
 
-static int syscon_match_node(struct device *dev, void *data)
+static struct syscon *of_syscon_register(struct device_node *np)
 {
-       struct device_node *dn = data;
+       struct syscon *syscon;
+       struct regmap *regmap;
+       void __iomem *base;
+       int ret;
+       struct regmap_config syscon_config = syscon_regmap_config;
+
+       if (!of_device_is_compatible(np, "syscon"))
+               return ERR_PTR(-EINVAL);
+
+       syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
+       if (!syscon)
+               return ERR_PTR(-ENOMEM);
+
+       base = of_iomap(np, 0);
+       if (!base) {
+               ret = -ENOMEM;
+               goto err_map;
+       }
+
+       /* Parse the device's DT node for an endianness specification */
+       if (of_property_read_bool(np, "big-endian"))
+               syscon_config.val_format_endian = REGMAP_ENDIAN_BIG;
+        else if (of_property_read_bool(np, "little-endian"))
+               syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;
+
+       regmap = regmap_init_mmio(NULL, base, &syscon_config);
+       if (IS_ERR(regmap)) {
+               pr_err("regmap init failed\n");
+               ret = PTR_ERR(regmap);
+               goto err_regmap;
+       }
+
+       syscon->regmap = regmap;
+       syscon->np = np;
+
+       spin_lock(&syscon_list_slock);
+       list_add_tail(&syscon->list, &syscon_list);
+       spin_unlock(&syscon_list_slock);
 
-       return (dev->of_node == dn) ? 1 : 0;
+       return syscon;
+
+err_regmap:
+       iounmap(base);
+err_map:
+       kfree(syscon);
+       return ERR_PTR(ret);
 }
 
 struct regmap *syscon_node_to_regmap(struct device_node *np)
 {
-       struct syscon *syscon;
-       struct device *dev;
+       struct syscon *entry, *syscon = NULL;
 
-       dev = driver_find_device(&syscon_driver.driver, NULL, np,
-                                syscon_match_node);
-       if (!dev)
-               return ERR_PTR(-EPROBE_DEFER);
+       spin_lock(&syscon_list_slock);
 
-       syscon = dev_get_drvdata(dev);
+       list_for_each_entry(entry, &syscon_list, list)
+               if (entry->np == np) {
+                       syscon = entry;
+                       break;
+               }
+
+       spin_unlock(&syscon_list_slock);
+
+       if (!syscon)
+               syscon = of_syscon_register(np);
+
+       if (IS_ERR(syscon))
+               return ERR_CAST(syscon);
 
        return syscon->regmap;
 }
@@ -110,17 +174,6 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
 }
 EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
 
-static const struct of_device_id of_syscon_match[] = {
-       { .compatible = "syscon", },
-       { },
-};
-
-static struct regmap_config syscon_regmap_config = {
-       .reg_bits = 32,
-       .val_bits = 32,
-       .reg_stride = 4,
-};
-
 static int syscon_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -167,7 +220,6 @@ static struct platform_driver syscon_driver = {
        .driver = {
                .name = "syscon",
                .owner = THIS_MODULE,
-               .of_match_table = of_syscon_match,
        },
        .probe          = syscon_probe,
        .id_table       = syscon_ids,
index 9e04a74859818bd0016dfd6a60bbcd94669a4248..439d905bb219cdae6973413746a1e409e9f657a3 100644 (file)
@@ -87,7 +87,7 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
        unsigned long flags;
        u8 dev_ctl;
 
-       clk_enable(t7l66xb->clk32k);
+       clk_prepare_enable(t7l66xb->clk32k);
 
        spin_lock_irqsave(&t7l66xb->lock, flags);
 
@@ -118,7 +118,7 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
 
        spin_unlock_irqrestore(&t7l66xb->lock, flags);
 
-       clk_disable(t7l66xb->clk32k);
+       clk_disable_unprepare(t7l66xb->clk32k);
 
        return 0;
 }
@@ -285,7 +285,7 @@ static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
 
        if (pdata && pdata->suspend)
                pdata->suspend(dev);
-       clk_disable(t7l66xb->clk48m);
+       clk_disable_unprepare(t7l66xb->clk48m);
 
        return 0;
 }
@@ -295,7 +295,7 @@ static int t7l66xb_resume(struct platform_device *dev)
        struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
        struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 
-       clk_enable(t7l66xb->clk48m);
+       clk_prepare_enable(t7l66xb->clk48m);
        if (pdata && pdata->resume)
                pdata->resume(dev);
 
@@ -369,7 +369,7 @@ static int t7l66xb_probe(struct platform_device *dev)
                goto err_ioremap;
        }
 
-       clk_enable(t7l66xb->clk48m);
+       clk_prepare_enable(t7l66xb->clk48m);
 
        if (pdata && pdata->enable)
                pdata->enable(dev);
@@ -414,9 +414,9 @@ static int t7l66xb_remove(struct platform_device *dev)
        int ret;
 
        ret = pdata->disable(dev);
-       clk_disable(t7l66xb->clk48m);
+       clk_disable_unprepare(t7l66xb->clk48m);
        clk_put(t7l66xb->clk48m);
-       clk_disable(t7l66xb->clk32k);
+       clk_disable_unprepare(t7l66xb->clk32k);
        clk_put(t7l66xb->clk32k);
        t7l66xb_detach_irq(dev);
        iounmap(t7l66xb->scr);
index 0072e668c208abc22608b245395323f7122f3283..aacb3720065c5e1d924d0d007755671b993cf84b 100644 (file)
@@ -241,10 +241,8 @@ static struct irq_domain_ops tc3589x_irq_ops = {
 
 static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
 {
-       int base = tc3589x->irq_base;
-
        tc3589x->domain = irq_domain_add_simple(
-               np, TC3589x_NR_INTERNAL_IRQS, base,
+               np, TC3589x_NR_INTERNAL_IRQS, 0,
                &tc3589x_irq_ops, tc3589x);
 
        if (!tc3589x->domain) {
@@ -298,7 +296,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
        if (blocks & TC3589x_BLOCK_GPIO) {
                ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
                                      ARRAY_SIZE(tc3589x_dev_gpio), NULL,
-                                     tc3589x->irq_base, tc3589x->domain);
+                                     0, tc3589x->domain);
                if (ret) {
                        dev_err(tc3589x->dev, "failed to add gpio child\n");
                        return ret;
@@ -309,7 +307,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
        if (blocks & TC3589x_BLOCK_KEYPAD) {
                ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
                                      ARRAY_SIZE(tc3589x_dev_keypad), NULL,
-                                     tc3589x->irq_base, tc3589x->domain);
+                                     0, tc3589x->domain);
                if (ret) {
                        dev_err(tc3589x->dev, "failed to keypad child\n");
                        return ret;
@@ -404,7 +402,6 @@ static int tc3589x_probe(struct i2c_client *i2c,
        tc3589x->dev = &i2c->dev;
        tc3589x->i2c = i2c;
        tc3589x->pdata = pdata;
-       tc3589x->irq_base = pdata->irq_base;
 
        switch (version) {
        case TC3589X_TC35893:
index e71f88000ae5f65fd39d1fddec86ff58e9fb5047..85fab3729102545ddf0ac609f78f29804ae19846 100644 (file)
@@ -52,7 +52,7 @@ static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
 
        if (pdata && pdata->suspend)
                pdata->suspend(dev);
-       clk_disable(tc6387xb->clk32k);
+       clk_disable_unprepare(tc6387xb->clk32k);
 
        return 0;
 }
@@ -62,7 +62,7 @@ static int tc6387xb_resume(struct platform_device *dev)
        struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
        struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 
-       clk_enable(tc6387xb->clk32k);
+       clk_prepare_enable(tc6387xb->clk32k);
        if (pdata && pdata->resume)
                pdata->resume(dev);
 
@@ -100,7 +100,7 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
        struct platform_device *dev      = to_platform_device(mmc->dev.parent);
        struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
 
-       clk_enable(tc6387xb->clk32k);
+       clk_prepare_enable(tc6387xb->clk32k);
 
        tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
                tc6387xb_mmc_resources[0].start & 0xfffe);
@@ -113,7 +113,7 @@ static int tc6387xb_mmc_disable(struct platform_device *mmc)
        struct platform_device *dev      = to_platform_device(mmc->dev.parent);
        struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
 
-       clk_disable(tc6387xb->clk32k);
+       clk_disable_unprepare(tc6387xb->clk32k);
 
        return 0;
 }
@@ -214,7 +214,7 @@ static int tc6387xb_remove(struct platform_device *dev)
        mfd_remove_devices(&dev->dev);
        iounmap(tc6387xb->scr);
        release_resource(&tc6387xb->rscr);
-       clk_disable(tc6387xb->clk32k);
+       clk_disable_unprepare(tc6387xb->clk32k);
        clk_put(tc6387xb->clk32k);
        kfree(tc6387xb);
 
index 4fac16bcd7320dd495ebdf9683ee6bb6d3db76dd..d35f11fbeab7708aa1419fce0172a29c65313cb4 100644 (file)
@@ -263,6 +263,17 @@ static int tc6393xb_ohci_disable(struct platform_device *dev)
        return 0;
 }
 
+static int tc6393xb_ohci_suspend(struct platform_device *dev)
+{
+       struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent);
+
+       /* We can't properly store/restore OHCI state, so fail here */
+       if (tcpd->resume_restore)
+               return -EBUSY;
+
+       return tc6393xb_ohci_disable(dev);
+}
+
 static int tc6393xb_fb_enable(struct platform_device *dev)
 {
        struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
@@ -403,7 +414,7 @@ static struct mfd_cell tc6393xb_cells[] = {
                .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
                .resources = tc6393xb_ohci_resources,
                .enable = tc6393xb_ohci_enable,
-               .suspend = tc6393xb_ohci_disable,
+               .suspend = tc6393xb_ohci_suspend,
                .resume = tc6393xb_ohci_enable,
                .disable = tc6393xb_ohci_disable,
        },
@@ -654,7 +665,7 @@ static int tc6393xb_probe(struct platform_device *dev)
                goto err_ioremap;
        }
 
-       ret = clk_enable(tc6393xb->clk);
+       ret = clk_prepare_enable(tc6393xb->clk);
        if (ret)
                goto err_clk_enable;
 
@@ -717,7 +728,7 @@ err_gpio_add:
                gpiochip_remove(&tc6393xb->gpio);
        tcpd->disable(dev);
 err_enable:
-       clk_disable(tc6393xb->clk);
+       clk_disable_unprepare(tc6393xb->clk);
 err_clk_enable:
        iounmap(tc6393xb->scr);
 err_ioremap:
@@ -748,7 +759,7 @@ static int tc6393xb_remove(struct platform_device *dev)
                gpiochip_remove(&tc6393xb->gpio);
 
        ret = tcpd->disable(dev);
-       clk_disable(tc6393xb->clk);
+       clk_disable_unprepare(tc6393xb->clk);
        iounmap(tc6393xb->scr);
        release_resource(&tc6393xb->rscr);
        clk_put(tc6393xb->clk);
@@ -776,7 +787,7 @@ static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
                        ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
        }
        ret = tcpd->suspend(dev);
-       clk_disable(tc6393xb->clk);
+       clk_disable_unprepare(tc6393xb->clk);
 
        return ret;
 }
@@ -788,7 +799,7 @@ static int tc6393xb_resume(struct platform_device *dev)
        int ret;
        int i;
 
-       clk_enable(tc6393xb->clk);
+       clk_prepare_enable(tc6393xb->clk);
 
        ret = tcpd->resume(dev);
        if (ret)
index 1c3e6e2efe410812d7fd0a58b9b940be47a5ecbc..14b62e11aff47277daea2f6856b0a7bbaa4fd374 100644 (file)
@@ -76,58 +76,58 @@ static struct mfd_cell tps65090s[] = {
 static const struct regmap_irq tps65090_irqs[] = {
        /* INT1 IRQs*/
        [TPS65090_IRQ_VAC_STATUS_CHANGE] = {
-                       .mask = TPS65090_INT1_MASK_VAC_STATUS_CHANGE,
+               .mask = TPS65090_INT1_MASK_VAC_STATUS_CHANGE,
        },
        [TPS65090_IRQ_VSYS_STATUS_CHANGE] = {
-                       .mask = TPS65090_INT1_MASK_VSYS_STATUS_CHANGE,
+               .mask = TPS65090_INT1_MASK_VSYS_STATUS_CHANGE,
        },
        [TPS65090_IRQ_BAT_STATUS_CHANGE] = {
-                       .mask = TPS65090_INT1_MASK_BAT_STATUS_CHANGE,
+               .mask = TPS65090_INT1_MASK_BAT_STATUS_CHANGE,
        },
        [TPS65090_IRQ_CHARGING_STATUS_CHANGE] = {
-                       .mask = TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE,
+               .mask = TPS65090_INT1_MASK_CHARGING_STATUS_CHANGE,
        },
        [TPS65090_IRQ_CHARGING_COMPLETE] = {
-                       .mask = TPS65090_INT1_MASK_CHARGING_COMPLETE,
+               .mask = TPS65090_INT1_MASK_CHARGING_COMPLETE,
        },
        [TPS65090_IRQ_OVERLOAD_DCDC1] = {
-                       .mask = TPS65090_INT1_MASK_OVERLOAD_DCDC1,
+               .mask = TPS65090_INT1_MASK_OVERLOAD_DCDC1,
        },
        [TPS65090_IRQ_OVERLOAD_DCDC2] = {
-                       .mask = TPS65090_INT1_MASK_OVERLOAD_DCDC2,
+               .mask = TPS65090_INT1_MASK_OVERLOAD_DCDC2,
        },
        /* INT2 IRQs*/
        [TPS65090_IRQ_OVERLOAD_DCDC3] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_DCDC3,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_DCDC3,
        },
        [TPS65090_IRQ_OVERLOAD_FET1] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_FET1,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_FET1,
        },
        [TPS65090_IRQ_OVERLOAD_FET2] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_FET2,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_FET2,
        },
        [TPS65090_IRQ_OVERLOAD_FET3] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_FET3,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_FET3,
        },
        [TPS65090_IRQ_OVERLOAD_FET4] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_FET4,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_FET4,
        },
        [TPS65090_IRQ_OVERLOAD_FET5] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_FET5,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_FET5,
        },
        [TPS65090_IRQ_OVERLOAD_FET6] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_FET6,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_FET6,
        },
        [TPS65090_IRQ_OVERLOAD_FET7] = {
-                       .reg_offset = 1,
-                       .mask = TPS65090_INT2_MASK_OVERLOAD_FET7,
+               .reg_offset = 1,
+               .mask = TPS65090_INT2_MASK_OVERLOAD_FET7,
        },
 };
 
@@ -176,7 +176,7 @@ MODULE_DEVICE_TABLE(of, tps65090_of_match);
 #endif
 
 static int tps65090_i2c_probe(struct i2c_client *client,
-                                       const struct i2c_device_id *id)
+                             const struct i2c_device_id *id)
 {
        struct tps65090_platform_data *pdata = dev_get_platdata(&client->dev);
        int irq_base = 0;
@@ -210,11 +210,11 @@ static int tps65090_i2c_probe(struct i2c_client *client,
 
        if (client->irq) {
                ret = regmap_add_irq_chip(tps65090->rmap, client->irq,
-                       IRQF_ONESHOT | IRQF_TRIGGER_LOW, irq_base,
-                       &tps65090_irq_chip, &tps65090->irq_data);
-                       if (ret) {
-                               dev_err(&client->dev,
-                                       "IRQ init failed with err: %d\n", ret);
+                                         IRQF_ONESHOT | IRQF_TRIGGER_LOW, irq_base,
+                                         &tps65090_irq_chip, &tps65090->irq_data);
+               if (ret) {
+                       dev_err(&client->dev,
+                               "IRQ init failed with err: %d\n", ret);
                        return ret;
                }
        } else {
@@ -223,8 +223,8 @@ static int tps65090_i2c_probe(struct i2c_client *client,
        }
 
        ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
-               ARRAY_SIZE(tps65090s), NULL,
-               0, regmap_irq_get_domain(tps65090->irq_data));
+                             ARRAY_SIZE(tps65090s), NULL,
+                             0, regmap_irq_get_domain(tps65090->irq_data));
        if (ret) {
                dev_err(&client->dev, "add mfd devices failed with err: %d\n",
                        ret);
index a8ee52c95f2fd4b51c4b6989ad840527739031eb..80a919a8ca975a2783650fe10e3ec18160818559 100644 (file)
 static const struct mfd_cell tps65217s[] = {
        {
                .name = "tps65217-pmic",
+               .of_compatible = "ti,tps65217-pmic",
        },
        {
                .name = "tps65217-bl",
+               .of_compatible = "ti,tps65217-bl",
        },
 };
 
index cf92a6d1c532ac578d6bd9d042f4d1e8ebe55e7c..7d63e324e6a813f4eba762cc462eadbf680ea24f 100644 (file)
@@ -44,6 +44,15 @@ static u8 twl4030_start_script_address = 0x2b;
 #define PWR_DEVSLP             BIT(1)
 #define PWR_DEVOFF             BIT(0)
 
+/* Register bits for CFG_P1_TRANSITION (also for P2 and P3) */
+#define STARTON_SWBUG          BIT(7)  /* Start on watchdog */
+#define STARTON_VBUS           BIT(5)  /* Start on VBUS */
+#define STARTON_VBAT           BIT(4)  /* Start on battery insert */
+#define STARTON_RTC            BIT(3)  /* Start on RTC */
+#define STARTON_USB            BIT(2)  /* Start on USB host */
+#define STARTON_CHG            BIT(1)  /* Start on charger */
+#define STARTON_PWON           BIT(0)  /* Start on PWRON button */
+
 #define SEQ_OFFSYNC            (1 << 0)
 
 #define PHY_TO_OFF_PM_MASTER(p)                (p - 0x36)
@@ -606,6 +615,44 @@ twl4030_power_configure_resources(const struct twl4030_power_data *pdata)
        return 0;
 }
 
+static int twl4030_starton_mask_and_set(u8 bitmask, u8 bitvalues)
+{
+       u8 regs[3] = { TWL4030_PM_MASTER_CFG_P1_TRANSITION,
+                      TWL4030_PM_MASTER_CFG_P2_TRANSITION,
+                      TWL4030_PM_MASTER_CFG_P3_TRANSITION, };
+       u8 val;
+       int i, err;
+
+       err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+                              TWL4030_PM_MASTER_PROTECT_KEY);
+       if (err)
+               goto relock;
+       err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
+                              TWL4030_PM_MASTER_KEY_CFG2,
+                              TWL4030_PM_MASTER_PROTECT_KEY);
+       if (err)
+               goto relock;
+
+       for (i = 0; i < sizeof(regs); i++) {
+               err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER,
+                                     &val, regs[i]);
+               if (err)
+                       break;
+               val = (~bitmask & val) | (bitmask & bitvalues);
+               err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
+                                      val, regs[i]);
+               if (err)
+                       break;
+       }
+
+       if (err)
+               pr_err("TWL4030 Register access failed: %i\n", err);
+
+relock:
+       return twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+                               TWL4030_PM_MASTER_PROTECT_KEY);
+}
+
 /*
  * In master mode, start the power off sequence.
  * After a successful execution, TWL shuts down the power to the SoC
@@ -615,6 +662,11 @@ void twl4030_power_off(void)
 {
        int err;
 
+       /* Disable start on charger or VBUS as it can break poweroff */
+       err = twl4030_starton_mask_and_set(STARTON_VBUS | STARTON_CHG, 0);
+       if (err)
+               pr_err("TWL4030 Unable to configure start-up\n");
+
        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF,
                               TWL4030_PM_MASTER_P1_SW_EVENTS);
        if (err)
@@ -778,6 +830,9 @@ static struct twl4030_power_data osc_off_idle = {
 };
 
 static struct of_device_id twl4030_power_of_match[] = {
+       {
+               .compatible = "ti,twl4030-power",
+       },
        {
                .compatible = "ti,twl4030-power-reset",
                .data = &omap3_reset,
index e00f5340ed872089d31998ff39d6bb57842e731a..e6b3c70aeb22cc919e0fef9f0ba8ad04cd3b56fa 100644 (file)
@@ -93,8 +93,8 @@ static int vprbrd_probe(struct usb_interface *interface,
                 version >> 8, version & 0xff,
                 vb->usb_dev->bus->busnum, vb->usb_dev->devnum);
 
-       ret = mfd_add_devices(&interface->dev, -1, vprbrd_devs,
-                               ARRAY_SIZE(vprbrd_devs), NULL, 0, NULL);
+       ret = mfd_add_hotplug_devices(&interface->dev, vprbrd_devs,
+                                     ARRAY_SIZE(vprbrd_devs));
        if (ret != 0) {
                dev_err(&interface->dev, "Failed to add mfd devices to core.");
                goto error;
index d6f35bbf795b43f75660878532cdd3dbd368cf99..b326a82017ee7f35dfeb0ab3355dda3854c0fc39 100644 (file)
@@ -336,8 +336,6 @@ static const struct reg_default wm5102_reg_default[] = {
        { 0x00000218, 0x01A6 },   /* R536   - Mic Bias Ctrl 1 */ 
        { 0x00000219, 0x01A6 },   /* R537   - Mic Bias Ctrl 2 */ 
        { 0x0000021A, 0x01A6 },   /* R538   - Mic Bias Ctrl 3 */ 
-       { 0x00000225, 0x0400 },   /* R549   - HP Ctrl 1L */
-       { 0x00000226, 0x0400 },   /* R550   - HP Ctrl 1R */
        { 0x00000293, 0x0000 },   /* R659   - Accessory Detect Mode 1 */ 
        { 0x0000029B, 0x0020 },   /* R667   - Headphone Detect 1 */ 
        { 0x0000029C, 0x0000 },   /* R668   - Headphone Detect 2 */
@@ -1112,6 +1110,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_MIC_BIAS_CTRL_1:
        case ARIZONA_MIC_BIAS_CTRL_2:
        case ARIZONA_MIC_BIAS_CTRL_3:
+       case ARIZONA_HP_CTRL_1L:
+       case ARIZONA_HP_CTRL_1R:
        case ARIZONA_ACCESSORY_DETECT_MODE_1:
        case ARIZONA_HEADPHONE_DETECT_1:
        case ARIZONA_HEADPHONE_DETECT_2:
@@ -1949,6 +1949,8 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_DSP1_SCRATCH_1:
        case ARIZONA_DSP1_SCRATCH_2:
        case ARIZONA_DSP1_SCRATCH_3:
+       case ARIZONA_HP_CTRL_1L:
+       case ARIZONA_HP_CTRL_1R:
        case ARIZONA_HEADPHONE_DETECT_2:
        case ARIZONA_HP_DACVAL:
        case ARIZONA_MIC_DETECT_3:
index 4642b5b816a043e723e61373703839bc9d90b7c2..12cad94b40354d8d548ab8974156f8c5c625f4db 100644 (file)
@@ -895,8 +895,16 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000548, 0x1818 },    /* R1352  - AIF2 Frame Ctrl 2 */
        { 0x00000549, 0x0000 },    /* R1353  - AIF2 Frame Ctrl 3 */
        { 0x0000054A, 0x0001 },    /* R1354  - AIF2 Frame Ctrl 4 */
+       { 0x0000054B, 0x0002 },    /* R1355  - AIF2 Frame Ctrl 5 */
+       { 0x0000054C, 0x0003 },    /* R1356  - AIF2 Frame Ctrl 6 */
+       { 0x0000054D, 0x0004 },    /* R1357  - AIF2 Frame Ctrl 7 */
+       { 0x0000054E, 0x0005 },    /* R1358  - AIF2 Frame Ctrl 8 */
        { 0x00000551, 0x0000 },    /* R1361  - AIF2 Frame Ctrl 11 */
        { 0x00000552, 0x0001 },    /* R1362  - AIF2 Frame Ctrl 12 */
+       { 0x00000553, 0x0002 },    /* R1363  - AIF2 Frame Ctrl 13 */
+       { 0x00000554, 0x0003 },    /* R1364  - AIF2 Frame Ctrl 14 */
+       { 0x00000555, 0x0004 },    /* R1365  - AIF2 Frame Ctrl 15 */
+       { 0x00000556, 0x0005 },    /* R1366  - AIF2 Frame Ctrl 16 */
        { 0x00000559, 0x0000 },    /* R1369  - AIF2 Tx Enables */
        { 0x0000055A, 0x0000 },    /* R1370  - AIF2 Rx Enables */
        { 0x00000580, 0x000C },    /* R1408  - AIF3 BCLK Ctrl */
@@ -1790,6 +1798,8 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_MIC_BIAS_CTRL_1:
        case ARIZONA_MIC_BIAS_CTRL_2:
        case ARIZONA_MIC_BIAS_CTRL_3:
+       case ARIZONA_HP_CTRL_1L:
+       case ARIZONA_HP_CTRL_1R:
        case ARIZONA_ACCESSORY_DETECT_MODE_1:
        case ARIZONA_HEADPHONE_DETECT_1:
        case ARIZONA_HEADPHONE_DETECT_2:
@@ -1934,8 +1944,16 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_AIF2_FRAME_CTRL_2:
        case ARIZONA_AIF2_FRAME_CTRL_3:
        case ARIZONA_AIF2_FRAME_CTRL_4:
+       case ARIZONA_AIF2_FRAME_CTRL_5:
+       case ARIZONA_AIF2_FRAME_CTRL_6:
+       case ARIZONA_AIF2_FRAME_CTRL_7:
+       case ARIZONA_AIF2_FRAME_CTRL_8:
        case ARIZONA_AIF2_FRAME_CTRL_11:
        case ARIZONA_AIF2_FRAME_CTRL_12:
+       case ARIZONA_AIF2_FRAME_CTRL_13:
+       case ARIZONA_AIF2_FRAME_CTRL_14:
+       case ARIZONA_AIF2_FRAME_CTRL_15:
+       case ARIZONA_AIF2_FRAME_CTRL_16:
        case ARIZONA_AIF2_TX_ENABLES:
        case ARIZONA_AIF2_RX_ENABLES:
        case ARIZONA_AIF3_BCLK_CTRL:
@@ -2825,6 +2843,8 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
        case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS:
        case ARIZONA_MIC_DETECT_3:
+       case ARIZONA_HP_CTRL_1L:
+       case ARIZONA_HP_CTRL_1R:
        case ARIZONA_HEADPHONE_DETECT_2:
        case ARIZONA_INPUT_ENABLES_STATUS:
        case ARIZONA_OUTPUT_STATUS_1:
index 4ab527f5c53b65ff2872ba07fcef30982a390f3a..f5124a8acad8e06fb8344c718b42d1048a37c455 100644 (file)
@@ -308,7 +308,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
                goto err;
        }
 
-       mode = id2 & WM8350_CONF_STS_MASK >> 10;
+       mode = (id2 & WM8350_CONF_STS_MASK) >> 10;
        cust_id = id2 & WM8350_CUST_ID_MASK;
        chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12;
        dev_info(wm8350->dev,
index 510da3b5232417bb4f216b2ef6555b99cdc564f0..c0c25d75aaccbf3a53218b71d5ea18f0b24c9d0d 100644 (file)
@@ -670,6 +670,7 @@ static const struct reg_default wm8997_reg_default[] = {
        { 0x00000C23, 0x0000 },    /* R3107  - Misc Pad Ctrl 4 */
        { 0x00000C24, 0x0000 },    /* R3108  - Misc Pad Ctrl 5 */
        { 0x00000D08, 0xFFFF },    /* R3336  - Interrupt Status 1 Mask */
+       { 0x00000D09, 0xFFFF },    /* R3337  - Interrupt Status 2 Mask */
        { 0x00000D0A, 0xFFFF },    /* R3338  - Interrupt Status 3 Mask */
        { 0x00000D0B, 0xFFFF },    /* R3339  - Interrupt Status 4 Mask */
        { 0x00000D0C, 0xFEFF },    /* R3340  - Interrupt Status 5 Mask */
@@ -886,6 +887,8 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_MIC_BIAS_CTRL_1:
        case ARIZONA_MIC_BIAS_CTRL_2:
        case ARIZONA_MIC_BIAS_CTRL_3:
+       case ARIZONA_HP_CTRL_1L:
+       case ARIZONA_HP_CTRL_1R:
        case ARIZONA_ACCESSORY_DETECT_MODE_1:
        case ARIZONA_HEADPHONE_DETECT_1:
        case ARIZONA_HEADPHONE_DETECT_2:
@@ -1328,6 +1331,7 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_INTERRUPT_STATUS_4:
        case ARIZONA_INTERRUPT_STATUS_5:
        case ARIZONA_INTERRUPT_STATUS_1_MASK:
+       case ARIZONA_INTERRUPT_STATUS_2_MASK:
        case ARIZONA_INTERRUPT_STATUS_3_MASK:
        case ARIZONA_INTERRUPT_STATUS_4_MASK:
        case ARIZONA_INTERRUPT_STATUS_5_MASK:
@@ -1477,6 +1481,8 @@ static bool wm8997_volatile_register(struct device *dev, unsigned int reg)
        case ARIZONA_SAMPLE_RATE_3_STATUS:
        case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
        case ARIZONA_MIC_DETECT_3:
+       case ARIZONA_HP_CTRL_1L:
+       case ARIZONA_HP_CTRL_1R:
        case ARIZONA_HEADPHONE_DETECT_2:
        case ARIZONA_INPUT_ENABLES_STATUS:
        case ARIZONA_OUTPUT_STATUS_1:
index bbeb4516facf239b7bce979f6993ae38f1e4e459..006242c8bca0fe9a0bfaa99a6bb0ce9a9605aa47 100644 (file)
@@ -75,7 +75,7 @@ config ATMEL_TCB_CLKSRC
 config ATMEL_TCB_CLKSRC_BLOCK
        int
        depends on ATMEL_TCB_CLKSRC
-       prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X
+       prompt "TC Block" if CPU_AT32AP700X
        default 0
        range 0 1
        help
index 69506ebd4d0765283d2a108cb8912e0a246323fc..c99e896604ee35909e0a2d55bbd95fd31caddbea 100644 (file)
 
 #include "cxl.h"
 
-static struct cxl_sste* find_free_sste(struct cxl_sste *primary_group,
-                                      bool sec_hash,
-                                      struct cxl_sste *secondary_group,
-                                      unsigned int *lru)
+static bool sste_matches(struct cxl_sste *sste, struct copro_slb *slb)
 {
-       unsigned int i, entry;
-       struct cxl_sste *sste, *group = primary_group;
-
-       for (i = 0; i < 2; i++) {
-               for (entry = 0; entry < 8; entry++) {
-                       sste = group + entry;
-                       if (!(be64_to_cpu(sste->esid_data) & SLB_ESID_V))
-                               return sste;
-               }
-               if (!sec_hash)
-                       break;
-               group = secondary_group;
+       return ((sste->vsid_data == cpu_to_be64(slb->vsid)) &&
+               (sste->esid_data == cpu_to_be64(slb->esid)));
+}
+
+/*
+ * This finds a free SSTE for the given SLB, or returns NULL if it's already in
+ * the segment table.
+ */
+static struct cxl_sste* find_free_sste(struct cxl_context *ctx,
+                                      struct copro_slb *slb)
+{
+       struct cxl_sste *primary, *sste, *ret = NULL;
+       unsigned int mask = (ctx->sst_size >> 7) - 1; /* SSTP0[SegTableSize] */
+       unsigned int entry;
+       unsigned int hash;
+
+       if (slb->vsid & SLB_VSID_B_1T)
+               hash = (slb->esid >> SID_SHIFT_1T) & mask;
+       else /* 256M */
+               hash = (slb->esid >> SID_SHIFT) & mask;
+
+       primary = ctx->sstp + (hash << 3);
+
+       for (entry = 0, sste = primary; entry < 8; entry++, sste++) {
+               if (!ret && !(be64_to_cpu(sste->esid_data) & SLB_ESID_V))
+                       ret = sste;
+               if (sste_matches(sste, slb))
+                       return NULL;
        }
+       if (ret)
+               return ret;
+
        /* Nothing free, select an entry to cast out */
-       if (sec_hash && (*lru & 0x8))
-               sste = secondary_group + (*lru & 0x7);
-       else
-               sste = primary_group + (*lru & 0x7);
-       *lru = (*lru + 1) & 0xf;
+       ret = primary + ctx->sst_lru;
+       ctx->sst_lru = (ctx->sst_lru + 1) & 0x7;
 
-       return sste;
+       return ret;
 }
 
 static void cxl_load_segment(struct cxl_context *ctx, struct copro_slb *slb)
 {
        /* mask is the group index, we search primary and secondary here. */
-       unsigned int mask = (ctx->sst_size >> 7)-1; /* SSTP0[SegTableSize] */
-       bool sec_hash = 1;
        struct cxl_sste *sste;
-       unsigned int hash;
        unsigned long flags;
 
-
-       sec_hash = !!(cxl_p1n_read(ctx->afu, CXL_PSL_SR_An) & CXL_PSL_SR_An_SC);
-
-       if (slb->vsid & SLB_VSID_B_1T)
-               hash = (slb->esid >> SID_SHIFT_1T) & mask;
-       else /* 256M */
-               hash = (slb->esid >> SID_SHIFT) & mask;
-
        spin_lock_irqsave(&ctx->sste_lock, flags);
-       sste = find_free_sste(ctx->sstp + (hash << 3), sec_hash,
-                             ctx->sstp + ((~hash & mask) << 3), &ctx->sst_lru);
+       sste = find_free_sste(ctx, slb);
+       if (!sste)
+               goto out_unlock;
 
        pr_devel("CXL Populating SST[%li]: %#llx %#llx\n",
                        sste - ctx->sstp, slb->vsid, slb->esid);
 
        sste->vsid_data = cpu_to_be64(slb->vsid);
        sste->esid_data = cpu_to_be64(slb->esid);
+out_unlock:
        spin_unlock_irqrestore(&ctx->sste_lock, flags);
 }
 
index 623286a77114946aa60ae05c87bf21b781fd24b6..d47532e8f4f16ca4ebd64d3a1bd33fe106a5c5c8 100644 (file)
@@ -417,7 +417,7 @@ static int attach_afu_directed(struct cxl_context *ctx, u64 wed, u64 amr)
        ctx->elem->haurp = 0; /* disable */
        ctx->elem->sdr = cpu_to_be64(mfspr(SPRN_SDR1));
 
-       sr = CXL_PSL_SR_An_SC;
+       sr = 0;
        if (ctx->master)
                sr |= CXL_PSL_SR_An_MP;
        if (mfspr(SPRN_LPCR) & LPCR_TC)
@@ -508,7 +508,7 @@ static int attach_dedicated(struct cxl_context *ctx, u64 wed, u64 amr)
        u64 sr;
        int rc;
 
-       sr = CXL_PSL_SR_An_SC;
+       sr = 0;
        set_endian(sr);
        if (ctx->master)
                sr |= CXL_PSL_SR_An_MP;
index 0ff4b02177be7b37c64dfe6b5513212ef7afee19..0cf2c9d676be839cb9040ba0500fe247b406286b 100644 (file)
@@ -170,7 +170,7 @@ static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
 }
 
 /**
- * eeprom_93cx6_read - Read multiple words from eeprom
+ * eeprom_93cx6_read - Read a word from eeprom
  * @eeprom: Pointer to eeprom structure
  * @word: Word index from where we should start reading
  * @data: target pointer where the information will have to be stored
@@ -234,6 +234,66 @@ void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
 }
 EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
 
+/**
+ * eeprom_93cx6_readb - Read a byte from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Byte index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read a byte of the eeprom data
+ * into the given data pointer.
+ */
+void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
+       u8 *data)
+{
+       u16 command;
+       u16 tmp;
+
+       /*
+        * Initialize the eeprom register
+        */
+       eeprom_93cx6_startup(eeprom);
+
+       /*
+        * Select the read opcode and the byte to be read.
+        */
+       command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte;
+       eeprom_93cx6_write_bits(eeprom, command,
+               PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
+
+       /*
+        * Read the requested 8 bits.
+        */
+       eeprom_93cx6_read_bits(eeprom, &tmp, 8);
+       *data = tmp & 0xff;
+
+       /*
+        * Cleanup eeprom register.
+        */
+       eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_readb);
+
+/**
+ * eeprom_93cx6_multireadb - Read multiple bytes from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @byte: Index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of bytes that should be read.
+ *
+ * This function will read all requested bytes from the eeprom,
+ * this is done by calling eeprom_93cx6_readb() multiple times.
+ */
+void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte,
+       u8 *data, const u16 bytes)
+{
+       unsigned int i;
+
+       for (i = 0; i < bytes; i++)
+               eeprom_93cx6_readb(eeprom, byte + i, &data[i]);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb);
+
 /**
  * eeprom_93cx6_wren - set the write enable state
  * @eeprom: Pointer to eeprom structure
index 2cf2bbc0b927e7d46f381d507dd0729d3bdab23c..180a5442fd4b8d0522cec564ed58cec51386b188 100644 (file)
@@ -187,6 +187,7 @@ void enclosure_unregister(struct enclosure_device *edev)
 EXPORT_SYMBOL_GPL(enclosure_unregister);
 
 #define ENCLOSURE_NAME_SIZE    64
+#define COMPONENT_NAME_SIZE    64
 
 static void enclosure_link_name(struct enclosure_component *cdev, char *name)
 {
@@ -246,6 +247,29 @@ static void enclosure_component_release(struct device *dev)
        put_device(dev->parent);
 }
 
+static struct enclosure_component *
+enclosure_component_find_by_name(struct enclosure_device *edev,
+                               const char *name)
+{
+       int i;
+       const char *cname;
+       struct enclosure_component *ecomp;
+
+       if (!edev || !name || !name[0])
+               return NULL;
+
+       for (i = 0; i < edev->components; i++) {
+               ecomp = &edev->component[i];
+               cname = dev_name(&ecomp->cdev);
+               if (ecomp->number != -1 &&
+                   cname && cname[0] &&
+                   !strcmp(cname, name))
+                       return ecomp;
+       }
+
+       return NULL;
+}
+
 static const struct attribute_group *enclosure_component_groups[];
 
 /**
@@ -269,7 +293,8 @@ enclosure_component_register(struct enclosure_device *edev,
 {
        struct enclosure_component *ecomp;
        struct device *cdev;
-       int err;
+       int err, i;
+       char newname[COMPONENT_NAME_SIZE];
 
        if (number >= edev->components)
                return ERR_PTR(-EINVAL);
@@ -283,9 +308,20 @@ enclosure_component_register(struct enclosure_device *edev,
        ecomp->number = number;
        cdev = &ecomp->cdev;
        cdev->parent = get_device(&edev->edev);
-       if (name && name[0])
-               dev_set_name(cdev, "%s", name);
-       else
+
+       if (name && name[0]) {
+               /* Some hardware (e.g. enclosure in RX300 S6) has components
+                * with non unique names. Registering duplicates in sysfs
+                * will lead to warnings during bootup. So make the names
+                * unique by appending consecutive numbers -1, -2, ... */
+               i = 1;
+               snprintf(newname, COMPONENT_NAME_SIZE,
+                        "%s", name);
+               while (enclosure_component_find_by_name(edev, newname))
+                       snprintf(newname, COMPONENT_NAME_SIZE,
+                                "%s-%i", name, i++);
+               dev_set_name(cdev, "%s", newname);
+       } else
                dev_set_name(cdev, "%u", number);
 
        cdev->release = enclosure_component_release;
index b3a812384a6f90a46384b0aac2050707e513b049..c344483fa7d65a273780a3f6460418466475f771 100644 (file)
@@ -145,7 +145,7 @@ static struct regmap_config vexpress_syscfg_regmap_config = {
 static struct regmap *vexpress_syscfg_regmap_init(struct device *dev,
                void *context)
 {
-       struct platform_device *pdev = to_platform_device(dev);
+       int err;
        struct vexpress_syscfg *syscfg = context;
        struct vexpress_syscfg_func *func;
        struct property *prop;
@@ -155,32 +155,18 @@ static struct regmap *vexpress_syscfg_regmap_init(struct device *dev,
        u32 site, position, dcc;
        int i;
 
-       if (dev->of_node) {
-               int err = vexpress_config_get_topo(dev->of_node, &site,
+       err = vexpress_config_get_topo(dev->of_node, &site,
                                &position, &dcc);
+       if (err)
+               return ERR_PTR(err);
 
-               if (err)
-                       return ERR_PTR(err);
-
-               prop = of_find_property(dev->of_node,
-                               "arm,vexpress-sysreg,func", NULL);
-               if (!prop)
-                       return ERR_PTR(-EINVAL);
-
-               num = prop->length / sizeof(u32) / 2;
-               val = prop->value;
-       } else {
-               if (pdev->num_resources != 1 ||
-                               pdev->resource[0].flags != IORESOURCE_BUS)
-                       return ERR_PTR(-EFAULT);
-
-               site = pdev->resource[0].start;
-               if (site == VEXPRESS_SITE_MASTER)
-                       site = vexpress_config_get_master();
-               position = 0;
-               dcc = 0;
-               num = 1;
-       }
+       prop = of_find_property(dev->of_node,
+                       "arm,vexpress-sysreg,func", NULL);
+       if (!prop)
+               return ERR_PTR(-EINVAL);
+
+       num = prop->length / sizeof(u32) / 2;
+       val = prop->value;
 
        /*
         * "arm,vexpress-energy" function used to be described
@@ -207,13 +193,8 @@ static struct regmap *vexpress_syscfg_regmap_init(struct device *dev,
        for (i = 0; i < num; i++) {
                u32 function, device;
 
-               if (dev->of_node) {
-                       function = be32_to_cpup(val++);
-                       device = be32_to_cpup(val++);
-               } else {
-                       function = pdev->resource[0].end;
-                       device = pdev->id;
-               }
+               function = be32_to_cpup(val++);
+               device = be32_to_cpup(val++);
 
                dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n",
                                func, site, position, dcc,
@@ -265,17 +246,6 @@ static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops = {
 };
 
 
-/* Non-DT hack, to be gone... */
-static struct device *vexpress_syscfg_bridge;
-
-int vexpress_syscfg_device_register(struct platform_device *pdev)
-{
-       pdev->dev.parent = vexpress_syscfg_bridge;
-
-       return platform_device_register(pdev);
-}
-
-
 static int vexpress_syscfg_probe(struct platform_device *pdev)
 {
        struct vexpress_syscfg *syscfg;
@@ -303,10 +273,6 @@ static int vexpress_syscfg_probe(struct platform_device *pdev)
        if (IS_ERR(bridge))
                return PTR_ERR(bridge);
 
-       /* Non-DT case */
-       if (!pdev->dev.of_node)
-               vexpress_syscfg_bridge = bridge;
-
        return 0;
 }
 
index 1fa4c80ff88639e894ba8276387cb73cfbd3b93b..4409d79ed650ee2a2de33475f0ecc686984ed79a 100644 (file)
@@ -78,13 +78,16 @@ static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
 
 /*
  * We've only got one major, so number of mmcblk devices is
- * limited to 256 / number of minors per device.
+ * limited to (1 << 20) / number of minors per device.  It is also
+ * currently limited by the size of the static bitmaps below.
  */
 static int max_devices;
 
-/* 256 minors, so at most 256 separate devices */
-static DECLARE_BITMAP(dev_use, 256);
-static DECLARE_BITMAP(name_use, 256);
+#define MAX_DEVICES 256
+
+/* TODO: Replace these with struct ida */
+static DECLARE_BITMAP(dev_use, MAX_DEVICES);
+static DECLARE_BITMAP(name_use, MAX_DEVICES);
 
 /*
  * There is one mmc_blk_data per slot.
@@ -112,7 +115,7 @@ struct mmc_blk_data {
 
        /*
         * Only set in main mmc_blk_data associated
-        * with mmc_card with mmc_set_drvdata, and keeps
+        * with mmc_card with dev_set_drvdata, and keeps
         * track of the current selected device partition.
         */
        unsigned int    part_curr;
@@ -260,7 +263,7 @@ static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
        int ret;
        struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
 
-       ret = snprintf(buf, PAGE_SIZE, "%d",
+       ret = snprintf(buf, PAGE_SIZE, "%d\n",
                       get_disk_ro(dev_to_disk(dev)) ^
                       md->read_only);
        mmc_blk_put(md);
@@ -642,7 +645,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card,
                                      struct mmc_blk_data *md)
 {
        int ret;
-       struct mmc_blk_data *main_md = mmc_get_drvdata(card);
+       struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
 
        if (main_md->part_curr == md->part_type)
                return 0;
@@ -1004,7 +1007,8 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
        err = mmc_hw_reset(host);
        /* Ensure we switch back to the correct partition */
        if (err != -EOPNOTSUPP) {
-               struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
+               struct mmc_blk_data *main_md =
+                       dev_get_drvdata(&host->card->dev);
                int part_err;
 
                main_md->part_curr = main_md->part_type;
@@ -1308,19 +1312,11 @@ static int mmc_blk_packed_err_check(struct mmc_card *card,
        }
 
        if (status & R1_EXCEPTION_EVENT) {
-               ext_csd = kzalloc(512, GFP_KERNEL);
-               if (!ext_csd) {
-                       pr_err("%s: unable to allocate buffer for ext_csd\n",
-                              req->rq_disk->disk_name);
-                       return -ENOMEM;
-               }
-
-               err = mmc_send_ext_csd(card, ext_csd);
+               err = mmc_get_ext_csd(card, &ext_csd);
                if (err) {
                        pr_err("%s: error %d sending ext_csd\n",
                               req->rq_disk->disk_name, err);
-                       check = MMC_BLK_ABORT;
-                       goto free;
+                       return MMC_BLK_ABORT;
                }
 
                if ((ext_csd[EXT_CSD_EXP_EVENTS_STATUS] &
@@ -1338,7 +1334,6 @@ static int mmc_blk_packed_err_check(struct mmc_card *card,
                               req->rq_disk->disk_name, packed->nr_entries,
                               packed->blocks, packed->idx_failure);
                }
-free:
                kfree(ext_csd);
        }
 
@@ -2093,7 +2088,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
 
        /*
         * !subname implies we are creating main mmc_blk_data that will be
-        * associated with mmc_card with mmc_set_drvdata. Due to device
+        * associated with mmc_card with dev_set_drvdata. Due to device
         * partitions, devidx will not coincide with a per-physical card
         * index anymore so we keep track of a name index.
         */
@@ -2425,8 +2420,9 @@ static const struct mmc_fixup blk_fixups[] =
        END_FIXUP
 };
 
-static int mmc_blk_probe(struct mmc_card *card)
+static int mmc_blk_probe(struct device *dev)
 {
+       struct mmc_card *card = mmc_dev_to_card(dev);
        struct mmc_blk_data *md, *part_md;
        char cap_str[10];
 
@@ -2451,7 +2447,7 @@ static int mmc_blk_probe(struct mmc_card *card)
        if (mmc_blk_alloc_parts(card, md))
                goto out;
 
-       mmc_set_drvdata(card, md);
+       dev_set_drvdata(dev, md);
 
        if (mmc_add_disk(md))
                goto out;
@@ -2481,9 +2477,10 @@ static int mmc_blk_probe(struct mmc_card *card)
        return 0;
 }
 
-static void mmc_blk_remove(struct mmc_card *card)
+static int mmc_blk_remove(struct device *dev)
 {
-       struct mmc_blk_data *md = mmc_get_drvdata(card);
+       struct mmc_card *card = mmc_dev_to_card(dev);
+       struct mmc_blk_data *md = dev_get_drvdata(dev);
 
        mmc_blk_remove_parts(card, md);
        pm_runtime_get_sync(&card->dev);
@@ -2494,13 +2491,15 @@ static void mmc_blk_remove(struct mmc_card *card)
                pm_runtime_disable(&card->dev);
        pm_runtime_put_noidle(&card->dev);
        mmc_blk_remove_req(md);
-       mmc_set_drvdata(card, NULL);
+       dev_set_drvdata(dev, NULL);
+
+       return 0;
 }
 
-static int _mmc_blk_suspend(struct mmc_card *card)
+static int _mmc_blk_suspend(struct device *dev)
 {
        struct mmc_blk_data *part_md;
-       struct mmc_blk_data *md = mmc_get_drvdata(card);
+       struct mmc_blk_data *md = dev_get_drvdata(dev);
 
        if (md) {
                mmc_queue_suspend(&md->queue);
@@ -2511,21 +2510,21 @@ static int _mmc_blk_suspend(struct mmc_card *card)
        return 0;
 }
 
-static void mmc_blk_shutdown(struct mmc_card *card)
+static void mmc_blk_shutdown(struct device *dev)
 {
-       _mmc_blk_suspend(card);
+       _mmc_blk_suspend(dev);
 }
 
-#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card)
+#ifdef CONFIG_PM_SLEEP
+static int mmc_blk_suspend(struct device *dev)
 {
-       return _mmc_blk_suspend(card);
+       return _mmc_blk_suspend(dev);
 }
 
-static int mmc_blk_resume(struct mmc_card *card)
+static int mmc_blk_resume(struct device *dev)
 {
        struct mmc_blk_data *part_md;
-       struct mmc_blk_data *md = mmc_get_drvdata(card);
+       struct mmc_blk_data *md = dev_get_drvdata(dev);
 
        if (md) {
                /*
@@ -2540,19 +2539,15 @@ static int mmc_blk_resume(struct mmc_card *card)
        }
        return 0;
 }
-#else
-#define        mmc_blk_suspend NULL
-#define mmc_blk_resume NULL
 #endif
 
-static struct mmc_driver mmc_driver = {
-       .drv            = {
-               .name   = "mmcblk",
-       },
+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,
        .probe          = mmc_blk_probe,
        .remove         = mmc_blk_remove,
-       .suspend        = mmc_blk_suspend,
-       .resume         = mmc_blk_resume,
        .shutdown       = mmc_blk_shutdown,
 };
 
@@ -2563,7 +2558,7 @@ static int __init mmc_blk_init(void)
        if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
                pr_info("mmcblk: using %d minors per device\n", perdev_minors);
 
-       max_devices = 256 / perdev_minors;
+       max_devices = min(MAX_DEVICES, (1 << MINORBITS) / perdev_minors);
 
        res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
        if (res)
index 0c0fc52d42c538bd3b6e543d050d40c61533551b..0a7430f94d2961a163fa647dd109b221b9d25286 100644 (file)
@@ -14,6 +14,7 @@
 #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() */
@@ -32,6 +33,8 @@
 #define BUFFER_ORDER           2
 #define BUFFER_SIZE            (PAGE_SIZE << BUFFER_ORDER)
 
+#define TEST_ALIGN_END         8
+
 /*
  * Limit the test area size to the maximum MMC HC erase group size.  Note that
  * the maximum SD allocation unit size is just 4MiB.
@@ -1174,7 +1177,7 @@ static int mmc_test_align_write(struct mmc_test_card *test)
        int ret, i;
        struct scatterlist sg;
 
-       for (i = 1;i < 4;i++) {
+       for (i = 1; i < TEST_ALIGN_END; i++) {
                sg_init_one(&sg, test->buffer + i, 512);
                ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
                if (ret)
@@ -1189,7 +1192,7 @@ static int mmc_test_align_read(struct mmc_test_card *test)
        int ret, i;
        struct scatterlist sg;
 
-       for (i = 1;i < 4;i++) {
+       for (i = 1; i < TEST_ALIGN_END; i++) {
                sg_init_one(&sg, test->buffer + i, 512);
                ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
                if (ret)
@@ -1216,7 +1219,7 @@ static int mmc_test_align_multi_write(struct mmc_test_card *test)
        if (size < 1024)
                return RESULT_UNSUP_HOST;
 
-       for (i = 1;i < 4;i++) {
+       for (i = 1; i < TEST_ALIGN_END; i++) {
                sg_init_one(&sg, test->buffer + i, size);
                ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
                if (ret)
@@ -1243,7 +1246,7 @@ static int mmc_test_align_multi_read(struct mmc_test_card *test)
        if (size < 1024)
                return RESULT_UNSUP_HOST;
 
-       for (i = 1;i < 4;i++) {
+       for (i = 1; i < TEST_ALIGN_END; i++) {
                sg_init_one(&sg, test->buffer + i, size);
                ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
                if (ret)
@@ -2997,8 +3000,9 @@ err:
        return ret;
 }
 
-static int mmc_test_probe(struct mmc_card *card)
+static int mmc_test_probe(struct device *dev)
 {
+       struct mmc_card *card = mmc_dev_to_card(dev);
        int ret;
 
        if (!mmc_card_mmc(card) && !mmc_card_sd(card))
@@ -3013,20 +3017,22 @@ static int mmc_test_probe(struct mmc_card *card)
        return 0;
 }
 
-static void mmc_test_remove(struct mmc_card *card)
+static int mmc_test_remove(struct device *dev)
 {
+       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 mmc_card *card)
+static void mmc_test_shutdown(struct device *dev)
 {
 }
 
-static struct mmc_driver mmc_driver = {
-       .drv            = {
-               .name   = "mmc_test",
-       },
+static struct device_driver mmc_driver = {
+       .name   = "mmc_test",
        .probe          = mmc_test_probe,
        .remove         = mmc_test_remove,
        .shutdown       = mmc_test_shutdown,
index cfa6110632c36efea3e150ab215689170e54a0ee..236d194c28835e87adb9bc108c55f5e122353c68 100644 (file)
@@ -232,13 +232,15 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
                        if (!mqrq_cur->bounce_buf) {
                                pr_warn("%s: unable to allocate bounce cur buffer\n",
                                        mmc_card_name(card));
-                       }
-                       mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
-                       if (!mqrq_prev->bounce_buf) {
-                               pr_warn("%s: unable to allocate bounce prev buffer\n",
-                                       mmc_card_name(card));
-                               kfree(mqrq_cur->bounce_buf);
-                               mqrq_cur->bounce_buf = NULL;
+                       } else {
+                               mqrq_prev->bounce_buf =
+                                               kmalloc(bouncesz, GFP_KERNEL);
+                               if (!mqrq_prev->bounce_buf) {
+                                       pr_warn("%s: unable to allocate bounce prev buffer\n",
+                                               mmc_card_name(card));
+                                       kfree(mqrq_cur->bounce_buf);
+                                       mqrq_cur->bounce_buf = NULL;
+                               }
                        }
                }
 
index 8a1f1240e05802f326986afdf093cd75f303496c..5ca562ccfcf389984122c9432447fc175a5121b2 100644 (file)
@@ -25,8 +25,6 @@
 #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)
 {
@@ -106,33 +104,14 @@ 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 && drv->shutdown)
-               drv->shutdown(card);
+       if (dev->driver && dev->driver->shutdown)
+               dev->driver->shutdown(dev);
 
        if (host->bus_ops->shutdown) {
                ret = host->bus_ops->shutdown(host);
@@ -145,16 +124,13 @@ static void mmc_bus_shutdown(struct device *dev)
 #ifdef CONFIG_PM_SLEEP
 static int mmc_bus_suspend(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 && drv->suspend) {
-               ret = drv->suspend(card);
-               if (ret)
-                       return ret;
-       }
+       ret = pm_generic_suspend(dev);
+       if (ret)
+               return ret;
 
        ret = host->bus_ops->suspend(host);
        return ret;
@@ -162,7 +138,6 @@ static int mmc_bus_suspend(struct device *dev)
 
 static int mmc_bus_resume(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;
@@ -172,9 +147,7 @@ static int mmc_bus_resume(struct device *dev)
                pr_warn("%s: error %d during resume (card was removed?)\n",
                        mmc_hostname(host), ret);
 
-       if (dev->driver && drv->resume)
-               ret = drv->resume(card);
-
+       ret = pm_generic_resume(dev);
        return ret;
 }
 #endif
@@ -207,8 +180,6 @@ 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,
 };
@@ -227,24 +198,22 @@ void mmc_unregister_bus(void)
  *     mmc_register_driver - register a media driver
  *     @drv: MMC media driver
  */
-int mmc_register_driver(struct mmc_driver *drv)
+int mmc_register_driver(struct device_driver *drv)
 {
-       drv->drv.bus = &mmc_bus_type;
-       return driver_register(&drv->drv);
+       drv->bus = &mmc_bus_type;
+       return driver_register(drv);
 }
-
 EXPORT_SYMBOL(mmc_register_driver);
 
 /**
  *     mmc_unregister_driver - unregister a media driver
  *     @drv: MMC media driver
  */
-void mmc_unregister_driver(struct mmc_driver *drv)
+void mmc_unregister_driver(struct device_driver *drv)
 {
-       drv->drv.bus = &mmc_bus_type;
-       driver_unregister(&drv->drv);
+       drv->bus = &mmc_bus_type;
+       driver_unregister(drv);
 }
-
 EXPORT_SYMBOL(mmc_unregister_driver);
 
 static void mmc_release_card(struct device *dev)
index f26a5f1d926dd7e6a79ec1b9f87f7be4fd691994..9584bffa8b227ed01ea7286542eb269d4b59a5b8 100644 (file)
@@ -149,6 +149,14 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
 
                led_trigger_event(host->led, LED_OFF);
 
+               if (mrq->sbc) {
+                       pr_debug("%s: req done <CMD%u>: %d: %08x %08x %08x %08x\n",
+                               mmc_hostname(host), mrq->sbc->opcode,
+                               mrq->sbc->error,
+                               mrq->sbc->resp[0], mrq->sbc->resp[1],
+                               mrq->sbc->resp[2], mrq->sbc->resp[3]);
+               }
+
                pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
                        mmc_hostname(host), cmd->opcode, err,
                        cmd->resp[0], cmd->resp[1],
@@ -214,6 +222,10 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
        mrq->cmd->error = 0;
        mrq->cmd->mrq = mrq;
+       if (mrq->sbc) {
+               mrq->sbc->error = 0;
+               mrq->sbc->mrq = mrq;
+       }
        if (mrq->data) {
                BUG_ON(mrq->data->blksz > host->max_blk_size);
                BUG_ON(mrq->data->blocks > host->max_blk_count);
@@ -538,8 +550,18 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
                if (host->card && mmc_card_mmc(host->card) &&
                    ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) ||
                     (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) &&
-                   (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT))
+                   (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) {
+
+                       /* Cancel the prepared request */
+                       if (areq)
+                               mmc_post_req(host, areq->mrq, -EINVAL);
+
                        mmc_start_bkops(host->card, true);
+
+                       /* prepare the request again */
+                       if (areq)
+                               mmc_pre_req(host, areq->mrq, !host->areq);
+               }
        }
 
        if (!err && areq)
@@ -709,27 +731,16 @@ int mmc_read_bkops_status(struct mmc_card *card)
        int err;
        u8 *ext_csd;
 
-       /*
-        * In future work, we should consider storing the entire ext_csd.
-        */
-       ext_csd = kmalloc(512, GFP_KERNEL);
-       if (!ext_csd) {
-               pr_err("%s: could not allocate buffer to receive the ext_csd.\n",
-                      mmc_hostname(card->host));
-               return -ENOMEM;
-       }
-
        mmc_claim_host(card->host);
-       err = mmc_send_ext_csd(card, ext_csd);
+       err = mmc_get_ext_csd(card, &ext_csd);
        mmc_release_host(card->host);
        if (err)
-               goto out;
+               return err;
 
        card->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS];
        card->ext_csd.raw_exception_status = ext_csd[EXT_CSD_EXP_EVENTS_STATUS];
-out:
        kfree(ext_csd);
-       return err;
+       return 0;
 }
 EXPORT_SYMBOL(mmc_read_bkops_status);
 
@@ -1088,6 +1099,22 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
        mmc_host_clk_release(host);
 }
 
+/*
+ * Set initial state after a power cycle or a hw_reset.
+ */
+void mmc_set_initial_state(struct mmc_host *host)
+{
+       if (mmc_host_is_spi(host))
+               host->ios.chip_select = MMC_CS_HIGH;
+       else
+               host->ios.chip_select = MMC_CS_DONTCARE;
+       host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+       host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
+
+       mmc_set_ios(host);
+}
+
 /**
  * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
  * @vdd:       voltage (mV)
@@ -1420,18 +1447,20 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
                pr_warn("%s: cannot verify signal voltage switch\n",
                        mmc_hostname(host));
 
+       mmc_host_clk_hold(host);
+
        cmd.opcode = SD_SWITCH_VOLTAGE;
        cmd.arg = 0;
        cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
        err = mmc_wait_for_cmd(host, &cmd, 0);
        if (err)
-               return err;
+               goto err_command;
 
-       if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
-               return -EIO;
-
-       mmc_host_clk_hold(host);
+       if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) {
+               err = -EIO;
+               goto err_command;
+       }
        /*
         * The card should drive cmd and dat[0:3] low immediately
         * after the response of cmd11, but wait 1 ms to be sure
@@ -1480,6 +1509,7 @@ power_cycle:
                mmc_power_cycle(host, ocr);
        }
 
+err_command:
        mmc_host_clk_release(host);
 
        return err;
@@ -1526,15 +1556,9 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
        mmc_host_clk_hold(host);
 
        host->ios.vdd = fls(ocr) - 1;
-       if (mmc_host_is_spi(host))
-               host->ios.chip_select = MMC_CS_HIGH;
-       else
-               host->ios.chip_select = MMC_CS_DONTCARE;
-       host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
        host->ios.power_mode = MMC_POWER_UP;
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
+       /* Set initial state and call mmc_set_ios */
+       mmc_set_initial_state(host);
 
        /* Try to set signal voltage to 3.3V but fall back to 1.8v or 1.2v */
        if (__mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330) == 0)
@@ -1574,14 +1598,9 @@ void mmc_power_off(struct mmc_host *host)
        host->ios.clock = 0;
        host->ios.vdd = 0;
 
-       if (!mmc_host_is_spi(host)) {
-               host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-               host->ios.chip_select = MMC_CS_DONTCARE;
-       }
        host->ios.power_mode = MMC_POWER_OFF;
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
+       /* Set initial state and call mmc_set_ios */
+       mmc_set_initial_state(host);
 
        /*
         * Some configurations, such as the 802.11 SDIO card in the OLPC
@@ -2259,30 +2278,16 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check)
 
        /* If the reset has happened, then a status command will fail */
        if (check) {
-               struct mmc_command cmd = {0};
-               int err;
+               u32 status;
 
-               cmd.opcode = MMC_SEND_STATUS;
-               if (!mmc_host_is_spi(card->host))
-                       cmd.arg = card->rca << 16;
-               cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-               err = mmc_wait_for_cmd(card->host, &cmd, 0);
-               if (!err) {
+               if (!mmc_send_status(card, &status)) {
                        mmc_host_clk_release(host);
                        return -ENOSYS;
                }
        }
 
-       if (mmc_host_is_spi(host)) {
-               host->ios.chip_select = MMC_CS_HIGH;
-               host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
-       } else {
-               host->ios.chip_select = MMC_CS_DONTCARE;
-               host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
-       }
-       host->ios.bus_width = MMC_BUS_WIDTH_1;
-       host->ios.timing = MMC_TIMING_LEGACY;
-       mmc_set_ios(host);
+       /* Set initial state and call mmc_set_ios */
+       mmc_set_initial_state(host);
 
        mmc_host_clk_release(host);
 
index 443a584660f0132de2b07ee232e068575a63faf4..d76597c65e3a64105e9f6728b7a81b417ab2b969 100644 (file)
@@ -49,6 +49,7 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
 void mmc_power_up(struct mmc_host *host, u32 ocr);
 void mmc_power_off(struct mmc_host *host);
 void mmc_power_cycle(struct mmc_host *host, u32 ocr);
+void mmc_set_initial_state(struct mmc_host *host);
 
 static inline void mmc_delay(unsigned int ms)
 {
index 91eb162232462d6f5f142904d9c4fea5b9e65451..e9142108a6c6d486d3ac15ba4cb8a317d1fd62b2 100644 (file)
@@ -291,14 +291,8 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
        if (!buf)
                return -ENOMEM;
 
-       ext_csd = kmalloc(512, GFP_KERNEL);
-       if (!ext_csd) {
-               err = -ENOMEM;
-               goto out_free;
-       }
-
        mmc_get_card(card);
-       err = mmc_send_ext_csd(card, ext_csd);
+       err = mmc_get_ext_csd(card, &ext_csd);
        mmc_put_card(card);
        if (err)
                goto out_free;
@@ -314,7 +308,6 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
 
 out_free:
        kfree(buf);
-       kfree(ext_csd);
        return err;
 }
 
index 03c53b72a2d6a34bafbea7e1a1bda90299772fa8..270d58a4c43dd0e25ffa66718ca0c0ada9ad5036 100644 (file)
@@ -311,7 +311,8 @@ int mmc_of_parse(struct mmc_host *host)
        struct device_node *np;
        u32 bus_width;
        int len, ret;
-       bool cap_invert, gpio_invert;
+       bool cd_cap_invert, cd_gpio_invert = false;
+       bool ro_cap_invert, ro_gpio_invert = false;
 
        if (!host->parent || !host->parent->of_node)
                return 0;
@@ -359,16 +360,13 @@ int mmc_of_parse(struct mmc_host *host)
        if (of_find_property(np, "non-removable", &len)) {
                host->caps |= MMC_CAP_NONREMOVABLE;
        } else {
-               if (of_property_read_bool(np, "cd-inverted"))
-                       cap_invert = true;
-               else
-                       cap_invert = false;
+               cd_cap_invert = of_property_read_bool(np, "cd-inverted");
 
                if (of_find_property(np, "broken-cd", &len))
                        host->caps |= MMC_CAP_NEEDS_POLL;
 
                ret = mmc_gpiod_request_cd(host, "cd", 0, true,
-                                          0, &gpio_invert);
+                                          0, &cd_gpio_invert);
                if (ret) {
                        if (ret == -EPROBE_DEFER)
                                return ret;
@@ -391,17 +389,14 @@ int mmc_of_parse(struct mmc_host *host)
                 * both inverted, the end result is that the CD line is
                 * not inverted.
                 */
-               if (cap_invert ^ gpio_invert)
+               if (cd_cap_invert ^ cd_gpio_invert)
                        host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
        }
 
        /* Parse Write Protection */
-       if (of_property_read_bool(np, "wp-inverted"))
-               cap_invert = true;
-       else
-               cap_invert = false;
+       ro_cap_invert = of_property_read_bool(np, "wp-inverted");
 
-       ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &gpio_invert);
+       ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert);
        if (ret) {
                if (ret == -EPROBE_DEFER)
                        goto out;
@@ -414,7 +409,7 @@ int mmc_of_parse(struct mmc_host *host)
                dev_info(host->parent, "Got WP GPIO\n");
 
        /* See the comment on CD inversion above */
-       if (cap_invert ^ gpio_invert)
+       if (ro_cap_invert ^ ro_gpio_invert)
                host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
 
        if (of_find_property(np, "cap-sd-highspeed", &len))
index a301a78a2bd1cdc11eb5f674ab563ac74700ea76..02ad79229f65ecf0b50b9bf29a1f63c0d297910e 100644 (file)
@@ -177,65 +177,6 @@ static int mmc_decode_csd(struct mmc_card *card)
        return 0;
 }
 
-/*
- * Read extended CSD.
- */
-static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
-{
-       int err;
-       u8 *ext_csd;
-
-       BUG_ON(!card);
-       BUG_ON(!new_ext_csd);
-
-       *new_ext_csd = NULL;
-
-       if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
-               return 0;
-
-       /*
-        * As the ext_csd is so large and mostly unused, we don't store the
-        * raw block in mmc_card.
-        */
-       ext_csd = kmalloc(512, GFP_KERNEL);
-       if (!ext_csd) {
-               pr_err("%s: could not allocate a buffer to "
-                       "receive the ext_csd.\n", mmc_hostname(card->host));
-               return -ENOMEM;
-       }
-
-       err = mmc_send_ext_csd(card, ext_csd);
-       if (err) {
-               kfree(ext_csd);
-               *new_ext_csd = NULL;
-
-               /* If the host or the card can't do the switch,
-                * fail more gracefully. */
-               if ((err != -EINVAL)
-                && (err != -ENOSYS)
-                && (err != -EFAULT))
-                       return err;
-
-               /*
-                * High capacity cards should have this "magic" size
-                * stored in their CSD.
-                */
-               if (card->csd.capacity == (4096 * 512)) {
-                       pr_err("%s: unable to read EXT_CSD "
-                               "on a possible high capacity card. "
-                               "Card will be ignored.\n",
-                               mmc_hostname(card->host));
-               } else {
-                       pr_warn("%s: unable to read EXT_CSD, performance might suffer\n",
-                               mmc_hostname(card->host));
-                       err = 0;
-               }
-       } else
-               *new_ext_csd = ext_csd;
-
-       return err;
-}
-
 static void mmc_select_card_type(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
@@ -391,16 +332,11 @@ static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd)
 /*
  * Decode extended CSD.
  */
-static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
+static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 {
        int err = 0, idx;
        unsigned int part_size;
 
-       BUG_ON(!card);
-
-       if (!ext_csd)
-               return 0;
-
        /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */
        card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE];
        if (card->csd.structure == 3) {
@@ -628,16 +564,56 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
                card->ext_csd.data_sector_size = 512;
        }
 
+       /* eMMC v5 or later */
+       if (card->ext_csd.rev >= 7) {
+               memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION],
+                      MMC_FIRMWARE_LEN);
+               card->ext_csd.ffu_capable =
+                       (ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) &&
+                       !(ext_csd[EXT_CSD_FW_CONFIG] & 0x1);
+       }
 out:
        return err;
 }
 
-static inline void mmc_free_ext_csd(u8 *ext_csd)
+static int mmc_read_ext_csd(struct mmc_card *card)
 {
+       u8 *ext_csd;
+       int err;
+
+       if (!mmc_can_ext_csd(card))
+               return 0;
+
+       err = mmc_get_ext_csd(card, &ext_csd);
+       if (err) {
+               /* If the host or the card can't do the switch,
+                * fail more gracefully. */
+               if ((err != -EINVAL)
+                && (err != -ENOSYS)
+                && (err != -EFAULT))
+                       return err;
+
+               /*
+                * High capacity cards should have this "magic" size
+                * stored in their CSD.
+                */
+               if (card->csd.capacity == (4096 * 512)) {
+                       pr_err("%s: unable to read EXT_CSD on a possible high capacity card. Card will be ignored.\n",
+                               mmc_hostname(card->host));
+               } else {
+                       pr_warn("%s: unable to read EXT_CSD, performance might suffer\n",
+                               mmc_hostname(card->host));
+                       err = 0;
+               }
+
+               return err;
+       }
+
+       err = mmc_decode_ext_csd(card, ext_csd);
        kfree(ext_csd);
+       return err;
 }
 
-
 static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
 {
        u8 *bw_ext_csd;
@@ -647,11 +623,8 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
                return 0;
 
        err = mmc_get_ext_csd(card, &bw_ext_csd);
-
-       if (err || bw_ext_csd == NULL) {
-               err = -EINVAL;
-               goto out;
-       }
+       if (err)
+               return err;
 
        /* only compare read only fields */
        err = !((card->ext_csd.raw_partition_support ==
@@ -710,8 +683,7 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
        if (err)
                err = -EINVAL;
 
-out:
-       mmc_free_ext_csd(bw_ext_csd);
+       kfree(bw_ext_csd);
        return err;
 }
 
@@ -722,7 +694,7 @@ MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
 MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
 MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9);
 MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9);
-MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_DEV_ATTR(ffu_capable, "%d\n", card->ext_csd.ffu_capable);
 MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
 MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
@@ -735,6 +707,22 @@ MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
 MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
 MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
 
+static ssize_t mmc_fwrev_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       struct mmc_card *card = mmc_dev_to_card(dev);
+
+       if (card->ext_csd.rev < 7) {
+               return sprintf(buf, "0x%x\n", card->cid.fwrev);
+       } else {
+               return sprintf(buf, "0x%*phN\n", MMC_FIRMWARE_LEN,
+                              card->ext_csd.fwrev);
+       }
+}
+
+static DEVICE_ATTR(fwrev, S_IRUGO, mmc_fwrev_show, NULL);
+
 static struct attribute *mmc_std_attrs[] = {
        &dev_attr_cid.attr,
        &dev_attr_csd.attr,
@@ -742,6 +730,7 @@ static struct attribute *mmc_std_attrs[] = {
        &dev_attr_erase_size.attr,
        &dev_attr_preferred_erase_size.attr,
        &dev_attr_fwrev.attr,
+       &dev_attr_ffu_capable.attr,
        &dev_attr_hwrev.attr,
        &dev_attr_manfid.attr,
        &dev_attr_name.attr,
@@ -774,14 +763,6 @@ static int __mmc_select_powerclass(struct mmc_card *card,
        unsigned int pwrclass_val = 0;
        int err = 0;
 
-       /* Power class selection is supported for versions >= 4.0 */
-       if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
-               return 0;
-
-       /* Power class values are defined only for 4/8 bit bus */
-       if (bus_width == EXT_CSD_BUS_WIDTH_1)
-               return 0;
-
        switch (1 << host->ios.vdd) {
        case MMC_VDD_165_195:
                if (host->ios.clock <= MMC_HIGH_26_MAX_DTR)
@@ -844,7 +825,7 @@ static int mmc_select_powerclass(struct mmc_card *card)
        int err, ddr;
 
        /* Power class selection is supported for versions >= 4.0 */
-       if (card->csd.mmca_vsn < CSD_SPEC_VER_4)
+       if (!mmc_can_ext_csd(card))
                return 0;
 
        bus_width = host->ios.bus_width;
@@ -905,7 +886,7 @@ static int mmc_select_bus_width(struct mmc_card *card)
        unsigned idx, bus_width = 0;
        int err = 0;
 
-       if ((card->csd.mmca_vsn < CSD_SPEC_VER_4) &&
+       if (!mmc_can_ext_csd(card) &&
            !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)))
                return 0;
 
@@ -998,7 +979,7 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
                        ext_csd_bits,
                        card->ext_csd.generic_cmd6_time);
        if (err) {
-               pr_warn("%s: switch to bus width %d ddr failed\n",
+               pr_err("%s: switch to bus width %d ddr failed\n",
                        mmc_hostname(host), 1 << bus_width);
                return err;
        }
@@ -1069,7 +1050,7 @@ static int mmc_select_hs400(struct mmc_card *card)
                           card->ext_csd.generic_cmd6_time,
                           true, true, true);
        if (err) {
-               pr_warn("%s: switch to high-speed from hs200 failed, err:%d\n",
+               pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
                        mmc_hostname(host), err);
                return err;
        }
@@ -1079,7 +1060,7 @@ static int mmc_select_hs400(struct mmc_card *card)
                         EXT_CSD_DDR_BUS_WIDTH_8,
                         card->ext_csd.generic_cmd6_time);
        if (err) {
-               pr_warn("%s: switch to bus width for hs400 failed, err:%d\n",
+               pr_err("%s: switch to bus width for hs400 failed, err:%d\n",
                        mmc_hostname(host), err);
                return err;
        }
@@ -1089,7 +1070,7 @@ static int mmc_select_hs400(struct mmc_card *card)
                           card->ext_csd.generic_cmd6_time,
                           true, true, true);
        if (err) {
-               pr_warn("%s: switch to hs400 failed, err:%d\n",
+               pr_err("%s: switch to hs400 failed, err:%d\n",
                         mmc_hostname(host), err);
                return err;
        }
@@ -1146,8 +1127,7 @@ static int mmc_select_timing(struct mmc_card *card)
 {
        int err = 0;
 
-       if ((card->csd.mmca_vsn < CSD_SPEC_VER_4 &&
-            card->ext_csd.hs_max_dtr == 0))
+       if (!mmc_can_ext_csd(card))
                goto bus_speed;
 
        if (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200)
@@ -1232,7 +1212,7 @@ static int mmc_hs200_tuning(struct mmc_card *card)
                mmc_host_clk_release(host);
 
                if (err)
-                       pr_warn("%s: tuning execution failed\n",
+                       pr_err("%s: tuning execution failed\n",
                                mmc_hostname(host));
        }
 
@@ -1252,7 +1232,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        int err;
        u32 cid[4];
        u32 rocr;
-       u8 *ext_csd = NULL;
 
        BUG_ON(!host);
        WARN_ON(!host->claimed);
@@ -1361,14 +1340,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        }
 
        if (!oldcard) {
-               /*
-                * Fetch and process extended CSD.
-                */
-
-               err = mmc_get_ext_csd(card, &ext_csd);
-               if (err)
-                       goto free_card;
-               err = mmc_read_ext_csd(card, ext_csd);
+               /* Read extended CSD. */
+               err = mmc_read_ext_csd(card);
                if (err)
                        goto free_card;
 
@@ -1458,18 +1431,18 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        if (mmc_card_hs200(card)) {
                err = mmc_hs200_tuning(card);
                if (err)
-                       goto err;
+                       goto free_card;
 
                err = mmc_select_hs400(card);
                if (err)
-                       goto err;
+                       goto free_card;
        } else if (mmc_card_hs(card)) {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
                if (!IS_ERR_VALUE(err)) {
                        err = mmc_select_hs_ddr(card);
                        if (err)
-                               goto err;
+                               goto free_card;
                }
        }
 
@@ -1545,15 +1518,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        if (!oldcard)
                host->card = card;
 
-       mmc_free_ext_csd(ext_csd);
        return 0;
 
 free_card:
        if (!oldcard)
                mmc_remove_card(card);
 err:
-       mmc_free_ext_csd(ext_csd);
-
        return err;
 }
 
index 7911e0510a1d6c2ed131e0fb74c913b2a9cc0162..3b044c5b029cd9f5814348af65d1d323fc29a28e 100644 (file)
@@ -264,20 +264,6 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
        struct mmc_command cmd = {0};
        struct mmc_data data = {0};
        struct scatterlist sg;
-       void *data_buf;
-       int is_on_stack;
-
-       is_on_stack = object_is_on_stack(buf);
-       if (is_on_stack) {
-               /*
-                * dma onto stack is unsafe/nonportable, but callers to this
-                * routine normally provide temporary on-stack buffers ...
-                */
-               data_buf = kmalloc(len, GFP_KERNEL);
-               if (!data_buf)
-                       return -ENOMEM;
-       } else
-               data_buf = buf;
 
        mrq.cmd = &cmd;
        mrq.data = &data;
@@ -298,7 +284,7 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
        data.sg = &sg;
        data.sg_len = 1;
 
-       sg_init_one(&sg, data_buf, len);
+       sg_init_one(&sg, buf, len);
 
        if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) {
                /*
@@ -312,11 +298,6 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
 
        mmc_wait_for_req(host, &mrq);
 
-       if (is_on_stack) {
-               memcpy(buf, data_buf, len);
-               kfree(data_buf);
-       }
-
        if (cmd.error)
                return cmd.error;
        if (data.error)
@@ -334,7 +315,7 @@ int mmc_send_csd(struct mmc_card *card, u32 *csd)
                return mmc_send_cxd_native(card->host, card->rca << 16,
                                csd, MMC_SEND_CSD);
 
-       csd_tmp = kmalloc(16, GFP_KERNEL);
+       csd_tmp = kzalloc(16, GFP_KERNEL);
        if (!csd_tmp)
                return -ENOMEM;
 
@@ -362,7 +343,7 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid)
                                cid, MMC_SEND_CID);
        }
 
-       cid_tmp = kmalloc(16, GFP_KERNEL);
+       cid_tmp = kzalloc(16, GFP_KERNEL);
        if (!cid_tmp)
                return -ENOMEM;
 
@@ -378,12 +359,35 @@ err:
        return ret;
 }
 
-int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd)
+int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
 {
-       return mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD,
-                       ext_csd, 512);
+       int err;
+       u8 *ext_csd;
+
+       if (!card || !new_ext_csd)
+               return -EINVAL;
+
+       if (!mmc_can_ext_csd(card))
+               return -EOPNOTSUPP;
+
+       /*
+        * As the ext_csd is so large and mostly unused, we don't store the
+        * raw block in mmc_card.
+        */
+       ext_csd = kzalloc(512, GFP_KERNEL);
+       if (!ext_csd)
+               return -ENOMEM;
+
+       err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd,
+                               512);
+       if (err)
+               kfree(ext_csd);
+       else
+               *new_ext_csd = ext_csd;
+
+       return err;
 }
-EXPORT_SYMBOL_GPL(mmc_send_ext_csd);
+EXPORT_SYMBOL_GPL(mmc_get_ext_csd);
 
 int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp)
 {
@@ -543,6 +547,75 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 }
 EXPORT_SYMBOL_GPL(mmc_switch);
 
+int mmc_send_tuning(struct mmc_host *host)
+{
+       struct mmc_request mrq = {NULL};
+       struct mmc_command cmd = {0};
+       struct mmc_data data = {0};
+       struct scatterlist sg;
+       struct mmc_ios *ios = &host->ios;
+       const u8 *tuning_block_pattern;
+       int size, err = 0;
+       u8 *data_buf;
+       u32 opcode;
+
+       if (ios->bus_width == MMC_BUS_WIDTH_8) {
+               tuning_block_pattern = tuning_blk_pattern_8bit;
+               size = sizeof(tuning_blk_pattern_8bit);
+               opcode = MMC_SEND_TUNING_BLOCK_HS200;
+       } else if (ios->bus_width == MMC_BUS_WIDTH_4) {
+               tuning_block_pattern = tuning_blk_pattern_4bit;
+               size = sizeof(tuning_blk_pattern_4bit);
+               opcode = MMC_SEND_TUNING_BLOCK;
+       } else
+               return -EINVAL;
+
+       data_buf = kzalloc(size, GFP_KERNEL);
+       if (!data_buf)
+               return -ENOMEM;
+
+       mrq.cmd = &cmd;
+       mrq.data = &data;
+
+       cmd.opcode = opcode;
+       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+       data.blksz = size;
+       data.blocks = 1;
+       data.flags = MMC_DATA_READ;
+
+       /*
+        * According to the tuning specs, Tuning process
+        * is normally shorter 40 executions of CMD19,
+        * and timeout value should be shorter than 150 ms
+        */
+       data.timeout_ns = 150 * NSEC_PER_MSEC;
+
+       data.sg = &sg;
+       data.sg_len = 1;
+       sg_init_one(&sg, data_buf, size);
+
+       mmc_wait_for_req(host, &mrq);
+
+       if (cmd.error) {
+               err = cmd.error;
+               goto out;
+       }
+
+       if (data.error) {
+               err = data.error;
+               goto out;
+       }
+
+       if (memcmp(data_buf, tuning_block_pattern, size))
+               err = -EIO;
+
+out:
+       kfree(data_buf);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mmc_send_tuning);
+
 static int
 mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
                  u8 len)
@@ -675,3 +748,8 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
 
        return 0;
 }
+
+int mmc_can_ext_csd(struct mmc_card *card)
+{
+       return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3);
+}
index 390dac665b2a6246309415ca019840bee4661b07..6f4b00ed93de9e7176464ee35d1c8a5aec0c6525 100644 (file)
@@ -20,13 +20,13 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
 int mmc_all_send_cid(struct mmc_host *host, u32 *cid);
 int mmc_set_relative_addr(struct mmc_card *card);
 int mmc_send_csd(struct mmc_card *card, u32 *csd);
-int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
 int mmc_send_status(struct mmc_card *card, u32 *status);
 int mmc_send_cid(struct mmc_host *host, u32 *cid);
 int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
 int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
 int mmc_bus_test(struct mmc_card *card, u8 bus_width);
 int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
+int mmc_can_ext_csd(struct mmc_card *card);
 
 #endif
 
index 2439e717655b132654fb67e9509af8d834940ee1..fd0750b5a6343a2f196d14078c2e998c9f80985f 100644 (file)
@@ -980,8 +980,12 @@ static int mmc_sdio_resume(struct mmc_host *host)
        if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) {
                sdio_reset(host);
                mmc_go_idle(host);
-               err = mmc_sdio_init_card(host, host->card->ocr, host->card,
-                                       mmc_card_keep_power(host));
+               mmc_send_if_cond(host, host->card->ocr);
+               err = mmc_send_io_op_cond(host, 0, NULL);
+               if (!err)
+                       err = mmc_sdio_init_card(host, host->card->ocr,
+                                                host->card,
+                                                mmc_card_keep_power(host));
        } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
                /* We may have switched to 1-bit mode during suspend */
                err = sdio_enable_4bit_bus(host->card);
@@ -1035,7 +1039,7 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
 
        sdio_reset(host);
        mmc_go_idle(host);
-       mmc_send_if_cond(host, host->ocr_avail);
+       mmc_send_if_cond(host, host->card->ocr);
 
        ret = mmc_send_io_op_cond(host, 0, NULL);
        if (ret)
index 6da97b170563a8f6bebfba78779d8cb20ffa78bb..60885316afbae7051390b0c86fcf5659173b9376 100644 (file)
@@ -26,6 +26,8 @@
 #include "sdio_cis.h"
 #include "sdio_bus.h"
 
+#define to_sdio_driver(d)      container_of(d, struct sdio_driver, drv)
+
 /* show configuration fields */
 #define sdio_config_attr(field, format_string)                         \
 static ssize_t                                                         \
@@ -196,8 +198,6 @@ static int sdio_bus_remove(struct device *dev)
        return ret;
 }
 
-#ifdef CONFIG_PM
-
 static const struct dev_pm_ops sdio_bus_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
        SET_RUNTIME_PM_OPS(
@@ -207,14 +207,6 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
        )
 };
 
-#define SDIO_PM_OPS_PTR        (&sdio_bus_pm_ops)
-
-#else /* !CONFIG_PM */
-
-#define SDIO_PM_OPS_PTR        NULL
-
-#endif /* !CONFIG_PM */
-
 static struct bus_type sdio_bus_type = {
        .name           = "sdio",
        .dev_groups     = sdio_dev_groups,
@@ -222,7 +214,7 @@ static struct bus_type sdio_bus_type = {
        .uevent         = sdio_bus_uevent,
        .probe          = sdio_bus_probe,
        .remove         = sdio_bus_remove,
-       .pm             = SDIO_PM_OPS_PTR,
+       .pm             = &sdio_bus_pm_ops,
 };
 
 int sdio_register_bus(void)
@@ -295,7 +287,7 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
 static void sdio_acpi_set_handle(struct sdio_func *func)
 {
        struct mmc_host *host = func->card->host;
-       u64 addr = (host->slotno << 16) | func->num;
+       u64 addr = ((u64)host->slotno << 16) | func->num;
 
        acpi_preset_companion(&func->dev, ACPI_COMPANION(host->parent), addr);
 }
index 13860656104b5f58df865ee74501750a3d045c7c..2d6fbdd11803d27e688e7cf8a831e820d83e55d4 100644 (file)
@@ -580,7 +580,7 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND
 config MMC_DW
        tristate "Synopsys DesignWare Memory Card Interface"
        depends on HAS_DMA
-       depends on ARC || ARM || MIPS || COMPILE_TEST
+       depends on ARC || ARM || ARM64 || MIPS || COMPILE_TEST
        help
          This selects support for the Synopsys DesignWare Mobile Storage IP
          block, this provides host support for SD and MMC interfaces, in both
@@ -748,3 +748,8 @@ config MMC_SUNXI
        help
          This selects support for the SD/MMC Host Controller on
          Allwinner sunxi SoCs.
+
+config MMC_TOSHIBA_PCI
+       tristate "Toshiba Type A SD/MMC Card Interface Driver"
+       depends on PCI
+       help
index b09ecfb88269da9f3d1b5796a2b84137e3e10dd5..f7b0a77cf419d8fe2d0bab59f896fe4abef69a7f 100644 (file)
@@ -55,6 +55,7 @@ obj-$(CONFIG_MMC_WMT)         += wmt-sdmmc.o
 obj-$(CONFIG_MMC_MOXART)       += moxart-mmc.o
 obj-$(CONFIG_MMC_SUNXI)                += sunxi-mmc.o
 obj-$(CONFIG_MMC_USDHI6ROL0)   += usdhi6rol0.o
+obj-$(CONFIG_MMC_TOSHIBA_PCI)  += toshsd.o
 
 obj-$(CONFIG_MMC_REALTEK_PCI)  += rtsx_pci_sdmmc.o
 obj-$(CONFIG_MMC_REALTEK_USB)  += rtsx_usb_sdmmc.o
index 77250d4b197923124f9389b811623ea3a6359c28..62aba9af19f49b19a1bd212bd054f2caff60b71d 100644 (file)
 #include <linux/stat.h>
 #include <linux/types.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/platform_data/mmc-atmel-mci.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdio.h>
 
-#include <mach/atmel-mci.h>
 #include <linux/atmel-mci.h>
 #include <linux/atmel_pdc.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <asm/cacheflush.h>
 #include <asm/io.h>
@@ -44,6 +47,8 @@
 
 #include "atmel-mci-regs.h"
 
+#define AUTOSUSPEND_DELAY      50
+
 #define ATMCI_DATA_ERROR_FLAGS (ATMCI_DCRCE | ATMCI_DTOE | ATMCI_OVRE | ATMCI_UNRE)
 #define ATMCI_DMA_THRESHOLD    16
 
@@ -386,20 +391,19 @@ static int atmci_regs_show(struct seq_file *s, void *v)
        if (!buf)
                return -ENOMEM;
 
+       pm_runtime_get_sync(&host->pdev->dev);
+
        /*
         * Grab a more or less consistent snapshot. Note that we're
         * not disabling interrupts, so IMR and SR may not be
         * consistent.
         */
-       ret = clk_prepare_enable(host->mck);
-       if (ret)
-               goto out;
-
        spin_lock_bh(&host->lock);
        memcpy_fromio(buf, host->regs, ATMCI_REGS_SIZE);
        spin_unlock_bh(&host->lock);
 
-       clk_disable_unprepare(host->mck);
+       pm_runtime_mark_last_busy(&host->pdev->dev);
+       pm_runtime_put_autosuspend(&host->pdev->dev);
 
        seq_printf(s, "MR:\t0x%08x%s%s ",
                        buf[ATMCI_MR / 4],
@@ -449,7 +453,6 @@ static int atmci_regs_show(struct seq_file *s, void *v)
                                val & ATMCI_CFG_LSYNC ? " LSYNC" : "");
        }
 
-out:
        kfree(buf);
 
        return ret;
@@ -560,6 +563,9 @@ atmci_of_init(struct platform_device *pdev)
                pdata->slot[slot_id].detect_is_active_high =
                        of_property_read_bool(cnp, "cd-inverted");
 
+               pdata->slot[slot_id].non_removable =
+                       of_property_read_bool(cnp, "non-removable");
+
                pdata->slot[slot_id].wp_pin =
                        of_get_named_gpio(cnp, "wp-gpios", 0);
        }
@@ -1252,6 +1258,8 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        WARN_ON(slot->mrq);
        dev_dbg(&host->pdev->dev, "MRQ: cmd %u\n", mrq->cmd->opcode);
 
+       pm_runtime_get_sync(&host->pdev->dev);
+
        /*
         * We may "know" the card is gone even though there's still an
         * electrical connection. If so, we really need to communicate
@@ -1281,7 +1289,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        struct atmel_mci_slot   *slot = mmc_priv(mmc);
        struct atmel_mci        *host = slot->host;
        unsigned int            i;
-       bool                    unprepare_clk;
+
+       pm_runtime_get_sync(&host->pdev->dev);
 
        slot->sdc_reg &= ~ATMCI_SDCBUS_MASK;
        switch (ios->bus_width) {
@@ -1297,13 +1306,8 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                unsigned int clock_min = ~0U;
                u32 clkdiv;
 
-               clk_prepare(host->mck);
-               unprepare_clk = true;
-
                spin_lock_bh(&host->lock);
                if (!host->mode_reg) {
-                       clk_enable(host->mck);
-                       unprepare_clk = false;
                        atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
                        atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN);
                        if (host->caps.has_cfg_reg)
@@ -1371,8 +1375,6 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        } else {
                bool any_slot_active = false;
 
-               unprepare_clk = false;
-
                spin_lock_bh(&host->lock);
                slot->clock = 0;
                for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
@@ -1385,17 +1387,12 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                        atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
                        if (host->mode_reg) {
                                atmci_readl(host, ATMCI_MR);
-                               clk_disable(host->mck);
-                               unprepare_clk = true;
                        }
                        host->mode_reg = 0;
                }
                spin_unlock_bh(&host->lock);
        }
 
-       if (unprepare_clk)
-               clk_unprepare(host->mck);
-
        switch (ios->power_mode) {
        case MMC_POWER_OFF:
                if (!IS_ERR(mmc->supply.vmmc))
@@ -1421,6 +1418,9 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                 */
                break;
        }
+
+       pm_runtime_mark_last_busy(&host->pdev->dev);
+       pm_runtime_put_autosuspend(&host->pdev->dev);
 }
 
 static int atmci_get_ro(struct mmc_host *mmc)
@@ -1512,6 +1512,9 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq)
        spin_unlock(&host->lock);
        mmc_request_done(prev_mmc, mrq);
        spin_lock(&host->lock);
+
+       pm_runtime_mark_last_busy(&host->pdev->dev);
+       pm_runtime_put_autosuspend(&host->pdev->dev);
 }
 
 static void atmci_command_complete(struct atmel_mci *host,
@@ -2137,7 +2140,7 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int __init atmci_init_slot(struct atmel_mci *host,
+static int atmci_init_slot(struct atmel_mci *host,
                struct mci_slot_pdata *slot_data, unsigned int id,
                u32 sdc_reg, u32 sdio_irq)
 {
@@ -2206,8 +2209,12 @@ static int __init atmci_init_slot(struct atmel_mci *host,
                }
        }
 
-       if (!gpio_is_valid(slot->detect_pin))
-               mmc->caps |= MMC_CAP_NEEDS_POLL;
+       if (!gpio_is_valid(slot->detect_pin)) {
+               if (slot_data->non_removable)
+                       mmc->caps |= MMC_CAP_NONREMOVABLE;
+               else
+                       mmc->caps |= MMC_CAP_NEEDS_POLL;
+       }
 
        if (gpio_is_valid(slot->wp_pin)) {
                if (devm_gpio_request(&host->pdev->dev, slot->wp_pin,
@@ -2265,55 +2272,25 @@ static void atmci_cleanup_slot(struct atmel_mci_slot *slot,
        mmc_free_host(slot->mmc);
 }
 
-static bool atmci_filter(struct dma_chan *chan, void *pdata)
+static int atmci_configure_dma(struct atmel_mci *host)
 {
-       struct mci_platform_data *sl_pdata = pdata;
-       struct mci_dma_data *sl;
-
-       if (!sl_pdata)
-               return false;
+       host->dma.chan = dma_request_slave_channel_reason(&host->pdev->dev,
+                                                       "rxtx");
+       if (IS_ERR(host->dma.chan))
+               return PTR_ERR(host->dma.chan);
+
+       dev_info(&host->pdev->dev, "using %s for DMA transfers\n",
+                dma_chan_name(host->dma.chan));
+
+       host->dma_conf.src_addr = host->mapbase + ATMCI_RDR;
+       host->dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       host->dma_conf.src_maxburst = 1;
+       host->dma_conf.dst_addr = host->mapbase + ATMCI_TDR;
+       host->dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       host->dma_conf.dst_maxburst = 1;
+       host->dma_conf.device_fc = false;
 
-       sl = sl_pdata->dma_slave;
-       if (sl && find_slave_dev(sl) == chan->device->dev) {
-               chan->private = slave_data_ptr(sl);
-               return true;
-       } else {
-               return false;
-       }
-}
-
-static bool atmci_configure_dma(struct atmel_mci *host)
-{
-       struct mci_platform_data        *pdata;
-       dma_cap_mask_t mask;
-
-       if (host == NULL)
-               return false;
-
-       pdata = host->pdev->dev.platform_data;
-
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-
-       host->dma.chan = dma_request_slave_channel_compat(mask, atmci_filter, pdata,
-                                                         &host->pdev->dev, "rxtx");
-       if (!host->dma.chan) {
-               dev_warn(&host->pdev->dev, "no DMA channel available\n");
-               return false;
-       } else {
-               dev_info(&host->pdev->dev,
-                                       "using %s for DMA transfers\n",
-                                       dma_chan_name(host->dma.chan));
-
-               host->dma_conf.src_addr = host->mapbase + ATMCI_RDR;
-               host->dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-               host->dma_conf.src_maxburst = 1;
-               host->dma_conf.dst_addr = host->mapbase + ATMCI_TDR;
-               host->dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-               host->dma_conf.dst_maxburst = 1;
-               host->dma_conf.device_fc = false;
-               return true;
-       }
+       return 0;
 }
 
 /*
@@ -2321,7 +2298,7 @@ static bool atmci_configure_dma(struct atmel_mci *host)
  * HSMCI provides DMA support and a new config register but no more supports
  * PDC.
  */
-static void __init atmci_get_cap(struct atmel_mci *host)
+static void atmci_get_cap(struct atmel_mci *host)
 {
        unsigned int version;
 
@@ -2370,7 +2347,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
        }
 }
 
-static int __init atmci_probe(struct platform_device *pdev)
+static int atmci_probe(struct platform_device *pdev)
 {
        struct mci_platform_data        *pdata;
        struct atmel_mci                *host;
@@ -2417,19 +2394,23 @@ static int __init atmci_probe(struct platform_device *pdev)
 
        atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST);
        host->bus_hz = clk_get_rate(host->mck);
-       clk_disable_unprepare(host->mck);
 
        host->mapbase = regs->start;
 
        tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)host);
 
        ret = request_irq(irq, atmci_interrupt, 0, dev_name(&pdev->dev), host);
-       if (ret)
+       if (ret) {
+               clk_disable_unprepare(host->mck);
                return ret;
+       }
 
        /* Get MCI capabilities and set operations according to it */
        atmci_get_cap(host);
-       if (atmci_configure_dma(host)) {
+       ret = atmci_configure_dma(host);
+       if (ret == -EPROBE_DEFER)
+               goto err_dma_probe_defer;
+       if (ret == 0) {
                host->prepare_data = &atmci_prepare_data_dma;
                host->submit_data = &atmci_submit_data_dma;
                host->stop_transfer = &atmci_stop_transfer_dma;
@@ -2449,6 +2430,12 @@ static int __init atmci_probe(struct platform_device *pdev)
 
        setup_timer(&host->timer, atmci_timeout_timer, (unsigned long)host);
 
+       pm_runtime_get_noresume(&pdev->dev);
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_DELAY);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+
        /* We need at least one slot to succeed */
        nr_slots = 0;
        ret = -ENODEV;
@@ -2491,6 +2478,9 @@ static int __init atmci_probe(struct platform_device *pdev)
                        "Atmel MCI controller at 0x%08lx irq %d, %u slots\n",
                        host->mapbase, irq, nr_slots);
 
+       pm_runtime_mark_last_busy(&host->pdev->dev);
+       pm_runtime_put_autosuspend(&pdev->dev);
+
        return 0;
 
 err_dma_alloc:
@@ -2499,18 +2489,26 @@ err_dma_alloc:
                        atmci_cleanup_slot(host->slot[i], i);
        }
 err_init_slot:
+       clk_disable_unprepare(host->mck);
+
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
+
        del_timer_sync(&host->timer);
-       if (host->dma.chan)
+       if (!IS_ERR(host->dma.chan))
                dma_release_channel(host->dma.chan);
+err_dma_probe_defer:
        free_irq(irq, host);
        return ret;
 }
 
-static int __exit atmci_remove(struct platform_device *pdev)
+static int atmci_remove(struct platform_device *pdev)
 {
        struct atmel_mci        *host = platform_get_drvdata(pdev);
        unsigned int            i;
 
+       pm_runtime_get_sync(&pdev->dev);
+
        if (host->buffer)
                dma_free_coherent(&pdev->dev, host->buf_size,
                                  host->buffer, host->buf_phys_addr);
@@ -2520,41 +2518,62 @@ static int __exit atmci_remove(struct platform_device *pdev)
                        atmci_cleanup_slot(host->slot[i], i);
        }
 
-       clk_prepare_enable(host->mck);
        atmci_writel(host, ATMCI_IDR, ~0UL);
        atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIDIS);
        atmci_readl(host, ATMCI_SR);
-       clk_disable_unprepare(host->mck);
 
        del_timer_sync(&host->timer);
-       if (host->dma.chan)
+       if (!IS_ERR(host->dma.chan))
                dma_release_channel(host->dma.chan);
 
        free_irq(platform_get_irq(pdev, 0), host);
 
+       clk_disable_unprepare(host->mck);
+
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_put_noidle(&pdev->dev);
+
        return 0;
 }
 
-static struct platform_driver atmci_driver = {
-       .remove         = __exit_p(atmci_remove),
-       .driver         = {
-               .name           = "atmel_mci",
-               .of_match_table = of_match_ptr(atmci_dt_ids),
-       },
-};
-
-static int __init atmci_init(void)
+#ifdef CONFIG_PM
+static int atmci_runtime_suspend(struct device *dev)
 {
-       return platform_driver_probe(&atmci_driver, atmci_probe);
+       struct atmel_mci *host = dev_get_drvdata(dev);
+
+       clk_disable_unprepare(host->mck);
+
+       pinctrl_pm_select_sleep_state(dev);
+
+       return 0;
 }
 
-static void __exit atmci_exit(void)
+static int atmci_runtime_resume(struct device *dev)
 {
-       platform_driver_unregister(&atmci_driver);
+       struct atmel_mci *host = dev_get_drvdata(dev);
+
+       pinctrl_pm_select_default_state(dev);
+
+       return clk_prepare_enable(host->mck);
 }
+#endif
 
-late_initcall(atmci_init); /* try to load after dma driver when built-in */
-module_exit(atmci_exit);
+static const struct dev_pm_ops atmci_dev_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                               pm_runtime_force_resume)
+       SET_PM_RUNTIME_PM_OPS(atmci_runtime_suspend, atmci_runtime_resume, NULL)
+};
+
+static struct platform_driver atmci_driver = {
+       .probe          = atmci_probe,
+       .remove         = atmci_remove,
+       .driver         = {
+               .name           = "atmel_mci",
+               .of_match_table = of_match_ptr(atmci_dt_ids),
+               .pm             = &atmci_dev_pm_ops,
+       },
+};
+module_platform_driver(atmci_driver);
 
 MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");
 MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
index 0fbc53ac7eae8fb27f60b12575be4cabbe759c15..509365cb22c6ad0fd0150a87aa9d5edb0d0161e1 100644 (file)
@@ -25,6 +25,7 @@
 #define NUM_PINS(x)                    (x + 2)
 
 #define SDMMC_CLKSEL                   0x09C
+#define SDMMC_CLKSEL64                 0x0A8
 #define SDMMC_CLKSEL_CCLK_SAMPLE(x)    (((x) & 7) << 0)
 #define SDMMC_CLKSEL_CCLK_DRIVE(x)     (((x) & 7) << 16)
 #define SDMMC_CLKSEL_CCLK_DIVIDER(x)   (((x) & 7) << 24)
@@ -65,6 +66,8 @@ enum dw_mci_exynos_type {
        DW_MCI_TYPE_EXYNOS5250,
        DW_MCI_TYPE_EXYNOS5420,
        DW_MCI_TYPE_EXYNOS5420_SMU,
+       DW_MCI_TYPE_EXYNOS7,
+       DW_MCI_TYPE_EXYNOS7_SMU,
 };
 
 /* Exynos implementation specific driver private data */
@@ -95,6 +98,12 @@ static struct dw_mci_exynos_compatible {
        }, {
                .compatible     = "samsung,exynos5420-dw-mshc-smu",
                .ctrl_type      = DW_MCI_TYPE_EXYNOS5420_SMU,
+       }, {
+               .compatible     = "samsung,exynos7-dw-mshc",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS7,
+       }, {
+               .compatible     = "samsung,exynos7-dw-mshc-smu",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS7_SMU,
        },
 };
 
@@ -102,7 +111,8 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
 {
        struct dw_mci_exynos_priv_data *priv = host->priv;
 
-       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU) {
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) {
                mci_writel(host, MPSBEGIN0, 0);
                mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM);
                mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT |
@@ -153,11 +163,22 @@ static int dw_mci_exynos_resume(struct device *dev)
 static int dw_mci_exynos_resume_noirq(struct device *dev)
 {
        struct dw_mci *host = dev_get_drvdata(dev);
+       struct dw_mci_exynos_priv_data *priv = host->priv;
        u32 clksel;
 
-       clksel = mci_readl(host, CLKSEL);
-       if (clksel & SDMMC_CLKSEL_WAKEUP_INT)
-               mci_writel(host, CLKSEL, clksel);
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               clksel = mci_readl(host, CLKSEL64);
+       else
+               clksel = mci_readl(host, CLKSEL);
+
+       if (clksel & SDMMC_CLKSEL_WAKEUP_INT) {
+               if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+                       mci_writel(host, CLKSEL64, clksel);
+               else
+                       mci_writel(host, CLKSEL, clksel);
+       }
 
        return 0;
 }
@@ -169,6 +190,7 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
 
 static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
 {
+       struct dw_mci_exynos_priv_data *priv = host->priv;
        /*
         * Exynos4412 and Exynos5250 extends the use of CMD register with the
         * use of bit 29 (which is reserved on standard MSHC controllers) for
@@ -176,8 +198,14 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
         * HOLD register should be bypassed in case there is no phase shift
         * applied on CMD/DATA that is sent to the card.
         */
-       if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL)))
-               *cmdr |= SDMMC_CMD_USE_HOLD_REG;
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) {
+               if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL64)))
+                       *cmdr |= SDMMC_CMD_USE_HOLD_REG;
+        } else {
+               if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL)))
+                       *cmdr |= SDMMC_CMD_USE_HOLD_REG;
+       }
 }
 
 static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
@@ -188,12 +216,20 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
        u8 div = priv->ciu_div + 1;
 
        if (ios->timing == MMC_TIMING_MMC_DDR52) {
-               mci_writel(host, CLKSEL, priv->ddr_timing);
+               if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+                       mci_writel(host, CLKSEL64, priv->ddr_timing);
+               else
+                       mci_writel(host, CLKSEL, priv->ddr_timing);
                /* Should be double rate for DDR mode */
                if (ios->bus_width == MMC_BUS_WIDTH_8)
                        wanted <<= 1;
        } else {
-               mci_writel(host, CLKSEL, priv->sdr_timing);
+               if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+                       mci_writel(host, CLKSEL64, priv->sdr_timing);
+               else
+                       mci_writel(host, CLKSEL, priv->sdr_timing);
        }
 
        /* Don't care if wanted clock is zero */
@@ -265,26 +301,51 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host)
 
 static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host)
 {
-       return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL));
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64));
+       else
+               return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL));
 }
 
 static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
 {
        u32 clksel;
-       clksel = mci_readl(host, CLKSEL);
+       struct dw_mci_exynos_priv_data *priv = host->priv;
+
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               clksel = mci_readl(host, CLKSEL64);
+       else
+               clksel = mci_readl(host, CLKSEL);
        clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
-       mci_writel(host, CLKSEL, clksel);
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               mci_writel(host, CLKSEL64, clksel);
+       else
+               mci_writel(host, CLKSEL, clksel);
 }
 
 static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
 {
+       struct dw_mci_exynos_priv_data *priv = host->priv;
        u32 clksel;
        u8 sample;
 
-       clksel = mci_readl(host, CLKSEL);
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               clksel = mci_readl(host, CLKSEL64);
+       else
+               clksel = mci_readl(host, CLKSEL);
        sample = (clksel + 1) & 0x7;
        clksel = (clksel & ~0x7) | sample;
-       mci_writel(host, CLKSEL, clksel);
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU)
+               mci_writel(host, CLKSEL64, clksel);
+       else
+               mci_writel(host, CLKSEL, clksel);
        return sample;
 }
 
@@ -411,6 +472,10 @@ static const struct of_device_id dw_mci_exynos_match[] = {
                        .data = &exynos_drv_data, },
        { .compatible = "samsung,exynos5420-dw-mshc-smu",
                        .data = &exynos_drv_data, },
+       { .compatible = "samsung,exynos7-dw-mshc",
+                       .data = &exynos_drv_data, },
+       { .compatible = "samsung,exynos7-dw-mshc-smu",
+                       .data = &exynos_drv_data, },
        {},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
index 8b6572162ed960ed9d8c0ead021dda6a574c664e..ec6dbcdec693beacc6fef823be15c515645e83a6 100644 (file)
@@ -35,6 +35,10 @@ static const struct dw_mci_drv_data socfpga_drv_data = {
        .prepare_command        = dw_mci_pltfm_prepare_command,
 };
 
+static const struct dw_mci_drv_data pistachio_drv_data = {
+       .prepare_command        = dw_mci_pltfm_prepare_command,
+};
+
 int dw_mci_pltfm_register(struct platform_device *pdev,
                          const struct dw_mci_drv_data *drv_data)
 {
@@ -90,6 +94,8 @@ static const struct of_device_id dw_mci_pltfm_match[] = {
        { .compatible = "snps,dw-mshc", },
        { .compatible = "altr,socfpga-dw-mshc",
                .data = &socfpga_drv_data },
+       { .compatible = "img,pistachio-dw-mshc",
+               .data = &pistachio_drv_data },
        {},
 };
 MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
index f0c2cb1a210d73ad284584b938fe044412cda4e4..5650ac488cf31c69df061322f870be2f746462aa 100644 (file)
@@ -37,6 +37,9 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
        unsigned int cclkin;
        u32 bus_hz;
 
+       if (ios->clock == 0)
+               return;
+
        /*
         * cclkin: source clock of mmc controller
         * bus_hz: card interface clock generated by CLKGEN
@@ -65,14 +68,24 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
        }
 }
 
+static int dw_mci_rockchip_init(struct dw_mci *host)
+{
+       /* It is slot 8 on Rockchip SoCs */
+       host->sdio_id0 = 8;
+
+       return 0;
+}
+
 static const struct dw_mci_drv_data rk2928_drv_data = {
        .prepare_command        = dw_mci_rockchip_prepare_command,
+       .init                   = dw_mci_rockchip_init,
 };
 
 static const struct dw_mci_drv_data rk3288_drv_data = {
        .prepare_command        = dw_mci_rockchip_prepare_command,
        .set_ios                = dw_mci_rk3288_set_ios,
        .setup_clock    = dw_mci_rk3288_setup_clock,
+       .init                   = dw_mci_rockchip_init,
 };
 
 static const struct of_device_id dw_mci_rockchip_match[] = {
index 69f0cc68d5b2727412c3b430d0f5eaee99072941..67c04518ec4c38c0657e2fef713e1b6cd51348f6 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/mmc/dw_mmc.h>
 #include <linux/bitops.h>
 #include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/mmc/slot-gpio.h>
                                 SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \
                                 SDMMC_IDMAC_INT_TI)
 
+struct idmac_desc_64addr {
+       u32             des0;   /* Control Descriptor */
+
+       u32             des1;   /* Reserved */
+
+       u32             des2;   /*Buffer sizes */
+#define IDMAC_64ADDR_SET_BUFFER1_SIZE(d, s) \
+       ((d)->des2 = ((d)->des2 & 0x03ffe000) | ((s) & 0x1fff))
+
+       u32             des3;   /* Reserved */
+
+       u32             des4;   /* Lower 32-bits of Buffer Address Pointer 1*/
+       u32             des5;   /* Upper 32-bits of Buffer Address Pointer 1*/
+
+       u32             des6;   /* Lower 32-bits of Next Descriptor Address */
+       u32             des7;   /* Upper 32-bits of Next Descriptor Address */
+};
+
 struct idmac_desc {
        u32             des0;   /* Control Descriptor */
 #define IDMAC_DES0_DIC BIT(1)
@@ -83,6 +100,7 @@ struct idmac_desc {
 #endif /* CONFIG_MMC_DW_IDMAC */
 
 static bool dw_mci_reset(struct dw_mci *host);
+static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset);
 
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -414,30 +432,66 @@ static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
                                    unsigned int sg_len)
 {
        int i;
-       struct idmac_desc *desc = host->sg_cpu;
+       if (host->dma_64bit_address == 1) {
+               struct idmac_desc_64addr *desc = host->sg_cpu;
 
-       for (i = 0; i < sg_len; i++, desc++) {
-               unsigned int length = sg_dma_len(&data->sg[i]);
-               u32 mem_addr = sg_dma_address(&data->sg[i]);
+               for (i = 0; i < sg_len; i++, desc++) {
+                       unsigned int length = sg_dma_len(&data->sg[i]);
+                       u64 mem_addr = sg_dma_address(&data->sg[i]);
 
-               /* Set the OWN bit and disable interrupts for this descriptor */
-               desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH;
+                       /*
+                        * Set the OWN bit and disable interrupts for this
+                        * descriptor
+                        */
+                       desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+                                               IDMAC_DES0_CH;
+                       /* Buffer length */
+                       IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, length);
+
+                       /* Physical address to DMA to/from */
+                       desc->des4 = mem_addr & 0xffffffff;
+                       desc->des5 = mem_addr >> 32;
+               }
 
-               /* Buffer length */
-               IDMAC_SET_BUFFER1_SIZE(desc, length);
+               /* Set first descriptor */
+               desc = host->sg_cpu;
+               desc->des0 |= IDMAC_DES0_FD;
 
-               /* Physical address to DMA to/from */
-               desc->des2 = mem_addr;
-       }
+               /* Set last descriptor */
+               desc = host->sg_cpu + (i - 1) *
+                               sizeof(struct idmac_desc_64addr);
+               desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+               desc->des0 |= IDMAC_DES0_LD;
 
-       /* Set first descriptor */
-       desc = host->sg_cpu;
-       desc->des0 |= IDMAC_DES0_FD;
+       } else {
+               struct idmac_desc *desc = host->sg_cpu;
+
+               for (i = 0; i < sg_len; i++, desc++) {
+                       unsigned int length = sg_dma_len(&data->sg[i]);
+                       u32 mem_addr = sg_dma_address(&data->sg[i]);
+
+                       /*
+                        * Set the OWN bit and disable interrupts for this
+                        * descriptor
+                        */
+                       desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
+                                               IDMAC_DES0_CH;
+                       /* Buffer length */
+                       IDMAC_SET_BUFFER1_SIZE(desc, length);
 
-       /* Set last descriptor */
-       desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
-       desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
-       desc->des0 |= IDMAC_DES0_LD;
+                       /* Physical address to DMA to/from */
+                       desc->des2 = mem_addr;
+               }
+
+               /* Set first descriptor */
+               desc = host->sg_cpu;
+               desc->des0 |= IDMAC_DES0_FD;
+
+               /* Set last descriptor */
+               desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc);
+               desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
+               desc->des0 |= IDMAC_DES0_LD;
+       }
 
        wmb();
 }
@@ -448,6 +502,10 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
 
        dw_mci_translate_sglist(host, host->data, sg_len);
 
+       /* Make sure to reset DMA in case we did PIO before this */
+       dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET);
+       dw_mci_idmac_reset(host);
+
        /* Select IDMAC interface */
        temp = mci_readl(host, CTRL);
        temp |= SDMMC_CTRL_USE_IDMAC;
@@ -466,29 +524,71 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
 
 static int dw_mci_idmac_init(struct dw_mci *host)
 {
-       struct idmac_desc *p;
        int i;
 
-       /* Number of descriptors in the ring buffer */
-       host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
+       if (host->dma_64bit_address == 1) {
+               struct idmac_desc_64addr *p;
+               /* Number of descriptors in the ring buffer */
+               host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc_64addr);
+
+               /* Forward link the descriptor list */
+               for (i = 0, p = host->sg_cpu; i < host->ring_size - 1;
+                                                               i++, p++) {
+                       p->des6 = (host->sg_dma +
+                                       (sizeof(struct idmac_desc_64addr) *
+                                                       (i + 1))) & 0xffffffff;
+
+                       p->des7 = (u64)(host->sg_dma +
+                                       (sizeof(struct idmac_desc_64addr) *
+                                                       (i + 1))) >> 32;
+                       /* Initialize reserved and buffer size fields to "0" */
+                       p->des1 = 0;
+                       p->des2 = 0;
+                       p->des3 = 0;
+               }
+
+               /* Set the last descriptor as the end-of-ring descriptor */
+               p->des6 = host->sg_dma & 0xffffffff;
+               p->des7 = (u64)host->sg_dma >> 32;
+               p->des0 = IDMAC_DES0_ER;
+
+       } else {
+               struct idmac_desc *p;
+               /* Number of descriptors in the ring buffer */
+               host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
 
-       /* Forward link the descriptor list */
-       for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
-               p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
+               /* Forward link the descriptor list */
+               for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
+                       p->des3 = host->sg_dma + (sizeof(struct idmac_desc) *
+                                                               (i + 1));
 
-       /* Set the last descriptor as the end-of-ring descriptor */
-       p->des3 = host->sg_dma;
-       p->des0 = IDMAC_DES0_ER;
+               /* Set the last descriptor as the end-of-ring descriptor */
+               p->des3 = host->sg_dma;
+               p->des0 = IDMAC_DES0_ER;
+       }
 
        dw_mci_idmac_reset(host);
 
-       /* Mask out interrupts - get Tx & Rx complete only */
-       mci_writel(host, IDSTS, IDMAC_INT_CLR);
-       mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI |
-                  SDMMC_IDMAC_INT_TI);
+       if (host->dma_64bit_address == 1) {
+               /* Mask out interrupts - get Tx & Rx complete only */
+               mci_writel(host, IDSTS64, IDMAC_INT_CLR);
+               mci_writel(host, IDINTEN64, SDMMC_IDMAC_INT_NI |
+                               SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+               /* Set the descriptor base address */
+               mci_writel(host, DBADDRL, host->sg_dma & 0xffffffff);
+               mci_writel(host, DBADDRU, (u64)host->sg_dma >> 32);
+
+       } else {
+               /* Mask out interrupts - get Tx & Rx complete only */
+               mci_writel(host, IDSTS, IDMAC_INT_CLR);
+               mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI |
+                               SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI);
+
+               /* Set the descriptor base address */
+               mci_writel(host, DBADDR, host->sg_dma);
+       }
 
-       /* Set the descriptor base address */
-       mci_writel(host, DBADDR, host->sg_dma);
        return 0;
 }
 
@@ -626,6 +726,13 @@ static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data)
 
        WARN_ON(!(data->flags & MMC_DATA_READ));
 
+       /*
+        * CDTHRCTL doesn't exist prior to 240A (in fact that register offset is
+        * in the FIFO region, so we really shouldn't access it).
+        */
+       if (host->verid < DW_MMC_240A)
+               return;
+
        if (host->timing != MMC_TIMING_MMC_HS200 &&
            host->timing != MMC_TIMING_UHS_SDR104)
                goto disable;
@@ -819,7 +926,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
 
                /* enable clock; only low power if no SDIO */
                clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
-               if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
+               if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->sdio_id)))
                        clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
                mci_writel(host, CLKENA, clk_en_a);
 
@@ -1075,7 +1182,7 @@ static int dw_mci_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
                ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv);
 
                if (ret) {
-                       dev_err(&mmc->class_dev,
+                       dev_dbg(&mmc->class_dev,
                                         "Regulator set error %d: %d - %d\n",
                                         ret, min_uv, max_uv);
                        return ret;
@@ -1180,10 +1287,10 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
                dw_mci_disable_low_power(slot);
 
                mci_writel(host, INTMASK,
-                          (int_mask | SDMMC_INT_SDIO(slot->id)));
+                          (int_mask | SDMMC_INT_SDIO(slot->sdio_id)));
        } else {
                mci_writel(host, INTMASK,
-                          (int_mask & ~SDMMC_INT_SDIO(slot->id)));
+                          (int_mask & ~SDMMC_INT_SDIO(slot->sdio_id)));
        }
 }
 
@@ -1954,6 +2061,23 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
        tasklet_schedule(&host->tasklet);
 }
 
+static void dw_mci_handle_cd(struct dw_mci *host)
+{
+       int i;
+
+       for (i = 0; i < host->num_slots; i++) {
+               struct dw_mci_slot *slot = host->slot[i];
+
+               if (!slot)
+                       continue;
+
+               if (slot->mmc->ops->card_event)
+                       slot->mmc->ops->card_event(slot->mmc);
+               mmc_detect_change(slot->mmc,
+                       msecs_to_jiffies(host->pdata->detect_delay_ms));
+       }
+}
+
 static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 {
        struct dw_mci *host = dev_id;
@@ -2029,14 +2153,15 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
                if (pending & SDMMC_INT_CD) {
                        mci_writel(host, RINTSTS, SDMMC_INT_CD);
-                       queue_work(host->card_workqueue, &host->card_work);
+                       dw_mci_handle_cd(host);
                }
 
                /* Handle SDIO Interrupts */
                for (i = 0; i < host->num_slots; i++) {
                        struct dw_mci_slot *slot = host->slot[i];
-                       if (pending & SDMMC_INT_SDIO(i)) {
-                               mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i));
+                       if (pending & SDMMC_INT_SDIO(slot->sdio_id)) {
+                               mci_writel(host, RINTSTS,
+                                          SDMMC_INT_SDIO(slot->sdio_id));
                                mmc_signal_sdio_irq(slot->mmc);
                        }
                }
@@ -2045,99 +2170,28 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
 #ifdef CONFIG_MMC_DW_IDMAC
        /* Handle DMA interrupts */
-       pending = mci_readl(host, IDSTS);
-       if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
-               mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI);
-               mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
-               host->dma_ops->complete(host);
+       if (host->dma_64bit_address == 1) {
+               pending = mci_readl(host, IDSTS64);
+               if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+                       mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_TI |
+                                                       SDMMC_IDMAC_INT_RI);
+                       mci_writel(host, IDSTS64, SDMMC_IDMAC_INT_NI);
+                       host->dma_ops->complete(host);
+               }
+       } else {
+               pending = mci_readl(host, IDSTS);
+               if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) {
+                       mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI |
+                                                       SDMMC_IDMAC_INT_RI);
+                       mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI);
+                       host->dma_ops->complete(host);
+               }
        }
 #endif
 
        return IRQ_HANDLED;
 }
 
-static void dw_mci_work_routine_card(struct work_struct *work)
-{
-       struct dw_mci *host = container_of(work, struct dw_mci, card_work);
-       int i;
-
-       for (i = 0; i < host->num_slots; i++) {
-               struct dw_mci_slot *slot = host->slot[i];
-               struct mmc_host *mmc = slot->mmc;
-               struct mmc_request *mrq;
-               int present;
-
-               present = dw_mci_get_cd(mmc);
-               while (present != slot->last_detect_state) {
-                       dev_dbg(&slot->mmc->class_dev, "card %s\n",
-                               present ? "inserted" : "removed");
-
-                       spin_lock_bh(&host->lock);
-
-                       /* Card change detected */
-                       slot->last_detect_state = present;
-
-                       /* Clean up queue if present */
-                       mrq = slot->mrq;
-                       if (mrq) {
-                               if (mrq == host->mrq) {
-                                       host->data = NULL;
-                                       host->cmd = NULL;
-
-                                       switch (host->state) {
-                                       case STATE_IDLE:
-                                       case STATE_WAITING_CMD11_DONE:
-                                               break;
-                                       case STATE_SENDING_CMD11:
-                                       case STATE_SENDING_CMD:
-                                               mrq->cmd->error = -ENOMEDIUM;
-                                               if (!mrq->data)
-                                                       break;
-                                               /* fall through */
-                                       case STATE_SENDING_DATA:
-                                               mrq->data->error = -ENOMEDIUM;
-                                               dw_mci_stop_dma(host);
-                                               break;
-                                       case STATE_DATA_BUSY:
-                                       case STATE_DATA_ERROR:
-                                               if (mrq->data->error == -EINPROGRESS)
-                                                       mrq->data->error = -ENOMEDIUM;
-                                               /* fall through */
-                                       case STATE_SENDING_STOP:
-                                               if (mrq->stop)
-                                                       mrq->stop->error = -ENOMEDIUM;
-                                               break;
-                                       }
-
-                                       dw_mci_request_end(host, mrq);
-                               } else {
-                                       list_del(&slot->queue_node);
-                                       mrq->cmd->error = -ENOMEDIUM;
-                                       if (mrq->data)
-                                               mrq->data->error = -ENOMEDIUM;
-                                       if (mrq->stop)
-                                               mrq->stop->error = -ENOMEDIUM;
-
-                                       spin_unlock(&host->lock);
-                                       mmc_request_done(slot->mmc, mrq);
-                                       spin_lock(&host->lock);
-                               }
-                       }
-
-                       /* Power down slot */
-                       if (present == 0)
-                               dw_mci_reset(host);
-
-                       spin_unlock_bh(&host->lock);
-
-                       present = dw_mci_get_cd(mmc);
-               }
-
-               mmc_detect_change(slot->mmc,
-                       msecs_to_jiffies(host->pdata->detect_delay_ms));
-       }
-}
-
 #ifdef CONFIG_OF
 /* given a slot id, find out the device node representing that slot */
 static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
@@ -2206,6 +2260,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 
        slot = mmc_priv(mmc);
        slot->id = id;
+       slot->sdio_id = host->sdio_id0 + id;
        slot->mmc = mmc;
        slot->host = host;
        host->slot[id] = slot;
@@ -2289,9 +2344,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        dw_mci_init_debugfs(slot);
 #endif
 
-       /* Card initially undetected */
-       slot->last_detect_state = 0;
-
        return 0;
 
 err_host_allocated:
@@ -2309,6 +2361,22 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
 
 static void dw_mci_init_dma(struct dw_mci *host)
 {
+       int addr_config;
+       /* Check ADDR_CONFIG bit in HCON to find IDMAC address bus width */
+       addr_config = (mci_readl(host, HCON) >> 27) & 0x01;
+
+       if (addr_config == 1) {
+               /* host supports IDMAC in 64-bit address mode */
+               host->dma_64bit_address = 1;
+               dev_info(host->dev, "IDMAC supports 64-bit address mode.\n");
+               if (!dma_set_mask(host->dev, DMA_BIT_MASK(64)))
+                       dma_set_coherent_mask(host->dev, DMA_BIT_MASK(64));
+       } else {
+               /* host supports IDMAC in 32-bit address mode */
+               host->dma_64bit_address = 0;
+               dev_info(host->dev, "IDMAC supports 32-bit address mode.\n");
+       }
+
        /* Alloc memory for sg translation */
        host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
                                          &host->sg_dma, GFP_KERNEL);
@@ -2672,17 +2740,10 @@ int dw_mci_probe(struct dw_mci *host)
                host->data_offset = DATA_240A_OFFSET;
 
        tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
-       host->card_workqueue = alloc_workqueue("dw-mci-card",
-                       WQ_MEM_RECLAIM, 1);
-       if (!host->card_workqueue) {
-               ret = -ENOMEM;
-               goto err_dmaunmap;
-       }
-       INIT_WORK(&host->card_work, dw_mci_work_routine_card);
        ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
                               host->irq_flags, "dw-mci", host);
        if (ret)
-               goto err_workqueue;
+               goto err_dmaunmap;
 
        if (host->pdata->num_slots)
                host->num_slots = host->pdata->num_slots;
@@ -2718,7 +2779,7 @@ int dw_mci_probe(struct dw_mci *host)
        } else {
                dev_dbg(host->dev, "attempted to initialize %d slots, "
                                        "but failed on all\n", host->num_slots);
-               goto err_workqueue;
+               goto err_dmaunmap;
        }
 
        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
@@ -2726,9 +2787,6 @@ int dw_mci_probe(struct dw_mci *host)
 
        return 0;
 
-err_workqueue:
-       destroy_workqueue(host->card_workqueue);
-
 err_dmaunmap:
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
@@ -2762,8 +2820,6 @@ void dw_mci_remove(struct dw_mci *host)
        mci_writel(host, CLKENA, 0);
        mci_writel(host, CLKSRC, 0);
 
-       destroy_workqueue(host->card_workqueue);
-
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
 
index 01b99e8a919073b10dace3daea7b8444f70b0e9b..0d0f7a271d635e711b64a5f1721b61828faad7df 100644 (file)
 #define SDMMC_BUFADDR          0x098
 #define SDMMC_CDTHRCTL         0x100
 #define SDMMC_DATA(x)          (x)
+/*
+* Registers to support idmac 64-bit address mode
+*/
+#define SDMMC_DBADDRL          0x088
+#define SDMMC_DBADDRU          0x08c
+#define SDMMC_IDSTS64          0x090
+#define SDMMC_IDINTEN64                0x094
+#define SDMMC_DSCADDRL         0x098
+#define SDMMC_DSCADDRU         0x09c
+#define SDMMC_BUFADDRL         0x0A0
+#define SDMMC_BUFADDRU         0x0A4
 
 /*
  * Data offset is difference according to Version
@@ -214,7 +225,7 @@ extern int dw_mci_resume(struct dw_mci *host);
  *     with CONFIG_MMC_CLKGATE.
  * @flags: Random state bits associated with the slot.
  * @id: Number of this slot.
- * @last_detect_state: Most recently observed card detect state.
+ * @sdio_id: Number of this slot in the SDIO interrupt registers.
  */
 struct dw_mci_slot {
        struct mmc_host         *mmc;
@@ -234,7 +245,7 @@ struct dw_mci_slot {
 #define DW_MMC_CARD_PRESENT    0
 #define DW_MMC_CARD_NEED_INIT  1
        int                     id;
-       int                     last_detect_state;
+       int                     sdio_id;
 };
 
 struct dw_mci_tuning_data {
index 43af791e2e45e1b29a94fc364978c99a315f2ffa..53bf7a4b58394846b3e7031d1d3e461666bcdb93 100644 (file)
@@ -736,8 +736,15 @@ static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq,
                        chan = host->dma_tx_channel;
                dmaengine_terminate_all(chan);
 
+               if (host->dma_desc_current == next->dma_desc)
+                       host->dma_desc_current = NULL;
+
+               if (host->dma_current == next->dma_chan)
+                       host->dma_current = NULL;
+
                next->dma_desc = NULL;
                next->dma_chan = NULL;
+               data->host_cookie = 0;
        }
 }
 
index 9405ecdaf6cf952f4a5d2cbd0c75f0d745915ae4..90c60fd4ff6e22f9503fd57e6f8df7b18faf659f 100644 (file)
@@ -1360,7 +1360,7 @@ msmsdcc_probe(struct platform_device *pdev)
        if (ret)
                goto cmd_irq_free;
 
-       mmc_set_drvdata(pdev, mmc);
+       platform_set_drvdata(pdev, mmc);
        mmc_add_host(mmc);
 
        pr_info("%s: Qualcomm MSM SDCC at 0x%016llx irq %d,%d dma %d\n",
@@ -1419,7 +1419,7 @@ ioremap_free:
 static int
 msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
 {
-       struct mmc_host *mmc = mmc_get_drvdata(dev);
+       struct mmc_host *mmc = platform_get_drvdata(dev);
 
        if (mmc) {
                struct msmsdcc_host *host = mmc_priv(mmc);
@@ -1437,7 +1437,7 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
 static int
 msmsdcc_resume(struct platform_device *dev)
 {
-       struct mmc_host *mmc = mmc_get_drvdata(dev);
+       struct mmc_host *mmc = platform_get_drvdata(dev);
 
        if (mmc) {
                struct msmsdcc_host *host = mmc_priv(mmc);
index 6b4c5ad3b3939c6103871eb790d304d1a1ad4f4d..4f8618f4522df2db6e08c4680dd0f08e75e8d7dd 100644 (file)
@@ -111,10 +111,15 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data)
        mvsd_write(MVSD_BLK_COUNT, data->blocks);
        mvsd_write(MVSD_BLK_SIZE, data->blksz);
 
-       if (nodma || (data->blksz | data->sg->offset) & 3) {
+       if (nodma || (data->blksz | data->sg->offset) & 3 ||
+           ((!(data->flags & MMC_DATA_READ) && data->sg->offset & 0x3f))) {
                /*
                 * We cannot do DMA on a buffer which offset or size
                 * is not aligned on a 4-byte boundary.
+                *
+                * It also appears the host to card DMA can corrupt
+                * data when the buffer is not aligned on a 64 byte
+                * boundary.
                 */
                host->pio_size = data->blocks * data->blksz;
                host->pio_ptr = sg_virt(data->sg);
index ad111422ad55b9dbbf3b83dacd0aaf33c286a204..5316d9b9e7b42f0bb1f5be0f8d16974ae93da041 100644 (file)
@@ -373,13 +373,9 @@ static void mxcmci_dma_callback(void *data)
        del_timer(&host->watchdog);
 
        stat = mxcmci_readl(host, MMC_REG_STATUS);
-       mxcmci_writel(host, stat & ~STATUS_DATA_TRANS_DONE, MMC_REG_STATUS);
 
        dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
 
-       if (stat & STATUS_READ_OP_DONE)
-               mxcmci_writel(host, STATUS_READ_OP_DONE, MMC_REG_STATUS);
-
        mxcmci_data_done(host, stat);
 }
 
@@ -743,10 +739,8 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
        sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
        spin_unlock_irqrestore(&host->lock, flags);
 
-       if (mxcmci_use_dma(host) &&
-           (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE)))
-               mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
-                       MMC_REG_STATUS);
+       if (mxcmci_use_dma(host) && (stat & (STATUS_WRITE_OP_DONE)))
+               mxcmci_writel(host, STATUS_WRITE_OP_DONE, MMC_REG_STATUS);
 
        if (sdio_irq) {
                mxcmci_writel(host, STATUS_SDIO_INT_ACTIVE, MMC_REG_STATUS);
@@ -756,8 +750,7 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
        if (stat & STATUS_END_CMD_RESP)
                mxcmci_cmd_done(host, stat);
 
-       if (mxcmci_use_dma(host) &&
-                 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) {
+       if (mxcmci_use_dma(host) && (stat & STATUS_WRITE_OP_DONE)) {
                del_timer(&host->watchdog);
                mxcmci_data_done(host, stat);
        }
@@ -1084,12 +1077,14 @@ static int mxcmci_probe(struct platform_device *pdev)
                dat3_card_detect = true;
 
        ret = mmc_regulator_get_supply(mmc);
-       if (ret) {
-               if (pdata && ret != -EPROBE_DEFER)
-                       mmc->ocr_avail = pdata->ocr_avail ? :
-                               MMC_VDD_32_33 | MMC_VDD_33_34;
+       if (ret == -EPROBE_DEFER)
+               goto out_free;
+
+       if (!mmc->ocr_avail) {
+               if (pdata && pdata->ocr_avail)
+                       mmc->ocr_avail = pdata->ocr_avail;
                else
-                       goto out_free;
+                       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
        }
 
        if (dat3_card_detect)
index cd74e5143c36a2d2c90641e45723920364ca08b1..60c4ca97a727785bb5dcfbd292a023d04cd3b5d0 100644 (file)
@@ -581,10 +581,9 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        struct regulator *reg_vmmc;
        struct mxs_ssp *ssp;
 
-       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq_err = platform_get_irq(pdev, 0);
-       if (!iores || irq_err < 0)
-               return -EINVAL;
+       if (irq_err < 0)
+               return irq_err;
 
        mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev);
        if (!mmc)
@@ -593,6 +592,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        host = mmc_priv(mmc);
        ssp = &host->ssp;
        ssp->dev = &pdev->dev;
+       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ssp->base = devm_ioremap_resource(&pdev->dev, iores);
        if (IS_ERR(ssp->base)) {
                ret = PTR_ERR(ssp->base);
@@ -619,7 +619,9 @@ static int mxs_mmc_probe(struct platform_device *pdev)
                ret = PTR_ERR(ssp->clk);
                goto out_mmc_free;
        }
-       clk_prepare_enable(ssp->clk);
+       ret = clk_prepare_enable(ssp->clk);
+       if (ret)
+               goto out_mmc_free;
 
        ret = mxs_mmc_reset(host);
        if (ret) {
@@ -660,7 +662,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, mmc);
 
        ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0,
-                              DRIVER_NAME, host);
+                              dev_name(&pdev->dev), host);
        if (ret)
                goto out_free_dma;
 
@@ -702,7 +704,7 @@ static int mxs_mmc_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int mxs_mmc_suspend(struct device *dev)
 {
        struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -719,25 +721,19 @@ static int mxs_mmc_resume(struct device *dev)
        struct mxs_mmc_host *host = mmc_priv(mmc);
        struct mxs_ssp *ssp = &host->ssp;
 
-       clk_prepare_enable(ssp->clk);
-       return 0;
+       return clk_prepare_enable(ssp->clk);
 }
-
-static const struct dev_pm_ops mxs_mmc_pm_ops = {
-       .suspend        = mxs_mmc_suspend,
-       .resume         = mxs_mmc_resume,
-};
 #endif
 
+static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume);
+
 static struct platform_driver mxs_mmc_driver = {
        .probe          = mxs_mmc_probe,
        .remove         = mxs_mmc_remove,
        .id_table       = mxs_ssp_ids,
        .driver         = {
                .name   = DRIVER_NAME,
-#ifdef CONFIG_PM
                .pm     = &mxs_mmc_pm_ops,
-#endif
                .of_match_table = mxs_mmc_dt_ids,
        },
 };
index df27bb4fc098b218a298e70493aa5c22131c7b52..7c71dcdcba8bdc4d5e59ff124e9f793f1dbf296d 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
-#include <linux/platform_data/mmc-omap.h>
+#include <linux/platform_data/hsmmc-omap.h>
 
 /* OMAP HSMMC Host Controller Registers */
 #define OMAP_HSMMC_SYSSTATUS   0x0014
  * omap.c controller driver. Luckily this is not currently done on any known
  * omap_hsmmc.c device.
  */
-#define mmc_slot(host)         (host->pdata->slots[host->slot_id])
+#define mmc_pdata(host)                host->pdata
 
 /*
  * MMC Host controller read/write API's
@@ -207,7 +207,6 @@ struct omap_hsmmc_host {
        int                     use_dma, dma_ch;
        struct dma_chan         *tx_chan;
        struct dma_chan         *rx_chan;
-       int                     slot_id;
        int                     response_busy;
        int                     context_loss;
        int                     protect_card;
@@ -220,7 +219,26 @@ struct omap_hsmmc_host {
 #define HSMMC_SDIO_IRQ_ENABLED (1 << 1)        /* SDIO irq enabled */
 #define HSMMC_WAKE_IRQ_ENABLED (1 << 2)
        struct omap_hsmmc_next  next_data;
-       struct  omap_mmc_platform_data  *pdata;
+       struct  omap_hsmmc_platform_data        *pdata;
+
+       /* To handle board related suspend/resume functionality for MMC */
+       int (*suspend)(struct device *dev);
+       int (*resume)(struct device *dev);
+
+       /* return MMC cover switch state, can be NULL if not supported.
+        *
+        * possible return values:
+        *   0 - closed
+        *   1 - open
+        */
+       int (*get_cover_state)(struct device *dev);
+
+       /* Card detection IRQs */
+       int card_detect_irq;
+
+       int (*card_detect)(struct device *dev);
+       int (*get_ro)(struct device *dev);
+
 };
 
 struct omap_mmc_of_data {
@@ -230,50 +248,48 @@ struct omap_mmc_of_data {
 
 static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host);
 
-static int omap_hsmmc_card_detect(struct device *dev, int slot)
+static int omap_hsmmc_card_detect(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
-       struct omap_mmc_platform_data *mmc = host->pdata;
+       struct omap_hsmmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
-       return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
+       return !gpio_get_value_cansleep(mmc->switch_pin);
 }
 
-static int omap_hsmmc_get_wp(struct device *dev, int slot)
+static int omap_hsmmc_get_wp(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
-       struct omap_mmc_platform_data *mmc = host->pdata;
+       struct omap_hsmmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes write protect signal is active-high */
-       return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
+       return gpio_get_value_cansleep(mmc->gpio_wp);
 }
 
-static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
+static int omap_hsmmc_get_cover_state(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
-       struct omap_mmc_platform_data *mmc = host->pdata;
+       struct omap_hsmmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
-       return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
+       return !gpio_get_value_cansleep(mmc->switch_pin);
 }
 
 #ifdef CONFIG_PM
 
-static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
+static int omap_hsmmc_suspend_cdirq(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
-       struct omap_mmc_platform_data *mmc = host->pdata;
 
-       disable_irq(mmc->slots[0].card_detect_irq);
+       disable_irq(host->card_detect_irq);
        return 0;
 }
 
-static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
+static int omap_hsmmc_resume_cdirq(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
-       struct omap_mmc_platform_data *mmc = host->pdata;
 
-       enable_irq(mmc->slots[0].card_detect_irq);
+       enable_irq(host->card_detect_irq);
        return 0;
 }
 
@@ -286,8 +302,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
 
 #ifdef CONFIG_REGULATOR
 
-static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
-                                  int vdd)
+static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd)
 {
        struct omap_hsmmc_host *host =
                platform_get_drvdata(to_platform_device(dev));
@@ -300,8 +315,8 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
        if (!host->vcc)
                return 0;
 
-       if (mmc_slot(host).before_set_reg)
-               mmc_slot(host).before_set_reg(dev, slot, power_on, vdd);
+       if (mmc_pdata(host)->before_set_reg)
+               mmc_pdata(host)->before_set_reg(dev, power_on, vdd);
 
        if (host->pbias) {
                if (host->pbias_enabled == 1) {
@@ -363,8 +378,8 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on,
                }
        }
 
-       if (mmc_slot(host).after_set_reg)
-               mmc_slot(host).after_set_reg(dev, slot, power_on, vdd);
+       if (mmc_pdata(host)->after_set_reg)
+               mmc_pdata(host)->after_set_reg(dev, power_on, vdd);
 
 error_set_power:
        return ret;
@@ -383,18 +398,18 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        } else {
                host->vcc = reg;
                ocr_value = mmc_regulator_get_ocrmask(reg);
-               if (!mmc_slot(host).ocr_mask) {
-                       mmc_slot(host).ocr_mask = ocr_value;
+               if (!mmc_pdata(host)->ocr_mask) {
+                       mmc_pdata(host)->ocr_mask = ocr_value;
                } else {
-                       if (!(mmc_slot(host).ocr_mask & ocr_value)) {
+                       if (!(mmc_pdata(host)->ocr_mask & ocr_value)) {
                                dev_err(host->dev, "ocrmask %x is not supported\n",
-                                       mmc_slot(host).ocr_mask);
-                               mmc_slot(host).ocr_mask = 0;
+                                       mmc_pdata(host)->ocr_mask);
+                               mmc_pdata(host)->ocr_mask = 0;
                                return -EINVAL;
                        }
                }
        }
-       mmc_slot(host).set_power = omap_hsmmc_set_power;
+       mmc_pdata(host)->set_power = omap_hsmmc_set_power;
 
        /* Allow an aux regulator */
        reg = devm_regulator_get_optional(host->dev, "vmmc_aux");
@@ -404,7 +419,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        host->pbias = IS_ERR(reg) ? NULL : reg;
 
        /* For eMMC do not power off when not in sleep state */
-       if (mmc_slot(host).no_regulator_off_init)
+       if (mmc_pdata(host)->no_regulator_off_init)
                return 0;
        /*
         * To disable boot_on regulator, enable regulator
@@ -412,10 +427,10 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
         */
        if ((host->vcc && regulator_is_enabled(host->vcc) > 0) ||
            (host->vcc_aux && regulator_is_enabled(host->vcc_aux))) {
-               int vdd = ffs(mmc_slot(host).ocr_mask) - 1;
+               int vdd = ffs(mmc_pdata(host)->ocr_mask) - 1;
 
-               mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd);
-               mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
+               mmc_pdata(host)->set_power(host->dev, 1, vdd);
+               mmc_pdata(host)->set_power(host->dev, 0, 0);
        }
 
        return 0;
@@ -423,7 +438,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 
 static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host)
 {
-       mmc_slot(host).set_power = NULL;
+       mmc_pdata(host)->set_power = NULL;
 }
 
 static inline int omap_hsmmc_have_reg(void)
@@ -449,55 +464,59 @@ static inline int omap_hsmmc_have_reg(void)
 
 #endif
 
-static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host,
+                               struct omap_hsmmc_platform_data *pdata)
 {
        int ret;
 
-       if (gpio_is_valid(pdata->slots[0].switch_pin)) {
-               if (pdata->slots[0].cover)
-                       pdata->slots[0].get_cover_state =
-                                       omap_hsmmc_get_cover_state;
+       if (gpio_is_valid(pdata->switch_pin)) {
+               if (pdata->cover)
+                       host->get_cover_state =
+                               omap_hsmmc_get_cover_state;
                else
-                       pdata->slots[0].card_detect = omap_hsmmc_card_detect;
-               pdata->slots[0].card_detect_irq =
-                               gpio_to_irq(pdata->slots[0].switch_pin);
-               ret = gpio_request(pdata->slots[0].switch_pin, "mmc_cd");
+                       host->card_detect = omap_hsmmc_card_detect;
+               host->card_detect_irq =
+                               gpio_to_irq(pdata->switch_pin);
+               ret = gpio_request(pdata->switch_pin, "mmc_cd");
                if (ret)
                        return ret;
-               ret = gpio_direction_input(pdata->slots[0].switch_pin);
+               ret = gpio_direction_input(pdata->switch_pin);
                if (ret)
                        goto err_free_sp;
-       } else
-               pdata->slots[0].switch_pin = -EINVAL;
+       } else {
+               pdata->switch_pin = -EINVAL;
+       }
 
-       if (gpio_is_valid(pdata->slots[0].gpio_wp)) {
-               pdata->slots[0].get_ro = omap_hsmmc_get_wp;
-               ret = gpio_request(pdata->slots[0].gpio_wp, "mmc_wp");
+       if (gpio_is_valid(pdata->gpio_wp)) {
+               host->get_ro = omap_hsmmc_get_wp;
+               ret = gpio_request(pdata->gpio_wp, "mmc_wp");
                if (ret)
                        goto err_free_cd;
-               ret = gpio_direction_input(pdata->slots[0].gpio_wp);
+               ret = gpio_direction_input(pdata->gpio_wp);
                if (ret)
                        goto err_free_wp;
-       } else
-               pdata->slots[0].gpio_wp = -EINVAL;
+       } else {
+               pdata->gpio_wp = -EINVAL;
+       }
 
        return 0;
 
 err_free_wp:
-       gpio_free(pdata->slots[0].gpio_wp);
+       gpio_free(pdata->gpio_wp);
 err_free_cd:
-       if (gpio_is_valid(pdata->slots[0].switch_pin))
+       if (gpio_is_valid(pdata->switch_pin))
 err_free_sp:
-               gpio_free(pdata->slots[0].switch_pin);
+               gpio_free(pdata->switch_pin);
        return ret;
 }
 
-static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
+static void omap_hsmmc_gpio_free(struct omap_hsmmc_host *host,
+                                struct omap_hsmmc_platform_data *pdata)
 {
-       if (gpio_is_valid(pdata->slots[0].gpio_wp))
-               gpio_free(pdata->slots[0].gpio_wp);
-       if (gpio_is_valid(pdata->slots[0].switch_pin))
-               gpio_free(pdata->slots[0].switch_pin);
+       if (gpio_is_valid(pdata->gpio_wp))
+               gpio_free(pdata->gpio_wp);
+       if (gpio_is_valid(pdata->switch_pin))
+               gpio_free(pdata->switch_pin);
 }
 
 /*
@@ -607,8 +626,9 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
         *        in capabilities register
         *      - MMC/SD clock coming out of controller > 25MHz
         */
-       if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) &&
+       if ((mmc_pdata(host)->features & HSMMC_HAS_HSPE_SUPPORT) &&
            (ios->timing != MMC_TIMING_MMC_DDR52) &&
+           (ios->timing != MMC_TIMING_UHS_DDR50) &&
            ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) {
                regval = OMAP_HSMMC_READ(host->base, HCTL);
                if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000)
@@ -628,7 +648,8 @@ static void omap_hsmmc_set_bus_width(struct omap_hsmmc_host *host)
        u32 con;
 
        con = OMAP_HSMMC_READ(host->base, CON);
-       if (ios->timing == MMC_TIMING_MMC_DDR52)
+       if (ios->timing == MMC_TIMING_MMC_DDR52 ||
+           ios->timing == MMC_TIMING_UHS_DDR50)
                con |= DDR;     /* configure in DDR mode */
        else
                con &= ~DDR;
@@ -791,8 +812,8 @@ int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host)
 {
        int r = 1;
 
-       if (mmc_slot(host).get_cover_state)
-               r = mmc_slot(host).get_cover_state(host->dev, host->slot_id);
+       if (host->get_cover_state)
+               r = host->get_cover_state(host->dev);
        return r;
 }
 
@@ -816,7 +837,7 @@ omap_hsmmc_show_slot_name(struct device *dev, struct device_attribute *attr,
        struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
        struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-       return sprintf(buf, "%s\n", mmc_slot(host).name);
+       return sprintf(buf, "%s\n", mmc_pdata(host)->name);
 }
 
 static DEVICE_ATTR(slot_name, S_IRUGO, omap_hsmmc_show_slot_name, NULL);
@@ -1061,7 +1082,7 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
         * OMAP4 ES2 and greater has an updated reset logic.
         * Monitor a 0->1 transition first
         */
-       if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {
+       if (mmc_pdata(host)->features & HSMMC_HAS_UPDATED_RESET) {
                while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
                                        && (i++ < limit))
                        udelay(1);
@@ -1210,12 +1231,11 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
                clk_disable_unprepare(host->dbclk);
 
        /* Turn the power off */
-       ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
+       ret = mmc_pdata(host)->set_power(host->dev, 0, 0);
 
        /* Turn the power ON with given VDD 1.8 or 3.0v */
        if (!ret)
-               ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1,
-                                              vdd);
+               ret = mmc_pdata(host)->set_power(host->dev, 1, vdd);
        pm_runtime_get_sync(host->dev);
        if (host->dbclk)
                clk_prepare_enable(host->dbclk);
@@ -1259,11 +1279,11 @@ err:
 /* Protect the card while the cover is open */
 static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host)
 {
-       if (!mmc_slot(host).get_cover_state)
+       if (!host->get_cover_state)
                return;
 
        host->reqs_blocked = 0;
-       if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) {
+       if (host->get_cover_state(host->dev)) {
                if (host->protect_card) {
                        dev_info(host->dev, "%s: cover is closed, "
                                         "card is now accessible\n",
@@ -1286,13 +1306,12 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host)
 static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id)
 {
        struct omap_hsmmc_host *host = dev_id;
-       struct omap_mmc_slot_data *slot = &mmc_slot(host);
        int carddetect;
 
        sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
 
-       if (slot->card_detect)
-               carddetect = slot->card_detect(host->dev, host->slot_id);
+       if (host->card_detect)
+               carddetect = host->card_detect(host->dev);
        else {
                omap_hsmmc_protect_card(host);
                carddetect = -ENOSYS;
@@ -1618,12 +1637,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        if (ios->power_mode != host->power_mode) {
                switch (ios->power_mode) {
                case MMC_POWER_OFF:
-                       mmc_slot(host).set_power(host->dev, host->slot_id,
-                                                0, 0);
+                       mmc_pdata(host)->set_power(host->dev, 0, 0);
                        break;
                case MMC_POWER_UP:
-                       mmc_slot(host).set_power(host->dev, host->slot_id,
-                                                1, ios->vdd);
+                       mmc_pdata(host)->set_power(host->dev, 1, ios->vdd);
                        break;
                case MMC_POWER_ON:
                        do_send_init_stream = 1;
@@ -1668,26 +1685,26 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc)
 {
        struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-       if (!mmc_slot(host).card_detect)
+       if (!host->card_detect)
                return -ENOSYS;
-       return mmc_slot(host).card_detect(host->dev, host->slot_id);
+       return host->card_detect(host->dev);
 }
 
 static int omap_hsmmc_get_ro(struct mmc_host *mmc)
 {
        struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-       if (!mmc_slot(host).get_ro)
+       if (!host->get_ro)
                return -ENOSYS;
-       return mmc_slot(host).get_ro(host->dev, 0);
+       return host->get_ro(host->dev);
 }
 
 static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
 {
        struct omap_hsmmc_host *host = mmc_priv(mmc);
 
-       if (mmc_slot(host).init_card)
-               mmc_slot(host).init_card(card);
+       if (mmc_pdata(host)->init_card)
+               mmc_pdata(host)->init_card(card);
 }
 
 static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -1957,9 +1974,9 @@ static const struct of_device_id omap_mmc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, omap_mmc_of_match);
 
-static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 {
-       struct omap_mmc_platform_data *pdata;
+       struct omap_hsmmc_platform_data *pdata;
        struct device_node *np = dev->of_node;
        u32 bus_width, max_freq;
        int cd_gpio, wp_gpio;
@@ -1976,40 +1993,38 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
        if (of_find_property(np, "ti,dual-volt", NULL))
                pdata->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
 
-       /* This driver only supports 1 slot */
-       pdata->nr_slots = 1;
-       pdata->slots[0].switch_pin = cd_gpio;
-       pdata->slots[0].gpio_wp = wp_gpio;
+       pdata->switch_pin = cd_gpio;
+       pdata->gpio_wp = wp_gpio;
 
        if (of_find_property(np, "ti,non-removable", NULL)) {
-               pdata->slots[0].nonremovable = true;
-               pdata->slots[0].no_regulator_off_init = true;
+               pdata->nonremovable = true;
+               pdata->no_regulator_off_init = true;
        }
        of_property_read_u32(np, "bus-width", &bus_width);
        if (bus_width == 4)
-               pdata->slots[0].caps |= MMC_CAP_4_BIT_DATA;
+               pdata->caps |= MMC_CAP_4_BIT_DATA;
        else if (bus_width == 8)
-               pdata->slots[0].caps |= MMC_CAP_8_BIT_DATA;
+               pdata->caps |= MMC_CAP_8_BIT_DATA;
 
        if (of_find_property(np, "ti,needs-special-reset", NULL))
-               pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+               pdata->features |= HSMMC_HAS_UPDATED_RESET;
 
        if (!of_property_read_u32(np, "max-frequency", &max_freq))
                pdata->max_freq = max_freq;
 
        if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
-               pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
+               pdata->features |= HSMMC_HAS_HSPE_SUPPORT;
 
        if (of_find_property(np, "keep-power-in-suspend", NULL))
-               pdata->slots[0].pm_caps |= MMC_PM_KEEP_POWER;
+               pdata->pm_caps |= MMC_PM_KEEP_POWER;
 
        if (of_find_property(np, "enable-sdio-wakeup", NULL))
-               pdata->slots[0].pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+               pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
 
        return pdata;
 }
 #else
-static inline struct omap_mmc_platform_data
+static inline struct omap_hsmmc_platform_data
                        *of_get_hsmmc_pdata(struct device *dev)
 {
        return ERR_PTR(-EINVAL);
@@ -2018,7 +2033,7 @@ static inline struct omap_mmc_platform_data
 
 static int omap_hsmmc_probe(struct platform_device *pdev)
 {
-       struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
+       struct omap_hsmmc_platform_data *pdata = pdev->dev.platform_data;
        struct mmc_host *mmc;
        struct omap_hsmmc_host *host = NULL;
        struct resource *res;
@@ -2048,11 +2063,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       if (pdata->nr_slots == 0) {
-               dev_err(&pdev->dev, "No Slots\n");
-               return -ENXIO;
-       }
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
        if (res == NULL || irq < 0)
@@ -2062,14 +2072,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
        if (IS_ERR(base))
                return PTR_ERR(base);
 
-       ret = omap_hsmmc_gpio_init(pdata);
-       if (ret)
-               goto err;
-
        mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev);
        if (!mmc) {
                ret = -ENOMEM;
-               goto err_alloc;
+               goto err;
        }
 
        host            = mmc_priv(mmc);
@@ -2079,13 +2085,16 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
        host->use_dma   = 1;
        host->dma_ch    = -1;
        host->irq       = irq;
-       host->slot_id   = 0;
        host->mapbase   = res->start + pdata->reg_offset;
        host->base      = base + pdata->reg_offset;
        host->power_mode = MMC_POWER_OFF;
        host->next_data.cookie = 1;
        host->pbias_enabled = 0;
 
+       ret = omap_hsmmc_gpio_init(host, pdata);
+       if (ret)
+               goto err_gpio;
+
        platform_set_drvdata(pdev, host);
 
        if (pdev->dev.of_node)
@@ -2144,14 +2153,14 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
        mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
 
-       mmc->caps |= mmc_slot(host).caps;
+       mmc->caps |= mmc_pdata(host)->caps;
        if (mmc->caps & MMC_CAP_8_BIT_DATA)
                mmc->caps |= MMC_CAP_4_BIT_DATA;
 
-       if (mmc_slot(host).nonremovable)
+       if (mmc_pdata(host)->nonremovable)
                mmc->caps |= MMC_CAP_NONREMOVABLE;
 
-       mmc->pm_caps = mmc_slot(host).pm_caps;
+       mmc->pm_caps = mmc_pdata(host)->pm_caps;
 
        omap_hsmmc_conf_bus_power(host);
 
@@ -2204,27 +2213,19 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
-       if (pdata->init != NULL) {
-               if (pdata->init(&pdev->dev) != 0) {
-                       dev_err(mmc_dev(host->mmc),
-                               "Unable to configure MMC IRQs\n");
-                       goto err_irq;
-               }
-       }
-
-       if (omap_hsmmc_have_reg() && !mmc_slot(host).set_power) {
+       if (omap_hsmmc_have_reg() && !mmc_pdata(host)->set_power) {
                ret = omap_hsmmc_reg_get(host);
                if (ret)
-                       goto err_reg;
+                       goto err_irq;
                host->use_reg = 1;
        }
 
-       mmc->ocr_avail = mmc_slot(host).ocr_mask;
+       mmc->ocr_avail = mmc_pdata(host)->ocr_mask;
 
        /* Request IRQ for card detect */
-       if ((mmc_slot(host).card_detect_irq)) {
+       if (host->card_detect_irq) {
                ret = devm_request_threaded_irq(&pdev->dev,
-                                               mmc_slot(host).card_detect_irq,
+                                               host->card_detect_irq,
                                                NULL, omap_hsmmc_detect,
                                           IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                           mmc_hostname(mmc), host);
@@ -2233,8 +2234,8 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
                                "Unable to grab MMC CD IRQ\n");
                        goto err_irq_cd;
                }
-               pdata->suspend = omap_hsmmc_suspend_cdirq;
-               pdata->resume = omap_hsmmc_resume_cdirq;
+               host->suspend = omap_hsmmc_suspend_cdirq;
+               host->resume = omap_hsmmc_resume_cdirq;
        }
 
        omap_hsmmc_disable_irq(host);
@@ -2255,12 +2256,12 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
        mmc_add_host(mmc);
 
-       if (mmc_slot(host).name != NULL) {
+       if (mmc_pdata(host)->name != NULL) {
                ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name);
                if (ret < 0)
                        goto err_slot_name;
        }
-       if (mmc_slot(host).card_detect_irq && mmc_slot(host).get_cover_state) {
+       if (host->card_detect_irq && host->get_cover_state) {
                ret = device_create_file(&mmc->class_dev,
                                        &dev_attr_cover_switch);
                if (ret < 0)
@@ -2278,9 +2279,6 @@ err_slot_name:
 err_irq_cd:
        if (host->use_reg)
                omap_hsmmc_reg_put(host);
-err_reg:
-       if (host->pdata->cleanup)
-               host->pdata->cleanup(&pdev->dev);
 err_irq:
        if (host->tx_chan)
                dma_release_channel(host->tx_chan);
@@ -2291,9 +2289,9 @@ err_irq:
        if (host->dbclk)
                clk_disable_unprepare(host->dbclk);
 err1:
+       omap_hsmmc_gpio_free(host, pdata);
+err_gpio:
        mmc_free_host(mmc);
-err_alloc:
-       omap_hsmmc_gpio_free(pdata);
 err:
        return ret;
 }
@@ -2306,8 +2304,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
        mmc_remove_host(host->mmc);
        if (host->use_reg)
                omap_hsmmc_reg_put(host);
-       if (host->pdata->cleanup)
-               host->pdata->cleanup(&pdev->dev);
 
        if (host->tx_chan)
                dma_release_channel(host->tx_chan);
@@ -2319,7 +2315,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
        if (host->dbclk)
                clk_disable_unprepare(host->dbclk);
 
-       omap_hsmmc_gpio_free(host->pdata);
+       omap_hsmmc_gpio_free(host, host->pdata);
        mmc_free_host(host->mmc);
 
        return 0;
@@ -2330,8 +2326,8 @@ static int omap_hsmmc_prepare(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
 
-       if (host->pdata->suspend)
-               return host->pdata->suspend(dev, host->slot_id);
+       if (host->suspend)
+               return host->suspend(dev);
 
        return 0;
 }
@@ -2340,8 +2336,8 @@ static void omap_hsmmc_complete(struct device *dev)
 {
        struct omap_hsmmc_host *host = dev_get_drvdata(dev);
 
-       if (host->pdata->resume)
-               host->pdata->resume(dev, host->slot_id);
+       if (host->resume)
+               host->resume(dev);
 
 }
 
index 9cccc0e89b0435928ca375d8b1640c5008cc6551..daba49ac12423dfc6e62f8b1d64d9e15340cf56f 100644 (file)
@@ -76,6 +76,7 @@ struct sdhci_acpi_host {
        const struct sdhci_acpi_slot    *slot;
        struct platform_device          *pdev;
        bool                            use_runtime_pm;
+       bool                            dma_setup;
 };
 
 static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag)
@@ -85,7 +86,29 @@ static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag)
 
 static int sdhci_acpi_enable_dma(struct sdhci_host *host)
 {
-       return 0;
+       struct sdhci_acpi_host *c = sdhci_priv(host);
+       struct device *dev = &c->pdev->dev;
+       int err = -1;
+
+       if (c->dma_setup)
+               return 0;
+
+       if (host->flags & SDHCI_USE_64_BIT_DMA) {
+               if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) {
+                       host->flags &= ~SDHCI_USE_64_BIT_DMA;
+               } else {
+                       err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+                       if (err)
+                               dev_warn(dev, "Failed to set 64-bit DMA mask\n");
+               }
+       }
+
+       if (err)
+               err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+
+       c->dma_setup = !err;
+
+       return err;
 }
 
 static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
@@ -180,17 +203,21 @@ static int sdhci_acpi_sd_probe_slot(struct platform_device *pdev,
 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
        .chip    = &sdhci_acpi_chip_int,
        .caps    = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
-                  MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR,
+                  MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
+                  MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
        .caps2   = MMC_CAP2_HC_ERASE_SZ,
        .flags   = SDHCI_ACPI_RUNTIME_PM,
+       .quirks  = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | SDHCI_QUIRK2_STOP_WITH_TC,
        .probe_slot     = sdhci_acpi_emmc_probe_slot,
 };
 
 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
-       .quirks  = SDHCI_QUIRK_BROKEN_CARD_DETECTION,
+       .quirks  = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+                  SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
-       .caps    = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD,
+       .caps    = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD |
+                  MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
        .flags   = SDHCI_ACPI_RUNTIME_PM,
        .pm_caps = MMC_PM_KEEP_POWER,
        .probe_slot     = sdhci_acpi_sdio_probe_slot,
@@ -199,8 +226,10 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
 static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
        .flags   = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL |
                   SDHCI_ACPI_RUNTIME_PM,
+       .quirks  = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
                   SDHCI_QUIRK2_STOP_WITH_TC,
+       .caps    = MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
        .probe_slot     = sdhci_acpi_sd_probe_slot,
 };
 
@@ -305,21 +334,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
                goto err_free;
        }
 
-       if (!dev->dma_mask) {
-               u64 dma_mask;
-
-               if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) {
-                       /* 64-bit DMA is not supported at present */
-                       dma_mask = DMA_BIT_MASK(32);
-               } else {
-                       dma_mask = DMA_BIT_MASK(32);
-               }
-
-               err = dma_coerce_mask_and_coherent(dev, dma_mask);
-               if (err)
-                       goto err_free;
-       }
-
        if (c->slot) {
                if (c->slot->probe_slot) {
                        err = c->slot->probe_slot(pdev, hid, uid);
index 587ee0edeb576b8ad2a25c0762d059afff8a1f2c..12711ab51aed24ecd32d1d967112b65f94bae7b0 100644 (file)
@@ -65,8 +65,6 @@
 /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
 #define ESDHC_TUNING_START_TAP         0x1
 
-#define ESDHC_TUNING_BLOCK_PATTERN_LEN 64
-
 /* pinctrl state */
 #define ESDHC_PINCTRL_STATE_100MHZ     "state_100mhz"
 #define ESDHC_PINCTRL_STATE_200MHZ     "state_200mhz"
@@ -692,8 +690,6 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
        /* FIXME: delay a bit for card to be ready for next tuning due to errors */
        mdelay(1);
 
-       /* This is balanced by the runtime put in sdhci_tasklet_finish */
-       pm_runtime_get_sync(host->mmc->parent);
        reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
        reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
                        ESDHC_MIX_CTRL_FBCLK_SEL;
@@ -704,54 +700,6 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
                        val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS));
 }
 
-static void esdhc_request_done(struct mmc_request *mrq)
-{
-       complete(&mrq->completion);
-}
-
-static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode,
-                                struct scatterlist *sg)
-{
-       struct mmc_command cmd = {0};
-       struct mmc_request mrq = {NULL};
-       struct mmc_data data = {0};
-
-       cmd.opcode = opcode;
-       cmd.arg = 0;
-       cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-       data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN;
-       data.blocks = 1;
-       data.flags = MMC_DATA_READ;
-       data.sg = sg;
-       data.sg_len = 1;
-
-       mrq.cmd = &cmd;
-       mrq.cmd->mrq = &mrq;
-       mrq.data = &data;
-       mrq.data->mrq = &mrq;
-       mrq.cmd->data = mrq.data;
-
-       mrq.done = esdhc_request_done;
-       init_completion(&(mrq.completion));
-
-       spin_lock_irq(&host->lock);
-       host->mrq = &mrq;
-
-       sdhci_send_command(host, mrq.cmd);
-
-       spin_unlock_irq(&host->lock);
-
-       wait_for_completion(&mrq.completion);
-
-       if (cmd.error)
-               return cmd.error;
-       if (data.error)
-               return data.error;
-
-       return 0;
-}
-
 static void esdhc_post_tuning(struct sdhci_host *host)
 {
        u32 reg;
@@ -763,21 +711,13 @@ static void esdhc_post_tuning(struct sdhci_host *host)
 
 static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
 {
-       struct scatterlist sg;
-       char *tuning_pattern;
        int min, max, avg, ret;
 
-       tuning_pattern = kmalloc(ESDHC_TUNING_BLOCK_PATTERN_LEN, GFP_KERNEL);
-       if (!tuning_pattern)
-               return -ENOMEM;
-
-       sg_init_one(&sg, tuning_pattern, ESDHC_TUNING_BLOCK_PATTERN_LEN);
-
        /* find the mininum delay first which can pass tuning */
        min = ESDHC_TUNE_CTRL_MIN;
        while (min < ESDHC_TUNE_CTRL_MAX) {
                esdhc_prepare_tuning(host, min);
-               if (!esdhc_send_tuning_cmd(host, opcode, &sg))
+               if (!mmc_send_tuning(host->mmc))
                        break;
                min += ESDHC_TUNE_CTRL_STEP;
        }
@@ -786,7 +726,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
        max = min + ESDHC_TUNE_CTRL_STEP;
        while (max < ESDHC_TUNE_CTRL_MAX) {
                esdhc_prepare_tuning(host, max);
-               if (esdhc_send_tuning_cmd(host, opcode, &sg)) {
+               if (mmc_send_tuning(host->mmc)) {
                        max -= ESDHC_TUNE_CTRL_STEP;
                        break;
                }
@@ -796,11 +736,9 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
        /* use average delay to get the best timing */
        avg = (min + max) / 2;
        esdhc_prepare_tuning(host, avg);
-       ret = esdhc_send_tuning_cmd(host, opcode, &sg);
+       ret = mmc_send_tuning(host->mmc);
        esdhc_post_tuning(host);
 
-       kfree(tuning_pattern);
-
        dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
                ret ? "failed" : "passed", avg, ret);
 
@@ -1031,11 +969,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
        imx_data->pins_default = pinctrl_lookup_state(imx_data->pinctrl,
                                                PINCTRL_STATE_DEFAULT);
-       if (IS_ERR(imx_data->pins_default)) {
-               err = PTR_ERR(imx_data->pins_default);
-               dev_err(mmc_dev(host->mmc), "could not get default state\n");
-               goto disable_clk;
-       }
+       if (IS_ERR(imx_data->pins_default))
+               dev_warn(mmc_dev(host->mmc), "could not get default state\n");
 
        host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
@@ -1123,7 +1058,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
        }
 
        /* sdr50 and sdr104 needs work on 1.8v signal voltage */
-       if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data)) {
+       if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) &&
+           !IS_ERR(imx_data->pins_default)) {
                imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
                                                ESDHC_PINCTRL_STATE_100MHZ);
                imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
index 30804385af6dd02106045d7ef0109319ec5318a1..3d32ce896b091f51cdfd74b383ade7ad6e8477a7 100644 (file)
@@ -339,9 +339,7 @@ static int msm_init_cm_dll(struct sdhci_host *host)
 static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 {
        int tuning_seq_cnt = 3;
-       u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
-       const u8 *tuning_block_pattern = tuning_blk_pattern_4bit;
-       int size = sizeof(tuning_blk_pattern_4bit);
+       u8 phase, tuned_phases[16], tuned_phase_cnt = 0;
        int rc;
        struct mmc_host *mmc = host->mmc;
        struct mmc_ios ios = host->mmc->ios;
@@ -355,53 +353,21 @@ static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
              (ios.timing == MMC_TIMING_UHS_SDR104)))
                return 0;
 
-       if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
-           (mmc->ios.bus_width == MMC_BUS_WIDTH_8)) {
-               tuning_block_pattern = tuning_blk_pattern_8bit;
-               size = sizeof(tuning_blk_pattern_8bit);
-       }
-
-       data_buf = kmalloc(size, GFP_KERNEL);
-       if (!data_buf)
-               return -ENOMEM;
-
 retry:
        /* First of all reset the tuning block */
        rc = msm_init_cm_dll(host);
        if (rc)
-               goto out;
+               return rc;
 
        phase = 0;
        do {
-               struct mmc_command cmd = { 0 };
-               struct mmc_data data = { 0 };
-               struct mmc_request mrq = {
-                       .cmd = &cmd,
-                       .data = &data
-               };
-               struct scatterlist sg;
-
                /* Set the phase in delay line hw block */
                rc = msm_config_cm_dll_phase(host, phase);
                if (rc)
-                       goto out;
+                       return rc;
 
-               cmd.opcode = opcode;
-               cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-               data.blksz = size;
-               data.blocks = 1;
-               data.flags = MMC_DATA_READ;
-               data.timeout_ns = NSEC_PER_SEC; /* 1 second */
-
-               data.sg = &sg;
-               data.sg_len = 1;
-               sg_init_one(&sg, data_buf, size);
-               memset(data_buf, 0, size);
-               mmc_wait_for_req(mmc, &mrq);
-
-               if (!cmd.error && !data.error &&
-                   !memcmp(data_buf, tuning_block_pattern, size)) {
+               rc = mmc_send_tuning(mmc);
+               if (!rc) {
                        /* Tuning is successful at this tuning point */
                        tuned_phases[tuned_phase_cnt++] = phase;
                        dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n",
@@ -413,7 +379,7 @@ retry:
                rc = msm_find_most_appropriate_phase(host, tuned_phases,
                                                     tuned_phase_cnt);
                if (rc < 0)
-                       goto out;
+                       return rc;
                else
                        phase = rc;
 
@@ -423,7 +389,7 @@ retry:
                 */
                rc = msm_config_cm_dll_phase(host, phase);
                if (rc)
-                       goto out;
+                       return rc;
                dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n",
                         mmc_hostname(mmc), phase);
        } else {
@@ -435,8 +401,6 @@ retry:
                rc = -EIO;
        }
 
-out:
-       kfree(data_buf);
        return rc;
 }
 
index 981d66e5c023147d99ae35a6e9e985e453800058..bcb51e9dfdcd0789866ca7739a60444106f88770 100644 (file)
@@ -165,7 +165,6 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
        host = sdhci_pltfm_init(pdev, &sdhci_arasan_pdata, 0);
        if (IS_ERR(host)) {
                ret = PTR_ERR(host);
-               dev_err(&pdev->dev, "platform init failed (%u)\n", ret);
                goto clk_disable_all;
        }
 
@@ -175,10 +174,8 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
        pltfm_host->clk = clk_xin;
 
        ret = sdhci_add_host(host);
-       if (ret) {
-               dev_err(&pdev->dev, "platform register failed (%u)\n", ret);
+       if (ret)
                goto err_pltfm_free;
-       }
 
        return 0;
 
index 5670e381b0cf7888c07614b15b7a3fda53ce2d45..e2ec108dba0e8220e1d23804f11b80ccfa71414f 100644 (file)
@@ -127,8 +127,6 @@ void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
                return;
        scratch_32 &= ~((1 << 21) | (1 << 30));
 
-       /* Set RTD3 function disabled */
-       scratch_32 |= ((1 << 29) | (1 << 28));
        pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32);
 
        /* Set L1 Entrance Timer */
index 61192973e7cbaad1305c2ebea324f43e2506665a..95f73007fccf9288e04b07266996c52516533c2c 100644 (file)
@@ -269,7 +269,9 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host)
 static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
        slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
-                                MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR;
+                                MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
+                                MMC_CAP_BUS_WIDTH_TEST |
+                                MMC_CAP_WAIT_WHILE_BUSY;
        slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
        slot->hw_reset = sdhci_pci_int_hw_reset;
        if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BSW_EMMC)
@@ -279,12 +281,16 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 
 static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
-       slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE;
+       slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
+                                MMC_CAP_BUS_WIDTH_TEST |
+                                MMC_CAP_WAIT_WHILE_BUSY;
        return 0;
 }
 
 static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
 {
+       slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST |
+                                MMC_CAP_WAIT_WHILE_BUSY;
        slot->cd_con_id = NULL;
        slot->cd_idx = 0;
        slot->cd_override_level = true;
@@ -294,11 +300,13 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
 static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
        .allow_runtime_pm = true,
        .probe_slot     = byt_emmc_probe_slot,
+       .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2        = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
                          SDHCI_QUIRK2_STOP_WITH_TC,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
+       .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2        = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
                        SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
        .allow_runtime_pm = true,
@@ -306,6 +314,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
+       .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2        = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
                          SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
                          SDHCI_QUIRK2_STOP_WITH_TC,
@@ -645,6 +654,25 @@ static const struct sdhci_pci_fixes sdhci_rtsx = {
        .probe_slot     = rtsx_probe_slot,
 };
 
+static int amd_probe(struct sdhci_pci_chip *chip)
+{
+       struct pci_dev  *smbus_dev;
+
+       smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                       PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
+
+       if (smbus_dev && (smbus_dev->revision < 0x51)) {
+               chip->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
+               chip->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
+       }
+
+       return 0;
+}
+
+static const struct sdhci_pci_fixes sdhci_amd = {
+       .probe          = amd_probe,
+};
+
 static const struct pci_device_id pci_ids[] = {
        {
                .vendor         = PCI_VENDOR_ID_RICOH,
@@ -1044,7 +1072,15 @@ static const struct pci_device_id pci_ids[] = {
                .subdevice      = PCI_ANY_ID,
                .driver_data    = (kernel_ulong_t)&sdhci_o2,
        },
-
+       {
+               .vendor         = PCI_VENDOR_ID_AMD,
+               .device         = PCI_ANY_ID,
+               .class          = PCI_CLASS_SYSTEM_SDHCI << 8,
+               .class_mask     = 0xFFFF00,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_amd,
+       },
        {       /* Generic SD host controller */
                PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
        },
@@ -1064,7 +1100,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
 {
        struct sdhci_pci_slot *slot;
        struct pci_dev *pdev;
-       int ret;
+       int ret = -1;
 
        slot = sdhci_priv(host);
        pdev = slot->chip->pdev;
@@ -1076,7 +1112,17 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
                        "doesn't fully claim to support it.\n");
        }
 
-       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (host->flags & SDHCI_USE_64_BIT_DMA) {
+               if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) {
+                       host->flags &= ~SDHCI_USE_64_BIT_DMA;
+               } else {
+                       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+                       if (ret)
+                               dev_warn(&pdev->dev, "Failed to set 64-bit DMA mask\n");
+               }
+       }
+       if (ret)
+               ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
 
index b4c23e983baf221c62d81ba0f957d2674e3296a4..f98008b5ea77926726d0fc5bec79abea4829b39a 100644 (file)
@@ -167,23 +167,17 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
        struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
        struct device *dev = &pdev->dev;
        struct sdhci_host *host = NULL;
-       struct sdhci_pxa *pxa = NULL;
        const struct of_device_id *match;
 
        int ret;
        struct clk *clk;
 
-       pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
-       if (!pxa)
-               return -ENOMEM;
-
        host = sdhci_pltfm_init(pdev, NULL, 0);
-       if (IS_ERR(host)) {
-               kfree(pxa);
+       if (IS_ERR(host))
                return PTR_ERR(host);
-       }
+
        pltfm_host = sdhci_priv(host);
-       pltfm_host->priv = pxa;
+       pltfm_host->priv = NULL;
 
        clk = clk_get(dev, "PXA-SDHCLK");
        if (IS_ERR(clk)) {
@@ -238,7 +232,6 @@ err_add_host:
        clk_put(clk);
 err_clk_get:
        sdhci_pltfm_free(pdev);
-       kfree(pxa);
        return ret;
 }
 
@@ -246,14 +239,12 @@ static int sdhci_pxav2_remove(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct sdhci_pxa *pxa = pltfm_host->priv;
 
        sdhci_remove_host(host, 1);
 
        clk_disable_unprepare(pltfm_host->clk);
        clk_put(pltfm_host->clk);
        sdhci_pltfm_free(pdev);
-       kfree(pxa);
 
        return 0;
 }
index 5036d7d39529a949d982e5814a9f4d010683a9a3..ad0badad0ebc8f4900b646e3a56b0d5b06a8e899 100644 (file)
 #define SDCE_MISC_INT          (1<<2)
 #define SDCE_MISC_INT_EN       (1<<1)
 
+struct sdhci_pxa {
+       struct clk *clk_core;
+       struct clk *clk_io;
+       u8      power_mode;
+};
+
 /*
  * These registers are relative to the second register region, for the
  * MBus bridge.
@@ -211,6 +217,7 @@ static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
        case MMC_TIMING_UHS_SDR104:
                ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
                break;
+       case MMC_TIMING_MMC_DDR52:
        case MMC_TIMING_UHS_DDR50:
                ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
                break;
@@ -283,9 +290,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
        struct sdhci_host *host = NULL;
        struct sdhci_pxa *pxa = NULL;
        const struct of_device_id *match;
-
        int ret;
-       struct clk *clk;
 
        pxa = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_pxa), GFP_KERNEL);
        if (!pxa)
@@ -305,14 +310,20 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
        pltfm_host = sdhci_priv(host);
        pltfm_host->priv = pxa;
 
-       clk = devm_clk_get(dev, NULL);
-       if (IS_ERR(clk)) {
+       pxa->clk_io = devm_clk_get(dev, "io");
+       if (IS_ERR(pxa->clk_io))
+               pxa->clk_io = devm_clk_get(dev, NULL);
+       if (IS_ERR(pxa->clk_io)) {
                dev_err(dev, "failed to get io clock\n");
-               ret = PTR_ERR(clk);
+               ret = PTR_ERR(pxa->clk_io);
                goto err_clk_get;
        }
-       pltfm_host->clk = clk;
-       clk_prepare_enable(clk);
+       pltfm_host->clk = pxa->clk_io;
+       clk_prepare_enable(pxa->clk_io);
+
+       pxa->clk_core = devm_clk_get(dev, "core");
+       if (!IS_ERR(pxa->clk_core))
+               clk_prepare_enable(pxa->clk_core);
 
        /* enable 1/8V DDR capable */
        host->mmc->caps |= MMC_CAP_1_8V_DDR;
@@ -385,7 +396,9 @@ err_add_host:
        pm_runtime_disable(&pdev->dev);
 err_of_parse:
 err_cd_req:
-       clk_disable_unprepare(clk);
+       clk_disable_unprepare(pxa->clk_io);
+       if (!IS_ERR(pxa->clk_core))
+               clk_disable_unprepare(pxa->clk_core);
 err_clk_get:
 err_mbus_win:
        sdhci_pltfm_free(pdev);
@@ -396,12 +409,15 @@ static int sdhci_pxav3_remove(struct platform_device *pdev)
 {
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_pxa *pxa = pltfm_host->priv;
 
        pm_runtime_get_sync(&pdev->dev);
        sdhci_remove_host(host, 1);
        pm_runtime_disable(&pdev->dev);
 
-       clk_disable_unprepare(pltfm_host->clk);
+       clk_disable_unprepare(pxa->clk_io);
+       if (!IS_ERR(pxa->clk_core))
+               clk_disable_unprepare(pxa->clk_core);
 
        sdhci_pltfm_free(pdev);
 
@@ -441,15 +457,16 @@ static int sdhci_pxav3_runtime_suspend(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_pxa *pxa = pltfm_host->priv;
        unsigned long flags;
 
-       if (pltfm_host->clk) {
-               spin_lock_irqsave(&host->lock, flags);
-               host->runtime_suspended = true;
-               spin_unlock_irqrestore(&host->lock, flags);
+       spin_lock_irqsave(&host->lock, flags);
+       host->runtime_suspended = true;
+       spin_unlock_irqrestore(&host->lock, flags);
 
-               clk_disable_unprepare(pltfm_host->clk);
-       }
+       clk_disable_unprepare(pxa->clk_io);
+       if (!IS_ERR(pxa->clk_core))
+               clk_disable_unprepare(pxa->clk_core);
 
        return 0;
 }
@@ -458,15 +475,16 @@ static int sdhci_pxav3_runtime_resume(struct device *dev)
 {
        struct sdhci_host *host = dev_get_drvdata(dev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_pxa *pxa = pltfm_host->priv;
        unsigned long flags;
 
-       if (pltfm_host->clk) {
-               clk_prepare_enable(pltfm_host->clk);
+       clk_prepare_enable(pxa->clk_io);
+       if (!IS_ERR(pxa->clk_core))
+               clk_prepare_enable(pxa->clk_core);
 
-               spin_lock_irqsave(&host->lock, flags);
-               host->runtime_suspended = false;
-               spin_unlock_irqrestore(&host->lock, flags);
-       }
+       spin_lock_irqsave(&host->lock, flags);
+       host->runtime_suspended = false;
+       spin_unlock_irqrestore(&host->lock, flags);
 
        return 0;
 }
index 0ce6eb17deaf5b6361199ed2e8583f7bd72c5b56..4f7a63213b33b524d7491b981cb7c22c4a45c532 100644 (file)
@@ -300,6 +300,7 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
        struct device *dev = &ourhost->pdev->dev;
        unsigned long timeout;
        u16 clk = 0;
+       int ret;
 
        host->mmc->actual_clock = 0;
 
@@ -311,7 +312,12 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 
        sdhci_s3c_set_clock(host, clock);
 
-       clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
+       ret = clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
+       if (ret != 0) {
+               dev_err(dev, "%s: failed to set clock rate %uHz\n",
+                       mmc_hostname(host->mmc), clock);
+               return;
+       }
 
        clk = SDHCI_CLOCK_INT_EN;
        sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
index ada1a3ea3a87122b7b6ca52c7397e338bc81128f..73de62a58d70b1cb4cad2d12cff72b966f1d25ac 100644 (file)
@@ -44,8 +44,6 @@
 
 #define MAX_TUNING_LOOP 40
 
-#define ADMA_SIZE      ((128 * 2 + 1) * 4)
-
 static unsigned int debug_quirks = 0;
 static unsigned int debug_quirks2;
 
@@ -119,10 +117,17 @@ static void sdhci_dumpregs(struct sdhci_host *host)
        pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
                sdhci_readw(host, SDHCI_HOST_CONTROL2));
 
-       if (host->flags & SDHCI_USE_ADMA)
-               pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
-                      readl(host->ioaddr + SDHCI_ADMA_ERROR),
-                      readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
+       if (host->flags & SDHCI_USE_ADMA) {
+               if (host->flags & SDHCI_USE_64_BIT_DMA)
+                       pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x%08x\n",
+                                readl(host->ioaddr + SDHCI_ADMA_ERROR),
+                                readl(host->ioaddr + SDHCI_ADMA_ADDRESS_HI),
+                                readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
+               else
+                       pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
+                                readl(host->ioaddr + SDHCI_ADMA_ERROR),
+                                readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
+       }
 
        pr_debug(DRIVER_NAME ": ===========================================\n");
 }
@@ -448,18 +453,26 @@ static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
        local_irq_restore(*flags);
 }
 
-static void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd)
+static void sdhci_adma_write_desc(struct sdhci_host *host, void *desc,
+                                 dma_addr_t addr, int len, unsigned cmd)
 {
-       __le32 *dataddr = (__le32 __force *)(desc + 4);
-       __le16 *cmdlen = (__le16 __force *)desc;
+       struct sdhci_adma2_64_desc *dma_desc = desc;
+
+       /* 32-bit and 64-bit descriptors have these members in same position */
+       dma_desc->cmd = cpu_to_le16(cmd);
+       dma_desc->len = cpu_to_le16(len);
+       dma_desc->addr_lo = cpu_to_le32((u32)addr);
 
-       /* SDHCI specification says ADMA descriptors should be 4 byte
-        * aligned, so using 16 or 32bit operations should be safe. */
+       if (host->flags & SDHCI_USE_64_BIT_DMA)
+               dma_desc->addr_hi = cpu_to_le32((u64)addr >> 32);
+}
 
-       cmdlen[0] = cpu_to_le16(cmd);
-       cmdlen[1] = cpu_to_le16(len);
+static void sdhci_adma_mark_end(void *desc)
+{
+       struct sdhci_adma2_64_desc *dma_desc = desc;
 
-       dataddr[0] = cpu_to_le32(addr);
+       /* 32-bit and 64-bit descriptors have 'cmd' in same position */
+       dma_desc->cmd |= cpu_to_le16(ADMA2_END);
 }
 
 static int sdhci_adma_table_pre(struct sdhci_host *host,
@@ -467,8 +480,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
 {
        int direction;
 
-       u8 *desc;
-       u8 *align;
+       void *desc;
+       void *align;
        dma_addr_t addr;
        dma_addr_t align_addr;
        int len, offset;
@@ -489,17 +502,17 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
                direction = DMA_TO_DEVICE;
 
        host->align_addr = dma_map_single(mmc_dev(host->mmc),
-               host->align_buffer, 128 * 4, direction);
+               host->align_buffer, host->align_buffer_sz, direction);
        if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
                goto fail;
-       BUG_ON(host->align_addr & 0x3);
+       BUG_ON(host->align_addr & host->align_mask);
 
        host->sg_count = dma_map_sg(mmc_dev(host->mmc),
                data->sg, data->sg_len, direction);
        if (host->sg_count == 0)
                goto unmap_align;
 
-       desc = host->adma_desc;
+       desc = host->adma_table;
        align = host->align_buffer;
 
        align_addr = host->align_addr;
@@ -515,24 +528,27 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
                 * the (up to three) bytes that screw up the
                 * alignment.
                 */
-               offset = (4 - (addr & 0x3)) & 0x3;
+               offset = (host->align_sz - (addr & host->align_mask)) &
+                        host->align_mask;
                if (offset) {
                        if (data->flags & MMC_DATA_WRITE) {
                                buffer = sdhci_kmap_atomic(sg, &flags);
-                               WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
+                               WARN_ON(((long)buffer & (PAGE_SIZE - 1)) >
+                                       (PAGE_SIZE - offset));
                                memcpy(align, buffer, offset);
                                sdhci_kunmap_atomic(buffer, &flags);
                        }
 
                        /* tran, valid */
-                       sdhci_set_adma_desc(desc, align_addr, offset, 0x21);
+                       sdhci_adma_write_desc(host, desc, align_addr, offset,
+                                             ADMA2_TRAN_VALID);
 
                        BUG_ON(offset > 65536);
 
-                       align += 4;
-                       align_addr += 4;
+                       align += host->align_sz;
+                       align_addr += host->align_sz;
 
-                       desc += 8;
+                       desc += host->desc_sz;
 
                        addr += offset;
                        len -= offset;
@@ -541,23 +557,23 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
                BUG_ON(len > 65536);
 
                /* tran, valid */
-               sdhci_set_adma_desc(desc, addr, len, 0x21);
-               desc += 8;
+               sdhci_adma_write_desc(host, desc, addr, len, ADMA2_TRAN_VALID);
+               desc += host->desc_sz;
 
                /*
                 * If this triggers then we have a calculation bug
                 * somewhere. :/
                 */
-               WARN_ON((desc - host->adma_desc) > ADMA_SIZE);
+               WARN_ON((desc - host->adma_table) >= host->adma_table_sz);
        }
 
        if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
                /*
                * Mark the last descriptor as the terminating descriptor
                */
-               if (desc != host->adma_desc) {
-                       desc -= 8;
-                       desc[0] |= 0x2; /* end */
+               if (desc != host->adma_table) {
+                       desc -= host->desc_sz;
+                       sdhci_adma_mark_end(desc);
                }
        } else {
                /*
@@ -565,7 +581,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
                */
 
                /* nop, end, valid */
-               sdhci_set_adma_desc(desc, 0, 0, 0x3);
+               sdhci_adma_write_desc(host, desc, 0, 0, ADMA2_NOP_END_VALID);
        }
 
        /*
@@ -573,14 +589,14 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
         */
        if (data->flags & MMC_DATA_WRITE) {
                dma_sync_single_for_device(mmc_dev(host->mmc),
-                       host->align_addr, 128 * 4, direction);
+                       host->align_addr, host->align_buffer_sz, direction);
        }
 
        return 0;
 
 unmap_align:
        dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
-               128 * 4, direction);
+               host->align_buffer_sz, direction);
 fail:
        return -EINVAL;
 }
@@ -592,7 +608,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
 
        struct scatterlist *sg;
        int i, size;
-       u8 *align;
+       void *align;
        char *buffer;
        unsigned long flags;
        bool has_unaligned;
@@ -603,12 +619,12 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
                direction = DMA_TO_DEVICE;
 
        dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
-               128 * 4, direction);
+               host->align_buffer_sz, direction);
 
        /* Do a quick scan of the SG list for any unaligned mappings */
        has_unaligned = false;
        for_each_sg(data->sg, sg, host->sg_count, i)
-               if (sg_dma_address(sg) & 3) {
+               if (sg_dma_address(sg) & host->align_mask) {
                        has_unaligned = true;
                        break;
                }
@@ -620,15 +636,17 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
                align = host->align_buffer;
 
                for_each_sg(data->sg, sg, host->sg_count, i) {
-                       if (sg_dma_address(sg) & 0x3) {
-                               size = 4 - (sg_dma_address(sg) & 0x3);
+                       if (sg_dma_address(sg) & host->align_mask) {
+                               size = host->align_sz -
+                                      (sg_dma_address(sg) & host->align_mask);
 
                                buffer = sdhci_kmap_atomic(sg, &flags);
-                               WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
+                               WARN_ON(((long)buffer & (PAGE_SIZE - 1)) >
+                                       (PAGE_SIZE - size));
                                memcpy(buffer, align, size);
                                sdhci_kunmap_atomic(buffer, &flags);
 
-                               align += 4;
+                               align += host->align_sz;
                        }
                }
        }
@@ -822,6 +840,10 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
                        } else {
                                sdhci_writel(host, host->adma_addr,
                                        SDHCI_ADMA_ADDRESS);
+                               if (host->flags & SDHCI_USE_64_BIT_DMA)
+                                       sdhci_writel(host,
+                                                    (u64)host->adma_addr >> 32,
+                                                    SDHCI_ADMA_ADDRESS_HI);
                        }
                } else {
                        int sg_cnt;
@@ -855,10 +877,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
                ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
                ctrl &= ~SDHCI_CTRL_DMA_MASK;
                if ((host->flags & SDHCI_REQ_USE_DMA) &&
-                       (host->flags & SDHCI_USE_ADMA))
-                       ctrl |= SDHCI_CTRL_ADMA32;
-               else
+                       (host->flags & SDHCI_USE_ADMA)) {
+                       if (host->flags & SDHCI_USE_64_BIT_DMA)
+                               ctrl |= SDHCI_CTRL_ADMA64;
+                       else
+                               ctrl |= SDHCI_CTRL_ADMA32;
+               } else {
                        ctrl |= SDHCI_CTRL_SDMA;
+               }
                sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
        }
 
@@ -889,10 +915,15 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
        struct mmc_data *data = cmd->data;
 
        if (data == NULL) {
+               if (host->quirks2 &
+                       SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
+                       sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
+               } else {
                /* clear Auto CMD settings for no data CMDs */
-               mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
-               sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
+                       mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
+                       sdhci_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 |
                                SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
+               }
                return;
        }
 
@@ -1117,6 +1148,9 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
        case MMC_TIMING_UHS_DDR50:
                preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
                break;
+       case MMC_TIMING_MMC_HS400:
+               preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400);
+               break;
        default:
                pr_warn("%s: Invalid UHS-I mode selected\n",
                        mmc_hostname(host->mmc));
@@ -1444,6 +1478,8 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
        else if ((timing == MMC_TIMING_UHS_DDR50) ||
                 (timing == MMC_TIMING_MMC_DDR52))
                ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+       else if (timing == MMC_TIMING_MMC_HS400)
+               ctrl_2 |= SDHCI_CTRL_HS400; /* Non-standard */
        sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
 }
 EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
@@ -1515,7 +1551,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
                u16 clk, ctrl_2;
 
                /* In case of UHS-I modes, set High Speed Enable */
-               if ((ios->timing == MMC_TIMING_MMC_HS200) ||
+               if ((ios->timing == MMC_TIMING_MMC_HS400) ||
+                   (ios->timing == MMC_TIMING_MMC_HS200) ||
                    (ios->timing == MMC_TIMING_MMC_DDR52) ||
                    (ios->timing == MMC_TIMING_UHS_SDR50) ||
                    (ios->timing == MMC_TIMING_UHS_SDR104) ||
@@ -1862,6 +1899,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
         * tuning function has to be executed.
         */
        switch (host->timing) {
+       case MMC_TIMING_MMC_HS400:
        case MMC_TIMING_MMC_HS200:
        case MMC_TIMING_UHS_SDR104:
                break;
@@ -2144,9 +2182,10 @@ static void sdhci_tasklet_finish(unsigned long param)
         */
        if (!(host->flags & SDHCI_DEVICE_DEAD) &&
            ((mrq->cmd && mrq->cmd->error) ||
-                (mrq->data && (mrq->data->error ||
-                 (mrq->data->stop && mrq->data->stop->error))) ||
-                  (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
+            (mrq->sbc && mrq->sbc->error) ||
+            (mrq->data && ((mrq->data->error && !mrq->data->stop) ||
+                           (mrq->data->stop && mrq->data->stop->error))) ||
+            (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
 
                /* Some controllers need this kick or reset won't work here */
                if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
@@ -2282,32 +2321,36 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
 }
 
 #ifdef CONFIG_MMC_DEBUG
-static void sdhci_show_adma_error(struct sdhci_host *host)
+static void sdhci_adma_show_error(struct sdhci_host *host)
 {
        const char *name = mmc_hostname(host->mmc);
-       u8 *desc = host->adma_desc;
-       __le32 *dma;
-       __le16 *len;
-       u8 attr;
+       void *desc = host->adma_table;
 
        sdhci_dumpregs(host);
 
        while (true) {
-               dma = (__le32 *)(desc + 4);
-               len = (__le16 *)(desc + 2);
-               attr = *desc;
-
-               DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
-                   name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr);
+               struct sdhci_adma2_64_desc *dma_desc = desc;
+
+               if (host->flags & SDHCI_USE_64_BIT_DMA)
+                       DBG("%s: %p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n",
+                           name, desc, le32_to_cpu(dma_desc->addr_hi),
+                           le32_to_cpu(dma_desc->addr_lo),
+                           le16_to_cpu(dma_desc->len),
+                           le16_to_cpu(dma_desc->cmd));
+               else
+                       DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
+                           name, desc, le32_to_cpu(dma_desc->addr_lo),
+                           le16_to_cpu(dma_desc->len),
+                           le16_to_cpu(dma_desc->cmd));
 
-               desc += 8;
+               desc += host->desc_sz;
 
-               if (attr & 2)
+               if (dma_desc->cmd & cpu_to_le16(ADMA2_END))
                        break;
        }
 }
 #else
-static void sdhci_show_adma_error(struct sdhci_host *host) { }
+static void sdhci_adma_show_error(struct sdhci_host *host) { }
 #endif
 
 static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
@@ -2370,7 +2413,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
                host->data->error = -EILSEQ;
        else if (intmask & SDHCI_INT_ADMA_ERROR) {
                pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
-               sdhci_show_adma_error(host);
+               sdhci_adma_show_error(host);
                host->data->error = -EIO;
                if (host->ops->adma_workaround)
                        host->ops->adma_workaround(host, intmask);
@@ -2849,6 +2892,16 @@ int sdhci_add_host(struct sdhci_host *host)
                host->flags &= ~SDHCI_USE_ADMA;
        }
 
+       /*
+        * It is assumed that a 64-bit capable device has set a 64-bit DMA mask
+        * and *must* do 64-bit DMA.  A driver has the opportunity to change
+        * that during the first call to ->enable_dma().  Similarly
+        * SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to
+        * implement.
+        */
+       if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT)
+               host->flags |= SDHCI_USE_64_BIT_DMA;
+
        if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
                if (host->ops->enable_dma) {
                        if (host->ops->enable_dma(host)) {
@@ -2860,33 +2913,56 @@ int sdhci_add_host(struct sdhci_host *host)
                }
        }
 
+       /* SDMA does not support 64-bit DMA */
+       if (host->flags & SDHCI_USE_64_BIT_DMA)
+               host->flags &= ~SDHCI_USE_SDMA;
+
        if (host->flags & SDHCI_USE_ADMA) {
                /*
-                * We need to allocate descriptors for all sg entries
-                * (128) and potentially one alignment transfer for
-                * each of those entries.
+                * The DMA descriptor table size is calculated as the maximum
+                * number of segments times 2, to allow for an alignment
+                * descriptor for each segment, plus 1 for a nop end descriptor,
+                * all multipled by the descriptor size.
                 */
-               host->adma_desc = dma_alloc_coherent(mmc_dev(mmc),
-                                                    ADMA_SIZE, &host->adma_addr,
-                                                    GFP_KERNEL);
-               host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
-               if (!host->adma_desc || !host->align_buffer) {
-                       dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
-                                         host->adma_desc, host->adma_addr);
+               if (host->flags & SDHCI_USE_64_BIT_DMA) {
+                       host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
+                                             SDHCI_ADMA2_64_DESC_SZ;
+                       host->align_buffer_sz = SDHCI_MAX_SEGS *
+                                               SDHCI_ADMA2_64_ALIGN;
+                       host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
+                       host->align_sz = SDHCI_ADMA2_64_ALIGN;
+                       host->align_mask = SDHCI_ADMA2_64_ALIGN - 1;
+               } else {
+                       host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
+                                             SDHCI_ADMA2_32_DESC_SZ;
+                       host->align_buffer_sz = SDHCI_MAX_SEGS *
+                                               SDHCI_ADMA2_32_ALIGN;
+                       host->desc_sz = SDHCI_ADMA2_32_DESC_SZ;
+                       host->align_sz = SDHCI_ADMA2_32_ALIGN;
+                       host->align_mask = SDHCI_ADMA2_32_ALIGN - 1;
+               }
+               host->adma_table = dma_alloc_coherent(mmc_dev(mmc),
+                                                     host->adma_table_sz,
+                                                     &host->adma_addr,
+                                                     GFP_KERNEL);
+               host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL);
+               if (!host->adma_table || !host->align_buffer) {
+                       dma_free_coherent(mmc_dev(mmc), host->adma_table_sz,
+                                         host->adma_table, host->adma_addr);
                        kfree(host->align_buffer);
                        pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",
                                mmc_hostname(mmc));
                        host->flags &= ~SDHCI_USE_ADMA;
-                       host->adma_desc = NULL;
+                       host->adma_table = NULL;
                        host->align_buffer = NULL;
-               } else if (host->adma_addr & 3) {
+               } else if (host->adma_addr & host->align_mask) {
                        pr_warn("%s: unable to allocate aligned ADMA descriptor\n",
                                mmc_hostname(mmc));
                        host->flags &= ~SDHCI_USE_ADMA;
-                       dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
-                                         host->adma_desc, host->adma_addr);
+                       dma_free_coherent(mmc_dev(mmc), host->adma_table_sz,
+                                         host->adma_table, host->adma_addr);
                        kfree(host->align_buffer);
-                       host->adma_desc = NULL;
+                       host->adma_table = NULL;
                        host->align_buffer = NULL;
                }
        }
@@ -3027,7 +3103,7 @@ int sdhci_add_host(struct sdhci_host *host)
                if (ret) {
                        pr_warn("%s: Failed to enable vqmmc regulator: %d\n",
                                mmc_hostname(mmc), ret);
-                       mmc->supply.vqmmc = NULL;
+                       mmc->supply.vqmmc = ERR_PTR(-EINVAL);
                }
        }
 
@@ -3046,16 +3122,21 @@ int sdhci_add_host(struct sdhci_host *host)
                /* SD3.0: SDR104 is supported so (for eMMC) the caps2
                 * field can be promoted to support HS200.
                 */
-               if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200)) {
+               if (!(host->quirks2 & SDHCI_QUIRK2_BROKEN_HS200))
                        mmc->caps2 |= MMC_CAP2_HS200;
-                       if (IS_ERR(mmc->supply.vqmmc) ||
-                                       !regulator_is_supported_voltage
-                                       (mmc->supply.vqmmc, 1100000, 1300000))
-                               mmc->caps2 &= ~MMC_CAP2_HS200_1_2V_SDR;
-               }
        } else if (caps[1] & SDHCI_SUPPORT_SDR50)
                mmc->caps |= MMC_CAP_UHS_SDR50;
 
+       if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 &&
+           (caps[1] & SDHCI_SUPPORT_HS400))
+               mmc->caps2 |= MMC_CAP2_HS400;
+
+       if ((mmc->caps2 & MMC_CAP2_HSX00_1_2V) &&
+           (IS_ERR(mmc->supply.vqmmc) ||
+            !regulator_is_supported_voltage(mmc->supply.vqmmc, 1100000,
+                                            1300000)))
+               mmc->caps2 &= ~MMC_CAP2_HSX00_1_2V;
+
        if ((caps[1] & SDHCI_SUPPORT_DDR50) &&
                !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
                mmc->caps |= MMC_CAP_UHS_DDR50;
@@ -3175,11 +3256,11 @@ int sdhci_add_host(struct sdhci_host *host)
         * can do scatter/gather or not.
         */
        if (host->flags & SDHCI_USE_ADMA)
-               mmc->max_segs = 128;
+               mmc->max_segs = SDHCI_MAX_SEGS;
        else if (host->flags & SDHCI_USE_SDMA)
                mmc->max_segs = 1;
        else /* PIO */
-               mmc->max_segs = 128;
+               mmc->max_segs = SDHCI_MAX_SEGS;
 
        /*
         * Maximum number of sectors in one transfer. Limited by DMA boundary
@@ -3277,7 +3358,8 @@ int sdhci_add_host(struct sdhci_host *host)
 
        pr_info("%s: SDHCI controller on %s [%s] using %s\n",
                mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
-               (host->flags & SDHCI_USE_ADMA) ? "ADMA" :
+               (host->flags & SDHCI_USE_ADMA) ?
+               (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" :
                (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
 
        sdhci_enable_card_detection(host);
@@ -3339,18 +3421,15 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
 
        tasklet_kill(&host->finish_tasklet);
 
-       if (!IS_ERR(mmc->supply.vmmc))
-               regulator_disable(mmc->supply.vmmc);
-
        if (!IS_ERR(mmc->supply.vqmmc))
                regulator_disable(mmc->supply.vqmmc);
 
-       if (host->adma_desc)
-               dma_free_coherent(mmc_dev(mmc), ADMA_SIZE,
-                                 host->adma_desc, host->adma_addr);
+       if (host->adma_table)
+               dma_free_coherent(mmc_dev(mmc), host->adma_table_sz,
+                                 host->adma_table, host->adma_addr);
        kfree(host->align_buffer);
 
-       host->adma_desc = NULL;
+       host->adma_table = NULL;
        host->align_buffer = NULL;
 }
 
index 31896a779d4ed07834026743ac9d87ad917bebb8..ddd31cda2370f39ed2a8682c165cffd3da97efb7 100644 (file)
 #define   SDHCI_CTRL_UHS_SDR50         0x0002
 #define   SDHCI_CTRL_UHS_SDR104                0x0003
 #define   SDHCI_CTRL_UHS_DDR50         0x0004
-#define   SDHCI_CTRL_HS_SDR200         0x0005 /* reserved value in SDIO spec */
+#define   SDHCI_CTRL_HS400             0x0005 /* Non-standard */
 #define  SDHCI_CTRL_VDD_180            0x0008
 #define  SDHCI_CTRL_DRV_TYPE_MASK      0x0030
 #define   SDHCI_CTRL_DRV_TYPE_B                0x0000
 #define  SDHCI_RETUNING_MODE_SHIFT             14
 #define  SDHCI_CLOCK_MUL_MASK  0x00FF0000
 #define  SDHCI_CLOCK_MUL_SHIFT 16
+#define  SDHCI_SUPPORT_HS400   0x80000000 /* Non-standard */
 
 #define SDHCI_CAPABILITIES_1   0x44
 
 /* 55-57 reserved */
 
 #define SDHCI_ADMA_ADDRESS     0x58
+#define SDHCI_ADMA_ADDRESS_HI  0x5C
 
 /* 60-FB reserved */
 
 #define SDHCI_PRESET_FOR_SDR50 0x6A
 #define SDHCI_PRESET_FOR_SDR104        0x6C
 #define SDHCI_PRESET_FOR_DDR50 0x6E
+#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */
 #define SDHCI_PRESET_DRV_MASK  0xC000
 #define SDHCI_PRESET_DRV_SHIFT  14
 #define SDHCI_PRESET_CLKGEN_SEL_MASK   0x400
 #define SDHCI_DEFAULT_BOUNDARY_SIZE  (512 * 1024)
 #define SDHCI_DEFAULT_BOUNDARY_ARG   (ilog2(SDHCI_DEFAULT_BOUNDARY_SIZE) - 12)
 
+/* ADMA2 32-bit DMA descriptor size */
+#define SDHCI_ADMA2_32_DESC_SZ 8
+
+/* ADMA2 32-bit DMA alignment */
+#define SDHCI_ADMA2_32_ALIGN   4
+
+/* ADMA2 32-bit descriptor */
+struct sdhci_adma2_32_desc {
+       __le16  cmd;
+       __le16  len;
+       __le32  addr;
+}  __packed __aligned(SDHCI_ADMA2_32_ALIGN);
+
+/* ADMA2 64-bit DMA descriptor size */
+#define SDHCI_ADMA2_64_DESC_SZ 12
+
+/* ADMA2 64-bit DMA alignment */
+#define SDHCI_ADMA2_64_ALIGN   8
+
+/*
+ * ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte
+ * aligned.
+ */
+struct sdhci_adma2_64_desc {
+       __le16  cmd;
+       __le16  len;
+       __le32  addr_lo;
+       __le32  addr_hi;
+}  __packed __aligned(4);
+
+#define ADMA2_TRAN_VALID       0x21
+#define ADMA2_NOP_END_VALID    0x3
+#define ADMA2_END              0x2
+
+/*
+ * Maximum segments assuming a 512KiB maximum requisition size and a minimum
+ * 4KiB page size.
+ */
+#define SDHCI_MAX_SEGS         128
+
 struct sdhci_ops {
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
        u32             (*read_l)(struct sdhci_host *host, int reg);
index d1663b3c41436fc4cb4a7f172364644c08cbaad5..15cb8b7ffc3418a19770f97cf388c59ad440c0f4 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/err.h>
 
 #include <linux/clk.h>
-#include <linux/clk-private.h>
 #include <linux/clk/sunxi.h>
 
 #include <linux/gpio.h>
diff --git a/drivers/mmc/host/toshsd.c b/drivers/mmc/host/toshsd.c
new file mode 100644 (file)
index 0000000..4666262
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ *  Toshiba PCI Secure Digital Host Controller Interface driver
+ *
+ *  Copyright (C) 2014 Ondrej Zary
+ *  Copyright (C) 2007 Richard Betts, All Rights Reserved.
+ *
+ *     Based on asic3_mmc.c, copyright (c) 2005 SDG Systems, LLC and,
+ *     sdhci.c, copyright (C) 2005-2006 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+
+#include "toshsd.h"
+
+#define DRIVER_NAME "toshsd"
+
+static const struct pci_device_id pci_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA, 0x0805) },
+       { /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static void toshsd_init(struct toshsd_host *host)
+{
+       /* enable clock */
+       pci_write_config_byte(host->pdev, SD_PCICFG_CLKSTOP,
+                                       SD_PCICFG_CLKSTOP_ENABLE_ALL);
+       pci_write_config_byte(host->pdev, SD_PCICFG_CARDDETECT, 2);
+
+       /* reset */
+       iowrite16(0, host->ioaddr + SD_SOFTWARERESET); /* assert */
+       mdelay(2);
+       iowrite16(1, host->ioaddr + SD_SOFTWARERESET); /* deassert */
+       mdelay(2);
+
+       /* Clear card registers */
+       iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL);
+       iowrite32(0, host->ioaddr + SD_CARDSTATUS);
+       iowrite32(0, host->ioaddr + SD_ERRORSTATUS0);
+       iowrite16(0, host->ioaddr + SD_STOPINTERNAL);
+
+       /* SDIO clock? */
+       iowrite16(0x100, host->ioaddr + SDIO_BASE + SDIO_CLOCKNWAITCTRL);
+
+       /* enable LED */
+       pci_write_config_byte(host->pdev, SD_PCICFG_SDLED_ENABLE1,
+                                       SD_PCICFG_LED_ENABLE1_START);
+       pci_write_config_byte(host->pdev, SD_PCICFG_SDLED_ENABLE2,
+                                       SD_PCICFG_LED_ENABLE2_START);
+
+       /* set interrupt masks */
+       iowrite32(~(u32)(SD_CARD_RESP_END | SD_CARD_RW_END
+                       | SD_CARD_CARD_REMOVED_0 | SD_CARD_CARD_INSERTED_0
+                       | SD_BUF_READ_ENABLE | SD_BUF_WRITE_ENABLE
+                       | SD_BUF_CMD_TIMEOUT),
+                       host->ioaddr + SD_INTMASKCARD);
+
+       iowrite16(0x1000, host->ioaddr + SD_TRANSACTIONCTRL);
+}
+
+/* Set MMC clock / power.
+ * Note: This controller uses a simple divider scheme therefore it cannot run
+ * SD/MMC cards at full speed (24/20MHz). HCLK (=33MHz PCI clock?) is too high
+ * and the next slowest is 16MHz (div=2).
+ */
+static void __toshsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct toshsd_host *host = mmc_priv(mmc);
+
+       if (ios->clock) {
+               u16 clk;
+               int div = 1;
+
+               while (ios->clock < HCLK / div)
+                       div *= 2;
+
+               clk = div >> 2;
+
+               if (div == 1) { /* disable the divider */
+                       pci_write_config_byte(host->pdev, SD_PCICFG_CLKMODE,
+                                             SD_PCICFG_CLKMODE_DIV_DISABLE);
+                       clk |= SD_CARDCLK_DIV_DISABLE;
+               } else
+                       pci_write_config_byte(host->pdev, SD_PCICFG_CLKMODE, 0);
+
+               clk |= SD_CARDCLK_ENABLE_CLOCK;
+               iowrite16(clk, host->ioaddr + SD_CARDCLOCKCTRL);
+
+               mdelay(10);
+       } else
+               iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL);
+
+       switch (ios->power_mode) {
+       case MMC_POWER_OFF:
+               pci_write_config_byte(host->pdev, SD_PCICFG_POWER1,
+                                       SD_PCICFG_PWR1_OFF);
+               mdelay(1);
+               break;
+       case MMC_POWER_UP:
+               break;
+       case MMC_POWER_ON:
+               pci_write_config_byte(host->pdev, SD_PCICFG_POWER1,
+                                       SD_PCICFG_PWR1_33V);
+               pci_write_config_byte(host->pdev, SD_PCICFG_POWER2,
+                                       SD_PCICFG_PWR2_AUTO);
+               mdelay(20);
+               break;
+       }
+
+       switch (ios->bus_width) {
+       case MMC_BUS_WIDTH_1:
+               iowrite16(SD_CARDOPT_REQUIRED | SD_CARDOPT_DATA_RESP_TIMEOUT(14)
+                               | SD_CARDOPT_C2_MODULE_ABSENT
+                               | SD_CARDOPT_DATA_XFR_WIDTH_1,
+                               host->ioaddr + SD_CARDOPTIONSETUP);
+               break;
+       case MMC_BUS_WIDTH_4:
+               iowrite16(SD_CARDOPT_REQUIRED | SD_CARDOPT_DATA_RESP_TIMEOUT(14)
+                               | SD_CARDOPT_C2_MODULE_ABSENT
+                               | SD_CARDOPT_DATA_XFR_WIDTH_4,
+                               host->ioaddr + SD_CARDOPTIONSETUP);
+               break;
+       }
+}
+
+static void toshsd_set_led(struct toshsd_host *host, unsigned char state)
+{
+       iowrite16(state, host->ioaddr + SDIO_BASE + SDIO_LEDCTRL);
+}
+
+static void toshsd_finish_request(struct toshsd_host *host)
+{
+       struct mmc_request *mrq = host->mrq;
+
+       /* Write something to end the command */
+       host->mrq = NULL;
+       host->cmd = NULL;
+       host->data = NULL;
+
+       toshsd_set_led(host, 0);
+       mmc_request_done(host->mmc, mrq);
+}
+
+static irqreturn_t toshsd_thread_irq(int irq, void *dev_id)
+{
+       struct toshsd_host *host = dev_id;
+       struct mmc_data *data = host->data;
+       struct sg_mapping_iter *sg_miter = &host->sg_miter;
+       unsigned short *buf;
+       int count;
+       unsigned long flags;
+
+       if (!data) {
+               dev_warn(&host->pdev->dev, "Spurious Data IRQ\n");
+               if (host->cmd) {
+                       host->cmd->error = -EIO;
+                       toshsd_finish_request(host);
+               }
+               return IRQ_NONE;
+       }
+       spin_lock_irqsave(&host->lock, flags);
+
+       if (!sg_miter_next(sg_miter))
+               return IRQ_HANDLED;
+       buf = sg_miter->addr;
+
+       /* Ensure we dont read more than one block. The chip will interrupt us
+        * When the next block is available.
+        */
+       count = sg_miter->length;
+       if (count > data->blksz)
+               count = data->blksz;
+
+       dev_dbg(&host->pdev->dev, "count: %08x, flags %08x\n", count,
+               data->flags);
+
+       /* Transfer the data */
+       if (data->flags & MMC_DATA_READ)
+               ioread32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2);
+       else
+               iowrite32_rep(host->ioaddr + SD_DATAPORT, buf, count >> 2);
+
+       sg_miter->consumed = count;
+       sg_miter_stop(sg_miter);
+
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+static void toshsd_cmd_irq(struct toshsd_host *host)
+{
+       struct mmc_command *cmd = host->cmd;
+       u8 *buf;
+       u16 data;
+
+       if (!host->cmd) {
+               dev_warn(&host->pdev->dev, "Spurious CMD irq\n");
+               return;
+       }
+       buf = (u8 *)cmd->resp;
+       host->cmd = NULL;
+
+       if (cmd->flags & MMC_RSP_PRESENT && cmd->flags & MMC_RSP_136) {
+               /* R2 */
+               buf[12] = 0xff;
+               data = ioread16(host->ioaddr + SD_RESPONSE0);
+               buf[13] = data & 0xff;
+               buf[14] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE1);
+               buf[15] = data & 0xff;
+               buf[8] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE2);
+               buf[9] = data & 0xff;
+               buf[10] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE3);
+               buf[11] = data & 0xff;
+               buf[4] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE4);
+               buf[5] = data & 0xff;
+               buf[6] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE5);
+               buf[7] = data & 0xff;
+               buf[0] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE6);
+               buf[1] = data & 0xff;
+               buf[2] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE7);
+               buf[3] = data & 0xff;
+       } else if (cmd->flags & MMC_RSP_PRESENT) {
+               /* R1, R1B, R3, R6, R7 */
+               data = ioread16(host->ioaddr + SD_RESPONSE0);
+               buf[0] = data & 0xff;
+               buf[1] = data >> 8;
+               data = ioread16(host->ioaddr + SD_RESPONSE1);
+               buf[2] = data & 0xff;
+               buf[3] = data >> 8;
+       }
+
+       dev_dbg(&host->pdev->dev, "Command IRQ complete %d %d %x\n",
+               cmd->opcode, cmd->error, cmd->flags);
+
+       /* If there is data to handle we will
+        * finish the request in the mmc_data_end_irq handler.*/
+       if (host->data)
+               return;
+
+       toshsd_finish_request(host);
+}
+
+static void toshsd_data_end_irq(struct toshsd_host *host)
+{
+       struct mmc_data *data = host->data;
+
+       host->data = NULL;
+
+       if (!data) {
+               dev_warn(&host->pdev->dev, "Spurious data end IRQ\n");
+               return;
+       }
+
+       if (data->error == 0)
+               data->bytes_xfered = data->blocks * data->blksz;
+       else
+               data->bytes_xfered = 0;
+
+       dev_dbg(&host->pdev->dev, "Completed data request xfr=%d\n",
+               data->bytes_xfered);
+
+       iowrite16(0, host->ioaddr + SD_STOPINTERNAL);
+
+       toshsd_finish_request(host);
+}
+
+static irqreturn_t toshsd_irq(int irq, void *dev_id)
+{
+       struct toshsd_host *host = dev_id;
+       u32 int_reg, int_mask, int_status, detail;
+       int error = 0, ret = IRQ_HANDLED;
+
+       spin_lock(&host->lock);
+       int_status = ioread32(host->ioaddr + SD_CARDSTATUS);
+       int_mask = ioread32(host->ioaddr + SD_INTMASKCARD);
+       int_reg = int_status & ~int_mask & ~IRQ_DONT_CARE_BITS;
+
+       dev_dbg(&host->pdev->dev, "IRQ status:%x mask:%x\n",
+               int_status, int_mask);
+
+       /* nothing to do: it's not our IRQ */
+       if (!int_reg) {
+               ret = IRQ_NONE;
+               goto irq_end;
+       }
+
+       if (int_reg & SD_BUF_CMD_TIMEOUT) {
+               error = -ETIMEDOUT;
+               dev_dbg(&host->pdev->dev, "Timeout\n");
+       } else if (int_reg & SD_BUF_CRC_ERR) {
+               error = -EILSEQ;
+               dev_err(&host->pdev->dev, "BadCRC\n");
+       } else if (int_reg & (SD_BUF_ILLEGAL_ACCESS
+                               | SD_BUF_CMD_INDEX_ERR
+                               | SD_BUF_STOP_BIT_END_ERR
+                               | SD_BUF_OVERFLOW
+                               | SD_BUF_UNDERFLOW
+                               | SD_BUF_DATA_TIMEOUT)) {
+               dev_err(&host->pdev->dev, "Buffer status error: { %s%s%s%s%s%s}\n",
+                       int_reg & SD_BUF_ILLEGAL_ACCESS ? "ILLEGAL_ACC " : "",
+                       int_reg & SD_BUF_CMD_INDEX_ERR ? "CMD_INDEX " : "",
+                       int_reg & SD_BUF_STOP_BIT_END_ERR ? "STOPBIT_END " : "",
+                       int_reg & SD_BUF_OVERFLOW ? "OVERFLOW " : "",
+                       int_reg & SD_BUF_UNDERFLOW ? "UNDERFLOW " : "",
+                       int_reg & SD_BUF_DATA_TIMEOUT ? "DATA_TIMEOUT " : "");
+
+               detail = ioread32(host->ioaddr + SD_ERRORSTATUS0);
+               dev_err(&host->pdev->dev, "detail error status { %s%s%s%s%s%s%s%s%s%s%s%s%s}\n",
+                       detail & SD_ERR0_RESP_CMD_ERR ? "RESP_CMD " : "",
+                       detail & SD_ERR0_RESP_NON_CMD12_END_BIT_ERR ? "RESP_END_BIT " : "",
+                       detail & SD_ERR0_RESP_CMD12_END_BIT_ERR ? "RESP_END_BIT " : "",
+                       detail & SD_ERR0_READ_DATA_END_BIT_ERR ? "READ_DATA_END_BIT " : "",
+                       detail & SD_ERR0_WRITE_CRC_STATUS_END_BIT_ERR ? "WRITE_CMD_END_BIT " : "",
+                       detail & SD_ERR0_RESP_NON_CMD12_CRC_ERR ? "RESP_CRC " : "",
+                       detail & SD_ERR0_RESP_CMD12_CRC_ERR ? "RESP_CRC " : "",
+                       detail & SD_ERR0_READ_DATA_CRC_ERR ? "READ_DATA_CRC " : "",
+                       detail & SD_ERR0_WRITE_CMD_CRC_ERR ? "WRITE_CMD_CRC " : "",
+                       detail & SD_ERR1_NO_CMD_RESP ? "NO_CMD_RESP " : "",
+                       detail & SD_ERR1_TIMEOUT_READ_DATA ? "READ_DATA_TIMEOUT " : "",
+                       detail & SD_ERR1_TIMEOUT_CRS_STATUS ? "CRS_STATUS_TIMEOUT " : "",
+                       detail & SD_ERR1_TIMEOUT_CRC_BUSY ? "CRC_BUSY_TIMEOUT " : "");
+               error = -EIO;
+       }
+
+       if (error) {
+               if (host->cmd)
+                       host->cmd->error = error;
+
+               if (error == -ETIMEDOUT) {
+                       iowrite32(int_status &
+                                 ~(SD_BUF_CMD_TIMEOUT | SD_CARD_RESP_END),
+                                 host->ioaddr + SD_CARDSTATUS);
+               } else {
+                       toshsd_init(host);
+                       __toshsd_set_ios(host->mmc, &host->mmc->ios);
+                       goto irq_end;
+               }
+       }
+
+       /* Card insert/remove. The mmc controlling code is stateless. */
+       if (int_reg & (SD_CARD_CARD_INSERTED_0 | SD_CARD_CARD_REMOVED_0)) {
+               iowrite32(int_status &
+                         ~(SD_CARD_CARD_REMOVED_0 | SD_CARD_CARD_INSERTED_0),
+                         host->ioaddr + SD_CARDSTATUS);
+
+               if (int_reg & SD_CARD_CARD_INSERTED_0)
+                       toshsd_init(host);
+
+               mmc_detect_change(host->mmc, 1);
+       }
+
+       /* Data transfer */
+       if (int_reg & (SD_BUF_READ_ENABLE | SD_BUF_WRITE_ENABLE)) {
+               iowrite32(int_status &
+                         ~(SD_BUF_WRITE_ENABLE | SD_BUF_READ_ENABLE),
+                         host->ioaddr + SD_CARDSTATUS);
+
+               ret = IRQ_WAKE_THREAD;
+               goto irq_end;
+       }
+
+       /* Command completion */
+       if (int_reg & SD_CARD_RESP_END) {
+               iowrite32(int_status & ~(SD_CARD_RESP_END),
+                         host->ioaddr + SD_CARDSTATUS);
+               toshsd_cmd_irq(host);
+       }
+
+       /* Data transfer completion */
+       if (int_reg & SD_CARD_RW_END) {
+               iowrite32(int_status & ~(SD_CARD_RW_END),
+                         host->ioaddr + SD_CARDSTATUS);
+               toshsd_data_end_irq(host);
+       }
+irq_end:
+       spin_unlock(&host->lock);
+       return ret;
+}
+
+static void toshsd_start_cmd(struct toshsd_host *host, struct mmc_command *cmd)
+{
+       struct mmc_data *data = host->data;
+       int c = cmd->opcode;
+
+       dev_dbg(&host->pdev->dev, "Command opcode: %d\n", cmd->opcode);
+
+       if (cmd->opcode == MMC_STOP_TRANSMISSION) {
+               iowrite16(SD_STOPINT_ISSUE_CMD12,
+                         host->ioaddr + SD_STOPINTERNAL);
+
+               cmd->resp[0] = cmd->opcode;
+               cmd->resp[1] = 0;
+               cmd->resp[2] = 0;
+               cmd->resp[3] = 0;
+
+               toshsd_finish_request(host);
+               return;
+       }
+
+       switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_NONE:
+               c |= SD_CMD_RESP_TYPE_NONE;
+               break;
+
+       case MMC_RSP_R1:
+               c |= SD_CMD_RESP_TYPE_EXT_R1;
+               break;
+       case MMC_RSP_R1B:
+               c |= SD_CMD_RESP_TYPE_EXT_R1B;
+               break;
+       case MMC_RSP_R2:
+               c |= SD_CMD_RESP_TYPE_EXT_R2;
+               break;
+       case MMC_RSP_R3:
+               c |= SD_CMD_RESP_TYPE_EXT_R3;
+               break;
+
+       default:
+               dev_err(&host->pdev->dev, "Unknown response type %d\n",
+                       mmc_resp_type(cmd));
+               break;
+       }
+
+       host->cmd = cmd;
+
+       if (cmd->opcode == MMC_APP_CMD)
+               c |= SD_CMD_TYPE_ACMD;
+
+       if (cmd->opcode == MMC_GO_IDLE_STATE)
+               c |= (3 << 8);  /* removed from ipaq-asic3.h for some reason */
+
+       if (data) {
+               c |= SD_CMD_DATA_PRESENT;
+
+               if (data->blocks > 1) {
+                       iowrite16(SD_STOPINT_AUTO_ISSUE_CMD12,
+                                 host->ioaddr + SD_STOPINTERNAL);
+                       c |= SD_CMD_MULTI_BLOCK;
+               }
+
+               if (data->flags & MMC_DATA_READ)
+                       c |= SD_CMD_TRANSFER_READ;
+
+               /* MMC_DATA_WRITE does not require a bit to be set */
+       }
+
+       /* Send the command */
+       iowrite32(cmd->arg, host->ioaddr + SD_ARG0);
+       iowrite16(c, host->ioaddr + SD_CMD);
+}
+
+static void toshsd_start_data(struct toshsd_host *host, struct mmc_data *data)
+{
+       unsigned int flags = SG_MITER_ATOMIC;
+
+       dev_dbg(&host->pdev->dev, "setup data transfer: blocksize %08x  nr_blocks %d, offset: %08x\n",
+               data->blksz, data->blocks, data->sg->offset);
+
+       host->data = data;
+
+       if (data->flags & MMC_DATA_READ)
+               flags |= SG_MITER_TO_SG;
+       else
+               flags |= SG_MITER_FROM_SG;
+
+       sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
+
+       /* Set transfer length and blocksize */
+       iowrite16(data->blocks, host->ioaddr + SD_BLOCKCOUNT);
+       iowrite16(data->blksz, host->ioaddr + SD_CARDXFERDATALEN);
+}
+
+/* Process requests from the MMC layer */
+static void toshsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+       struct toshsd_host *host = mmc_priv(mmc);
+       unsigned long flags;
+
+       /* abort if card not present */
+       if (!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0)) {
+               mrq->cmd->error = -ENOMEDIUM;
+               mmc_request_done(mmc, mrq);
+               return;
+       }
+
+       spin_lock_irqsave(&host->lock, flags);
+
+       WARN_ON(host->mrq != NULL);
+
+       host->mrq = mrq;
+
+       if (mrq->data)
+               toshsd_start_data(host, mrq->data);
+
+       toshsd_set_led(host, 1);
+
+       toshsd_start_cmd(host, mrq->cmd);
+
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void toshsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct toshsd_host *host = mmc_priv(mmc);
+       unsigned long flags;
+
+       spin_lock_irqsave(&host->lock, flags);
+       __toshsd_set_ios(mmc, ios);
+       spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static int toshsd_get_ro(struct mmc_host *mmc)
+{
+       struct toshsd_host *host = mmc_priv(mmc);
+
+       /* active low */
+       return !(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_WRITE_PROTECT);
+}
+
+static int toshsd_get_cd(struct mmc_host *mmc)
+{
+       struct toshsd_host *host = mmc_priv(mmc);
+
+       return !!(ioread16(host->ioaddr + SD_CARDSTATUS) & SD_CARD_PRESENT_0);
+}
+
+static struct mmc_host_ops toshsd_ops = {
+       .request = toshsd_request,
+       .set_ios = toshsd_set_ios,
+       .get_ro = toshsd_get_ro,
+       .get_cd = toshsd_get_cd,
+};
+
+
+static void toshsd_powerdown(struct toshsd_host *host)
+{
+       /* mask all interrupts */
+       iowrite32(0xffffffff, host->ioaddr + SD_INTMASKCARD);
+       /* disable card clock */
+       iowrite16(0x000, host->ioaddr + SDIO_BASE + SDIO_CLOCKNWAITCTRL);
+       iowrite16(0, host->ioaddr + SD_CARDCLOCKCTRL);
+       /* power down card */
+       pci_write_config_byte(host->pdev, SD_PCICFG_POWER1, SD_PCICFG_PWR1_OFF);
+       /* disable clock */
+       pci_write_config_byte(host->pdev, SD_PCICFG_CLKSTOP, 0);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int toshsd_pm_suspend(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct toshsd_host *host = pci_get_drvdata(pdev);
+
+       toshsd_powerdown(host);
+
+       pci_save_state(pdev);
+       pci_enable_wake(pdev, PCI_D3hot, 0);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       return 0;
+}
+
+static int toshsd_pm_resume(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct toshsd_host *host = pci_get_drvdata(pdev);
+       int ret;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       toshsd_init(host);
+
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static int toshsd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int ret;
+       struct toshsd_host *host;
+       struct mmc_host *mmc;
+       resource_size_t base;
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       mmc = mmc_alloc_host(sizeof(struct toshsd_host), &pdev->dev);
+       if (!mmc) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+
+       host->pdev = pdev;
+       pci_set_drvdata(pdev, host);
+
+       ret = pci_request_regions(pdev, DRIVER_NAME);
+       if (ret)
+               goto free;
+
+       host->ioaddr = pci_iomap(pdev, 0, 0);
+       if (!host->ioaddr) {
+               ret = -ENOMEM;
+               goto release;
+       }
+
+       /* Set MMC host parameters */
+       mmc->ops = &toshsd_ops;
+       mmc->caps = MMC_CAP_4_BIT_DATA;
+       mmc->ocr_avail = MMC_VDD_32_33;
+
+       mmc->f_min = HCLK / 512;
+       mmc->f_max = HCLK;
+
+       spin_lock_init(&host->lock);
+
+       toshsd_init(host);
+
+       ret = request_threaded_irq(pdev->irq, toshsd_irq, toshsd_thread_irq,
+                                  IRQF_SHARED, DRIVER_NAME, host);
+       if (ret)
+               goto unmap;
+
+       mmc_add_host(mmc);
+
+       base = pci_resource_start(pdev, 0);
+       dev_dbg(&pdev->dev, "MMIO %pa, IRQ %d\n", &base, pdev->irq);
+
+       pm_suspend_ignore_children(&pdev->dev, 1);
+
+       return 0;
+
+unmap:
+       pci_iounmap(pdev, host->ioaddr);
+release:
+       pci_release_regions(pdev);
+free:
+       mmc_free_host(mmc);
+       pci_set_drvdata(pdev, NULL);
+err:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void toshsd_remove(struct pci_dev *pdev)
+{
+       struct toshsd_host *host = pci_get_drvdata(pdev);
+
+       mmc_remove_host(host->mmc);
+       toshsd_powerdown(host);
+       free_irq(pdev->irq, host);
+       pci_iounmap(pdev, host->ioaddr);
+       pci_release_regions(pdev);
+       mmc_free_host(host->mmc);
+       pci_set_drvdata(pdev, NULL);
+       pci_disable_device(pdev);
+}
+
+static const struct dev_pm_ops toshsd_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(toshsd_pm_suspend, toshsd_pm_resume)
+};
+
+static struct pci_driver toshsd_driver = {
+       .name = DRIVER_NAME,
+       .id_table = pci_ids,
+       .probe = toshsd_probe,
+       .remove = toshsd_remove,
+       .driver.pm = &toshsd_pm_ops,
+};
+
+static int __init toshsd_drv_init(void)
+{
+       return pci_register_driver(&toshsd_driver);
+}
+
+static void __exit toshsd_drv_exit(void)
+{
+       pci_unregister_driver(&toshsd_driver);
+}
+
+module_init(toshsd_drv_init);
+module_exit(toshsd_drv_exit);
+
+MODULE_AUTHOR("Ondrej Zary, Richard Betts");
+MODULE_DESCRIPTION("Toshiba PCI Secure Digital Host Controller Interface driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/toshsd.h b/drivers/mmc/host/toshsd.h
new file mode 100644 (file)
index 0000000..b6c0d89
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ *  Toshiba PCI Secure Digital Host Controller Interface driver
+ *
+ *  Copyright (C) 2014 Ondrej Zary
+ *  Copyright (C) 2007 Richard Betts, All Rights Reserved.
+ *
+ *      Based on asic3_mmc.c Copyright (c) 2005 SDG Systems, LLC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#define HCLK   33000000        /* 33 MHz (PCI clock) */
+
+#define SD_PCICFG_CLKSTOP      0x40    /* 0x1f = clock controller, 0 = stop */
+#define SD_PCICFG_GATEDCLK     0x41    /* Gated clock */
+#define SD_PCICFG_CLKMODE      0x42    /* Control clock of SD controller */
+#define SD_PCICFG_PINSTATUS    0x44    /* R/O: read status of SD pins */
+#define SD_PCICFG_POWER1       0x48
+#define SD_PCICFG_POWER2       0x49
+#define SD_PCICFG_POWER3       0x4a
+#define SD_PCICFG_CARDDETECT   0x4c
+#define SD_PCICFG_SLOTS                0x50    /* R/O: define support slot number */
+#define SD_PCICFG_EXTGATECLK1  0xf0    /* Could be used for gated clock */
+#define SD_PCICFG_EXTGATECLK2  0xf1    /* Could be used for gated clock */
+#define SD_PCICFG_EXTGATECLK3  0xf9    /* Bit 1: double buffer/single buffer */
+#define SD_PCICFG_SDLED_ENABLE1        0xfa
+#define SD_PCICFG_SDLED_ENABLE2        0xfe
+
+#define SD_PCICFG_CLKMODE_DIV_DISABLE  BIT(0)
+#define SD_PCICFG_CLKSTOP_ENABLE_ALL   0x1f
+#define SD_PCICFG_LED_ENABLE1_START    0x12
+#define SD_PCICFG_LED_ENABLE2_START    0x80
+
+#define SD_PCICFG_PWR1_33V     0x08    /* Set for 3.3 volts */
+#define SD_PCICFG_PWR1_OFF     0x00    /* Turn off power */
+#define SD_PCICFG_PWR2_AUTO    0x02
+
+#define SD_CMD                 0x00    /* also for SDIO */
+#define SD_ARG0                        0x04    /* also for SDIO */
+#define SD_ARG1                        0x06    /* also for SDIO */
+#define SD_STOPINTERNAL                0x08
+#define SD_BLOCKCOUNT          0x0a    /* also for SDIO */
+#define SD_RESPONSE0           0x0c    /* also for SDIO */
+#define SD_RESPONSE1           0x0e    /* also for SDIO */
+#define SD_RESPONSE2           0x10    /* also for SDIO */
+#define SD_RESPONSE3           0x12    /* also for SDIO */
+#define SD_RESPONSE4           0x14    /* also for SDIO */
+#define SD_RESPONSE5           0x16    /* also for SDIO */
+#define SD_RESPONSE6           0x18    /* also for SDIO */
+#define SD_RESPONSE7           0x1a    /* also for SDIO */
+#define SD_CARDSTATUS          0x1c    /* also for SDIO */
+#define SD_BUFFERCTRL          0x1e    /* also for SDIO */
+#define SD_INTMASKCARD         0x20    /* also for SDIO */
+#define SD_INTMASKBUFFER       0x22    /* also for SDIO */
+#define SD_CARDCLOCKCTRL       0x24
+#define SD_CARDXFERDATALEN     0x26    /* also for SDIO */
+#define SD_CARDOPTIONSETUP     0x28    /* also for SDIO */
+#define SD_ERRORSTATUS0                0x2c    /* also for SDIO */
+#define SD_ERRORSTATUS1                0x2e    /* also for SDIO */
+#define SD_DATAPORT            0x30    /* also for SDIO */
+#define SD_TRANSACTIONCTRL     0x34    /* also for SDIO */
+#define SD_SOFTWARERESET       0xe0    /* also for SDIO */
+
+/* registers above marked "also for SDIO" and all SDIO registers below can be
+ * accessed at SDIO_BASE + reg address */
+#define SDIO_BASE       0x100
+
+#define SDIO_CARDPORTSEL       0x02
+#define SDIO_CARDINTCTRL       0x36
+#define SDIO_CLOCKNWAITCTRL    0x38
+#define SDIO_HOSTINFORMATION   0x3a
+#define SDIO_ERRORCTRL         0x3c
+#define SDIO_LEDCTRL           0x3e
+
+#define SD_TRANSCTL_SET                BIT(8)
+
+#define SD_CARDCLK_DIV_DISABLE BIT(15)
+#define SD_CARDCLK_ENABLE_CLOCK        BIT(8)
+#define SD_CARDCLK_CLK_DIV_512 BIT(7)
+#define SD_CARDCLK_CLK_DIV_256 BIT(6)
+#define SD_CARDCLK_CLK_DIV_128 BIT(5)
+#define SD_CARDCLK_CLK_DIV_64  BIT(4)
+#define SD_CARDCLK_CLK_DIV_32  BIT(3)
+#define SD_CARDCLK_CLK_DIV_16  BIT(2)
+#define SD_CARDCLK_CLK_DIV_8   BIT(1)
+#define SD_CARDCLK_CLK_DIV_4   BIT(0)
+#define SD_CARDCLK_CLK_DIV_2   0
+
+#define SD_CARDOPT_REQUIRED            0x000e
+#define SD_CARDOPT_DATA_RESP_TIMEOUT(x)        (((x) & 0x0f) << 4) /* 4 bits */
+#define SD_CARDOPT_C2_MODULE_ABSENT    BIT(14)
+#define SD_CARDOPT_DATA_XFR_WIDTH_1    (1 << 15)
+#define SD_CARDOPT_DATA_XFR_WIDTH_4    (0 << 15)
+
+#define SD_CMD_TYPE_CMD                        (0 << 6)
+#define SD_CMD_TYPE_ACMD               (1 << 6)
+#define SD_CMD_TYPE_AUTHEN             (2 << 6)
+#define SD_CMD_RESP_TYPE_NONE          (3 << 8)
+#define SD_CMD_RESP_TYPE_EXT_R1                (4 << 8)
+#define SD_CMD_RESP_TYPE_EXT_R1B       (5 << 8)
+#define SD_CMD_RESP_TYPE_EXT_R2                (6 << 8)
+#define SD_CMD_RESP_TYPE_EXT_R3                (7 << 8)
+#define SD_CMD_RESP_TYPE_EXT_R6                (4 << 8)
+#define SD_CMD_RESP_TYPE_EXT_R7                (4 << 8)
+#define SD_CMD_DATA_PRESENT            BIT(11)
+#define SD_CMD_TRANSFER_READ           BIT(12)
+#define SD_CMD_MULTI_BLOCK             BIT(13)
+#define SD_CMD_SECURITY_CMD            BIT(14)
+
+#define SD_STOPINT_ISSUE_CMD12         BIT(0)
+#define SD_STOPINT_AUTO_ISSUE_CMD12    BIT(8)
+
+#define SD_CARD_RESP_END       BIT(0)
+#define SD_CARD_RW_END         BIT(2)
+#define SD_CARD_CARD_REMOVED_0 BIT(3)
+#define SD_CARD_CARD_INSERTED_0        BIT(4)
+#define SD_CARD_PRESENT_0      BIT(5)
+#define SD_CARD_UNK6           BIT(6)
+#define SD_CARD_WRITE_PROTECT  BIT(7)
+#define SD_CARD_CARD_REMOVED_3 BIT(8)
+#define SD_CARD_CARD_INSERTED_3        BIT(9)
+#define SD_CARD_PRESENT_3      BIT(10)
+
+#define SD_BUF_CMD_INDEX_ERR   BIT(16)
+#define SD_BUF_CRC_ERR         BIT(17)
+#define SD_BUF_STOP_BIT_END_ERR        BIT(18)
+#define SD_BUF_DATA_TIMEOUT    BIT(19)
+#define SD_BUF_OVERFLOW                BIT(20)
+#define SD_BUF_UNDERFLOW       BIT(21)
+#define SD_BUF_CMD_TIMEOUT     BIT(22)
+#define SD_BUF_UNK7            BIT(23)
+#define SD_BUF_READ_ENABLE     BIT(24)
+#define SD_BUF_WRITE_ENABLE    BIT(25)
+#define SD_BUF_ILLEGAL_FUNCTION        BIT(29)
+#define SD_BUF_CMD_BUSY                BIT(30)
+#define SD_BUF_ILLEGAL_ACCESS  BIT(31)
+
+#define SD_ERR0_RESP_CMD_ERR                   BIT(0)
+#define SD_ERR0_RESP_NON_CMD12_END_BIT_ERR     BIT(2)
+#define SD_ERR0_RESP_CMD12_END_BIT_ERR         BIT(3)
+#define SD_ERR0_READ_DATA_END_BIT_ERR          BIT(4)
+#define SD_ERR0_WRITE_CRC_STATUS_END_BIT_ERR   BIT(5)
+#define SD_ERR0_RESP_NON_CMD12_CRC_ERR         BIT(8)
+#define SD_ERR0_RESP_CMD12_CRC_ERR             BIT(9)
+#define SD_ERR0_READ_DATA_CRC_ERR              BIT(10)
+#define SD_ERR0_WRITE_CMD_CRC_ERR              BIT(11)
+
+#define SD_ERR1_NO_CMD_RESP            BIT(16)
+#define SD_ERR1_TIMEOUT_READ_DATA      BIT(20)
+#define SD_ERR1_TIMEOUT_CRS_STATUS     BIT(21)
+#define SD_ERR1_TIMEOUT_CRC_BUSY       BIT(22)
+
+#define IRQ_DONT_CARE_BITS (SD_CARD_PRESENT_3 \
+       | SD_CARD_WRITE_PROTECT \
+       | SD_CARD_UNK6 \
+       | SD_CARD_PRESENT_0 \
+       | SD_BUF_UNK7 \
+       | SD_BUF_CMD_BUSY)
+
+struct toshsd_host {
+       struct pci_dev *pdev;
+       struct mmc_host *mmc;
+
+       spinlock_t lock;
+
+       struct mmc_request *mrq;/* Current request */
+       struct mmc_command *cmd;/* Current command */
+       struct mmc_data *data;  /* Current data request */
+
+       struct sg_mapping_iter sg_miter; /* for PIO */
+
+       void __iomem *ioaddr; /* mapped address */
+};
index a7543ba3e19041e5aad85c6718b856a07f8f9726..3096f3ded3adf051454d5a99176267b070ceae2d 100644 (file)
@@ -2590,6 +2590,8 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
 
                /* Go to known state. Chip may have been power cycled */
                if (chip->state == FL_PM_SUSPENDED) {
+                       /* Refresh LH28F640BF Partition Config. Register */
+                       fixup_LH28F640BF(mtd);
                        map_write(map, CMD(0xFF), cfi->chips[i].start);
                        chip->oldstate = chip->state = FL_READY;
                        wake_up(&chip->wq);
index dcda6287228d0b6c671b0f5f456892aabd3c98df..ed827cf894e4d803701c9abec9756302fa899252 100644 (file)
@@ -193,10 +193,10 @@ static int m25p_probe(struct spi_device *spi)
 {
        struct mtd_part_parser_data     ppdata;
        struct flash_platform_data      *data;
-       const struct spi_device_id *id = NULL;
        struct m25p *flash;
        struct spi_nor *nor;
        enum read_mode mode = SPI_NOR_NORMAL;
+       char *flash_name = NULL;
        int ret;
 
        data = dev_get_platdata(&spi->dev);
@@ -236,13 +236,11 @@ static int m25p_probe(struct spi_device *spi)
         * If that's the case, respect "type" and ignore a "name".
         */
        if (data && data->type)
-               id = spi_nor_match_id(data->type);
+               flash_name = data->type;
+       else
+               flash_name = spi->modalias;
 
-       /* If we didn't get name from platform, simply use "modalias". */
-       if (!id)
-               id = spi_get_device_id(spi);
-
-       ret = spi_nor_scan(nor, id, mode);
+       ret = spi_nor_scan(nor, flash_name, mode);
        if (ret)
                return ret;
 
@@ -263,12 +261,62 @@ 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.
+ */
+static const struct spi_device_id m25p_ids[] = {
+       {"at25fs010"},  {"at25fs040"},  {"at25df041a"}, {"at25df321a"},
+       {"at25df641"},  {"at26f004"},   {"at26df081a"}, {"at26df161a"},
+       {"at26df321"},  {"at45db081d"},
+       {"en25f32"},    {"en25p32"},    {"en25q32b"},   {"en25p64"},
+       {"en25q64"},    {"en25qh128"},  {"en25qh256"},
+       {"f25l32pa"},
+       {"mr25h256"},   {"mr25h10"},
+       {"gd25q32"},    {"gd25q64"},
+       {"160s33b"},    {"320s33b"},    {"640s33b"},
+       {"mx25l2005a"}, {"mx25l4005a"}, {"mx25l8005"},  {"mx25l1606e"},
+       {"mx25l3205d"}, {"mx25l3255e"}, {"mx25l6405d"}, {"mx25l12805d"},
+       {"mx25l12855e"},{"mx25l25635e"},{"mx25l25655e"},{"mx66l51235l"},
+       {"mx66l1g55g"},
+       {"n25q064"},    {"n25q128a11"}, {"n25q128a13"}, {"n25q256a"},
+       {"n25q512a"},   {"n25q512ax3"}, {"n25q00"},
+       {"pm25lv512"},  {"pm25lv010"},  {"pm25lq032"},
+       {"s25sl032p"},  {"s25sl064p"},  {"s25fl256s0"}, {"s25fl256s1"},
+       {"s25fl512s"},  {"s70fl01gs"},  {"s25sl12800"}, {"s25sl12801"},
+       {"s25fl129p0"}, {"s25fl129p1"}, {"s25sl004a"},  {"s25sl008a"},
+       {"s25sl016a"},  {"s25sl032a"},  {"s25sl064a"},  {"s25fl008k"},
+       {"s25fl016k"},  {"s25fl064k"},
+       {"sst25vf040b"},{"sst25vf080b"},{"sst25vf016b"},{"sst25vf032b"},
+       {"sst25vf064c"},{"sst25wf512"}, {"sst25wf010"}, {"sst25wf020"},
+       {"sst25wf040"},
+       {"m25p05"},     {"m25p10"},     {"m25p20"},     {"m25p40"},
+       {"m25p80"},     {"m25p16"},     {"m25p32"},     {"m25p64"},
+       {"m25p128"},    {"n25q032"},
+       {"m25p05-nonjedec"},    {"m25p10-nonjedec"},    {"m25p20-nonjedec"},
+       {"m25p40-nonjedec"},    {"m25p80-nonjedec"},    {"m25p16-nonjedec"},
+       {"m25p32-nonjedec"},    {"m25p64-nonjedec"},    {"m25p128-nonjedec"},
+       {"m45pe10"},    {"m45pe80"},    {"m45pe16"},
+       {"m25pe20"},    {"m25pe80"},    {"m25pe16"},
+       {"m25px16"},    {"m25px32"},    {"m25px32-s0"}, {"m25px32-s1"},
+       {"m25px64"},
+       {"w25x10"},     {"w25x20"},     {"w25x40"},     {"w25x80"},
+       {"w25x16"},     {"w25x32"},     {"w25q32"},     {"w25q32dw"},
+       {"w25x64"},     {"w25q64"},     {"w25q128"},    {"w25q80"},
+       {"w25q80bl"},   {"w25q128"},    {"w25q256"},    {"cat25c11"},
+       {"cat25c03"},   {"cat25c09"},   {"cat25c17"},   {"cat25128"},
+       { },
+};
+MODULE_DEVICE_TABLE(spi, m25p_ids);
+
+
 static struct spi_driver m25p80_driver = {
        .driver = {
                .name   = "m25p80",
                .owner  = THIS_MODULE,
        },
-       .id_table       = spi_nor_ids,
+       .id_table       = m25p_ids,
        .probe  = m25p_probe,
        .remove = m25p_remove,
 
index b4f61c7fc161c6dc32e080e8328ca78f96fa1093..058531044ceb01112e38fa99004c9036c9d2c57a 100644 (file)
@@ -115,7 +115,7 @@ int elm_config(struct device *dev, enum bch_ecc bch_type,
 
        if (!info) {
                dev_err(dev, "Unable to configure elm - device not probed?\n");
-               return -ENODEV;
+               return -EPROBE_DEFER;
        }
        /* ELM cannot detect ECC errors for chunks > 1KB */
        if (ecc_step_size > ((ELM_ECC_SIZE + 1) / 2)) {
index 8d659a2888d5f0a7cb8d9a03446250aaad03e324..d5269a26c839384eefa052534013828f6feaab89 100644 (file)
@@ -881,7 +881,6 @@ static int fsl_qspi_probe(struct platform_device *pdev)
 
        /* iterate the subnodes. */
        for_each_available_child_of_node(dev->of_node, np) {
-               const struct spi_device_id *id;
                char modalias[40];
 
                /* skip the holes */
@@ -909,10 +908,6 @@ static int fsl_qspi_probe(struct platform_device *pdev)
                if (of_modalias_node(np, modalias, sizeof(modalias)) < 0)
                        goto map_failed;
 
-               id = spi_nor_match_id(modalias);
-               if (!id)
-                       goto map_failed;
-
                ret = of_property_read_u32(np, "spi-max-frequency",
                                &q->clk_rate);
                if (ret < 0)
@@ -921,7 +916,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
                /* set the chip address for READID */
                fsl_qspi_set_base_addr(q, nor);
 
-               ret = spi_nor_scan(nor, id, SPI_NOR_QUAD);
+               ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD);
                if (ret)
                        goto map_failed;
 
index ae16aa2f688526d6f0da3e6b0f8405e39e710081..c51ee52386a71d9166dd178d57663f8da4636bfd 100644 (file)
@@ -28,6 +28,8 @@
 
 #define JEDEC_MFR(_jedec_id)   ((_jedec_id) >> 16)
 
+static const struct spi_device_id *spi_nor_match_id(const char *name);
+
 /*
  * Read the status register, returning its value in the location
  * Return the status register value.
@@ -473,7 +475,7 @@ struct flash_info {
  * more nor chips.  This current list focusses on newer chips, which
  * have been converging on command sets which including JEDEC ID.
  */
-const struct spi_device_id spi_nor_ids[] = {
+static const struct spi_device_id spi_nor_ids[] = {
        /* Atmel -- some are (confusingly) marketed as "DataFlash" */
        { "at25fs010",  INFO(0x1f6601, 0, 32 * 1024,   4, SECT_4K) },
        { "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
@@ -637,7 +639,6 @@ const struct spi_device_id spi_nor_ids[] = {
        { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
        { },
 };
-EXPORT_SYMBOL_GPL(spi_nor_ids);
 
 static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor)
 {
@@ -911,9 +912,9 @@ static int spi_nor_check(struct spi_nor *nor)
        return 0;
 }
 
-int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
-                       enum read_mode mode)
+int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
 {
+       const struct spi_device_id      *id = NULL;
        struct flash_info               *info;
        struct device *dev = nor->dev;
        struct mtd_info *mtd = nor->mtd;
@@ -925,6 +926,10 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
        if (ret)
                return ret;
 
+       id = spi_nor_match_id(name);
+       if (!id)
+               return -ENOENT;
+
        info = (void *)id->driver_data;
 
        if (info->jedec_id) {
@@ -1113,7 +1118,7 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
 }
 EXPORT_SYMBOL_GPL(spi_nor_scan);
 
-const struct spi_device_id *spi_nor_match_id(char *name)
+static const struct spi_device_id *spi_nor_match_id(const char *name)
 {
        const struct spi_device_id *id = spi_nor_ids;
 
@@ -1124,7 +1129,6 @@ const struct spi_device_id *spi_nor_match_id(char *name)
        }
        return NULL;
 }
-EXPORT_SYMBOL_GPL(spi_nor_match_id);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
index 4706386b7d34c2d719e30eb602defd49ee92a72d..f9009be3f3077057222984bbf6d03fdac8fcbe7c 100644 (file)
@@ -135,6 +135,7 @@ config MACVLAN
 config MACVTAP
        tristate "MAC-VLAN based tap driver"
        depends on MACVLAN
+       depends on INET
        help
          This adds a specialized tap character device driver that is based
          on the MAC-VLAN network interface, called macvtap. A macvtap device
@@ -200,6 +201,7 @@ config RIONET_RX_SIZE
 
 config TUN
        tristate "Universal TUN/TAP device driver support"
+       depends on INET
        select CRC32
        ---help---
          TUN/TAP provides packet reception and transmission for user space
index c9ac06cfe6b7b3a8f62568b70a6ad6d7ca9b44d0..a5115fb7cf331b9c39ed19a0b53d1ff527739295 100644 (file)
@@ -2471,7 +2471,8 @@ static void bond_loadbalance_arp_mon(struct work_struct *work)
                        bond_slave_state_change(bond);
                        if (BOND_MODE(bond) == BOND_MODE_XOR)
                                bond_update_slave_arr(bond, NULL);
-               } else if (do_failover) {
+               }
+               if (do_failover) {
                        block_netpoll_tx();
                        bond_select_active_slave(bond);
                        unblock_netpoll_tx();
index c13d83e15ace440fc624ff6913d617fdabd2699f..45f09a66e6c96662febe3015fad41b4e5e6251bf 100644 (file)
@@ -225,7 +225,12 @@ static int bond_changelink(struct net_device *bond_dev,
 
                bond_option_arp_ip_targets_clear(bond);
                nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
-                       __be32 target = nla_get_be32(attr);
+                       __be32 target;
+
+                       if (nla_len(attr) < sizeof(target))
+                               return -EINVAL;
+
+                       target = nla_get_be32(attr);
 
                        bond_opt_initval(&newval, (__force u64)target);
                        err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
index 02492d241e4c9e8cb8d49ae319067c7c0aa1f9cf..2cfe5012e4e58c3c4c51b968fba5c9c029e0db44 100644 (file)
@@ -110,7 +110,7 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
        long rate;
        u64 v64;
 
-       /* Use CIA recommended sample points */
+       /* Use CiA recommended sample points */
        if (bt->sample_point) {
                sampl_pt = bt->sample_point;
        } else {
@@ -382,7 +382,7 @@ void can_free_echo_skb(struct net_device *dev, unsigned int idx)
        BUG_ON(idx >= priv->echo_skb_max);
 
        if (priv->echo_skb[idx]) {
-               kfree_skb(priv->echo_skb[idx]);
+               dev_kfree_skb_any(priv->echo_skb[idx]);
                priv->echo_skb[idx] = NULL;
        }
 }
index fca5482c09acd43237f85e69765d3e66b96a4b86..04f20dd39007a105e329cb0168732cd8e909fd5d 100644 (file)
@@ -1,4 +1,5 @@
 config CAN_M_CAN
+       depends on HAS_IOMEM
        tristate "Bosch M_CAN devices"
        ---help---
          Say Y here if you want to support for Bosch M_CAN controller.
index 10d571eaed856814928151da898bd2053d4d899c..d7bc462aafdc27a26774aa6cb6cadb0e0d8547a3 100644 (file)
@@ -105,14 +105,36 @@ enum m_can_mram_cfg {
        MRAM_CFG_NUM,
 };
 
+/* Fast Bit Timing & Prescaler Register (FBTP) */
+#define FBTR_FBRP_MASK         0x1f
+#define FBTR_FBRP_SHIFT                16
+#define FBTR_FTSEG1_SHIFT      8
+#define FBTR_FTSEG1_MASK       (0xf << FBTR_FTSEG1_SHIFT)
+#define FBTR_FTSEG2_SHIFT      4
+#define FBTR_FTSEG2_MASK       (0x7 << FBTR_FTSEG2_SHIFT)
+#define FBTR_FSJW_SHIFT                0
+#define FBTR_FSJW_MASK         0x3
+
 /* Test Register (TEST) */
 #define TEST_LBCK      BIT(4)
 
 /* CC Control Register(CCCR) */
-#define CCCR_TEST      BIT(7)
-#define CCCR_MON       BIT(5)
-#define CCCR_CCE       BIT(1)
-#define CCCR_INIT      BIT(0)
+#define CCCR_TEST              BIT(7)
+#define CCCR_CMR_MASK          0x3
+#define CCCR_CMR_SHIFT         10
+#define CCCR_CMR_CANFD         0x1
+#define CCCR_CMR_CANFD_BRS     0x2
+#define CCCR_CMR_CAN           0x3
+#define CCCR_CME_MASK          0x3
+#define CCCR_CME_SHIFT         8
+#define CCCR_CME_CAN           0
+#define CCCR_CME_CANFD         0x1
+#define CCCR_CME_CANFD_BRS     0x2
+#define CCCR_TEST              BIT(7)
+#define CCCR_MON               BIT(5)
+#define CCCR_CCE               BIT(1)
+#define CCCR_INIT              BIT(0)
+#define CCCR_CANFD             0x10
 
 /* Bit Timing & Prescaler Register (BTP) */
 #define BTR_BRP_MASK           0x3ff
@@ -204,6 +226,7 @@ enum m_can_mram_cfg {
 
 /* Rx Buffer / FIFO Element Size Configuration (RXESC) */
 #define M_CAN_RXESC_8BYTES     0x0
+#define M_CAN_RXESC_64BYTES    0x777
 
 /* Tx Buffer Configuration(TXBC) */
 #define TXBC_NDTB_OFF          16
@@ -211,6 +234,7 @@ enum m_can_mram_cfg {
 
 /* Tx Buffer Element Size Configuration(TXESC) */
 #define TXESC_TBDS_8BYTES      0x0
+#define TXESC_TBDS_64BYTES     0x7
 
 /* Tx Event FIFO Con.guration (TXEFC) */
 #define TXEFC_EFS_OFF          16
@@ -219,11 +243,11 @@ enum m_can_mram_cfg {
 /* Message RAM Configuration (in bytes) */
 #define SIDF_ELEMENT_SIZE      4
 #define XIDF_ELEMENT_SIZE      8
-#define RXF0_ELEMENT_SIZE      16
-#define RXF1_ELEMENT_SIZE      16
+#define RXF0_ELEMENT_SIZE      72
+#define RXF1_ELEMENT_SIZE      72
 #define RXB_ELEMENT_SIZE       16
 #define TXE_ELEMENT_SIZE       8
-#define TXB_ELEMENT_SIZE       16
+#define TXB_ELEMENT_SIZE       72
 
 /* Message RAM Elements */
 #define M_CAN_FIFO_ID          0x0
@@ -231,11 +255,17 @@ enum m_can_mram_cfg {
 #define M_CAN_FIFO_DATA(n)     (0x8 + ((n) << 2))
 
 /* Rx Buffer Element */
+/* R0 */
 #define RX_BUF_ESI             BIT(31)
 #define RX_BUF_XTD             BIT(30)
 #define RX_BUF_RTR             BIT(29)
+/* R1 */
+#define RX_BUF_ANMF            BIT(31)
+#define RX_BUF_EDL             BIT(21)
+#define RX_BUF_BRS             BIT(20)
 
 /* Tx Buffer Element */
+/* R0 */
 #define TX_BUF_XTD             BIT(30)
 #define TX_BUF_RTR             BIT(29)
 
@@ -296,6 +326,7 @@ static inline void m_can_config_endisable(const struct m_can_priv *priv,
        if (enable) {
                /* enable m_can configuration */
                m_can_write(priv, M_CAN_CCCR, cccr | CCCR_INIT);
+               udelay(5);
                /* CCCR.CCE can only be set/reset while CCCR.INIT = '1' */
                m_can_write(priv, M_CAN_CCCR, cccr | CCCR_INIT | CCCR_CCE);
        } else {
@@ -326,41 +357,67 @@ static inline void m_can_disable_all_interrupts(const struct m_can_priv *priv)
        m_can_write(priv, M_CAN_ILE, 0x0);
 }
 
-static void m_can_read_fifo(const struct net_device *dev, struct can_frame *cf,
-                           u32 rxfs)
+static void m_can_read_fifo(struct net_device *dev, u32 rxfs)
 {
+       struct net_device_stats *stats = &dev->stats;
        struct m_can_priv *priv = netdev_priv(dev);
-       u32 id, fgi;
+       struct canfd_frame *cf;
+       struct sk_buff *skb;
+       u32 id, fgi, dlc;
+       int i;
 
        /* calculate the fifo get index for where to read data */
        fgi = (rxfs & RXFS_FGI_MASK) >> RXFS_FGI_OFF;
+       dlc = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC);
+       if (dlc & RX_BUF_EDL)
+               skb = alloc_canfd_skb(dev, &cf);
+       else
+               skb = alloc_can_skb(dev, (struct can_frame **)&cf);
+       if (!skb) {
+               stats->rx_dropped++;
+               return;
+       }
+
+       if (dlc & RX_BUF_EDL)
+               cf->len = can_dlc2len((dlc >> 16) & 0x0F);
+       else
+               cf->len = get_can_dlc((dlc >> 16) & 0x0F);
+
        id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_ID);
        if (id & RX_BUF_XTD)
                cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
        else
                cf->can_id = (id >> 18) & CAN_SFF_MASK;
 
-       if (id & RX_BUF_RTR) {
+       if (id & RX_BUF_ESI) {
+               cf->flags |= CANFD_ESI;
+               netdev_dbg(dev, "ESI Error\n");
+       }
+
+       if (!(dlc & RX_BUF_EDL) && (id & RX_BUF_RTR)) {
                cf->can_id |= CAN_RTR_FLAG;
        } else {
-               id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC);
-               cf->can_dlc = get_can_dlc((id >> 16) & 0x0F);
-               *(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi,
-                                                        M_CAN_FIFO_DATA(0));
-               *(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi,
-                                                        M_CAN_FIFO_DATA(1));
+               if (dlc & RX_BUF_BRS)
+                       cf->flags |= CANFD_BRS;
+
+               for (i = 0; i < cf->len; i += 4)
+                       *(u32 *)(cf->data + i) =
+                               m_can_fifo_read(priv, fgi,
+                                               M_CAN_FIFO_DATA(i / 4));
        }
 
        /* acknowledge rx fifo 0 */
        m_can_write(priv, M_CAN_RXF0A, fgi);
+
+       stats->rx_packets++;
+       stats->rx_bytes += cf->len;
+
+       netif_receive_skb(skb);
 }
 
 static int m_can_do_rx_poll(struct net_device *dev, int quota)
 {
        struct m_can_priv *priv = netdev_priv(dev);
-       struct net_device_stats *stats = &dev->stats;
-       struct sk_buff *skb;
-       struct can_frame *frame;
        u32 pkts = 0;
        u32 rxfs;
 
@@ -374,18 +431,7 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota)
                if (rxfs & RXFS_RFL)
                        netdev_warn(dev, "Rx FIFO 0 Message Lost\n");
 
-               skb = alloc_can_skb(dev, &frame);
-               if (!skb) {
-                       stats->rx_dropped++;
-                       return pkts;
-               }
-
-               m_can_read_fifo(dev, frame, rxfs);
-
-               stats->rx_packets++;
-               stats->rx_bytes += frame->can_dlc;
-
-               netif_receive_skb(skb);
+               m_can_read_fifo(dev, rxfs);
 
                quota--;
                pkts++;
@@ -481,11 +527,23 @@ static int m_can_handle_lec_err(struct net_device *dev,
        return 1;
 }
 
+static int __m_can_get_berr_counter(const struct net_device *dev,
+                                   struct can_berr_counter *bec)
+{
+       struct m_can_priv *priv = netdev_priv(dev);
+       unsigned int ecr;
+
+       ecr = m_can_read(priv, M_CAN_ECR);
+       bec->rxerr = (ecr & ECR_REC_MASK) >> ECR_REC_SHIFT;
+       bec->txerr = ecr & ECR_TEC_MASK;
+
+       return 0;
+}
+
 static int m_can_get_berr_counter(const struct net_device *dev,
                                  struct can_berr_counter *bec)
 {
        struct m_can_priv *priv = netdev_priv(dev);
-       unsigned int ecr;
        int err;
 
        err = clk_prepare_enable(priv->hclk);
@@ -498,9 +556,7 @@ static int m_can_get_berr_counter(const struct net_device *dev,
                return err;
        }
 
-       ecr = m_can_read(priv, M_CAN_ECR);
-       bec->rxerr = (ecr & ECR_REC_MASK) >> ECR_REC_SHIFT;
-       bec->txerr = ecr & ECR_TEC_MASK;
+       __m_can_get_berr_counter(dev, bec);
 
        clk_disable_unprepare(priv->cclk);
        clk_disable_unprepare(priv->hclk);
@@ -544,7 +600,7 @@ static int m_can_handle_state_change(struct net_device *dev,
        if (unlikely(!skb))
                return 0;
 
-       m_can_get_berr_counter(dev, &bec);
+       __m_can_get_berr_counter(dev, &bec);
 
        switch (new_state) {
        case CAN_STATE_ERROR_ACTIVE:
@@ -596,14 +652,14 @@ static int m_can_handle_state_errors(struct net_device *dev, u32 psr)
 
        if ((psr & PSR_EP) &&
            (priv->can.state != CAN_STATE_ERROR_PASSIVE)) {
-               netdev_dbg(dev, "entered error warning state\n");
+               netdev_dbg(dev, "entered error passive state\n");
                work_done += m_can_handle_state_change(dev,
                                                       CAN_STATE_ERROR_PASSIVE);
        }
 
        if ((psr & PSR_BO) &&
            (priv->can.state != CAN_STATE_BUS_OFF)) {
-               netdev_dbg(dev, "entered error warning state\n");
+               netdev_dbg(dev, "entered error bus off state\n");
                work_done += m_can_handle_state_change(dev,
                                                       CAN_STATE_BUS_OFF);
        }
@@ -615,7 +671,7 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus)
 {
        if (irqstatus & IR_WDI)
                netdev_err(dev, "Message RAM Watchdog event due to missing READY\n");
-       if (irqstatus & IR_BEU)
+       if (irqstatus & IR_ELO)
                netdev_err(dev, "Error Logging Overflow\n");
        if (irqstatus & IR_BEU)
                netdev_err(dev, "Bit Error Uncorrected\n");
@@ -733,10 +789,23 @@ static const struct can_bittiming_const m_can_bittiming_const = {
        .brp_inc = 1,
 };
 
+static const struct can_bittiming_const m_can_data_bittiming_const = {
+       .name = KBUILD_MODNAME,
+       .tseg1_min = 2,         /* Time segment 1 = prop_seg + phase_seg1 */
+       .tseg1_max = 16,
+       .tseg2_min = 1,         /* Time segment 2 = phase_seg2 */
+       .tseg2_max = 8,
+       .sjw_max = 4,
+       .brp_min = 1,
+       .brp_max = 32,
+       .brp_inc = 1,
+};
+
 static int m_can_set_bittiming(struct net_device *dev)
 {
        struct m_can_priv *priv = netdev_priv(dev);
        const struct can_bittiming *bt = &priv->can.bittiming;
+       const struct can_bittiming *dbt = &priv->can.data_bittiming;
        u16 brp, sjw, tseg1, tseg2;
        u32 reg_btp;
 
@@ -747,7 +816,17 @@ static int m_can_set_bittiming(struct net_device *dev)
        reg_btp = (brp << BTR_BRP_SHIFT) | (sjw << BTR_SJW_SHIFT) |
                        (tseg1 << BTR_TSEG1_SHIFT) | (tseg2 << BTR_TSEG2_SHIFT);
        m_can_write(priv, M_CAN_BTP, reg_btp);
-       netdev_dbg(dev, "setting BTP 0x%x\n", reg_btp);
+
+       if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+               brp = dbt->brp - 1;
+               sjw = dbt->sjw - 1;
+               tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
+               tseg2 = dbt->phase_seg2 - 1;
+               reg_btp = (brp << FBTR_FBRP_SHIFT) | (sjw << FBTR_FSJW_SHIFT) |
+                               (tseg1 << FBTR_FTSEG1_SHIFT) |
+                               (tseg2 << FBTR_FTSEG2_SHIFT);
+               m_can_write(priv, M_CAN_FBTP, reg_btp);
+       }
 
        return 0;
 }
@@ -767,8 +846,8 @@ static void m_can_chip_config(struct net_device *dev)
 
        m_can_config_endisable(priv, true);
 
-       /* RX Buffer/FIFO Element Size 8 bytes data field */
-       m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_8BYTES);
+       /* RX Buffer/FIFO Element Size 64 bytes data field */
+       m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_64BYTES);
 
        /* Accept Non-matching Frames Into FIFO 0 */
        m_can_write(priv, M_CAN_GFC, 0x0);
@@ -777,8 +856,8 @@ static void m_can_chip_config(struct net_device *dev)
        m_can_write(priv, M_CAN_TXBC, (1 << TXBC_NDTB_OFF) |
                    priv->mcfg[MRAM_TXB].off);
 
-       /* only support 8 bytes firstly */
-       m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_8BYTES);
+       /* support 64 bytes payload */
+       m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_64BYTES);
 
        m_can_write(priv, M_CAN_TXEFC, (1 << TXEFC_EFS_OFF) |
                    priv->mcfg[MRAM_TXE].off);
@@ -793,7 +872,8 @@ static void m_can_chip_config(struct net_device *dev)
                    RXFC_FWM_1 | priv->mcfg[MRAM_RXF1].off);
 
        cccr = m_can_read(priv, M_CAN_CCCR);
-       cccr &= ~(CCCR_TEST | CCCR_MON);
+       cccr &= ~(CCCR_TEST | CCCR_MON | (CCCR_CMR_MASK << CCCR_CMR_SHIFT) |
+               (CCCR_CME_MASK << CCCR_CME_SHIFT));
        test = m_can_read(priv, M_CAN_TEST);
        test &= ~TEST_LBCK;
 
@@ -805,6 +885,9 @@ static void m_can_chip_config(struct net_device *dev)
                test |= TEST_LBCK;
        }
 
+       if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+               cccr |= CCCR_CME_CANFD_BRS << CCCR_CME_SHIFT;
+
        m_can_write(priv, M_CAN_CCCR, cccr);
        m_can_write(priv, M_CAN_TEST, test);
 
@@ -869,11 +952,13 @@ static struct net_device *alloc_m_can_dev(void)
 
        priv->dev = dev;
        priv->can.bittiming_const = &m_can_bittiming_const;
+       priv->can.data_bittiming_const = &m_can_data_bittiming_const;
        priv->can.do_set_mode = m_can_set_mode;
        priv->can.do_get_berr_counter = m_can_get_berr_counter;
        priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
                                        CAN_CTRLMODE_LISTENONLY |
-                                       CAN_CTRLMODE_BERR_REPORTING;
+                                       CAN_CTRLMODE_BERR_REPORTING |
+                                       CAN_CTRLMODE_FD;
 
        return dev;
 }
@@ -956,8 +1041,9 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
                                    struct net_device *dev)
 {
        struct m_can_priv *priv = netdev_priv(dev);
-       struct can_frame *cf = (struct can_frame *)skb->data;
-       u32 id;
+       struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+       u32 id, cccr;
+       int i;
 
        if (can_dropped_invalid_skb(dev, skb))
                return NETDEV_TX_OK;
@@ -976,11 +1062,28 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
 
        /* message ram configuration */
        m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id);
-       m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, cf->can_dlc << 16);
-       m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0));
-       m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4));
+       m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, can_len2dlc(cf->len) << 16);
+
+       for (i = 0; i < cf->len; i += 4)
+               m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(i / 4),
+                                *(u32 *)(cf->data + i));
+
        can_put_echo_skb(skb, dev, 0);
 
+       if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+               cccr = m_can_read(priv, M_CAN_CCCR);
+               cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT);
+               if (can_is_canfd_skb(skb)) {
+                       if (cf->flags & CANFD_BRS)
+                               cccr |= CCCR_CMR_CANFD_BRS << CCCR_CMR_SHIFT;
+                       else
+                               cccr |= CCCR_CMR_CANFD << CCCR_CMR_SHIFT;
+               } else {
+                       cccr |= CCCR_CMR_CAN << CCCR_CMR_SHIFT;
+               }
+               m_can_write(priv, M_CAN_CCCR, cccr);
+       }
+
        /* enable first TX buffer to start transfer  */
        m_can_write(priv, M_CAN_TXBTIE, 0x1);
        m_can_write(priv, M_CAN_TXBAR, 0x1);
@@ -992,6 +1095,7 @@ static const struct net_device_ops m_can_netdev_ops = {
        .ndo_open = m_can_open,
        .ndo_stop = m_can_close,
        .ndo_start_xmit = m_can_start_xmit,
+       .ndo_change_mtu = can_change_mtu,
 };
 
 static int register_m_can_dev(struct net_device *dev)
@@ -1009,7 +1113,7 @@ static int m_can_of_parse_mram(struct platform_device *pdev,
        struct resource *res;
        void __iomem *addr;
        u32 out_val[MRAM_CFG_LEN];
-       int ret;
+       int i, start, end, ret;
 
        /* message ram could be shared */
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
@@ -1060,6 +1164,15 @@ static int m_can_of_parse_mram(struct platform_device *pdev,
                priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num,
                priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num);
 
+       /* initialize the entire Message RAM in use to avoid possible
+        * ECC/parity checksum errors when reading an uninitialized buffer
+        */
+       start = priv->mcfg[MRAM_SIDF].off;
+       end = priv->mcfg[MRAM_TXB].off +
+               priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE;
+       for (i = start; i < end; i += 4)
+               writel(0x0, priv->mram_base + i);
+
        return 0;
 }
 
index 1abe133d159428e0e098d611e8898bdaabb04c71..9718248e55f1e7c95c748b33538a4fb90a6f8d01 100644 (file)
@@ -628,6 +628,7 @@ static const struct net_device_ops rcar_can_netdev_ops = {
        .ndo_open = rcar_can_open,
        .ndo_stop = rcar_can_close,
        .ndo_start_xmit = rcar_can_start_xmit,
+       .ndo_change_mtu = can_change_mtu,
 };
 
 static void rcar_can_rx_pkt(struct rcar_can_priv *priv)
index 8ff3424d51472bc1df5753c025c6cd73f9ab1ed0..15c00faeec61001ab02c22689709efb523a96eb0 100644 (file)
@@ -214,7 +214,7 @@ static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
        struct net_device *dev;
        struct sja1000_priv *priv;
        struct kvaser_pci *board;
-       int err, init_step;
+       int err;
 
        dev = alloc_sja1000dev(sizeof(struct kvaser_pci));
        if (dev == NULL)
@@ -235,7 +235,6 @@ static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
        if (channel == 0) {
                board->xilinx_ver =
                        ioread8(board->res_addr + XILINX_VERINT) >> 4;
-               init_step = 2;
 
                /* Assert PTADR# - we're in passive mode so the other bits are
                   not important */
@@ -264,8 +263,6 @@ static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
        priv->irq_flags = IRQF_SHARED;
        dev->irq = pdev->irq;
 
-       init_step = 4;
-
        dev_info(&pdev->dev, "reg_base=%p conf_addr=%p irq=%d\n",
                 priv->reg_base, board->conf_addr, dev->irq);
 
index 00f2534dde736f1dd8cda9b016bd6a78f79eeab0..29d3f0938eb836b4da53a0898f574ebf42721ae2 100644 (file)
@@ -434,10 +434,9 @@ static void ems_usb_read_bulk_callback(struct urb *urb)
        if (urb->actual_length > CPC_HEADER_SIZE) {
                struct ems_cpc_msg *msg;
                u8 *ibuf = urb->transfer_buffer;
-               u8 msg_count, again, start;
+               u8 msg_count, start;
 
                msg_count = ibuf[0] & ~0x80;
-               again = ibuf[0] & 0x80;
 
                start = CPC_HEADER_SIZE;
 
index b7c9e8b11460a3d6bd0e4fe7836f0e07e73eb586..c063a54ab8dd8a598f36e5a7e712722bb5931df1 100644 (file)
@@ -464,7 +464,6 @@ static void esd_usb2_write_bulk_callback(struct urb *urb)
 {
        struct esd_tx_urb_context *context = urb->context;
        struct esd_usb2_net_priv *priv;
-       struct esd_usb2 *dev;
        struct net_device *netdev;
        size_t size = sizeof(struct esd_usb2_msg);
 
@@ -472,7 +471,6 @@ static void esd_usb2_write_bulk_callback(struct urb *urb)
 
        priv = context->priv;
        netdev = priv->netdev;
-       dev = priv->usb2;
 
        /* free up our allocated buffer */
        usb_free_coherent(urb->dev, size,
@@ -1143,6 +1141,7 @@ static void esd_usb2_disconnect(struct usb_interface *intf)
                        }
                }
                unlink_all_urbs(dev);
+               kfree(dev);
        }
 }
 
index 04b0f84612f0cf12fd1cfc59925a60c448423fa2..009acc8641fc557cb580cb688983daf041519e4b 100644 (file)
@@ -718,6 +718,7 @@ static const struct net_device_ops gs_usb_netdev_ops = {
        .ndo_open = gs_can_open,
        .ndo_stop = gs_can_close,
        .ndo_start_xmit = gs_can_start_xmit,
+       .ndo_change_mtu = can_change_mtu,
 };
 
 static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface *intf)
index 5e8b5609c067c53c2283a94dacd820fac8f1c565..8a998e3884ce0d502d9ebb19e7abde941ab85d3e 100644 (file)
@@ -300,7 +300,8 @@ static int xcan_set_bittiming(struct net_device *ndev)
 static int xcan_chip_start(struct net_device *ndev)
 {
        struct xcan_priv *priv = netdev_priv(ndev);
-       u32 err, reg_msr, reg_sr_mask;
+       u32 reg_msr, reg_sr_mask;
+       int err;
        unsigned long timeout;
 
        /* Check if it is in reset mode */
@@ -961,6 +962,7 @@ static const struct net_device_ops xcan_netdev_ops = {
        .ndo_open       = xcan_open,
        .ndo_stop       = xcan_close,
        .ndo_start_xmit = xcan_start_xmit,
+       .ndo_change_mtu = can_change_mtu,
 };
 
 /**
index b9625968daacc0eb89c0f7371a3a4e70242f95ce..4f4c2a7888e5d74ee06ae58df8feaf5f1dea3123 100644 (file)
@@ -377,6 +377,29 @@ static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
+{
+       unsigned int timeout = 1000;
+       u32 reg;
+
+       reg = core_readl(priv, CORE_WATCHDOG_CTRL);
+       reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
+       core_writel(priv, reg, CORE_WATCHDOG_CTRL);
+
+       do {
+               reg = core_readl(priv, CORE_WATCHDOG_CTRL);
+               if (!(reg & SOFTWARE_RESET))
+                       break;
+
+               usleep_range(1000, 2000);
+       } while (timeout-- > 0);
+
+       if (timeout == 0)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
 static int bcm_sf2_sw_setup(struct dsa_switch *ds)
 {
        const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
@@ -404,11 +427,18 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
                *base = of_iomap(dn, i);
                if (*base == NULL) {
                        pr_err("unable to find register: %s\n", reg_names[i]);
-                       return -ENODEV;
+                       ret = -ENOMEM;
+                       goto out_unmap;
                }
                base++;
        }
 
+       ret = bcm_sf2_sw_rst(priv);
+       if (ret) {
+               pr_err("unable to software reset switch: %d\n", ret);
+               goto out_unmap;
+       }
+
        /* Disable all interrupts and request them */
        intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
        intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
@@ -484,7 +514,8 @@ out_free_irq0:
 out_unmap:
        base = &priv->core;
        for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
-               iounmap(*base);
+               if (*base)
+                       iounmap(*base);
                base++;
        }
        return ret;
@@ -733,29 +764,6 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
        return 0;
 }
 
-static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
-{
-       unsigned int timeout = 1000;
-       u32 reg;
-
-       reg = core_readl(priv, CORE_WATCHDOG_CTRL);
-       reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
-       core_writel(priv, reg, CORE_WATCHDOG_CTRL);
-
-       do {
-               reg = core_readl(priv, CORE_WATCHDOG_CTRL);
-               if (!(reg & SOFTWARE_RESET))
-                       break;
-
-               usleep_range(1000, 2000);
-       } while (timeout-- > 0);
-
-       if (timeout == 0)
-               return -ETIMEDOUT;
-
-       return 0;
-}
-
 static int bcm_sf2_sw_resume(struct dsa_switch *ds)
 {
        struct bcm_sf2_priv *priv = ds_to_priv(ds);
index 1020a7af67cf6d8bbaf5016d2367454c63b393da..78d8e876f3aaada8ae88c429d007d4c8e3361633 100644 (file)
@@ -395,7 +395,7 @@ static int mv88e6171_get_sset_count(struct dsa_switch *ds)
 }
 
 struct dsa_switch_driver mv88e6171_switch_driver = {
-       .tag_protocol           = DSA_TAG_PROTO_DSA,
+       .tag_protocol           = DSA_TAG_PROTO_EDSA,
        .priv_size              = sizeof(struct mv88e6xxx_priv_state),
        .probe                  = mv88e6171_probe,
        .setup                  = mv88e6171_setup,
index 29554992215aa18301f26b7e431b1fc19dfff9cb..2349ea9702557b95de0860eb5921589104cd5c9d 100644 (file)
@@ -1465,7 +1465,7 @@ static int xgbe_set_features(struct net_device *netdev,
 {
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
-       unsigned int rxcsum, rxvlan, rxvlan_filter;
+       netdev_features_t rxcsum, rxvlan, rxvlan_filter;
 
        rxcsum = pdata->netdev_features & NETIF_F_RXCSUM;
        rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX;
@@ -1598,7 +1598,8 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
        struct skb_shared_hwtstamps *hwtstamps;
        unsigned int incomplete, error, context_next, context;
        unsigned int len, put_len, max_len;
-       int received = 0;
+       unsigned int received = 0;
+       int packet_count = 0;
 
        DBGPR("-->xgbe_rx_poll: budget=%d\n", budget);
 
@@ -1608,7 +1609,7 @@ static int xgbe_rx_poll(struct xgbe_channel *channel, int budget)
 
        rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
        packet = &ring->packet_data;
-       while (received < budget) {
+       while (packet_count < budget) {
                DBGPR("  cur = %d\n", ring->cur);
 
                /* First time in loop see if we need to restore state */
@@ -1662,7 +1663,7 @@ read_again:
                        if (packet->errors)
                                DBGPR("Error in received packet\n");
                        dev_kfree_skb(skb);
-                       continue;
+                       goto next_packet;
                }
 
                if (!context) {
@@ -1677,7 +1678,7 @@ read_again:
                                        }
 
                                        dev_kfree_skb(skb);
-                                       continue;
+                                       goto next_packet;
                                }
                                memcpy(skb_tail_pointer(skb), rdata->skb->data,
                                       put_len);
@@ -1694,7 +1695,7 @@ read_again:
 
                /* Stray Context Descriptor? */
                if (!skb)
-                       continue;
+                       goto next_packet;
 
                /* Be sure we don't exceed the configured MTU */
                max_len = netdev->mtu + ETH_HLEN;
@@ -1705,7 +1706,7 @@ read_again:
                if (skb->len > max_len) {
                        DBGPR("packet length exceeds configured MTU\n");
                        dev_kfree_skb(skb);
-                       continue;
+                       goto next_packet;
                }
 
 #ifdef XGMAC_ENABLE_RX_PKT_DUMP
@@ -1739,6 +1740,9 @@ read_again:
 
                netdev->last_rx = jiffies;
                napi_gro_receive(&pdata->napi, skb);
+
+next_packet:
+               packet_count++;
        }
 
        /* Check if we need to save state before leaving */
@@ -1752,9 +1756,9 @@ read_again:
                rdata->state.error = error;
        }
 
-       DBGPR("<--xgbe_rx_poll: received = %d\n", received);
+       DBGPR("<--xgbe_rx_poll: packet_count = %d\n", packet_count);
 
-       return received;
+       return packet_count;
 }
 
 static int xgbe_poll(struct napi_struct *napi, int budget)
index 63ea1941e973b6338aa7d4431ac2b9ef2d2e418b..7ba83ffb08ac73b6437f1fd4a87c3a560b9d4f84 100644 (file)
@@ -575,10 +575,24 @@ static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata)
        xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN);
 }
 
-static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
+bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
+{
+       if (!ioread32(p->ring_csr_addr + CLKEN_ADDR))
+               return false;
+
+       if (ioread32(p->ring_csr_addr + SRST_ADDR))
+               return false;
+
+       return true;
+}
+
+static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 {
        u32 val;
 
+       if (!xgene_ring_mgr_init(pdata))
+               return -ENODEV;
+
        clk_prepare_enable(pdata->clk);
        clk_disable_unprepare(pdata->clk);
        clk_prepare_enable(pdata->clk);
@@ -590,6 +604,8 @@ static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
        val |= SCAN_AUTO_INCR;
        MGMT_CLOCK_SEL_SET(&val, 1);
        xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val);
+
+       return 0;
 }
 
 static void xgene_gport_shutdown(struct xgene_enet_pdata *pdata)
index 38558584080ed8029a3640f171353fe09cb6503e..ec45f3256f0e3da2928c8be98ba9abcc0d58fb27 100644 (file)
@@ -104,6 +104,9 @@ enum xgene_enet_rm {
 #define BLOCK_ETH_MAC_OFFSET           0x0000
 #define BLOCK_ETH_MAC_CSR_OFFSET       0x2800
 
+#define CLKEN_ADDR                     0xc208
+#define SRST_ADDR                      0xc200
+
 #define MAC_ADDR_REG_OFFSET            0x00
 #define MAC_COMMAND_REG_OFFSET         0x04
 #define MAC_WRITE_REG_OFFSET           0x08
@@ -318,6 +321,7 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
 
 int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata);
 void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata);
+bool xgene_ring_mgr_init(struct xgene_enet_pdata *p);
 
 extern struct xgene_mac_ops xgene_gmac_ops;
 extern struct xgene_port_ops xgene_gport_ops;
index 3c208cc6f6bb470ae97d74f06fbaf0dcbaaf7ee6..123669696184fde824328fb61c9b2649f1c750c9 100644 (file)
@@ -639,9 +639,9 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
        struct device *dev = ndev_to_dev(ndev);
        struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
        struct xgene_enet_desc_ring *buf_pool = NULL;
-       u8 cpu_bufnum = 0, eth_bufnum = 0;
-       u8 bp_bufnum = 0x20;
-       u16 ring_id, ring_num = 0;
+       u8 cpu_bufnum = 0, eth_bufnum = START_ETH_BUFNUM;
+       u8 bp_bufnum = START_BP_BUFNUM;
+       u16 ring_id, ring_num = START_RING_NUM;
        int ret;
 
        /* allocate rx descriptor ring */
@@ -852,7 +852,9 @@ static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
        u16 dst_ring_num;
        int ret;
 
-       pdata->port_ops->reset(pdata);
+       ret = pdata->port_ops->reset(pdata);
+       if (ret)
+               return ret;
 
        ret = xgene_enet_create_desc_rings(ndev);
        if (ret) {
@@ -954,6 +956,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
 
        return ret;
 err:
+       unregister_netdev(ndev);
        free_netdev(ndev);
        return ret;
 }
index 874e5a01161fb9e9e1a05eb90afee3b148c07182..f9958fae6ffdc9fcba7cbb8f8438d95024b40ac9 100644 (file)
@@ -38,6 +38,9 @@
 #define SKB_BUFFER_SIZE                (XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
 #define NUM_PKT_BUF    64
 #define NUM_BUFPOOL    32
+#define START_ETH_BUFNUM       2
+#define START_BP_BUFNUM                0x22
+#define START_RING_NUM         8
 
 #define PHY_POLL_LINK_ON       (10 * HZ)
 #define PHY_POLL_LINK_OFF      (PHY_POLL_LINK_ON / 5)
@@ -83,7 +86,7 @@ struct xgene_mac_ops {
 };
 
 struct xgene_port_ops {
-       void (*reset)(struct xgene_enet_pdata *pdata);
+       int (*reset)(struct xgene_enet_pdata *pdata);
        void (*cle_bypass)(struct xgene_enet_pdata *pdata,
                           u32 dst_ring_num, u16 bufpool_id);
        void (*shutdown)(struct xgene_enet_pdata *pdata);
index e6d24c2101982444bde4d500d7559633e8685a2e..f5d4f68c288c395076205ba128788797d7114cdf 100644 (file)
@@ -124,20 +124,18 @@ static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
 {
        struct net_device *ndev = p->ndev;
        u32 data;
-       int i;
+       int i = 0;
 
        xgene_enet_wr_diag_csr(p, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0);
-       for (i = 0; i < 10 && data != ~0U ; i++) {
+       do {
                usleep_range(100, 110);
                data = xgene_enet_rd_diag_csr(p, ENET_BLOCK_MEM_RDY_ADDR);
-       }
-
-       if (data != ~0U) {
-               netdev_err(ndev, "Failed to release memory from shutdown\n");
-               return -ENODEV;
-       }
+               if (data == ~0U)
+                       return 0;
+       } while (++i < 10);
 
-       return 0;
+       netdev_err(ndev, "Failed to release memory from shutdown\n");
+       return -ENODEV;
 }
 
 static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *p)
@@ -313,14 +311,19 @@ static void xgene_sgmac_tx_disable(struct xgene_enet_pdata *p)
        xgene_sgmac_rxtx(p, TX_EN, false);
 }
 
-static void xgene_enet_reset(struct xgene_enet_pdata *p)
+static int xgene_enet_reset(struct xgene_enet_pdata *p)
 {
+       if (!xgene_ring_mgr_init(p))
+               return -ENODEV;
+
        clk_prepare_enable(p->clk);
        clk_disable_unprepare(p->clk);
        clk_prepare_enable(p->clk);
 
        xgene_enet_ecc_init(p);
        xgene_enet_config_ring_if_assoc(p);
+
+       return 0;
 }
 
 static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
index 67d07206b3c7723e2287a41fb964860cc4b78d04..a18a9d1f11432d4469d2d711ec633f22565017eb 100644 (file)
@@ -252,14 +252,19 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata)
        xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN);
 }
 
-static void xgene_enet_reset(struct xgene_enet_pdata *pdata)
+static int xgene_enet_reset(struct xgene_enet_pdata *pdata)
 {
+       if (!xgene_ring_mgr_init(pdata))
+               return -ENODEV;
+
        clk_prepare_enable(pdata->clk);
        clk_disable_unprepare(pdata->clk);
        clk_prepare_enable(pdata->clk);
 
        xgene_enet_ecc_init(pdata);
        xgene_enet_config_ring_if_assoc(pdata);
+
+       return 0;
 }
 
 static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
index 9ae36979bdee010aa2e8a276dc17611593e3383c..531bb7c57531b17fc64b0719690accba8afb6b1e 100644 (file)
@@ -1110,7 +1110,8 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
        /* We just need one DMA descriptor which is DMA-able, since writing to
         * the port will allocate a new descriptor in its internal linked-list
         */
-       p = dma_zalloc_coherent(kdev, 1, &ring->desc_dma, GFP_KERNEL);
+       p = dma_zalloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma,
+                               GFP_KERNEL);
        if (!p) {
                netif_err(priv, hw, priv->netdev, "DMA alloc failed\n");
                return -ENOMEM;
@@ -1174,6 +1175,13 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
        if (!(reg & TDMA_DISABLED))
                netdev_warn(priv->netdev, "TDMA not stopped!\n");
 
+       /* ring->cbs is the last part in bcm_sysport_init_tx_ring which could
+        * fail, so by checking this pointer we know whether the TX ring was
+        * fully initialized or not.
+        */
+       if (!ring->cbs)
+               return;
+
        napi_disable(&ring->napi);
        netif_napi_del(&ring->napi);
 
@@ -1183,7 +1191,8 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
        ring->cbs = NULL;
 
        if (ring->desc_dma) {
-               dma_free_coherent(kdev, 1, ring->desc_cpu, ring->desc_dma);
+               dma_free_coherent(kdev, sizeof(struct dma_desc),
+                                 ring->desc_cpu, ring->desc_dma);
                ring->desc_dma = 0;
        }
        ring->size = 0;
@@ -1397,6 +1406,9 @@ static void bcm_sysport_netif_start(struct net_device *dev)
        /* Enable NAPI */
        napi_enable(&priv->napi);
 
+       /* Enable RX interrupt and TX ring full interrupt */
+       intrl2_0_mask_clear(priv, INTRL2_0_RDMA_MBDONE | INTRL2_0_TX_RING_FULL);
+
        phy_start(priv->phydev);
 
        /* Enable TX interrupts for the 32 TXQs */
@@ -1499,9 +1511,6 @@ static int bcm_sysport_open(struct net_device *dev)
        if (ret)
                goto out_free_rx_ring;
 
-       /* Enable RX interrupt and TX ring full interrupt */
-       intrl2_0_mask_clear(priv, INTRL2_0_RDMA_MBDONE | INTRL2_0_TX_RING_FULL);
-
        /* Turn on TDMA */
        ret = tdma_enable_set(priv, 1);
        if (ret)
@@ -1858,6 +1867,8 @@ static int bcm_sysport_resume(struct device *d)
        if (!netif_running(dev))
                return 0;
 
+       umac_reset(priv);
+
        /* We may have been suspended and never received a WOL event that
         * would turn off MPD detection, take care of that now
         */
@@ -1885,9 +1896,6 @@ static int bcm_sysport_resume(struct device *d)
 
        netif_device_attach(dev);
 
-       /* Enable RX interrupt and TX ring full interrupt */
-       intrl2_0_mask_clear(priv, INTRL2_0_RDMA_MBDONE | INTRL2_0_TX_RING_FULL);
-
        /* RX pipe enable */
        topctrl_writel(priv, 0, RX_FLUSH_CNTL);
 
index 23f23c97c2ad7b9fa52b8d589b1627a560635f92..f05fab65d78ac62b3b7905102d39893087b1450b 100644 (file)
@@ -382,10 +382,8 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
                if (l5_cid >= MAX_CM_SK_TBL_SZ)
                        break;
 
-               rcu_read_lock();
                if (!rcu_access_pointer(cp->ulp_ops[CNIC_ULP_L4])) {
                        rc = -ENODEV;
-                       rcu_read_unlock();
                        break;
                }
                csk = &cp->csk_tbl[l5_cid];
@@ -414,7 +412,6 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type,
                        }
                }
                csk_put(csk);
-               rcu_read_unlock();
                rc = 0;
        }
        }
@@ -615,7 +612,7 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
                cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
 
        mutex_lock(&cnic_lock);
-       if (rcu_dereference(cp->ulp_ops[ulp_type])) {
+       if (rcu_access_pointer(cp->ulp_ops[ulp_type])) {
                RCU_INIT_POINTER(cp->ulp_ops[ulp_type], NULL);
                cnic_put(dev);
        } else {
index fdc9ec09e453510636460780226e0349cc51b9a5..da1a2500c91ce43677e7cada4b66196c17af2513 100644 (file)
@@ -2140,6 +2140,12 @@ static int bcmgenet_open(struct net_device *dev)
                goto err_irq0;
        }
 
+       /* Re-configure the port multiplexer towards the PHY device */
+       bcmgenet_mii_config(priv->dev, false);
+
+       phy_connect_direct(dev, priv->phydev, bcmgenet_mii_setup,
+                          priv->phy_interface);
+
        bcmgenet_netif_start(dev);
 
        return 0;
@@ -2184,6 +2190,9 @@ static int bcmgenet_close(struct net_device *dev)
 
        bcmgenet_netif_stop(dev);
 
+       /* Really kill the PHY state machine and disconnect from it */
+       phy_disconnect(priv->phydev);
+
        /* Disable MAC receive */
        umac_enable_set(priv, CMD_RX_EN, false);
 
@@ -2685,7 +2694,7 @@ static int bcmgenet_resume(struct device *d)
 
        phy_init_hw(priv->phydev);
        /* Speed settings must be restored */
-       bcmgenet_mii_config(priv->dev);
+       bcmgenet_mii_config(priv->dev, false);
 
        /* disable ethernet MAC while updating its registers */
        umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, false);
index dbf524ea3b19561bc1098b3cd58620cf9d66ac43..31b2da5f9b821342315ddebd958a765e7560cd51 100644 (file)
@@ -617,9 +617,10 @@ GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
 
 /* MDIO routines */
 int bcmgenet_mii_init(struct net_device *dev);
-int bcmgenet_mii_config(struct net_device *dev);
+int bcmgenet_mii_config(struct net_device *dev, bool init);
 void bcmgenet_mii_exit(struct net_device *dev);
 void bcmgenet_mii_reset(struct net_device *dev);
+void bcmgenet_mii_setup(struct net_device *dev);
 
 /* Wake-on-LAN routines */
 void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
index 9ff799a9f8019dafe2d47be33aba738921e588a3..933cd7e7cd33708bf89292a7bb50035165d0e867 100644 (file)
@@ -77,7 +77,7 @@ static int bcmgenet_mii_write(struct mii_bus *bus, int phy_id,
 /* setup netdev link state when PHY link status change and
  * update UMAC and RGMII block when link up
  */
-static void bcmgenet_mii_setup(struct net_device *dev)
+void bcmgenet_mii_setup(struct net_device *dev)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
        struct phy_device *phydev = priv->phydev;
@@ -211,7 +211,7 @@ static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
        bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
 }
 
-int bcmgenet_mii_config(struct net_device *dev)
+int bcmgenet_mii_config(struct net_device *dev, bool init)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
        struct phy_device *phydev = priv->phydev;
@@ -298,7 +298,8 @@ int bcmgenet_mii_config(struct net_device *dev)
                return -EINVAL;
        }
 
-       dev_info(kdev, "configuring instance for %s\n", phy_name);
+       if (init)
+               dev_info(kdev, "configuring instance for %s\n", phy_name);
 
        return 0;
 }
@@ -350,7 +351,7 @@ static int bcmgenet_mii_probe(struct net_device *dev)
         * PHY speed which is needed for bcmgenet_mii_config() to configure
         * things appropriately.
         */
-       ret = bcmgenet_mii_config(dev);
+       ret = bcmgenet_mii_config(dev, true);
        if (ret) {
                phy_disconnect(priv->phydev);
                return ret;
index dbb41c1923e60cf1a152bf414ef3428c2d0f2167..77f8f836cbbe18a75d1ffa58fc61c077414eab5b 100644 (file)
@@ -8563,7 +8563,8 @@ static int tg3_init_rings(struct tg3 *tp)
                if (tnapi->rx_rcb)
                        memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
 
-               if (tg3_rx_prodring_alloc(tp, &tnapi->prodring)) {
+               if (tnapi->prodring.rx_std &&
+                   tg3_rx_prodring_alloc(tp, &tnapi->prodring)) {
                        tg3_free_rings(tp);
                        return -ENOMEM;
                }
index 9e089d24466e65fb6c8b01c08f2ece882e23aaaa..3564fe9d3f69bab9e5a8536fe551e0b345591121 100644 (file)
@@ -22,7 +22,7 @@ if NET_CADENCE
 
 config ARM_AT91_ETHER
        tristate "AT91RM9200 Ethernet support"
-       depends on HAS_DMA && (ARCH_AT91RM9200 || COMPILE_TEST)
+       depends on HAS_DMA && (ARCH_AT91 || COMPILE_TEST)
        select MACB
        ---help---
          If you wish to compile a kernel for the AT91RM9200 and enable
index 8edf0f5bd679bf24b366887ff973a5d454c3af73..4fe33606f372755efb2bcef46f28c68b7d763312 100644 (file)
@@ -60,6 +60,43 @@ void cxgb4_dcb_version_init(struct net_device *dev)
        dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
 }
 
+static void cxgb4_dcb_cleanup_apps(struct net_device *dev)
+{
+       struct port_info *pi = netdev2pinfo(dev);
+       struct adapter *adap = pi->adapter;
+       struct port_dcb_info *dcb = &pi->dcb;
+       struct dcb_app app;
+       int i, err;
+
+       /* zero priority implies remove */
+       app.priority = 0;
+
+       for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
+               /* Check if app list is exhausted */
+               if (!dcb->app_priority[i].protocolid)
+                       break;
+
+               app.protocol = dcb->app_priority[i].protocolid;
+
+               if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
+                       app.priority = dcb->app_priority[i].user_prio_map;
+                       app.selector = dcb->app_priority[i].sel_field + 1;
+                       err = dcb_ieee_delapp(dev, &app);
+               } else {
+                       app.selector = !!(dcb->app_priority[i].sel_field);
+                       err = dcb_setapp(dev, &app);
+               }
+
+               if (err) {
+                       dev_err(adap->pdev_dev,
+                               "Failed DCB Clear %s Application Priority: sel=%d, prot=%d, , err=%d\n",
+                               dcb_ver_array[dcb->dcb_version], app.selector,
+                               app.protocol, -err);
+                       break;
+               }
+       }
+}
+
 /* Finite State machine for Data Center Bridging.
  */
 void cxgb4_dcb_state_fsm(struct net_device *dev,
@@ -80,14 +117,17 @@ void cxgb4_dcb_state_fsm(struct net_device *dev,
                        /* we're going to use Host DCB */
                        dcb->state = CXGB4_DCB_STATE_HOST;
                        dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
-                       dcb->enabled = 1;
                        break;
                }
 
                case CXGB4_DCB_INPUT_FW_ENABLED: {
                        /* we're going to use Firmware DCB */
                        dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
-                       dcb->supported = CXGB4_DCBX_FW_SUPPORT;
+                       dcb->supported = DCB_CAP_DCBX_LLD_MANAGED;
+                       if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE)
+                               dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
+                       else
+                               dcb->supported |= DCB_CAP_DCBX_VER_CEE;
                        break;
                }
 
@@ -145,6 +185,7 @@ void cxgb4_dcb_state_fsm(struct net_device *dev,
                         * state.  We need to reset back to a ground state
                         * of incomplete.
                         */
+                       cxgb4_dcb_cleanup_apps(dev);
                        cxgb4_dcb_state_init(dev);
                        dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
                        dcb->supported = CXGB4_DCBX_FW_SUPPORT;
@@ -349,6 +390,12 @@ static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
 {
        struct port_info *pi = netdev2pinfo(dev);
 
+       /* If DCBx is host-managed, dcb is enabled by outside lldp agents */
+       if (pi->dcb.state == CXGB4_DCB_STATE_HOST) {
+               pi->dcb.enabled = enabled;
+               return 0;
+       }
+
        /* Firmware doesn't provide any mechanism to control the DCB state.
         */
        if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
@@ -394,14 +441,17 @@ static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
        *up_tc_map = (1 << tc);
 
        /* prio_type is link strict */
-       *prio_type = 0x2;
+       if (*pgid != 0xF)
+               *prio_type = 0x2;
 }
 
 static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
                                u8 *prio_type, u8 *pgid, u8 *bw_per,
                                u8 *up_tc_map)
 {
-       return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 1);
+       /* tc 0 is written at MSB position */
+       return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
+                               up_tc_map, 1);
 }
 
 
@@ -409,7 +459,9 @@ static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
                                u8 *prio_type, u8 *pgid, u8 *bw_per,
                                u8 *up_tc_map)
 {
-       return cxgb4_getpgtccfg(dev, tc, prio_type, pgid, bw_per, up_tc_map, 0);
+       /* tc 0 is written at MSB position */
+       return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
+                               up_tc_map, 0);
 }
 
 static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
@@ -419,6 +471,7 @@ static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
        struct fw_port_cmd pcmd;
        struct port_info *pi = netdev2pinfo(dev);
        struct adapter *adap = pi->adapter;
+       int fw_tc = 7 - tc;
        u32 _pgid;
        int err;
 
@@ -437,8 +490,8 @@ static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
        }
 
        _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
-       _pgid &= ~(0xF << (tc * 4));
-       _pgid |= pgid << (tc * 4);
+       _pgid &= ~(0xF << (fw_tc * 4));
+       _pgid |= pgid << (fw_tc * 4);
        pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
 
        INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
@@ -551,7 +604,7 @@ static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
            priority >= CXGB4_MAX_PRIORITY)
                *pfccfg = 0;
        else
-               *pfccfg = (pi->dcb.pfcen >> priority) & 1;
+               *pfccfg = (pi->dcb.pfcen >> (7 - priority)) & 1;
 }
 
 /* Enable/disable Priority Pause Frames for the specified Traffic Class
@@ -576,9 +629,9 @@ static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
        pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
 
        if (pfccfg)
-               pcmd.u.dcb.pfc.pfcen |= (1 << priority);
+               pcmd.u.dcb.pfc.pfcen |= (1 << (7 - priority));
        else
-               pcmd.u.dcb.pfc.pfcen &= (~(1 << priority));
+               pcmd.u.dcb.pfc.pfcen &= (~(1 << (7 - priority)));
 
        err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
        if (err != FW_PORT_DCB_CFG_SUCCESS) {
@@ -833,11 +886,16 @@ static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
 
 /* Return whether IEEE Data Center Bridging has been negotiated.
  */
-static inline int cxgb4_ieee_negotiation_complete(struct net_device *dev)
+static inline int
+cxgb4_ieee_negotiation_complete(struct net_device *dev,
+                               enum cxgb4_dcb_fw_msgs dcb_subtype)
 {
        struct port_info *pi = netdev2pinfo(dev);
        struct port_dcb_info *dcb = &pi->dcb;
 
+       if (dcb_subtype && !(dcb->msgs & dcb_subtype))
+               return 0;
+
        return (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED &&
                (dcb->supported & DCB_CAP_DCBX_VER_IEEE));
 }
@@ -850,7 +908,7 @@ static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
 {
        int prio;
 
-       if (!cxgb4_ieee_negotiation_complete(dev))
+       if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
                return -EINVAL;
        if (!(app->selector && app->protocol))
                return -EINVAL;
@@ -872,7 +930,7 @@ static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
 {
        int ret;
 
-       if (!cxgb4_ieee_negotiation_complete(dev))
+       if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
                return -EINVAL;
        if (!(app->selector && app->protocol))
                return -EINVAL;
@@ -1024,7 +1082,7 @@ static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
        pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
 
        for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
-               pg->prio_pg[i] = (pgid >> (i * 4)) & 0xF;
+               pg->prio_pg[7 - i] = (pgid >> (i * 4)) & 0xF;
 
        INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
        pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
index 3f60070f2519d2f1df97eb2d9dd39bfae0c0ae92..279873cb6e3ac33b196d4689daeefdb7c1bf87f5 100644 (file)
@@ -694,7 +694,11 @@ int cxgb4_dcb_enabled(const struct net_device *dev)
 #ifdef CONFIG_CHELSIO_T4_DCB
        struct port_info *pi = netdev_priv(dev);
 
-       return pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED;
+       if (!pi->dcb.enabled)
+               return 0;
+
+       return ((pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED) ||
+               (pi->dcb.state == CXGB4_DCB_STATE_HOST));
 #else
        return 0;
 #endif
@@ -2438,9 +2442,13 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps)
                     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full |
                     SUPPORTED_10000baseKX4_Full;
        else if (type == FW_PORT_TYPE_FIBER_XFI ||
-                type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
+                type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP) {
                v |= SUPPORTED_FIBRE;
-       else if (type == FW_PORT_TYPE_BP40_BA)
+               if (caps & FW_PORT_CAP_SPEED_1G)
+                       v |= SUPPORTED_1000baseT_Full;
+               if (caps & FW_PORT_CAP_SPEED_10G)
+                       v |= SUPPORTED_10000baseT_Full;
+       } else if (type == FW_PORT_TYPE_BP40_BA)
                v |= SUPPORTED_40000baseSR4_Full;
 
        if (caps & FW_PORT_CAP_ANEG)
@@ -6610,6 +6618,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        spin_lock_init(&adapter->stats_lock);
        spin_lock_init(&adapter->tid_release_lock);
+       spin_lock_init(&adapter->win0_lock);
 
        INIT_WORK(&adapter->tid_release_task, process_tid_release_list);
        INIT_WORK(&adapter->db_full_task, process_db_full);
index 5e1b314e11af674f8d0f7f1ebf3bed60835dda08..39f2b13e66c731add3b842ef8a8db1fcde906c4b 100644 (file)
@@ -2914,7 +2914,8 @@ static int t4_sge_init_hard(struct adapter *adap)
 int t4_sge_init(struct adapter *adap)
 {
        struct sge *s = &adap->sge;
-       u32 sge_control, sge_conm_ctrl;
+       u32 sge_control, sge_control2, sge_conm_ctrl;
+       unsigned int ingpadboundary, ingpackboundary;
        int ret, egress_threshold;
 
        /*
@@ -2924,8 +2925,31 @@ int t4_sge_init(struct adapter *adap)
        sge_control = t4_read_reg(adap, SGE_CONTROL);
        s->pktshift = PKTSHIFT_GET(sge_control);
        s->stat_len = (sge_control & EGRSTATUSPAGESIZE_MASK) ? 128 : 64;
-       s->fl_align = 1 << (INGPADBOUNDARY_GET(sge_control) +
-                           X_INGPADBOUNDARY_SHIFT);
+
+       /* T4 uses a single control field to specify both the PCIe Padding and
+        * Packing Boundary.  T5 introduced the ability to specify these
+        * separately.  The actual Ingress Packet Data alignment boundary
+        * within Packed Buffer Mode is the maximum of these two
+        * specifications.
+        */
+       ingpadboundary = 1 << (INGPADBOUNDARY_GET(sge_control) +
+                              X_INGPADBOUNDARY_SHIFT);
+       if (is_t4(adap->params.chip)) {
+               s->fl_align = ingpadboundary;
+       } else {
+               /* T5 has a different interpretation of one of the PCIe Packing
+                * Boundary values.
+                */
+               sge_control2 = t4_read_reg(adap, SGE_CONTROL2_A);
+               ingpackboundary = INGPACKBOUNDARY_G(sge_control2);
+               if (ingpackboundary == INGPACKBOUNDARY_16B_X)
+                       ingpackboundary = 16;
+               else
+                       ingpackboundary = 1 << (ingpackboundary +
+                                               INGPACKBOUNDARY_SHIFT_X);
+
+               s->fl_align = max(ingpadboundary, ingpackboundary);
+       }
 
        if (adap->flags & USING_SOFT_PARAMS)
                ret = t4_sge_init_soft(adap);
index a9d9d74e4f092f969c2d58eaf01455b7bca7e257..163a2a14948cf8e3f5d78cf63588ee3905baa315 100644 (file)
@@ -3129,12 +3129,51 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                     HOSTPAGESIZEPF6(sge_hps) |
                     HOSTPAGESIZEPF7(sge_hps));
 
-       t4_set_reg_field(adap, SGE_CONTROL,
-                        INGPADBOUNDARY_MASK |
-                        EGRSTATUSPAGESIZE_MASK,
-                        INGPADBOUNDARY(fl_align_log - 5) |
-                        EGRSTATUSPAGESIZE(stat_len != 64));
-
+       if (is_t4(adap->params.chip)) {
+               t4_set_reg_field(adap, SGE_CONTROL,
+                                INGPADBOUNDARY_MASK |
+                                EGRSTATUSPAGESIZE_MASK,
+                                INGPADBOUNDARY(fl_align_log - 5) |
+                                EGRSTATUSPAGESIZE(stat_len != 64));
+       } else {
+               /* T5 introduced the separation of the Free List Padding and
+                * Packing Boundaries.  Thus, we can select a smaller Padding
+                * Boundary to avoid uselessly chewing up PCIe Link and Memory
+                * Bandwidth, and use a Packing Boundary which is large enough
+                * to avoid false sharing between CPUs, etc.
+                *
+                * For the PCI Link, the smaller the Padding Boundary the
+                * better.  For the Memory Controller, a smaller Padding
+                * Boundary is better until we cross under the Memory Line
+                * Size (the minimum unit of transfer to/from Memory).  If we
+                * have a Padding Boundary which is smaller than the Memory
+                * Line Size, that'll involve a Read-Modify-Write cycle on the
+                * Memory Controller which is never good.  For T5 the smallest
+                * Padding Boundary which we can select is 32 bytes which is
+                * larger than any known Memory Controller Line Size so we'll
+                * use that.
+                *
+                * T5 has a different interpretation of the "0" value for the
+                * Packing Boundary.  This corresponds to 16 bytes instead of
+                * the expected 32 bytes.  We never have a Packing Boundary
+                * less than 32 bytes so we can't use that special value but
+                * on the other hand, if we wanted 32 bytes, the best we can
+                * really do is 64 bytes.
+               */
+               if (fl_align <= 32) {
+                       fl_align = 64;
+                       fl_align_log = 6;
+               }
+               t4_set_reg_field(adap, SGE_CONTROL,
+                                INGPADBOUNDARY_MASK |
+                                EGRSTATUSPAGESIZE_MASK,
+                                INGPADBOUNDARY(INGPCIEBOUNDARY_32B_X) |
+                                EGRSTATUSPAGESIZE(stat_len != 64));
+               t4_set_reg_field(adap, SGE_CONTROL2_A,
+                                INGPACKBOUNDARY_V(INGPACKBOUNDARY_M),
+                                INGPACKBOUNDARY_V(fl_align_log -
+                                                INGPACKBOUNDARY_SHIFT_X));
+       }
        /*
         * Adjust various SGE Free List Host Buffer Sizes.
         *
index a1024db5dc136bb2a64fe5d3d696580ae3e38434..8d2de1006b084574e78a9095a721cd359b115945 100644 (file)
@@ -95,6 +95,7 @@
 #define X_INGPADBOUNDARY_SHIFT 5
 
 #define SGE_CONTROL 0x1008
+#define SGE_CONTROL2_A         0x1124
 #define  DCASYSTYPE             0x00080000U
 #define  RXPKTCPLMODE_MASK      0x00040000U
 #define  RXPKTCPLMODE_SHIFT     18
 #define  PKTSHIFT_SHIFT         10
 #define  PKTSHIFT(x)            ((x) << PKTSHIFT_SHIFT)
 #define  PKTSHIFT_GET(x)       (((x) & PKTSHIFT_MASK) >> PKTSHIFT_SHIFT)
+#define  INGPCIEBOUNDARY_32B_X 0
 #define  INGPCIEBOUNDARY_MASK   0x00000380U
 #define  INGPCIEBOUNDARY_SHIFT  7
 #define  INGPCIEBOUNDARY(x)     ((x) << INGPCIEBOUNDARY_SHIFT)
 #define  INGPADBOUNDARY(x)      ((x) << INGPADBOUNDARY_SHIFT)
 #define  INGPADBOUNDARY_GET(x) (((x) & INGPADBOUNDARY_MASK) \
                                 >> INGPADBOUNDARY_SHIFT)
+#define  INGPACKBOUNDARY_16B_X 0
+#define  INGPACKBOUNDARY_SHIFT_X 5
+
+#define  INGPACKBOUNDARY_S     16
+#define  INGPACKBOUNDARY_M     0x7U
+#define  INGPACKBOUNDARY_V(x)  ((x) << INGPACKBOUNDARY_S)
+#define  INGPACKBOUNDARY_G(x)  (((x) >> INGPACKBOUNDARY_S) \
+                                & INGPACKBOUNDARY_M)
 #define  EGRPCIEBOUNDARY_MASK   0x0000000eU
 #define  EGRPCIEBOUNDARY_SHIFT  1
 #define  EGRPCIEBOUNDARY(x)     ((x) << EGRPCIEBOUNDARY_SHIFT)
index 68eaa9c88c7d8a77646bd217e00877a281254a59..3d06e77d7121510e70c846c5d9a6c0e7526aa736 100644 (file)
@@ -299,6 +299,14 @@ struct sge {
        u16 timer_val[SGE_NTIMERS];     /* interrupt holdoff timer array */
        u8 counter_val[SGE_NCOUNTERS];  /* interrupt RX threshold array */
 
+       /* Decoded Adapter Parameters.
+        */
+       u32 fl_pg_order;                /* large page allocation size */
+       u32 stat_len;                   /* length of status page at ring end */
+       u32 pktshift;                   /* padding between CPL & packet data */
+       u32 fl_align;                   /* response queue message alignment */
+       u32 fl_starve_thres;            /* Free List starvation threshold */
+
        /*
         * Reverse maps from Absolute Queue IDs to associated queue pointers.
         * The absolute Queue IDs are in a compact range which start at a
index bfa398d9182681c92203f5a7687010e5fdcad7d8..0b42bddaf28443dbdc9317feee3dc43fcab8ade9 100644 (file)
@@ -2929,14 +2929,14 @@ static const struct pci_device_id cxgb4vf_pci_tbl[] = {
        CH_DEVICE(0x480d),      /* T480-cr */
        CH_DEVICE(0x480e),      /* T440-lp-cr */
        CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
-       CH_DEVICE(0x4880),
+       CH_DEVICE(0x4881),
+       CH_DEVICE(0x4882),
+       CH_DEVICE(0x4883),
+       CH_DEVICE(0x4884),
+       CH_DEVICE(0x4885),
+       CH_DEVICE(0x4886),
+       CH_DEVICE(0x4887),
+       CH_DEVICE(0x4888),
        CH_DEVICE(0x5801),      /* T520-cr */
        CH_DEVICE(0x5802),      /* T522-cr */
        CH_DEVICE(0x5803),      /* T540-cr */
index 85036e6b42c4cd4f7663ef2487948448d2d04be8..fdd078d7d82c661ec5c63e8198c9ae6d464366c3 100644 (file)
 #include "../cxgb4/t4fw_api.h"
 #include "../cxgb4/t4_msg.h"
 
-/*
- * Decoded Adapter Parameters.
- */
-static u32 FL_PG_ORDER;                /* large page allocation size */
-static u32 STAT_LEN;           /* length of status page at ring end */
-static u32 PKTSHIFT;           /* padding between CPL and packet data */
-static u32 FL_ALIGN;           /* response queue message alignment */
-
 /*
  * Constants ...
  */
@@ -101,12 +93,6 @@ enum {
        TX_QCHECK_PERIOD = (HZ / 2),
        MAX_TIMER_TX_RECLAIM = 100,
 
-       /*
-        * An FL with <= FL_STARVE_THRES buffers is starving and a periodic
-        * timer will attempt to refill it.
-        */
-       FL_STARVE_THRES = 4,
-
        /*
         * Suspend an Ethernet TX queue with fewer available descriptors than
         * this.  We always want to have room for a maximum sized packet:
@@ -264,15 +250,19 @@ static inline unsigned int fl_cap(const struct sge_fl *fl)
 
 /**
  *     fl_starving - return whether a Free List is starving.
+ *     @adapter: pointer to the adapter
  *     @fl: the Free List
  *
  *     Tests specified Free List to see whether the number of buffers
  *     available to the hardware has falled below our "starvation"
  *     threshold.
  */
-static inline bool fl_starving(const struct sge_fl *fl)
+static inline bool fl_starving(const struct adapter *adapter,
+                              const struct sge_fl *fl)
 {
-       return fl->avail - fl->pend_cred <= FL_STARVE_THRES;
+       const struct sge *s = &adapter->sge;
+
+       return fl->avail - fl->pend_cred <= s->fl_starve_thres;
 }
 
 /**
@@ -457,13 +447,16 @@ static inline void reclaim_completed_tx(struct adapter *adapter,
 
 /**
  *     get_buf_size - return the size of an RX Free List buffer.
+ *     @adapter: pointer to the associated adapter
  *     @sdesc: pointer to the software buffer descriptor
  */
-static inline int get_buf_size(const struct rx_sw_desc *sdesc)
+static inline int get_buf_size(const struct adapter *adapter,
+                              const struct rx_sw_desc *sdesc)
 {
-       return FL_PG_ORDER > 0 && (sdesc->dma_addr & RX_LARGE_BUF)
-               ? (PAGE_SIZE << FL_PG_ORDER)
-               : PAGE_SIZE;
+       const struct sge *s = &adapter->sge;
+
+       return (s->fl_pg_order > 0 && (sdesc->dma_addr & RX_LARGE_BUF)
+               ? (PAGE_SIZE << s->fl_pg_order) : PAGE_SIZE);
 }
 
 /**
@@ -483,7 +476,8 @@ static void free_rx_bufs(struct adapter *adapter, struct sge_fl *fl, int n)
 
                if (is_buf_mapped(sdesc))
                        dma_unmap_page(adapter->pdev_dev, get_buf_addr(sdesc),
-                                      get_buf_size(sdesc), PCI_DMA_FROMDEVICE);
+                                      get_buf_size(adapter, sdesc),
+                                      PCI_DMA_FROMDEVICE);
                put_page(sdesc->page);
                sdesc->page = NULL;
                if (++fl->cidx == fl->size)
@@ -511,7 +505,8 @@ static void unmap_rx_buf(struct adapter *adapter, struct sge_fl *fl)
 
        if (is_buf_mapped(sdesc))
                dma_unmap_page(adapter->pdev_dev, get_buf_addr(sdesc),
-                              get_buf_size(sdesc), PCI_DMA_FROMDEVICE);
+                              get_buf_size(adapter, sdesc),
+                              PCI_DMA_FROMDEVICE);
        sdesc->page = NULL;
        if (++fl->cidx == fl->size)
                fl->cidx = 0;
@@ -589,6 +584,7 @@ static inline void poison_buf(struct page *page, size_t sz)
 static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl,
                              int n, gfp_t gfp)
 {
+       struct sge *s = &adapter->sge;
        struct page *page;
        dma_addr_t dma_addr;
        unsigned int cred = fl->avail;
@@ -608,12 +604,12 @@ static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl,
         * If we don't support large pages, drop directly into the small page
         * allocation code.
         */
-       if (FL_PG_ORDER == 0)
+       if (s->fl_pg_order == 0)
                goto alloc_small_pages;
 
        while (n) {
                page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN,
-                                  FL_PG_ORDER);
+                                  s->fl_pg_order);
                if (unlikely(!page)) {
                        /*
                         * We've failed inour attempt to allocate a "large
@@ -623,10 +619,10 @@ static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl,
                        fl->large_alloc_failed++;
                        break;
                }
-               poison_buf(page, PAGE_SIZE << FL_PG_ORDER);
+               poison_buf(page, PAGE_SIZE << s->fl_pg_order);
 
                dma_addr = dma_map_page(adapter->pdev_dev, page, 0,
-                                       PAGE_SIZE << FL_PG_ORDER,
+                                       PAGE_SIZE << s->fl_pg_order,
                                        PCI_DMA_FROMDEVICE);
                if (unlikely(dma_mapping_error(adapter->pdev_dev, dma_addr))) {
                        /*
@@ -637,7 +633,7 @@ static unsigned int refill_fl(struct adapter *adapter, struct sge_fl *fl,
                         * because DMA mapping resources are typically
                         * critical resources once they become scarse.
                         */
-                       __free_pages(page, FL_PG_ORDER);
+                       __free_pages(page, s->fl_pg_order);
                        goto out;
                }
                dma_addr |= RX_LARGE_BUF;
@@ -693,7 +689,7 @@ out:
        fl->pend_cred += cred;
        ring_fl_db(adapter, fl);
 
-       if (unlikely(fl_starving(fl))) {
+       if (unlikely(fl_starving(adapter, fl))) {
                smp_wmb();
                set_bit(fl->cntxt_id, adapter->sge.starving_fl);
        }
@@ -1468,6 +1464,8 @@ static void t4vf_pktgl_free(const struct pkt_gl *gl)
 static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
                   const struct cpl_rx_pkt *pkt)
 {
+       struct adapter *adapter = rxq->rspq.adapter;
+       struct sge *s = &adapter->sge;
        int ret;
        struct sk_buff *skb;
 
@@ -1478,8 +1476,8 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
                return;
        }
 
-       copy_frags(skb, gl, PKTSHIFT);
-       skb->len = gl->tot_len - PKTSHIFT;
+       copy_frags(skb, gl, s->pktshift);
+       skb->len = gl->tot_len - s->pktshift;
        skb->data_len = skb->len;
        skb->truesize += skb->data_len;
        skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1516,6 +1514,8 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
        bool csum_ok = pkt->csum_calc && !pkt->err_vec &&
                       (rspq->netdev->features & NETIF_F_RXCSUM);
        struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
+       struct adapter *adapter = rspq->adapter;
+       struct sge *s = &adapter->sge;
 
        /*
         * If this is a good TCP packet and we have Generic Receive Offload
@@ -1537,7 +1537,7 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
                rxq->stats.rx_drops++;
                return 0;
        }
-       __skb_pull(skb, PKTSHIFT);
+       __skb_pull(skb, s->pktshift);
        skb->protocol = eth_type_trans(skb, rspq->netdev);
        skb_record_rx_queue(skb, rspq->idx);
        rxq->stats.pkts++;
@@ -1648,6 +1648,8 @@ static inline void rspq_next(struct sge_rspq *rspq)
 static int process_responses(struct sge_rspq *rspq, int budget)
 {
        struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
+       struct adapter *adapter = rspq->adapter;
+       struct sge *s = &adapter->sge;
        int budget_left = budget;
 
        while (likely(budget_left)) {
@@ -1697,7 +1699,7 @@ static int process_responses(struct sge_rspq *rspq, int budget)
                                BUG_ON(frag >= MAX_SKB_FRAGS);
                                BUG_ON(rxq->fl.avail == 0);
                                sdesc = &rxq->fl.sdesc[rxq->fl.cidx];
-                               bufsz = get_buf_size(sdesc);
+                               bufsz = get_buf_size(adapter, sdesc);
                                fp->page = sdesc->page;
                                fp->offset = rspq->offset;
                                fp->size = min(bufsz, len);
@@ -1726,7 +1728,7 @@ static int process_responses(struct sge_rspq *rspq, int budget)
                         */
                        ret = rspq->handler(rspq, rspq->cur_desc, &gl);
                        if (likely(ret == 0))
-                               rspq->offset += ALIGN(fp->size, FL_ALIGN);
+                               rspq->offset += ALIGN(fp->size, s->fl_align);
                        else
                                restore_rx_bufs(&gl, &rxq->fl, frag);
                } else if (likely(rsp_type == RSP_TYPE_CPL)) {
@@ -1963,7 +1965,7 @@ static void sge_rx_timer_cb(unsigned long data)
                         * schedule napi but the FL is no longer starving.
                         * No biggie.
                         */
-                       if (fl_starving(fl)) {
+                       if (fl_starving(adapter, fl)) {
                                struct sge_eth_rxq *rxq;
 
                                rxq = container_of(fl, struct sge_eth_rxq, fl);
@@ -2047,6 +2049,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
                       int intr_dest,
                       struct sge_fl *fl, rspq_handler_t hnd)
 {
+       struct sge *s = &adapter->sge;
        struct port_info *pi = netdev_priv(dev);
        struct fw_iq_cmd cmd, rpl;
        int ret, iqandst, flsz = 0;
@@ -2117,7 +2120,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
                fl->size = roundup(fl->size, FL_PER_EQ_UNIT);
                fl->desc = alloc_ring(adapter->pdev_dev, fl->size,
                                      sizeof(__be64), sizeof(struct rx_sw_desc),
-                                     &fl->addr, &fl->sdesc, STAT_LEN);
+                                     &fl->addr, &fl->sdesc, s->stat_len);
                if (!fl->desc) {
                        ret = -ENOMEM;
                        goto err;
@@ -2129,7 +2132,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq,
                 * free list ring) in Egress Queue Units.
                 */
                flsz = (fl->size / FL_PER_EQ_UNIT +
-                       STAT_LEN / EQ_UNIT);
+                       s->stat_len / EQ_UNIT);
 
                /*
                 * Fill in all the relevant firmware Ingress Queue Command
@@ -2217,6 +2220,7 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
                           struct net_device *dev, struct netdev_queue *devq,
                           unsigned int iqid)
 {
+       struct sge *s = &adapter->sge;
        int ret, nentries;
        struct fw_eq_eth_cmd cmd, rpl;
        struct port_info *pi = netdev_priv(dev);
@@ -2225,7 +2229,7 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
         * Calculate the size of the hardware TX Queue (including the Status
         * Page on the end of the TX Queue) in units of TX Descriptors.
         */
-       nentries = txq->q.size + STAT_LEN / sizeof(struct tx_desc);
+       nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
 
        /*
         * Allocate the hardware ring for the TX ring (with space for its
@@ -2234,7 +2238,7 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
        txq->q.desc = alloc_ring(adapter->pdev_dev, txq->q.size,
                                 sizeof(struct tx_desc),
                                 sizeof(struct tx_sw_desc),
-                                &txq->q.phys_addr, &txq->q.sdesc, STAT_LEN);
+                                &txq->q.phys_addr, &txq->q.sdesc, s->stat_len);
        if (!txq->q.desc)
                return -ENOMEM;
 
@@ -2307,8 +2311,10 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq,
  */
 static void free_txq(struct adapter *adapter, struct sge_txq *tq)
 {
+       struct sge *s = &adapter->sge;
+
        dma_free_coherent(adapter->pdev_dev,
-                         tq->size * sizeof(*tq->desc) + STAT_LEN,
+                         tq->size * sizeof(*tq->desc) + s->stat_len,
                          tq->desc, tq->phys_addr);
        tq->cntxt_id = 0;
        tq->sdesc = NULL;
@@ -2322,6 +2328,7 @@ static void free_txq(struct adapter *adapter, struct sge_txq *tq)
 static void free_rspq_fl(struct adapter *adapter, struct sge_rspq *rspq,
                         struct sge_fl *fl)
 {
+       struct sge *s = &adapter->sge;
        unsigned int flid = fl ? fl->cntxt_id : 0xffff;
 
        t4vf_iq_free(adapter, FW_IQ_TYPE_FL_INT_CAP,
@@ -2337,7 +2344,7 @@ static void free_rspq_fl(struct adapter *adapter, struct sge_rspq *rspq,
        if (fl) {
                free_rx_bufs(adapter, fl, fl->avail);
                dma_free_coherent(adapter->pdev_dev,
-                                 fl->size * sizeof(*fl->desc) + STAT_LEN,
+                                 fl->size * sizeof(*fl->desc) + s->stat_len,
                                  fl->desc, fl->addr);
                kfree(fl->sdesc);
                fl->sdesc = NULL;
@@ -2423,6 +2430,7 @@ int t4vf_sge_init(struct adapter *adapter)
        u32 fl0 = sge_params->sge_fl_buffer_size[0];
        u32 fl1 = sge_params->sge_fl_buffer_size[1];
        struct sge *s = &adapter->sge;
+       unsigned int ingpadboundary, ingpackboundary;
 
        /*
         * Start by vetting the basic SGE parameters which have been set up by
@@ -2443,12 +2451,48 @@ int t4vf_sge_init(struct adapter *adapter)
         * Now translate the adapter parameters into our internal forms.
         */
        if (fl1)
-               FL_PG_ORDER = ilog2(fl1) - PAGE_SHIFT;
-       STAT_LEN = ((sge_params->sge_control & EGRSTATUSPAGESIZE_MASK)
-                   ? 128 : 64);
-       PKTSHIFT = PKTSHIFT_GET(sge_params->sge_control);
-       FL_ALIGN = 1 << (INGPADBOUNDARY_GET(sge_params->sge_control) +
-                        SGE_INGPADBOUNDARY_SHIFT);
+               s->fl_pg_order = ilog2(fl1) - PAGE_SHIFT;
+       s->stat_len = ((sge_params->sge_control & EGRSTATUSPAGESIZE_MASK)
+                       ? 128 : 64);
+       s->pktshift = PKTSHIFT_GET(sge_params->sge_control);
+
+       /* T4 uses a single control field to specify both the PCIe Padding and
+        * Packing Boundary.  T5 introduced the ability to specify these
+        * separately.  The actual Ingress Packet Data alignment boundary
+        * within Packed Buffer Mode is the maximum of these two
+        * specifications.  (Note that it makes no real practical sense to
+        * have the Pading Boudary be larger than the Packing Boundary but you
+        * could set the chip up that way and, in fact, legacy T4 code would
+        * end doing this because it would initialize the Padding Boundary and
+        * leave the Packing Boundary initialized to 0 (16 bytes).)
+        */
+       ingpadboundary = 1 << (INGPADBOUNDARY_GET(sge_params->sge_control) +
+                              X_INGPADBOUNDARY_SHIFT);
+       if (is_t4(adapter->params.chip)) {
+               s->fl_align = ingpadboundary;
+       } else {
+               /* T5 has a different interpretation of one of the PCIe Packing
+                * Boundary values.
+                */
+               ingpackboundary = INGPACKBOUNDARY_G(sge_params->sge_control2);
+               if (ingpackboundary == INGPACKBOUNDARY_16B_X)
+                       ingpackboundary = 16;
+               else
+                       ingpackboundary = 1 << (ingpackboundary +
+                                               INGPACKBOUNDARY_SHIFT_X);
+
+               s->fl_align = max(ingpadboundary, ingpackboundary);
+       }
+
+       /* A FL with <= fl_starve_thres buffers is starving and a periodic
+        * timer will attempt to refill it.  This needs to be larger than the
+        * SGE's Egress Congestion Threshold.  If it isn't, then we can get
+        * stuck waiting for new packets while the SGE is waiting for us to
+        * give it more Free List entries.  (Note that the SGE's Egress
+        * Congestion Threshold is in units of 2 Free List pointers.)
+        */
+       s->fl_starve_thres
+               = EGRTHRESHOLD_GET(sge_params->sge_congestion_control)*2 + 1;
 
        /*
         * Set up tasklet timers.
index 95df61dcb4ce57021237a15013bfdc8e88c0fa5d..4b6a6d14d86d98df42bea1de5a6a507d9820374e 100644 (file)
@@ -134,11 +134,13 @@ struct dev_params {
  */
 struct sge_params {
        u32 sge_control;                /* padding, boundaries, lengths, etc. */
+       u32 sge_control2;               /* T5: more of the same */
        u32 sge_host_page_size;         /* RDMA page sizes */
        u32 sge_queues_per_page;        /* RDMA queues/page */
        u32 sge_user_mode_limits;       /* limits for BAR2 user mode accesses */
        u32 sge_fl_buffer_size[16];     /* free list buffer sizes */
        u32 sge_ingress_rx_threshold;   /* RX counter interrupt threshold[4] */
+       u32 sge_congestion_control;     /* congestion thresholds, etc. */
        u32 sge_timer_value_0_and_1;    /* interrupt coalescing timer values */
        u32 sge_timer_value_2_and_3;
        u32 sge_timer_value_4_and_5;
index e984fdc48ba2e326a738e6f5bfa14e1bfda73f02..1e896b923234f6d1b2e21da52fd73b010d45f214 100644 (file)
@@ -468,12 +468,38 @@ int t4vf_get_sge_params(struct adapter *adapter)
        sge_params->sge_timer_value_2_and_3 = vals[5];
        sge_params->sge_timer_value_4_and_5 = vals[6];
 
+       /* T4 uses a single control field to specify both the PCIe Padding and
+        * Packing Boundary.  T5 introduced the ability to specify these
+        * separately with the Padding Boundary in SGE_CONTROL and and Packing
+        * Boundary in SGE_CONTROL2.  So for T5 and later we need to grab
+        * SGE_CONTROL in order to determine how ingress packet data will be
+        * laid out in Packed Buffer Mode.  Unfortunately, older versions of
+        * the firmware won't let us retrieve SGE_CONTROL2 so if we get a
+        * failure grabbing it we throw an error since we can't figure out the
+        * right value.
+        */
+       if (!is_t4(adapter->params.chip)) {
+               params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
+                            FW_PARAMS_PARAM_XYZ(SGE_CONTROL2_A));
+               v = t4vf_query_params(adapter, 1, params, vals);
+               if (v != FW_SUCCESS) {
+                       dev_err(adapter->pdev_dev,
+                               "Unable to get SGE Control2; "
+                               "probably old firmware.\n");
+                       return v;
+               }
+               sge_params->sge_control2 = vals[0];
+       }
+
        params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
                     FW_PARAMS_PARAM_XYZ(SGE_INGRESS_RX_THRESHOLD));
-       v = t4vf_query_params(adapter, 1, params, vals);
+       params[1] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
+                    FW_PARAMS_PARAM_XYZ(SGE_CONM_CTRL));
+       v = t4vf_query_params(adapter, 2, params, vals);
        if (v)
                return v;
        sge_params->sge_ingress_rx_threshold = vals[0];
+       sge_params->sge_congestion_control = vals[1];
 
        return 0;
 }
index 69dfd3c9e5298a8519792cb8fcb77fe436d1847f..0be6850be8a2383e11240093bd421dfbd2595595 100644 (file)
@@ -86,7 +86,7 @@ void enic_rfs_flw_tbl_free(struct enic *enic)
        int i;
 
        enic_rfs_timer_stop(enic);
-       spin_lock(&enic->rfs_h.lock);
+       spin_lock_bh(&enic->rfs_h.lock);
        enic->rfs_h.free = 0;
        for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
                struct hlist_head *hhead;
@@ -100,7 +100,7 @@ void enic_rfs_flw_tbl_free(struct enic *enic)
                        kfree(n);
                }
        }
-       spin_unlock(&enic->rfs_h.lock);
+       spin_unlock_bh(&enic->rfs_h.lock);
 }
 
 struct enic_rfs_fltr_node *htbl_fltr_search(struct enic *enic, u16 fltr_id)
@@ -128,7 +128,7 @@ void enic_flow_may_expire(unsigned long data)
        bool res;
        int j;
 
-       spin_lock(&enic->rfs_h.lock);
+       spin_lock_bh(&enic->rfs_h.lock);
        for (j = 0; j < ENIC_CLSF_EXPIRE_COUNT; j++) {
                struct hlist_head *hhead;
                struct hlist_node *tmp;
@@ -148,7 +148,7 @@ void enic_flow_may_expire(unsigned long data)
                        }
                }
        }
-       spin_unlock(&enic->rfs_h.lock);
+       spin_unlock_bh(&enic->rfs_h.lock);
        mod_timer(&enic->rfs_h.rfs_may_expire, jiffies + HZ/4);
 }
 
@@ -183,7 +183,7 @@ int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                return -EPROTONOSUPPORT;
 
        tbl_idx = skb_get_hash_raw(skb) & ENIC_RFS_FLW_MASK;
-       spin_lock(&enic->rfs_h.lock);
+       spin_lock_bh(&enic->rfs_h.lock);
        n = htbl_key_search(&enic->rfs_h.ht_head[tbl_idx], &keys);
 
        if (n) { /* entry already present  */
@@ -277,7 +277,7 @@ int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
        }
 
 ret_unlock:
-       spin_unlock(&enic->rfs_h.lock);
+       spin_unlock_bh(&enic->rfs_h.lock);
        return res;
 }
 
index 929bfe70080ac040bd879ede472d72744aaa300c..73cf1653a4a3d4225951334e26506e89145cd1e4 100644 (file)
@@ -940,18 +940,8 @@ static int enic_rq_alloc_buf(struct vnic_rq *rq)
        struct vnic_rq_buf *buf = rq->to_use;
 
        if (buf->os_buf) {
-               buf = buf->next;
-               rq->to_use = buf;
-               rq->ring.desc_avail--;
-               if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) {
-                       /* Adding write memory barrier prevents compiler and/or
-                        * CPU reordering, thus avoiding descriptor posting
-                        * before descriptor is initialized. Otherwise, hardware
-                        * can read stale descriptor fields.
-                        */
-                       wmb();
-                       iowrite32(buf->index, &rq->ctrl->posted_index);
-               }
+               enic_queue_rq_desc(rq, buf->os_buf, os_buf_index, buf->dma_addr,
+                                  buf->len);
 
                return 0;
        }
@@ -1037,7 +1027,10 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
                                enic->rq_truncated_pkts++;
                }
 
+               pci_unmap_single(enic->pdev, buf->dma_addr, buf->len,
+                                PCI_DMA_FROMDEVICE);
                dev_kfree_skb_any(skb);
+               buf->os_buf = NULL;
 
                return;
        }
@@ -1088,7 +1081,10 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
                /* Buffer overflow
                 */
 
+               pci_unmap_single(enic->pdev, buf->dma_addr, buf->len,
+                                PCI_DMA_FROMDEVICE);
                dev_kfree_skb_any(skb);
+               buf->os_buf = NULL;
        }
 }
 
@@ -1674,13 +1670,13 @@ static int enic_stop(struct net_device *netdev)
 
        enic_dev_disable(enic);
 
-       local_bh_disable();
        for (i = 0; i < enic->rq_count; i++) {
                napi_disable(&enic->napi[i]);
+               local_bh_disable();
                while (!enic_poll_lock_napi(&enic->rq[i]))
                        mdelay(1);
+               local_bh_enable();
        }
-       local_bh_enable();
 
        netif_carrier_off(netdev);
        netif_tx_disable(netdev);
index 9a18e7930b31bea1cebc533d014655af5673c748..597c463e384d0d5d9fb0f46a9b363e9c9165c6cf 100644 (file)
@@ -4309,11 +4309,16 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh)
                return -EOPNOTSUPP;
 
        br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+       if (!br_spec)
+               return -EINVAL;
 
        nla_for_each_nested(attr, br_spec, rem) {
                if (nla_type(attr) != IFLA_BRIDGE_MODE)
                        continue;
 
+               if (nla_len(attr) < sizeof(mode))
+                       return -EINVAL;
+
                mode = nla_get_u16(attr);
                if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
                        return -EINVAL;
@@ -4421,6 +4426,11 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
                 "Disabled VxLAN offloads for UDP port %d\n",
                 be16_to_cpu(port));
 }
+
+static bool be_gso_check(struct sk_buff *skb, struct net_device *dev)
+{
+       return vxlan_gso_check(skb);
+}
 #endif
 
 static const struct net_device_ops be_netdev_ops = {
@@ -4450,6 +4460,7 @@ static const struct net_device_ops be_netdev_ops = {
 #ifdef CONFIG_BE2NET_VXLAN
        .ndo_add_vxlan_port     = be_add_vxlan_port,
        .ndo_del_vxlan_port     = be_del_vxlan_port,
+       .ndo_gso_check          = be_gso_check,
 #endif
 };
 
index 81b96cf875740f6faa418885718dcc78c2113570..3dca494797bd2ebb8a7dd6c1983b7f19e72e481c 100644 (file)
@@ -298,6 +298,16 @@ static void *swap_buffer(void *bufaddr, int len)
        return bufaddr;
 }
 
+static void swap_buffer2(void *dst_buf, void *src_buf, int len)
+{
+       int i;
+       unsigned int *src = src_buf;
+       unsigned int *dst = dst_buf;
+
+       for (i = 0; i < len; i += 4, src++, dst++)
+               *dst = swab32p(src);
+}
+
 static void fec_dump(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1307,7 +1317,7 @@ fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff
 }
 
 static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
-                              struct bufdesc *bdp, u32 length)
+                              struct bufdesc *bdp, u32 length, bool swap)
 {
        struct  fec_enet_private *fep = netdev_priv(ndev);
        struct sk_buff *new_skb;
@@ -1322,7 +1332,10 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb,
        dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
                                FEC_ENET_RX_FRSIZE - fep->rx_align,
                                DMA_FROM_DEVICE);
-       memcpy(new_skb->data, (*skb)->data, length);
+       if (!swap)
+               memcpy(new_skb->data, (*skb)->data, length);
+       else
+               swap_buffer2(new_skb->data, (*skb)->data, length);
        *skb = new_skb;
 
        return true;
@@ -1352,6 +1365,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
        u16     vlan_tag;
        int     index = 0;
        bool    is_copybreak;
+       bool    need_swap = id_entry->driver_data & FEC_QUIRK_SWAP_FRAME;
 
 #ifdef CONFIG_M532x
        flush_cache_all();
@@ -1415,7 +1429,8 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
                 * include that when passing upstream as it messes up
                 * bridging applications.
                 */
-               is_copybreak = fec_enet_copybreak(ndev, &skb, bdp, pkt_len - 4);
+               is_copybreak = fec_enet_copybreak(ndev, &skb, bdp, pkt_len - 4,
+                                                 need_swap);
                if (!is_copybreak) {
                        skb_new = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
                        if (unlikely(!skb_new)) {
@@ -1430,7 +1445,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
                prefetch(skb->data - NET_IP_ALIGN);
                skb_put(skb, pkt_len - 4);
                data = skb->data;
-               if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
+               if (!is_copybreak && need_swap)
                        swap_buffer(data, pkt_len);
 
                /* Extract the enhanced buffer descriptor */
@@ -1581,7 +1596,8 @@ fec_enet_interrupt(int irq, void *dev_id)
                complete(&fep->mdio_done);
        }
 
-       fec_ptp_check_pps_event(fep);
+       if (fep->ptp_clock)
+               fec_ptp_check_pps_event(fep);
 
        return ret;
 }
@@ -3342,12 +3358,11 @@ static int __maybe_unused fec_suspend(struct device *dev)
                netif_device_detach(ndev);
                netif_tx_unlock_bh(ndev);
                fec_stop(ndev);
+               fec_enet_clk_enable(ndev, false);
+               pinctrl_pm_select_sleep_state(&fep->pdev->dev);
        }
        rtnl_unlock();
 
-       fec_enet_clk_enable(ndev, false);
-       pinctrl_pm_select_sleep_state(&fep->pdev->dev);
-
        if (fep->reg_phy)
                regulator_disable(fep->reg_phy);
 
@@ -3366,13 +3381,14 @@ static int __maybe_unused fec_resume(struct device *dev)
                        return ret;
        }
 
-       pinctrl_pm_select_default_state(&fep->pdev->dev);
-       ret = fec_enet_clk_enable(ndev, true);
-       if (ret)
-               goto failed_clk;
-
        rtnl_lock();
        if (netif_running(ndev)) {
+               pinctrl_pm_select_default_state(&fep->pdev->dev);
+               ret = fec_enet_clk_enable(ndev, true);
+               if (ret) {
+                       rtnl_unlock();
+                       goto failed_clk;
+               }
                fec_restart(ndev);
                netif_tx_lock_bh(ndev);
                netif_device_attach(ndev);
index 3d4e08be170970b7f981c19a23e65c35f7ae860b..b34214e2df5f6e55bdbb29e6a8016c139e74345c 100644 (file)
@@ -341,6 +341,9 @@ static void restart(struct net_device *dev)
                FC(fecp, x_cntrl, FEC_TCNTRL_FDEN);     /* FD disable */
        }
 
+       /* Restore multicast and promiscuous settings */
+       set_multicast_list(dev);
+
        /*
         * Enable interrupts we wish to service.
         */
index f30411f0701f694175392198941b0d69d3798682..7a184e8816a48f9eb74f4890b60b32345dbcf5f1 100644 (file)
@@ -355,6 +355,9 @@ static void restart(struct net_device *dev)
        if (fep->phydev->duplex)
                S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
 
+       /* Restore multicast and promiscuous settings */
+       set_multicast_list(dev);
+
        S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
 }
 
index 5f6aded512f539f9a12cb692f810fd3d8e560a3f..24f3986cfae2950f582d3a5e4644c4e1b666391e 100644 (file)
@@ -1075,7 +1075,10 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                                  NETIF_F_HW_CSUM |
                                  NETIF_F_SG);
 
-       netdev->priv_flags |= IFF_UNICAST_FLT;
+       /* Do not set IFF_UNICAST_FLT for VMWare's 82545EM */
+       if (hw->device_id != E1000_DEV_ID_82545EM_COPPER ||
+           hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE)
+               netdev->priv_flags |= IFF_UNICAST_FLT;
 
        adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
 
index ed5f1c15fb0f4cd5fe7ce797920fd3b6cd21f7df..c3a7f4a4b7757a35afa4a23b944a64e0ac4d673b 100644 (file)
@@ -6151,7 +6151,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
                                I40E_GL_MDET_TX_PF_NUM_SHIFT;
                u8 vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >>
                                I40E_GL_MDET_TX_VF_NUM_SHIFT;
-               u8 event = (reg & I40E_GL_MDET_TX_EVENT_SHIFT) >>
+               u8 event = (reg & I40E_GL_MDET_TX_EVENT_MASK) >>
                                I40E_GL_MDET_TX_EVENT_SHIFT;
                u8 queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >>
                                I40E_GL_MDET_TX_QUEUE_SHIFT;
@@ -6165,7 +6165,7 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
        if (reg & I40E_GL_MDET_RX_VALID_MASK) {
                u8 func = (reg & I40E_GL_MDET_RX_FUNCTION_MASK) >>
                                I40E_GL_MDET_RX_FUNCTION_SHIFT;
-               u8 event = (reg & I40E_GL_MDET_RX_EVENT_SHIFT) >>
+               u8 event = (reg & I40E_GL_MDET_RX_EVENT_MASK) >>
                                I40E_GL_MDET_RX_EVENT_SHIFT;
                u8 queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >>
                                I40E_GL_MDET_RX_QUEUE_SHIFT;
index a21b14495ebd0d7b953a1d8e4b2319d23452b95e..487cd9c4ac0d33a3ce07bb12fbe3f5db00e01586 100644 (file)
@@ -1012,7 +1012,8 @@ static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx)
        /* igb_get_stats64() might access the rings on this vector,
         * we must wait a grace period before freeing it.
         */
-       kfree_rcu(q_vector, rcu);
+       if (q_vector)
+               kfree_rcu(q_vector, rcu);
 }
 
 /**
@@ -1792,8 +1793,10 @@ void igb_down(struct igb_adapter *adapter)
        adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE;
 
        for (i = 0; i < adapter->num_q_vectors; i++) {
-               napi_synchronize(&(adapter->q_vector[i]->napi));
-               napi_disable(&(adapter->q_vector[i]->napi));
+               if (adapter->q_vector[i]) {
+                       napi_synchronize(&adapter->q_vector[i]->napi);
+                       napi_disable(&adapter->q_vector[i]->napi);
+               }
        }
 
 
@@ -3717,7 +3720,8 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter)
        int i;
 
        for (i = 0; i < adapter->num_tx_queues; i++)
-               igb_free_tx_resources(adapter->tx_ring[i]);
+               if (adapter->tx_ring[i])
+                       igb_free_tx_resources(adapter->tx_ring[i]);
 }
 
 void igb_unmap_and_free_tx_resource(struct igb_ring *ring,
@@ -3782,7 +3786,8 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter)
        int i;
 
        for (i = 0; i < adapter->num_tx_queues; i++)
-               igb_clean_tx_ring(adapter->tx_ring[i]);
+               if (adapter->tx_ring[i])
+                       igb_clean_tx_ring(adapter->tx_ring[i]);
 }
 
 /**
@@ -3819,7 +3824,8 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter)
        int i;
 
        for (i = 0; i < adapter->num_rx_queues; i++)
-               igb_free_rx_resources(adapter->rx_ring[i]);
+               if (adapter->rx_ring[i])
+                       igb_free_rx_resources(adapter->rx_ring[i]);
 }
 
 /**
@@ -3874,7 +3880,8 @@ static void igb_clean_all_rx_rings(struct igb_adapter *adapter)
        int i;
 
        for (i = 0; i < adapter->num_rx_queues; i++)
-               igb_clean_rx_ring(adapter->rx_ring[i]);
+               if (adapter->rx_ring[i])
+                       igb_clean_rx_ring(adapter->rx_ring[i]);
 }
 
 /**
@@ -6537,6 +6544,9 @@ static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,
        if (unlikely(page_to_nid(page) != numa_node_id()))
                return false;
 
+       if (unlikely(page->pfmemalloc))
+               return false;
+
 #if (PAGE_SIZE < 8192)
        /* if we are only owner of page we can reuse it */
        if (unlikely(page_count(page) != 1))
@@ -6603,7 +6613,8 @@ static bool igb_add_rx_frag(struct igb_ring *rx_ring,
                memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
 
                /* we can reuse buffer as-is, just make sure it is local */
-               if (likely(page_to_nid(page) == numa_node_id()))
+               if (likely((page_to_nid(page) == numa_node_id()) &&
+                          !page->pfmemalloc))
                        return true;
 
                /* this page cannot be reused so discard it */
@@ -7400,6 +7411,8 @@ static int igb_resume(struct device *dev)
        pci_restore_state(pdev);
        pci_save_state(pdev);
 
+       if (!pci_device_is_present(pdev))
+               return -ENODEV;
        err = pci_enable_device_mem(pdev);
        if (err) {
                dev_err(&pdev->dev,
index 3ce4a258f94534da25304c9138e0bf28fdd3c9ff..0ae038b9af90cfc7dc15bd01c0b4014e37fa1911 100644 (file)
@@ -342,12 +342,16 @@ static int ixgbe_set_settings(struct net_device *netdev,
                if (old == advertised)
                        return err;
                /* this sets the link speed and restarts auto-neg */
+               while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
+                       usleep_range(1000, 2000);
+
                hw->mac.autotry_restart = true;
                err = hw->mac.ops.setup_link(hw, advertised, true);
                if (err) {
                        e_info(probe, "setup link failed with code %d\n", err);
                        hw->mac.ops.setup_link(hw, old, true);
                }
+               clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
        } else {
                /* in this case we currently only support 10Gb/FULL */
                u32 speed = ethtool_cmd_speed(ecmd);
index fec5212d43374835156049f8b7c5f0bc828dcdde..cc51554c9e99a49e74c24ab7bf8f97848a06d7a3 100644 (file)
@@ -3936,8 +3936,8 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
                 * if SR-IOV and VMDQ are disabled - otherwise ensure
                 * that hardware VLAN filters remain enabled.
                 */
-               if (!(adapter->flags & (IXGBE_FLAG_VMDQ_ENABLED |
-                                       IXGBE_FLAG_SRIOV_ENABLED)))
+               if (adapter->flags & (IXGBE_FLAG_VMDQ_ENABLED |
+                                     IXGBE_FLAG_SRIOV_ENABLED))
                        vlnctrl |= (IXGBE_VLNCTRL_VFE | IXGBE_VLNCTRL_CFIEN);
        } else {
                if (netdev->flags & IFF_ALLMULTI) {
@@ -4321,8 +4321,8 @@ static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
                                IXGBE_CB(skb)->page_released = false;
                        }
                        dev_kfree_skb(skb);
+                       rx_buffer->skb = NULL;
                }
-               rx_buffer->skb = NULL;
                if (rx_buffer->dma)
                        dma_unmap_page(dev, rx_buffer->dma,
                                       ixgbe_rx_pg_size(rx_ring),
@@ -7669,6 +7669,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
                return -EOPNOTSUPP;
 
        br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+       if (!br_spec)
+               return -EINVAL;
 
        nla_for_each_nested(attr, br_spec, rem) {
                __u16 mode;
@@ -7677,6 +7679,9 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
                if (nla_type(attr) != IFLA_BRIDGE_MODE)
                        continue;
 
+               if (nla_len(attr) < sizeof(mode))
+                       return -EINVAL;
+
                mode = nla_get_u16(attr);
                if (mode == BRIDGE_MODE_VEPA) {
                        reg = 0;
@@ -7979,6 +7984,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        int i, err, pci_using_dac, expected_gts;
        unsigned int indices = MAX_TX_QUEUES;
        u8 part_str[IXGBE_PBANUM_LENGTH];
+       bool disable_dev = false;
 #ifdef IXGBE_FCOE
        u16 device_caps;
 #endif
@@ -8369,13 +8375,14 @@ err_sw_init:
        iounmap(adapter->io_addr);
        kfree(adapter->mac_table);
 err_ioremap:
+       disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
        free_netdev(netdev);
 err_alloc_etherdev:
        pci_release_selected_regions(pdev,
                                     pci_select_bars(pdev, IORESOURCE_MEM));
 err_pci_reg:
 err_dma:
-       if (!adapter || !test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+       if (!adapter || disable_dev)
                pci_disable_device(pdev);
        return err;
 }
@@ -8393,6 +8400,7 @@ static void ixgbe_remove(struct pci_dev *pdev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
        struct net_device *netdev = adapter->netdev;
+       bool disable_dev;
 
        ixgbe_dbg_adapter_exit(adapter);
 
@@ -8442,11 +8450,12 @@ static void ixgbe_remove(struct pci_dev *pdev)
        e_dev_info("complete\n");
 
        kfree(adapter->mac_table);
+       disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
        free_netdev(netdev);
 
        pci_disable_pcie_error_reporting(pdev);
 
-       if (!test_and_set_bit(__IXGBE_DISABLED, &adapter->state))
+       if (disable_dev)
                pci_disable_device(pdev);
 }
 
index d47b19f27c355c96ea006c004afa38efac3dcfe7..28b81ae09b5ae2288e8d05fac82176a8d504fd18 100644 (file)
@@ -635,7 +635,6 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
  **/
 s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
 {
-       s32 status;
        u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
        bool autoneg = false;
        ixgbe_link_speed speed;
@@ -700,8 +699,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
 
        hw->phy.ops.write_reg(hw, MDIO_CTRL1,
                              MDIO_MMD_AN, autoneg_reg);
-
-       return status;
+       return 0;
 }
 
 /**
index b151a949f352a20ec8e74b4f3a7b6bb194ce841c..d44560d1d268caae42143b674535db45c2784289 100644 (file)
@@ -1047,7 +1047,6 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
                int tx_index;
                struct tx_desc *desc;
                u32 cmd_sts;
-               struct sk_buff *skb;
 
                tx_index = txq->tx_used_desc;
                desc = &txq->tx_desc_area[tx_index];
@@ -1066,19 +1065,22 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
                reclaimed++;
                txq->tx_desc_count--;
 
-               skb = NULL;
-               if (cmd_sts & TX_LAST_DESC)
-                       skb = __skb_dequeue(&txq->tx_skb);
+               if (!IS_TSO_HEADER(txq, desc->buf_ptr))
+                       dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
+                                        desc->byte_cnt, DMA_TO_DEVICE);
+
+               if (cmd_sts & TX_ENABLE_INTERRUPT) {
+                       struct sk_buff *skb = __skb_dequeue(&txq->tx_skb);
+
+                       if (!WARN_ON(!skb))
+                               dev_kfree_skb(skb);
+               }
 
                if (cmd_sts & ERROR_SUMMARY) {
                        netdev_info(mp->dev, "tx error\n");
                        mp->dev->stats.tx_errors++;
                }
 
-               if (!IS_TSO_HEADER(txq, desc->buf_ptr))
-                       dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
-                                        desc->byte_cnt, DMA_TO_DEVICE);
-               dev_kfree_skb(skb);
        }
 
        __netif_tx_unlock_bh(nq);
index ece83f101526de02fac0af5ccf0f85c88d440670..fdf3e382e4649313b677fa8c164e1d2430130f3b 100644 (file)
@@ -1692,6 +1692,7 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
 {
        struct mvpp2_prs_entry *pe;
        int tid_aux, tid;
+       int ret = 0;
 
        pe = mvpp2_prs_vlan_find(priv, tpid, ai);
 
@@ -1723,8 +1724,10 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
                                break;
                }
 
-               if (tid <= tid_aux)
-                       return -EINVAL;
+               if (tid <= tid_aux) {
+                       ret = -EINVAL;
+                       goto error;
+               }
 
                memset(pe, 0 , sizeof(struct mvpp2_prs_entry));
                mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
@@ -1756,9 +1759,10 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
 
        mvpp2_prs_hw_write(priv, pe);
 
+error:
        kfree(pe);
 
-       return 0;
+       return ret;
 }
 
 /* Get first free double vlan ai number */
@@ -1821,7 +1825,7 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
                                     unsigned int port_map)
 {
        struct mvpp2_prs_entry *pe;
-       int tid_aux, tid, ai;
+       int tid_aux, tid, ai, ret = 0;
 
        pe = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
 
@@ -1838,8 +1842,10 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
 
                /* Set ai value for new double vlan entry */
                ai = mvpp2_prs_double_vlan_ai_free_get(priv);
-               if (ai < 0)
-                       return ai;
+               if (ai < 0) {
+                       ret = ai;
+                       goto error;
+               }
 
                /* Get first single/triple vlan tid */
                for (tid_aux = MVPP2_PE_FIRST_FREE_TID;
@@ -1859,8 +1865,10 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
                                break;
                }
 
-               if (tid >= tid_aux)
-                       return -ERANGE;
+               if (tid >= tid_aux) {
+                       ret = -ERANGE;
+                       goto error;
+               }
 
                memset(pe, 0, sizeof(struct mvpp2_prs_entry));
                mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
@@ -1887,8 +1895,9 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
        mvpp2_prs_tcam_port_map_set(pe, port_map);
        mvpp2_prs_hw_write(priv, pe);
 
+error:
        kfree(pe);
-       return 0;
+       return ret;
 }
 
 /* IPv4 header parsing for fragmentation and L4 offset */
index f3032fec8fce03767580bd555a4760e8d7faba1e..4d69e382b4e5d07ab22fe327276c867099a12ca4 100644 (file)
@@ -1693,7 +1693,7 @@ int mlx4_en_start_port(struct net_device *dev)
        mlx4_set_stats_bitmap(mdev->dev, &priv->stats_bitmap);
 
 #ifdef CONFIG_MLX4_EN_VXLAN
-       if (priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VXLAN_OFFLOADS)
+       if (priv->mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
                vxlan_get_rx_port(dev);
 #endif
        priv->port_up = true;
@@ -2281,8 +2281,16 @@ static void mlx4_en_add_vxlan_offloads(struct work_struct *work)
        ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port,
                                  VXLAN_STEER_BY_OUTER_MAC, 1);
 out:
-       if (ret)
+       if (ret) {
                en_err(priv, "failed setting L2 tunnel configuration ret %d\n", ret);
+               return;
+       }
+
+       /* set offloads */
+       priv->dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+                                     NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL;
+       priv->dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
+       priv->dev->features    |= NETIF_F_GSO_UDP_TUNNEL;
 }
 
 static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
@@ -2290,6 +2298,11 @@ static void mlx4_en_del_vxlan_offloads(struct work_struct *work)
        int ret;
        struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
                                                 vxlan_del_task);
+       /* unset offloads */
+       priv->dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+                                     NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL);
+       priv->dev->hw_features &= ~NETIF_F_GSO_UDP_TUNNEL;
+       priv->dev->features    &= ~NETIF_F_GSO_UDP_TUNNEL;
 
        ret = mlx4_SET_PORT_VXLAN(priv->mdev->dev, priv->port,
                                  VXLAN_STEER_BY_OUTER_MAC, 0);
@@ -2342,6 +2355,11 @@ static void mlx4_en_del_vxlan_port(struct  net_device *dev,
 
        queue_work(priv->mdev->workqueue, &priv->vxlan_del_task);
 }
+
+static bool mlx4_en_gso_check(struct sk_buff *skb, struct net_device *dev)
+{
+       return vxlan_gso_check(skb);
+}
 #endif
 
 static const struct net_device_ops mlx4_netdev_ops = {
@@ -2373,6 +2391,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
 #ifdef CONFIG_MLX4_EN_VXLAN
        .ndo_add_vxlan_port     = mlx4_en_add_vxlan_port,
        .ndo_del_vxlan_port     = mlx4_en_del_vxlan_port,
+       .ndo_gso_check          = mlx4_en_gso_check,
 #endif
 };
 
@@ -2403,6 +2422,11 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
        .ndo_rx_flow_steer      = mlx4_en_filter_rfs,
 #endif
        .ndo_get_phys_port_id   = mlx4_en_get_phys_port_id,
+#ifdef CONFIG_MLX4_EN_VXLAN
+       .ndo_add_vxlan_port     = mlx4_en_add_vxlan_port,
+       .ndo_del_vxlan_port     = mlx4_en_del_vxlan_port,
+       .ndo_gso_check          = mlx4_en_gso_check,
+#endif
 };
 
 int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
@@ -2568,13 +2592,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
                dev->priv_flags |= IFF_UNICAST_FLT;
 
-       if (mdev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
-               dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
-                                       NETIF_F_TSO | NETIF_F_GSO_UDP_TUNNEL;
-               dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL;
-               dev->features    |= NETIF_F_GSO_UDP_TUNNEL;
-       }
-
        mdev->pndev[port] = dev;
 
        netif_carrier_off(dev);
index 34c137878545fc672dad1a3d86e11c034c0ac368..454d9fea640ecb0aa849b8d8106695d017ca3309 100644 (file)
@@ -836,8 +836,11 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
         * whether LSO is used */
        tx_desc->ctrl.srcrb_flags = priv->ctrl_flags;
        if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
-               tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
-                                                        MLX4_WQE_CTRL_TCP_UDP_CSUM);
+               if (!skb->encapsulation)
+                       tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM |
+                                                                MLX4_WQE_CTRL_TCP_UDP_CSUM);
+               else
+                       tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM);
                ring->tx_csum++;
        }
 
index a49c9d11d8a58e5a8bcc5419133a7909204a0a41..49290a4059039a72c86e119c59d2d03ec6c3eb4c 100644 (file)
@@ -1026,6 +1026,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
                                pr_cont("\n");
                }
        }
+       synchronize_irq(eq->irq);
 
        mlx4_mtt_cleanup(dev, &eq->mtt);
        for (i = 0; i < npages; ++i)
index ca0f98c951054945cd29fc3be2284fc7eeb7d729..872843179f44af3c7442614477bd2af131118347 100644 (file)
@@ -955,6 +955,10 @@ static void mlx4_err_rule(struct mlx4_dev *dev, char *str,
                                        cur->ib.dst_gid_msk);
                        break;
 
+               case MLX4_NET_TRANS_RULE_ID_VXLAN:
+                       len += snprintf(buf + len, BUF_SIZE - len,
+                                       "VNID = %d ", be32_to_cpu(cur->vxlan.vni));
+                       break;
                case MLX4_NET_TRANS_RULE_ID_IPV6:
                        break;
 
index 5d2498dcf536d5e96cc13b9274b00137d4508c5d..cd5cf6d957c7afa98d76ad54ba42beb1b395e3c8 100644 (file)
@@ -1546,7 +1546,7 @@ static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
 
        switch (op) {
        case RES_OP_RESERVE:
-               count = get_param_l(&in_param);
+               count = get_param_l(&in_param) & 0xffffff;
                align = get_param_h(&in_param);
                err = mlx4_grant_resource(dev, slave, RES_QP, count, 0);
                if (err)
index ed53291468f3226e644aa039025a962aff0b0fe0..ad2c96a02a5352caec2d8649c714c3616be98ea8 100644 (file)
@@ -374,15 +374,14 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
        snprintf(eq->name, MLX5_MAX_EQ_NAME, "%s@pci:%s",
                 name, pci_name(dev->pdev));
        eq->eqn = out.eq_number;
+       eq->irqn = vecidx;
+       eq->dev = dev;
+       eq->doorbell = uar->map + MLX5_EQ_DOORBEL_OFFSET;
        err = request_irq(table->msix_arr[vecidx].vector, mlx5_msix_handler, 0,
                          eq->name, eq);
        if (err)
                goto err_eq;
 
-       eq->irqn = vecidx;
-       eq->dev = dev;
-       eq->doorbell = uar->map + MLX5_EQ_DOORBEL_OFFSET;
-
        err = mlx5_debug_eq_add(dev, eq);
        if (err)
                goto err_irq;
@@ -420,6 +419,7 @@ int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
        if (err)
                mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n",
                               eq->eqn);
+       synchronize_irq(table->msix_arr[eq->irqn].vector);
        mlx5_buf_free(dev, &eq->buf);
 
        return err;
index 3d8e8e489b2ddb3539a4a9c89b784974c833e50e..71b10b210792e316582d0280d87f92cbee6bb2d8 100644 (file)
@@ -864,14 +864,14 @@ static int init_one(struct pci_dev *pdev,
        dev->profile = &profile[prof_sel];
        dev->event = mlx5_core_event;
 
+       INIT_LIST_HEAD(&priv->ctx_list);
+       spin_lock_init(&priv->ctx_lock);
        err = mlx5_dev_init(dev, pdev);
        if (err) {
                dev_err(&pdev->dev, "mlx5_dev_init failed %d\n", err);
                goto out;
        }
 
-       INIT_LIST_HEAD(&priv->ctx_list);
-       spin_lock_init(&priv->ctx_lock);
        err = mlx5_register_device(dev);
        if (err) {
                dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
index 0b2a1ccd276dbd4c1e582ef635b6304c351d03d7..613037584d08e785ef2700ca1d2221b50b256e9c 100644 (file)
@@ -2762,7 +2762,8 @@ netxen_fw_poll_work(struct work_struct *work)
        if (test_bit(__NX_RESETTING, &adapter->state))
                goto reschedule;
 
-       if (test_bit(__NX_DEV_UP, &adapter->state)) {
+       if (test_bit(__NX_DEV_UP, &adapter->state) &&
+           !(adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)) {
                if (!adapter->has_link_events) {
 
                        netxen_nic_handle_phy_intr(adapter);
index f5e29f7bdae39b77eed8abc0b8e73360ceeda698..a913b3ad2f899e791a9abd3c5e518d1f7410ceeb 100644 (file)
@@ -503,6 +503,11 @@ static void qlcnic_del_vxlan_port(struct net_device *netdev,
 
        adapter->flags |= QLCNIC_DEL_VXLAN_PORT;
 }
+
+static bool qlcnic_gso_check(struct sk_buff *skb, struct net_device *dev)
+{
+       return vxlan_gso_check(skb);
+}
 #endif
 
 static const struct net_device_ops qlcnic_netdev_ops = {
@@ -526,6 +531,7 @@ static const struct net_device_ops qlcnic_netdev_ops = {
 #ifdef CONFIG_QLCNIC_VXLAN
        .ndo_add_vxlan_port     = qlcnic_add_vxlan_port,
        .ndo_del_vxlan_port     = qlcnic_del_vxlan_port,
+       .ndo_gso_check          = qlcnic_gso_check,
 #endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = qlcnic_poll_controller,
index f3a47147937d46b3a7aa5955b6e9729d17597a99..9a49f42ac2ba4a76e743f1c400f9f4bd69850a6a 100644 (file)
@@ -5,7 +5,6 @@
 config NET_VENDOR_QUALCOMM
        bool "Qualcomm devices"
        default y
-       depends on SPI_MASTER && OF_GPIO
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
@@ -20,7 +19,7 @@ if NET_VENDOR_QUALCOMM
 
 config QCA7000
        tristate "Qualcomm Atheros QCA7000 support"
-       depends on SPI_MASTER && OF_GPIO
+       depends on SPI_MASTER && OF
        ---help---
          This SPI protocol driver supports the Qualcomm Atheros QCA7000.
 
index 60e9c2cd051e98bd9a1466f32e7344c52f241572..b5db6b3f939fc00884f313829cb9c1ffff118981 100644 (file)
@@ -917,21 +917,13 @@ static int sh_eth_reset(struct net_device *ndev)
        return ret;
 }
 
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
 static void sh_eth_set_receive_align(struct sk_buff *skb)
 {
-       int reserve;
+       uintptr_t reserve = (uintptr_t)skb->data & (SH_ETH_RX_ALIGN - 1);
 
-       reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1));
        if (reserve)
-               skb_reserve(skb, reserve);
+               skb_reserve(skb, SH_ETH_RX_ALIGN - reserve);
 }
-#else
-static void sh_eth_set_receive_align(struct sk_buff *skb)
-{
-       skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN);
-}
-#endif
 
 
 /* CPU <-> EDMAC endian convert */
@@ -1119,6 +1111,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
        struct sh_eth_txdesc *txdesc = NULL;
        int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
        int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
 
        mdp->cur_rx = 0;
        mdp->cur_tx = 0;
@@ -1131,21 +1124,21 @@ static void sh_eth_ring_format(struct net_device *ndev)
        for (i = 0; i < mdp->num_rx_ring; i++) {
                /* skb */
                mdp->rx_skbuff[i] = NULL;
-               skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
+               skb = netdev_alloc_skb(ndev, skbuff_size);
                mdp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
-               dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                              DMA_FROM_DEVICE);
                sh_eth_set_receive_align(skb);
 
                /* RX descriptor */
                rxdesc = &mdp->rx_ring[i];
+               /* The size of the buffer is a multiple of 16 bytes. */
+               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+               dma_map_single(&ndev->dev, skb->data, rxdesc->buffer_length,
+                              DMA_FROM_DEVICE);
                rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
                rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
 
-               /* The size of the buffer is 16 byte boundary. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
                /* Rx descriptor address set */
                if (i == 0) {
                        sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
@@ -1397,6 +1390,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        struct sk_buff *skb;
        u16 pkt_len = 0;
        u32 desc_status;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
 
        rxdesc = &mdp->rx_ring[entry];
        while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
@@ -1448,7 +1442,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                        if (mdp->cd->rpadir)
                                skb_reserve(skb, NET_IP_ALIGN);
                        dma_sync_single_for_cpu(&ndev->dev, rxdesc->addr,
-                                               mdp->rx_buf_sz,
+                                               ALIGN(mdp->rx_buf_sz, 16),
                                                DMA_FROM_DEVICE);
                        skb_put(skb, pkt_len);
                        skb->protocol = eth_type_trans(skb, ndev);
@@ -1468,13 +1462,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
 
                if (mdp->rx_skbuff[entry] == NULL) {
-                       skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
+                       skb = netdev_alloc_skb(ndev, skbuff_size);
                        mdp->rx_skbuff[entry] = skb;
                        if (skb == NULL)
                                break;  /* Better luck next round. */
-                       dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                                      DMA_FROM_DEVICE);
                        sh_eth_set_receive_align(skb);
+                       dma_map_single(&ndev->dev, skb->data,
+                                      rxdesc->buffer_length, DMA_FROM_DEVICE);
 
                        skb_checksum_none_assert(skb);
                        rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
@@ -2042,6 +2036,8 @@ static int sh_eth_open(struct net_device *ndev)
        if (ret)
                goto out_free_irq;
 
+       mdp->is_opened = 1;
+
        return ret;
 
 out_free_irq:
@@ -2131,6 +2127,36 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
+{
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+
+       if (sh_eth_is_rz_fast_ether(mdp))
+               return &ndev->stats;
+
+       if (!mdp->is_opened)
+               return &ndev->stats;
+
+       ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
+       sh_eth_write(ndev, 0, TROCR);   /* (write clear) */
+       ndev->stats.collisions += sh_eth_read(ndev, CDCR);
+       sh_eth_write(ndev, 0, CDCR);    /* (write clear) */
+       ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
+       sh_eth_write(ndev, 0, LCCR);    /* (write clear) */
+
+       if (sh_eth_is_gether(mdp)) {
+               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
+               sh_eth_write(ndev, 0, CERCR);   /* (write clear) */
+               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
+               sh_eth_write(ndev, 0, CEECR);   /* (write clear) */
+       } else {
+               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
+               sh_eth_write(ndev, 0, CNDCR);   /* (write clear) */
+       }
+
+       return &ndev->stats;
+}
+
 /* device close function */
 static int sh_eth_close(struct net_device *ndev)
 {
@@ -2145,6 +2171,7 @@ static int sh_eth_close(struct net_device *ndev)
        sh_eth_write(ndev, 0, EDTRR);
        sh_eth_write(ndev, 0, EDRRR);
 
+       sh_eth_get_stats(ndev);
        /* PHY Disconnect */
        if (mdp->phydev) {
                phy_stop(mdp->phydev);
@@ -2163,36 +2190,9 @@ static int sh_eth_close(struct net_device *ndev)
 
        pm_runtime_put_sync(&mdp->pdev->dev);
 
-       return 0;
-}
-
-static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
-{
-       struct sh_eth_private *mdp = netdev_priv(ndev);
-
-       if (sh_eth_is_rz_fast_ether(mdp))
-               return &ndev->stats;
+       mdp->is_opened = 0;
 
-       pm_runtime_get_sync(&mdp->pdev->dev);
-
-       ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
-       sh_eth_write(ndev, 0, TROCR);   /* (write clear) */
-       ndev->stats.collisions += sh_eth_read(ndev, CDCR);
-       sh_eth_write(ndev, 0, CDCR);    /* (write clear) */
-       ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
-       sh_eth_write(ndev, 0, LCCR);    /* (write clear) */
-       if (sh_eth_is_gether(mdp)) {
-               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
-               sh_eth_write(ndev, 0, CERCR);   /* (write clear) */
-               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
-               sh_eth_write(ndev, 0, CEECR);   /* (write clear) */
-       } else {
-               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
-               sh_eth_write(ndev, 0, CNDCR);   /* (write clear) */
-       }
-       pm_runtime_put_sync(&mdp->pdev->dev);
-
-       return &ndev->stats;
+       return 0;
 }
 
 /* ioctl to device function */
index b37c427144ee0a1010794ff2beff42bc298fd1e9..22301bf9c21daeb925d75aa7ce5c7a588d977e11 100644 (file)
@@ -162,9 +162,9 @@ enum {
 
 /* Driver's parameters */
 #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
-#define SH4_SKB_RX_ALIGN       32
+#define SH_ETH_RX_ALIGN                32
 #else
-#define SH2_SH3_SKB_RX_ALIGN   2
+#define SH_ETH_RX_ALIGN                2
 #endif
 
 /* Register's bits
@@ -522,6 +522,7 @@ struct sh_eth_private {
 
        unsigned no_ether_link:1;
        unsigned ether_link_active_low:1;
+       unsigned is_opened:1;
 };
 
 static inline void sh_eth_soft_swap(char *src, int len)
index 002d4cdc319fda80a064c7cea199e1bf417d479c..a77f05ce832596d0c8eb10ef3a9735f48ba64b55 100644 (file)
@@ -180,7 +180,8 @@ static int efx_ef10_probe(struct efx_nic *efx)
                      EFX_MAX_CHANNELS,
                      resource_size(&efx->pci_dev->resource[EFX_MEM_BAR]) /
                      (EFX_VI_PAGE_SIZE * EFX_TXQ_TYPES));
-       BUG_ON(efx->max_channels == 0);
+       if (WARN_ON(efx->max_channels == 0))
+               return -EIO;
 
        nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
        if (!nic_data)
index ee84a90e371c5dedf2fa5b0b31ba520d8611c85b..aaf2987512b5db7472bdef518c4aa4c510612ef7 100644 (file)
@@ -343,8 +343,6 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
        unsigned short dma_flags;
        int i = 0;
 
-       EFX_BUG_ON_PARANOID(tx_queue->write_count > tx_queue->insert_count);
-
        if (skb_shinfo(skb)->gso_size)
                return efx_enqueue_skb_tso(tx_queue, skb);
 
@@ -1258,8 +1256,6 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
        /* Find the packet protocol and sanity-check it */
        state.protocol = efx_tso_check_protocol(skb);
 
-       EFX_BUG_ON_PARANOID(tx_queue->write_count > tx_queue->insert_count);
-
        rc = tso_start(&state, efx, skb);
        if (rc)
                goto mem_err;
index 5e94d00b96b301d9dc9cd09a17943520b96e8b52..6cc3cf6f17c846cdcf900d47f17b40749dfb5966 100644 (file)
@@ -81,6 +81,7 @@ static const char version[] =
 #include <linux/workqueue.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2188,6 +2189,41 @@ static const struct of_device_id smc91x_match[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, smc91x_match);
+
+/**
+ * of_try_set_control_gpio - configure a gpio if it exists
+ */
+static int try_toggle_control_gpio(struct device *dev,
+                                  struct gpio_desc **desc,
+                                  const char *name, int index,
+                                  int value, unsigned int nsdelay)
+{
+       struct gpio_desc *gpio = *desc;
+       int res;
+
+       gpio = devm_gpiod_get_index(dev, name, index);
+       if (IS_ERR(gpio)) {
+               if (PTR_ERR(gpio) == -ENOENT) {
+                       *desc = NULL;
+                       return 0;
+               }
+
+               return PTR_ERR(gpio);
+       }
+       res = gpiod_direction_output(gpio, !value);
+       if (res) {
+               dev_err(dev, "unable to toggle gpio %s: %i\n", name, res);
+               devm_gpiod_put(dev, gpio);
+               gpio = NULL;
+               return res;
+       }
+       if (nsdelay)
+               usleep_range(nsdelay, 2 * nsdelay);
+       gpiod_set_value_cansleep(gpio, value);
+       *desc = gpio;
+
+       return 0;
+}
 #endif
 
 /*
@@ -2207,9 +2243,10 @@ static int smc_drv_probe(struct platform_device *pdev)
        const struct of_device_id *match = NULL;
        struct smc_local *lp;
        struct net_device *ndev;
-       struct resource *res, *ires;
+       struct resource *res;
        unsigned int __iomem *addr;
        unsigned long irq_flags = SMC_IRQ_FLAGS;
+       unsigned long irq_resflags;
        int ret;
 
        ndev = alloc_etherdev(sizeof(struct smc_local));
@@ -2237,6 +2274,28 @@ static int smc_drv_probe(struct platform_device *pdev)
                struct device_node *np = pdev->dev.of_node;
                u32 val;
 
+               /* Optional pwrdwn GPIO configured? */
+               ret = try_toggle_control_gpio(&pdev->dev, &lp->power_gpio,
+                                             "power", 0, 0, 100);
+               if (ret)
+                       return ret;
+
+               /*
+                * Optional reset GPIO configured? Minimum 100 ns reset needed
+                * according to LAN91C96 datasheet page 14.
+                */
+               ret = try_toggle_control_gpio(&pdev->dev, &lp->reset_gpio,
+                                             "reset", 0, 0, 100);
+               if (ret)
+                       return ret;
+
+               /*
+                * Need to wait for optional EEPROM to load, max 750 us according
+                * to LAN91C96 datasheet page 55.
+                */
+               if (lp->reset_gpio)
+                       usleep_range(750, 1000);
+
                /* Combination of IO widths supported, default to 16-bit */
                if (!of_property_read_u32(np, "reg-io-width", &val)) {
                        if (val & 1)
@@ -2279,16 +2338,19 @@ static int smc_drv_probe(struct platform_device *pdev)
                goto out_free_netdev;
        }
 
-       ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!ires) {
+       ndev->irq = platform_get_irq(pdev, 0);
+       if (ndev->irq <= 0) {
                ret = -ENODEV;
                goto out_release_io;
        }
-
-       ndev->irq = ires->start;
-
-       if (irq_flags == -1 || ires->flags & IRQF_TRIGGER_MASK)
-               irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+       /*
+        * If this platform does not specify any special irqflags, or if
+        * the resource supplies a trigger, override the irqflags with
+        * the trigger flags from the resource.
+        */
+       irq_resflags = irqd_get_trigger_type(irq_get_irq_data(ndev->irq));
+       if (irq_flags == -1 || irq_resflags & IRQF_TRIGGER_MASK)
+               irq_flags = irq_resflags & IRQF_TRIGGER_MASK;
 
        ret = smc_request_attrib(pdev, ndev);
        if (ret)
index 47dce918eb0f49741a9dec7ae3cee68354fb7a0a..2a38dacbbd27fba4f153790117cb10102dadd6e6 100644 (file)
@@ -298,6 +298,9 @@ struct smc_local {
        struct sk_buff *pending_tx_skb;
        struct tasklet_struct tx_task;
 
+       struct gpio_desc *power_gpio;
+       struct gpio_desc *reset_gpio;
+
        /* version/revision of the SMC91x chip */
        int     version;
 
index affb29da353e29139fb758c5a5ce68b701479815..77ed74561e5fe815de9c7efdd1477404d3591b81 100644 (file)
@@ -1342,6 +1342,42 @@ static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata)
        spin_unlock(&pdata->mac_lock);
 }
 
+static int smsc911x_phy_general_power_up(struct smsc911x_data *pdata)
+{
+       int rc = 0;
+
+       if (!pdata->phy_dev)
+               return rc;
+
+       /* If the internal PHY is in General Power-Down mode, all, except the
+        * management interface, is powered-down and stays in that condition as
+        * long as Phy register bit 0.11 is HIGH.
+        *
+        * In that case, clear the bit 0.11, so the PHY powers up and we can
+        * access to the phy registers.
+        */
+       rc = phy_read(pdata->phy_dev, MII_BMCR);
+       if (rc < 0) {
+               SMSC_WARN(pdata, drv, "Failed reading PHY control reg");
+               return rc;
+       }
+
+       /* If the PHY general power-down bit is not set is not necessary to
+        * disable the general power down-mode.
+        */
+       if (rc & BMCR_PDOWN) {
+               rc = phy_write(pdata->phy_dev, MII_BMCR, rc & ~BMCR_PDOWN);
+               if (rc < 0) {
+                       SMSC_WARN(pdata, drv, "Failed writing PHY control reg");
+                       return rc;
+               }
+
+               usleep_range(1000, 1500);
+       }
+
+       return 0;
+}
+
 static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata)
 {
        int rc = 0;
@@ -1356,12 +1392,8 @@ static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata)
                return rc;
        }
 
-       /*
-        * If energy is detected the PHY is already awake so is not necessary
-        * to disable the energy detect power-down mode.
-        */
-       if ((rc & MII_LAN83C185_EDPWRDOWN) &&
-           !(rc & MII_LAN83C185_ENERGYON)) {
+       /* Only disable if energy detect mode is already enabled */
+       if (rc & MII_LAN83C185_EDPWRDOWN) {
                /* Disable energy detect mode for this SMSC Transceivers */
                rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS,
                               rc & (~MII_LAN83C185_EDPWRDOWN));
@@ -1370,8 +1402,8 @@ static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata)
                        SMSC_WARN(pdata, drv, "Failed writing PHY control reg");
                        return rc;
                }
-
-               mdelay(1);
+               /* Allow PHY to wakeup */
+               mdelay(2);
        }
 
        return 0;
@@ -1393,7 +1425,6 @@ static int smsc911x_phy_enable_energy_detect(struct smsc911x_data *pdata)
 
        /* Only enable if energy detect mode is already disabled */
        if (!(rc & MII_LAN83C185_EDPWRDOWN)) {
-               mdelay(100);
                /* Enable energy detect mode for this SMSC Transceivers */
                rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS,
                               rc | MII_LAN83C185_EDPWRDOWN);
@@ -1402,8 +1433,6 @@ static int smsc911x_phy_enable_energy_detect(struct smsc911x_data *pdata)
                        SMSC_WARN(pdata, drv, "Failed writing PHY control reg");
                        return rc;
                }
-
-               mdelay(1);
        }
        return 0;
 }
@@ -1414,6 +1443,16 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata)
        unsigned int temp;
        int ret;
 
+       /*
+        * Make sure to power-up the PHY chip before doing a reset, otherwise
+        * the reset fails.
+        */
+       ret = smsc911x_phy_general_power_up(pdata);
+       if (ret) {
+               SMSC_WARN(pdata, drv, "Failed to power-up the PHY chip");
+               return ret;
+       }
+
        /*
         * LAN9210/LAN9211/LAN9220/LAN9221 chips have an internal PHY that
         * are initialized in a Energy Detect Power-Down mode that prevents
index 6f77a46c7e2c446da3b3b4ae139057a621ef00ef..18c46bb0f3bfa296096ab2ec6624a4bd27bd304f 100644 (file)
@@ -276,6 +276,7 @@ static void stmmac_eee_ctrl_timer(unsigned long arg)
 bool stmmac_eee_init(struct stmmac_priv *priv)
 {
        char *phy_bus_name = priv->plat->phy_bus_name;
+       unsigned long flags;
        bool ret = false;
 
        /* Using PCS we cannot dial with the phy registers at this stage
@@ -300,6 +301,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                         * changed).
                         * In that case the driver disable own timers.
                         */
+                       spin_lock_irqsave(&priv->lock, flags);
                        if (priv->eee_active) {
                                pr_debug("stmmac: disable EEE\n");
                                del_timer_sync(&priv->eee_ctrl_timer);
@@ -307,9 +309,11 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                                                             tx_lpi_timer);
                        }
                        priv->eee_active = 0;
+                       spin_unlock_irqrestore(&priv->lock, flags);
                        goto out;
                }
                /* Activate the EEE and start timers */
+               spin_lock_irqsave(&priv->lock, flags);
                if (!priv->eee_active) {
                        priv->eee_active = 1;
                        init_timer(&priv->eee_ctrl_timer);
@@ -325,9 +329,10 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                /* Set HW EEE according to the speed */
                priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
 
-               pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
-
                ret = true;
+               spin_unlock_irqrestore(&priv->lock, flags);
+
+               pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
        }
 out:
        return ret;
@@ -760,12 +765,12 @@ static void stmmac_adjust_link(struct net_device *dev)
        if (new_state && netif_msg_link(priv))
                phy_print_status(phydev);
 
+       spin_unlock_irqrestore(&priv->lock, flags);
+
        /* At this stage, it could be needed to setup the EEE or adjust some
         * MAC related HW registers.
         */
        priv->eee_enabled = stmmac_eee_init(priv);
-
-       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 /**
@@ -959,12 +964,12 @@ static void stmmac_clear_descriptors(struct stmmac_priv *priv)
 }
 
 static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
-                                 int i)
+                                 int i, gfp_t flags)
 {
        struct sk_buff *skb;
 
        skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
-                                GFP_KERNEL);
+                                flags);
        if (!skb) {
                pr_err("%s: Rx init fails; skb is NULL\n", __func__);
                return -ENOMEM;
@@ -1006,7 +1011,7 @@ static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
  * and allocates the socket buffers. It suppors the chained and ring
  * modes.
  */
-static int init_dma_desc_rings(struct net_device *dev)
+static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
 {
        int i;
        struct stmmac_priv *priv = netdev_priv(dev);
@@ -1041,7 +1046,7 @@ static int init_dma_desc_rings(struct net_device *dev)
                else
                        p = priv->dma_rx + i;
 
-               ret = stmmac_init_rx_buffers(priv, p, i);
+               ret = stmmac_init_rx_buffers(priv, p, i, flags);
                if (ret)
                        goto err_init_rx_buffers;
 
@@ -1647,11 +1652,6 @@ static int stmmac_hw_setup(struct net_device *dev)
        struct stmmac_priv *priv = netdev_priv(dev);
        int ret;
 
-       ret = init_dma_desc_rings(dev);
-       if (ret < 0) {
-               pr_err("%s: DMA descriptors initialization failed\n", __func__);
-               return ret;
-       }
        /* DMA initialization and SW reset */
        ret = stmmac_init_dma_engine(priv);
        if (ret < 0) {
@@ -1705,10 +1705,6 @@ static int stmmac_hw_setup(struct net_device *dev)
        }
        priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
 
-       priv->eee_enabled = stmmac_eee_init(priv);
-
-       stmmac_init_tx_coalesce(priv);
-
        if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
                priv->rx_riwt = MAX_DMA_RIWT;
                priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
@@ -1761,12 +1757,20 @@ static int stmmac_open(struct net_device *dev)
                goto dma_desc_error;
        }
 
+       ret = init_dma_desc_rings(dev, GFP_KERNEL);
+       if (ret < 0) {
+               pr_err("%s: DMA descriptors initialization failed\n", __func__);
+               goto init_error;
+       }
+
        ret = stmmac_hw_setup(dev);
        if (ret < 0) {
                pr_err("%s: Hw setup failed\n", __func__);
                goto init_error;
        }
 
+       stmmac_init_tx_coalesce(priv);
+
        if (priv->phydev)
                phy_start(priv->phydev);
 
@@ -1894,7 +1898,10 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        unsigned int nopaged_len = skb_headlen(skb);
        unsigned int enh_desc = priv->plat->enh_desc;
 
+       spin_lock(&priv->tx_lock);
+
        if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
+               spin_unlock(&priv->tx_lock);
                if (!netif_queue_stopped(dev)) {
                        netif_stop_queue(dev);
                        /* This is a hard error, log it. */
@@ -1903,8 +1910,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       spin_lock(&priv->tx_lock);
-
        if (priv->tx_path_in_lpi_mode)
                stmmac_disable_eee_mode(priv);
 
@@ -2025,6 +2030,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 
 dma_map_err:
+       spin_unlock(&priv->tx_lock);
        dev_err(priv->device, "Tx dma map failed\n");
        dev_kfree_skb(skb);
        priv->dev->stats.tx_dropped++;
@@ -2281,9 +2287,7 @@ static void stmmac_set_rx_mode(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       spin_lock(&priv->lock);
        priv->hw->mac->set_filter(priv->hw, dev);
-       spin_unlock(&priv->lock);
 }
 
 /**
@@ -2950,7 +2954,7 @@ int stmmac_suspend(struct net_device *ndev)
                stmmac_set_mac(priv->ioaddr, false);
                pinctrl_pm_select_sleep_state(priv->device);
                /* Disable clock in case of PWM is off */
-               clk_disable_unprepare(priv->stmmac_clk);
+               clk_disable(priv->stmmac_clk);
        }
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -2982,7 +2986,7 @@ int stmmac_resume(struct net_device *ndev)
        } else {
                pinctrl_pm_select_default_state(priv->device);
                /* enable the clk prevously disabled */
-               clk_prepare_enable(priv->stmmac_clk);
+               clk_enable(priv->stmmac_clk);
                /* reset the phy so that it's ready */
                if (priv->mii)
                        stmmac_mdio_reset(priv->mii);
@@ -2990,7 +2994,9 @@ int stmmac_resume(struct net_device *ndev)
 
        netif_device_attach(ndev);
 
+       init_dma_desc_rings(ndev, GFP_ATOMIC);
        stmmac_hw_setup(ndev);
+       stmmac_init_tx_coalesce(priv);
 
        napi_enable(&priv->napi);
 
index 655a23bbc45113595be3c049a05003382a6de049..e17a970eaf2b87a1ff184270835102a85fa5f1f4 100644 (file)
@@ -33,6 +33,7 @@ static struct stmmac_dma_cfg dma_cfg;
 static void stmmac_default_data(void)
 {
        memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
+
        plat_dat.bus_id = 1;
        plat_dat.phy_addr = 0;
        plat_dat.interface = PHY_INTERFACE_MODE_GMII;
@@ -47,6 +48,12 @@ static void stmmac_default_data(void)
        dma_cfg.pbl = 32;
        dma_cfg.burst_len = DMA_AXI_BLEN_256;
        plat_dat.dma_cfg = &dma_cfg;
+
+       /* Set default value for multicast hash bins */
+       plat_dat.multicast_filter_bins = HASH_TABLE_SIZE;
+
+       /* Set default value for unicast filter entries */
+       plat_dat.unicast_filter_entries = 1;
 }
 
 /**
index db56fa7ce8f91ae816b4733c501f60504c2ae228..58a1a0a423d494e2ce4fcc0861a02ff97e9077dc 100644 (file)
@@ -177,12 +177,6 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
         */
        plat->maxmtu = JUMBO_LEN;
 
-       /* Set default value for multicast hash bins */
-       plat->multicast_filter_bins = HASH_TABLE_SIZE;
-
-       /* Set default value for unicast filter entries */
-       plat->unicast_filter_entries = 1;
-
        /*
         * Currently only the properties needed on SPEAr600
         * are provided. All other properties should be added
@@ -270,16 +264,23 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
                return PTR_ERR(addr);
 
        plat_dat = dev_get_platdata(&pdev->dev);
-       if (pdev->dev.of_node) {
-               if (!plat_dat)
-                       plat_dat = devm_kzalloc(&pdev->dev,
+
+       if (!plat_dat)
+               plat_dat = devm_kzalloc(&pdev->dev,
                                        sizeof(struct plat_stmmacenet_data),
                                        GFP_KERNEL);
-               if (!plat_dat) {
-                       pr_err("%s: ERROR: no memory", __func__);
-                       return  -ENOMEM;
-               }
+       if (!plat_dat) {
+               pr_err("%s: ERROR: no memory", __func__);
+               return  -ENOMEM;
+       }
+
+       /* Set default value for multicast hash bins */
+       plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
 
+       /* Set default value for unicast filter entries */
+       plat_dat->unicast_filter_entries = 1;
+
+       if (pdev->dev.of_node) {
                ret = stmmac_probe_config_dt(pdev, plat_dat, &mac);
                if (ret) {
                        pr_err("%s: main dt probe failed", __func__);
index 72c8525d5457b40af75c5c15d6b4bd1432185543..9c014803b03b2338ad2f97fd31794966cfc02b66 100644 (file)
@@ -1262,6 +1262,7 @@ static void happy_meal_init_rings(struct happy_meal *hp)
        HMD(("init rxring, "));
        for (i = 0; i < RX_RING_SIZE; i++) {
                struct sk_buff *skb;
+               u32 mapping;
 
                skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC);
                if (!skb) {
@@ -1272,10 +1273,16 @@ static void happy_meal_init_rings(struct happy_meal *hp)
 
                /* Because we reserve afterwards. */
                skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
+               mapping = dma_map_single(hp->dma_dev, skb->data, RX_BUF_ALLOC_SIZE,
+                                        DMA_FROM_DEVICE);
+               if (dma_mapping_error(hp->dma_dev, mapping)) {
+                       dev_kfree_skb_any(skb);
+                       hme_write_rxd(hp, &hb->happy_meal_rxd[i], 0, 0);
+                       continue;
+               }
                hme_write_rxd(hp, &hb->happy_meal_rxd[i],
                              (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)),
-                             dma_map_single(hp->dma_dev, skb->data, RX_BUF_ALLOC_SIZE,
-                                            DMA_FROM_DEVICE));
+                             mapping);
                skb_reserve(skb, RX_OFFSET);
        }
 
@@ -2020,6 +2027,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
                skb = hp->rx_skbs[elem];
                if (len > RX_COPY_THRESHOLD) {
                        struct sk_buff *new_skb;
+                       u32 mapping;
 
                        /* Now refill the entry, if we can. */
                        new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC);
@@ -2027,13 +2035,21 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
                                drops++;
                                goto drop_it;
                        }
+                       skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
+                       mapping = dma_map_single(hp->dma_dev, new_skb->data,
+                                                RX_BUF_ALLOC_SIZE,
+                                                DMA_FROM_DEVICE);
+                       if (unlikely(dma_mapping_error(hp->dma_dev, mapping))) {
+                               dev_kfree_skb_any(new_skb);
+                               drops++;
+                               goto drop_it;
+                       }
+
                        dma_unmap_single(hp->dma_dev, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE);
                        hp->rx_skbs[elem] = new_skb;
-                       skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4));
                        hme_write_rxd(hp, this,
                                      (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
-                                     dma_map_single(hp->dma_dev, new_skb->data, RX_BUF_ALLOC_SIZE,
-                                                    DMA_FROM_DEVICE));
+                                     mapping);
                        skb_reserve(new_skb, RX_OFFSET);
 
                        /* Trim the original skb for the netif. */
@@ -2248,6 +2264,25 @@ static void happy_meal_tx_timeout(struct net_device *dev)
        netif_wake_queue(dev);
 }
 
+static void unmap_partial_tx_skb(struct happy_meal *hp, u32 first_mapping,
+                                u32 first_len, u32 first_entry, u32 entry)
+{
+       struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0];
+
+       dma_unmap_single(hp->dma_dev, first_mapping, first_len, DMA_TO_DEVICE);
+
+       first_entry = NEXT_TX(first_entry);
+       while (first_entry != entry) {
+               struct happy_meal_txd *this = &txbase[first_entry];
+               u32 addr, len;
+
+               addr = hme_read_desc32(hp, &this->tx_addr);
+               len = hme_read_desc32(hp, &this->tx_flags);
+               len &= TXFLAG_SIZE;
+               dma_unmap_page(hp->dma_dev, addr, len, DMA_TO_DEVICE);
+       }
+}
+
 static netdev_tx_t happy_meal_start_xmit(struct sk_buff *skb,
                                         struct net_device *dev)
 {
@@ -2284,6 +2319,8 @@ static netdev_tx_t happy_meal_start_xmit(struct sk_buff *skb,
 
                len = skb->len;
                mapping = dma_map_single(hp->dma_dev, skb->data, len, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(hp->dma_dev, mapping)))
+                       goto out_dma_error;
                tx_flags |= (TXFLAG_SOP | TXFLAG_EOP);
                hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry],
                              (tx_flags | (len & TXFLAG_SIZE)),
@@ -2299,6 +2336,8 @@ static netdev_tx_t happy_meal_start_xmit(struct sk_buff *skb,
                first_len = skb_headlen(skb);
                first_mapping = dma_map_single(hp->dma_dev, skb->data, first_len,
                                               DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(hp->dma_dev, first_mapping)))
+                       goto out_dma_error;
                entry = NEXT_TX(entry);
 
                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -2308,6 +2347,11 @@ static netdev_tx_t happy_meal_start_xmit(struct sk_buff *skb,
                        len = skb_frag_size(this_frag);
                        mapping = skb_frag_dma_map(hp->dma_dev, this_frag,
                                                   0, len, DMA_TO_DEVICE);
+                       if (unlikely(dma_mapping_error(hp->dma_dev, mapping))) {
+                               unmap_partial_tx_skb(hp, first_mapping, first_len,
+                                                    first_entry, entry);
+                               goto out_dma_error;
+                       }
                        this_txflags = tx_flags;
                        if (frag == skb_shinfo(skb)->nr_frags - 1)
                                this_txflags |= TXFLAG_EOP;
@@ -2333,6 +2377,14 @@ static netdev_tx_t happy_meal_start_xmit(struct sk_buff *skb,
 
        tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
        return NETDEV_TX_OK;
+
+out_dma_error:
+       hp->tx_skbs[hp->tx_new] = NULL;
+       spin_unlock_irq(&hp->happy_lock);
+
+       dev_kfree_skb_any(skb);
+       dev->stats.tx_dropped++;
+       return NETDEV_TX_OK;
 }
 
 static struct net_device_stats *happy_meal_get_stats(struct net_device *dev)
index 952e1e4764b74d64688875815b25dc90316f3214..c560f9aeb55d691f23c65dae362c18defa1e9e44 100644 (file)
@@ -129,9 +129,9 @@ do {                                                                \
 #define CPSW_VLAN_AWARE                BIT(1)
 #define CPSW_ALE_VLAN_AWARE    1
 
-#define CPSW_FIFO_NORMAL_MODE          (0 << 15)
-#define CPSW_FIFO_DUAL_MAC_MODE                (1 << 15)
-#define CPSW_FIFO_RATE_LIMIT_MODE      (2 << 15)
+#define CPSW_FIFO_NORMAL_MODE          (0 << 16)
+#define CPSW_FIFO_DUAL_MAC_MODE                (1 << 16)
+#define CPSW_FIFO_RATE_LIMIT_MODE      (2 << 16)
 
 #define CPSW_INTPACEEN         (0x3f << 16)
 #define CPSW_INTPRESCALE_MASK  (0x7FF << 0)
@@ -591,8 +591,8 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                if (enable) {
                        unsigned long timeout = jiffies + HZ;
 
-                       /* Disable Learn for all ports */
-                       for (i = 0; i < priv->data.slaves; i++) {
+                       /* Disable Learn for all ports (host is port 0 and slaves are port 1 and up */
+                       for (i = 0; i <= priv->data.slaves; i++) {
                                cpsw_ale_control_set(ale, i,
                                                     ALE_PORT_NOLEARN, 1);
                                cpsw_ale_control_set(ale, i,
@@ -616,11 +616,11 @@ static void cpsw_set_promiscious(struct net_device *ndev, bool enable)
                        cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 1);
                        dev_dbg(&ndev->dev, "promiscuity enabled\n");
                } else {
-                       /* Flood All Unicast Packets to Host port */
+                       /* Don't Flood All Unicast Packets to Host port */
                        cpsw_ale_control_set(ale, 0, ALE_P0_UNI_FLOOD, 0);
 
-                       /* Enable Learn for all ports */
-                       for (i = 0; i < priv->data.slaves; i++) {
+                       /* Enable Learn for all ports (host is port 0 and slaves are port 1 and up */
+                       for (i = 0; i <= priv->data.slaves; i++) {
                                cpsw_ale_control_set(ale, i,
                                                     ALE_PORT_NOLEARN, 0);
                                cpsw_ale_control_set(ale, i,
@@ -638,12 +638,16 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
        if (ndev->flags & IFF_PROMISC) {
                /* Enable promiscuous mode */
                cpsw_set_promiscious(ndev, true);
+               cpsw_ale_set_allmulti(priv->ale, IFF_ALLMULTI);
                return;
        } else {
                /* Disable promiscuous mode */
                cpsw_set_promiscious(ndev, false);
        }
 
+       /* Restore allmulti on vlans if necessary */
+       cpsw_ale_set_allmulti(priv->ale, priv->ndev->flags & IFF_ALLMULTI);
+
        /* Clear all mcast from ALE */
        cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port);
 
@@ -1149,6 +1153,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
        const int port = priv->host_port;
        u32 reg;
        int i;
+       int unreg_mcast_mask;
 
        reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
               CPSW2_PORT_VLAN;
@@ -1158,9 +1163,14 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
        for (i = 0; i < priv->data.slaves; i++)
                slave_write(priv->slaves + i, vlan, reg);
 
+       if (priv->ndev->flags & IFF_ALLMULTI)
+               unreg_mcast_mask = ALE_ALL_PORTS;
+       else
+               unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
+
        cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
                          ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
-                         (ALE_PORT_1 | ALE_PORT_2) << port);
+                         unreg_mcast_mask << port);
 }
 
 static void cpsw_init_host_port(struct cpsw_priv *priv)
@@ -1620,11 +1630,17 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
                                unsigned short vid)
 {
        int ret;
+       int unreg_mcast_mask;
+
+       if (priv->ndev->flags & IFF_ALLMULTI)
+               unreg_mcast_mask = ALE_ALL_PORTS;
+       else
+               unreg_mcast_mask = ALE_PORT_1 | ALE_PORT_2;
 
        ret = cpsw_ale_add_vlan(priv->ale, vid,
                                ALE_ALL_PORTS << priv->host_port,
                                0, ALE_ALL_PORTS << priv->host_port,
-                               (ALE_PORT_1 | ALE_PORT_2) << priv->host_port);
+                               unreg_mcast_mask << priv->host_port);
        if (ret != 0)
                return ret;
 
@@ -2006,7 +2022,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                parp = of_get_property(slave_node, "phy_id", &lenp);
                if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
                        dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i);
-                       return -EINVAL;
+                       goto no_phy_slave;
                }
                mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
                phyid = be32_to_cpup(parp+1);
@@ -2019,6 +2035,14 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
                         PHY_ID_FMT, mdio->name, phyid);
 
+               slave_data->phy_if = of_get_phy_mode(slave_node);
+               if (slave_data->phy_if < 0) {
+                       dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
+                               i);
+                       return slave_data->phy_if;
+               }
+
+no_phy_slave:
                mac_addr = of_get_mac_address(slave_node);
                if (mac_addr) {
                        memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
@@ -2030,14 +2054,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                                        return ret;
                        }
                }
-
-               slave_data->phy_if = of_get_phy_mode(slave_node);
-               if (slave_data->phy_if < 0) {
-                       dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
-                               i);
-                       return slave_data->phy_if;
-               }
-
                if (data->dual_emac) {
                        if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
                                                 &prop)) {
index 0579b2243bb6d7fdfb20e27b761fbdf1d33b00b6..097ebe7077ac0c8de51e3eb7e8da5809f5e6bcea 100644 (file)
@@ -443,6 +443,35 @@ int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
        return 0;
 }
 
+void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti)
+{
+       u32 ale_entry[ALE_ENTRY_WORDS];
+       int type, idx;
+       int unreg_mcast = 0;
+
+       /* Only bother doing the work if the setting is actually changing */
+       if (ale->allmulti == allmulti)
+               return;
+
+       /* Remember the new setting to check against next time */
+       ale->allmulti = allmulti;
+
+       for (idx = 0; idx < ale->params.ale_entries; idx++) {
+               cpsw_ale_read(ale, idx, ale_entry);
+               type = cpsw_ale_get_entry_type(ale_entry);
+               if (type != ALE_TYPE_VLAN)
+                       continue;
+
+               unreg_mcast = cpsw_ale_get_vlan_unreg_mcast(ale_entry);
+               if (allmulti)
+                       unreg_mcast |= 1;
+               else
+                       unreg_mcast &= ~1;
+               cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
+               cpsw_ale_write(ale, idx, ale_entry);
+       }
+}
+
 struct ale_control_info {
        const char      *name;
        int             offset, port_offset;
@@ -756,7 +785,6 @@ int cpsw_ale_destroy(struct cpsw_ale *ale)
 {
        if (!ale)
                return -EINVAL;
-       cpsw_ale_stop(ale);
        cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
        kfree(ale);
        return 0;
index 31cf43cab42ee7ba70b6948593bc93cf28c5a6e7..c0d4127aa549285c7e50e47214c1579e17478210 100644 (file)
@@ -27,6 +27,7 @@ struct cpsw_ale {
        struct cpsw_ale_params  params;
        struct timer_list       timer;
        unsigned long           ageout;
+       int                     allmulti;
 };
 
 enum cpsw_ale_control {
@@ -103,6 +104,7 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
 int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
                        int reg_mcast, int unreg_mcast);
 int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
+void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti);
 
 int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
 int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
index ab92f67da035f2f5f9aaa8ea4effa87ca83a2a41..4a4388b813ac6b2392917da20f873ceb34297e39 100644 (file)
@@ -264,7 +264,7 @@ static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
 
        switch (ptp_class & PTP_CLASS_PMASK) {
        case PTP_CLASS_IPV4:
-               offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+               offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
                break;
        case PTP_CLASS_IPV6:
                offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
index 9e17d1a91e7193fb3cf566b468abdd4386889495..78ec33f5100b183e31bfc949763acfa4685b9836 100644 (file)
@@ -550,6 +550,7 @@ do_lso:
 do_send:
        /* Start filling in the page buffers with the rndis hdr */
        rndis_msg->msg_len += rndis_msg_size;
+       packet->total_data_buflen = rndis_msg->msg_len;
        packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size,
                                        skb, &packet->page_buf[0]);
 
index 9ce854f43917ad723da924e7a99e3629c6a6e9bd..6cbc56ad9ff49256fa218e87c031c5c9f371d17a 100644 (file)
@@ -377,17 +377,20 @@ static int ieee802154fake_probe(struct platform_device *pdev)
 
        err = wpan_phy_register(phy);
        if (err)
-               goto out;
+               goto err_phy_reg;
 
        err = register_netdev(dev);
-       if (err < 0)
-               goto out;
+       if (err)
+               goto err_netdev_reg;
 
        dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n");
        return 0;
 
-out:
-       unregister_netdev(dev);
+err_netdev_reg:
+       wpan_phy_unregister(phy);
+err_phy_reg:
+       free_netdev(dev);
+       wpan_phy_free(phy);
        return err;
 }
 
index 29b3bb410781c2530a41ae689b8a91d51e1de3ef..bfb0b6ec8c56e26d67fa94814fe460af34c95fed 100644 (file)
@@ -272,7 +272,7 @@ static void macvlan_process_broadcast(struct work_struct *w)
        struct sk_buff *skb;
        struct sk_buff_head list;
 
-       skb_queue_head_init(&list);
+       __skb_queue_head_init(&list);
 
        spin_lock_bh(&port->bc_queue.lock);
        skb_queue_splice_tail_init(&port->bc_queue, &list);
@@ -1082,9 +1082,15 @@ static void macvlan_port_destroy(struct net_device *dev)
 {
        struct macvlan_port *port = macvlan_port_get_rtnl(dev);
 
-       cancel_work_sync(&port->bc_work);
        dev->priv_flags &= ~IFF_MACVLAN_PORT;
        netdev_rx_handler_unregister(dev);
+
+       /* After this point, no packet can schedule bc_work anymore,
+        * but we need to cancel it and purge left skbs if any.
+        */
+       cancel_work_sync(&port->bc_work);
+       __skb_queue_purge(&port->bc_queue);
+
        kfree_rcu(port, rcu);
 }
 
index 65e2892342bd0cdf31a6c790e3344dc1a4f12816..880cc090dc44ecb0167682e951bedff7753aef94 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/idr.h>
 #include <linux/fs.h>
 
+#include <net/ipv6.h>
 #include <net/net_namespace.h>
 #include <net/rtnetlink.h>
 #include <net/sock.h>
@@ -65,7 +66,7 @@ static struct cdev macvtap_cdev;
 static const struct proto_ops macvtap_socket_ops;
 
 #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
-                     NETIF_F_TSO6 | NETIF_F_UFO)
+                     NETIF_F_TSO6)
 #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
 #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
 
@@ -569,7 +570,11 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb,
                        gso_type = SKB_GSO_TCPV6;
                        break;
                case VIRTIO_NET_HDR_GSO_UDP:
+                       pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n",
+                                    current->comm);
                        gso_type = SKB_GSO_UDP;
+                       if (skb->protocol == htons(ETH_P_IPV6))
+                               ipv6_proxy_select_ident(skb);
                        break;
                default:
                        return -EINVAL;
@@ -614,8 +619,6 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
                        vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
                else if (sinfo->gso_type & SKB_GSO_TCPV6)
                        vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
-               else if (sinfo->gso_type & SKB_GSO_UDP)
-                       vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
                else
                        BUG();
                if (sinfo->gso_type & SKB_GSO_TCP_ECN)
@@ -626,6 +629,8 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
                vnet_hdr->csum_start = skb_checksum_start_offset(skb);
+               if (vlan_tx_tag_present(skb))
+                       vnet_hdr->csum_start += VLAN_HLEN;
                vnet_hdr->csum_offset = skb->csum_offset;
        } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
                vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
@@ -950,9 +955,6 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
                        if (arg & TUN_F_TSO6)
                                feature_mask |= NETIF_F_TSO6;
                }
-
-               if (arg & TUN_F_UFO)
-                       feature_mask |= NETIF_F_UFO;
        }
 
        /* tun/tap driver inverts the usage for TSO offloads, where
@@ -963,7 +965,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
         * When user space turns off TSO, we turn off GSO/LRO so that
         * user-space will not receive TSO frames.
         */
-       if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO))
+       if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
                features |= RX_OFFLOADS;
        else
                features &= ~RX_OFFLOADS;
@@ -1064,7 +1066,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
        case TUNSETOFFLOAD:
                /* let the user check for future flags */
                if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
-                           TUN_F_TSO_ECN | TUN_F_UFO))
+                           TUN_F_TSO_ECN))
                        return -EINVAL;
 
                rtnl_lock();
index 2954052706e8bcbf0979e89772326656ba6c57fa..e22e602beef3426a600db641a66237f40c039732 100644 (file)
@@ -791,7 +791,7 @@ static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
 
        switch (type & PTP_CLASS_PMASK) {
        case PTP_CLASS_IPV4:
-               offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+               offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
                break;
        case PTP_CLASS_IPV6:
                offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
@@ -934,7 +934,7 @@ static int is_sync(struct sk_buff *skb, int type)
 
        switch (type & PTP_CLASS_PMASK) {
        case PTP_CLASS_IPV4:
-               offset += ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+               offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
                break;
        case PTP_CLASS_IPV6:
                offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
index bd37e45c89c0e13f8128c82ac284c4ba6530d52d..225c033b08f3fbc4217fc238ec7048b611b8d87b 100644 (file)
 #define MII_M1011_PHY_SCR              0x10
 #define MII_M1011_PHY_SCR_AUTO_CROSS   0x0060
 
+#define MII_M1145_PHY_EXT_SR           0x1b
 #define MII_M1145_PHY_EXT_CR           0x14
 #define MII_M1145_RGMII_RX_DELAY       0x0080
 #define MII_M1145_RGMII_TX_DELAY       0x0002
 
+#define MII_M1145_HWCFG_MODE_SGMII_NO_CLK      0x4
+#define MII_M1145_HWCFG_MODE_MASK              0xf
+#define MII_M1145_HWCFG_FIBER_COPPER_AUTO      0x8000
+
 #define MII_M1111_PHY_LED_CONTROL      0x18
 #define MII_M1111_PHY_LED_DIRECT       0x4100
 #define MII_M1111_PHY_LED_COMBINE      0x411c
@@ -676,6 +681,20 @@ static int m88e1145_config_init(struct phy_device *phydev)
                }
        }
 
+       if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+               int temp = phy_read(phydev, MII_M1145_PHY_EXT_SR);
+               if (temp < 0)
+                       return temp;
+
+               temp &= ~MII_M1145_HWCFG_MODE_MASK;
+               temp |= MII_M1145_HWCFG_MODE_SGMII_NO_CLK;
+               temp |= MII_M1145_HWCFG_FIBER_COPPER_AUTO;
+
+               err = phy_write(phydev, MII_M1145_PHY_EXT_SR, temp);
+               if (err < 0)
+                       return err;
+       }
+
        err = marvell_of_reg_init(phydev);
        if (err < 0)
                return err;
index 1dfffdc9dfc3577bd6893688da191c38539e243f..767cd110f49688d2b4118ba4dffc1a373972e56d 100644 (file)
@@ -352,6 +352,7 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
 {
        struct mii_ioctl_data *mii_data = if_mii(ifr);
        u16 val = mii_data->val_in;
+       bool change_autoneg = false;
 
        switch (cmd) {
        case SIOCGMIIPHY:
@@ -367,22 +368,29 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
                if (mii_data->phy_id == phydev->addr) {
                        switch (mii_data->reg_num) {
                        case MII_BMCR:
-                               if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0)
+                               if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0) {
+                                       if (phydev->autoneg == AUTONEG_ENABLE)
+                                               change_autoneg = true;
                                        phydev->autoneg = AUTONEG_DISABLE;
-                               else
+                                       if (val & BMCR_FULLDPLX)
+                                               phydev->duplex = DUPLEX_FULL;
+                                       else
+                                               phydev->duplex = DUPLEX_HALF;
+                                       if (val & BMCR_SPEED1000)
+                                               phydev->speed = SPEED_1000;
+                                       else if (val & BMCR_SPEED100)
+                                               phydev->speed = SPEED_100;
+                                       else phydev->speed = SPEED_10;
+                               }
+                               else {
+                                       if (phydev->autoneg == AUTONEG_DISABLE)
+                                               change_autoneg = true;
                                        phydev->autoneg = AUTONEG_ENABLE;
-                               if (!phydev->autoneg && (val & BMCR_FULLDPLX))
-                                       phydev->duplex = DUPLEX_FULL;
-                               else
-                                       phydev->duplex = DUPLEX_HALF;
-                               if (!phydev->autoneg && (val & BMCR_SPEED1000))
-                                       phydev->speed = SPEED_1000;
-                               else if (!phydev->autoneg &&
-                                        (val & BMCR_SPEED100))
-                                       phydev->speed = SPEED_100;
+                               }
                                break;
                        case MII_ADVERTISE:
-                               phydev->advertising = val;
+                               phydev->advertising = mii_adv_to_ethtool_adv_t(val);
+                               change_autoneg = true;
                                break;
                        default:
                                /* do nothing */
@@ -396,6 +404,10 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
                if (mii_data->reg_num == MII_BMCR &&
                    val & BMCR_RESET)
                        return phy_init_hw(phydev);
+
+               if (change_autoneg)
+                       return phy_start_aneg(phydev);
+
                return 0;
 
        case SIOCSHWTSTAMP:
index 68c3a3f4e0abe54910923aca8aa64286366e131a..794a4732936883c662212e0769e62993e67d96b0 100644 (file)
@@ -755,23 +755,23 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
                err = get_filter(argp, &code);
                if (err >= 0) {
+                       struct bpf_prog *pass_filter = NULL;
                        struct sock_fprog_kern fprog = {
                                .len = err,
                                .filter = code,
                        };
 
-                       ppp_lock(ppp);
-                       if (ppp->pass_filter) {
-                               bpf_prog_destroy(ppp->pass_filter);
-                               ppp->pass_filter = NULL;
+                       err = 0;
+                       if (fprog.filter)
+                               err = bpf_prog_create(&pass_filter, &fprog);
+                       if (!err) {
+                               ppp_lock(ppp);
+                               if (ppp->pass_filter)
+                                       bpf_prog_destroy(ppp->pass_filter);
+                               ppp->pass_filter = pass_filter;
+                               ppp_unlock(ppp);
                        }
-                       if (fprog.filter != NULL)
-                               err = bpf_prog_create(&ppp->pass_filter,
-                                                     &fprog);
-                       else
-                               err = 0;
                        kfree(code);
-                       ppp_unlock(ppp);
                }
                break;
        }
@@ -781,23 +781,23 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
                err = get_filter(argp, &code);
                if (err >= 0) {
+                       struct bpf_prog *active_filter = NULL;
                        struct sock_fprog_kern fprog = {
                                .len = err,
                                .filter = code,
                        };
 
-                       ppp_lock(ppp);
-                       if (ppp->active_filter) {
-                               bpf_prog_destroy(ppp->active_filter);
-                               ppp->active_filter = NULL;
+                       err = 0;
+                       if (fprog.filter)
+                               err = bpf_prog_create(&active_filter, &fprog);
+                       if (!err) {
+                               ppp_lock(ppp);
+                               if (ppp->active_filter)
+                                       bpf_prog_destroy(ppp->active_filter);
+                               ppp->active_filter = active_filter;
+                               ppp_unlock(ppp);
                        }
-                       if (fprog.filter != NULL)
-                               err = bpf_prog_create(&ppp->active_filter,
-                                                     &fprog);
-                       else
-                               err = 0;
                        kfree(code);
-                       ppp_unlock(ppp);
                }
                break;
        }
index 1aff970be33ec88ec8ff6781467155f68cf5b3b4..1dc628ffce2b52a565354f060dca84467d67e4b9 100644 (file)
@@ -506,7 +506,9 @@ static int pptp_getname(struct socket *sock, struct sockaddr *uaddr,
        int len = sizeof(struct sockaddr_pppox);
        struct sockaddr_pppox sp;
 
-       sp.sa_family      = AF_PPPOX;
+       memset(&sp.sa_addr, 0, sizeof(sp.sa_addr));
+
+       sp.sa_family    = AF_PPPOX;
        sp.sa_protocol  = PX_PROTO_PPTP;
        sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr;
 
index 186ce541c65762f8ee1720aae7f573f145982406..9dd3746994a42cb73c585848876ff3e878963f24 100644 (file)
@@ -65,6 +65,7 @@
 #include <linux/nsproxy.h>
 #include <linux/virtio_net.h>
 #include <linux/rcupdate.h>
+#include <net/ipv6.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
@@ -174,7 +175,7 @@ struct tun_struct {
        struct net_device       *dev;
        netdev_features_t       set_features;
 #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
-                         NETIF_F_TSO6|NETIF_F_UFO)
+                         NETIF_F_TSO6)
 
        int                     vnet_hdr_sz;
        int                     sndbuf;
@@ -1139,6 +1140,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
                break;
        }
 
+       skb_reset_network_header(skb);
+
        if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
                pr_debug("GSO!\n");
                switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
@@ -1149,8 +1152,20 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
                        skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
                        break;
                case VIRTIO_NET_HDR_GSO_UDP:
+               {
+                       static bool warned;
+
+                       if (!warned) {
+                               warned = true;
+                               netdev_warn(tun->dev,
+                                           "%s: using disabled UFO feature; please fix this program\n",
+                                           current->comm);
+                       }
                        skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+                       if (skb->protocol == htons(ETH_P_IPV6))
+                               ipv6_proxy_select_ident(skb);
                        break;
+               }
                default:
                        tun->dev->stats.rx_frame_errors++;
                        kfree_skb(skb);
@@ -1179,7 +1194,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
                skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
        }
 
-       skb_reset_network_header(skb);
        skb_probe_transport_header(skb, 0);
 
        rxhash = skb_get_hash(skb);
@@ -1221,12 +1235,20 @@ static ssize_t tun_put_user(struct tun_struct *tun,
        struct tun_pi pi = { 0, skb->protocol };
        ssize_t total = 0;
        int vlan_offset = 0, copied;
+       int vlan_hlen = 0;
+       int vnet_hdr_sz = 0;
+
+       if (vlan_tx_tag_present(skb))
+               vlan_hlen = VLAN_HLEN;
+
+       if (tun->flags & TUN_VNET_HDR)
+               vnet_hdr_sz = tun->vnet_hdr_sz;
 
        if (!(tun->flags & TUN_NO_PI)) {
                if ((len -= sizeof(pi)) < 0)
                        return -EINVAL;
 
-               if (len < skb->len) {
+               if (len < skb->len + vlan_hlen + vnet_hdr_sz) {
                        /* Packet will be striped */
                        pi.flags |= TUN_PKT_STRIP;
                }
@@ -1236,9 +1258,9 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                total += sizeof(pi);
        }
 
-       if (tun->flags & TUN_VNET_HDR) {
+       if (vnet_hdr_sz) {
                struct virtio_net_hdr gso = { 0 }; /* no info leak */
-               if ((len -= tun->vnet_hdr_sz) < 0)
+               if ((len -= vnet_hdr_sz) < 0)
                        return -EINVAL;
 
                if (skb_is_gso(skb)) {
@@ -1251,8 +1273,6 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                                gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
                        else if (sinfo->gso_type & SKB_GSO_TCPV6)
                                gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
-                       else if (sinfo->gso_type & SKB_GSO_UDP)
-                               gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
                        else {
                                pr_err("unexpected GSO type: "
                                       "0x%x, gso_size %d, hdr_len %d\n",
@@ -1272,7 +1292,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
 
                if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
-                       gso.csum_start = skb_checksum_start_offset(skb);
+                       gso.csum_start = skb_checksum_start_offset(skb) +
+                                        vlan_hlen;
                        gso.csum_offset = skb->csum_offset;
                } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
                        gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
@@ -1281,14 +1302,13 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
                                               sizeof(gso))))
                        return -EFAULT;
-               total += tun->vnet_hdr_sz;
+               total += vnet_hdr_sz;
        }
 
        copied = total;
-       total += skb->len;
-       if (!vlan_tx_tag_present(skb)) {
-               len = min_t(int, skb->len, len);
-       } else {
+       len = min_t(int, skb->len + vlan_hlen, len);
+       total += skb->len + vlan_hlen;
+       if (vlan_hlen) {
                int copy, ret;
                struct {
                        __be16 h_vlan_proto;
@@ -1299,8 +1319,6 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
 
                vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
-               len = min_t(int, skb->len + VLAN_HLEN, len);
-               total += VLAN_HLEN;
 
                copy = min_t(int, vlan_offset, len);
                ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy);
@@ -1762,11 +1780,6 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
                                features |= NETIF_F_TSO6;
                        arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
                }
-
-               if (arg & TUN_F_UFO) {
-                       features |= NETIF_F_UFO;
-                       arg &= ~TUN_F_UFO;
-               }
        }
 
        /* This gives the user a way to test for new features in future by
index 2c05f6cdb12f3a1e2ae9bed29c6241cee7dc3a46..816d511e34d33065a80cd171bab45ec25b8af3db 100644 (file)
@@ -465,19 +465,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                return ret;
        }
 
-       ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL);
-       if (ret < 0)
-               return ret;
-
-       msleep(150);
-
-       ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
-       if (ret < 0)
-               return ret;
-
-       msleep(150);
-
-       ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE);
+       ax88772_reset(dev);
 
        /* Read PHYID register *AFTER* the PHY was reset properly */
        phyid = asix_get_phyid(dev);
index be4275721039ad3b01cb1eb44cbca9d85a606597..e6338c16081a5d66c11ad400e876ca7b6c7bcd40 100644 (file)
@@ -937,6 +937,7 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p)
 {
        struct usbnet *dev = netdev_priv(net);
        struct sockaddr *addr = p;
+       int ret;
 
        if (netif_running(net))
                return -EBUSY;
@@ -946,8 +947,12 @@ static int ax88179_set_mac_addr(struct net_device *net, void *p)
        memcpy(net->dev_addr, addr->sa_data, ETH_ALEN);
 
        /* Set the MAC address */
-       return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
+       ret = ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN,
                                 ETH_ALEN, net->dev_addr);
+       if (ret < 0)
+               return ret;
+
+       return 0;
 }
 
 static const struct net_device_ops ax88179_netdev_ops = {
index 2a32d9167d3b931fb82c434bb0198e27bfc1d8ae..d3920b54a92ce3de23a581d3cf80e99aa7d61e72 100644 (file)
@@ -67,6 +67,35 @@ static const u8 mbm_guid[16] = {
        0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
 };
 
+static void usbnet_cdc_update_filter(struct usbnet *dev)
+{
+       struct cdc_state        *info = (void *) &dev->data;
+       struct usb_interface    *intf = info->control;
+
+       u16 cdc_filter =
+           USB_CDC_PACKET_TYPE_ALL_MULTICAST | USB_CDC_PACKET_TYPE_DIRECTED |
+           USB_CDC_PACKET_TYPE_BROADCAST;
+
+       if (dev->net->flags & IFF_PROMISC)
+               cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS;
+
+       /* FIXME cdc-ether has some multicast code too, though it complains
+        * in routine cases.  info->ether describes the multicast support.
+        * Implement that here, manipulating the cdc filter as needed.
+        */
+
+       usb_control_msg(dev->udev,
+                       usb_sndctrlpipe(dev->udev, 0),
+                       USB_CDC_SET_ETHERNET_PACKET_FILTER,
+                       USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                       cdc_filter,
+                       intf->cur_altsetting->desc.bInterfaceNumber,
+                       NULL,
+                       0,
+                       USB_CTRL_SET_TIMEOUT
+               );
+}
+
 /* probes control interface, claims data interface, collects the bulk
  * endpoints, activates data interface (if needed), maybe sets MTU.
  * all pure cdc, except for certain firmware workarounds, and knowing
@@ -347,16 +376,8 @@ next_desc:
         * don't do reset all the way. So the packet filter should
         * be set to a sane initial value.
         */
-       usb_control_msg(dev->udev,
-                       usb_sndctrlpipe(dev->udev, 0),
-                       USB_CDC_SET_ETHERNET_PACKET_FILTER,
-                       USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                       USB_CDC_PACKET_TYPE_ALL_MULTICAST | USB_CDC_PACKET_TYPE_DIRECTED | USB_CDC_PACKET_TYPE_BROADCAST,
-                       intf->cur_altsetting->desc.bInterfaceNumber,
-                       NULL,
-                       0,
-                       USB_CTRL_SET_TIMEOUT
-               );
+       usbnet_cdc_update_filter(dev);
+
        return 0;
 
 bad_desc:
@@ -468,10 +489,6 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
                return status;
        }
 
-       /* FIXME cdc-ether has some multicast code too, though it complains
-        * in routine cases.  info->ether describes the multicast support.
-        * Implement that here, manipulating the cdc filter as needed.
-        */
        return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
@@ -482,6 +499,7 @@ static const struct driver_info     cdc_info = {
        .bind =         usbnet_cdc_bind,
        .unbind =       usbnet_cdc_unbind,
        .status =       usbnet_cdc_status,
+       .set_rx_mode =  usbnet_cdc_update_filter,
        .manage_power = usbnet_manage_power,
 };
 
@@ -491,6 +509,7 @@ static const struct driver_info wwan_info = {
        .bind =         usbnet_cdc_bind,
        .unbind =       usbnet_cdc_unbind,
        .status =       usbnet_cdc_status,
+       .set_rx_mode =  usbnet_cdc_update_filter,
        .manage_power = usbnet_manage_power,
 };
 
index 22756db53dcacc3138fd000cad8dbda968948fb8..b8a82b86f909095632c7d5747b9bf25cb81c970e 100644 (file)
@@ -780,6 +780,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x413c, 0x81a4, 8)},    /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
        {QMI_FIXED_INTF(0x413c, 0x81a8, 8)},    /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
        {QMI_FIXED_INTF(0x413c, 0x81a9, 8)},    /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+       {QMI_FIXED_INTF(0x03f0, 0x581d, 4)},    /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index e3d84c322e4ec2589d496ad9a6355bd14e08da31..c6554c7a8147045450ec8385797038f1ceba955f 100644 (file)
@@ -1162,6 +1162,9 @@ static void intr_callback(struct urb *urb)
        case -ESHUTDOWN:
                netif_device_detach(tp->netdev);
        case -ENOENT:
+       case -EPROTO:
+               netif_info(tp, intr, tp->netdev,
+                          "Stop submitting intr, status %d\n", status);
                return;
        case -EOVERFLOW:
                netif_info(tp, intr, tp->netdev, "intr status -EOVERFLOW\n");
@@ -2891,6 +2894,9 @@ static int rtl8152_open(struct net_device *netdev)
        if (res)
                goto out;
 
+       /* set speed to 0 to avoid autoresume try to submit rx */
+       tp->speed = 0;
+
        res = usb_autopm_get_interface(tp->intf);
        if (res < 0) {
                free_all_mem(tp);
@@ -2904,6 +2910,8 @@ static int rtl8152_open(struct net_device *netdev)
                clear_bit(WORK_ENABLE, &tp->flags);
                usb_kill_urb(tp->intr_urb);
                cancel_delayed_work_sync(&tp->schedule);
+
+               /* disable the tx/rx, if the workqueue has enabled them. */
                if (tp->speed & LINK_STATUS)
                        tp->rtl_ops.disable(tp);
        }
@@ -2955,10 +2963,7 @@ static int rtl8152_close(struct net_device *netdev)
                 * be disable when autoresume occurs, because the
                 * netif_running() would be false.
                 */
-               if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
-                       rtl_runtime_suspend_enable(tp, false);
-                       clear_bit(SELECTIVE_SUSPEND, &tp->flags);
-               }
+               rtl_runtime_suspend_enable(tp, false);
 
                tasklet_disable(&tp->tl);
                tp->rtl_ops.down(tp);
@@ -3205,7 +3210,7 @@ static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
                netif_device_detach(netdev);
        }
 
-       if (netif_running(netdev)) {
+       if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
                clear_bit(WORK_ENABLE, &tp->flags);
                usb_kill_urb(tp->intr_urb);
                tasklet_disable(&tp->tl);
@@ -3253,6 +3258,8 @@ static int rtl8152_resume(struct usb_interface *intf)
                        set_bit(WORK_ENABLE, &tp->flags);
                }
                usb_submit_urb(tp->intr_urb, GFP_KERNEL);
+       } else if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+               clear_bit(SELECTIVE_SUSPEND, &tp->flags);
        }
 
        mutex_unlock(&tp->control);
index 20615bbd693b2eb782f8a6bba08adaff3cfa724a..3a6770a65d7836ace177cff2bb45c925b474a84a 100644 (file)
@@ -1052,6 +1052,21 @@ static void __handle_link_change(struct usbnet *dev)
        clear_bit(EVENT_LINK_CHANGE, &dev->flags);
 }
 
+static void usbnet_set_rx_mode(struct net_device *net)
+{
+       struct usbnet           *dev = netdev_priv(net);
+
+       usbnet_defer_kevent(dev, EVENT_SET_RX_MODE);
+}
+
+static void __handle_set_rx_mode(struct usbnet *dev)
+{
+       if (dev->driver_info->set_rx_mode)
+               (dev->driver_info->set_rx_mode)(dev);
+
+       clear_bit(EVENT_SET_RX_MODE, &dev->flags);
+}
+
 /* work that cannot be done in interrupt context uses keventd.
  *
  * NOTE:  with 2.5 we could do more of this using completion callbacks,
@@ -1157,6 +1172,10 @@ skip_reset:
        if (test_bit (EVENT_LINK_CHANGE, &dev->flags))
                __handle_link_change(dev);
 
+       if (test_bit (EVENT_SET_RX_MODE, &dev->flags))
+               __handle_set_rx_mode(dev);
+
+
        if (dev->flags)
                netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags);
 }
@@ -1525,6 +1544,7 @@ static const struct net_device_ops usbnet_netdev_ops = {
        .ndo_stop               = usbnet_stop,
        .ndo_start_xmit         = usbnet_start_xmit,
        .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_set_rx_mode        = usbnet_set_rx_mode,
        .ndo_change_mtu         = usbnet_change_mtu,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
index d75256bd1a6ab8bb6284ad4088e9513469fffe8a..b0bc8ead47de240c8f27605488eb300d0445c4fb 100644 (file)
@@ -491,8 +491,17 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
                        skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
                        break;
                case VIRTIO_NET_HDR_GSO_UDP:
+               {
+                       static bool warned;
+
+                       if (!warned) {
+                               warned = true;
+                               netdev_warn(dev,
+                                           "host using disabled UFO feature; please fix it\n");
+                       }
                        skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
                        break;
+               }
                case VIRTIO_NET_HDR_GSO_TCPV6:
                        skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
                        break;
@@ -881,8 +890,6 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
                        hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
                else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
                        hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
-               else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
-                       hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
                else
                        BUG();
                if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
@@ -1666,6 +1673,40 @@ static const struct attribute_group virtio_net_mrg_rx_group = {
 };
 #endif
 
+static bool virtnet_fail_on_feature(struct virtio_device *vdev,
+                                   unsigned int fbit,
+                                   const char *fname, const char *dname)
+{
+       if (!virtio_has_feature(vdev, fbit))
+               return false;
+
+       dev_err(&vdev->dev, "device advertises feature %s but not %s",
+               fname, dname);
+
+       return true;
+}
+
+#define VIRTNET_FAIL_ON(vdev, fbit, dbit)                      \
+       virtnet_fail_on_feature(vdev, fbit, #fbit, dbit)
+
+static bool virtnet_validate_features(struct virtio_device *vdev)
+{
+       if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ) &&
+           (VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_RX,
+                            "VIRTIO_NET_F_CTRL_VQ") ||
+            VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_VLAN,
+                            "VIRTIO_NET_F_CTRL_VQ") ||
+            VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE,
+                            "VIRTIO_NET_F_CTRL_VQ") ||
+            VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_MQ, "VIRTIO_NET_F_CTRL_VQ") ||
+            VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR,
+                            "VIRTIO_NET_F_CTRL_VQ"))) {
+               return false;
+       }
+
+       return true;
+}
+
 static int virtnet_probe(struct virtio_device *vdev)
 {
        int i, err;
@@ -1673,6 +1714,9 @@ static int virtnet_probe(struct virtio_device *vdev)
        struct virtnet_info *vi;
        u16 max_queue_pairs;
 
+       if (!virtnet_validate_features(vdev))
+               return -EINVAL;
+
        /* Find if host supports multiqueue virtio_net device */
        err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ,
                                   struct virtio_net_config,
@@ -1705,7 +1749,7 @@ static int virtnet_probe(struct virtio_device *vdev)
                        dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
 
                if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
-                       dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
+                       dev->hw_features |= NETIF_F_TSO
                                | NETIF_F_TSO_ECN | NETIF_F_TSO6;
                }
                /* Individual feature bits: what can host handle? */
@@ -1715,11 +1759,9 @@ static int virtnet_probe(struct virtio_device *vdev)
                        dev->hw_features |= NETIF_F_TSO6;
                if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
                        dev->hw_features |= NETIF_F_TSO_ECN;
-               if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
-                       dev->hw_features |= NETIF_F_UFO;
 
                if (gso)
-                       dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO);
+                       dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
                /* (!csum && gso) case will be fixed by register_netdev() */
        }
        if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
@@ -1757,8 +1799,7 @@ static int virtnet_probe(struct virtio_device *vdev)
        /* If we can receive ANY GSO packets, we must allocate large ones. */
        if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
            virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
-           virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) ||
-           virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
+           virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
                vi->big_packets = true;
 
        if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
@@ -1952,9 +1993,9 @@ static struct virtio_device_id id_table[] = {
 static unsigned int features[] = {
        VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
        VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
-       VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
+       VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6,
        VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
-       VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
+       VIRTIO_NET_F_GUEST_ECN,
        VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
        VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
        VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
index ca309820d39e1ba7995f38d3a2f9bacbd1c1f857..be4649a49c5e8bb2bec68aca08d27a82f5563d40 100644 (file)
 
 #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
 
-/* VXLAN protocol header */
-struct vxlanhdr {
-       __be32 vx_flags;
-       __be32 vx_vni;
-};
-
 /* UDP port for VXLAN traffic.
  * The IANA assigned port is 4789, but the Linux default is 8472
  * for compatibility with early adopters.
@@ -275,13 +269,15 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
        return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
 }
 
-/* Find VXLAN socket based on network namespace and UDP port */
-static struct vxlan_sock *vxlan_find_sock(struct net *net, __be16 port)
+/* Find VXLAN socket based on network namespace, address family and UDP port */
+static struct vxlan_sock *vxlan_find_sock(struct net *net,
+                                         sa_family_t family, __be16 port)
 {
        struct vxlan_sock *vs;
 
        hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
-               if (inet_sk(vs->sock->sk)->inet_sport == port)
+               if (inet_sk(vs->sock->sk)->inet_sport == port &&
+                   inet_sk(vs->sock->sk)->sk.sk_family == family)
                        return vs;
        }
        return NULL;
@@ -300,11 +296,12 @@ static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, u32 id)
 }
 
 /* Look up VNI in a per net namespace table */
-static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, __be16 port)
+static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id,
+                                       sa_family_t family, __be16 port)
 {
        struct vxlan_sock *vs;
 
-       vs = vxlan_find_sock(net, port);
+       vs = vxlan_find_sock(net, family, port);
        if (!vs)
                return NULL;
 
@@ -621,6 +618,8 @@ static int vxlan_gro_complete(struct sk_buff *skb, int nhoff)
        int vxlan_len  = sizeof(struct vxlanhdr) + sizeof(struct ethhdr);
        int err = -ENOSYS;
 
+       udp_tunnel_gro_complete(skb, nhoff);
+
        eh = (struct ethhdr *)(skb->data + nhoff + sizeof(struct vxlanhdr));
        type = eh->h_proto;
 
@@ -1771,7 +1770,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                        struct vxlan_dev *dst_vxlan;
 
                        ip_rt_put(rt);
-                       dst_vxlan = vxlan_find_vni(vxlan->net, vni, dst_port);
+                       dst_vxlan = vxlan_find_vni(vxlan->net, vni,
+                                                  dst->sa.sa_family, dst_port);
                        if (!dst_vxlan)
                                goto tx_error;
                        vxlan_encap_bypass(skb, vxlan, dst_vxlan);
@@ -1825,7 +1825,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                        struct vxlan_dev *dst_vxlan;
 
                        dst_release(ndst);
-                       dst_vxlan = vxlan_find_vni(vxlan->net, vni, dst_port);
+                       dst_vxlan = vxlan_find_vni(vxlan->net, vni,
+                                                  dst->sa.sa_family, dst_port);
                        if (!dst_vxlan)
                                goto tx_error;
                        vxlan_encap_bypass(skb, vxlan, dst_vxlan);
@@ -1985,13 +1986,15 @@ static int vxlan_init(struct net_device *dev)
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
        struct vxlan_sock *vs;
+       bool ipv6 = vxlan->flags & VXLAN_F_IPV6;
 
        dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
        spin_lock(&vn->sock_lock);
-       vs = vxlan_find_sock(vxlan->net, vxlan->dst_port);
+       vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
+                            vxlan->dst_port);
        if (vs) {
                /* If we have a socket with same port already, reuse it */
                atomic_inc(&vs->refcnt);
@@ -2303,9 +2306,9 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
        if (ipv6) {
                udp_conf.family = AF_INET6;
                udp_conf.use_udp6_tx_checksums =
-                   !!(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
+                   !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
                udp_conf.use_udp6_rx_checksums =
-                   !!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
+                   !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
        } else {
                udp_conf.family = AF_INET;
                udp_conf.local_ip.s_addr = INADDR_ANY;
@@ -2382,6 +2385,7 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
 {
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
        struct vxlan_sock *vs;
+       bool ipv6 = flags & VXLAN_F_IPV6;
 
        vs = vxlan_socket_create(net, port, rcv, data, flags);
        if (!IS_ERR(vs))
@@ -2391,7 +2395,7 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
                return vs;
 
        spin_lock(&vn->sock_lock);
-       vs = vxlan_find_sock(net, port);
+       vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port);
        if (vs) {
                if (vs->rcv == rcv)
                        atomic_inc(&vs->refcnt);
@@ -2550,7 +2554,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
            nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
                vxlan->flags |= VXLAN_F_UDP_ZERO_CSUM6_RX;
 
-       if (vxlan_find_vni(net, vni, vxlan->dst_port)) {
+       if (vxlan_find_vni(net, vni, use_ipv6 ? AF_INET6 : AF_INET,
+                          vxlan->dst_port)) {
                pr_info("duplicate VNI %u\n", vni);
                return -EEXIST;
        }
index e5ba6faf32815173fa47fa81fd303082688202bd..86907e5ba6ca21a5e7e6d8ff8b6b20499e004cce 100644 (file)
@@ -80,6 +80,7 @@ struct reg_dmn_pair_mapping {
 
 struct ath_regulatory {
        char alpha2[2];
+       enum nl80211_dfs_regions region;
        u16 country_code;
        u16 max_power_level;
        u16 current_rd;
index 697c4ae90af006f9c7f962bd21ea938af1892455..1e8ea5e4d4ca71ecd7598aea30d5a76f4749e85a 100644 (file)
@@ -664,6 +664,19 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
                ah->enabled_cals |= TX_CL_CAL;
        else
                ah->enabled_cals &= ~TX_CL_CAL;
+
+       if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
+               if (ah->is_clk_25mhz) {
+                       REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
+                       REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
+                       REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
+               } else {
+                       REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
+                       REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
+                       REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
+               }
+               udelay(100);
+       }
 }
 
 static void ar9003_hw_prog_ini(struct ath_hw *ah,
index c6dd7f1fed65ed52b2ed1d0fd72c474260b5656f..33b0c7aef2ea39f527962f483a8014a052ac10ce 100644 (file)
@@ -368,11 +368,11 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
 {
        struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 
-       if (reg->power_limit != new_txpow) {
+       if (reg->power_limit != new_txpow)
                ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
-               /* read back in case value is clamped */
-               *txpower = reg->max_power_level;
-       }
+
+       /* read back in case value is clamped */
+       *txpower = reg->max_power_level;
 }
 EXPORT_SYMBOL(ath9k_cmn_update_txpow);
 
index 46f20a309b5f53c10e6d487c999d560de4f5f6e3..5c45e787814ed6a9b65f9f3e523626f282201ddb 100644 (file)
@@ -455,7 +455,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
                         "%2d          %2x      %1x     %2x           %2x\n",
                         i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
                         (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
-                        val[2] & (0x7 << (i * 3)) >> (i * 3),
+                        (val[2] & (0x7 << (i * 3))) >> (i * 3),
                         (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
        }
 
index 8be4b145339426b7ea8a47a4788c9dd6be04b238..2ad605760e2136584a56c25680cb14324fa3d30c 100644 (file)
@@ -861,19 +861,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
        udelay(RTC_PLL_SETTLE_DELAY);
 
        REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
-
-       if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
-               if (ah->is_clk_25mhz) {
-                       REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
-                       REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
-                       REG_WRITE(ah,  AR_SLP32_INC, 0x0001e7ae);
-               } else {
-                       REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
-                       REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
-                       REG_WRITE(ah,  AR_SLP32_INC, 0x0001e800);
-               }
-               udelay(100);
-       }
 }
 
 static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
index 156a944134dcfb09ee139ccc2ffde1af306bb936..3bd030494986a087bfd9744873649442fa67b572 100644 (file)
@@ -734,6 +734,32 @@ static const struct ieee80211_iface_combination if_comb[] = {
 #endif
 };
 
+#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
+static void ath9k_set_mcc_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+{
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (!ath9k_is_chanctx_enabled())
+               return;
+
+       hw->flags |= IEEE80211_HW_QUEUE_CONTROL;
+       hw->queues = ATH9K_NUM_TX_QUEUES;
+       hw->offchannel_tx_hw_queue = hw->queues - 1;
+       hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS);
+       hw->wiphy->iface_combinations = if_comb_multi;
+       hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi);
+       hw->wiphy->max_scan_ssids = 255;
+       hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+       hw->wiphy->max_remain_on_channel_duration = 10000;
+       hw->chanctx_data_size = sizeof(void *);
+       hw->extra_beacon_tailroom =
+               sizeof(struct ieee80211_p2p_noa_attr) + 9;
+
+       ath_dbg(common, CHAN_CTX, "Use channel contexts\n");
+}
+#endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
+
 static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
        struct ath_hw *ah = sc->sc_ah;
@@ -746,7 +772,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                IEEE80211_HW_SPECTRUM_MGMT |
                IEEE80211_HW_REPORTS_TX_ACK_STATUS |
                IEEE80211_HW_SUPPORTS_RC_TABLE |
-               IEEE80211_HW_QUEUE_CONTROL |
                IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
 
        if (ath9k_ps_enable)
@@ -781,24 +806,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                        hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
        }
 
-#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
-
-       if (ath9k_is_chanctx_enabled()) {
-               hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS);
-               hw->wiphy->iface_combinations = if_comb_multi;
-               hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi);
-               hw->wiphy->max_scan_ssids = 255;
-               hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
-               hw->wiphy->max_remain_on_channel_duration = 10000;
-               hw->chanctx_data_size = sizeof(void *);
-               hw->extra_beacon_tailroom =
-                       sizeof(struct ieee80211_p2p_noa_attr) + 9;
-
-               ath_dbg(common, CHAN_CTX, "Use channel contexts\n");
-       }
-
-#endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */
-
        hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
@@ -808,12 +815,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
        hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
 
-       /* allow 4 queues per channel context +
-        * 1 cab queue + 1 offchannel tx queue
-        */
-       hw->queues = ATH9K_NUM_TX_QUEUES;
-       /* last queue for offchannel */
-       hw->offchannel_tx_hw_queue = hw->queues - 1;
+       hw->queues = 4;
        hw->max_rates = 4;
        hw->max_listen_interval = 10;
        hw->max_rate_tries = 10;
@@ -837,6 +839,9 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
                hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
                        &common->sbands[IEEE80211_BAND_5GHZ];
 
+#ifdef CONFIG_ATH9K_CHANNEL_CONTEXT
+       ath9k_set_mcc_capab(sc, hw);
+#endif
        ath9k_init_wow(hw);
        ath9k_cmn_reload_chainmask(ah);
 
index 6f6a974f7fdb265960db2098f2c45b9684ffca2b..4f18a6be0c7d706092998c15bb290b3f6ddcdbc1 100644 (file)
@@ -974,9 +974,8 @@ void ath9k_calculate_iter_data(struct ath_softc *sc,
        struct ath_vif *avp;
 
        /*
-        * Pick the MAC address of the first interface as the new hardware
-        * MAC address. The hardware will use it together with the BSSID mask
-        * when matching addresses.
+        * The hardware will use primary station addr together with the
+        * BSSID mask when matching addresses.
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
@@ -1162,6 +1161,9 @@ static void ath9k_assign_hw_queues(struct ieee80211_hw *hw,
 {
        int i;
 
+       if (!ath9k_is_chanctx_enabled())
+               return;
+
        for (i = 0; i < IEEE80211_NUM_ACS; i++)
                vif->hw_queue[i] = i;
 
@@ -1202,6 +1204,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
                list_add_tail(&avp->list, &avp->chanctx->vifs);
        }
 
+       ath9k_calculate_summary_state(sc, avp->chanctx);
+
        ath9k_assign_hw_queues(hw, vif);
 
        an->sc = sc;
@@ -1271,6 +1275,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 
        ath_tx_node_cleanup(sc, &avp->mcast_node);
 
+       ath9k_calculate_summary_state(sc, avp->chanctx);
+
        mutex_unlock(&sc->mutex);
 }
 
index 493a183d0aaf7d04c77103a8c4ea2b2c477089ad..d6e54a3c88f671f08ae3174ddabf6721fb39e051 100644 (file)
@@ -169,7 +169,10 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
 
        if (txq->stopped &&
            txq->pending_frames < sc->tx.txq_max_pending[q]) {
-               ieee80211_wake_queue(sc->hw, info->hw_queue);
+               if (ath9k_is_chanctx_enabled())
+                       ieee80211_wake_queue(sc->hw, info->hw_queue);
+               else
+                       ieee80211_wake_queue(sc->hw, q);
                txq->stopped = false;
        }
 }
@@ -2247,7 +2250,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
                fi->txq = q;
                if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
                    !txq->stopped) {
-                       ieee80211_stop_queue(sc->hw, info->hw_queue);
+                       if (ath9k_is_chanctx_enabled())
+                               ieee80211_stop_queue(sc->hw, info->hw_queue);
+                       else
+                               ieee80211_stop_queue(sc->hw, q);
                        txq->stopped = true;
                }
        }
index 415393dfb6fc17b51d33f4d24e70c6700620d4b5..06ea6cc9e30a5e07c379116a8e1ec0996e3f189e 100644 (file)
@@ -515,6 +515,7 @@ void ath_reg_notifier_apply(struct wiphy *wiphy,
        if (!request)
                return;
 
+       reg->region = request->dfs_region;
        switch (request->initiator) {
        case NL80211_REGDOM_SET_BY_CORE:
                /*
@@ -779,6 +780,19 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
                return SD_NO_CTL;
        }
 
+       if (ath_regd_get_eepromRD(reg) == CTRY_DEFAULT) {
+               switch (reg->region) {
+               case NL80211_DFS_FCC:
+                       return CTL_FCC;
+               case NL80211_DFS_ETSI:
+                       return CTL_ETSI;
+               case NL80211_DFS_JP:
+                       return CTL_MKK;
+               default:
+                       break;
+               }
+       }
+
        switch (band) {
        case IEEE80211_BAND_2GHZ:
                return reg->regpair->reg_2ghz_ctl;
index 1dfc682a805513f5e5d160f6198f6d17bec644fc..ee27b06074e1213f68bb2e3f6bb632b61aeb5fd5 100644 (file)
@@ -300,9 +300,7 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
 
 void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
 {
-       assert_mac_suspended(dev);
-       dev->phy.ops->phy_write(dev, destreg,
-               dev->phy.ops->phy_read(dev, srcreg));
+       b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg));
 }
 
 void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
index f55f625fd06b4aab850ffa16761714a5dff196f6..d20d4e6f391ae89706e422e2b817034ee030c0ae 100644 (file)
@@ -670,7 +670,6 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
                                  struct brcmf_sdio_dev *sdiodev)
 {
        int i;
-       uint fw_len, nv_len;
        char end;
 
        for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
@@ -684,25 +683,25 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
                return -ENODEV;
        }
 
-       fw_len = sizeof(sdiodev->fw_name) - 1;
-       nv_len = sizeof(sdiodev->nvram_name) - 1;
        /* check if firmware path is provided by module parameter */
        if (brcmf_firmware_path[0] != '\0') {
-               strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len);
-               strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len);
-               fw_len -= strlen(sdiodev->fw_name);
-               nv_len -= strlen(sdiodev->nvram_name);
+               strlcpy(sdiodev->fw_name, brcmf_firmware_path,
+                       sizeof(sdiodev->fw_name));
+               strlcpy(sdiodev->nvram_name, brcmf_firmware_path,
+                       sizeof(sdiodev->nvram_name));
 
                end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
                if (end != '/') {
-                       strncat(sdiodev->fw_name, "/", fw_len);
-                       strncat(sdiodev->nvram_name, "/", nv_len);
-                       fw_len--;
-                       nv_len--;
+                       strlcat(sdiodev->fw_name, "/",
+                               sizeof(sdiodev->fw_name));
+                       strlcat(sdiodev->nvram_name, "/",
+                               sizeof(sdiodev->nvram_name));
                }
        }
-       strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len);
-       strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len);
+       strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin,
+               sizeof(sdiodev->fw_name));
+       strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
+               sizeof(sdiodev->nvram_name));
 
        return 0;
 }
index f05f5270fec1095df589b96490308bfe5193568a..927bffd5be6487125ca5f3e269b5eb0d690fb2f7 100644 (file)
@@ -40,8 +40,8 @@ void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
                return;
 
        irq = irq_of_parse_and_map(np, 0);
-       if (irq < 0) {
-               brcmf_err("interrupt could not be mapped: err=%d\n", irq);
+       if (!irq) {
+               brcmf_err("interrupt could not be mapped\n");
                devm_kfree(dev, sdiodev->pdata);
                return;
        }
index 8c0632ec9f7a6041e72a0a3c6e6243a00955d97f..16fef3382019192d90462835625011075b33a2ec 100644 (file)
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
-#include <linux/unaligned/access_ok.h>
 #include <linux/interrupt.h>
 #include <linux/bcma/bcma.h>
 #include <linux/sched.h>
+#include <asm/unaligned.h>
 
 #include <soc.h>
 #include <chipcommon.h>
index dc135915470d2cb70efab5480d11a036a0e00d3f..875d1142c8b0f5f65111a8674c7017a7e895721d 100644 (file)
@@ -669,10 +669,12 @@ static int brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
                goto finalize;
        }
 
-       if (!brcmf_usb_ioctl_resp_wait(devinfo))
+       if (!brcmf_usb_ioctl_resp_wait(devinfo)) {
+               usb_kill_urb(devinfo->ctl_urb);
                ret = -ETIMEDOUT;
-       else
+       } else {
                memcpy(buffer, tmpbuf, buflen);
+       }
 
 finalize:
        kfree(tmpbuf);
index 28fa25b509db8c3154d2ff0220d4b05c5f83c99d..39b45c038a93ec2a538665bbe90498230493ec42 100644 (file)
@@ -299,6 +299,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
        primary_offset = ch->center_freq1 - ch->chan->center_freq;
        switch (ch->width) {
        case NL80211_CHAN_WIDTH_20:
+       case NL80211_CHAN_WIDTH_20_NOHT:
                ch_inf.bw = BRCMU_CHAN_BW_20;
                WARN_ON(primary_offset != 0);
                break;
@@ -323,6 +324,10 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
                                ch_inf.sb = BRCMU_CHAN_SB_LU;
                }
                break;
+       case NL80211_CHAN_WIDTH_80P80:
+       case NL80211_CHAN_WIDTH_160:
+       case NL80211_CHAN_WIDTH_5:
+       case NL80211_CHAN_WIDTH_10:
        default:
                WARN_ON_ONCE(1);
        }
@@ -333,6 +338,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
        case IEEE80211_BAND_5GHZ:
                ch_inf.band = BRCMU_CHAN_BAND_5G;
                break;
+       case IEEE80211_BAND_60GHZ:
        default:
                WARN_ON_ONCE(1);
        }
index 2364a3c09b9eb8037ba6237112c679749a3ac94c..cae692ff1013f9ee00b93861558c6144cfad4cc1 100644 (file)
@@ -1095,6 +1095,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                             u32 queues, bool drop)
 {
        struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+       u32 scd_queues;
 
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1108,18 +1109,19 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                goto done;
        }
 
-       /*
-        * mac80211 will not push any more frames for transmit
-        * until the flush is completed
-        */
-       if (drop) {
-               IWL_DEBUG_MAC80211(priv, "send flush command\n");
-               if (iwlagn_txfifo_flush(priv, 0)) {
-                       IWL_ERR(priv, "flush request fail\n");
-                       goto done;
-               }
+       scd_queues = BIT(priv->cfg->base_params->num_of_queues) - 1;
+       scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) |
+                       BIT(IWL_DEFAULT_CMD_QUEUE_NUM));
+
+       if (vif)
+               scd_queues &= ~BIT(vif->hw_queue[IEEE80211_AC_VO]);
+
+       IWL_DEBUG_TX_QUEUES(priv, "Flushing SCD queues: 0x%x\n", scd_queues);
+       if (iwlagn_txfifo_flush(priv, scd_queues)) {
+               IWL_ERR(priv, "flush request fail\n");
+               goto done;
        }
-       IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
+       IWL_DEBUG_TX_QUEUES(priv, "wait transmit/flush all frames\n");
        iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff);
 done:
        mutex_unlock(&priv->mutex);
index e4351487ca7269aefe06d4bf2da3c2fedc1f34da..d2b7234b1c73e00f76ed17094d52e0e18431d81f 100644 (file)
@@ -82,7 +82,8 @@
 #define IWL8000_TX_POWER_VERSION       0xffff /* meaningless */
 
 #define IWL8000_FW_PRE "iwlwifi-8000"
-#define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode"
+#define IWL8000_MODULE_FIRMWARE(api) \
+       IWL8000_FW_PRE "-" __stringify(api) ".ucode"
 
 #define NVM_HW_SECTION_NUM_FAMILY_8000         10
 #define DEFAULT_NVM_FILE_FAMILY_8000           "iwl_nvm_8000.bin"
index 4f6e66892acc4658473aed57fc4c6cc72dd33fc4..b894a84e8393062a113102c8bbe96cf4b28f4f24 100644 (file)
@@ -155,6 +155,7 @@ enum iwl_ucode_tlv_api {
  * @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
  * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),
  *     which also implies support for the scheduler configuration command
+ * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
  */
 enum iwl_ucode_tlv_capa {
        IWL_UCODE_TLV_CAPA_D0I3_SUPPORT                 = BIT(0),
@@ -163,6 +164,7 @@ enum iwl_ucode_tlv_capa {
        IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT       = BIT(10),
        IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT         = BIT(11),
        IWL_UCODE_TLV_CAPA_DQA_SUPPORT                  = BIT(12),
+       IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT              = BIT(18),
 };
 
 /* The default calibrate table size if not specified by firmware file */
index 9eb85249e89c46aa980ae22893b48af2150ee4df..d8fc548c0d6cd561993eebb6df185e3ccad0d6ac 100644 (file)
@@ -563,6 +563,7 @@ enum iwl_trans_state {
  *     Set during transport allocation.
  * @hw_id_str: a string with info about HW ID. Set during transport allocation.
  * @pm_support: set to true in start_hw if link pm is supported
+ * @ltr_enabled: set to true if the LTR is enabled
  * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
  *     The user should use iwl_trans_{alloc,free}_tx_cmd.
  * @dev_cmd_headroom: room needed for the transport's private use before the
@@ -589,6 +590,7 @@ struct iwl_trans {
        u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
 
        bool pm_support;
+       bool ltr_enabled;
 
        /* The following fields are internal only */
        struct kmem_cache *dev_cmd_pool;
index 8df2021f9856365b2bec8465bb4ddbb02e907586..da2ffb78519431a1b14e9b355280a3c7a3446ed6 100644 (file)
@@ -303,8 +303,8 @@ static const __le64 iwl_ci_mask[][3] = {
 };
 
 static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
-       cpu_to_le32(0x28412201),
-       cpu_to_le32(0x11118451),
+       cpu_to_le32(0x2e402280),
+       cpu_to_le32(0x7711a751),
 };
 
 struct corunning_block_luts {
index 585c0ab4a3ec5fc59ca8d2e84395c74b27b4fcd2..8a1d2f33d5b7da2768a7e5849e305b6386b0b480 100644 (file)
@@ -291,8 +291,8 @@ static const __le64 iwl_ci_mask[][3] = {
 };
 
 static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
-       cpu_to_le32(0x28412201),
-       cpu_to_le32(0x11118451),
+       cpu_to_le32(0x2e402280),
+       cpu_to_le32(0x7711a751),
 };
 
 struct corunning_block_luts {
index 27dd86395b39dd0f5800efe9c73a52294a2099ed..2fd8ad4633e0ee717096461398c96fc67181d288 100644 (file)
 
 /* Power Management Commands, Responses, Notifications */
 
+/**
+ * enum iwl_ltr_config_flags - masks for LTR config command flags
+ * @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status
+ * @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow
+ *     memory access
+ * @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR
+ *     reg change
+ * @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from
+ *     D0 to D3
+ * @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
+ * @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
+ * @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
+ */
+enum iwl_ltr_config_flags {
+       LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
+       LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1),
+       LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2),
+       LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3),
+       LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
+       LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
+       LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
+};
+
+/**
+ * struct iwl_ltr_config_cmd - configures the LTR
+ * @flags: See %enum iwl_ltr_config_flags
+ */
+struct iwl_ltr_config_cmd {
+       __le32 flags;
+       __le32 static_long;
+       __le32 static_short;
+} __packed;
+
 /* Radio LP RX Energy Threshold measured in dBm */
 #define POWER_LPRX_RSSI_THRESHOLD      75
 #define POWER_LPRX_RSSI_THRESHOLD_MAX  94
 #define POWER_LPRX_RSSI_THRESHOLD_MIN  30
 
 /**
- * enum iwl_scan_flags - masks for power table command flags
+ * enum iwl_power_flags - masks for power table command flags
  * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
  *             receiver and transmitter. '0' - does not allow.
  * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
index 667a92274c87773c1d123b41911afb5e38d19405..c62575d86bcdbe5e75c724cacf8605e8569309e6 100644 (file)
@@ -157,6 +157,7 @@ enum {
        /* Power - legacy power table command */
        POWER_TABLE_CMD = 0x77,
        PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
+       LTR_CONFIG = 0xee,
 
        /* Thermal Throttling*/
        REPLY_THERMAL_MNG_BACKOFF = 0x7e,
index 23fd711a67e456055b50d171ec243a124ca3ce6c..eb03943f846326207061a2ed63e95df09af93caf 100644 (file)
@@ -284,7 +284,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 
        lockdep_assert_held(&mvm->mutex);
 
-       if (WARN_ON_ONCE(mvm->init_ucode_complete))
+       if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
                return 0;
 
        iwl_init_notification_wait(&mvm->notif_wait,
@@ -334,6 +334,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                goto out;
        }
 
+       mvm->calibrating = true;
+
        /* Send TX valid antennas before triggering calibrations */
        ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
        if (ret)
@@ -358,11 +360,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                        MVM_UCODE_CALIB_TIMEOUT);
        if (!ret)
                mvm->init_ucode_complete = true;
+
+       if (ret && iwl_mvm_is_radio_killed(mvm)) {
+               IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
+               ret = 1;
+       }
        goto out;
 
 error:
        iwl_remove_notification(&mvm->notif_wait, &calib_wait);
 out:
+       mvm->calibrating = false;
        if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
                /* we want to debug INIT and we have no NVM - fake */
                mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
@@ -480,6 +488,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
        /* Initialize tx backoffs to the minimal possible */
        iwl_mvm_tt_tx_backoff(mvm, 0);
 
+       if (mvm->trans->ltr_enabled) {
+               struct iwl_ltr_config_cmd cmd = {
+                       .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
+               };
+
+               WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
+                                            sizeof(cmd), &cmd));
+       }
+
        ret = iwl_mvm_power_update_device(mvm);
        if (ret)
                goto error;
index c7a73c68bdabddcb2eb2536256e0a7736be06dc1..b6d2683da3a96dab9c53d0c6f291ab69de6e9e8f 100644 (file)
@@ -526,7 +526,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
        }
 
        if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
-           !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
+           !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) &&
+           !test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
                goto drop;
 
        /* treat non-bufferable MMPDUs as broadcast if sta is sleeping */
@@ -787,6 +788,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 
        mvm->scan_status = IWL_MVM_SCAN_NONE;
        mvm->ps_disabled = false;
+       mvm->calibrating = false;
 
        /* just in case one was running */
        ieee80211_remain_on_channel_expired(mvm->hw);
@@ -1734,6 +1736,13 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
        if (changes & BSS_CHANGED_BEACON &&
            iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
                IWL_WARN(mvm, "Failed updating beacon data\n");
+
+       if (changes & BSS_CHANGED_TXPOWER) {
+               IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
+                               bss_conf->txpower);
+               iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
+       }
+
 }
 
 static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
@@ -2367,14 +2376,19 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
        /* Set the node address */
        memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
 
+       lockdep_assert_held(&mvm->mutex);
+
+       spin_lock_bh(&mvm->time_event_lock);
+
+       if (WARN_ON(te_data->id == HOT_SPOT_CMD)) {
+               spin_unlock_bh(&mvm->time_event_lock);
+               return -EIO;
+       }
+
        te_data->vif = vif;
        te_data->duration = duration;
        te_data->id = HOT_SPOT_CMD;
 
-       lockdep_assert_held(&mvm->mutex);
-
-       spin_lock_bh(&mvm->time_event_lock);
-       list_add_tail(&te_data->list, &mvm->time_event_list);
        spin_unlock_bh(&mvm->time_event_lock);
 
        /*
@@ -2430,22 +2444,29 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
        IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
                           duration, type);
 
+       mutex_lock(&mvm->mutex);
+
        switch (vif->type) {
        case NL80211_IFTYPE_STATION:
-               /* Use aux roc framework (HS20) */
-               ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
-                                              vif, duration);
-               return ret;
+               if (mvm->fw->ucode_capa.capa[0] &
+                   IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT) {
+                       /* Use aux roc framework (HS20) */
+                       ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
+                                                      vif, duration);
+                       goto out_unlock;
+               }
+               IWL_ERR(mvm, "hotspot not supported\n");
+               ret = -EINVAL;
+               goto out_unlock;
        case NL80211_IFTYPE_P2P_DEVICE:
                /* handle below */
                break;
        default:
                IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out_unlock;
        }
 
-       mutex_lock(&mvm->mutex);
-
        for (i = 0; i < NUM_PHY_CTX; i++) {
                phy_ctxt = &mvm->phy_ctxts[i];
                if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt)
index b153ced7015bfef8984a9ecb78f844d4533ed7d9..845429c88cf403fdaffee73951fa99251b619137 100644 (file)
@@ -548,6 +548,7 @@ struct iwl_mvm {
        enum iwl_ucode_type cur_ucode;
        bool ucode_loaded;
        bool init_ucode_complete;
+       bool calibrating;
        u32 error_event_table;
        u32 log_event_table;
        u32 umac_error_event_table;
index 15aa298ee79c749b5e7e7e7401d92375a270c29e..5b719ee8e789075e6e7517512ca311cb6f9b6121 100644 (file)
@@ -336,6 +336,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
        CMD(DTS_MEASUREMENT_NOTIFICATION),
        CMD(REPLY_THERMAL_MNG_BACKOFF),
        CMD(MAC_PM_POWER_TABLE),
+       CMD(LTR_CONFIG),
        CMD(BT_COEX_CI),
        CMD(BT_COEX_UPDATE_SW_BOOST),
        CMD(BT_COEX_UPDATE_CORUN_LUT),
@@ -423,6 +424,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        }
        mvm->sf_state = SF_UNINIT;
        mvm->low_latency_agg_frame_limit = 6;
+       mvm->cur_ucode = IWL_UCODE_INIT;
 
        mutex_init(&mvm->mutex);
        mutex_init(&mvm->d0i3_suspend_mutex);
@@ -751,6 +753,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
 static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 {
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+       bool calibrating = ACCESS_ONCE(mvm->calibrating);
 
        if (state)
                set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@@ -759,7 +762,15 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 
        wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
 
-       return state && mvm->cur_ucode != IWL_UCODE_INIT;
+       /* iwl_run_init_mvm_ucode is waiting for results, abort it */
+       if (calibrating)
+               iwl_abort_notification_waits(&mvm->notif_wait);
+
+       /*
+        * Stop the device if we run OPERATIONAL firmware or if we are in the
+        * middle of the calibrations.
+        */
+       return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating);
 }
 
 static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
index cb85e63c20aa340d70f2be0a3c4f48c3781e8182..7554f705383063fa3c7c3610595e9e39f0cc9af8 100644 (file)
@@ -459,7 +459,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
                                basic_ssid ? 1 : 0);
 
        cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
-                                          TX_CMD_FLG_BT_DIS);
+                                          3 << TX_CMD_FLG_BT_PRIO_POS);
+
        cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id;
        cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
        cmd->tx_cmd.rate_n_flags =
@@ -601,16 +602,6 @@ static int iwl_mvm_cancel_regular_scan(struct iwl_mvm *mvm)
                                               SCAN_COMPLETE_NOTIFICATION };
        int ret;
 
-       if (mvm->scan_status == IWL_MVM_SCAN_NONE)
-               return 0;
-
-       if (iwl_mvm_is_radio_killed(mvm)) {
-               ieee80211_scan_completed(mvm->hw, true);
-               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-               mvm->scan_status = IWL_MVM_SCAN_NONE;
-               return 0;
-       }
-
        iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
                                   scan_abort_notif,
                                   ARRAY_SIZE(scan_abort_notif),
@@ -1399,6 +1390,16 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
 
 int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
 {
+       if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+               return 0;
+
+       if (iwl_mvm_is_radio_killed(mvm)) {
+               ieee80211_scan_completed(mvm->hw, true);
+               iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+               mvm->scan_status = IWL_MVM_SCAN_NONE;
+               return 0;
+       }
+
        if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
                return iwl_mvm_scan_offload_stop(mvm, true);
        return iwl_mvm_cancel_regular_scan(mvm);
index b7f9e61d14e276f5505060a0e1cc78e3f2d1af4c..6dfad230be5ed658f2cb3f295e71b43d724d293c 100644 (file)
@@ -305,8 +305,8 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
                te_data->running = false;
                te_data->vif = NULL;
                te_data->uid = 0;
+               te_data->id = TE_MAX;
        } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
-               set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
                set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
                te_data->running = true;
                ieee80211_ready_on_channel(mvm->hw); /* Start TE */
index 1cb793a498ac88a221cccb9e5efa31267e4cb028..c6a517c771df5045cd5d2cecc80b4b29848a6c9c 100644 (file)
@@ -175,14 +175,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
 
        /*
         * for data packets, rate info comes from the table inside the fw. This
-        * table is controlled by LINK_QUALITY commands. Exclude ctrl port
-        * frames like EAPOLs which should be treated as mgmt frames. This
-        * avoids them being sent initially in high rates which increases the
-        * chances for completion of the 4-Way handshake.
+        * table is controlled by LINK_QUALITY commands
         */
 
-       if (ieee80211_is_data(fc) && sta &&
-           !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) {
+       if (ieee80211_is_data(fc) && sta) {
                tx_cmd->initial_rate_index = 0;
                tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
                return;
index 1393bac0025c59de0b24b1453eb7932bebda1b22..dd2f3f8baa9dbea639005b3b65dbbbda9109408f 100644 (file)
@@ -174,6 +174,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        u16 lctl;
+       u16 cap;
 
        /*
         * HW bug W/A for instability in PCIe bus L0S->L1 transition.
@@ -184,16 +185,17 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
         *    power savings, even without L1.
         */
        pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
-       if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
-               /* L1-ASPM enabled; disable(!) L0S */
+       if (lctl & PCI_EXP_LNKCTL_ASPM_L1)
                iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
-               dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
-       } else {
-               /* L1-ASPM disabled; enable(!) L0S */
+       else
                iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
-               dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
-       }
        trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
+
+       pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
+       trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
+       dev_info(trans->dev, "L1 %sabled - LTR %sabled\n",
+                (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
+                trans->ltr_enabled ? "En" : "Dis");
 }
 
 /*
@@ -428,7 +430,7 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
        ret = iwl_poll_bit(trans, CSR_RESET,
                           CSR_RESET_REG_FLAG_MASTER_DISABLED,
                           CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
-       if (ret)
+       if (ret < 0)
                IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n");
 
        IWL_DEBUG_INFO(trans, "stop master\n");
@@ -544,7 +546,7 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
                msleep(25);
        }
 
-       IWL_DEBUG_INFO(trans, "got NIC after %d iterations\n", iter);
+       IWL_ERR(trans, "Couldn't prepare the card\n");
 
        return ret;
 }
@@ -913,7 +915,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
         * restart. So don't process again if the device is
         * already dead.
         */
-       if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+       if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+               IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
                iwl_pcie_tx_stop(trans);
                iwl_pcie_rx_stop(trans);
 
@@ -943,7 +946,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
        /* clear all status bits */
        clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
        clear_bit(STATUS_INT_ENABLED, &trans->status);
-       clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
        clear_bit(STATUS_TPOWER_PMI, &trans->status);
        clear_bit(STATUS_RFKILL, &trans->status);
 
@@ -1043,7 +1045,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
                           CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
                           CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
                           25000);
-       if (ret) {
+       if (ret < 0) {
                IWL_ERR(trans, "Failed to resume the device (mac ready)\n");
                return ret;
        }
@@ -1892,8 +1894,7 @@ static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
                int reg;
                __le32 *val;
 
-               prph_len += sizeof(*data) + sizeof(*prph) +
-                       num_bytes_in_chunk;
+               prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
 
                (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
                (*data)->len = cpu_to_le32(sizeof(*prph) +
index babbdc1ce741c62024bc6220fdcf2a7bd3487790..c9ad4cf1adfb4b1d7a30068c2546ac7354345139 100644 (file)
@@ -1987,7 +1987,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
        if (err != 0) {
                printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n",
                       err);
-               goto failed_hw;
+               goto failed_bind;
        }
 
        skb_queue_head_init(&data->pending);
@@ -2183,6 +2183,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
        return idx;
 
 failed_hw:
+       device_release_driver(data->dev);
+failed_bind:
        device_unregister(data->dev);
 failed_drvdata:
        ieee80211_free_hw(hw);
index 40057079ffb9537eae9549518be3e5df29f1a16b..5ef5a0eeba50eb682d30e5879f565ac48ad217e4 100644 (file)
@@ -196,6 +196,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
        mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
 
        del_timer_sync(&tbl->timer_context.timer);
+       tbl->timer_context.timer_is_set = false;
 
        spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
        list_del(&tbl->list);
@@ -297,6 +298,7 @@ mwifiex_flush_data(unsigned long context)
                (struct reorder_tmr_cnxt *) context;
        int start_win, seq_num;
 
+       ctx->timer_is_set = false;
        seq_num = mwifiex_11n_find_last_seq_num(ctx);
 
        if (seq_num < 0)
@@ -385,6 +387,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
 
        new_node->timer_context.ptr = new_node;
        new_node->timer_context.priv = priv;
+       new_node->timer_context.timer_is_set = false;
 
        init_timer(&new_node->timer_context.timer);
        new_node->timer_context.timer.function = mwifiex_flush_data;
@@ -399,6 +402,22 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
        spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
 }
 
+static void
+mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
+{
+       u32 min_flush_time;
+
+       if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
+               min_flush_time = MIN_FLUSH_TIMER_15_MS;
+       else
+               min_flush_time = MIN_FLUSH_TIMER_MS;
+
+       mod_timer(&tbl->timer_context.timer,
+                 jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
+
+       tbl->timer_context.timer_is_set = true;
+}
+
 /*
  * This function prepares command for adding a BA request.
  *
@@ -523,31 +542,31 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                                u8 *ta, u8 pkt_type, void *payload)
 {
        struct mwifiex_rx_reorder_tbl *tbl;
-       int start_win, end_win, win_size;
+       int prev_start_win, start_win, end_win, win_size;
        u16 pkt_index;
        bool init_window_shift = false;
+       int ret = 0;
 
        tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
        if (!tbl) {
                if (pkt_type != PKT_TYPE_BAR)
                        mwifiex_11n_dispatch_pkt(priv, payload);
-               return 0;
+               return ret;
        }
 
        if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
                mwifiex_11n_dispatch_pkt(priv, payload);
-               return 0;
+               return ret;
        }
 
        start_win = tbl->start_win;
+       prev_start_win = start_win;
        win_size = tbl->win_size;
        end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
        if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
                init_window_shift = true;
                tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
        }
-       mod_timer(&tbl->timer_context.timer,
-                 jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
 
        if (tbl->flags & RXREOR_FORCE_NO_DROP) {
                dev_dbg(priv->adapter->dev,
@@ -568,11 +587,14 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
                        if (seq_num >= ((start_win + TWOPOW11) &
                                        (MAX_TID_VALUE - 1)) &&
-                           seq_num < start_win)
-                               return -1;
+                           seq_num < start_win) {
+                               ret = -1;
+                               goto done;
+                       }
                } else if ((seq_num < start_win) ||
-                          (seq_num > (start_win + TWOPOW11))) {
-                       return -1;
+                          (seq_num >= (start_win + TWOPOW11))) {
+                       ret = -1;
+                       goto done;
                }
        }
 
@@ -601,8 +623,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
                else
                        pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
 
-               if (tbl->rx_reorder_ptr[pkt_index])
-                       return -1;
+               if (tbl->rx_reorder_ptr[pkt_index]) {
+                       ret = -1;
+                       goto done;
+               }
 
                tbl->rx_reorder_ptr[pkt_index] = payload;
        }
@@ -613,7 +637,11 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
         */
        mwifiex_11n_scan_and_dispatch(priv, tbl);
 
-       return 0;
+done:
+       if (!tbl->timer_context.timer_is_set ||
+           prev_start_win != tbl->start_win)
+               mwifiex_11n_rxreorder_timer_restart(tbl);
+       return ret;
 }
 
 /*
index 3a87bb0e3a62adb477784a94feba13cefd32626b..63ecea89b4ab562cc00942b2542fac63ed8202e0 100644 (file)
@@ -21,6 +21,8 @@
 #define _MWIFIEX_11N_RXREORDER_H_
 
 #define MIN_FLUSH_TIMER_MS             50
+#define MIN_FLUSH_TIMER_15_MS          15
+#define MWIFIEX_BA_WIN_SIZE_32         32
 
 #define PKT_TYPE_BAR 0xE7
 #define MAX_TID_VALUE                  (2 << 11)
index e2635747d9669c21f30f08780a2024c70af2245e..f55658d15c60710d44603d12b9fbab58414050fc 100644 (file)
@@ -592,6 +592,7 @@ struct reorder_tmr_cnxt {
        struct timer_list timer;
        struct mwifiex_rx_reorder_tbl *ptr;
        struct mwifiex_private *priv;
+       u8 timer_is_set;
 };
 
 struct mwifiex_rx_reorder_tbl {
index 573897b8e878a2e6bfc3aa61a9df72d9b99e0372..8444313eabe2bbc1bdcb660c5a82bff17f3fdb90 100644 (file)
@@ -1111,6 +1111,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
        /* Ovislink */
        { USB_DEVICE(0x1b75, 0x3071) },
        { USB_DEVICE(0x1b75, 0x3072) },
+       { USB_DEVICE(0x1b75, 0xa200) },
        /* Para */
        { USB_DEVICE(0x20b8, 0x8888) },
        /* Pegatron */
index 8e68f87ab13c3081f062acc69fb71f59601e836f..66ff36447b9473799e27899bf44c3c3c8eb3994b 100644 (file)
@@ -158,55 +158,29 @@ void rt2x00queue_align_frame(struct sk_buff *skb)
        skb_trim(skb, frame_length);
 }
 
-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
+/*
+ * H/W needs L2 padding between the header and the paylod if header size
+ * is not 4 bytes aligned.
+ */
+void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len)
 {
-       unsigned int payload_length = skb->len - header_length;
-       unsigned int header_align = ALIGN_SIZE(skb, 0);
-       unsigned int payload_align = ALIGN_SIZE(skb, header_length);
-       unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
+       unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
 
-       /*
-        * Adjust the header alignment if the payload needs to be moved more
-        * than the header.
-        */
-       if (payload_align > header_align)
-               header_align += 4;
-
-       /* There is nothing to do if no alignment is needed */
-       if (!header_align)
+       if (!l2pad)
                return;
 
-       /* Reserve the amount of space needed in front of the frame */
-       skb_push(skb, header_align);
-
-       /*
-        * Move the header.
-        */
-       memmove(skb->data, skb->data + header_align, header_length);
-
-       /* Move the payload, if present and if required */
-       if (payload_length && payload_align)
-               memmove(skb->data + header_length + l2pad,
-                       skb->data + header_length + l2pad + payload_align,
-                       payload_length);
-
-       /* Trim the skb to the correct size */
-       skb_trim(skb, header_length + l2pad + payload_length);
+       skb_push(skb, l2pad);
+       memmove(skb->data, skb->data + l2pad, hdr_len);
 }
 
-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
+void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len)
 {
-       /*
-        * L2 padding is only present if the skb contains more than just the
-        * IEEE 802.11 header.
-        */
-       unsigned int l2pad = (skb->len > header_length) ?
-                               L2PAD_SIZE(header_length) : 0;
+       unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
 
        if (!l2pad)
                return;
 
-       memmove(skb->data + l2pad, skb->data, header_length);
+       memmove(skb->data + l2pad, skb->data, hdr_len);
        skb_pull(skb, l2pad);
 }
 
index 58ba718308862391b108a41e0eab1e7ff7fa226a..40b6d1d006d7ab7dc9076a967fedae75259dc1fd 100644 (file)
@@ -467,7 +467,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
                    rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
        /* <2> work queue */
        rtlpriv->works.hw = hw;
-       rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
+       rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
        INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
                          (void *)rtl_watchdog_wq_callback);
        INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
index f6179bc060869cfdb6dd6d9d9c90d8cc43197904..07dae0d44abc09a78025d71e32570dc68b50194c 100644 (file)
@@ -1828,3 +1828,9 @@ const struct ieee80211_ops rtl_ops = {
        .flush = rtl_op_flush,
 };
 EXPORT_SYMBOL_GPL(rtl_ops);
+
+bool rtl_btc_status_false(void)
+{
+       return false;
+}
+EXPORT_SYMBOL_GPL(rtl_btc_status_false);
index 59cd3b9dca25f895bcd6ee24f43f366867c8e41a..624e1dc16d31d383ba92cbc8cd08e28d180df882 100644 (file)
@@ -42,5 +42,6 @@ void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr,
                     u32 mask, u32 data);
 void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data);
 bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
+bool rtl_btc_status_false(void);
 
 #endif
index 667aba81246c9ac094db11a5c455be9c29d273ad..846a2e6e34d855d62726eda65b51ee427bc1a939 100644 (file)
@@ -842,7 +842,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
                        break;
                }
                /* handle command packet here */
-               if (rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
+               if (rtlpriv->cfg->ops->rx_command_packet &&
+                   rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
                                dev_kfree_skb_any(skb);
                                goto end;
                }
@@ -1127,9 +1128,14 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
 
        __skb_queue_tail(&ring->queue, pskb);
 
-       rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
-                                   &temp_one);
-
+       if (rtlpriv->use_new_trx_flow) {
+               temp_one = 4;
+               rtlpriv->cfg->ops->set_desc(hw, (u8 *)pbuffer_desc, true,
+                                           HW_DESC_OWN, (u8 *)&temp_one);
+       } else {
+               rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
+                                           &temp_one);
+       }
        return;
 }
 
@@ -1370,9 +1376,9 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
        ring->desc = NULL;
        if (rtlpriv->use_new_trx_flow) {
                pci_free_consistent(rtlpci->pdev,
-                                   sizeof(*ring->desc) * ring->entries,
+                                   sizeof(*ring->buffer_desc) * ring->entries,
                                    ring->buffer_desc, ring->buffer_desc_dma);
-               ring->desc = NULL;
+               ring->buffer_desc = NULL;
        }
 }
 
@@ -1543,7 +1549,6 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
                                                         true,
                                                         HW_DESC_TXBUFF_ADDR),
                                                 skb->len, PCI_DMA_TODEVICE);
-                               ring->idx = (ring->idx + 1) % ring->entries;
                                kfree_skb(skb);
                                ring->idx = (ring->idx + 1) % ring->entries;
                        }
@@ -1796,7 +1801,8 @@ static int rtl_pci_start(struct ieee80211_hw *hw)
        rtl_pci_reset_trx_ring(hw);
 
        rtlpci->driver_is_goingto_unload = false;
-       if (rtlpriv->cfg->ops->get_btc_status()) {
+       if (rtlpriv->cfg->ops->get_btc_status &&
+           rtlpriv->cfg->ops->get_btc_status()) {
                rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv);
                rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv);
        }
@@ -2243,6 +2249,16 @@ int rtl_pci_probe(struct pci_dev *pdev,
        /*like read eeprom and so on */
        rtlpriv->cfg->ops->read_eeprom_info(hw);
 
+       if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
+               err = -ENODEV;
+               goto fail3;
+       }
+       rtlpriv->cfg->ops->init_sw_leds(hw);
+
+       /*aspm */
+       rtl_pci_init_aspm(hw);
+
        /* Init mac80211 sw */
        err = rtl_init_core(hw);
        if (err) {
@@ -2258,16 +2274,6 @@ int rtl_pci_probe(struct pci_dev *pdev,
                goto fail3;
        }
 
-       if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
-               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
-               err = -ENODEV;
-               goto fail3;
-       }
-       rtlpriv->cfg->ops->init_sw_leds(hw);
-
-       /*aspm */
-       rtl_pci_init_aspm(hw);
-
        err = ieee80211_register_hw(hw);
        if (err) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
index a00861b26ece7ae6b2c6168ca22bdaed42c71033..29983bc96a89289187617a5cf202386f74386639 100644 (file)
@@ -656,7 +656,8 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
+        bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -722,7 +723,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
        memcpy((u8 *)skb_put(skb, totalpacketlen),
               &reserved_page_packet, totalpacketlen);
 
-       rtstatus = rtl_cmd_send_packet(hw, skb);
+       if (cmd_send_packet)
+               rtstatus = cmd_send_packet(hw, skb);
+       else
+               rtstatus = rtl_cmd_send_packet(hw, skb);
 
        if (rtstatus)
                b_dlok = true;
index a815bd6273da0645cf86f6f77050f220875ec6ff..b64ae45dc6743869da3746a7382683936e86f88c 100644 (file)
@@ -109,7 +109,9 @@ void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
                         u32 cmd_len, u8 *p_cmdbuffer);
 void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92c_set_fw_rsvdpagepkt
+       (struct ieee80211_hw *hw,
+        bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *));
 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
 void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
 void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
index 831df101d7b7a97866b55283c8e998e3c9152806..9b660df6fd712fd517638723bb0616b17b9df257 100644 (file)
        LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
 #define        GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr)       \
        LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
+#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc)                  \
+       SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
 
 #define CHIP_VER_B                     BIT(4)
 #define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
index 8ec0f031f48a575035dbe59af4b2f236d4260c72..55357d69397a3370d8f4081ecec3d578daa3b8b9 100644 (file)
@@ -459,7 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
                                rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
                                               tmp_reg422 & (~BIT(6)));
 
-                               rtl92c_set_fw_rsvdpagepkt(hw, 0);
+                               rtl92c_set_fw_rsvdpagepkt(hw, NULL);
 
                                _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
                                _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4));
index d86b5b566444e1098a666909e3d86865c00f0b7c..46ea07605eb47f449f7850dea3b8b0862555ffde 100644 (file)
@@ -244,6 +244,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
        .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate,
        .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback,
        .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower,
+       .get_btc_status = rtl_btc_status_false,
 };
 
 static struct rtl_mod_params rtl92ce_mod_params = {
index 2fb9c7acb76a3bf7d6fa1feee728b15365b86207..dc3d20b17a265479906fa9d6777cc6e29e533f34 100644 (file)
@@ -728,6 +728,9 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
                case HW_DESC_RXPKT_LEN:
                        ret = GET_RX_DESC_PKT_LEN(pdesc);
                        break;
+               case HW_DESC_RXBUFF_ADDR:
+                       ret = GET_RX_STATUS_DESC_BUFF_ADDR(pdesc);
+                       break;
                default:
                        RT_ASSERT(false, "ERR rxdesc :%d not process\n",
                                  desc_name);
index 04aa0b5f5b3d10a1ae16eb8db5ea74d4f38e1890..873363acbacfac12df0d0c724dc962c74b2a2fc7 100644 (file)
@@ -1592,6 +1592,20 @@ void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
        }
 }
 
+bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+  /* Currently nothing happens here.
+   * Traffic stops after some seconds in WPA2 802.11n mode.
+   * Maybe because rtl8192cu chip should be set from here?
+   * If I understand correctly, the realtek vendor driver sends some urbs
+   * if its "here".
+   *
+   * This is maybe necessary:
+   * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb);
+   */
+       return true;
+}
+
 void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1939,7 +1953,8 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
                                        recover = true;
                                rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
                                               tmp_reg422 & (~BIT(6)));
-                               rtl92c_set_fw_rsvdpagepkt(hw, 0);
+                               rtl92c_set_fw_rsvdpagepkt(hw,
+                                                         &usb_cmd_send_packet);
                                _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
                                _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
                                if (recover)
index 0f7812e0c8aa0c75d5382c52b4872431447c8108..c1e33b0228c0176e1ae31f5a8f99085a4f840397 100644 (file)
@@ -104,7 +104,6 @@ bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid);
 void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
 int rtl92c_download_fw(struct ieee80211_hw *hw);
 void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
 void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
 void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
                         u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
index 7c5fbaf5fee0d790d1cfbeaa563a1c360a1a976b..e06bafee37f9764b4041bd64665c46e3a889d238 100644 (file)
@@ -101,6 +101,12 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw)
        }
 }
 
+/* get bt coexist status */
+static bool rtl92cu_get_btc_status(void)
+{
+       return false;
+}
+
 static struct rtl_hal_ops rtl8192cu_hal_ops = {
        .init_sw_vars = rtl92cu_init_sw_vars,
        .deinit_sw_vars = rtl92cu_deinit_sw_vars,
@@ -148,6 +154,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = {
        .phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
        .dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
        .fill_h2c_cmd = rtl92c_fill_h2c_cmd,
+       .get_btc_status = rtl92cu_get_btc_status,
 };
 
 static struct rtl_mod_params rtl92cu_mod_params = {
index edab5a5351b52a814ec10833109666309279e2b1..a0aba088259aa97b6f80fb37e02d6f0c881b039b 100644 (file)
@@ -251,6 +251,7 @@ static struct rtl_hal_ops rtl8192de_hal_ops = {
        .get_rfreg = rtl92d_phy_query_rf_reg,
        .set_rfreg = rtl92d_phy_set_rf_reg,
        .linked_set_reg = rtl92d_linked_set_reg,
+       .get_btc_status = rtl_btc_status_false,
 };
 
 static struct rtl_mod_params rtl92de_mod_params = {
index dfdc9b20e4ad4d868012c80f4233559e58050052..1a87edca2c3f36a1d540eabc4c3247da5b1959d6 100644 (file)
@@ -362,7 +362,7 @@ void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
                }
                break;
        default:
-               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
                         "switch case not process %x\n", variable);
                break;
        }
@@ -591,7 +591,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
                                acm_ctrl &= (~ACMHW_BEQEN);
                                break;
                        default:
-                               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+                               RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
                                         "switch case not process\n");
                                break;
                        }
@@ -710,7 +710,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
                }
                break;
        default:
-               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
                         "switch case not process %x\n", variable);
                break;
        }
@@ -2424,7 +2424,7 @@ void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index,
                        enc_algo = CAM_AES;
                        break;
                default:
-                       RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+                       RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
                                 "switch case not process\n");
                        enc_algo = CAM_TKIP;
                        break;
index 83c98674bfd3176f8fc512f80b7a31be83ba87da..6e7a70b43949eab504d70a70742dc216fb6e27d1 100644 (file)
 /* DWORD 6 */
 #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val)  \
        SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
+#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc)                  \
+       SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
 
 #define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
        (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||  \
index 00e067044c08d0a9cafa9009466eb22c21965d56..5761d5b49e39e4e9cb2ce703f39578ad1cf99e74 100644 (file)
@@ -1201,6 +1201,9 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,
 
        }
 
+       if (type != NL80211_IFTYPE_AP &&
+           rtlpriv->mac80211.link_state < MAC80211_LINKED)
+               bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK;
        rtl_write_byte(rtlpriv, (MSR), bt_msr);
 
        temp = rtl_read_dword(rtlpriv, TCR);
@@ -1262,6 +1265,7 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)
        rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);
        /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */
        rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);
+       rtlpci->irq_enabled = true;
 }
 
 void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
@@ -1276,8 +1280,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
        rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        rtl_write_dword(rtlpriv, INTA_MASK, 0);
        rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
-
-       synchronize_irq(rtlpci->pdev->irq);
+       rtlpci->irq_enabled = false;
 }
 
 static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
index 77c5b5f352441a3a2a2d0c26b5627266aa15d5d9..4b4612fe2fdbdf318bad0b0a6e36873a6340d60b 100644 (file)
@@ -399,6 +399,8 @@ static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
                case 2:
                        currentcmd = &postcommoncmd[*step];
                        break;
+               default:
+                       return true;
                }
 
                if (currentcmd->cmdid == CMDID_END) {
index 1bff2a0f760087d0a510e247f01d1c6a33eee891..fb003868bdef7ed9bbb775042a380190ce68162d 100644 (file)
@@ -87,11 +87,8 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
 static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
 {
        struct ieee80211_hw *hw = context;
-       struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
        struct rt_firmware *pfirmware = NULL;
-       int err;
 
        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
                         "Firmware callback routine entered!\n");
@@ -112,20 +109,6 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
        memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
        pfirmware->sz_fw_tmpbufferlen = firmware->size;
        release_firmware(firmware);
-
-       err = ieee80211_register_hw(hw);
-       if (err) {
-               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-                        "Can't register mac80211 hw\n");
-               return;
-       } else {
-               rtlpriv->mac80211.mac80211_registered = 1;
-       }
-       rtlpci->irq_alloc = 1;
-       set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
-
-       /*init rfkill */
-       rtl_init_rfkill(hw);
 }
 
 static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
@@ -226,8 +209,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
        if (!rtlpriv->rtlhal.pfirmware)
                return 1;
 
-       rtlpriv->max_fw_size = RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE;
-
+       rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 +
+                              sizeof(struct fw_hdr);
        pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
                "Loading firmware %s\n", rtlpriv->cfg->fw_name);
        /* request fw */
@@ -253,6 +236,19 @@ static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw)
        }
 }
 
+static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue,
+                                     u16 index)
+{
+       struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+       struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
+       u8 *entry = (u8 *)(&ring->desc[ring->idx]);
+       u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN);
+
+       if (own)
+               return false;
+       return true;
+}
+
 static struct rtl_hal_ops rtl8192se_hal_ops = {
        .init_sw_vars = rtl92s_init_sw_vars,
        .deinit_sw_vars = rtl92s_deinit_sw_vars,
@@ -286,6 +282,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
        .led_control = rtl92se_led_control,
        .set_desc = rtl92se_set_desc,
        .get_desc = rtl92se_get_desc,
+       .is_tx_desc_closed = rtl92se_is_tx_desc_closed,
        .tx_polling = rtl92se_tx_polling,
        .enable_hw_sec = rtl92se_enable_hw_security_config,
        .set_key = rtl92se_set_key,
@@ -294,6 +291,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
        .set_bbreg = rtl92s_phy_set_bb_reg,
        .get_rfreg = rtl92s_phy_query_rf_reg,
        .set_rfreg = rtl92s_phy_set_rf_reg,
+       .get_btc_status = rtl_btc_status_false,
 };
 
 static struct rtl_mod_params rtl92se_mod_params = {
@@ -322,6 +320,8 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {
        .maps[MAC_RCR_ACRC32] = RCR_ACRC32,
        .maps[MAC_RCR_ACF] = RCR_ACF,
        .maps[MAC_RCR_AAP] = RCR_AAP,
+       .maps[MAC_HIMR] = INTA_MASK,
+       .maps[MAC_HIMRE] = INTA_MASK + 4,
 
        .maps[EFUSE_TEST] = REG_EFUSE_TEST,
        .maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
index b358ebce8942127413105b39e3799006d559eed8..672fd3b02835e30414044311af02a3383886e554 100644 (file)
@@ -640,6 +640,9 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
                case HW_DESC_RXPKT_LEN:
                        ret = GET_RX_STATUS_DESC_PKT_LEN(desc);
                        break;
+               case HW_DESC_RXBUFF_ADDR:
+                       ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc);
+                       break;
                default:
                        RT_ASSERT(false, "ERR rxdesc :%d not process\n",
                                  desc_name);
index 310d3163dc5b6a3f1e51a9a59ed999fe991a2f06..8ec8200002c7311025b3ae645c9956bf08c44a17 100644 (file)
@@ -3672,8 +3672,9 @@ static void rtl8821ae_update_hal_rate_mask(struct ieee80211_hw *hw,
                mac->opmode == NL80211_IFTYPE_ADHOC)
                macid = sta->aid + 1;
        if (wirelessmode == WIRELESS_MODE_N_5G ||
-           wirelessmode == WIRELESS_MODE_AC_5G)
-               ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ];
+           wirelessmode == WIRELESS_MODE_AC_5G ||
+           wirelessmode == WIRELESS_MODE_A)
+               ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ] << 4;
        else
                ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ];
 
index 9786313dc62f2b3a50143bffc59255e8f1d45af8..1e9570fa874fe6309962d2de2251fc923da424cb 100644 (file)
@@ -1889,15 +1889,18 @@ static void _rtl8821ae_store_tx_power_by_rate(struct ieee80211_hw *hw,
        struct rtl_phy *rtlphy = &rtlpriv->phy;
        u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr);
 
-       if (band != BAND_ON_2_4G && band != BAND_ON_5G)
+       if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
                RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band);
-
-       if (rfpath >= MAX_RF_PATH)
+               band = BAND_ON_2_4G;
+       }
+       if (rfpath >= MAX_RF_PATH) {
                RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath);
-
-       if (txnum >= MAX_RF_PATH)
+               rfpath = MAX_RF_PATH - 1;
+       }
+       if (txnum >= MAX_RF_PATH) {
                RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum);
-
+               txnum = MAX_RF_PATH - 1;
+       }
        rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data;
        RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
                 "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n",
index 10cf69c4bc42ea93adefdab5569cbe90a19a4a63..46ee956d0235dc79dbb8130242b5b2586fd4db5e 100644 (file)
@@ -1117,7 +1117,18 @@ int rtl_usb_probe(struct usb_interface *intf,
        }
        rtlpriv->cfg->ops->init_sw_leds(hw);
 
+       err = ieee80211_register_hw(hw);
+       if (err) {
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+                        "Can't register mac80211 hw.\n");
+               err = -ENODEV;
+               goto error_out;
+       }
+       rtlpriv->mac80211.mac80211_registered = 1;
+
+       set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
        return 0;
+
 error_out:
        rtl_deinit_core(hw);
        _rtl_usb_io_handler_release(hw);
index d4eb8d2e9cb7f7f2bc0b3816dd788e6eb01c7927..083ecc93fe5e7b0941aedba3ccb9fd27158cc03b 100644 (file)
@@ -176,10 +176,11 @@ struct xenvif_queue { /* Per-queue data for xenvif */
        char rx_irq_name[IRQ_NAME_SIZE]; /* DEVNAME-qN-rx */
        struct xen_netif_rx_back_ring rx;
        struct sk_buff_head rx_queue;
-       RING_IDX rx_last_skb_slots;
-       unsigned long status;
 
-       struct timer_list rx_stalled;
+       unsigned int rx_queue_max;
+       unsigned int rx_queue_len;
+       unsigned long last_rx_time;
+       bool stalled;
 
        struct gnttab_copy grant_copy_op[MAX_GRANT_COPY_OPS];
 
@@ -199,18 +200,14 @@ struct xenvif_queue { /* Per-queue data for xenvif */
        struct xenvif_stats stats;
 };
 
+/* Maximum number of Rx slots a to-guest packet may use, including the
+ * slot needed for GSO meta-data.
+ */
+#define XEN_NETBK_RX_SLOTS_MAX (MAX_SKB_FRAGS + 1)
+
 enum state_bit_shift {
        /* This bit marks that the vif is connected */
        VIF_STATUS_CONNECTED,
-       /* This bit signals the RX thread that queuing was stopped (in
-        * start_xmit), and either the timer fired or an RX interrupt came
-        */
-       QUEUE_STATUS_RX_PURGE_EVENT,
-       /* This bit tells the interrupt handler that this queue was the reason
-        * for the carrier off, so it should kick the thread. Only queues which
-        * brought it down can turn on the carrier.
-        */
-       QUEUE_STATUS_RX_STALLED
 };
 
 struct xenvif {
@@ -228,9 +225,6 @@ struct xenvif {
        u8 ip_csum:1;
        u8 ipv6_csum:1;
 
-       /* Internal feature information. */
-       u8 can_queue:1;     /* can queue packets for receiver? */
-
        /* Is this interface disabled? True when backend discovers
         * frontend is rogue.
         */
@@ -240,6 +234,9 @@ struct xenvif {
        /* Queues */
        struct xenvif_queue *queues;
        unsigned int num_queues; /* active queues, resource allocated */
+       unsigned int stalled_queues;
+
+       spinlock_t lock;
 
 #ifdef CONFIG_DEBUG_FS
        struct dentry *xenvif_dbg_root;
@@ -249,6 +246,14 @@ struct xenvif {
        struct net_device *dev;
 };
 
+struct xenvif_rx_cb {
+       unsigned long expires;
+       int meta_slots_used;
+       bool full_coalesce;
+};
+
+#define XENVIF_RX_CB(skb) ((struct xenvif_rx_cb *)(skb)->cb)
+
 static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif)
 {
        return to_xenbus_device(vif->dev->dev.parent);
@@ -272,8 +277,6 @@ void xenvif_xenbus_fini(void);
 
 int xenvif_schedulable(struct xenvif *vif);
 
-int xenvif_must_stop_queue(struct xenvif_queue *queue);
-
 int xenvif_queue_stopped(struct xenvif_queue *queue);
 void xenvif_wake_queue(struct xenvif_queue *queue);
 
@@ -296,6 +299,8 @@ void xenvif_kick_thread(struct xenvif_queue *queue);
 
 int xenvif_dealloc_kthread(void *data);
 
+void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
+
 /* Determine whether the needed number of slots (req) are available,
  * and set req_event if not.
  */
index f379689dde309b7bf63eb511ef7f28a827f71fc5..895fe84011e7ea4a2138b33d9e84ab802f1142f6 100644 (file)
@@ -43,6 +43,9 @@
 #define XENVIF_QUEUE_LENGTH 32
 #define XENVIF_NAPI_WEIGHT  64
 
+/* Number of bytes allowed on the internal guest Rx queue. */
+#define XENVIF_RX_QUEUE_BYTES (XEN_NETIF_RX_RING_SIZE/2 * PAGE_SIZE)
+
 /* This function is used to set SKBTX_DEV_ZEROCOPY as well as
  * increasing the inflight counter. We need to increase the inflight
  * counter because core driver calls into xenvif_zerocopy_callback
@@ -60,20 +63,11 @@ void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
        atomic_dec(&queue->inflight_packets);
 }
 
-static inline void xenvif_stop_queue(struct xenvif_queue *queue)
-{
-       struct net_device *dev = queue->vif->dev;
-
-       if (!queue->vif->can_queue)
-               return;
-
-       netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id));
-}
-
 int xenvif_schedulable(struct xenvif *vif)
 {
        return netif_running(vif->dev) &&
-               test_bit(VIF_STATUS_CONNECTED, &vif->status);
+               test_bit(VIF_STATUS_CONNECTED, &vif->status) &&
+               !vif->disabled;
 }
 
 static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id)
@@ -114,16 +108,7 @@ int xenvif_poll(struct napi_struct *napi, int budget)
 static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
 {
        struct xenvif_queue *queue = dev_id;
-       struct netdev_queue *net_queue =
-               netdev_get_tx_queue(queue->vif->dev, queue->id);
 
-       /* QUEUE_STATUS_RX_PURGE_EVENT is only set if either QDisc was off OR
-        * the carrier went down and this queue was previously blocked
-        */
-       if (unlikely(netif_tx_queue_stopped(net_queue) ||
-                    (!netif_carrier_ok(queue->vif->dev) &&
-                     test_bit(QUEUE_STATUS_RX_STALLED, &queue->status))))
-               set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
        xenvif_kick_thread(queue);
 
        return IRQ_HANDLED;
@@ -151,24 +136,13 @@ void xenvif_wake_queue(struct xenvif_queue *queue)
        netif_tx_wake_queue(netdev_get_tx_queue(dev, id));
 }
 
-/* Callback to wake the queue's thread and turn the carrier off on timeout */
-static void xenvif_rx_stalled(unsigned long data)
-{
-       struct xenvif_queue *queue = (struct xenvif_queue *)data;
-
-       if (xenvif_queue_stopped(queue)) {
-               set_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status);
-               xenvif_kick_thread(queue);
-       }
-}
-
 static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct xenvif *vif = netdev_priv(dev);
        struct xenvif_queue *queue = NULL;
        unsigned int num_queues = vif->num_queues;
        u16 index;
-       int min_slots_needed;
+       struct xenvif_rx_cb *cb;
 
        BUG_ON(skb->dev != dev);
 
@@ -191,30 +165,10 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
            !xenvif_schedulable(vif))
                goto drop;
 
-       /* At best we'll need one slot for the header and one for each
-        * frag.
-        */
-       min_slots_needed = 1 + skb_shinfo(skb)->nr_frags;
-
-       /* If the skb is GSO then we'll also need an extra slot for the
-        * metadata.
-        */
-       if (skb_is_gso(skb))
-               min_slots_needed++;
+       cb = XENVIF_RX_CB(skb);
+       cb->expires = jiffies + rx_drain_timeout_jiffies;
 
-       /* If the skb can't possibly fit in the remaining slots
-        * then turn off the queue to give the ring a chance to
-        * drain.
-        */
-       if (!xenvif_rx_ring_slots_available(queue, min_slots_needed)) {
-               queue->rx_stalled.function = xenvif_rx_stalled;
-               queue->rx_stalled.data = (unsigned long)queue;
-               xenvif_stop_queue(queue);
-               mod_timer(&queue->rx_stalled,
-                         jiffies + rx_drain_timeout_jiffies);
-       }
-
-       skb_queue_tail(&queue->rx_queue, skb);
+       xenvif_rx_queue_tail(queue, skb);
        xenvif_kick_thread(queue);
 
        return NETDEV_TX_OK;
@@ -465,6 +419,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        vif->queues = NULL;
        vif->num_queues = 0;
 
+       spin_lock_init(&vif->lock);
+
        dev->netdev_ops = &xenvif_netdev_ops;
        dev->hw_features = NETIF_F_SG |
                NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
@@ -508,6 +464,8 @@ int xenvif_init_queue(struct xenvif_queue *queue)
        init_timer(&queue->credit_timeout);
        queue->credit_window_start = get_jiffies_64();
 
+       queue->rx_queue_max = XENVIF_RX_QUEUE_BYTES;
+
        skb_queue_head_init(&queue->rx_queue);
        skb_queue_head_init(&queue->tx_queue);
 
@@ -539,8 +497,6 @@ int xenvif_init_queue(struct xenvif_queue *queue)
                queue->grant_tx_handle[i] = NETBACK_INVALID_HANDLE;
        }
 
-       init_timer(&queue->rx_stalled);
-
        return 0;
 }
 
@@ -551,7 +507,6 @@ void xenvif_carrier_on(struct xenvif *vif)
                dev_set_mtu(vif->dev, ETH_DATA_LEN);
        netdev_update_features(vif->dev);
        set_bit(VIF_STATUS_CONNECTED, &vif->status);
-       netif_carrier_on(vif->dev);
        if (netif_running(vif->dev))
                xenvif_up(vif);
        rtnl_unlock();
@@ -611,6 +566,8 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
                disable_irq(queue->rx_irq);
        }
 
+       queue->stalled = true;
+
        task = kthread_create(xenvif_kthread_guest_rx,
                              (void *)queue, "%s-guest-rx", queue->name);
        if (IS_ERR(task)) {
@@ -674,7 +631,6 @@ void xenvif_disconnect(struct xenvif *vif)
                netif_napi_del(&queue->napi);
 
                if (queue->task) {
-                       del_timer_sync(&queue->rx_stalled);
                        kthread_stop(queue->task);
                        queue->task = NULL;
                }
index 08f65996534cbd1b861c0031b70ebd6d78d47720..6563f0713fc0f5e324a18e2d87ba1f4614e1a008 100644 (file)
 bool separate_tx_rx_irq = 1;
 module_param(separate_tx_rx_irq, bool, 0644);
 
-/* When guest ring is filled up, qdisc queues the packets for us, but we have
- * to timeout them, otherwise other guests' packets can get stuck there
+/* The time that packets can stay on the guest Rx internal queue
+ * before they are dropped.
  */
 unsigned int rx_drain_timeout_msecs = 10000;
 module_param(rx_drain_timeout_msecs, uint, 0444);
 unsigned int rx_drain_timeout_jiffies;
 
+/* The length of time before the frontend is considered unresponsive
+ * because it isn't providing Rx slots.
+ */
+static unsigned int rx_stall_timeout_msecs = 60000;
+module_param(rx_stall_timeout_msecs, uint, 0444);
+static unsigned int rx_stall_timeout_jiffies;
+
 unsigned int xenvif_max_queues;
 module_param_named(max_queues, xenvif_max_queues, uint, 0644);
 MODULE_PARM_DESC(max_queues,
@@ -83,7 +90,6 @@ static void make_tx_response(struct xenvif_queue *queue,
                             s8       st);
 
 static inline int tx_work_todo(struct xenvif_queue *queue);
-static inline int rx_work_todo(struct xenvif_queue *queue);
 
 static struct xen_netif_rx_response *make_rx_response(struct xenvif_queue *queue,
                                             u16      id,
@@ -163,6 +169,69 @@ bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue, int needed)
        return false;
 }
 
+void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&queue->rx_queue.lock, flags);
+
+       __skb_queue_tail(&queue->rx_queue, skb);
+
+       queue->rx_queue_len += skb->len;
+       if (queue->rx_queue_len > queue->rx_queue_max)
+               netif_tx_stop_queue(netdev_get_tx_queue(queue->vif->dev, queue->id));
+
+       spin_unlock_irqrestore(&queue->rx_queue.lock, flags);
+}
+
+static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue)
+{
+       struct sk_buff *skb;
+
+       spin_lock_irq(&queue->rx_queue.lock);
+
+       skb = __skb_dequeue(&queue->rx_queue);
+       if (skb)
+               queue->rx_queue_len -= skb->len;
+
+       spin_unlock_irq(&queue->rx_queue.lock);
+
+       return skb;
+}
+
+static void xenvif_rx_queue_maybe_wake(struct xenvif_queue *queue)
+{
+       spin_lock_irq(&queue->rx_queue.lock);
+
+       if (queue->rx_queue_len < queue->rx_queue_max)
+               netif_tx_wake_queue(netdev_get_tx_queue(queue->vif->dev, queue->id));
+
+       spin_unlock_irq(&queue->rx_queue.lock);
+}
+
+
+static void xenvif_rx_queue_purge(struct xenvif_queue *queue)
+{
+       struct sk_buff *skb;
+       while ((skb = xenvif_rx_dequeue(queue)) != NULL)
+               kfree_skb(skb);
+}
+
+static void xenvif_rx_queue_drop_expired(struct xenvif_queue *queue)
+{
+       struct sk_buff *skb;
+
+       for(;;) {
+               skb = skb_peek(&queue->rx_queue);
+               if (!skb)
+                       break;
+               if (time_before(jiffies, XENVIF_RX_CB(skb)->expires))
+                       break;
+               xenvif_rx_dequeue(queue);
+               kfree_skb(skb);
+       }
+}
+
 /*
  * Returns true if we should start a new receive buffer instead of
  * adding 'size' bytes to a buffer which currently contains 'offset'
@@ -237,13 +306,6 @@ static struct xenvif_rx_meta *get_next_rx_buffer(struct xenvif_queue *queue,
        return meta;
 }
 
-struct xenvif_rx_cb {
-       int meta_slots_used;
-       bool full_coalesce;
-};
-
-#define XENVIF_RX_CB(skb) ((struct xenvif_rx_cb *)(skb)->cb)
-
 /*
  * Set up the grant operations for this fragment. If it's a flipping
  * interface, we also set up the unmap request from here.
@@ -587,12 +649,15 @@ static void xenvif_rx_action(struct xenvif_queue *queue)
 
        skb_queue_head_init(&rxq);
 
-       while ((skb = skb_dequeue(&queue->rx_queue)) != NULL) {
+       while (xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX)
+              && (skb = xenvif_rx_dequeue(queue)) != NULL) {
                RING_IDX max_slots_needed;
                RING_IDX old_req_cons;
                RING_IDX ring_slots_used;
                int i;
 
+               queue->last_rx_time = jiffies;
+
                /* We need a cheap worse case estimate for the number of
                 * slots we'll use.
                 */
@@ -634,15 +699,6 @@ static void xenvif_rx_action(struct xenvif_queue *queue)
                    skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6))
                        max_slots_needed++;
 
-               /* If the skb may not fit then bail out now */
-               if (!xenvif_rx_ring_slots_available(queue, max_slots_needed)) {
-                       skb_queue_head(&queue->rx_queue, skb);
-                       need_to_notify = true;
-                       queue->rx_last_skb_slots = max_slots_needed;
-                       break;
-               } else
-                       queue->rx_last_skb_slots = 0;
-
                old_req_cons = queue->rx.req_cons;
                XENVIF_RX_CB(skb)->meta_slots_used = xenvif_gop_skb(skb, &npo, queue);
                ring_slots_used = queue->rx.req_cons - old_req_cons;
@@ -1869,12 +1925,6 @@ void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
        }
 }
 
-static inline int rx_work_todo(struct xenvif_queue *queue)
-{
-       return (!skb_queue_empty(&queue->rx_queue) &&
-              xenvif_rx_ring_slots_available(queue, queue->rx_last_skb_slots));
-}
-
 static inline int tx_work_todo(struct xenvif_queue *queue)
 {
        if (likely(RING_HAS_UNCONSUMED_REQUESTS(&queue->tx)))
@@ -1931,92 +1981,121 @@ err:
        return err;
 }
 
-static void xenvif_start_queue(struct xenvif_queue *queue)
+static void xenvif_queue_carrier_off(struct xenvif_queue *queue)
 {
-       if (xenvif_schedulable(queue->vif))
-               xenvif_wake_queue(queue);
+       struct xenvif *vif = queue->vif;
+
+       queue->stalled = true;
+
+       /* At least one queue has stalled? Disable the carrier. */
+       spin_lock(&vif->lock);
+       if (vif->stalled_queues++ == 0) {
+               netdev_info(vif->dev, "Guest Rx stalled");
+               netif_carrier_off(vif->dev);
+       }
+       spin_unlock(&vif->lock);
 }
 
-/* Only called from the queue's thread, it handles the situation when the guest
- * doesn't post enough requests on the receiving ring.
- * First xenvif_start_xmit disables QDisc and start a timer, and then either the
- * timer fires, or the guest send an interrupt after posting new request. If it
- * is the timer, the carrier is turned off here.
- * */
-static void xenvif_rx_purge_event(struct xenvif_queue *queue)
+static void xenvif_queue_carrier_on(struct xenvif_queue *queue)
 {
-       /* Either the last unsuccesful skb or at least 1 slot should fit */
-       int needed = queue->rx_last_skb_slots ?
-                    queue->rx_last_skb_slots : 1;
+       struct xenvif *vif = queue->vif;
 
-       /* It is assumed that if the guest post new slots after this, the RX
-        * interrupt will set the QUEUE_STATUS_RX_PURGE_EVENT bit and wake up
-        * the thread again
-        */
-       set_bit(QUEUE_STATUS_RX_STALLED, &queue->status);
-       if (!xenvif_rx_ring_slots_available(queue, needed)) {
-               rtnl_lock();
-               if (netif_carrier_ok(queue->vif->dev)) {
-                       /* Timer fired and there are still no slots. Turn off
-                        * everything except the interrupts
-                        */
-                       netif_carrier_off(queue->vif->dev);
-                       skb_queue_purge(&queue->rx_queue);
-                       queue->rx_last_skb_slots = 0;
-                       if (net_ratelimit())
-                               netdev_err(queue->vif->dev, "Carrier off due to lack of guest response on queue %d\n", queue->id);
-               } else {
-                       /* Probably an another queue already turned the carrier
-                        * off, make sure nothing is stucked in the internal
-                        * queue of this queue
-                        */
-                       skb_queue_purge(&queue->rx_queue);
-                       queue->rx_last_skb_slots = 0;
-               }
-               rtnl_unlock();
-       } else if (!netif_carrier_ok(queue->vif->dev)) {
-               unsigned int num_queues = queue->vif->num_queues;
-               unsigned int i;
-               /* The carrier was down, but an interrupt kicked
-                * the thread again after new requests were
-                * posted
-                */
-               clear_bit(QUEUE_STATUS_RX_STALLED,
-                         &queue->status);
-               rtnl_lock();
-               netif_carrier_on(queue->vif->dev);
-               netif_tx_wake_all_queues(queue->vif->dev);
-               rtnl_unlock();
+       queue->last_rx_time = jiffies; /* Reset Rx stall detection. */
+       queue->stalled = false;
 
-               for (i = 0; i < num_queues; i++) {
-                       struct xenvif_queue *temp = &queue->vif->queues[i];
+       /* All queues are ready? Enable the carrier. */
+       spin_lock(&vif->lock);
+       if (--vif->stalled_queues == 0) {
+               netdev_info(vif->dev, "Guest Rx ready");
+               netif_carrier_on(vif->dev);
+       }
+       spin_unlock(&vif->lock);
+}
 
-                       xenvif_napi_schedule_or_enable_events(temp);
-               }
-               if (net_ratelimit())
-                       netdev_err(queue->vif->dev, "Carrier on again\n");
-       } else {
-               /* Queuing were stopped, but the guest posted
-                * new requests and sent an interrupt
-                */
-               clear_bit(QUEUE_STATUS_RX_STALLED,
-                         &queue->status);
-               del_timer_sync(&queue->rx_stalled);
-               xenvif_start_queue(queue);
+static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue)
+{
+       RING_IDX prod, cons;
+
+       prod = queue->rx.sring->req_prod;
+       cons = queue->rx.req_cons;
+
+       return !queue->stalled
+               && prod - cons < XEN_NETBK_RX_SLOTS_MAX
+               && time_after(jiffies,
+                             queue->last_rx_time + rx_stall_timeout_jiffies);
+}
+
+static bool xenvif_rx_queue_ready(struct xenvif_queue *queue)
+{
+       RING_IDX prod, cons;
+
+       prod = queue->rx.sring->req_prod;
+       cons = queue->rx.req_cons;
+
+       return queue->stalled
+               && prod - cons >= XEN_NETBK_RX_SLOTS_MAX;
+}
+
+static bool xenvif_have_rx_work(struct xenvif_queue *queue)
+{
+       return (!skb_queue_empty(&queue->rx_queue)
+               && xenvif_rx_ring_slots_available(queue, XEN_NETBK_RX_SLOTS_MAX))
+               || xenvif_rx_queue_stalled(queue)
+               || xenvif_rx_queue_ready(queue)
+               || kthread_should_stop()
+               || queue->vif->disabled;
+}
+
+static long xenvif_rx_queue_timeout(struct xenvif_queue *queue)
+{
+       struct sk_buff *skb;
+       long timeout;
+
+       skb = skb_peek(&queue->rx_queue);
+       if (!skb)
+               return MAX_SCHEDULE_TIMEOUT;
+
+       timeout = XENVIF_RX_CB(skb)->expires - jiffies;
+       return timeout < 0 ? 0 : timeout;
+}
+
+/* Wait until the guest Rx thread has work.
+ *
+ * The timeout needs to be adjusted based on the current head of the
+ * queue (and not just the head at the beginning).  In particular, if
+ * the queue is initially empty an infinite timeout is used and this
+ * needs to be reduced when a skb is queued.
+ *
+ * This cannot be done with wait_event_timeout() because it only
+ * calculates the timeout once.
+ */
+static void xenvif_wait_for_rx_work(struct xenvif_queue *queue)
+{
+       DEFINE_WAIT(wait);
+
+       if (xenvif_have_rx_work(queue))
+               return;
+
+       for (;;) {
+               long ret;
+
+               prepare_to_wait(&queue->wq, &wait, TASK_INTERRUPTIBLE);
+               if (xenvif_have_rx_work(queue))
+                       break;
+               ret = schedule_timeout(xenvif_rx_queue_timeout(queue));
+               if (!ret)
+                       break;
        }
+       finish_wait(&queue->wq, &wait);
 }
 
 int xenvif_kthread_guest_rx(void *data)
 {
        struct xenvif_queue *queue = data;
-       struct sk_buff *skb;
+       struct xenvif *vif = queue->vif;
 
-       while (!kthread_should_stop()) {
-               wait_event_interruptible(queue->wq,
-                                        rx_work_todo(queue) ||
-                                        queue->vif->disabled ||
-                                        test_bit(QUEUE_STATUS_RX_PURGE_EVENT, &queue->status) ||
-                                        kthread_should_stop());
+       for (;;) {
+               xenvif_wait_for_rx_work(queue);
 
                if (kthread_should_stop())
                        break;
@@ -2028,35 +2107,38 @@ int xenvif_kthread_guest_rx(void *data)
                 * context so we defer it here, if this thread is
                 * associated with queue 0.
                 */
-               if (unlikely(queue->vif->disabled && queue->id == 0)) {
-                       xenvif_carrier_off(queue->vif);
-               } else if (unlikely(queue->vif->disabled)) {
-                       /* kthread_stop() would be called upon this thread soon,
-                        * be a bit proactive
-                        */
-                       skb_queue_purge(&queue->rx_queue);
-                       queue->rx_last_skb_slots = 0;
-               } else if (unlikely(test_and_clear_bit(QUEUE_STATUS_RX_PURGE_EVENT,
-                                                    &queue->status))) {
-                       xenvif_rx_purge_event(queue);
-               } else if (!netif_carrier_ok(queue->vif->dev)) {
-                       /* Another queue stalled and turned the carrier off, so
-                        * purge the internal queue of queues which were not
-                        * blocked
-                        */
-                       skb_queue_purge(&queue->rx_queue);
-                       queue->rx_last_skb_slots = 0;
+               if (unlikely(vif->disabled && queue->id == 0)) {
+                       xenvif_carrier_off(vif);
+                       xenvif_rx_queue_purge(queue);
+                       continue;
                }
 
                if (!skb_queue_empty(&queue->rx_queue))
                        xenvif_rx_action(queue);
 
+               /* If the guest hasn't provided any Rx slots for a
+                * while it's probably not responsive, drop the
+                * carrier so packets are dropped earlier.
+                */
+               if (xenvif_rx_queue_stalled(queue))
+                       xenvif_queue_carrier_off(queue);
+               else if (xenvif_rx_queue_ready(queue))
+                       xenvif_queue_carrier_on(queue);
+
+               /* Queued packets may have foreign pages from other
+                * domains.  These cannot be queued indefinitely as
+                * this would starve guests of grant refs and transmit
+                * slots.
+                */
+               xenvif_rx_queue_drop_expired(queue);
+
+               xenvif_rx_queue_maybe_wake(queue);
+
                cond_resched();
        }
 
        /* Bin any remaining skbs */
-       while ((skb = skb_dequeue(&queue->rx_queue)) != NULL)
-               dev_kfree_skb(skb);
+       xenvif_rx_queue_purge(queue);
 
        return 0;
 }
@@ -2113,6 +2195,7 @@ static int __init netback_init(void)
                goto failed_init;
 
        rx_drain_timeout_jiffies = msecs_to_jiffies(rx_drain_timeout_msecs);
+       rx_stall_timeout_jiffies = msecs_to_jiffies(rx_stall_timeout_msecs);
 
 #ifdef CONFIG_DEBUG_FS
        xen_netback_dbg_root = debugfs_create_dir("xen-netback", NULL);
index 8079c31ac5e64372fe978405c8faa72981998320..fab0d4b42f58fca511dc447b62ea91607732ba81 100644 (file)
@@ -39,7 +39,7 @@ struct backend_info {
 static int connect_rings(struct backend_info *be, struct xenvif_queue *queue);
 static void connect(struct backend_info *be);
 static int read_xenbus_vif_flags(struct backend_info *be);
-static void backend_create_xenvif(struct backend_info *be);
+static int backend_create_xenvif(struct backend_info *be);
 static void unregister_hotplug_status_watch(struct backend_info *be);
 static void set_backend_state(struct backend_info *be,
                              enum xenbus_state state);
@@ -52,6 +52,7 @@ static int xenvif_read_io_ring(struct seq_file *m, void *v)
        struct xenvif_queue *queue = m->private;
        struct xen_netif_tx_back_ring *tx_ring = &queue->tx;
        struct xen_netif_rx_back_ring *rx_ring = &queue->rx;
+       struct netdev_queue *dev_queue;
 
        if (tx_ring->sring) {
                struct xen_netif_tx_sring *sring = tx_ring->sring;
@@ -112,6 +113,13 @@ static int xenvif_read_io_ring(struct seq_file *m, void *v)
                   queue->credit_timeout.expires,
                   jiffies);
 
+       dev_queue = netdev_get_tx_queue(queue->vif->dev, queue->id);
+
+       seq_printf(m, "\nRx internal queue: len %u max %u pkts %u %s\n",
+                  queue->rx_queue_len, queue->rx_queue_max,
+                  skb_queue_len(&queue->rx_queue),
+                  netif_tx_queue_stopped(dev_queue) ? "stopped" : "running");
+
        return 0;
 }
 
@@ -344,7 +352,9 @@ static int netback_probe(struct xenbus_device *dev,
        be->state = XenbusStateInitWait;
 
        /* This kicks hotplug scripts, so do it immediately. */
-       backend_create_xenvif(be);
+       err = backend_create_xenvif(be);
+       if (err)
+               goto fail;
 
        return 0;
 
@@ -389,19 +399,19 @@ static int netback_uevent(struct xenbus_device *xdev,
 }
 
 
-static void backend_create_xenvif(struct backend_info *be)
+static int backend_create_xenvif(struct backend_info *be)
 {
        int err;
        long handle;
        struct xenbus_device *dev = be->dev;
 
        if (be->vif != NULL)
-               return;
+               return 0;
 
        err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%li", &handle);
        if (err != 1) {
                xenbus_dev_fatal(dev, err, "reading handle");
-               return;
+               return (err < 0) ? err : -EINVAL;
        }
 
        be->vif = xenvif_alloc(&dev->dev, dev->otherend_id, handle);
@@ -409,10 +419,11 @@ static void backend_create_xenvif(struct backend_info *be)
                err = PTR_ERR(be->vif);
                be->vif = NULL;
                xenbus_dev_fatal(dev, err, "creating interface");
-               return;
+               return err;
        }
 
        kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
+       return 0;
 }
 
 static void backend_disconnect(struct backend_info *be)
@@ -703,6 +714,7 @@ static void connect(struct backend_info *be)
        be->vif->queues = vzalloc(requested_num_queues *
                                  sizeof(struct xenvif_queue));
        be->vif->num_queues = requested_num_queues;
+       be->vif->stalled_queues = requested_num_queues;
 
        for (queue_index = 0; queue_index < requested_num_queues; ++queue_index) {
                queue = &be->vif->queues[queue_index];
@@ -873,15 +885,10 @@ static int read_xenbus_vif_flags(struct backend_info *be)
        if (!rx_copy)
                return -EOPNOTSUPP;
 
-       if (vif->dev->tx_queue_len != 0) {
-               if (xenbus_scanf(XBT_NIL, dev->otherend,
-                                "feature-rx-notify", "%d", &val) < 0)
-                       val = 0;
-               if (val)
-                       vif->can_queue = 1;
-               else
-                       /* Must be non-zero for pfifo_fast to work. */
-                       vif->dev->tx_queue_len = 1;
+       if (xenbus_scanf(XBT_NIL, dev->otherend,
+                        "feature-rx-notify", "%d", &val) < 0 || val == 0) {
+               xenbus_dev_fatal(dev, -EINVAL, "feature-rx-notify is mandatory");
+               return -EINVAL;
        }
 
        if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
index cca871346a0ff5cfe22ffbcdce0f8c973cf59214..ece8d1804d13606c71b8f39e90851cb8b82de8ac 100644 (file)
@@ -496,9 +496,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct netfront_queue *queue,
                len = skb_frag_size(frag);
                offset = frag->page_offset;
 
-               /* Data must not cross a page boundary. */
-               BUG_ON(len + offset > PAGE_SIZE<<compound_order(page));
-
                /* Skip unused frames from start of page */
                page += offset >> PAGE_SHIFT;
                offset &= ~PAGE_MASK;
@@ -506,8 +503,6 @@ static void xennet_make_frags(struct sk_buff *skb, struct netfront_queue *queue,
                while (len > 0) {
                        unsigned long bytes;
 
-                       BUG_ON(offset >= PAGE_SIZE);
-
                        bytes = PAGE_SIZE - offset;
                        if (bytes > len)
                                bytes = len;
index 5066a7ef7b6c38a2064c69003bff4f90b481293e..3319cf19deebe0f27a0243bb0661cebc24a3f74a 100644 (file)
@@ -920,14 +920,10 @@ void __init nubus_probe_slot(int slot)
        rp = nubus_rom_addr(slot);      
        for(i = 4; i; i--)
        {
-               unsigned long flags;
                int card_present;
 
                rp--;
-               local_irq_save(flags);
                card_present = hwreg_present(rp);
-               local_irq_restore(flags);
-              
                if (!card_present)
                        continue;
 
index afdb78299f61f8d5465ec1d203d482d0674fe31d..06af494184d657456df3c353b9e61e380ec98dec 100644 (file)
@@ -450,6 +450,21 @@ static struct of_bus *of_match_bus(struct device_node *np)
        return NULL;
 }
 
+static int of_empty_ranges_quirk(void)
+{
+       if (IS_ENABLED(CONFIG_PPC)) {
+               /* To save cycles, we cache the result */
+               static int quirk_state = -1;
+
+               if (quirk_state < 0)
+                       quirk_state =
+                               of_machine_is_compatible("Power Macintosh") ||
+                               of_machine_is_compatible("MacRISC");
+               return quirk_state;
+       }
+       return false;
+}
+
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
                            struct of_bus *pbus, __be32 *addr,
                            int na, int ns, int pna, const char *rprop)
@@ -475,12 +490,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
         * This code is only enabled on powerpc. --gcl
         */
        ranges = of_get_property(parent, rprop, &rlen);
-#if !defined(CONFIG_PPC)
-       if (ranges == NULL) {
+       if (ranges == NULL && !of_empty_ranges_quirk()) {
                pr_err("OF: no ranges; cannot translate\n");
                return 1;
        }
-#endif /* !defined(CONFIG_PPC) */
        if (ranges == NULL || rlen == 0) {
                offset = of_read_number(addr, na);
                memset(addr, 0, pna * 4);
index 2305dc0382bca0a5c86bc89f5335253de46ff109..3823edf2d0120d9e89a8195f4845c7d144bcefcf 100644 (file)
@@ -1279,52 +1279,6 @@ int of_property_read_string(struct device_node *np, const char *propname,
 }
 EXPORT_SYMBOL_GPL(of_property_read_string);
 
-/**
- * of_property_read_string_index - Find and read a string from a multiple
- * strings property.
- * @np:                device node from which the property value is to be read.
- * @propname:  name of the property to be searched.
- * @index:     index of the string in the list of strings
- * @out_string:        pointer to null terminated return string, modified only if
- *             return value is 0.
- *
- * Search for a property in a device tree node and retrieve a null
- * terminated string value (pointer to data, not a copy) in the list of strings
- * contained in that property.
- * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
- * property does not have a value, and -EILSEQ if the string is not
- * null-terminated within the length of the property data.
- *
- * The out_string pointer is modified only if a valid string can be decoded.
- */
-int of_property_read_string_index(struct device_node *np, const char *propname,
-                                 int index, const char **output)
-{
-       struct property *prop = of_find_property(np, propname, NULL);
-       int i = 0;
-       size_t l = 0, total = 0;
-       const char *p;
-
-       if (!prop)
-               return -EINVAL;
-       if (!prop->value)
-               return -ENODATA;
-       if (strnlen(prop->value, prop->length) >= prop->length)
-               return -EILSEQ;
-
-       p = prop->value;
-
-       for (i = 0; total < prop->length; total += l, p += l) {
-               l = strlen(p) + 1;
-               if (i++ == index) {
-                       *output = p;
-                       return 0;
-               }
-       }
-       return -ENODATA;
-}
-EXPORT_SYMBOL_GPL(of_property_read_string_index);
-
 /**
  * of_property_match_string() - Find string in a list and return index
  * @np: pointer to node containing string list property
@@ -1351,7 +1305,7 @@ int of_property_match_string(struct device_node *np, const char *propname,
        end = p + prop->length;
 
        for (i = 0; p < end; i++, p += l) {
-               l = strlen(p) + 1;
+               l = strnlen(p, end - p) + 1;
                if (p + l > end)
                        return -EILSEQ;
                pr_debug("comparing %s with %s\n", string, p);
@@ -1363,39 +1317,41 @@ int of_property_match_string(struct device_node *np, const char *propname,
 EXPORT_SYMBOL_GPL(of_property_match_string);
 
 /**
- * of_property_count_strings - Find and return the number of strings from a
- * multiple strings property.
+ * of_property_read_string_util() - Utility helper for parsing string properties
  * @np:                device node from which the property value is to be read.
  * @propname:  name of the property to be searched.
+ * @out_strs:  output array of string pointers.
+ * @sz:                number of array elements to read.
+ * @skip:      Number of strings to skip over at beginning of list.
  *
- * Search for a property in a device tree node and retrieve the number of null
- * terminated string contain in it. Returns the number of strings on
- * success, -EINVAL if the property does not exist, -ENODATA if property
- * does not have a value, and -EILSEQ if the string is not null-terminated
- * within the length of the property data.
+ * Don't call this function directly. It is a utility helper for the
+ * of_property_read_string*() family of functions.
  */
-int of_property_count_strings(struct device_node *np, const char *propname)
+int of_property_read_string_helper(struct device_node *np, const char *propname,
+                                  const char **out_strs, size_t sz, int skip)
 {
        struct property *prop = of_find_property(np, propname, NULL);
-       int i = 0;
-       size_t l = 0, total = 0;
-       const char *p;
+       int l = 0, i = 0;
+       const char *p, *end;
 
        if (!prop)
                return -EINVAL;
        if (!prop->value)
                return -ENODATA;
-       if (strnlen(prop->value, prop->length) >= prop->length)
-               return -EILSEQ;
-
        p = prop->value;
+       end = p + prop->length;
 
-       for (i = 0; total < prop->length; total += l, p += l, i++)
-               l = strlen(p) + 1;
-
-       return i;
+       for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) {
+               l = strnlen(p, end - p) + 1;
+               if (p + l > end)
+                       return -EILSEQ;
+               if (out_strs && i >= skip)
+                       *out_strs++ = p;
+       }
+       i -= skip;
+       return i <= 0 ? -ENODATA : i;
 }
-EXPORT_SYMBOL_GPL(of_property_count_strings);
+EXPORT_SYMBOL_GPL(of_property_read_string_helper);
 
 void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
 {
index f297891d852908ae3e78fe9bfa2bfe5b231875e6..d4994177dec25506e454bf1556050ffc2754d084 100644 (file)
@@ -247,7 +247,7 @@ void of_node_release(struct kobject *kobj)
  * @allocflags:        Allocation flags (typically pass GFP_KERNEL)
  *
  * Copy a property by dynamically allocating the memory of both the
- * property stucture and the property name & contents. The property's
+ * property structure and the property name & contents. The property's
  * flags have the OF_DYNAMIC bit set so that we can differentiate between
  * dynamically allocated properties and not.
  * Returns the newly allocated property or NULL on out of memory error.
index d1ffca8b34eac51853c812a230cfd438862f8cff..d134710de96dabcf873ed8ea135611784c60b1d0 100644 (file)
@@ -773,7 +773,7 @@ int __init early_init_dt_scan_chosen_serial(void)
        if (offset < 0)
                return -ENODEV;
 
-       while (match->compatible) {
+       while (match->compatible[0]) {
                unsigned long addr;
                if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
                        match++;
@@ -964,8 +964,6 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
 int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
                                        phys_addr_t size, bool nomap)
 {
-       if (memblock_is_region_reserved(base, size))
-               return -EBUSY;
        if (nomap)
                return memblock_remove(base, size);
        return memblock_reserve(base, size);
index 59fb12e84e6bb8da22f62c6de25817cf3d743682..dc566b38645f6fcd3a296aa5e82419c857b81bcc 100644 (file)
@@ -243,23 +243,27 @@ static inline struct reserved_mem *__find_rmem(struct device_node *node)
  * This function assign memory region pointed by "memory-region" device tree
  * property to the given device.
  */
-void of_reserved_mem_device_init(struct device *dev)
+int of_reserved_mem_device_init(struct device *dev)
 {
        struct reserved_mem *rmem;
        struct device_node *np;
+       int ret;
 
        np = of_parse_phandle(dev->of_node, "memory-region", 0);
        if (!np)
-               return;
+               return -ENODEV;
 
        rmem = __find_rmem(np);
        of_node_put(np);
 
        if (!rmem || !rmem->ops || !rmem->ops->device_init)
-               return;
+               return -EINVAL;
+
+       ret = rmem->ops->device_init(rmem, dev);
+       if (ret == 0)
+               dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
 
-       rmem->ops->device_init(rmem, dev);
-       dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
+       return ret;
 }
 
 /**
index 78001270a5980bc7342a5241c8930297cf92f883..e2d79afa9dc6153613c4281570eb620332249c8c 100644 (file)
@@ -339,8 +339,9 @@ static void __init of_selftest_parse_phandle_with_args(void)
        selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
 }
 
-static void __init of_selftest_property_match_string(void)
+static void __init of_selftest_property_string(void)
 {
+       const char *strings[4];
        struct device_node *np;
        int rc;
 
@@ -357,13 +358,66 @@ static void __init of_selftest_property_match_string(void)
        rc = of_property_match_string(np, "phandle-list-names", "third");
        selftest(rc == 2, "third expected:0 got:%i\n", rc);
        rc = of_property_match_string(np, "phandle-list-names", "fourth");
-       selftest(rc == -ENODATA, "unmatched string; rc=%i", rc);
+       selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc);
        rc = of_property_match_string(np, "missing-property", "blah");
-       selftest(rc == -EINVAL, "missing property; rc=%i", rc);
+       selftest(rc == -EINVAL, "missing property; rc=%i\n", rc);
        rc = of_property_match_string(np, "empty-property", "blah");
-       selftest(rc == -ENODATA, "empty property; rc=%i", rc);
+       selftest(rc == -ENODATA, "empty property; rc=%i\n", rc);
        rc = of_property_match_string(np, "unterminated-string", "blah");
-       selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
+       selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
+
+       /* of_property_count_strings() tests */
+       rc = of_property_count_strings(np, "string-property");
+       selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
+       rc = of_property_count_strings(np, "phandle-list-names");
+       selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
+       rc = of_property_count_strings(np, "unterminated-string");
+       selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
+       rc = of_property_count_strings(np, "unterminated-string-list");
+       selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);
+
+       /* of_property_read_string_index() tests */
+       rc = of_property_read_string_index(np, "string-property", 0, strings);
+       selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc);
+       strings[0] = NULL;
+       rc = of_property_read_string_index(np, "string-property", 1, strings);
+       selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
+       rc = of_property_read_string_index(np, "phandle-list-names", 0, strings);
+       selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
+       rc = of_property_read_string_index(np, "phandle-list-names", 1, strings);
+       selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc);
+       rc = of_property_read_string_index(np, "phandle-list-names", 2, strings);
+       selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc);
+       strings[0] = NULL;
+       rc = of_property_read_string_index(np, "phandle-list-names", 3, strings);
+       selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
+       strings[0] = NULL;
+       rc = of_property_read_string_index(np, "unterminated-string", 0, strings);
+       selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
+       rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings);
+       selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc);
+       strings[0] = NULL;
+       rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */
+       selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc);
+       strings[1] = NULL;
+
+       /* of_property_read_string_array() tests */
+       rc = of_property_read_string_array(np, "string-property", strings, 4);
+       selftest(rc == 1, "Incorrect string count; rc=%i\n", rc);
+       rc = of_property_read_string_array(np, "phandle-list-names", strings, 4);
+       selftest(rc == 3, "Incorrect string count; rc=%i\n", rc);
+       rc = of_property_read_string_array(np, "unterminated-string", strings, 4);
+       selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc);
+       /* -- An incorrectly formed string should cause a failure */
+       rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4);
+       selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc);
+       /* -- parsing the correctly formed strings should still work: */
+       strings[2] = NULL;
+       rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2);
+       selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc);
+       strings[1] = NULL;
+       rc = of_property_read_string_array(np, "phandle-list-names", strings, 1);
+       selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]);
 }
 
 #define propcmp(p1, p2) (((p1)->length == (p2)->length) && \
@@ -842,10 +896,14 @@ static void selftest_data_remove(void)
                return;
        }
 
-       while (last_node_index >= 0) {
+       while (last_node_index-- > 0) {
                if (nodes[last_node_index]) {
                        np = of_find_node_by_path(nodes[last_node_index]->full_name);
-                       if (strcmp(np->full_name, "/aliases") != 0) {
+                       if (np == nodes[last_node_index]) {
+                               if (of_aliases == np) {
+                                       of_node_put(of_aliases);
+                                       of_aliases = NULL;
+                               }
                                detach_node_and_children(np);
                        } else {
                                for_each_property_of_node(np, prop) {
@@ -854,7 +912,6 @@ static void selftest_data_remove(void)
                                }
                        }
                }
-               last_node_index--;
        }
 }
 
@@ -867,6 +924,8 @@ static int __init of_selftest(void)
        res = selftest_data_add();
        if (res)
                return res;
+       if (!of_aliases)
+               of_aliases = of_find_node_by_path("/aliases");
 
        np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
        if (!np) {
@@ -881,7 +940,7 @@ static int __init of_selftest(void)
        of_selftest_find_node_by_name();
        of_selftest_dynamic();
        of_selftest_parse_phandle_with_args();
-       of_selftest_property_match_string();
+       of_selftest_property_string();
        of_selftest_property_copy();
        of_selftest_changeset();
        of_selftest_parse_interrupts();
index ce0fe083d4062eec02145105b44691741337667d..5b1527e8a7fb3ae471a359aed37daa81bd44c0ce 100644 (file)
@@ -39,7 +39,9 @@
                                phandle-list-bad-args = <&provider2 1 0>,
                                                        <&provider3 0>;
                                empty-property;
+                               string-property = "foobar";
                                unterminated-string = [40 41 42 43];
+                               unterminated-string-list = "first", "second", [40 41 42 43];
                        };
                };
        };
index d292d7cb3417062643379805a969f5d29718de2f..49dd766852ba58f5ebad21199e38f1e2a912b498 100644 (file)
@@ -444,7 +444,7 @@ static inline int pcie_cap_version(const struct pci_dev *dev)
        return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
 }
 
-static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
+bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
 {
        int type = pci_pcie_type(dev);
 
index 233fe8a882649dfc4197b8ac58ff1dd0bdaed6e9..69202d1eb8fbc1d0e91eccb64e2acedd03f16d62 100644 (file)
@@ -275,15 +275,22 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp)
                goto err_pcie;
        }
 
-       /* allow the clocks to stabilize */
-       usleep_range(200, 500);
-
        /* power up core phy and enable ref clock */
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
                        IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
+       /*
+        * the async reset input need ref clock to sync internally,
+        * when the ref clock comes after reset, internal synced
+        * reset time is too short, cannot meet the requirement.
+        * add one ~10us delay here.
+        */
+       udelay(10);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
                        IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
 
+       /* allow the clocks to stabilize */
+       usleep_range(200, 500);
+
        /* Some boards don't have PCIe reset GPIO. */
        if (gpio_is_valid(imx6_pcie->reset_gpio)) {
                gpio_set_value(imx6_pcie->reset_gpio, 0);
index 3d43874319bebb13999889522f8d85e61b7251a2..19bb19c7db4a77eb649ddc3c9fc77b95a1f7c479 100644 (file)
@@ -276,6 +276,7 @@ struct tegra_pcie {
 
        struct resource all;
        struct resource io;
+       struct resource pio;
        struct resource mem;
        struct resource prefetch;
        struct resource busn;
@@ -658,7 +659,6 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 {
        struct tegra_pcie *pcie = sys_to_pcie(sys);
        int err;
-       phys_addr_t io_start;
 
        err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem);
        if (err < 0)
@@ -668,14 +668,12 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
        if (err)
                return err;
 
-       io_start = pci_pio_to_address(pcie->io.start);
-
        pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
        pci_add_resource_offset(&sys->resources, &pcie->prefetch,
                                sys->mem_offset);
        pci_add_resource(&sys->resources, &pcie->busn);
 
-       pci_ioremap_io(nr * SZ_64K, io_start);
+       pci_ioremap_io(pcie->pio.start, pcie->io.start);
 
        return 1;
 }
@@ -786,7 +784,6 @@ static irqreturn_t tegra_pcie_isr(int irq, void *arg)
 static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
 {
        u32 fpci_bar, size, axi_address;
-       phys_addr_t io_start = pci_pio_to_address(pcie->io.start);
 
        /* Bar 0: type 1 extended configuration space */
        fpci_bar = 0xfe100000;
@@ -799,7 +796,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
        /* Bar 1: downstream IO bar */
        fpci_bar = 0xfdfc0000;
        size = resource_size(&pcie->io);
-       axi_address = io_start;
+       axi_address = pcie->io.start;
        afi_writel(pcie, axi_address, AFI_AXI_BAR1_START);
        afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ);
        afi_writel(pcie, fpci_bar, AFI_FPCI_BAR1);
@@ -1690,8 +1687,23 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
 
                switch (res.flags & IORESOURCE_TYPE_BITS) {
                case IORESOURCE_IO:
-                       memcpy(&pcie->io, &res, sizeof(res));
-                       pcie->io.name = np->full_name;
+                       memcpy(&pcie->pio, &res, sizeof(res));
+                       pcie->pio.name = np->full_name;
+
+                       /*
+                        * The Tegra PCIe host bridge uses this to program the
+                        * mapping of the I/O space to the physical address,
+                        * so we override the .start and .end fields here that
+                        * of_pci_range_to_resource() converted to I/O space.
+                        * We also set the IORESOURCE_MEM type to clarify that
+                        * the resource is in the physical memory space.
+                        */
+                       pcie->io.start = range.cpu_addr;
+                       pcie->io.end = range.cpu_addr + range.size - 1;
+                       pcie->io.flags = IORESOURCE_MEM;
+                       pcie->io.name = "I/O";
+
+                       memcpy(&res, &pcie->io, sizeof(res));
                        break;
 
                case IORESOURCE_MEM:
index 9ecabfa8c6343a83afba9d33b101bc4161b6bd3f..2988fe136c1e3ede0240e90db80d6e4e013e6e8a 100644 (file)
@@ -631,10 +631,15 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       bus = pci_scan_root_bus(&pdev->dev, 0, &xgene_pcie_ops, port, &res);
+       bus = pci_create_root_bus(&pdev->dev, 0,
+                                       &xgene_pcie_ops, port, &res);
        if (!bus)
                return -ENOMEM;
 
+       pci_scan_child_bus(bus);
+       pci_assign_unassigned_bus_resources(bus);
+       pci_bus_add_devices(bus);
+
        platform_set_drvdata(pdev, port);
        return 0;
 }
index 3a5e7e28b8740307efd8eb2aa5e69c9717cd0e81..07aa722bb12cd61a6a3a8767b2efe1dd826e6952 100644 (file)
@@ -262,13 +262,6 @@ static int pciehp_probe(struct pcie_device *dev)
                goto err_out_none;
        }
 
-       if (!dev->port->subordinate) {
-               /* Can happen if we run out of bus numbers during probe */
-               dev_err(&dev->device,
-                       "Hotplug bridge without secondary bus, ignoring\n");
-               goto err_out_none;
-       }
-
        ctrl = pcie_init(dev);
        if (!ctrl) {
                dev_err(&dev->device, "Controller initialization failed\n");
index 9fab30af0e75abdcec135707363951d7e9e26f8c..084587d7cd134ce0e8e20410368f5b60b9e88f74 100644 (file)
@@ -590,6 +590,20 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev)
        return entry;
 }
 
+static int msi_verify_entries(struct pci_dev *dev)
+{
+       struct msi_desc *entry;
+
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               if (!dev->no_64bit_msi || !entry->msg.address_hi)
+                       continue;
+               dev_err(&dev->dev, "Device has broken 64-bit MSI but arch"
+                       " tried to assign one above 4G\n");
+               return -EIO;
+       }
+       return 0;
+}
+
 /**
  * msi_capability_init - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -627,6 +641,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
                return ret;
        }
 
+       ret = msi_verify_entries(dev);
+       if (ret) {
+               msi_mask_irq(entry, mask, ~mask);
+               free_msi_irqs(dev);
+               return ret;
+       }
+
        ret = populate_msi_sysfs(dev);
        if (ret) {
                msi_mask_irq(entry, mask, ~mask);
@@ -739,6 +760,11 @@ static int msix_capability_init(struct pci_dev *dev,
        if (ret)
                goto out_avail;
 
+       /* Check if all MSI entries honor device restrictions */
+       ret = msi_verify_entries(dev);
+       if (ret)
+               goto out_free;
+
        /*
         * Some devices require MSI-X to be enabled before we can touch the
         * MSI-X registers.  We need to mask all the vectors to prevent
index 92b6d9ab00e498ac02fdd08ead2d4f3bfc76d207..2c6643fdc0cf27bcb9b726bb6c9febf3ca137dc7 100644 (file)
@@ -185,7 +185,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(modalias);
 
-static ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
+static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -210,7 +210,7 @@ static ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
        return result < 0 ? result : count;
 }
 
-static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
+static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
                            char *buf)
 {
        struct pci_dev *pdev;
@@ -218,7 +218,7 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
        pdev = to_pci_dev(dev);
        return sprintf(buf, "%u\n", atomic_read(&pdev->enable_cnt));
 }
-static DEVICE_ATTR_RW(enabled);
+static DEVICE_ATTR_RW(enable);
 
 #ifdef CONFIG_NUMA
 static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr,
@@ -563,7 +563,7 @@ static struct attribute *pci_dev_attrs[] = {
 #endif
        &dev_attr_dma_mask_bits.attr,
        &dev_attr_consistent_dma_mask_bits.attr,
-       &dev_attr_enabled.attr,
+       &dev_attr_enable.attr,
        &dev_attr_broken_parity_status.attr,
        &dev_attr_msi_bus.attr,
 #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
index 0601890db22de96131af2d67fd872651ab608133..4a3902d8e6fec7984bb483b55aee4115101cc1f4 100644 (file)
@@ -6,6 +6,8 @@
 
 extern const unsigned char pcie_link_speed[];
 
+bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
+
 /* Functions internal to the PCI core code */
 
 int pci_create_sysfs_dev_files(struct pci_dev *pdev);
index a9f9c46e50221d75eefc73457425876199f79a0e..63fc63911295e7c0be875b39436c889c6850234e 100644 (file)
@@ -397,6 +397,7 @@ static int pcie_pme_suspend(struct pcie_device *srv)
        struct pcie_pme_service_data *data = get_service_data(srv);
        struct pci_dev *port = srv->port;
        bool wakeup;
+       int ret;
 
        if (device_may_wakeup(&port->dev)) {
                wakeup = true;
@@ -407,9 +408,10 @@ static int pcie_pme_suspend(struct pcie_device *srv)
        }
        spin_lock_irq(&data->lock);
        if (wakeup) {
-               enable_irq_wake(srv->irq);
+               ret = enable_irq_wake(srv->irq);
                data->suspend_level = PME_SUSPEND_WAKEUP;
-       } else {
+       }
+       if (!wakeup || ret) {
                struct pci_dev *port = srv->port;
 
                pcie_pme_interrupt_enable(port, false);
index 5ed99309c75800938b666c5c523d7ea3ca07d51f..c8ca98c2b480a41d57676ef21e97cd6612134110 100644 (file)
@@ -407,15 +407,16 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)
 {
        struct pci_dev *dev = child->self;
        u16 mem_base_lo, mem_limit_lo;
-       unsigned long base, limit;
+       u64 base64, limit64;
+       dma_addr_t base, limit;
        struct pci_bus_region region;
        struct resource *res;
 
        res = child->resource[2];
        pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
        pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
-       base = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
-       limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+       base64 = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+       limit64 = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
 
        if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
                u32 mem_base_hi, mem_limit_hi;
@@ -429,17 +430,20 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)
                 * this, just assume they are not being used.
                 */
                if (mem_base_hi <= mem_limit_hi) {
-#if BITS_PER_LONG == 64
-                       base |= ((unsigned long) mem_base_hi) << 32;
-                       limit |= ((unsigned long) mem_limit_hi) << 32;
-#else
-                       if (mem_base_hi || mem_limit_hi) {
-                               dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n");
-                               return;
-                       }
-#endif
+                       base64 |= (u64) mem_base_hi << 32;
+                       limit64 |= (u64) mem_limit_hi << 32;
                }
        }
+
+       base = (dma_addr_t) base64;
+       limit = (dma_addr_t) limit64;
+
+       if (base != base64) {
+               dev_err(&dev->dev, "can't handle bridge window above 4GB (bus address %#010llx)\n",
+                       (unsigned long long) base64);
+               return;
+       }
+
        if (base <= limit) {
                res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
                                         IORESOURCE_MEM | IORESOURCE_PREFETCH;
@@ -1323,7 +1327,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
                        ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
 
        /* Initialize Link Control Register */
-       if (dev->subordinate)
+       if (pcie_cap_has_lnkctl(dev))
                pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
                        ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
 
index 8c842980834a2cebb40a77d31bc30f5f6ed643ae..f091576b644903a2ab1320550c090479a6f8d56c 100644 (file)
@@ -258,14 +258,16 @@ static int omap_usb2_probe(struct platform_device *pdev)
        otg->phy                = &phy->phy;
 
        platform_set_drvdata(pdev, phy);
+       pm_runtime_enable(phy->dev);
 
        generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
-       if (IS_ERR(generic_phy))
+       if (IS_ERR(generic_phy)) {
+               pm_runtime_disable(phy->dev);
                return PTR_ERR(generic_phy);
+       }
 
        phy_set_drvdata(generic_phy, phy);
 
-       pm_runtime_enable(phy->dev);
        phy_provider = devm_of_phy_provider_register(phy->dev,
                        of_phy_simple_xlate);
        if (IS_ERR(phy_provider)) {
index e12e5b07f6d751aba9cce63cf49d2acabe50b7ab..9dc38140194bf8a8f6e4765ea9c790e112beaa31 100644 (file)
@@ -227,10 +227,14 @@ static int byt_irq_type(struct irq_data *d, unsigned type)
        spin_lock_irqsave(&vg->lock, flags);
        value = readl(reg);
 
+       WARN(value & BYT_DIRECT_IRQ_EN,
+               "Bad pad config for io mode, force direct_irq_en bit clearing");
+
        /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
         * are used to indicate high and low level triggering
         */
-       value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+       value &= ~(BYT_DIRECT_IRQ_EN | BYT_TRIG_POS | BYT_TRIG_NEG |
+                  BYT_TRIG_LVL);
 
        switch (type) {
        case IRQ_TYPE_LEVEL_HIGH:
@@ -318,7 +322,7 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
                "Potential Error: Setting GPIO with direct_irq_en to output");
 
        reg_val = readl(reg) | BYT_DIR_MASK;
-       reg_val &= ~BYT_OUTPUT_EN;
+       reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN);
 
        if (value)
                writel(reg_val | BYT_LEVEL, reg);
index 4dcfb7116a0487656bf489a45c6345c18ea1e219..a2eabe6ff9ada9b7bff3991a0116c8137a78b92d 100644 (file)
@@ -202,6 +202,7 @@ config TC1100_WMI
 config HP_ACCEL
        tristate "HP laptop accelerometer"
        depends on INPUT && ACPI
+       depends on SERIO_I8042
        select SENSORS_LIS3LV02D
        select NEW_LEDS
        select LEDS_CLASS
index 96a0b75c52c9a6232c99b18e61751f3eb62e940a..26c4fd1394da553f465612d096fe30316784b7f1 100644 (file)
@@ -579,6 +579,17 @@ static const struct dmi_system_id video_vendor_dmi_table[] __initconst = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5741"),
                },
        },
+       {
+               /*
+                * Note no video_set_backlight_video_vendor, we must use the
+                * acer interface, as there is no native backlight interface.
+                */
+               .ident = "Acer KAV80",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "KAV80"),
+               },
+       },
        {}
 };
 
index 3a4951f46065dc95abf7767572426566027e1381..c1a6cd66af421753668c0746a78c0870048ff7f9 100644 (file)
@@ -180,6 +180,15 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_wapf4,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK COMPUTER INC. X550VB",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X550VB"),
+               },
+               .driver_data = &quirk_asus_wapf4,
+       },
        {
                .callback = dmi_matched,
                .ident = "ASUSTeK COMPUTER INC. X55A",
index 13e14ec1d3d7118c4e4ab63ac98a2ef0c1258118..6bec745b6b92dc6e3f849a12da003b639d1900ed 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/leds.h>
 #include <linux/atomic.h>
 #include <linux/acpi.h>
+#include <linux/i8042.h>
+#include <linux/serio.h>
 #include "../../misc/lis3lv02d/lis3lv02d.h"
 
 #define DRIVER_NAME     "hp_accel"
@@ -73,6 +75,13 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
 
 /* HP-specific accelerometer driver ------------------------------------ */
 
+/* e0 25, e0 26, e0 27, e0 28 are scan codes that the accelerometer with acpi id
+ * HPQ6000 sends through the keyboard bus */
+#define ACCEL_1 0x25
+#define ACCEL_2 0x26
+#define ACCEL_3 0x27
+#define ACCEL_4 0x28
+
 /* For automatic insertion of the module */
 static const struct acpi_device_id lis3lv02d_device_ids[] = {
        {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
@@ -294,6 +303,35 @@ static void lis3lv02d_enum_resources(struct acpi_device *device)
                printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
 }
 
+static bool hp_accel_i8042_filter(unsigned char data, unsigned char str,
+                                 struct serio *port)
+{
+       static bool extended;
+
+       if (str & I8042_STR_AUXDATA)
+               return false;
+
+       if (data == 0xe0) {
+               extended = true;
+               return true;
+       } else if (unlikely(extended)) {
+               extended = false;
+
+               switch (data) {
+               case ACCEL_1:
+               case ACCEL_2:
+               case ACCEL_3:
+               case ACCEL_4:
+                       return true;
+               default:
+                       serio_interrupt(port, 0xe0, 0);
+                       return false;
+               }
+       }
+
+       return false;
+}
+
 static int lis3lv02d_add(struct acpi_device *device)
 {
        int ret;
@@ -326,6 +364,11 @@ static int lis3lv02d_add(struct acpi_device *device)
        if (ret)
                return ret;
 
+       /* filter to remove HPQ6000 accelerometer data
+        * from keyboard bus stream */
+       if (strstr(dev_name(&device->dev), "HPQ6000"))
+               i8042_install_filter(hp_accel_i8042_filter);
+
        INIT_WORK(&hpled_led.work, delayed_set_status_worker);
        ret = led_classdev_register(NULL, &hpled_led.led_classdev);
        if (ret) {
@@ -343,6 +386,7 @@ static int lis3lv02d_remove(struct acpi_device *device)
        if (!device)
                return -EINVAL;
 
+       i8042_remove_filter(hp_accel_i8042_filter);
        lis3lv02d_joystick_disable(&lis3_dev);
        lis3lv02d_poweroff(&lis3_dev);
 
index 02152de135b5c43b79318c6c5ac7971f0723e478..ed494f37c40f5b95d201c94a0bf9119c5b4b031f 100644 (file)
@@ -837,6 +837,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
                },
        },
+       {
+               .ident = "Lenovo Yoga 3 Pro 1370",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3 Pro-1370"),
+               },
+       },
        {}
 };
 
index 5a59665122776d036cc43e885ec56845ea6b362b..ff765d8e1a09f648ad40770cdd59cf6aadaaf7e8 100644 (file)
@@ -1559,6 +1559,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
         .driver_data = &samsung_broken_acpi_video,
        },
+       {
+        .callback = samsung_dmi_matched,
+        .ident = "NC210",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "NC210/NC110"),
+               DMI_MATCH(DMI_BOARD_NAME, "NC210/NC110"),
+               },
+        .driver_data = &samsung_broken_acpi_video,
+       },
        {
         .callback = samsung_dmi_matched,
         .ident = "730U3E/740U3E",
index ef3a1904e92fe0827de83d79540bc1b569801554..ab6151f054204c46063ad824b14985c97e3b934c 100644 (file)
@@ -240,6 +240,12 @@ static const struct dmi_system_id toshiba_alt_keymap_dmi[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A50-A"),
+               },
+       },
        {}
 };
 
index 217da4b2ca8639ee5f2d5ced62615bfc558aed4f..99a78d365ceb11f2c3c6308296f62ce4db6c2a5d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/time.h>
+#include <linux/time64.h>
 #include <linux/of.h>
 #include <linux/completion.h>
 #include <linux/mfd/core.h>
@@ -108,7 +109,7 @@ enum ab8500_fg_calibration_state {
 struct ab8500_fg_avg_cap {
        int avg;
        int samples[NBR_AVG_SAMPLES];
-       __kernel_time_t time_stamps[NBR_AVG_SAMPLES];
+       time64_t time_stamps[NBR_AVG_SAMPLES];
        int pos;
        int nbr_samples;
        int sum;
@@ -386,15 +387,15 @@ static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr)
  */
 static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
 {
-       struct timespec ts;
+       struct timespec64 ts64;
        struct ab8500_fg_avg_cap *avg = &di->avg_cap;
 
-       getnstimeofday(&ts);
+       getnstimeofday64(&ts64);
 
        do {
                avg->sum += sample - avg->samples[avg->pos];
                avg->samples[avg->pos] = sample;
-               avg->time_stamps[avg->pos] = ts.tv_sec;
+               avg->time_stamps[avg->pos] = ts64.tv_sec;
                avg->pos++;
 
                if (avg->pos == NBR_AVG_SAMPLES)
@@ -407,7 +408,7 @@ static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
                 * Check the time stamp for each sample. If too old,
                 * replace with latest sample
                 */
-       } while (ts.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
+       } while (ts64.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
 
        avg->avg = avg->sum / avg->nbr_samples;
 
@@ -446,14 +447,14 @@ static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
 static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample)
 {
        int i;
-       struct timespec ts;
+       struct timespec64 ts64;
        struct ab8500_fg_avg_cap *avg = &di->avg_cap;
 
-       getnstimeofday(&ts);
+       getnstimeofday64(&ts64);
 
        for (i = 0; i < NBR_AVG_SAMPLES; i++) {
                avg->samples[i] = sample;
-               avg->time_stamps[i] = ts.tv_sec;
+               avg->time_stamps[i] = ts64.tv_sec;
        }
 
        avg->pos = 0;
index e384844a1ae1957ffd3687e7f54d0ff3eba2b59f..1f49986fc6057c8c4db858735ec8d9fd38326f8a 100644 (file)
@@ -1579,8 +1579,15 @@ static int bq2415x_probe(struct i2c_client *client,
        if (np) {
                bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection");
 
-               if (!bq->notify_psy)
-                       return -EPROBE_DEFER;
+               if (IS_ERR(bq->notify_psy)) {
+                       dev_info(&client->dev,
+                               "no 'ti,usb-charger-detection' property (err=%ld)\n",
+                               PTR_ERR(bq->notify_psy));
+                       bq->notify_psy = NULL;
+               } else if (!bq->notify_psy) {
+                       ret = -EPROBE_DEFER;
+                       goto error_2;
+               }
        }
        else if (pdata->notify_device)
                bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
@@ -1602,27 +1609,27 @@ static int bq2415x_probe(struct i2c_client *client,
                ret = of_property_read_u32(np, "ti,current-limit",
                                &bq->init_data.current_limit);
                if (ret)
-                       return ret;
+                       goto error_2;
                ret = of_property_read_u32(np, "ti,weak-battery-voltage",
                                &bq->init_data.weak_battery_voltage);
                if (ret)
-                       return ret;
+                       goto error_2;
                ret = of_property_read_u32(np, "ti,battery-regulation-voltage",
                                &bq->init_data.battery_regulation_voltage);
                if (ret)
-                       return ret;
+                       goto error_2;
                ret = of_property_read_u32(np, "ti,charge-current",
                                &bq->init_data.charge_current);
                if (ret)
-                       return ret;
+                       goto error_2;
                ret = of_property_read_u32(np, "ti,termination-current",
                                &bq->init_data.termination_current);
                if (ret)
-                       return ret;
+                       goto error_2;
                ret = of_property_read_u32(np, "ti,resistor-sense",
                                &bq->init_data.resistor_sense);
                if (ret)
-                       return ret;
+                       goto error_2;
        } else {
                memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
        }
index 7098a1ce2d3c1068e2ef6cc5fbbe4d185ece9850..ef8094a61f1e91caa16fdcb204ce4ced9485334e 100644 (file)
@@ -97,6 +97,7 @@ static struct charger_global_desc *g_desc; /* init with setup_charger_manager */
 static bool is_batt_present(struct charger_manager *cm)
 {
        union power_supply_propval val;
+       struct power_supply *psy;
        bool present = false;
        int i, ret;
 
@@ -107,16 +108,27 @@ static bool is_batt_present(struct charger_manager *cm)
        case CM_NO_BATTERY:
                break;
        case CM_FUEL_GAUGE:
-               ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+               psy = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+               if (!psy)
+                       break;
+
+               ret = psy->get_property(psy,
                                POWER_SUPPLY_PROP_PRESENT, &val);
                if (ret == 0 && val.intval)
                        present = true;
                break;
        case CM_CHARGER_STAT:
-               for (i = 0; cm->charger_stat[i]; i++) {
-                       ret = cm->charger_stat[i]->get_property(
-                                       cm->charger_stat[i],
-                                       POWER_SUPPLY_PROP_PRESENT, &val);
+               for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
+                       psy = power_supply_get_by_name(
+                                       cm->desc->psy_charger_stat[i]);
+                       if (!psy) {
+                               dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
+                                       cm->desc->psy_charger_stat[i]);
+                               continue;
+                       }
+
+                       ret = psy->get_property(psy, POWER_SUPPLY_PROP_PRESENT,
+                                       &val);
                        if (ret == 0 && val.intval) {
                                present = true;
                                break;
@@ -139,14 +151,20 @@ static bool is_batt_present(struct charger_manager *cm)
 static bool is_ext_pwr_online(struct charger_manager *cm)
 {
        union power_supply_propval val;
+       struct power_supply *psy;
        bool online = false;
        int i, ret;
 
        /* If at least one of them has one, it's yes. */
-       for (i = 0; cm->charger_stat[i]; i++) {
-               ret = cm->charger_stat[i]->get_property(
-                               cm->charger_stat[i],
-                               POWER_SUPPLY_PROP_ONLINE, &val);
+       for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
+               psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]);
+               if (!psy) {
+                       dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
+                                       cm->desc->psy_charger_stat[i]);
+                       continue;
+               }
+
+               ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
                if (ret == 0 && val.intval) {
                        online = true;
                        break;
@@ -167,12 +185,14 @@ static bool is_ext_pwr_online(struct charger_manager *cm)
 static int get_batt_uV(struct charger_manager *cm, int *uV)
 {
        union power_supply_propval val;
+       struct power_supply *fuel_gauge;
        int ret;
 
-       if (!cm->fuel_gauge)
+       fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+       if (!fuel_gauge)
                return -ENODEV;
 
-       ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+       ret = fuel_gauge->get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
        if (ret)
                return ret;
@@ -189,6 +209,7 @@ static bool is_charging(struct charger_manager *cm)
 {
        int i, ret;
        bool charging = false;
+       struct power_supply *psy;
        union power_supply_propval val;
 
        /* If there is no battery, it cannot be charged */
@@ -196,17 +217,22 @@ static bool is_charging(struct charger_manager *cm)
                return false;
 
        /* If at least one of the charger is charging, return yes */
-       for (i = 0; cm->charger_stat[i]; i++) {
+       for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
                /* 1. The charger sholuld not be DISABLED */
                if (cm->emergency_stop)
                        continue;
                if (!cm->charger_enabled)
                        continue;
 
+               psy = power_supply_get_by_name(cm->desc->psy_charger_stat[i]);
+               if (!psy) {
+                       dev_err(cm->dev, "Cannot find power supply \"%s\"\n",
+                                       cm->desc->psy_charger_stat[i]);
+                       continue;
+               }
+
                /* 2. The charger should be online (ext-power) */
-               ret = cm->charger_stat[i]->get_property(
-                               cm->charger_stat[i],
-                               POWER_SUPPLY_PROP_ONLINE, &val);
+               ret = psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &val);
                if (ret) {
                        dev_warn(cm->dev, "Cannot read ONLINE value from %s\n",
                                 cm->desc->psy_charger_stat[i]);
@@ -219,9 +245,7 @@ static bool is_charging(struct charger_manager *cm)
                 * 3. The charger should not be FULL, DISCHARGING,
                 * or NOT_CHARGING.
                 */
-               ret = cm->charger_stat[i]->get_property(
-                               cm->charger_stat[i],
-                               POWER_SUPPLY_PROP_STATUS, &val);
+               ret = psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &val);
                if (ret) {
                        dev_warn(cm->dev, "Cannot read STATUS value from %s\n",
                                 cm->desc->psy_charger_stat[i]);
@@ -248,6 +272,7 @@ static bool is_full_charged(struct charger_manager *cm)
 {
        struct charger_desc *desc = cm->desc;
        union power_supply_propval val;
+       struct power_supply *fuel_gauge;
        int ret = 0;
        int uV;
 
@@ -255,11 +280,15 @@ static bool is_full_charged(struct charger_manager *cm)
        if (!is_batt_present(cm))
                return false;
 
-       if (cm->fuel_gauge && desc->fullbatt_full_capacity > 0) {
+       fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+       if (!fuel_gauge)
+               return false;
+
+       if (desc->fullbatt_full_capacity > 0) {
                val.intval = 0;
 
                /* Not full if capacity of fuel gauge isn't full */
-               ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+               ret = fuel_gauge->get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_CHARGE_FULL, &val);
                if (!ret && val.intval > desc->fullbatt_full_capacity)
                        return true;
@@ -273,10 +302,10 @@ static bool is_full_charged(struct charger_manager *cm)
        }
 
        /* Full, if the capacity is more than fullbatt_soc */
-       if (cm->fuel_gauge && desc->fullbatt_soc > 0) {
+       if (desc->fullbatt_soc > 0) {
                val.intval = 0;
 
-               ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+               ret = fuel_gauge->get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_CAPACITY, &val);
                if (!ret && val.intval >= desc->fullbatt_soc)
                        return true;
@@ -551,6 +580,20 @@ static int check_charging_duration(struct charger_manager *cm)
        return ret;
 }
 
+static int cm_get_battery_temperature_by_psy(struct charger_manager *cm,
+                                       int *temp)
+{
+       struct power_supply *fuel_gauge;
+
+       fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+       if (!fuel_gauge)
+               return -ENODEV;
+
+       return fuel_gauge->get_property(fuel_gauge,
+                               POWER_SUPPLY_PROP_TEMP,
+                               (union power_supply_propval *)temp);
+}
+
 static int cm_get_battery_temperature(struct charger_manager *cm,
                                        int *temp)
 {
@@ -560,15 +603,18 @@ static int cm_get_battery_temperature(struct charger_manager *cm,
                return -ENODEV;
 
 #ifdef CONFIG_THERMAL
-       ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
-       if (!ret)
-               /* Calibrate temperature unit */
-               *temp /= 100;
-#else
-       ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
-                               POWER_SUPPLY_PROP_TEMP,
-                               (union power_supply_propval *)temp);
+       if (cm->tzd_batt) {
+               ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
+               if (!ret)
+                       /* Calibrate temperature unit */
+                       *temp /= 100;
+       } else
 #endif
+       {
+               /* if-else continued from CONFIG_THERMAL */
+               ret = cm_get_battery_temperature_by_psy(cm, temp);
+       }
+
        return ret;
 }
 
@@ -827,6 +873,7 @@ static int charger_get_property(struct power_supply *psy,
        struct charger_manager *cm = container_of(psy,
                        struct charger_manager, charger_psy);
        struct charger_desc *desc = cm->desc;
+       struct power_supply *fuel_gauge;
        int ret = 0;
        int uV;
 
@@ -857,14 +904,20 @@ static int charger_get_property(struct power_supply *psy,
                ret = get_batt_uV(cm, &val->intval);
                break;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
-               ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+               fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+               if (!fuel_gauge) {
+                       ret = -ENODEV;
+                       break;
+               }
+               ret = fuel_gauge->get_property(fuel_gauge,
                                POWER_SUPPLY_PROP_CURRENT_NOW, val);
                break;
        case POWER_SUPPLY_PROP_TEMP:
        case POWER_SUPPLY_PROP_TEMP_AMBIENT:
                return cm_get_battery_temperature(cm, &val->intval);
        case POWER_SUPPLY_PROP_CAPACITY:
-               if (!cm->fuel_gauge) {
+               fuel_gauge = power_supply_get_by_name(cm->desc->psy_fuel_gauge);
+               if (!fuel_gauge) {
                        ret = -ENODEV;
                        break;
                }
@@ -875,7 +928,7 @@ static int charger_get_property(struct power_supply *psy,
                        break;
                }
 
-               ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+               ret = fuel_gauge->get_property(fuel_gauge,
                                        POWER_SUPPLY_PROP_CAPACITY, val);
                if (ret)
                        break;
@@ -924,7 +977,14 @@ static int charger_get_property(struct power_supply *psy,
                break;
        case POWER_SUPPLY_PROP_CHARGE_NOW:
                if (is_charging(cm)) {
-                       ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+                       fuel_gauge = power_supply_get_by_name(
+                                       cm->desc->psy_fuel_gauge);
+                       if (!fuel_gauge) {
+                               ret = -ENODEV;
+                               break;
+                       }
+
+                       ret = fuel_gauge->get_property(fuel_gauge,
                                                POWER_SUPPLY_PROP_CHARGE_NOW,
                                                val);
                        if (ret) {
@@ -970,6 +1030,7 @@ static struct power_supply psy_default = {
        .properties = default_charger_props,
        .num_properties = ARRAY_SIZE(default_charger_props),
        .get_property = charger_get_property,
+       .no_thermal = true,
 };
 
 /**
@@ -1485,14 +1546,15 @@ err:
        return ret;
 }
 
-static int cm_init_thermal_data(struct charger_manager *cm)
+static int cm_init_thermal_data(struct charger_manager *cm,
+               struct power_supply *fuel_gauge)
 {
        struct charger_desc *desc = cm->desc;
        union power_supply_propval val;
        int ret;
 
        /* Verify whether fuel gauge provides battery temperature */
-       ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+       ret = fuel_gauge->get_property(fuel_gauge,
                                        POWER_SUPPLY_PROP_TEMP, &val);
 
        if (!ret) {
@@ -1502,8 +1564,6 @@ static int cm_init_thermal_data(struct charger_manager *cm)
                cm->desc->measure_battery_temp = true;
        }
 #ifdef CONFIG_THERMAL
-       cm->tzd_batt = cm->fuel_gauge->tzd;
-
        if (ret && desc->thermal_zone) {
                cm->tzd_batt =
                        thermal_zone_get_zone_by_name(desc->thermal_zone);
@@ -1666,6 +1726,7 @@ static int charger_manager_probe(struct platform_device *pdev)
        int ret = 0, i = 0;
        int j = 0;
        union power_supply_propval val;
+       struct power_supply *fuel_gauge;
 
        if (g_desc && !rtc_dev && g_desc->rtc_name) {
                rtc_dev = rtc_class_open(g_desc->rtc_name);
@@ -1729,23 +1790,20 @@ static int charger_manager_probe(struct platform_device *pdev)
        while (desc->psy_charger_stat[i])
                i++;
 
-       cm->charger_stat = devm_kzalloc(&pdev->dev,
-                               sizeof(struct power_supply *) * i, GFP_KERNEL);
-       if (!cm->charger_stat)
-               return -ENOMEM;
-
+       /* Check if charger's supplies are present at probe */
        for (i = 0; desc->psy_charger_stat[i]; i++) {
-               cm->charger_stat[i] = power_supply_get_by_name(
-                                       desc->psy_charger_stat[i]);
-               if (!cm->charger_stat[i]) {
+               struct power_supply *psy;
+
+               psy = power_supply_get_by_name(desc->psy_charger_stat[i]);
+               if (!psy) {
                        dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
                                desc->psy_charger_stat[i]);
                        return -ENODEV;
                }
        }
 
-       cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
-       if (!cm->fuel_gauge) {
+       fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
+       if (!fuel_gauge) {
                dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
                        desc->psy_fuel_gauge);
                return -ENODEV;
@@ -1788,13 +1846,13 @@ static int charger_manager_probe(struct platform_device *pdev)
        cm->charger_psy.num_properties = psy_default.num_properties;
 
        /* Find which optional psy-properties are available */
-       if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
+       if (!fuel_gauge->get_property(fuel_gauge,
                                          POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
                cm->charger_psy.properties[cm->charger_psy.num_properties] =
                                POWER_SUPPLY_PROP_CHARGE_NOW;
                cm->charger_psy.num_properties++;
        }
-       if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
+       if (!fuel_gauge->get_property(fuel_gauge,
                                          POWER_SUPPLY_PROP_CURRENT_NOW,
                                          &val)) {
                cm->charger_psy.properties[cm->charger_psy.num_properties] =
@@ -1802,7 +1860,7 @@ static int charger_manager_probe(struct platform_device *pdev)
                cm->charger_psy.num_properties++;
        }
 
-       ret = cm_init_thermal_data(cm);
+       ret = cm_init_thermal_data(cm, fuel_gauge);
        if (ret) {
                dev_err(&pdev->dev, "Failed to initialize thermal data\n");
                cm->desc->measure_battery_temp = false;
@@ -2066,8 +2124,8 @@ static bool find_power_supply(struct charger_manager *cm,
        int i;
        bool found = false;
 
-       for (i = 0; cm->charger_stat[i]; i++) {
-               if (psy == cm->charger_stat[i]) {
+       for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
+               if (!strcmp(psy->name, cm->desc->psy_charger_stat[i])) {
                        found = true;
                        break;
                }
index 6cb7fe5c022d48ca237e31eb89e78f8f70665776..694e8cddd5c13e1760e7c9cd5fc0170876a9df04 100644 (file)
@@ -417,6 +417,9 @@ static int psy_register_thermal(struct power_supply *psy)
 {
        int i;
 
+       if (psy->no_thermal)
+               return 0;
+
        /* Register battery zone device psy reports temperature */
        for (i = 0; i < psy->num_properties; i++) {
                if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
index f65ff49bb27508ca72817877c91790df54b5a8a6..028e765045196f89a9339f0dd5d733643b78fc66 100644 (file)
@@ -71,6 +71,15 @@ config POWER_RESET_HISI
        help
          Reboot support for Hisilicon boards.
 
+config POWER_RESET_IMX
+       bool "IMX6 power-off driver"
+       depends on POWER_RESET && SOC_IMX6
+       help
+         This driver support power off external PMIC by PMIC_ON_REQ on i.mx6
+         boards.If you want to use other pin to control external power,please
+         say N here or disable in dts to make sure pm_power_off never be
+         overwrote wrongly by this driver.
+
 config POWER_RESET_MSM
        bool "Qualcomm MSM power-off driver"
        depends on ARCH_QCOM
index 76ce1c59469b25851f5d2db7403bff5efb3fd99b..1d4804d6b3237c1ca4c7b98dd05db2878a622722 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
+obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
 obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
index 3611806c9cfdd01f3beb19ccefd1fbce825dcb10..69a75d99ae927a2fe254f81d512d4dd35e5ef909 100644 (file)
@@ -19,8 +19,8 @@
 
 #include <asm/system_misc.h>
 
-#include <mach/at91sam9_ddrsdr.h>
-#include <mach/at91sam9_sdramc.h>
+#include <soc/at91/at91sam9_ddrsdr.h>
+#include <soc/at91/at91sam9_sdramc.h>
 
 #define AT91_RSTC_CR   0x00            /* Reset Controller Control Register */
 #define AT91_RSTC_PROCRST      BIT(0)          /* Processor Reset */
@@ -100,11 +100,11 @@ static void at91sam9g45_restart(enum reboot_mode mode, const char *cmd)
                /* Disable SDRAM0 accesses */
                "1:     str     %3, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
                /* Power down SDRAM0 */
-               "       str     %4, [%0, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+               "       str     %4, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
                /* Disable SDRAM1 accesses */
                "       strne   %3, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
                /* Power down SDRAM1 */
-               "       strne   %4, [%1, #" __stringify(AT91_DDRSDRC_RTR) "]\n\t"
+               "       strne   %4, [%1, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"
                /* Reset CPU */
                "       str     %5, [%2, #" __stringify(AT91_RSTC_CR) "]\n\t"
 
diff --git a/drivers/power/reset/imx-snvs-poweroff.c b/drivers/power/reset/imx-snvs-poweroff.c
new file mode 100644 (file)
index 0000000..ad6ce50
--- /dev/null
@@ -0,0 +1,66 @@
+/* Power off driver for i.mx6
+ * Copyright (c) 2014, FREESCALE CORPORATION.  All rights reserved.
+ *
+ * based on msm-poweroff.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 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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+static void __iomem *snvs_base;
+
+static void do_imx_poweroff(void)
+{
+       u32 value = readl(snvs_base);
+
+       /* set TOP and DP_EN bit */
+       writel(value | 0x60, snvs_base);
+}
+
+static int imx_poweroff_probe(struct platform_device *pdev)
+{
+       snvs_base = of_iomap(pdev->dev.of_node, 0);
+       if (!snvs_base) {
+               dev_err(&pdev->dev, "failed to get memory\n");
+               return -ENODEV;
+       }
+
+       pm_power_off = do_imx_poweroff;
+       return 0;
+}
+
+static const struct of_device_id of_imx_poweroff_match[] = {
+       { .compatible = "fsl,sec-v4.0-poweroff", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_imx_poweroff_match);
+
+static struct platform_driver imx_poweroff_driver = {
+       .probe = imx_poweroff_probe,
+       .driver = {
+               .name = "imx-snvs-poweroff",
+               .of_match_table = of_match_ptr(of_imx_poweroff_match),
+       },
+};
+
+static int __init imx_poweroff_init(void)
+{
+       return platform_driver_register(&imx_poweroff_driver);
+}
+device_initcall(imx_poweroff_init);
index b800783800a3a133895d0cf6dcb3498e48528516..ef2dd2e4754bacd784cd519ec7f4b66216a13e99 100644 (file)
@@ -83,6 +83,7 @@ config PWM_BFIN
 config PWM_CLPS711X
        tristate "CLPS711X PWM support"
        depends on ARCH_CLPS711X || COMPILE_TEST
+       depends on HAS_IOMEM
        help
          Generic PWM framework driver for Cirrus Logic CLPS711X.
 
@@ -101,6 +102,7 @@ config PWM_EP93XX
 config PWM_FSL_FTM
        tristate "Freescale FlexTimer Module (FTM) PWM support"
        depends on OF
+       select REGMAP_MMIO
        help
          Generic FTM PWM framework driver for Freescale VF610 and
          Layerscape LS-1 SoCs.
@@ -149,7 +151,7 @@ config PWM_LPC32XX
 
 config PWM_LPSS
        tristate "Intel LPSS PWM support"
-       depends on ACPI
+       depends on X86
        help
          Generic PWM framework driver for Intel Low Power Subsystem PWM
          controller.
@@ -157,6 +159,24 @@ config PWM_LPSS
          To compile this driver as a module, choose M here: the module
          will be called pwm-lpss.
 
+config PWM_LPSS_PCI
+       tristate "Intel LPSS PWM PCI driver"
+       depends on PWM_LPSS && PCI
+       help
+         The PCI driver for Intel Low Power Subsystem PWM controller.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-lpss-pci.
+
+config PWM_LPSS_PLATFORM
+       tristate "Intel LPSS PWM platform driver"
+       depends on PWM_LPSS && ACPI
+       help
+         The platform driver for Intel Low Power Subsystem PWM controller.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-lpss-platform.
+
 config PWM_MXS
        tristate "Freescale MXS PWM support"
        depends on ARCH_MXS && OF
index f8c577d410916e7b7c4c889a4138d62d3c0fc326..c458606c3755c327ed5e648c3ddc68e2b884ffeb 100644 (file)
@@ -13,6 +13,8 @@ obj-$(CONFIG_PWM_JZ4740)      += pwm-jz4740.o
 obj-$(CONFIG_PWM_LP3943)       += pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC32XX)      += pwm-lpc32xx.o
 obj-$(CONFIG_PWM_LPSS)         += pwm-lpss.o
+obj-$(CONFIG_PWM_LPSS_PCI)     += pwm-lpss-pci.o
+obj-$(CONFIG_PWM_LPSS_PLATFORM)        += pwm-lpss-platform.o
 obj-$(CONFIG_PWM_MXS)          += pwm-mxs.o
 obj-$(CONFIG_PWM_PCA9685)      += pwm-pca9685.o
 obj-$(CONFIG_PWM_PUV3)         += pwm-puv3.o
index d2c35920ff08e7e84e4f1a6be3ce1c15454b2a4b..966497d10c6ef201144fd6cd66edef7298b18c99 100644 (file)
@@ -236,7 +236,7 @@ int pwmchip_add(struct pwm_chip *chip)
        int ret;
 
        if (!chip || !chip->dev || !chip->ops || !chip->ops->config ||
-           !chip->ops->enable || !chip->ops->disable)
+           !chip->ops->enable || !chip->ops->disable || !chip->npwm)
                return -EINVAL;
 
        mutex_lock(&pwm_lock);
@@ -602,12 +602,9 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
        struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER);
        const char *dev_id = dev ? dev_name(dev) : NULL;
        struct pwm_chip *chip = NULL;
-       unsigned int index = 0;
        unsigned int best = 0;
-       struct pwm_lookup *p;
+       struct pwm_lookup *p, *chosen = NULL;
        unsigned int match;
-       unsigned int period;
-       enum pwm_polarity polarity;
 
        /* look up via DT first */
        if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
@@ -653,10 +650,7 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
                }
 
                if (match > best) {
-                       chip = pwmchip_find_by_name(p->provider);
-                       index = p->index;
-                       period = p->period;
-                       polarity = p->polarity;
+                       chosen = p;
 
                        if (match != 3)
                                best = match;
@@ -665,17 +659,22 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
                }
        }
 
-       mutex_unlock(&pwm_lookup_lock);
+       if (!chosen)
+               goto out;
 
-       if (chip)
-               pwm = pwm_request_from_chip(chip, index, con_id ?: dev_id);
-       if (IS_ERR(pwm))
-               return pwm;
+       chip = pwmchip_find_by_name(chosen->provider);
+       if (!chip)
+               goto out;
 
-       pwm_set_period(pwm, period);
-       pwm_set_polarity(pwm, polarity);
+       pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id);
+       if (IS_ERR(pwm))
+               goto out;
 
+       pwm_set_period(pwm, chosen->period);
+       pwm_set_polarity(pwm, chosen->polarity);
 
+out:
+       mutex_unlock(&pwm_lookup_lock);
        return pwm;
 }
 EXPORT_SYMBOL_GPL(pwm_get);
index 6e700a541ca32ded0d5881842214a53d87ffe0f6..d3c22de9ee47b8e7546557bc756e62a353c62556 100644 (file)
@@ -102,7 +102,7 @@ static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                            int duty_ns, int period_ns)
 {
        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
-       unsigned long clk_rate, prd, dty;
+       unsigned long prd, dty;
        unsigned long long div;
        unsigned int pres = 0;
        u32 val;
@@ -113,20 +113,18 @@ static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                return -EBUSY;
        }
 
-       clk_rate = clk_get_rate(atmel_pwm->clk);
-       div = clk_rate;
+       /* Calculate the period cycles and prescale value */
+       div = (unsigned long long)clk_get_rate(atmel_pwm->clk) * period_ns;
+       do_div(div, NSEC_PER_SEC);
 
-       /* Calculate the period cycles */
        while (div > PWM_MAX_PRD) {
-               div = clk_rate / (1 << pres);
-               div = div * period_ns;
-               /* 1/Hz = 100000000 ns */
-               do_div(div, 1000000000);
-
-               if (pres++ > PRD_MAX_PRES) {
-                       dev_err(chip->dev, "pres exceeds the maximum value\n");
-                       return -EINVAL;
-               }
+               div >>= 1;
+               pres++;
+       }
+
+       if (pres > PRD_MAX_PRES) {
+               dev_err(chip->dev, "pres exceeds the maximum value\n");
+               return -EINVAL;
        }
 
        /* Calculate the duty cycles */
index a18bc8fea3853bf96671938ab021cb1d9c71f66b..0f2cc7ef77848d3cec24ad9e4e6e428bbad7f318 100644 (file)
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 
 #define FTM_SC         0x00
-#define FTM_SC_CLK_MASK        0x3
-#define FTM_SC_CLK_SHIFT       3
-#define FTM_SC_CLK(c)  (((c) + 1) << FTM_SC_CLK_SHIFT)
+#define FTM_SC_CLK_MASK_SHIFT  3
+#define FTM_SC_CLK_MASK        (3 << FTM_SC_CLK_MASK_SHIFT)
+#define FTM_SC_CLK(c)  (((c) + 1) << FTM_SC_CLK_MASK_SHIFT)
 #define FTM_SC_PS_MASK 0x7
-#define FTM_SC_PS_SHIFT        0
 
 #define FTM_CNT                0x04
 #define FTM_MOD                0x08
@@ -83,7 +83,7 @@ struct fsl_pwm_chip {
        unsigned int cnt_select;
        unsigned int clk_ps;
 
-       void __iomem *base;
+       struct regmap *regmap;
 
        int period_ns;
 
@@ -219,10 +219,11 @@ static unsigned long fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc,
                                            unsigned long period_ns,
                                            unsigned long duty_ns)
 {
-       unsigned long long val, duty;
+       unsigned long long duty;
+       u32 val;
 
-       val = readl(fpc->base + FTM_MOD);
-       duty = duty_ns * (val + 1);
+       regmap_read(fpc->regmap, FTM_MOD, &val);
+       duty = (unsigned long long)duty_ns * (val + 1);
        do_div(duty, period_ns);
 
        return (unsigned long)duty;
@@ -232,7 +233,7 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                          int duty_ns, int period_ns)
 {
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
-       u32 val, period, duty;
+       u32 period, duty;
 
        mutex_lock(&fpc->lock);
 
@@ -257,11 +258,9 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                        return -EINVAL;
                }
 
-               val = readl(fpc->base + FTM_SC);
-               val &= ~(FTM_SC_PS_MASK << FTM_SC_PS_SHIFT);
-               val |= fpc->clk_ps;
-               writel(val, fpc->base + FTM_SC);
-               writel(period - 1, fpc->base + FTM_MOD);
+               regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_PS_MASK,
+                                  fpc->clk_ps);
+               regmap_write(fpc->regmap, FTM_MOD, period - 1);
 
                fpc->period_ns = period_ns;
        }
@@ -270,8 +269,9 @@ static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 
        duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns);
 
-       writel(FTM_CSC_MSB | FTM_CSC_ELSB, fpc->base + FTM_CSC(pwm->hwpwm));
-       writel(duty, fpc->base + FTM_CV(pwm->hwpwm));
+       regmap_write(fpc->regmap, FTM_CSC(pwm->hwpwm),
+                    FTM_CSC_MSB | FTM_CSC_ELSB);
+       regmap_write(fpc->regmap, FTM_CV(pwm->hwpwm), duty);
 
        return 0;
 }
@@ -283,31 +283,28 @@ static int fsl_pwm_set_polarity(struct pwm_chip *chip,
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
        u32 val;
 
-       val = readl(fpc->base + FTM_POL);
+       regmap_read(fpc->regmap, FTM_POL, &val);
 
        if (polarity == PWM_POLARITY_INVERSED)
                val |= BIT(pwm->hwpwm);
        else
                val &= ~BIT(pwm->hwpwm);
 
-       writel(val, fpc->base + FTM_POL);
+       regmap_write(fpc->regmap, FTM_POL, val);
 
        return 0;
 }
 
 static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
 {
-       u32 val;
        int ret;
 
        if (fpc->use_count != 0)
                return 0;
 
        /* select counter clock source */
-       val = readl(fpc->base + FTM_SC);
-       val &= ~(FTM_SC_CLK_MASK << FTM_SC_CLK_SHIFT);
-       val |= FTM_SC_CLK(fpc->cnt_select);
-       writel(val, fpc->base + FTM_SC);
+       regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK,
+                          FTM_SC_CLK(fpc->cnt_select));
 
        ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]);
        if (ret)
@@ -327,13 +324,10 @@ static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
 static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
-       u32 val;
        int ret;
 
        mutex_lock(&fpc->lock);
-       val = readl(fpc->base + FTM_OUTMASK);
-       val &= ~BIT(pwm->hwpwm);
-       writel(val, fpc->base + FTM_OUTMASK);
+       regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm), 0);
 
        ret = fsl_counter_clock_enable(fpc);
        mutex_unlock(&fpc->lock);
@@ -343,8 +337,6 @@ static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
 {
-       u32 val;
-
        /*
         * already disabled, do nothing
         */
@@ -356,9 +348,7 @@ static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
                return;
 
        /* no users left, disable PWM counter clock */
-       val = readl(fpc->base + FTM_SC);
-       val &= ~(FTM_SC_CLK_MASK << FTM_SC_CLK_SHIFT);
-       writel(val, fpc->base + FTM_SC);
+       regmap_update_bits(fpc->regmap, FTM_SC, FTM_SC_CLK_MASK, 0);
 
        clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]);
        clk_disable_unprepare(fpc->clk[fpc->cnt_select]);
@@ -370,14 +360,12 @@ static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
        u32 val;
 
        mutex_lock(&fpc->lock);
-       val = readl(fpc->base + FTM_OUTMASK);
-       val |= BIT(pwm->hwpwm);
-       writel(val, fpc->base + FTM_OUTMASK);
+       regmap_update_bits(fpc->regmap, FTM_OUTMASK, BIT(pwm->hwpwm),
+                          BIT(pwm->hwpwm));
 
        fsl_counter_clock_disable(fpc);
 
-       val = readl(fpc->base + FTM_OUTMASK);
-
+       regmap_read(fpc->regmap, FTM_OUTMASK, &val);
        if ((val & 0xFF) == 0xFF)
                fpc->period_ns = 0;
 
@@ -402,19 +390,28 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
        if (ret)
                return ret;
 
-       writel(0x00, fpc->base + FTM_CNTIN);
-       writel(0x00, fpc->base + FTM_OUTINIT);
-       writel(0xFF, fpc->base + FTM_OUTMASK);
+       regmap_write(fpc->regmap, FTM_CNTIN, 0x00);
+       regmap_write(fpc->regmap, FTM_OUTINIT, 0x00);
+       regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF);
 
        clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
 
        return 0;
 }
 
+static const struct regmap_config fsl_pwm_regmap_config = {
+       .reg_bits = 32,
+       .reg_stride = 4,
+       .val_bits = 32,
+
+       .max_register = FTM_PWMLOAD,
+};
+
 static int fsl_pwm_probe(struct platform_device *pdev)
 {
        struct fsl_pwm_chip *fpc;
        struct resource *res;
+       void __iomem *base;
        int ret;
 
        fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL);
@@ -426,9 +423,16 @@ static int fsl_pwm_probe(struct platform_device *pdev)
        fpc->chip.dev = &pdev->dev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       fpc->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(fpc->base))
-               return PTR_ERR(fpc->base);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       fpc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
+                                               &fsl_pwm_regmap_config);
+       if (IS_ERR(fpc->regmap)) {
+               dev_err(&pdev->dev, "regmap init failed\n");
+               return PTR_ERR(fpc->regmap);
+       }
 
        fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys");
        if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) {
index 5449d9150d40d245fdd2380ca291ca53aa2b0b31..f8b5f109c1abc570eb891e57a9ce86f05da91e07 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/pwm.h>
 #include <linux/of.h>
 
 /* i.MX1 and i.MX21 share the same PWM function block: */
 
-#define MX1_PWMC    0x00   /* PWM Control Register */
-#define MX1_PWMS    0x04   /* PWM Sample Register */
-#define MX1_PWMP    0x08   /* PWM Period Register */
+#define MX1_PWMC                       0x00   /* PWM Control Register */
+#define MX1_PWMS                       0x04   /* PWM Sample Register */
+#define MX1_PWMP                       0x08   /* PWM Period Register */
 
-#define MX1_PWMC_EN            (1 << 4)
+#define MX1_PWMC_EN                    (1 << 4)
 
 /* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
 
-#define MX3_PWMCR                 0x00    /* PWM Control Register */
-#define MX3_PWMSAR                0x0C    /* PWM Sample Register */
-#define MX3_PWMPR                 0x10    /* PWM Period Register */
-#define MX3_PWMCR_PRESCALER(x)    (((x - 1) & 0xFFF) << 4)
-#define MX3_PWMCR_DOZEEN                (1 << 24)
-#define MX3_PWMCR_WAITEN                (1 << 23)
+#define MX3_PWMCR                      0x00    /* PWM Control Register */
+#define MX3_PWMSR                      0x04    /* PWM Status Register */
+#define MX3_PWMSAR                     0x0C    /* PWM Sample Register */
+#define MX3_PWMPR                      0x10    /* PWM Period Register */
+#define MX3_PWMCR_PRESCALER(x)         ((((x) - 1) & 0xFFF) << 4)
+#define MX3_PWMCR_DOZEEN               (1 << 24)
+#define MX3_PWMCR_WAITEN               (1 << 23)
 #define MX3_PWMCR_DBGEN                        (1 << 22)
-#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
-#define MX3_PWMCR_CLKSRC_IPG      (1 << 16)
-#define MX3_PWMCR_EN              (1 << 0)
+#define MX3_PWMCR_CLKSRC_IPG_HIGH      (2 << 16)
+#define MX3_PWMCR_CLKSRC_IPG           (1 << 16)
+#define MX3_PWMCR_SWR                  (1 << 3)
+#define MX3_PWMCR_EN                   (1 << 0)
+#define MX3_PWMSR_FIFOAV_4WORDS                0x4
+#define MX3_PWMSR_FIFOAV_MASK          0x7
+
+#define MX3_PWM_SWR_LOOP               5
 
 struct imx_chip {
        struct clk      *clk_per;
@@ -103,9 +110,43 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
                struct pwm_device *pwm, int duty_ns, int period_ns)
 {
        struct imx_chip *imx = to_imx_chip(chip);
+       struct device *dev = chip->dev;
        unsigned long long c;
        unsigned long period_cycles, duty_cycles, prescale;
-       u32 cr;
+       unsigned int period_ms;
+       bool enable = test_bit(PWMF_ENABLED, &pwm->flags);
+       int wait_count = 0, fifoav;
+       u32 cr, sr;
+
+       /*
+        * i.MX PWMv2 has a 4-word sample FIFO.
+        * In order to avoid FIFO overflow issue, we do software reset
+        * to clear all sample FIFO if the controller is disabled or
+        * wait for a full PWM cycle to get a relinquished FIFO slot
+        * when the controller is enabled and the FIFO is fully loaded.
+        */
+       if (enable) {
+               sr = readl(imx->mmio_base + MX3_PWMSR);
+               fifoav = sr & MX3_PWMSR_FIFOAV_MASK;
+               if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
+                       period_ms = DIV_ROUND_UP(pwm->period, NSEC_PER_MSEC);
+                       msleep(period_ms);
+
+                       sr = readl(imx->mmio_base + MX3_PWMSR);
+                       if (fifoav == (sr & MX3_PWMSR_FIFOAV_MASK))
+                               dev_warn(dev, "there is no free FIFO slot\n");
+               }
+       } else {
+               writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR);
+               do {
+                       usleep_range(200, 1000);
+                       cr = readl(imx->mmio_base + MX3_PWMCR);
+               } while ((cr & MX3_PWMCR_SWR) &&
+                        (wait_count++ < MX3_PWM_SWR_LOOP));
+
+               if (cr & MX3_PWMCR_SWR)
+                       dev_warn(dev, "software reset timeout\n");
+       }
 
        c = clk_get_rate(imx->clk_per);
        c = c * period_ns;
@@ -135,7 +176,7 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
                MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN |
                MX3_PWMCR_DBGEN | MX3_PWMCR_CLKSRC_IPG_HIGH;
 
-       if (test_bit(PWMF_ENABLED, &pwm->flags))
+       if (enable)
                cr |= MX3_PWMCR_EN;
 
        writel(cr, imx->mmio_base + MX3_PWMCR);
diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c
new file mode 100644 (file)
index 0000000..cf20d2b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Intel Low Power Subsystem PWM controller PCI driver
+ *
+ * Copyright (C) 2014, Intel Corporation
+ *
+ * Derived from the original pwm-lpss.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/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "pwm-lpss.h"
+
+static int pwm_lpss_probe_pci(struct pci_dev *pdev,
+                             const struct pci_device_id *id)
+{
+       const struct pwm_lpss_boardinfo *info;
+       struct pwm_lpss_chip *lpwm;
+       int err;
+
+       err = pcim_enable_device(pdev);
+       if (err < 0)
+               return err;
+
+       info = (struct pwm_lpss_boardinfo *)id->driver_data;
+       lpwm = pwm_lpss_probe(&pdev->dev, &pdev->resource[0], info);
+       if (IS_ERR(lpwm))
+               return PTR_ERR(lpwm);
+
+       pci_set_drvdata(pdev, lpwm);
+       return 0;
+}
+
+static void pwm_lpss_remove_pci(struct pci_dev *pdev)
+{
+       struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev);
+
+       pwm_lpss_remove(lpwm);
+}
+
+static const struct pci_device_id pwm_lpss_pci_ids[] = {
+       { PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
+       { PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info},
+       { PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
+       { PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
+       { },
+};
+MODULE_DEVICE_TABLE(pci, pwm_lpss_pci_ids);
+
+static struct pci_driver pwm_lpss_driver_pci = {
+       .name = "pwm-lpss",
+       .id_table = pwm_lpss_pci_ids,
+       .probe = pwm_lpss_probe_pci,
+       .remove = pwm_lpss_remove_pci,
+};
+module_pci_driver(pwm_lpss_driver_pci);
+
+MODULE_DESCRIPTION("PWM PCI driver for Intel LPSS");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
new file mode 100644 (file)
index 0000000..18a9c88
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Intel Low Power Subsystem PWM controller driver
+ *
+ * Copyright (C) 2014, Intel Corporation
+ *
+ * Derived from the original pwm-lpss.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/acpi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "pwm-lpss.h"
+
+static int pwm_lpss_probe_platform(struct platform_device *pdev)
+{
+       const struct pwm_lpss_boardinfo *info;
+       const struct acpi_device_id *id;
+       struct pwm_lpss_chip *lpwm;
+       struct resource *r;
+
+       id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+       if (!id)
+               return -ENODEV;
+
+       info = (const struct pwm_lpss_boardinfo *)id->driver_data;
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       lpwm = pwm_lpss_probe(&pdev->dev, r, info);
+       if (IS_ERR(lpwm))
+               return PTR_ERR(lpwm);
+
+       platform_set_drvdata(pdev, lpwm);
+       return 0;
+}
+
+static int pwm_lpss_remove_platform(struct platform_device *pdev)
+{
+       struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev);
+
+       return pwm_lpss_remove(lpwm);
+}
+
+static const struct acpi_device_id pwm_lpss_acpi_match[] = {
+       { "80860F09", (unsigned long)&pwm_lpss_byt_info },
+       { "80862288", (unsigned long)&pwm_lpss_bsw_info },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
+
+static struct platform_driver pwm_lpss_driver_platform = {
+       .driver = {
+               .name = "pwm-lpss",
+               .acpi_match_table = pwm_lpss_acpi_match,
+       },
+       .probe = pwm_lpss_probe_platform,
+       .remove = pwm_lpss_remove_platform,
+};
+module_platform_driver(pwm_lpss_driver_platform);
+
+MODULE_DESCRIPTION("PWM platform driver for Intel LPSS");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:pwm-lpss");
index 4df994f72d9604071f936e72b1f3e52dce5633d6..e9798253a16fcfb76117c219c1c7212e171f8fe5 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include <linux/acpi.h>
-#include <linux/device.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/pwm.h>
-#include <linux/platform_device.h>
-#include <linux/pci.h>
 
-static int pci_drv, plat_drv;  /* So we know which drivers registered */
+#include "pwm-lpss.h"
 
 #define PWM                            0x00000000
 #define PWM_ENABLE                     BIT(31)
@@ -39,14 +35,17 @@ struct pwm_lpss_chip {
        unsigned long clk_rate;
 };
 
-struct pwm_lpss_boardinfo {
-       unsigned long clk_rate;
+/* BayTrail */
+const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
+       .clk_rate = 25000000
 };
+EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
 
-/* BayTrail */
-static const struct pwm_lpss_boardinfo byt_info = {
-       25000000
+/* Braswell */
+const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
+       .clk_rate = 19200000
 };
+EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
 
 static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
 {
@@ -118,9 +117,8 @@ static const struct pwm_ops pwm_lpss_ops = {
        .owner = THIS_MODULE,
 };
 
-static struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev,
-                                           struct resource *r,
-                                           const struct pwm_lpss_boardinfo *info)
+struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
+                                    const struct pwm_lpss_boardinfo *info)
 {
        struct pwm_lpss_chip *lpwm;
        int ret;
@@ -147,8 +145,9 @@ static struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev,
 
        return lpwm;
 }
+EXPORT_SYMBOL_GPL(pwm_lpss_probe);
 
-static int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
+int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
 {
        u32 ctrl;
 
@@ -157,114 +156,8 @@ static int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
 
        return pwmchip_remove(&lpwm->chip);
 }
-
-static int pwm_lpss_probe_pci(struct pci_dev *pdev,
-                             const struct pci_device_id *id)
-{
-       const struct pwm_lpss_boardinfo *info;
-       struct pwm_lpss_chip *lpwm;
-       int err;
-
-       err = pci_enable_device(pdev);
-       if (err < 0)
-               return err;
-
-       info = (struct pwm_lpss_boardinfo *)id->driver_data;
-       lpwm = pwm_lpss_probe(&pdev->dev, &pdev->resource[0], info);
-       if (IS_ERR(lpwm))
-               return PTR_ERR(lpwm);
-
-       pci_set_drvdata(pdev, lpwm);
-       return 0;
-}
-
-static void pwm_lpss_remove_pci(struct pci_dev *pdev)
-{
-       struct pwm_lpss_chip *lpwm = pci_get_drvdata(pdev);
-
-       pwm_lpss_remove(lpwm);
-       pci_disable_device(pdev);
-}
-
-static struct pci_device_id pwm_lpss_pci_ids[] = {
-       { PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&byt_info},
-       { PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&byt_info},
-       { },
-};
-MODULE_DEVICE_TABLE(pci, pwm_lpss_pci_ids);
-
-static struct pci_driver pwm_lpss_driver_pci = {
-       .name = "pwm-lpss",
-       .id_table = pwm_lpss_pci_ids,
-       .probe = pwm_lpss_probe_pci,
-       .remove = pwm_lpss_remove_pci,
-};
-
-static int pwm_lpss_probe_platform(struct platform_device *pdev)
-{
-       const struct pwm_lpss_boardinfo *info;
-       const struct acpi_device_id *id;
-       struct pwm_lpss_chip *lpwm;
-       struct resource *r;
-
-       id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
-       if (!id)
-               return -ENODEV;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       info = (struct pwm_lpss_boardinfo *)id->driver_data;
-       lpwm = pwm_lpss_probe(&pdev->dev, r, info);
-       if (IS_ERR(lpwm))
-               return PTR_ERR(lpwm);
-
-       platform_set_drvdata(pdev, lpwm);
-       return 0;
-}
-
-static int pwm_lpss_remove_platform(struct platform_device *pdev)
-{
-       struct pwm_lpss_chip *lpwm = platform_get_drvdata(pdev);
-
-       return pwm_lpss_remove(lpwm);
-}
-
-static const struct acpi_device_id pwm_lpss_acpi_match[] = {
-       { "80860F09", (unsigned long)&byt_info },
-       { },
-};
-MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
-
-static struct platform_driver pwm_lpss_driver_platform = {
-       .driver = {
-               .name = "pwm-lpss",
-               .acpi_match_table = pwm_lpss_acpi_match,
-       },
-       .probe = pwm_lpss_probe_platform,
-       .remove = pwm_lpss_remove_platform,
-};
-
-static int __init pwm_init(void)
-{
-       pci_drv = pci_register_driver(&pwm_lpss_driver_pci);
-       plat_drv = platform_driver_register(&pwm_lpss_driver_platform);
-       if (pci_drv && plat_drv)
-               return pci_drv;
-
-       return 0;
-}
-module_init(pwm_init);
-
-static void __exit pwm_exit(void)
-{
-       if (!pci_drv)
-               pci_unregister_driver(&pwm_lpss_driver_pci);
-       if (!plat_drv)
-               platform_driver_unregister(&pwm_lpss_driver_platform);
-}
-module_exit(pwm_exit);
+EXPORT_SYMBOL_GPL(pwm_lpss_remove);
 
 MODULE_DESCRIPTION("PWM driver for Intel LPSS");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:pwm-lpss");
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
new file mode 100644 (file)
index 0000000..aa041bb
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Intel Low Power Subsystem PWM controller driver
+ *
+ * Copyright (C) 2014, Intel Corporation
+ *
+ * Derived from the original pwm-lpss.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 __PWM_LPSS_H
+#define __PWM_LPSS_H
+
+#include <linux/device.h>
+#include <linux/pwm.h>
+
+struct pwm_lpss_chip;
+
+struct pwm_lpss_boardinfo {
+       unsigned long clk_rate;
+};
+
+extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
+extern const struct pwm_lpss_boardinfo pwm_lpss_bsw_info;
+
+struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
+                                    const struct pwm_lpss_boardinfo *info);
+int pwm_lpss_remove(struct pwm_lpss_chip *lpwm);
+
+#endif /* __PWM_LPSS_H */
index bdd8644c01cf18bb62ad169cf3de4729b29421e8..9442df244101772259a0ddb6824fe6035c4dd568 100644 (file)
@@ -24,7 +24,9 @@
 #define PWM_ENABLE             (1 << 0)
 #define PWM_CONTINUOUS         (1 << 1)
 #define PWM_DUTY_POSITIVE      (1 << 3)
+#define PWM_DUTY_NEGATIVE      (0 << 3)
 #define PWM_INACTIVE_NEGATIVE  (0 << 4)
+#define PWM_INACTIVE_POSITIVE  (1 << 4)
 #define PWM_OUTPUT_LEFT                (0 << 5)
 #define PWM_LP_DISABLE         (0 << 8)
 
@@ -45,8 +47,10 @@ struct rockchip_pwm_regs {
 struct rockchip_pwm_data {
        struct rockchip_pwm_regs regs;
        unsigned int prescaler;
+       const struct pwm_ops *ops;
 
-       void (*set_enable)(struct pwm_chip *chip, bool enable);
+       void (*set_enable)(struct pwm_chip *chip,
+                          struct pwm_device *pwm, bool enable);
 };
 
 static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
@@ -54,7 +58,8 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
        return container_of(c, struct rockchip_pwm_chip, chip);
 }
 
-static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
+static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip,
+                                      struct pwm_device *pwm, bool enable)
 {
        struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
        u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
@@ -70,14 +75,19 @@ static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
        writel_relaxed(val, pc->base + pc->data->regs.ctrl);
 }
 
-static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
+static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
+                                      struct pwm_device *pwm, bool enable)
 {
        struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
        u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
-                         PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
-                         PWM_INACTIVE_NEGATIVE;
+                         PWM_CONTINUOUS;
        u32 val;
 
+       if (pwm->polarity == PWM_POLARITY_INVERSED)
+               enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
+       else
+               enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
+
        val = readl_relaxed(pc->base + pc->data->regs.ctrl);
 
        if (enable)
@@ -124,6 +134,19 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        return 0;
 }
 
+static int rockchip_pwm_set_polarity(struct pwm_chip *chip,
+                                    struct pwm_device *pwm,
+                                    enum pwm_polarity polarity)
+{
+       /*
+        * No action needed here because pwm->polarity will be set by the core
+        * and the core will only change polarity when the PWM is not enabled.
+        * We'll handle things in set_enable().
+        */
+
+       return 0;
+}
+
 static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
@@ -133,7 +156,7 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
        if (ret)
                return ret;
 
-       pc->data->set_enable(chip, true);
+       pc->data->set_enable(chip, pwm, true);
 
        return 0;
 }
@@ -142,18 +165,26 @@ static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
 
-       pc->data->set_enable(chip, false);
+       pc->data->set_enable(chip, pwm, false);
 
        clk_disable(pc->clk);
 }
 
-static const struct pwm_ops rockchip_pwm_ops = {
+static const struct pwm_ops rockchip_pwm_ops_v1 = {
        .config = rockchip_pwm_config,
        .enable = rockchip_pwm_enable,
        .disable = rockchip_pwm_disable,
        .owner = THIS_MODULE,
 };
 
+static const struct pwm_ops rockchip_pwm_ops_v2 = {
+       .config = rockchip_pwm_config,
+       .set_polarity = rockchip_pwm_set_polarity,
+       .enable = rockchip_pwm_enable,
+       .disable = rockchip_pwm_disable,
+       .owner = THIS_MODULE,
+};
+
 static const struct rockchip_pwm_data pwm_data_v1 = {
        .regs = {
                .duty = 0x04,
@@ -162,6 +193,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = {
                .ctrl = 0x0c,
        },
        .prescaler = 2,
+       .ops = &rockchip_pwm_ops_v1,
        .set_enable = rockchip_pwm_set_enable_v1,
 };
 
@@ -173,6 +205,7 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
                .ctrl = 0x0c,
        },
        .prescaler = 1,
+       .ops = &rockchip_pwm_ops_v2,
        .set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -184,6 +217,7 @@ static const struct rockchip_pwm_data pwm_data_vop = {
                .ctrl = 0x00,
        },
        .prescaler = 1,
+       .ops = &rockchip_pwm_ops_v2,
        .set_enable = rockchip_pwm_set_enable_v2,
 };
 
@@ -227,10 +261,15 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
 
        pc->data = id->data;
        pc->chip.dev = &pdev->dev;
-       pc->chip.ops = &rockchip_pwm_ops;
+       pc->chip.ops = pc->data->ops;
        pc->chip.base = -1;
        pc->chip.npwm = 1;
 
+       if (pc->data->ops->set_polarity) {
+               pc->chip.of_xlate = of_pwm_xlate_with_flags;
+               pc->chip.of_pwm_n_cells = 3;
+       }
+
        ret = pwmchip_add(&pc->chip);
        if (ret < 0) {
                clk_unprepare(pc->clk);
index 6d77dcd7dcf6cfb3a8f76745c779d09eae2f7d97..3fe47bd66153e06ecdf965a368d4a665d1fe725b 100644 (file)
@@ -330,7 +330,8 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
        for_each_child_of_node(nproot, np) {
                if (!of_node_cmp(np->name, info->desc.name)) {
                        config->init_data =
-                               of_get_regulator_init_data(&pdev->dev, np);
+                               of_get_regulator_init_data(&pdev->dev, np,
+                                                          &info->desc);
                        config->of_node = np;
                        break;
                }
index 55d7b7b0f2e011d036826111f5064c600b639d23..c3a60b57a865eae77b232ff6d94a2700df3fa5d7 100644 (file)
@@ -521,6 +521,14 @@ config REGULATOR_RN5T618
        help
          Say y here to support the regulators found on Ricoh RN5T618 PMIC.
 
+config REGULATOR_RT5033
+       tristate "Richtek RT5033 Regulators"
+       depends on MFD_RT5033
+       help
+         This adds support for voltage and current regulators in Richtek
+         RT5033 PMIC. The device supports multiple regulators like
+         current source, LDO and Buck.
+
 config REGULATOR_S2MPA01
        tristate "Samsung S2MPA01 voltage regulator"
        depends on MFD_SEC_CORE
@@ -529,13 +537,13 @@ config REGULATOR_S2MPA01
         via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
 
 config REGULATOR_S2MPS11
-       tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator"
+       tristate "Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage regulator"
        depends on MFD_SEC_CORE
        help
-        This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output
-        regulator via I2C bus. The chip is comprised of high efficient Buck
-        converters including Dual-Phase Buck converter, Buck-Boost converter,
-        various LDOs.
+        This driver supports a Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage
+        output regulator via I2C bus. The chip is comprised of high efficient
+        Buck converters including Dual-Phase Buck converter, Buck-Boost
+        converter, various LDOs.
 
 config REGULATOR_S5M8767
        tristate "Samsung S5M8767A voltage regulator"
@@ -547,7 +555,7 @@ config REGULATOR_S5M8767
 
 config REGULATOR_SKY81452
        tristate "Skyworks Solutions SKY81452 voltage regulator"
-       depends on SKY81452
+       depends on MFD_SKY81452
        help
          This driver supports Skyworks SKY81452 voltage output regulator
          via I2C bus. SKY81452 has one voltage linear regulator can be
index 1029ed39c5124b3fd95e3203abe7448da4b0c501..1f28ebfc6f3a09b3b555a23a2633a6402d1c141b 100644 (file)
@@ -69,6 +69,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
 obj-$(CONFIG_REGULATOR_RK808)   += rk808-regulator.o
 obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o
+obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o
 obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
index afd06f92dfdf006cba0cc282d5e87e0b757bdf9e..9eec453b745d87facf2bb339194f0b6f32d80feb 100644 (file)
@@ -61,6 +61,8 @@
 #define        ACT8846_REG12_VSET      0xa0
 #define        ACT8846_REG12_CTRL      0xa1
 #define        ACT8846_REG13_CTRL      0xb1
+#define        ACT8846_GLB_OFF_CTRL    0xc3
+#define        ACT8846_OFF_SYSMASK     0x18
 
 /*
  * ACT8865 Global Register Map.
@@ -84,6 +86,7 @@
 #define        ACT8865_LDO3_CTRL       0x61
 #define        ACT8865_LDO4_VSET       0x64
 #define        ACT8865_LDO4_CTRL       0x65
+#define        ACT8865_MSTROFF         0x20
 
 /*
  * Field Definitions.
 
 struct act8865 {
        struct regmap *regmap;
+       int off_reg;
+       int off_mask;
 };
 
 static const struct regmap_config act8865_regmap_config = {
@@ -275,6 +280,16 @@ static struct regulator_init_data
        return NULL;
 }
 
+static struct i2c_client *act8865_i2c_client;
+static void act8865_power_off(void)
+{
+       struct act8865 *act8865;
+
+       act8865 = i2c_get_clientdata(act8865_i2c_client);
+       regmap_write(act8865->regmap, act8865->off_reg, act8865->off_mask);
+       while (1);
+}
+
 static int act8865_pmic_probe(struct i2c_client *client,
                              const struct i2c_device_id *i2c_id)
 {
@@ -285,6 +300,7 @@ static int act8865_pmic_probe(struct i2c_client *client,
        int i, ret, num_regulators;
        struct act8865 *act8865;
        unsigned long type;
+       int off_reg, off_mask;
 
        pdata = dev_get_platdata(dev);
 
@@ -304,10 +320,14 @@ static int act8865_pmic_probe(struct i2c_client *client,
        case ACT8846:
                regulators = act8846_regulators;
                num_regulators = ARRAY_SIZE(act8846_regulators);
+               off_reg = ACT8846_GLB_OFF_CTRL;
+               off_mask = ACT8846_OFF_SYSMASK;
                break;
        case ACT8865:
                regulators = act8865_regulators;
                num_regulators = ARRAY_SIZE(act8865_regulators);
+               off_reg = ACT8865_SYS_CTRL;
+               off_mask = ACT8865_MSTROFF;
                break;
        default:
                dev_err(dev, "invalid device id %lu\n", type);
@@ -345,6 +365,17 @@ static int act8865_pmic_probe(struct i2c_client *client,
                return ret;
        }
 
+       if (of_device_is_system_power_controller(dev->of_node)) {
+               if (!pm_power_off) {
+                       act8865_i2c_client = client;
+                       act8865->off_reg = off_reg;
+                       act8865->off_mask = off_mask;
+                       pm_power_off = act8865_power_off;
+               } else {
+                       dev_err(dev, "Failed to set poweroff capability, already defined\n");
+               }
+       }
+
        /* Finally register devices */
        for (i = 0; i < num_regulators; i++) {
                const struct regulator_desc *desc = &regulators[i];
index 4f730af70e7c8b650bc7ef144f7c147e523b5eea..3586571814b2826c6e12d1292ef285f909deb79d 100644 (file)
@@ -189,17 +189,18 @@ static int anatop_regulator_probe(struct platform_device *pdev)
        int ret = 0;
        u32 val;
 
-       initdata = of_get_regulator_init_data(dev, np);
        sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
        if (!sreg)
                return -ENOMEM;
-       sreg->initdata = initdata;
        sreg->name = of_get_property(np, "regulator-name", NULL);
        rdesc = &sreg->rdesc;
        rdesc->name = sreg->name;
        rdesc->type = REGULATOR_VOLTAGE;
        rdesc->owner = THIS_MODULE;
 
+       initdata = of_get_regulator_init_data(dev, np, rdesc);
+       sreg->initdata = initdata;
+
        anatop_np = of_get_parent(np);
        if (!anatop_np)
                return -ENODEV;
@@ -283,6 +284,19 @@ static int anatop_regulator_probe(struct platform_device *pdev)
                        sreg->sel = 0;
                        sreg->bypass = true;
                }
+
+               /*
+                * In case vddpu was disabled by the bootloader, we need to set
+                * a sane default until imx6-cpufreq was probed and changes the
+                * voltage to the correct value. In this case we set 1.25V.
+                */
+               if (!sreg->sel && !strcmp(sreg->name, "vddpu"))
+                       sreg->sel = 22;
+
+               if (!sreg->sel) {
+                       dev_err(&pdev->dev, "Failed to read a valid default voltage selector.\n");
+                       return -EINVAL;
+               }
        } else {
                rdesc->ops = &anatop_rops;
        }
index 4c9db589f6c138ff0ce4c63607c353e7360946ea..d071b2119a60b3af7d44bd4fedb688f23c12503f 100644 (file)
@@ -179,7 +179,8 @@ static const struct regulator_init_data arizona_ldo1_default = {
 };
 
 static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
-                                    struct regulator_config *config)
+                                    struct regulator_config *config,
+                                    const struct regulator_desc *desc)
 {
        struct arizona_pdata *pdata = &arizona->pdata;
        struct arizona_ldo1 *ldo1 = config->driver_data;
@@ -194,7 +195,8 @@ static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
        if (init_node) {
                config->of_node = init_node;
 
-               init_data = of_get_regulator_init_data(arizona->dev, init_node);
+               init_data = of_get_regulator_init_data(arizona->dev, init_node,
+                                                      desc);
 
                if (init_data) {
                        init_data->consumer_supplies = &ldo1->supply;
@@ -257,9 +259,11 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
 
        if (IS_ENABLED(CONFIG_OF)) {
                if (!dev_get_platdata(arizona->dev)) {
-                       ret = arizona_ldo1_of_get_pdata(arizona, &config);
+                       ret = arizona_ldo1_of_get_pdata(arizona, &config, desc);
                        if (ret < 0)
                                return ret;
+
+                       config.ena_gpio_initialized = true;
                }
        }
 
index ce9aca5f8ee73b5c114b28f41a464d9279c191b9..c313ef4c3a2f885b0a894f4c50e0204f691cf66c 100644 (file)
@@ -198,7 +198,8 @@ static const struct regulator_init_data arizona_micsupp_ext_default = {
 };
 
 static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
-                                       struct regulator_config *config)
+                                       struct regulator_config *config,
+                                       const struct regulator_desc *desc)
 {
        struct arizona_pdata *pdata = &arizona->pdata;
        struct arizona_micsupp *micsupp = config->driver_data;
@@ -210,7 +211,7 @@ static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
        if (np) {
                config->of_node = np;
 
-               init_data = of_get_regulator_init_data(arizona->dev, np);
+               init_data = of_get_regulator_init_data(arizona->dev, np, desc);
 
                if (init_data) {
                        init_data->consumer_supplies = &micsupp->supply;
@@ -264,7 +265,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
 
        if (IS_ENABLED(CONFIG_OF)) {
                if (!dev_get_platdata(arizona->dev)) {
-                       ret = arizona_micsupp_of_get_pdata(arizona, &config);
+                       ret = arizona_micsupp_of_get_pdata(arizona, &config,
+                                                          desc);
                        if (ret < 0)
                                return ret;
                }
index cd87c0c37034de32ad2f2c7ae2085d4761041761..e225711bb8bc0009114d6ec0d95ab8d2bb2d68f3 100644 (file)
@@ -828,7 +828,7 @@ static void print_constraints(struct regulator_dev *rdev)
        if (!count)
                sprintf(buf, "no parameters");
 
-       rdev_info(rdev, "%s\n", buf);
+       rdev_dbg(rdev, "%s\n", buf);
 
        if ((constraints->min_uV != constraints->max_uV) &&
            !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE))
@@ -1713,6 +1713,8 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)
                                gpiod_put(pin->gpiod);
                                list_del(&pin->list);
                                kfree(pin);
+                               rdev->ena_pin = NULL;
+                               return;
                        } else {
                                pin->request_count--;
                        }
@@ -1976,9 +1978,18 @@ static int _regulator_disable(struct regulator_dev *rdev)
 
                /* we are last user */
                if (_regulator_can_change_status(rdev)) {
+                       ret = _notifier_call_chain(rdev,
+                                                  REGULATOR_EVENT_PRE_DISABLE,
+                                                  NULL);
+                       if (ret & NOTIFY_STOP_MASK)
+                               return -EINVAL;
+
                        ret = _regulator_do_disable(rdev);
                        if (ret < 0) {
                                rdev_err(rdev, "failed to disable\n");
+                               _notifier_call_chain(rdev,
+                                               REGULATOR_EVENT_ABORT_DISABLE,
+                                               NULL);
                                return ret;
                        }
                        _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
@@ -2035,9 +2046,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
 
+       ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
+                       REGULATOR_EVENT_PRE_DISABLE, NULL);
+       if (ret & NOTIFY_STOP_MASK)
+               return -EINVAL;
+
        ret = _regulator_do_disable(rdev);
        if (ret < 0) {
                rdev_err(rdev, "failed to force disable\n");
+               _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
+                               REGULATOR_EVENT_ABORT_DISABLE, NULL);
                return ret;
        }
 
@@ -3650,7 +3668,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
 
        dev_set_drvdata(&rdev->dev, rdev);
 
-       if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
+       if ((config->ena_gpio || config->ena_gpio_initialized) &&
+           gpio_is_valid(config->ena_gpio)) {
                ret = regulator_ena_gpio_request(rdev, config);
                if (ret != 0) {
                        rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
index 00033625a09ce3c601833ec6f7f6b8a0e723956a..3945f1006d23c17f236fd334c3627be8db3d9bfc 100644 (file)
@@ -436,7 +436,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)
                        if (!of_node_cmp(np->name,
                                         regulator->info->reg_desc.name)) {
                                config.init_data = of_get_regulator_init_data(
-                                       &pdev->dev, np);
+                                       &pdev->dev, np,
+                                       &regulator->info->reg_desc);
                                config.of_node = np;
                                break;
                        }
index 7c9461d13313ea1c4d1ddd86d3cf7e6ac783b7ee..37dd42759ca9e55f3305797bd5681ac7155b627a 100644 (file)
@@ -867,17 +867,14 @@ static int da9063_regulator_probe(struct platform_device *pdev)
                return irq;
        }
 
-       regulators->irq_ldo_lim = regmap_irq_get_virq(da9063->regmap_irq, irq);
-       if (regulators->irq_ldo_lim >= 0) {
-               ret = request_threaded_irq(regulators->irq_ldo_lim,
-                                          NULL, da9063_ldo_lim_event,
-                                          IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-                                          "LDO_LIM", regulators);
-               if (ret) {
-                       dev_err(&pdev->dev,
-                                       "Failed to request LDO_LIM IRQ.\n");
-                       regulators->irq_ldo_lim = -ENXIO;
-               }
+       ret = request_threaded_irq(irq,
+                               NULL, da9063_ldo_lim_event,
+                               IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+                               "LDO_LIM", regulators);
+       if (ret) {
+               dev_err(&pdev->dev,
+                               "Failed to request LDO_LIM IRQ.\n");
+               regulators->irq_ldo_lim = -ENXIO;
        }
 
        return 0;
index 7a320dd11c46220bfff3869510f1abcd7903ae2d..bc6100103f7f476e7381482a404f33ea01851fad 100644 (file)
@@ -147,7 +147,7 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
 
        config.dev = &i2c->dev;
        config.init_data = pdata ? &pdata->da9210_constraints :
-               of_get_regulator_init_data(dev, dev->of_node);
+               of_get_regulator_init_data(dev, dev->of_node, &da9210_reg);
        config.driver_data = chip;
        config.regmap = chip->regmap;
        config.of_node = dev->of_node;
index 2436db9e2ca35f60875ab56cc825050c0d6a3ff2..7aef9e4c6fbf60d47bf7812918d48042c6045637 100644 (file)
@@ -33,7 +33,7 @@ static struct regulator_init_data dummy_initdata = {
 
 static struct regulator_ops dummy_ops;
 
-static struct regulator_desc dummy_desc = {
+static const struct regulator_desc dummy_desc = {
        .name = "regulator-dummy",
        .id = -1,
        .type = REGULATOR_VOLTAGE,
index f8e4257aef923d16f32f969e3e74e2e1fb55c6ff..6c43ab2d51211653eb1dd2374ff7844f6ff1c634 100644 (file)
@@ -302,7 +302,8 @@ static struct regmap_config fan53555_regmap_config = {
 };
 
 static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
-                                                       struct device_node *np)
+                                             struct device_node *np,
+                                             const struct regulator_desc *desc)
 {
        struct fan53555_platform_data *pdata;
        int ret;
@@ -312,7 +313,7 @@ static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
        if (!pdata)
                return NULL;
 
-       pdata->regulator = of_get_regulator_init_data(dev, np);
+       pdata->regulator = of_get_regulator_init_data(dev, np, desc);
 
        ret = of_property_read_u32(np, "fcs,suspend-voltage-selector",
                                   &tmp);
@@ -347,20 +348,20 @@ static int fan53555_regulator_probe(struct i2c_client *client,
        unsigned int val;
        int ret;
 
+       di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
+                                       GFP_KERNEL);
+       if (!di)
+               return -ENOMEM;
+
        pdata = dev_get_platdata(&client->dev);
        if (!pdata)
-               pdata = fan53555_parse_dt(&client->dev, np);
+               pdata = fan53555_parse_dt(&client->dev, np, &di->desc);
 
        if (!pdata || !pdata->regulator) {
                dev_err(&client->dev, "Platform data not found!\n");
                return -ENODEV;
        }
 
-       di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
-                                       GFP_KERNEL);
-       if (!di)
-               return -ENOMEM;
-
        di->regulator = pdata->regulator;
        if (client->dev.of_node) {
                const struct of_device_id *match;
index 354105eff1f80ed392951b41518e3062eac70582..d21da27c0eb6893c7c3c4877cd65b79ce8ad29b2 100644 (file)
@@ -40,13 +40,15 @@ struct fixed_voltage_data {
 /**
  * of_get_fixed_voltage_config - extract fixed_voltage_config structure info
  * @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
  *
  * Populates fixed_voltage_config structure by extracting data from device
  * tree node, returns a pointer to the populated structure of NULL if memory
  * alloc fails.
  */
 static struct fixed_voltage_config *
-of_get_fixed_voltage_config(struct device *dev)
+of_get_fixed_voltage_config(struct device *dev,
+                           const struct regulator_desc *desc)
 {
        struct fixed_voltage_config *config;
        struct device_node *np = dev->of_node;
@@ -57,7 +59,7 @@ of_get_fixed_voltage_config(struct device *dev)
        if (!config)
                return ERR_PTR(-ENOMEM);
 
-       config->init_data = of_get_regulator_init_data(dev, dev->of_node);
+       config->init_data = of_get_regulator_init_data(dev, dev->of_node, desc);
        if (!config->init_data)
                return ERR_PTR(-EINVAL);
 
@@ -112,8 +114,14 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        struct regulator_config cfg = { };
        int ret;
 
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
+                              GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
        if (pdev->dev.of_node) {
-               config = of_get_fixed_voltage_config(&pdev->dev);
+               config = of_get_fixed_voltage_config(&pdev->dev,
+                                                    &drvdata->desc);
                if (IS_ERR(config))
                        return PTR_ERR(config);
        } else {
@@ -123,11 +131,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        if (!config)
                return -ENOMEM;
 
-       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
-                              GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
        drvdata->desc.name = devm_kstrdup(&pdev->dev,
                                          config->supply_name,
                                          GFP_KERNEL);
@@ -157,8 +160,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 
        drvdata->desc.fixed_uV = config->microvolts;
 
-       if (config->gpio >= 0)
+       if (gpio_is_valid(config->gpio)) {
                cfg.ena_gpio = config->gpio;
+               if (pdev->dev.of_node)
+                       cfg.ena_gpio_initialized = true;
+       }
        cfg.ena_gpio_invert = !config->enable_high;
        if (config->enabled_at_boot) {
                if (config->enable_high)
index 989b23b377c0d2bb511227749e871ce72f46398b..c888a9a9482c938b705d3eae12e739dc0e44d4fa 100644 (file)
@@ -133,7 +133,8 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
 };
 
 static struct gpio_regulator_config *
-of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
+                            const struct regulator_desc *desc)
 {
        struct gpio_regulator_config *config;
        const char *regtype;
@@ -146,7 +147,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
        if (!config)
                return ERR_PTR(-ENOMEM);
 
-       config->init_data = of_get_regulator_init_data(dev, np);
+       config->init_data = of_get_regulator_init_data(dev, np, desc);
        if (!config->init_data)
                return ERR_PTR(-EINVAL);
 
@@ -162,34 +163,41 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
 
        config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
 
-       /* Fetch GPIOs. */
-       config->nr_gpios = of_gpio_count(np);
-
-       config->gpios = devm_kzalloc(dev,
-                               sizeof(struct gpio) * config->nr_gpios,
-                               GFP_KERNEL);
-       if (!config->gpios)
-               return ERR_PTR(-ENOMEM);
-
-       proplen = of_property_count_u32_elems(np, "gpios-states");
-       /* optional property */
-       if (proplen < 0)
-               proplen = 0;
-
-       if (proplen > 0 && proplen != config->nr_gpios) {
-               dev_warn(dev, "gpios <-> gpios-states mismatch\n");
-               proplen = 0;
-       }
+       /* Fetch GPIOs. - optional property*/
+       ret = of_gpio_count(np);
+       if ((ret < 0) && (ret != -ENOENT))
+               return ERR_PTR(ret);
+
+       if (ret > 0) {
+               config->nr_gpios = ret;
+               config->gpios = devm_kzalloc(dev,
+                                       sizeof(struct gpio) * config->nr_gpios,
+                                       GFP_KERNEL);
+               if (!config->gpios)
+                       return ERR_PTR(-ENOMEM);
+
+               proplen = of_property_count_u32_elems(np, "gpios-states");
+               /* optional property */
+               if (proplen < 0)
+                       proplen = 0;
+
+               if (proplen > 0 && proplen != config->nr_gpios) {
+                       dev_warn(dev, "gpios <-> gpios-states mismatch\n");
+                       proplen = 0;
+               }
 
-       for (i = 0; i < config->nr_gpios; i++) {
-               gpio = of_get_named_gpio(np, "gpios", i);
-               if (gpio < 0)
-                       break;
-               config->gpios[i].gpio = gpio;
-               if (proplen > 0) {
-                       of_property_read_u32_index(np, "gpios-states", i, &ret);
-                       if (ret)
-                               config->gpios[i].flags = GPIOF_OUT_INIT_HIGH;
+               for (i = 0; i < config->nr_gpios; i++) {
+                       gpio = of_get_named_gpio(np, "gpios", i);
+                       if (gpio < 0)
+                               break;
+                       config->gpios[i].gpio = gpio;
+                       if (proplen > 0) {
+                               of_property_read_u32_index(np, "gpios-states",
+                                                          i, &ret);
+                               if (ret)
+                                       config->gpios[i].flags =
+                                                          GPIOF_OUT_INIT_HIGH;
+                       }
                }
        }
 
@@ -243,17 +251,18 @@ static int gpio_regulator_probe(struct platform_device *pdev)
        struct regulator_config cfg = { };
        int ptr, ret, state;
 
-       if (np) {
-               config = of_get_gpio_regulator_config(&pdev->dev, np);
-               if (IS_ERR(config))
-                       return PTR_ERR(config);
-       }
-
        drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
                               GFP_KERNEL);
        if (drvdata == NULL)
                return -ENOMEM;
 
+       if (np) {
+               config = of_get_gpio_regulator_config(&pdev->dev, np,
+                                                     &drvdata->desc);
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       }
+
        drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
        if (drvdata->desc.name == NULL) {
                dev_err(&pdev->dev, "Failed to allocate supply name\n");
@@ -261,13 +270,23 @@ static int gpio_regulator_probe(struct platform_device *pdev)
                goto err;
        }
 
-       drvdata->gpios = kmemdup(config->gpios,
-                                config->nr_gpios * sizeof(struct gpio),
-                                GFP_KERNEL);
-       if (drvdata->gpios == NULL) {
-               dev_err(&pdev->dev, "Failed to allocate gpio data\n");
-               ret = -ENOMEM;
-               goto err_name;
+       if (config->nr_gpios != 0) {
+               drvdata->gpios = kmemdup(config->gpios,
+                                        config->nr_gpios * sizeof(struct gpio),
+                                        GFP_KERNEL);
+               if (drvdata->gpios == NULL) {
+                       dev_err(&pdev->dev, "Failed to allocate gpio data\n");
+                       ret = -ENOMEM;
+                       goto err_name;
+               }
+
+               drvdata->nr_gpios = config->nr_gpios;
+               ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                       "Could not obtain regulator setting GPIOs: %d\n", ret);
+                       goto err_memstate;
+               }
        }
 
        drvdata->states = kmemdup(config->states,
@@ -301,14 +320,6 @@ static int gpio_regulator_probe(struct platform_device *pdev)
                goto err_memgpio;
        }
 
-       drvdata->nr_gpios = config->nr_gpios;
-       ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
-       if (ret) {
-               dev_err(&pdev->dev,
-                  "Could not obtain regulator setting GPIOs: %d\n", ret);
-               goto err_memstate;
-       }
-
        /* build initial state from gpio init data. */
        state = 0;
        for (ptr = 0; ptr < drvdata->nr_gpios; ptr++) {
@@ -322,8 +333,10 @@ static int gpio_regulator_probe(struct platform_device *pdev)
        cfg.driver_data = drvdata;
        cfg.of_node = np;
 
-       if (config->enable_gpio >= 0)
+       if (gpio_is_valid(config->enable_gpio)) {
                cfg.ena_gpio = config->enable_gpio;
+               cfg.ena_gpio_initialized = true;
+       }
        cfg.ena_gpio_invert = !config->enable_high;
        if (config->enabled_at_boot) {
                if (config->enable_high)
index 86db310d5304ad00dadcd605c6f9a9deb63a652c..d2a8c64cae42a9bc83890e922b7971781347ee62 100644 (file)
@@ -163,7 +163,7 @@ static int of_get_max1586_platform_data(struct device *dev,
                                 struct max1586_platform_data *pdata)
 {
        struct max1586_subdev_data *sub;
-       struct of_regulator_match rmatch[ARRAY_SIZE(max1586_reg)];
+       struct of_regulator_match rmatch[ARRAY_SIZE(max1586_reg)] = { };
        struct device_node *np = dev->of_node;
        int i, matched;
 
index ef1af2debbd293af555cbcde4ed5c72d866ad47a..871b96bcd2d0cfb16b0173c2222ffae63859207c 100644 (file)
 #define MAX77686_DVS_MINUV     600000
 #define MAX77686_DVS_UVSTEP    12500
 
+/*
+ * Values used for configuring LDOs and bucks.
+ * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26
+ */
+#define MAX77686_LDO_LOWPOWER          0x1
+/*
+ * On/off controlled by PWRREQ:
+ *  - LDO2, 6-8, 10-12, 14-16
+ *  - buck[1234]
+ */
+#define MAX77686_OFF_PWRREQ            0x1
+/* Low power mode controlled by PWRREQ: All LDOs */
+#define MAX77686_LDO_LOWPOWER_PWRREQ   0x2
+/* Forcing low power mode: buck[234] */
+#define MAX77686_BUCK_LOWPOWER         0x2
+#define MAX77686_NORMAL                        0x3
+
 #define MAX77686_OPMODE_SHIFT  6
 #define MAX77686_OPMODE_BUCK234_SHIFT  4
 #define MAX77686_OPMODE_MASK   0x3
@@ -65,23 +82,36 @@ enum max77686_ramp_rate {
 };
 
 struct max77686_data {
+       /* Array indexed by regulator id */
        unsigned int opmode[MAX77686_REGULATORS];
 };
 
-/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
-static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
+static unsigned int max77686_get_opmode_shift(int id)
 {
-       unsigned int val;
+       switch (id) {
+       case MAX77686_BUCK1:
+       case MAX77686_BUCK5 ... MAX77686_BUCK9:
+               return 0;
+       case MAX77686_BUCK2 ... MAX77686_BUCK4:
+               return MAX77686_OPMODE_BUCK234_SHIFT;
+       default:
+               /* all LDOs */
+               return MAX77686_OPMODE_SHIFT;
+       }
+}
+
+/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */
+static int max77686_set_suspend_disable(struct regulator_dev *rdev)
+{
+       unsigned int val, shift;
        struct max77686_data *max77686 = rdev_get_drvdata(rdev);
        int ret, id = rdev_get_id(rdev);
 
-       if (id == MAX77686_BUCK1)
-               val = 0x1;
-       else
-               val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
+       shift = max77686_get_opmode_shift(id);
+       val = MAX77686_OFF_PWRREQ;
 
        ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                rdev->desc->enable_mask, val);
+                                rdev->desc->enable_mask, val << shift);
        if (ret)
                return ret;
 
@@ -103,10 +133,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev,
 
        switch (mode) {
        case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
-               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               val = MAX77686_LDO_LOWPOWER_PWRREQ;
                break;
        case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
-               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               val = MAX77686_NORMAL;
                break;
        default:
                pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
@@ -115,7 +145,8 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev,
        }
 
        ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask, val);
+                                 rdev->desc->enable_mask,
+                                 val << MAX77686_OPMODE_SHIFT);
        if (ret)
                return ret;
 
@@ -133,13 +164,13 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
 
        switch (mode) {
        case REGULATOR_MODE_STANDBY:                    /* switch off */
-               val = 0x1 << MAX77686_OPMODE_SHIFT;
+               val = MAX77686_OFF_PWRREQ;
                break;
        case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
-               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               val = MAX77686_LDO_LOWPOWER_PWRREQ;
                break;
        case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
-               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               val = MAX77686_NORMAL;
                break;
        default:
                pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
@@ -148,7 +179,8 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
        }
 
        ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                rdev->desc->enable_mask, val);
+                                rdev->desc->enable_mask,
+                                val << MAX77686_OPMODE_SHIFT);
        if (ret)
                return ret;
 
@@ -159,10 +191,17 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
 static int max77686_enable(struct regulator_dev *rdev)
 {
        struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       unsigned int shift;
+       int id = rdev_get_id(rdev);
+
+       shift = max77686_get_opmode_shift(id);
+
+       if (max77686->opmode[id] == MAX77686_OFF_PWRREQ)
+               max77686->opmode[id] = MAX77686_NORMAL;
 
        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
                                  rdev->desc->enable_mask,
-                                 max77686->opmode[rdev_get_id(rdev)]);
+                                 max77686->opmode[id] << shift);
 }
 
 static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
@@ -212,6 +251,7 @@ static struct regulator_ops max77686_ldo_ops = {
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_suspend_mode       = max77686_ldo_set_suspend_mode,
+       .set_suspend_disable    = max77686_set_suspend_disable,
 };
 
 static struct regulator_ops max77686_buck1_ops = {
@@ -223,7 +263,7 @@ static struct regulator_ops max77686_buck1_ops = {
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_disable    = max77686_buck_set_suspend_disable,
+       .set_suspend_disable    = max77686_set_suspend_disable,
 };
 
 static struct regulator_ops max77686_buck_dvs_ops = {
@@ -236,11 +276,13 @@ static struct regulator_ops max77686_buck_dvs_ops = {
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_ramp_delay         = max77686_set_ramp_delay,
-       .set_suspend_disable    = max77686_buck_set_suspend_disable,
+       .set_suspend_disable    = max77686_set_suspend_disable,
 };
 
 #define regulator_desc_ldo(num)                {                               \
        .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
        .id             = MAX77686_LDO##num,                            \
        .ops            = &max77686_ops,                                \
        .type           = REGULATOR_VOLTAGE,                            \
@@ -257,6 +299,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 #define regulator_desc_lpm_ldo(num)    {                               \
        .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
        .id             = MAX77686_LDO##num,                            \
        .ops            = &max77686_ldo_ops,                            \
        .type           = REGULATOR_VOLTAGE,                            \
@@ -273,6 +317,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 #define regulator_desc_ldo_low(num)            {                       \
        .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
        .id             = MAX77686_LDO##num,                            \
        .ops            = &max77686_ldo_ops,                            \
        .type           = REGULATOR_VOLTAGE,                            \
@@ -289,6 +335,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 #define regulator_desc_ldo1_low(num)           {                       \
        .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
        .id             = MAX77686_LDO##num,                            \
        .ops            = &max77686_ops,                                \
        .type           = REGULATOR_VOLTAGE,                            \
@@ -305,6 +353,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 #define regulator_desc_buck(num)               {                       \
        .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
        .id             = MAX77686_BUCK##num,                           \
        .ops            = &max77686_ops,                                \
        .type           = REGULATOR_VOLTAGE,                            \
@@ -320,6 +370,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 #define regulator_desc_buck1(num)              {                       \
        .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
        .id             = MAX77686_BUCK##num,                           \
        .ops            = &max77686_buck1_ops,                          \
        .type           = REGULATOR_VOLTAGE,                            \
@@ -335,6 +387,8 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 #define regulator_desc_buck_dvs(num)           {                       \
        .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
        .id             = MAX77686_BUCK##num,                           \
        .ops            = &max77686_buck_dvs_ops,                       \
        .type           = REGULATOR_VOLTAGE,                            \
@@ -350,7 +404,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
                        << MAX77686_OPMODE_BUCK234_SHIFT,               \
 }
 
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
        regulator_desc_ldo1_low(1),
        regulator_desc_ldo_low(2),
        regulator_desc_ldo(3),
@@ -388,103 +442,37 @@ static struct regulator_desc regulators[] = {
        regulator_desc_buck(9),
 };
 
-#ifdef CONFIG_OF
-static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
-                                       struct max77686_platform_data *pdata)
-{
-       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct device_node *pmic_np, *regulators_np;
-       struct max77686_regulator_data *rdata;
-       struct of_regulator_match rmatch;
-       unsigned int i;
-
-       pmic_np = iodev->dev->of_node;
-       regulators_np = of_get_child_by_name(pmic_np, "voltage-regulators");
-       if (!regulators_np) {
-               dev_err(&pdev->dev, "could not find regulators sub-node\n");
-               return -EINVAL;
-       }
-
-       pdata->num_regulators = ARRAY_SIZE(regulators);
-       rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
-                            pdata->num_regulators, GFP_KERNEL);
-       if (!rdata) {
-               of_node_put(regulators_np);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < pdata->num_regulators; i++) {
-               rmatch.name = regulators[i].name;
-               rmatch.init_data = NULL;
-               rmatch.of_node = NULL;
-               of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1);
-               rdata[i].initdata = rmatch.init_data;
-               rdata[i].of_node = rmatch.of_node;
-       }
-
-       pdata->regulators = rdata;
-       of_node_put(regulators_np);
-
-       return 0;
-}
-#else
-static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
-                                       struct max77686_platform_data *pdata)
-{
-       return 0;
-}
-#endif /* CONFIG_OF */
-
 static int max77686_pmic_probe(struct platform_device *pdev)
 {
        struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
        struct max77686_data *max77686;
-       int i, ret = 0;
+       int i;
        struct regulator_config config = { };
 
        dev_dbg(&pdev->dev, "%s\n", __func__);
 
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data found for regulator\n");
-               return -ENODEV;
-       }
-
-       if (iodev->dev->of_node) {
-               ret = max77686_pmic_dt_parse_pdata(pdev, pdata);
-               if (ret)
-                       return ret;
-       }
-
-       if (pdata->num_regulators != MAX77686_REGULATORS) {
-               dev_err(&pdev->dev,
-                       "Invalid initial data for regulator's initialiation\n");
-               return -EINVAL;
-       }
-
        max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
                                GFP_KERNEL);
        if (!max77686)
                return -ENOMEM;
 
-       config.dev = &pdev->dev;
+       config.dev = iodev->dev;
        config.regmap = iodev->regmap;
        config.driver_data = max77686;
        platform_set_drvdata(pdev, max77686);
 
        for (i = 0; i < MAX77686_REGULATORS; i++) {
                struct regulator_dev *rdev;
+               int id = regulators[i].id;
 
-               config.init_data = pdata->regulators[i].initdata;
-               config.of_node = pdata->regulators[i].of_node;
-
-               max77686->opmode[i] = regulators[i].enable_mask;
+               max77686->opmode[id] = MAX77686_NORMAL;
                rdev = devm_regulator_register(&pdev->dev,
                                                &regulators[i], &config);
                if (IS_ERR(rdev)) {
+                       int ret = PTR_ERR(rdev);
                        dev_err(&pdev->dev,
-                               "regulator init failed for %d\n", i);
-                       return PTR_ERR(rdev);
+                               "regulator init failed for %d: %d\n", i, ret);
+                       return ret;
                }
        }
 
index c67ff05fc1dd1354cd0a72601f31b407f99638ad..7b9755a6c3b57b077e7f56f2a396d105450388e9 100644 (file)
@@ -139,7 +139,7 @@ static struct regulator_ops max77693_charger_ops = {
        .enable_mask    = SAFEOUT_CTRL_ENSAFEOUT##_num##_MASK , \
 }
 
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
        regulator_desc_esafeout(1),
        regulator_desc_esafeout(2),
        {
@@ -227,7 +227,7 @@ static int max77693_pmic_probe(struct platform_device *pdev)
        struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max77693_regulator_data *rdata = NULL;
        int num_rdata, i;
-       struct regulator_config config;
+       struct regulator_config config = { };
 
        num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
        if (!rdata || num_rdata <= 0) {
index d89792b084e937a9fd29bbc28defe65ab6c07959..0766615c60bccf547cd162248a39dc3771fa3e32 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/regulator/of_regulator.h>
 #include <linux/mfd/max77686.h>
 #include <linux/mfd/max77686-private.h>
+#include <dt-bindings/regulator/maxim,max77802.h>
 
 /* Default ramp delay in case it is not manually set */
 #define MAX77802_RAMP_DELAY            100000          /* uV/us */
 #define MAX77802_RAMP_RATE_MASK_4BIT   0xF0
 #define MAX77802_RAMP_RATE_SHIFT_4BIT  4
 
+#define MAX77802_STATUS_OFF            0x0
+#define MAX77802_OFF_PWRREQ            0x1
+#define MAX77802_LP_PWRREQ             0x2
+
 /* MAX77802 has two register formats: 2-bit and 4-bit */
 static const unsigned int ramp_table_77802_2bit[] = {
        12500,
@@ -65,9 +70,16 @@ static unsigned int ramp_table_77802_4bit[] = {
 };
 
 struct max77802_regulator_prv {
+       /* Array indexed by regulator id */
        unsigned int opmode[MAX77802_REG_MAX];
 };
 
+static inline unsigned int max77802_map_mode(unsigned int mode)
+{
+       return mode == MAX77802_OPMODE_NORMAL ?
+               REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY;
+}
+
 static int max77802_get_opmode_shift(int id)
 {
        if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 &&
@@ -83,17 +95,16 @@ static int max77802_get_opmode_shift(int id)
        return -EINVAL;
 }
 
-/*
- * Some BUCKS supports Normal[ON/OFF] mode during suspend
+/**
+ * max77802_set_suspend_disable - Disable the regulator during system suspend
+ * @rdev: regulator to mark as disabled
  *
- * BUCK 1, 6, 2-4, 5, 7-10 (all)
- *
- * The other mode (0x02) will make PWRREQ switch between normal
- * and low power.
+ * All regulators expect LDO 1, 3, 20 and 21 support OFF by PWRREQ.
+ * Configure the regulator so the PMIC will turn it OFF during system suspend.
  */
-static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev)
+static int max77802_set_suspend_disable(struct regulator_dev *rdev)
 {
-       unsigned int val = MAX77802_OPMODE_STANDBY;
+       unsigned int val = MAX77802_OFF_PWRREQ;
        struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
        int id = rdev_get_id(rdev);
        int shift = max77802_get_opmode_shift(id);
@@ -104,14 +115,11 @@ static int max77802_buck_set_suspend_disable(struct regulator_dev *rdev)
 }
 
 /*
- * Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state
- * (Enable Control Logic1 by PWRREQ)
- *
- * LDOs 2, 4-19, 22-35.
+ * Some LDOs support Low Power Mode while the system is running.
  *
+ * LDOs 1, 3, 20, 21.
  */
-static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
-                                               unsigned int mode)
+static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
        int id = rdev_get_id(rdev);
@@ -119,14 +127,11 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
        int shift = max77802_get_opmode_shift(id);
 
        switch (mode) {
-       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
-               val = MAX77802_OPMODE_LP;
+       case REGULATOR_MODE_STANDBY:
+               val = MAX77802_OPMODE_LP;       /* ON in Low Power Mode */
                break;
-       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
-               val = MAX77802_OPMODE_NORMAL;
-               break;
-       case REGULATOR_MODE_STANDBY:                    /* ON/OFF by PWRREQ */
-               val = MAX77802_OPMODE_STANDBY;
+       case REGULATOR_MODE_NORMAL:
+               val = MAX77802_OPMODE_NORMAL;   /* ON in Normal Mode */
                break;
        default:
                dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
@@ -139,35 +144,76 @@ static int max77802_ldo_set_suspend_mode_logic1(struct regulator_dev *rdev,
                                  rdev->desc->enable_mask, val << shift);
 }
 
-/*
- * Mode 1 (Output[ON/OFF] by PWRREQ) is not supported on some LDOs
- * (Enable Control Logic2 by PWRREQ)
+static unsigned max77802_get_mode(struct regulator_dev *rdev)
+{
+       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+
+       return max77802_map_mode(max77802->opmode[id]);
+}
+
+/**
+ * max77802_set_suspend_mode - set regulator opmode when the system is suspended
+ * @rdev: regulator to change mode
+ * @mode: operating mode to be set
  *
- * LDOs 1, 20, 21, and 3,
+ * Will set the operating mode for the regulators during system suspend.
+ * This function is valid for the three different enable control logics:
  *
+ * Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35)
+ * Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21)
+ * Enable Control Logic3 by PWRREQ (LDO 3)
+ *
+ * If setting the regulator mode fails, the function only warns but does
+ * not return an error code to avoid the regulator core to stop setting
+ * the operating mode for the remaining regulators.
  */
-static int max77802_ldo_set_suspend_mode_logic2(struct regulator_dev *rdev,
-                                               unsigned int mode)
+static int max77802_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
 {
        struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
        int id = rdev_get_id(rdev);
        unsigned int val;
        int shift = max77802_get_opmode_shift(id);
 
+       /*
+        * If the regulator has been disabled for suspend
+        * then is invalid to try setting a suspend mode.
+        */
+       if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) {
+               dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n",
+                        rdev->desc->name, mode);
+               return 0;
+       }
+
        switch (mode) {
-       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
-               val = MAX77802_OPMODE_LP;
-               break;
-       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
-               val = MAX77802_OPMODE_NORMAL;
+       case REGULATOR_MODE_STANDBY:
+               /*
+                * If the regulator opmode is normal then enable
+                * ON in Low Power Mode by PWRREQ. If the mode is
+                * already Low Power then no action is required.
+                */
+               if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL)
+                       val = MAX77802_LP_PWRREQ;
+               else
+                       return 0;
                break;
+       case REGULATOR_MODE_NORMAL:
+               /*
+                * If the regulator operating mode is Low Power then
+                * normal is not a valid opmode in suspend. If the
+                * mode is already normal then no action is required.
+                */
+               if (max77802->opmode[id] == MAX77802_OPMODE_LP)
+                       dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n",
+                                rdev->desc->name, mode);
+               return 0;
        default:
                dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
                         rdev->desc->name, mode);
                return -EINVAL;
        }
 
-       max77802->opmode[id] = val;
        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
                                  rdev->desc->enable_mask, val << shift);
 }
@@ -178,6 +224,9 @@ static int max77802_enable(struct regulator_dev *rdev)
        int id = rdev_get_id(rdev);
        int shift = max77802_get_opmode_shift(id);
 
+       if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
+               max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
+
        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
                                  rdev->desc->enable_mask,
                                  max77802->opmode[id] << shift);
@@ -247,7 +296,8 @@ static struct regulator_ops max77802_ldo_ops_logic1 = {
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_mode       = max77802_ldo_set_suspend_mode_logic1,
+       .set_suspend_disable    = max77802_set_suspend_disable,
+       .set_suspend_mode       = max77802_set_suspend_mode,
 };
 
 /*
@@ -262,7 +312,9 @@ static struct regulator_ops max77802_ldo_ops_logic2 = {
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_mode       = max77802_ldo_set_suspend_mode_logic2,
+       .set_mode               = max77802_set_mode,
+       .get_mode               = max77802_get_mode,
+       .set_suspend_mode       = max77802_set_suspend_mode,
 };
 
 /* BUCKS 1, 6 */
@@ -276,10 +328,25 @@ static struct regulator_ops max77802_buck_16_dvs_ops = {
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_ramp_delay         = max77802_set_ramp_delay_4bit,
-       .set_suspend_disable    = max77802_buck_set_suspend_disable,
+       .set_suspend_disable    = max77802_set_suspend_disable,
 };
 
-/* BUCKs 2-4, 5, 7-10 */
+/* BUCKs 2-4 */
+static struct regulator_ops max77802_buck_234_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77802_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = max77802_set_ramp_delay_2bit,
+       .set_suspend_disable    = max77802_set_suspend_disable,
+       .set_suspend_mode       = max77802_set_suspend_mode,
+};
+
+/* BUCKs 5, 7-10 */
 static struct regulator_ops max77802_buck_dvs_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
@@ -290,12 +357,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_ramp_delay         = max77802_set_ramp_delay_2bit,
-       .set_suspend_disable    = max77802_buck_set_suspend_disable,
+       .set_suspend_disable    = max77802_set_suspend_disable,
 };
 
 /* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */
 #define regulator_77802_desc_p_ldo(num, supply, log)   {               \
        .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("regulators"),           \
        .id             = MAX77802_LDO##num,                            \
        .supply_name    = "inl"#supply,                                 \
        .ops            = &max77802_ldo_ops_logic##log,                 \
@@ -309,11 +378,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
        .vsel_mask      = MAX77802_VSEL_MASK,                           \
        .enable_reg     = MAX77802_REG_LDO1CTRL1 + num - 1,             \
        .enable_mask    = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
+       .of_map_mode    = max77802_map_mode,                            \
 }
 
 /* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */
 #define regulator_77802_desc_n_ldo(num, supply, log)   {               \
        .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("regulators"),           \
        .id             = MAX77802_LDO##num,                            \
        .supply_name    = "inl"#supply,                                 \
        .ops            = &max77802_ldo_ops_logic##log,                 \
@@ -327,11 +399,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
        .vsel_mask      = MAX77802_VSEL_MASK,                           \
        .enable_reg     = MAX77802_REG_LDO1CTRL1 + num - 1,             \
        .enable_mask    = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
+       .of_map_mode    = max77802_map_mode,                            \
 }
 
 /* BUCKs 1, 6 */
 #define regulator_77802_desc_16_buck(num)      {               \
        .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
        .id             = MAX77802_BUCK##num,                           \
        .supply_name    = "inb"#num,                                    \
        .ops            = &max77802_buck_16_dvs_ops,                    \
@@ -345,14 +420,17 @@ static struct regulator_ops max77802_buck_dvs_ops = {
        .vsel_mask      = MAX77802_DVS_VSEL_MASK,                       \
        .enable_reg     = MAX77802_REG_BUCK ## num ## CTRL,             \
        .enable_mask    = MAX77802_OPMODE_MASK,                         \
+       .of_map_mode    = max77802_map_mode,                            \
 }
 
 /* BUCKS 2-4 */
 #define regulator_77802_desc_234_buck(num)     {               \
        .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
        .id             = MAX77802_BUCK##num,                           \
        .supply_name    = "inb"#num,                                    \
-       .ops            = &max77802_buck_dvs_ops,                       \
+       .ops            = &max77802_buck_234_ops,                       \
        .type           = REGULATOR_VOLTAGE,                            \
        .owner          = THIS_MODULE,                                  \
        .min_uV         = 600000,                                       \
@@ -364,11 +442,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
        .enable_reg     = MAX77802_REG_BUCK ## num ## CTRL1,            \
        .enable_mask    = MAX77802_OPMODE_MASK <<                       \
                                MAX77802_OPMODE_BUCK234_SHIFT,          \
+       .of_map_mode    = max77802_map_mode,                            \
 }
 
 /* BUCK 5 */
 #define regulator_77802_desc_buck5(num)                {               \
        .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
        .id             = MAX77802_BUCK##num,                           \
        .supply_name    = "inb"#num,                                    \
        .ops            = &max77802_buck_dvs_ops,                       \
@@ -382,11 +463,14 @@ static struct regulator_ops max77802_buck_dvs_ops = {
        .vsel_mask      = MAX77802_VSEL_MASK,                           \
        .enable_reg     = MAX77802_REG_BUCK5CTRL,                       \
        .enable_mask    = MAX77802_OPMODE_MASK,                         \
+       .of_map_mode    = max77802_map_mode,                            \
 }
 
 /* BUCKs 7-10 */
 #define regulator_77802_desc_buck7_10(num)     {               \
        .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
        .id             = MAX77802_BUCK##num,                           \
        .supply_name    = "inb"#num,                                    \
        .ops            = &max77802_buck_dvs_ops,                       \
@@ -400,9 +484,10 @@ static struct regulator_ops max77802_buck_dvs_ops = {
        .vsel_mask      = MAX77802_VSEL_MASK,                           \
        .enable_reg     = MAX77802_REG_BUCK7CTRL + (num - 7) * 3,       \
        .enable_mask    = MAX77802_OPMODE_MASK,                         \
+       .of_map_mode    = max77802_map_mode,                            \
 }
 
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
        regulator_77802_desc_16_buck(1),
        regulator_77802_desc_234_buck(2),
        regulator_77802_desc_234_buck(3),
@@ -447,85 +532,19 @@ static struct regulator_desc regulators[] = {
        regulator_77802_desc_n_ldo(35, 2, 1),
 };
 
-#ifdef CONFIG_OF
-static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
-                                       struct max77686_platform_data *pdata)
-{
-       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct device_node *pmic_np, *regulators_np;
-       struct max77686_regulator_data *rdata;
-       struct of_regulator_match rmatch;
-       unsigned int i;
-
-       pmic_np = iodev->dev->of_node;
-       regulators_np = of_get_child_by_name(pmic_np, "regulators");
-       if (!regulators_np) {
-               dev_err(&pdev->dev, "could not find regulators sub-node\n");
-               return -EINVAL;
-       }
-
-       pdata->num_regulators = ARRAY_SIZE(regulators);
-       rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
-                            pdata->num_regulators, GFP_KERNEL);
-       if (!rdata) {
-               of_node_put(regulators_np);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < pdata->num_regulators; i++) {
-               rmatch.name = regulators[i].name;
-               rmatch.init_data = NULL;
-               rmatch.of_node = NULL;
-               if (of_regulator_match(&pdev->dev, regulators_np, &rmatch,
-                                      1) != 1) {
-                       dev_warn(&pdev->dev, "No matching regulator for '%s'\n",
-                                rmatch.name);
-                       continue;
-               }
-               rdata[i].initdata = rmatch.init_data;
-               rdata[i].of_node = rmatch.of_node;
-               rdata[i].id = regulators[i].id;
-       }
-
-       pdata->regulators = rdata;
-       of_node_put(regulators_np);
-
-       return 0;
-}
-#else
-static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
-                                       struct max77686_platform_data *pdata)
-{
-       return 0;
-}
-#endif /* CONFIG_OF */
-
 static int max77802_pmic_probe(struct platform_device *pdev)
 {
        struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
        struct max77802_regulator_prv *max77802;
-       int i, ret = 0, val;
+       int i, val;
        struct regulator_config config = { };
 
-       /* This is allocated by the MFD driver */
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data found for regulator\n");
-               return -ENODEV;
-       }
-
        max77802 = devm_kzalloc(&pdev->dev,
                                sizeof(struct max77802_regulator_prv),
                                GFP_KERNEL);
        if (!max77802)
                return -ENOMEM;
 
-       if (iodev->dev->of_node) {
-               ret = max77802_pmic_dt_parse_pdata(pdev, pdata);
-               if (ret)
-                       return ret;
-       }
-
        config.dev = iodev->dev;
        config.regmap = iodev->regmap;
        config.driver_data = max77802;
@@ -533,21 +552,25 @@ static int max77802_pmic_probe(struct platform_device *pdev)
 
        for (i = 0; i < MAX77802_REG_MAX; i++) {
                struct regulator_dev *rdev;
-               int id = pdata->regulators[i].id;
+               int id = regulators[i].id;
                int shift = max77802_get_opmode_shift(id);
-
-               config.init_data = pdata->regulators[i].initdata;
-               config.of_node = pdata->regulators[i].of_node;
+               int ret;
 
                ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val);
-               val = val >> shift & MAX77802_OPMODE_MASK;
+               if (ret < 0) {
+                       dev_warn(&pdev->dev,
+                               "cannot read current mode for %d\n", i);
+                       val = MAX77802_OPMODE_NORMAL;
+               } else {
+                       val = val >> shift & MAX77802_OPMODE_MASK;
+               }
 
                /*
                 * If the regulator is disabled and the system warm rebooted,
                 * the hardware reports OFF as the regulator operating mode.
                 * Default to operating mode NORMAL in that case.
                 */
-               if (val == MAX77802_OPMODE_OFF)
+               if (val == MAX77802_STATUS_OFF)
                        max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
                else
                        max77802->opmode[id] = val;
@@ -555,9 +578,10 @@ static int max77802_pmic_probe(struct platform_device *pdev)
                rdev = devm_regulator_register(&pdev->dev,
                                               &regulators[i], &config);
                if (IS_ERR(rdev)) {
+                       ret = PTR_ERR(rdev);
                        dev_err(&pdev->dev,
-                               "regulator init failed for %d\n", i);
-                       return PTR_ERR(rdev);
+                               "regulator init failed for %d: %d\n", i, ret);
+                       return ret;
                }
        }
 
index 2fc4111887949e01e04b023d6065962853779d42..7eee2ca1854183b05e4d4b08180020afc7337033 100644 (file)
@@ -335,7 +335,7 @@ static int max8660_pdata_from_dt(struct device *dev,
        int matched, i;
        struct device_node *np;
        struct max8660_subdev_data *sub;
-       struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)];
+       struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)] = { };
 
        np = of_get_child_by_name(dev->of_node, "regulators");
        if (!np) {
index f7f9efcfedb7ac1dcd66a64845805a56a9a07604..1af8f4a2ab86dedab889510baeba7cc93921ea06 100644 (file)
@@ -174,7 +174,7 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev)
        if (of_property_read_u32(np, "max8952,ramp-speed", &pd->ramp_speed))
                dev_warn(dev, "max8952,ramp-speed property not specified, defaulting to 32mV/us\n");
 
-       pd->reg_data = of_get_regulator_init_data(dev, np);
+       pd->reg_data = of_get_regulator_init_data(dev, np, &regulator);
        if (!pd->reg_data) {
                dev_err(dev, "Failed to parse regulator init data\n");
                return NULL;
@@ -225,6 +225,8 @@ static int max8952_pmic_probe(struct i2c_client *client,
        config.of_node = client->dev.of_node;
 
        config.ena_gpio = pdata->gpio_en;
+       if (client->dev.of_node)
+               config.ena_gpio_initialized = true;
        if (pdata->reg_data->constraints.boot_on)
                config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
 
index dbedf1768db0268f4f07f168bb89eb36f0c74429..c3d55c2db593b8f37a253c4a07bd21130db99353 100644 (file)
@@ -458,7 +458,8 @@ static int max8973_probe(struct i2c_client *client,
 
        config.dev = &client->dev;
        config.init_data = pdata ? pdata->reg_init_data :
-               of_get_regulator_init_data(&client->dev, client->dev.of_node);
+               of_get_regulator_init_data(&client->dev, client->dev.of_node,
+                                          &max->desc);
        config.driver_data = max;
        config.of_node = client->dev.of_node;
        config.regmap = max->regmap;
index 9c31e215a521e71c7cf7148f8e69a09ce5f58acc..726fde1d883e8f9fb180da118a5c961c5e609dff 100644 (file)
@@ -953,7 +953,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
 
                rdata->id = i;
                rdata->initdata = of_get_regulator_init_data(&pdev->dev,
-                                                            reg_np);
+                                                            reg_np,
+                                                            &regulators[i]);
                rdata->reg_node = reg_np;
                rdata++;
        }
index 961091b46557a40cc4e20029c9056afd4a34e80b..59e34a05a4a21b34fa6b283c76a2536af5cee5a2 100644 (file)
@@ -686,8 +686,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
                        continue;
 
                rdata->id = regulators[i].id;
-               rdata->initdata = of_get_regulator_init_data(
-                                                       iodev->dev, reg_np);
+               rdata->initdata = of_get_regulator_init_data(iodev->dev,
+                                                            reg_np,
+                                                            &regulators[i]);
                rdata->reg_node = reg_np;
                ++rdata;
        }
index afba024953e15c88f00d134f236dd4b574be4ffc..0281c31ae2edc0abd22ac44e4407d2c3fd9d6751 100644 (file)
@@ -194,7 +194,8 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
                                         regulators[i].desc.name)) {
                                p->id = i;
                                p->init_data = of_get_regulator_init_data(
-                                                       &pdev->dev, child);
+                                                       &pdev->dev, child,
+                                                       &regulators[i].desc);
                                p->node = child;
                                p++;
 
index 7a51814abdc56b5dba53dfe8d9ea95108899d423..91eaaf01052494e6579a87890ac2875cce740018 100644 (file)
 
 #include "internal.h"
 
+static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
+       [PM_SUSPEND_MEM]        = "regulator-state-mem",
+       [PM_SUSPEND_MAX]        = "regulator-state-disk",
+};
+
 static void of_get_regulation_constraints(struct device_node *np,
-                                       struct regulator_init_data **init_data)
+                                       struct regulator_init_data **init_data,
+                                       const struct regulator_desc *desc)
 {
        const __be32 *min_uV, *max_uV;
        struct regulation_constraints *constraints = &(*init_data)->constraints;
-       int ret;
+       struct regulator_state *suspend_state;
+       struct device_node *suspend_np;
+       int ret, i;
        u32 pval;
 
        constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -73,18 +81,84 @@ static void of_get_regulation_constraints(struct device_node *np,
        ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
        if (!ret)
                constraints->enable_time = pval;
+
+       if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
+               if (desc && desc->of_map_mode) {
+                       ret = desc->of_map_mode(pval);
+                       if (ret == -EINVAL)
+                               pr_err("%s: invalid mode %u\n", np->name, pval);
+                       else
+                               constraints->initial_mode = ret;
+               } else {
+                       pr_warn("%s: mapping for mode %d not defined\n",
+                               np->name, pval);
+               }
+       }
+
+       for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
+               switch (i) {
+               case PM_SUSPEND_MEM:
+                       suspend_state = &constraints->state_mem;
+                       break;
+               case PM_SUSPEND_MAX:
+                       suspend_state = &constraints->state_disk;
+                       break;
+               case PM_SUSPEND_ON:
+               case PM_SUSPEND_FREEZE:
+               case PM_SUSPEND_STANDBY:
+               default:
+                       continue;
+               };
+
+               suspend_np = of_get_child_by_name(np, regulator_states[i]);
+               if (!suspend_np || !suspend_state)
+                       continue;
+
+               if (!of_property_read_u32(suspend_np, "regulator-mode",
+                                         &pval)) {
+                       if (desc && desc->of_map_mode) {
+                               ret = desc->of_map_mode(pval);
+                               if (ret == -EINVAL)
+                                       pr_err("%s: invalid mode %u\n",
+                                              np->name, pval);
+                               else
+                                       suspend_state->mode = ret;
+                       } else {
+                               pr_warn("%s: mapping for mode %d not defined\n",
+                                       np->name, pval);
+                       }
+               }
+
+               if (of_property_read_bool(suspend_np,
+                                       "regulator-on-in-suspend"))
+                       suspend_state->enabled = true;
+               else if (of_property_read_bool(suspend_np,
+                                       "regulator-off-in-suspend"))
+                       suspend_state->disabled = true;
+
+               if (!of_property_read_u32(suspend_np,
+                                       "regulator-suspend-microvolt", &pval))
+                       suspend_state->uV = pval;
+
+               of_node_put(suspend_np);
+               suspend_state = NULL;
+               suspend_np = NULL;
+       }
 }
 
 /**
  * of_get_regulator_init_data - extract regulator_init_data structure info
  * @dev: device requesting for regulator_init_data
+ * @node: regulator device node
+ * @desc: regulator description
  *
  * Populates regulator_init_data structure by extracting data from device
  * tree node, returns a pointer to the populated struture or NULL if memory
  * alloc fails.
  */
 struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
-                                               struct device_node *node)
+                                         struct device_node *node,
+                                         const struct regulator_desc *desc)
 {
        struct regulator_init_data *init_data;
 
@@ -95,7 +169,7 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
        if (!init_data)
                return NULL; /* Out of memory? */
 
-       of_get_regulation_constraints(node, &init_data);
+       of_get_regulation_constraints(node, &init_data, desc);
        return init_data;
 }
 EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
@@ -176,7 +250,8 @@ int of_regulator_match(struct device *dev, struct device_node *node,
                                continue;
 
                        match->init_data =
-                               of_get_regulator_init_data(dev, child);
+                               of_get_regulator_init_data(dev, child,
+                                                          match->desc);
                        if (!match->init_data) {
                                dev_err(dev,
                                        "failed to parse DT for regulator %s\n",
@@ -211,7 +286,8 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
                search = dev->of_node;
 
        if (!search) {
-               dev_err(dev, "Failed to find regulator container node\n");
+               dev_dbg(dev, "Failed to find regulator container node '%s'\n",
+                       desc->regulators_node);
                return NULL;
        }
 
@@ -223,7 +299,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
                if (strcmp(desc->of_match, name))
                        continue;
 
-               init_data = of_get_regulator_init_data(dev, child);
+               init_data = of_get_regulator_init_data(dev, child, desc);
                if (!init_data) {
                        dev_err(dev,
                                "failed to parse DT for regulator %s\n",
index d3f55eaea0581999e5b5d14dbd04c32fa5f5ecda..91f34ca3a9acaec74fce1b88ead6689cc0bf04f7 100644 (file)
@@ -149,7 +149,8 @@ static int pwm_regulator_probe(struct platform_device *pdev)
                return ret;
        }
 
-       config.init_data = of_get_regulator_init_data(&pdev->dev, np);
+       config.init_data = of_get_regulator_init_data(&pdev->dev, np,
+                                                     &drvdata->desc);
        if (!config.init_data)
                return -ENOMEM;
 
index b55cd5b50ebe546da8c6b096a93e06c5e772e218..183598b111f96457a686726b4c0ddcace2968a2b 100644 (file)
@@ -183,6 +183,13 @@ static const struct regulator_linear_range ftsmps_ranges[] = {
        REGULATOR_LINEAR_RANGE(1500000,  64, 100, 50000),
 };
 
+static const struct regulator_linear_range smb208_ranges[] = {
+       REGULATOR_LINEAR_RANGE( 375000,   0,  29, 12500),
+       REGULATOR_LINEAR_RANGE( 750000,  30,  89, 12500),
+       REGULATOR_LINEAR_RANGE(1500000,  90, 153, 25000),
+       REGULATOR_LINEAR_RANGE(3100000, 154, 234, 25000),
+};
+
 static const struct regulator_linear_range ncp_ranges[] = {
        REGULATOR_LINEAR_RANGE(1500000,   0,  31, 50000),
 };
@@ -559,6 +566,16 @@ static const struct qcom_rpm_reg pm8921_switch = {
        .parts = &rpm8960_switch_parts,
 };
 
+static const struct qcom_rpm_reg smb208_smps = {
+       .desc.linear_ranges = smb208_ranges,
+       .desc.n_linear_ranges = ARRAY_SIZE(smb208_ranges),
+       .desc.n_voltages = 235,
+       .desc.ops = &uV_ops,
+       .parts = &rpm8960_smps_parts,
+       .supports_force_mode_auto = false,
+       .supports_force_mode_bypass = false,
+};
+
 static const struct of_device_id rpm_of_match[] = {
        { .compatible = "qcom,rpm-pm8058-pldo",     .data = &pm8058_pldo },
        { .compatible = "qcom,rpm-pm8058-nldo",     .data = &pm8058_nldo },
@@ -578,6 +595,8 @@ static const struct of_device_id rpm_of_match[] = {
        { .compatible = "qcom,rpm-pm8921-ftsmps",   .data = &pm8921_ftsmps },
        { .compatible = "qcom,rpm-pm8921-ncp",      .data = &pm8921_ncp },
        { .compatible = "qcom,rpm-pm8921-switch",   .data = &pm8921_switch },
+
+       { .compatible = "qcom,rpm-smb208", .data = &smb208_smps },
        { }
 };
 MODULE_DEVICE_TABLE(of, rpm_of_match);
@@ -643,10 +662,6 @@ static int rpm_reg_probe(struct platform_device *pdev)
        match = of_match_device(rpm_of_match, &pdev->dev);
        template = match->data;
 
-       initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
-       if (!initdata)
-               return -EINVAL;
-
        vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
        if (!vreg) {
                dev_err(&pdev->dev, "failed to allocate vreg\n");
@@ -666,6 +681,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+                                             &vreg->desc);
+       if (!initdata)
+               return -EINVAL;
+
        key = "reg";
        ret = of_property_read_u32(pdev->dev.of_node, key, &val);
        if (ret) {
index e305416d7697d2fd114ab86be2d7cd914484b649..ea9d05eabd0a81eea861694c57268afc23b1e220 100644 (file)
 #define RK808_RAMP_RATE_6MV_PER_US     (2 << RK808_RAMP_RATE_OFFSET)
 #define RK808_RAMP_RATE_10MV_PER_US    (3 << RK808_RAMP_RATE_OFFSET)
 
+/* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */
+#define RK808_SLP_REG_OFFSET 1
+
+/* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */
+#define RK808_SLP_SET_OFF_REG_OFFSET 2
+
 static const int rk808_buck_config_regs[] = {
        RK808_BUCK1_CONFIG_REG,
        RK808_BUCK2_CONFIG_REG,
@@ -44,7 +50,7 @@ static const int rk808_buck_config_regs[] = {
 };
 
 static const struct regulator_linear_range rk808_buck_voltage_ranges[] = {
-       REGULATOR_LINEAR_RANGE(700000, 0, 63, 12500),
+       REGULATOR_LINEAR_RANGE(712500, 0, 63, 12500),
 };
 
 static const struct regulator_linear_range rk808_buck4_voltage_ranges[] = {
@@ -91,6 +97,43 @@ static int rk808_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
                                  RK808_RAMP_RATE_MASK, ramp_value);
 }
 
+int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv)
+{
+       unsigned int reg;
+       int sel = regulator_map_voltage_linear_range(rdev, uv, uv);
+
+       if (sel < 0)
+               return -EINVAL;
+
+       reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
+
+       return regmap_update_bits(rdev->regmap, reg,
+                                 rdev->desc->vsel_mask,
+                                 sel);
+}
+
+int rk808_set_suspend_enable(struct regulator_dev *rdev)
+{
+       unsigned int reg;
+
+       reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
+
+       return regmap_update_bits(rdev->regmap, reg,
+                                 rdev->desc->enable_mask,
+                                 0);
+}
+
+int rk808_set_suspend_disable(struct regulator_dev *rdev)
+{
+       unsigned int reg;
+
+       reg = rdev->desc->enable_reg + RK808_SLP_SET_OFF_REG_OFFSET;
+
+       return regmap_update_bits(rdev->regmap, reg,
+                                 rdev->desc->enable_mask,
+                                 rdev->desc->enable_mask);
+}
+
 static struct regulator_ops rk808_buck1_2_ops = {
        .list_voltage           = regulator_list_voltage_linear_range,
        .map_voltage            = regulator_map_voltage_linear_range,
@@ -100,6 +143,9 @@ static struct regulator_ops rk808_buck1_2_ops = {
        .disable                = regulator_disable_regmap,
        .is_enabled             = regulator_is_enabled_regmap,
        .set_ramp_delay         = rk808_set_ramp_delay,
+       .set_suspend_voltage    = rk808_set_suspend_voltage,
+       .set_suspend_enable     = rk808_set_suspend_enable,
+       .set_suspend_disable    = rk808_set_suspend_disable,
 };
 
 static struct regulator_ops rk808_reg_ops = {
@@ -110,12 +156,17 @@ static struct regulator_ops rk808_reg_ops = {
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .is_enabled             = regulator_is_enabled_regmap,
+       .set_suspend_voltage    = rk808_set_suspend_voltage,
+       .set_suspend_enable     = rk808_set_suspend_enable,
+       .set_suspend_disable    = rk808_set_suspend_disable,
 };
 
 static struct regulator_ops rk808_switch_ops = {
-       .enable = regulator_enable_regmap,
-       .disable = regulator_disable_regmap,
-       .is_enabled = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .set_suspend_enable     = rk808_set_suspend_enable,
+       .set_suspend_disable    = rk808_set_suspend_disable,
 };
 
 static const struct regulator_desc rk808_reg[] = {
index e58d79aeb393627873bc22a79c23d9f470e2b0a5..b85ceb8ff9111ccecc672fc66d4c5082718b8a3d 100644 (file)
@@ -31,6 +31,8 @@ static struct regulator_ops rn5t618_reg_ops = {
 #define REG(rid, ereg, emask, vreg, vmask, min, max, step)             \
        [RN5T618_##rid] = {                                             \
                .name           = #rid,                                 \
+               .of_match       = of_match_ptr(#rid),                   \
+               .regulators_node = of_match_ptr("regulators"),          \
                .id             = RN5T618_##rid,                        \
                .type           = REGULATOR_VOLTAGE,                    \
                .owner          = THIS_MODULE,                          \
@@ -60,60 +62,15 @@ static struct regulator_desc rn5t618_regulators[] = {
        REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
 };
 
-static struct of_regulator_match rn5t618_matches[] = {
-       [RN5T618_DCDC1]         = { .name = "DCDC1" },
-       [RN5T618_DCDC2]         = { .name = "DCDC2" },
-       [RN5T618_DCDC3]         = { .name = "DCDC3" },
-       [RN5T618_LDO1]          = { .name = "LDO1" },
-       [RN5T618_LDO2]          = { .name = "LDO2" },
-       [RN5T618_LDO3]          = { .name = "LDO3" },
-       [RN5T618_LDO4]          = { .name = "LDO4" },
-       [RN5T618_LDO5]          = { .name = "LDO5" },
-       [RN5T618_LDORTC1]       = { .name = "LDORTC1" },
-       [RN5T618_LDORTC2]       = { .name = "LDORTC2" },
-};
-
-static int rn5t618_regulator_parse_dt(struct platform_device *pdev)
-{
-       struct device_node *np, *regulators;
-       int ret;
-
-       np = of_node_get(pdev->dev.parent->of_node);
-       if (!np)
-               return 0;
-
-       regulators = of_get_child_by_name(np, "regulators");
-       if (!regulators) {
-               dev_err(&pdev->dev, "regulators node not found\n");
-               return -EINVAL;
-       }
-
-       ret = of_regulator_match(&pdev->dev, regulators, rn5t618_matches,
-                                ARRAY_SIZE(rn5t618_matches));
-       of_node_put(regulators);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "error parsing regulator init data: %d\n",
-                       ret);
-       }
-
-       return 0;
-}
-
 static int rn5t618_regulator_probe(struct platform_device *pdev)
 {
        struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
        struct regulator_dev *rdev;
-       int ret, i;
-
-       ret = rn5t618_regulator_parse_dt(pdev);
-       if (ret)
-               return ret;
+       int i;
 
        for (i = 0; i < RN5T618_REG_NUM; i++) {
-               config.dev = &pdev->dev;
-               config.init_data = rn5t618_matches[i].init_data;
-               config.of_node = rn5t618_matches[i].of_node;
+               config.dev = pdev->dev.parent;
                config.regmap = rn5t618->regmap;
 
                rdev = devm_regulator_register(&pdev->dev,
diff --git a/drivers/regulator/rt5033-regulator.c b/drivers/regulator/rt5033-regulator.c
new file mode 100644 (file)
index 0000000..870cc49
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Regulator driver for the Richtek RT5033
+ *
+ * Copyright (C) 2014 Samsung Electronics, Co., Ltd.
+ * Author: Beomho Seo <beomho.seo@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 bythe Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/rt5033.h>
+#include <linux/mfd/rt5033-private.h>
+#include <linux/regulator/of_regulator.h>
+
+static struct regulator_ops rt5033_safe_ldo_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .list_voltage           = regulator_list_voltage_linear,
+};
+
+static struct regulator_ops rt5033_buck_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_desc rt5033_supported_regulators[] = {
+       [RT5033_BUCK] = {
+               .name           = "BUCK",
+               .id             = RT5033_BUCK,
+               .ops            = &rt5033_buck_ops,
+               .type           = REGULATOR_VOLTAGE,
+               .owner          = THIS_MODULE,
+               .n_voltages     = RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM,
+               .min_uV         = RT5033_REGULATOR_BUCK_VOLTAGE_MIN,
+               .uV_step        = RT5033_REGULATOR_BUCK_VOLTAGE_STEP,
+               .enable_reg     = RT5033_REG_CTRL,
+               .enable_mask    = RT5033_CTRL_EN_BUCK_MASK,
+               .vsel_reg       = RT5033_REG_BUCK_CTRL,
+               .vsel_mask      = RT5033_BUCK_CTRL_MASK,
+       },
+       [RT5033_LDO] = {
+               .name           = "LDO",
+               .id             = RT5033_LDO,
+               .ops            = &rt5033_buck_ops,
+               .type           = REGULATOR_VOLTAGE,
+               .owner          = THIS_MODULE,
+               .n_voltages     = RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM,
+               .min_uV         = RT5033_REGULATOR_LDO_VOLTAGE_MIN,
+               .uV_step        = RT5033_REGULATOR_LDO_VOLTAGE_STEP,
+               .enable_reg     = RT5033_REG_CTRL,
+               .enable_mask    = RT5033_CTRL_EN_LDO_MASK,
+               .vsel_reg       = RT5033_REG_LDO_CTRL,
+               .vsel_mask      = RT5033_LDO_CTRL_MASK,
+       },
+       [RT5033_SAFE_LDO] = {
+               .name           = "SAFE_LDO",
+               .id             = RT5033_SAFE_LDO,
+               .ops            = &rt5033_safe_ldo_ops,
+               .type           = REGULATOR_VOLTAGE,
+               .owner          = THIS_MODULE,
+               .n_voltages     = 1,
+               .min_uV         = RT5033_REGULATOR_SAFE_LDO_VOLTAGE,
+               .enable_reg     = RT5033_REG_CTRL,
+               .enable_mask    = RT5033_CTRL_EN_SAFE_LDO_MASK,
+       },
+};
+
+static int rt5033_regulator_probe(struct platform_device *pdev)
+{
+       struct rt5033_dev *rt5033 = dev_get_drvdata(pdev->dev.parent);
+       int ret, i;
+       struct regulator_config config = {};
+
+       config.dev = &pdev->dev;
+       config.driver_data = rt5033;
+
+       for (i = 0; i < ARRAY_SIZE(rt5033_supported_regulators); i++) {
+               struct regulator_dev *regulator;
+
+               config.regmap = rt5033->regmap;
+
+               regulator = devm_regulator_register(&pdev->dev,
+                               &rt5033_supported_regulators[i], &config);
+               if (IS_ERR(regulator)) {
+                       ret = PTR_ERR(regulator);
+                       dev_err(&pdev->dev,
+                               "Regulator init failed %d: with error: %d\n",
+                               i, ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct platform_device_id rt5033_regulator_id[] = {
+       { "rt5033-regulator", },
+       { }
+};
+MODULE_DEVICE_TABLE(platform, rt5033_regulator_id);
+
+static struct platform_driver rt5033_regulator_driver = {
+       .driver = {
+               .name = "rt5033-regulator",
+       },
+       .probe          = rt5033_regulator_probe,
+       .id_table       = rt5033_regulator_id,
+};
+module_platform_driver(rt5033_regulator_driver);
+
+MODULE_DESCRIPTION("Richtek RT5033 Regulator driver");
+MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
+MODULE_LICENSE("GPL");
index 4acefa6b462e0d8e362866b1b86bc2ca4177bb00..5db4e12a7e0479bbcef860e7c2cda2d8ac3116c1 100644 (file)
@@ -298,7 +298,7 @@ static struct regulator_ops s2mpa01_buck_ops = {
        .enable_mask    = S2MPA01_ENABLE_MASK                   \
 }
 
-static struct regulator_desc regulators[] = {
+static const struct regulator_desc regulators[] = {
        regulator_desc_ldo(1, STEP_25_MV),
        regulator_desc_ldo(2, STEP_50_MV),
        regulator_desc_ldo(3, STEP_50_MV),
@@ -341,7 +341,7 @@ static int s2mpa01_pmic_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
-       struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX];
+       struct of_regulator_match rdata[S2MPA01_REGULATOR_MAX] = { };
        struct device_node *reg_np = NULL;
        struct regulator_config config = { };
        struct s2mpa01_info *s2mpa01;
index adab82d5279f0696319f53d04e30b07615121dbb..b345cf51225a71dc374bff3611d74b6ee9a0ad64 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/of_gpio.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/s2mps11.h>
+#include <linux/mfd/samsung/s2mps13.h>
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mpu02.h>
 
@@ -45,10 +46,10 @@ struct s2mps11_info {
        enum sec_device_type dev_type;
 
        /*
-        * One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode
-        * was enabled.
+        * One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether
+        * the suspend mode was enabled.
         */
-       unsigned long long s2mps14_suspend_state:35;
+       unsigned long long s2mps14_suspend_state:50;
 
        /* Array of size rdev_num with GPIO-s for external sleep control */
        int *ext_control_gpio;
@@ -369,12 +370,101 @@ static const struct regulator_desc s2mps11_regulators[] = {
        regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
 };
 
+static struct regulator_ops s2mps14_reg_ops;
+
+#define regulator_desc_s2mps13_ldo(num, min, step, min_sel) {  \
+       .name           = "LDO"#num,                            \
+       .id             = S2MPS13_LDO##num,                     \
+       .ops            = &s2mps14_reg_ops,                     \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = min,                                  \
+       .uV_step        = step,                                 \
+       .linear_min_sel = min_sel,                              \
+       .n_voltages     = S2MPS14_LDO_N_VOLTAGES,               \
+       .vsel_reg       = S2MPS13_REG_L1CTRL + num - 1,         \
+       .vsel_mask      = S2MPS14_LDO_VSEL_MASK,                \
+       .enable_reg     = S2MPS13_REG_L1CTRL + num - 1,         \
+       .enable_mask    = S2MPS14_ENABLE_MASK                   \
+}
+
+#define regulator_desc_s2mps13_buck(num, min, step, min_sel) { \
+       .name           = "BUCK"#num,                           \
+       .id             = S2MPS13_BUCK##num,                    \
+       .ops            = &s2mps14_reg_ops,                     \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = min,                                  \
+       .uV_step        = step,                                 \
+       .linear_min_sel = min_sel,                              \
+       .n_voltages     = S2MPS14_BUCK_N_VOLTAGES,              \
+       .ramp_delay     = S2MPS13_BUCK_RAMP_DELAY,              \
+       .vsel_reg       = S2MPS13_REG_B1OUT + (num - 1) * 2,    \
+       .vsel_mask      = S2MPS14_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS13_REG_B1CTRL + (num - 1) * 2,   \
+       .enable_mask    = S2MPS14_ENABLE_MASK                   \
+}
+
+static const struct regulator_desc s2mps13_regulators[] = {
+       regulator_desc_s2mps13_ldo(1,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(2,  MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(3,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(4,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(5,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(6,  MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(7,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(8,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(9,  MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(10, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(11, MIN_800_MV,  STEP_25_MV,   0x10),
+       regulator_desc_s2mps13_ldo(12, MIN_800_MV,  STEP_25_MV,   0x10),
+       regulator_desc_s2mps13_ldo(13, MIN_800_MV,  STEP_25_MV,   0x10),
+       regulator_desc_s2mps13_ldo(14, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(15, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(16, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(17, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(18, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(19, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(20, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(21, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(22, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(23, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(24, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(25, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(26, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(27, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(28, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(29, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(30, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(31, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(32, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(33, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(34, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(35, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(36, MIN_800_MV,  STEP_12_5_MV, 0x00),
+       regulator_desc_s2mps13_ldo(37, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(38, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_ldo(39, MIN_1000_MV, STEP_25_MV,   0x08),
+       regulator_desc_s2mps13_ldo(40, MIN_1400_MV, STEP_50_MV,   0x0C),
+       regulator_desc_s2mps13_buck(1,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(2,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(3,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(4,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(5,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(6,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(7,  MIN_500_MV,  STEP_6_25_MV, 0x10),
+       regulator_desc_s2mps13_buck(8,  MIN_1000_MV, STEP_12_5_MV, 0x20),
+       regulator_desc_s2mps13_buck(9,  MIN_1000_MV, STEP_12_5_MV, 0x20),
+       regulator_desc_s2mps13_buck(10, MIN_500_MV,  STEP_6_25_MV, 0x10),
+};
+
 static int s2mps14_regulator_enable(struct regulator_dev *rdev)
 {
        struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
        unsigned int val;
 
        switch (s2mps11->dev_type) {
+       case S2MPS13X:
        case S2MPS14X:
                if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
                        val = S2MPS14_ENABLE_SUSPEND;
@@ -406,6 +496,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
 
        /* Below LDO should be always on or does not support suspend mode. */
        switch (s2mps11->dev_type) {
+       case S2MPS13X:
        case S2MPS14X:
                switch (rdev_id) {
                case S2MPS14_LDO3:
@@ -831,6 +922,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
                s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
                regulators = s2mps11_regulators;
                break;
+       case S2MPS13X:
+               s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
+               regulators = s2mps13_regulators;
+               break;
        case S2MPS14X:
                s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
                regulators = s2mps14_regulators;
@@ -845,7 +940,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
                return -EINVAL;
        };
 
-       s2mps11->ext_control_gpio = devm_kzalloc(&pdev->dev,
+       s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev,
                        sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
                        GFP_KERNEL);
        if (!s2mps11->ext_control_gpio)
@@ -886,6 +981,7 @@ common_reg:
        config.regmap = iodev->regmap_pmic;
        config.driver_data = s2mps11;
        config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+       config.ena_gpio_initialized = true;
        for (i = 0; i < s2mps11->rdev_num; i++) {
                struct regulator_dev *regulator;
 
@@ -927,6 +1023,7 @@ out:
 
 static const struct platform_device_id s2mps11_pmic_id[] = {
        { "s2mps11-pmic", S2MPS11X},
+       { "s2mps13-pmic", S2MPS13X},
        { "s2mps14-pmic", S2MPS14X},
        { "s2mpu02-pmic", S2MPU02},
        { },
index 0ab5cbeeb797adda5a6c89e8a9608531cb4a8fdb..dc1328c0c71c49017d0752a8689f956e97bc955a 100644 (file)
@@ -581,7 +581,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
 
                rdata->id = i;
                rdata->initdata = of_get_regulator_init_data(
-                                               &pdev->dev, reg_np);
+                                               &pdev->dev, reg_np,
+                                               &regulators[i]);
                rdata->reg_node = reg_np;
                rdata++;
                rmode->id = i;
@@ -950,6 +951,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
                config.of_node = pdata->regulators[i].reg_node;
                config.ena_gpio = -EINVAL;
                config.ena_gpio_flags = 0;
+               config.ena_gpio_initialized = true;
                if (gpio_is_valid(pdata->regulators[i].ext_control_gpio))
                        s5m8767_regulator_config_ext_control(s5m8767,
                                        &pdata->regulators[i], &config);
index 97aff0ccd65ff3062ec435c8d626941d1cde03c9..6478606119160b63740947ca02c2e3f8737028af 100644 (file)
@@ -5,9 +5,8 @@
  * Author : Gyungoh Yoo <jack.yoo@skyworksinc.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, or (at your option) any
- * later version.
+ * 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
@@ -52,6 +51,8 @@ static const struct regulator_linear_range sky81452_reg_ranges[] = {
 
 static const struct regulator_desc sky81452_reg = {
        .name = "LOUT",
+       .of_match = of_match_ptr("lout"),
+       .regulators_node = of_match_ptr("regulator"),
        .ops = &sky81452_reg_ops,
        .type = REGULATOR_VOLTAGE,
        .owner = THIS_MODULE,
@@ -64,30 +65,6 @@ static const struct regulator_desc sky81452_reg = {
        .enable_mask = SKY81452_LEN,
 };
 
-#ifdef CONFIG_OF
-static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev)
-{
-       struct regulator_init_data *init_data;
-       struct device_node *np;
-
-       np = of_get_child_by_name(dev->parent->of_node, "regulator");
-       if (unlikely(!np)) {
-               dev_err(dev, "regulator node not found");
-               return NULL;
-       }
-
-       init_data = of_get_regulator_init_data(dev, np);
-
-       of_node_put(np);
-       return init_data;
-}
-#else
-static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev)
-{
-       return ERR_PTR(-EINVAL);
-}
-#endif
-
 static int sky81452_reg_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -95,20 +72,16 @@ static int sky81452_reg_probe(struct platform_device *pdev)
        struct regulator_config config = { };
        struct regulator_dev *rdev;
 
-       if (!init_data) {
-               init_data = sky81452_reg_parse_dt(dev);
-               if (IS_ERR(init_data))
-                       return PTR_ERR(init_data);
-       }
-
-       config.dev = dev;
+       config.dev = dev->parent;
        config.init_data = init_data;
        config.of_node = dev->of_node;
        config.regmap = dev_get_drvdata(dev->parent);
 
        rdev = devm_regulator_register(dev, &sky81452_reg, &config);
-       if (IS_ERR(rdev))
+       if (IS_ERR(rdev)) {
+               dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(rdev));
                return PTR_ERR(rdev);
+       }
 
        platform_set_drvdata(pdev, rdev);
 
@@ -126,5 +99,4 @@ module_platform_driver(sky81452_reg_driver);
 
 MODULE_DESCRIPTION("Skyworks SKY81452 Regulator driver");
 MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
index a7e152696a022f4ed20b2175fb2689e21072e3cc..b4f1696456a7f09b6c7c8f45bafda539c9a2e983 100644 (file)
@@ -72,7 +72,8 @@ static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
        config.regmap = stw481x->map;
        config.of_node = pdev->dev.of_node;
        config.init_data = of_get_regulator_init_data(&pdev->dev,
-                                                     pdev->dev.of_node);
+                                                     pdev->dev.of_node,
+                                                     &vmmc_regulator);
 
        stw481x->vmmc_regulator = devm_regulator_register(&pdev->dev,
                                                &vmmc_regulator, &config);
index a2dabb575b97d6260837da1deca24e821accc4f0..1ef5aba96f1719c4b7b575eedb112c519893c7d6 100644 (file)
@@ -837,7 +837,8 @@ skip_opt:
                return -EINVAL;
        }
 
-       initdata = of_get_regulator_init_data(dev, pdev->dev.of_node);
+       initdata = of_get_regulator_init_data(dev, pdev->dev.of_node,
+                                             &abb->rdesc);
        if (!initdata) {
                dev_err(dev, "%s: Unable to alloc regulator init data\n",
                        __func__);
index f31f22e3e1bd56c0b6f1e36a07152f8c3d0039bc..c213e37eb69e06c65a2d592c00afff2e0a92f4ef 100644 (file)
@@ -221,7 +221,8 @@ static const struct of_device_id tps51632_of_match[] = {
 MODULE_DEVICE_TABLE(of, tps51632_of_match);
 
 static struct tps51632_regulator_platform_data *
-       of_get_tps51632_platform_data(struct device *dev)
+       of_get_tps51632_platform_data(struct device *dev,
+                                     const struct regulator_desc *desc)
 {
        struct tps51632_regulator_platform_data *pdata;
        struct device_node *np = dev->of_node;
@@ -230,7 +231,8 @@ static struct tps51632_regulator_platform_data *
        if (!pdata)
                return NULL;
 
-       pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
+       pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node,
+                                                         desc);
        if (!pdata->reg_init_data) {
                dev_err(dev, "Not able to get OF regulator init data\n");
                return NULL;
@@ -248,7 +250,8 @@ static struct tps51632_regulator_platform_data *
 }
 #else
 static struct tps51632_regulator_platform_data *
-       of_get_tps51632_platform_data(struct device *dev)
+       of_get_tps51632_platform_data(struct device *dev,
+                                     const struct regulator_desc *desc)
 {
        return NULL;
 }
@@ -273,9 +276,25 @@ static int tps51632_probe(struct i2c_client *client,
                }
        }
 
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       tps->dev = &client->dev;
+       tps->desc.name = client->name;
+       tps->desc.id = 0;
+       tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+       tps->desc.min_uV = TPS51632_MIN_VOLTAGE;
+       tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV;
+       tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
+       tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
+       tps->desc.ops = &tps51632_dcdc_ops;
+       tps->desc.type = REGULATOR_VOLTAGE;
+       tps->desc.owner = THIS_MODULE;
+
        pdata = dev_get_platdata(&client->dev);
        if (!pdata && client->dev.of_node)
-               pdata = of_get_tps51632_platform_data(&client->dev);
+               pdata = of_get_tps51632_platform_data(&client->dev, &tps->desc);
        if (!pdata) {
                dev_err(&client->dev, "No Platform data\n");
                return -EINVAL;
@@ -296,22 +315,6 @@ static int tps51632_probe(struct i2c_client *client,
                }
        }
 
-       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
-       if (!tps)
-               return -ENOMEM;
-
-       tps->dev = &client->dev;
-       tps->desc.name = client->name;
-       tps->desc.id = 0;
-       tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
-       tps->desc.min_uV = TPS51632_MIN_VOLTAGE;
-       tps->desc.uV_step = TPS51632_VOLTAGE_STEP_10mV;
-       tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
-       tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
-       tps->desc.ops = &tps51632_dcdc_ops;
-       tps->desc.type = REGULATOR_VOLTAGE;
-       tps->desc.owner = THIS_MODULE;
-
        if (pdata->enable_pwm_dvfs)
                tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG;
        else
index a1672044e5195304095f5de99e5c4e01218cb828..a1fd626c6c966fb13dce292120278a33e378a3a2 100644 (file)
@@ -293,7 +293,8 @@ static const struct regmap_config tps62360_regmap_config = {
 };
 
 static struct tps62360_regulator_platform_data *
-       of_get_tps62360_platform_data(struct device *dev)
+       of_get_tps62360_platform_data(struct device *dev,
+                                     const struct regulator_desc *desc)
 {
        struct tps62360_regulator_platform_data *pdata;
        struct device_node *np = dev->of_node;
@@ -302,7 +303,8 @@ static struct tps62360_regulator_platform_data *
        if (!pdata)
                return NULL;
 
-       pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node);
+       pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node,
+                                                         desc);
        if (!pdata->reg_init_data) {
                dev_err(dev, "Not able to get OF regulator init data\n");
                return NULL;
@@ -350,6 +352,17 @@ static int tps62360_probe(struct i2c_client *client,
 
        pdata = dev_get_platdata(&client->dev);
 
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps)
+               return -ENOMEM;
+
+       tps->desc.name = client->name;
+       tps->desc.id = 0;
+       tps->desc.ops = &tps62360_dcdc_ops;
+       tps->desc.type = REGULATOR_VOLTAGE;
+       tps->desc.owner = THIS_MODULE;
+       tps->desc.uV_step = 10000;
+
        if (client->dev.of_node) {
                const struct of_device_id *match;
                match = of_match_device(of_match_ptr(tps62360_of_match),
@@ -360,7 +373,8 @@ static int tps62360_probe(struct i2c_client *client,
                }
                chip_id = (int)(long)match->data;
                if (!pdata)
-                       pdata = of_get_tps62360_platform_data(&client->dev);
+                       pdata = of_get_tps62360_platform_data(&client->dev,
+                                                             &tps->desc);
        } else if (id) {
                chip_id = id->driver_data;
        } else {
@@ -374,10 +388,6 @@ static int tps62360_probe(struct i2c_client *client,
                return -EIO;
        }
 
-       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
-       if (!tps)
-               return -ENOMEM;
-
        tps->en_discharge = pdata->en_discharge;
        tps->en_internal_pulldn = pdata->en_internal_pulldn;
        tps->vsel0_gpio = pdata->vsel0_gpio;
@@ -401,13 +411,6 @@ static int tps62360_probe(struct i2c_client *client,
                return -ENODEV;
        }
 
-       tps->desc.name = client->name;
-       tps->desc.id = 0;
-       tps->desc.ops = &tps62360_dcdc_ops;
-       tps->desc.type = REGULATOR_VOLTAGE;
-       tps->desc.owner = THIS_MODULE;
-       tps->desc.uV_step = 10000;
-
        tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
        if (IS_ERR(tps->regmap)) {
                ret = PTR_ERR(tps->regmap);
index d5df1e9ad1da659a230e4765ad2ea73292faef06..f1df4423d361c64dc588bf6b6708c366dc513e8b 100644 (file)
@@ -312,7 +312,11 @@ static void tps65090_configure_regulator_config(
                        gpio_flag = GPIOF_OUT_INIT_HIGH;
 
                config->ena_gpio = tps_pdata->gpio;
+               config->ena_gpio_initialized = true;
                config->ena_gpio_flags = gpio_flag;
+       } else {
+               config->ena_gpio = -EINVAL;
+               config->ena_gpio_initialized = false;
        }
 }
 
index f0a40281b9c10a043def2fbd040a7ee4e6a70d1f..263cc85d6202a955f22dfdd43d07a4f5e24ff4f6 100644 (file)
@@ -231,7 +231,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
 
        template = match->data;
        id = template->id;
-       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+                                              &regulators[id]);
 
        platform_set_drvdata(pdev, tps);
 
index 0b4f8660fdb4b65c3521e10184109378d98f766d..dd727bca19832cc157f6a158966c87d5fdc455c6 100644 (file)
@@ -1104,7 +1104,8 @@ static int twlreg_probe(struct platform_device *pdev)
                template = match->data;
                id = template->desc.id;
                initdata = of_get_regulator_init_data(&pdev->dev,
-                                                     pdev->dev.of_node);
+                                                     pdev->dev.of_node,
+                                                     &template->desc);
                drvdata = NULL;
        } else {
                id = pdev->id;
index 02e7267ccf927732d6b604a6ed05966040108b46..5e7c789023a901553c43ce663df657c1daa0b746 100644 (file)
@@ -74,7 +74,8 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
        reg->desc.owner = THIS_MODULE;
        reg->desc.continuous_voltage_range = true;
 
-       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+                                              &reg->desc);
        if (!init_data)
                return -EINVAL;
 
index c24346db8a71139e202c60464317e4fc03123253..88f5064e412b74a802c00c28855376d35c054237 100644 (file)
@@ -145,10 +145,12 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
        config.driver_data = ldo;
        config.regmap = wm8994->regmap;
        config.init_data = &ldo->init_data;
-       if (pdata)
+       if (pdata) {
                config.ena_gpio = pdata->ldo[id].enable;
-       else if (wm8994->dev->of_node)
+       } else if (wm8994->dev->of_node) {
                config.ena_gpio = wm8994->pdata.ldo[id].enable;
+               config.ena_gpio_initialized = true;
+       }
 
        /* Use default constraints if none set up */
        if (!pdata || !pdata->ldo[id].init_data || wm8994->dev->of_node) {
index 60fed3d7820b75fc0a0a8fd2157bb7a84918ff79..157d421f755bcb4e221cbe77539bf9b7ddf6fcd2 100644 (file)
@@ -1,4 +1,5 @@
 obj-$(CONFIG_RESET_CONTROLLER) += core.o
 obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
 obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
index baeaf82d40d9f1982761d68ee1cf0c56cd6c346e..7955e00d04d49fca9f16d78f1fa50835c038bf46 100644 (file)
@@ -125,6 +125,21 @@ int reset_control_deassert(struct reset_control *rstc)
 }
 EXPORT_SYMBOL_GPL(reset_control_deassert);
 
+/**
+ * reset_control_status - returns a negative errno if not supported, a
+ * positive value if the reset line is asserted, or zero if the reset
+ * line is not asserted.
+ * @rstc: reset controller
+ */
+int reset_control_status(struct reset_control *rstc)
+{
+       if (rstc->rcdev->ops->status)
+               return rstc->rcdev->ops->status(rstc->rcdev, rstc->id);
+
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(reset_control_status);
+
 /**
  * of_reset_control_get - Lookup and obtain a reference to a reset controller.
  * @node: device to be reset by the controller
diff --git a/drivers/reset/reset-berlin.c b/drivers/reset/reset-berlin.c
new file mode 100644 (file)
index 0000000..f8b48a1
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Tenart <antoine.tenart@free-electrons.com>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define BERLIN_MAX_RESETS      32
+
+#define to_berlin_reset_priv(p)                \
+       container_of((p), struct berlin_reset_priv, rcdev)
+
+struct berlin_reset_priv {
+       void __iomem                    *base;
+       unsigned int                    size;
+       struct reset_controller_dev     rcdev;
+};
+
+static int berlin_reset_reset(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
+       int offset = id >> 8;
+       int mask = BIT(id & 0x1f);
+
+       writel(mask, priv->base + offset);
+
+       /* let the reset be effective */
+       udelay(10);
+
+       return 0;
+}
+
+static struct reset_control_ops berlin_reset_ops = {
+       .reset  = berlin_reset_reset,
+};
+
+static int berlin_reset_xlate(struct reset_controller_dev *rcdev,
+                             const struct of_phandle_args *reset_spec)
+{
+       struct berlin_reset_priv *priv = to_berlin_reset_priv(rcdev);
+       unsigned offset, bit;
+
+       if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
+               return -EINVAL;
+
+       offset = reset_spec->args[0];
+       bit = reset_spec->args[1];
+
+       if (offset >= priv->size)
+               return -EINVAL;
+
+       if (bit >= BERLIN_MAX_RESETS)
+               return -EINVAL;
+
+       return (offset << 8) | bit;
+}
+
+static int __berlin_reset_init(struct device_node *np)
+{
+       struct berlin_reset_priv *priv;
+       struct resource res;
+       resource_size_t size;
+       int ret;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       ret = of_address_to_resource(np, 0, &res);
+       if (ret)
+               goto err;
+
+       size = resource_size(&res);
+       priv->base = ioremap(res.start, size);
+       if (!priv->base) {
+               ret = -ENOMEM;
+               goto err;
+       }
+       priv->size = size;
+
+       priv->rcdev.owner = THIS_MODULE;
+       priv->rcdev.ops = &berlin_reset_ops;
+       priv->rcdev.of_node = np;
+       priv->rcdev.of_reset_n_cells = 2;
+       priv->rcdev.of_xlate = berlin_reset_xlate;
+
+       reset_controller_register(&priv->rcdev);
+
+       return 0;
+
+err:
+       kfree(priv);
+       return ret;
+}
+
+static const struct of_device_id berlin_reset_of_match[] __initconst = {
+       { .compatible = "marvell,berlin2-chip-ctrl" },
+       { .compatible = "marvell,berlin2cd-chip-ctrl" },
+       { .compatible = "marvell,berlin2q-chip-ctrl" },
+       { },
+};
+
+static int __init berlin_reset_init(void)
+{
+       struct device_node *np;
+       int ret;
+
+       for_each_matching_node(np, berlin_reset_of_match) {
+               ret = __berlin_reset_init(np);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+arch_initcall(berlin_reset_init);
index 79c32ca84ef161a9205fc9bb061d187188889035..40582089474a5df515dfb926f58c0cf79968b77e 100644 (file)
@@ -76,9 +76,24 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
        return 0;
 }
 
+static int socfpga_reset_status(struct reset_controller_dev *rcdev,
+                               unsigned long id)
+{
+       struct socfpga_reset_data *data = container_of(rcdev,
+                                               struct socfpga_reset_data, rcdev);
+       int bank = id / BITS_PER_LONG;
+       int offset = id % BITS_PER_LONG;
+       u32 reg;
+
+       reg = readl(data->membase + OFFSET_MODRST + (bank * NR_BANKS));
+
+       return !(reg & BIT(offset));
+}
+
 static struct reset_control_ops socfpga_reset_ops = {
        .assert         = socfpga_reset_assert,
        .deassert       = socfpga_reset_deassert,
+       .status         = socfpga_reset_status,
 };
 
 static int socfpga_reset_probe(struct platform_device *pdev)
index 88d2d0316613f8ba65735088c198a5ff228fc048..f8c15a37fb3530d64b704d0818c598d2405a1fa5 100644 (file)
@@ -12,4 +12,8 @@ config STIH416_RESET
        bool
        select STI_RESET_SYSCFG
 
+config STIH407_RESET
+       bool
+       select STI_RESET_SYSCFG
+
 endif
index be1c97647871c400d202c3743cdf41fc27a641ba..dc85dfbe56a91746185f495cceb967a0addce8b3 100644 (file)
@@ -2,3 +2,4 @@ obj-$(CONFIG_STI_RESET_SYSCFG) += reset-syscfg.o
 
 obj-$(CONFIG_STIH415_RESET) += reset-stih415.o
 obj-$(CONFIG_STIH416_RESET) += reset-stih416.o
+obj-$(CONFIG_STIH407_RESET) += reset-stih407.o
diff --git a/drivers/reset/sti/reset-stih407.c b/drivers/reset/sti/reset-stih407.c
new file mode 100644 (file)
index 0000000..d83db5d
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics (R&D) Limited
+ * Author: Giuseppe Cavallaro <peppe.cavallaro@st.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/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/reset-controller/stih407-resets.h>
+#include "reset-syscfg.h"
+
+/* STiH407 Peripheral powerdown definitions. */
+static const char stih407_core[] = "st,stih407-core-syscfg";
+static const char stih407_sbc_reg[] = "st,stih407-sbc-reg-syscfg";
+static const char stih407_lpm[] = "st,stih407-lpm-syscfg";
+
+#define STIH407_PDN_0(_bit) \
+       _SYSCFG_RST_CH(stih407_core, SYSCFG_5000, _bit, SYSSTAT_5500, _bit)
+#define STIH407_PDN_1(_bit) \
+       _SYSCFG_RST_CH(stih407_core, SYSCFG_5001, _bit, SYSSTAT_5501, _bit)
+#define STIH407_PDN_ETH(_bit, _stat) \
+       _SYSCFG_RST_CH(stih407_sbc_reg, SYSCFG_4032, _bit, SYSSTAT_4520, _stat)
+
+/* Powerdown requests control 0 */
+#define SYSCFG_5000    0x0
+#define SYSSTAT_5500   0x7d0
+/* Powerdown requests control 1 (High Speed Links) */
+#define SYSCFG_5001    0x4
+#define SYSSTAT_5501   0x7d4
+
+/* Ethernet powerdown/status/reset */
+#define SYSCFG_4032    0x80
+#define SYSSTAT_4520   0x820
+#define SYSCFG_4002    0x8
+
+static const struct syscfg_reset_channel_data stih407_powerdowns[] = {
+       [STIH407_EMISS_POWERDOWN] = STIH407_PDN_0(1),
+       [STIH407_NAND_POWERDOWN] = STIH407_PDN_0(0),
+       [STIH407_USB3_POWERDOWN] = STIH407_PDN_1(6),
+       [STIH407_USB2_PORT1_POWERDOWN] = STIH407_PDN_1(5),
+       [STIH407_USB2_PORT0_POWERDOWN] = STIH407_PDN_1(4),
+       [STIH407_PCIE1_POWERDOWN] = STIH407_PDN_1(3),
+       [STIH407_PCIE0_POWERDOWN] = STIH407_PDN_1(2),
+       [STIH407_SATA1_POWERDOWN] = STIH407_PDN_1(1),
+       [STIH407_SATA0_POWERDOWN] = STIH407_PDN_1(0),
+       [STIH407_ETH1_POWERDOWN] = STIH407_PDN_ETH(0, 2),
+};
+
+/* Reset Generator control 0/1 */
+#define SYSCFG_5131    0x20c
+#define SYSCFG_5132    0x210
+
+#define LPM_SYSCFG_1   0x4     /* Softreset IRB & SBC UART */
+
+#define STIH407_SRST_CORE(_reg, _bit) \
+       _SYSCFG_RST_CH_NO_ACK(stih407_core, _reg, _bit)
+
+#define STIH407_SRST_SBC(_reg, _bit) \
+       _SYSCFG_RST_CH_NO_ACK(stih407_sbc_reg, _reg, _bit)
+
+#define STIH407_SRST_LPM(_reg, _bit) \
+       _SYSCFG_RST_CH_NO_ACK(stih407_lpm, _reg, _bit)
+
+static const struct syscfg_reset_channel_data stih407_softresets[] = {
+       [STIH407_ETH1_SOFTRESET] = STIH407_SRST_SBC(SYSCFG_4002, 4),
+       [STIH407_MMC1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 3),
+       [STIH407_USB2_PORT0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 28),
+       [STIH407_USB2_PORT1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 29),
+       [STIH407_PICOPHY_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 30),
+       [STIH407_IRB_SOFTRESET] = STIH407_SRST_LPM(LPM_SYSCFG_1, 6),
+       [STIH407_PCIE0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 6),
+       [STIH407_PCIE1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 15),
+       [STIH407_SATA0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 7),
+       [STIH407_SATA1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 16),
+       [STIH407_MIPHY0_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 4),
+       [STIH407_MIPHY1_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 13),
+       [STIH407_MIPHY2_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 22),
+       [STIH407_SATA0_PWR_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 5),
+       [STIH407_SATA1_PWR_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 14),
+       [STIH407_DELTA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 3),
+       [STIH407_BLITTER_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 10),
+       [STIH407_HDTVOUT_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 11),
+       [STIH407_HDQVDP_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 12),
+       [STIH407_VDP_AUX_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 14),
+       [STIH407_COMPO_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 15),
+       [STIH407_HDMI_TX_PHY_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 21),
+       [STIH407_JPEG_DEC_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 23),
+       [STIH407_VP8_DEC_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 24),
+       [STIH407_GPU_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5131, 30),
+       [STIH407_HVA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 0),
+       [STIH407_ERAM_HVA_SOFTRESET] = STIH407_SRST_CORE(SYSCFG_5132, 1),
+       [STIH407_LPM_SOFTRESET] = STIH407_SRST_SBC(SYSCFG_4002, 2),
+       [STIH407_KEYSCAN_SOFTRESET] = STIH407_SRST_LPM(LPM_SYSCFG_1, 8),
+};
+
+/* PicoPHY reset/control */
+#define SYSCFG_5061    0x0f4
+
+static const struct syscfg_reset_channel_data stih407_picophyresets[] = {
+       [STIH407_PICOPHY0_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 5),
+       [STIH407_PICOPHY1_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 6),
+       [STIH407_PICOPHY2_RESET] = STIH407_SRST_CORE(SYSCFG_5061, 7),
+};
+
+static const struct syscfg_reset_controller_data stih407_powerdown_controller = {
+       .wait_for_ack = true,
+       .nr_channels = ARRAY_SIZE(stih407_powerdowns),
+       .channels = stih407_powerdowns,
+};
+
+static const struct syscfg_reset_controller_data stih407_softreset_controller = {
+       .wait_for_ack = false,
+       .active_low = true,
+       .nr_channels = ARRAY_SIZE(stih407_softresets),
+       .channels = stih407_softresets,
+};
+
+static const struct syscfg_reset_controller_data stih407_picophyreset_controller = {
+       .wait_for_ack = false,
+       .nr_channels = ARRAY_SIZE(stih407_picophyresets),
+       .channels = stih407_picophyresets,
+};
+
+static struct of_device_id stih407_reset_match[] = {
+       {
+               .compatible = "st,stih407-powerdown",
+               .data = &stih407_powerdown_controller,
+       },
+       {
+               .compatible = "st,stih407-softreset",
+               .data = &stih407_softreset_controller,
+       },
+       {
+               .compatible = "st,stih407-picophyreset",
+               .data = &stih407_picophyreset_controller,
+       },
+       { /* sentinel */ },
+};
+
+static struct platform_driver stih407_reset_driver = {
+       .probe = syscfg_reset_probe,
+       .driver = {
+               .name = "reset-stih407",
+               .of_match_table = stih407_reset_match,
+       },
+};
+
+static int __init stih407_reset_init(void)
+{
+       return platform_driver_register(&stih407_reset_driver);
+}
+
+arch_initcall(stih407_reset_init);
index 8cd0beebdc3f0464670893eec27222b5d11c8b69..b682651b5307b7f7c908052557da9c57300339df 100644 (file)
@@ -830,7 +830,7 @@ config RTC_DRV_DA9063
 
 config RTC_DRV_EFI
        tristate "EFI RTC"
-       depends on EFI
+       depends on EFI && !X86
        help
          If you say yes here you will get support for the EFI
          Real Time Clock.
@@ -1109,36 +1109,42 @@ config RTC_DRV_AT91RM9200
          this is powered by the backup power supply.
 
 config RTC_DRV_AT91SAM9
-       tristate "AT91SAM9x/AT91CAP9 RTT as RTC"
-       depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40)
+       tristate "AT91SAM9 RTT as RTC"
+       depends on ARCH_AT91
+       select MFD_SYSCON
        help
-         RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT
-         (Real Time Timer). These timers are powered by the backup power
-         supply (such as a small coin cell battery), but do not need to
-         be used as RTCs.
-
-         (On AT91SAM9rl and AT91SAM9G45 chips you probably want to use the
-         dedicated RTC module and leave the RTT available for other uses.)
+         Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which
+         can be used as an RTC thanks to the backup power supply (e.g. a
+         small coin cell battery) which keeps this block and the GPBR
+         (General Purpose Backup Registers) block powered when the device
+         is shutdown.
+         Some AT91SAM9 SoCs provide a real RTC block, on those ones you'd
+         probably want to use the real RTC block instead of the "RTT as an
+         RTC" driver.
 
 config RTC_DRV_AT91SAM9_RTT
        int
        range 0 1
        default 0
-       prompt "RTT module Number" if ARCH_AT91SAM9263
        depends on RTC_DRV_AT91SAM9
        help
+         This option is only relevant for legacy board support and
+         won't be used when booting a DT board.
+
          More than one RTT module is available. You can choose which
          one will be used as an RTC. The default of zero is normally
          OK to use, though some systems use that for non-RTC purposes.
 
 config RTC_DRV_AT91SAM9_GPBR
        int
-       range 0 3 if !ARCH_AT91SAM9263
-       range 0 15 if ARCH_AT91SAM9263
+       range 0 3
        default 0
        prompt "Backup Register Number"
        depends on RTC_DRV_AT91SAM9
        help
+         This option is only relevant for legacy board support and
+         won't be used when booting a DT board.
+
          The RTC driver needs to use one of the General Purpose Backup
          Registers (GPBRs) as well as the RTT. You can choose which one
          will be used. The default of zero is normally OK to use, but
@@ -1320,7 +1326,7 @@ config RTC_DRV_LPC32XX
 
 config RTC_DRV_PM8XXX
        tristate "Qualcomm PMIC8XXX RTC"
-       depends on MFD_PM8XXX
+       depends on MFD_PM8XXX || MFD_SPMI_PMIC
        help
          If you say yes here you get support for the
          Qualcomm PMIC8XXX RTC.
index 38e26be705be5f2c6ac37034d705639da8d3830d..472a5adc4642790d2ff1df9eab73aaaf2c4b064d 100644 (file)
@@ -45,14 +45,14 @@ int rtc_hctosys_ret = -ENODEV;
  * system's wall clock; restore it on resume().
  */
 
-static struct timespec old_rtc, old_system, old_delta;
+static struct timespec64 old_rtc, old_system, old_delta;
 
 
 static int rtc_suspend(struct device *dev)
 {
        struct rtc_device       *rtc = to_rtc_device(dev);
        struct rtc_time         tm;
-       struct timespec         delta, delta_delta;
+       struct timespec64       delta, delta_delta;
        int err;
 
        if (has_persistent_clock())
@@ -68,8 +68,8 @@ static int rtc_suspend(struct device *dev)
                return 0;
        }
 
-       getnstimeofday(&old_system);
-       rtc_tm_to_time(&tm, &old_rtc.tv_sec);
+       getnstimeofday64(&old_system);
+       old_rtc.tv_sec = rtc_tm_to_time64(&tm);
 
 
        /*
@@ -78,8 +78,8 @@ static int rtc_suspend(struct device *dev)
         * try to compensate so the difference in system time
         * and rtc time stays close to constant.
         */
-       delta = timespec_sub(old_system, old_rtc);
-       delta_delta = timespec_sub(delta, old_delta);
+       delta = timespec64_sub(old_system, old_rtc);
+       delta_delta = timespec64_sub(delta, old_delta);
        if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) {
                /*
                 * if delta_delta is too large, assume time correction
@@ -88,7 +88,7 @@ static int rtc_suspend(struct device *dev)
                old_delta = delta;
        } else {
                /* Otherwise try to adjust old_system to compensate */
-               old_system = timespec_sub(old_system, delta_delta);
+               old_system = timespec64_sub(old_system, delta_delta);
        }
 
        return 0;
@@ -98,8 +98,8 @@ static int rtc_resume(struct device *dev)
 {
        struct rtc_device       *rtc = to_rtc_device(dev);
        struct rtc_time         tm;
-       struct timespec         new_system, new_rtc;
-       struct timespec         sleep_time;
+       struct timespec64       new_system, new_rtc;
+       struct timespec64       sleep_time;
        int err;
 
        if (has_persistent_clock())
@@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev)
                return 0;
 
        /* snapshot the current rtc and system time at resume */
-       getnstimeofday(&new_system);
+       getnstimeofday64(&new_system);
        err = rtc_read_time(rtc, &tm);
        if (err < 0) {
                pr_debug("%s:  fail to read rtc time\n", dev_name(&rtc->dev));
@@ -121,7 +121,7 @@ static int rtc_resume(struct device *dev)
                pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));
                return 0;
        }
-       rtc_tm_to_time(&tm, &new_rtc.tv_sec);
+       new_rtc.tv_sec = rtc_tm_to_time64(&tm);
        new_rtc.tv_nsec = 0;
 
        if (new_rtc.tv_sec < old_rtc.tv_sec) {
@@ -130,7 +130,7 @@ static int rtc_resume(struct device *dev)
        }
 
        /* calculate the RTC time delta (sleep time)*/
-       sleep_time = timespec_sub(new_rtc, old_rtc);
+       sleep_time = timespec64_sub(new_rtc, old_rtc);
 
        /*
         * Since these RTC suspend/resume handlers are not called
@@ -139,11 +139,11 @@ static int rtc_resume(struct device *dev)
         * so subtract kernel run-time between rtc_suspend to rtc_resume
         * to keep things accurate.
         */
-       sleep_time = timespec_sub(sleep_time,
-                       timespec_sub(new_system, old_system));
+       sleep_time = timespec64_sub(sleep_time,
+                       timespec64_sub(new_system, old_system));
 
        if (sleep_time.tv_sec >= 0)
-               timekeeping_inject_sleeptime(&sleep_time);
+               timekeeping_inject_sleeptime64(&sleep_time);
        rtc_hctosys_ret = 0;
        return 0;
 }
index 59637430453226c0a7526c44bdba2a3b529030e6..abac38abd38e58b1ff958169c1eb2109e412814c 100644 (file)
 #include <linux/slab.h>
 #include <linux/platform_data/atmel.h>
 #include <linux/io.h>
-
-#include <mach/at91_rtt.h>
-#include <mach/cpu.h>
-#include <mach/hardware.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/clk.h>
 
 /*
  * This driver uses two configurable hardware resources that live in the
  * registers available, likewise usable for more than "RTC" support.
  */
 
+#define AT91_RTT_MR            0x00                    /* Real-time Mode Register */
+#define AT91_RTT_RTPRES                (0xffff << 0)           /* Real-time Timer Prescaler Value */
+#define AT91_RTT_ALMIEN                (1 << 16)               /* Alarm Interrupt Enable */
+#define AT91_RTT_RTTINCIEN     (1 << 17)               /* Real Time Timer Increment Interrupt Enable */
+#define AT91_RTT_RTTRST                (1 << 18)               /* Real Time Timer Restart */
+
+#define AT91_RTT_AR            0x04                    /* Real-time Alarm Register */
+#define AT91_RTT_ALMV          (0xffffffff)            /* Alarm Value */
+
+#define AT91_RTT_VR            0x08                    /* Real-time Value Register */
+#define AT91_RTT_CRTV          (0xffffffff)            /* Current Real-time Value */
+
+#define AT91_RTT_SR            0x0c                    /* Real-time Status Register */
+#define AT91_RTT_ALMS          (1 << 0)                /* Real-time Alarm Status */
+#define AT91_RTT_RTTINC                (1 << 1)                /* Real-time Timer Increment */
+
 /*
  * We store ALARM_DISABLED in ALMV to record that no alarm is set.
  * It's also the reset value for that field.
@@ -58,19 +73,30 @@ struct sam9_rtc {
        void __iomem            *rtt;
        struct rtc_device       *rtcdev;
        u32                     imr;
-       void __iomem            *gpbr;
+       struct regmap           *gpbr;
+       unsigned int            gpbr_offset;
        int                     irq;
+       struct clk              *sclk;
 };
 
 #define rtt_readl(rtc, field) \
-       __raw_readl((rtc)->rtt + AT91_RTT_ ## field)
+       readl((rtc)->rtt + AT91_RTT_ ## field)
 #define rtt_writel(rtc, field, val) \
-       __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field)
+       writel((val), (rtc)->rtt + AT91_RTT_ ## field)
+
+static inline unsigned int gpbr_readl(struct sam9_rtc *rtc)
+{
+       unsigned int val;
+
+       regmap_read(rtc->gpbr, rtc->gpbr_offset, &val);
 
-#define gpbr_readl(rtc) \
-       __raw_readl((rtc)->gpbr)
-#define gpbr_writel(rtc, val) \
-       __raw_writel((val), (rtc)->gpbr)
+       return val;
+}
+
+static inline void gpbr_writel(struct sam9_rtc *rtc, unsigned int val)
+{
+       regmap_write(rtc->gpbr, rtc->gpbr_offset, val);
+}
 
 /*
  * Read current time and date in RTC
@@ -287,22 +313,22 @@ static const struct rtc_class_ops at91_rtc_ops = {
        .alarm_irq_enable = at91_rtc_alarm_irq_enable,
 };
 
+static struct regmap_config gpbr_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+};
+
 /*
  * Initialize and install RTC driver
  */
 static int at91_rtc_probe(struct platform_device *pdev)
 {
-       struct resource *r, *r_gpbr;
+       struct resource *r;
        struct sam9_rtc *rtc;
        int             ret, irq;
        u32             mr;
-
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       r_gpbr = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!r || !r_gpbr) {
-               dev_err(&pdev->dev, "need 2 ressources\n");
-               return -ENODEV;
-       }
+       unsigned int    sclk_rate;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -321,24 +347,66 @@ static int at91_rtc_probe(struct platform_device *pdev)
                device_init_wakeup(&pdev->dev, 1);
 
        platform_set_drvdata(pdev, rtc);
-       rtc->rtt = devm_ioremap(&pdev->dev, r->start, resource_size(r));
-       if (!rtc->rtt) {
-               dev_err(&pdev->dev, "failed to map registers, aborting.\n");
-               return -ENOMEM;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       rtc->rtt = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(rtc->rtt))
+               return PTR_ERR(rtc->rtt);
+
+       if (!pdev->dev.of_node) {
+               /*
+                * TODO: Remove this code chunk when removing non DT board
+                * support. Remember to remove the gpbr_regmap_config
+                * variable too.
+                */
+               void __iomem *gpbr;
+
+               r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               gpbr = devm_ioremap_resource(&pdev->dev, r);
+               if (IS_ERR(gpbr))
+                       return PTR_ERR(gpbr);
+
+               rtc->gpbr = regmap_init_mmio(NULL, gpbr,
+                                            &gpbr_regmap_config);
+       } else {
+               struct of_phandle_args args;
+
+               ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
+                                               "atmel,rtt-rtc-time-reg", 1, 0,
+                                               &args);
+               if (ret)
+                       return ret;
+
+               rtc->gpbr = syscon_node_to_regmap(args.np);
+               rtc->gpbr_offset = args.args[0];
        }
 
-       rtc->gpbr = devm_ioremap(&pdev->dev, r_gpbr->start,
-                               resource_size(r_gpbr));
-       if (!rtc->gpbr) {
-               dev_err(&pdev->dev, "failed to map gpbr registers, aborting.\n");
+       if (IS_ERR(rtc->gpbr)) {
+               dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n");
                return -ENOMEM;
        }
 
+       rtc->sclk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(rtc->sclk))
+               return PTR_ERR(rtc->sclk);
+
+       sclk_rate = clk_get_rate(rtc->sclk);
+       if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) {
+               dev_err(&pdev->dev, "Invalid slow clock rate\n");
+               return -EINVAL;
+       }
+
+       ret = clk_prepare_enable(rtc->sclk);
+       if (ret) {
+               dev_err(&pdev->dev, "Could not enable slow clock\n");
+               return ret;
+       }
+
        mr = rtt_readl(rtc, MR);
 
        /* unless RTT is counting at 1 Hz, re-initialize it */
-       if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) {
-               mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES);
+       if ((mr & AT91_RTT_RTPRES) != sclk_rate) {
+               mr = AT91_RTT_RTTRST | (sclk_rate & AT91_RTT_RTPRES);
                gpbr_writel(rtc, 0);
        }
 
@@ -383,6 +451,9 @@ static int at91_rtc_remove(struct platform_device *pdev)
        /* disable all interrupts */
        rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
 
+       if (!IS_ERR(rtc->sclk))
+               clk_disable_unprepare(rtc->sclk);
+
        return 0;
 }
 
@@ -440,6 +511,14 @@ static int at91_rtc_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);
 
+#ifdef CONFIG_OF
+static const struct of_device_id at91_rtc_dt_ids[] = {
+       { .compatible = "atmel,at91sam9260-rtt" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
+#endif
+
 static struct platform_driver at91_rtc_driver = {
        .probe          = at91_rtc_probe,
        .remove         = at91_rtc_remove,
@@ -448,6 +527,7 @@ static struct platform_driver at91_rtc_driver = {
                .name   = "rtc-at91sam9",
                .owner  = THIS_MODULE,
                .pm     = &at91_rtc_pm_ops,
+               .of_match_table = of_match_ptr(at91_rtc_dt_ids),
        },
 };
 
index 314129e66d6e8fd47280202cacf19f0793848e58..92679df6d6e222dd12e4f2471f9e1b3109048c50 100644 (file)
@@ -160,7 +160,7 @@ static int trickle_charger_of_init(struct device *dev, struct device_node *node)
                        dev_err(dev, "bq32k: diode and resistor mismatch\n");
                        return -EINVAL;
                }
-               reg = 0x25;
+               reg = 0x45;
                break;
 
        default:
index c384fec6d173b2f051c2871e78fb0128ac65782c..53b589dc34ebe7a7ee6a6466322515b8f62a1f10 100644 (file)
@@ -236,3 +236,4 @@ MODULE_ALIAS("platform:rtc-efi");
 MODULE_AUTHOR("dann frazier <dannf@hp.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("EFI RTC driver");
+MODULE_ALIAS("platform:rtc-efi");
index c4cf05731118a245cff79181ba81eac90ca92be6..e6bfb9c42a10b08948910345e34f1b3b83057e82 100644 (file)
@@ -45,16 +45,20 @@ int rtc_year_days(unsigned int day, unsigned int month, unsigned int year)
 }
 EXPORT_SYMBOL(rtc_year_days);
 
+
 /*
+ * rtc_time_to_tm64 - Converts time64_t to rtc_time.
  * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
  */
-void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
+void rtc_time64_to_tm(time64_t time, struct rtc_time *tm)
 {
        unsigned int month, year;
+       unsigned long secs;
        int days;
 
-       days = time / 86400;
-       time -= (unsigned int) days * 86400;
+       /* time must be positive */
+       days = div_s64(time, 86400);
+       secs = time - (unsigned int) days * 86400;
 
        /* day of the week, 1970-01-01 was a Thursday */
        tm->tm_wday = (days + 4) % 7;
@@ -81,14 +85,14 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
        tm->tm_mon = month;
        tm->tm_mday = days + 1;
 
-       tm->tm_hour = time / 3600;
-       time -= tm->tm_hour * 3600;
-       tm->tm_min = time / 60;
-       tm->tm_sec = time - tm->tm_min * 60;
+       tm->tm_hour = secs / 3600;
+       secs -= tm->tm_hour * 3600;
+       tm->tm_min = secs / 60;
+       tm->tm_sec = secs - tm->tm_min * 60;
 
        tm->tm_isdst = 0;
 }
-EXPORT_SYMBOL(rtc_time_to_tm);
+EXPORT_SYMBOL(rtc_time64_to_tm);
 
 /*
  * Does the rtc_time represent a valid date/time?
@@ -109,24 +113,22 @@ int rtc_valid_tm(struct rtc_time *tm)
 EXPORT_SYMBOL(rtc_valid_tm);
 
 /*
+ * rtc_tm_to_time64 - Converts rtc_time to time64_t.
  * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
  */
-int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+time64_t rtc_tm_to_time64(struct rtc_time *tm)
 {
-       *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+       return mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                        tm->tm_hour, tm->tm_min, tm->tm_sec);
-       return 0;
 }
-EXPORT_SYMBOL(rtc_tm_to_time);
+EXPORT_SYMBOL(rtc_tm_to_time64);
 
 /*
  * Convert rtc_time to ktime
  */
 ktime_t rtc_tm_to_ktime(struct rtc_time tm)
 {
-       time_t time;
-       rtc_tm_to_time(&tm, &time);
-       return ktime_set(time, 0);
+       return ktime_set(rtc_tm_to_time64(&tm), 0);
 }
 EXPORT_SYMBOL_GPL(rtc_tm_to_ktime);
 
@@ -135,14 +137,14 @@ EXPORT_SYMBOL_GPL(rtc_tm_to_ktime);
  */
 struct rtc_time rtc_ktime_to_tm(ktime_t kt)
 {
-       struct timespec ts;
+       struct timespec64 ts;
        struct rtc_time ret;
 
-       ts = ktime_to_timespec(kt);
+       ts = ktime_to_timespec64(kt);
        /* Round up any ns */
        if (ts.tv_nsec)
                ts.tv_sec++;
-       rtc_time_to_tm(ts.tv_sec, &ret);
+       rtc_time64_to_tm(ts.tv_sec, &ret);
        return ret;
 }
 EXPORT_SYMBOL_GPL(rtc_ktime_to_tm);
index 197699f358c7c18456d9ff7ab8130700001507a7..5adcf111fc1409ac12cd35869cad76cf58c93d1d 100644 (file)
 
 /* RTC_CTRL register bit fields */
 #define PM8xxx_RTC_ENABLE              BIT(7)
-#define PM8xxx_RTC_ALARM_ENABLE                BIT(1)
 #define PM8xxx_RTC_ALARM_CLEAR         BIT(0)
 
 #define NUM_8_BIT_RTC_REGS             0x4
 
+/**
+ * struct pm8xxx_rtc_regs - describe RTC registers per PMIC versions
+ * @ctrl: base address of control register
+ * @write: base address of write register
+ * @read: base address of read register
+ * @alarm_ctrl: base address of alarm control register
+ * @alarm_ctrl2: base address of alarm control2 register
+ * @alarm_rw: base address of alarm read-write register
+ * @alarm_en: alarm enable mask
+ */
+struct pm8xxx_rtc_regs {
+       unsigned int ctrl;
+       unsigned int write;
+       unsigned int read;
+       unsigned int alarm_ctrl;
+       unsigned int alarm_ctrl2;
+       unsigned int alarm_rw;
+       unsigned int alarm_en;
+};
+
 /**
  * struct pm8xxx_rtc -  rtc driver internal structure
  * @rtc:               rtc device for this driver.
  * @regmap:            regmap used to access RTC registers
  * @allow_set_time:    indicates whether writing to the RTC is allowed
  * @rtc_alarm_irq:     rtc alarm irq number.
- * @rtc_base:          address of rtc control register.
- * @rtc_read_base:     base address of read registers.
- * @rtc_write_base:    base address of write registers.
- * @alarm_rw_base:     base address of alarm registers.
  * @ctrl_reg:          rtc control register.
  * @rtc_dev:           device structure.
  * @ctrl_reg_lock:     spinlock protecting access to ctrl_reg.
@@ -51,11 +66,7 @@ struct pm8xxx_rtc {
        struct regmap *regmap;
        bool allow_set_time;
        int rtc_alarm_irq;
-       int rtc_base;
-       int rtc_read_base;
-       int rtc_write_base;
-       int alarm_rw_base;
-       u8 ctrl_reg;
+       const struct pm8xxx_rtc_regs *regs;
        struct device *rtc_dev;
        spinlock_t ctrl_reg_lock;
 };
@@ -71,8 +82,10 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        int rc, i;
        unsigned long secs, irq_flags;
-       u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, ctrl_reg;
+       u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0;
+       unsigned int ctrl_reg;
        struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+       const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
 
        if (!rtc_dd->allow_set_time)
                return -EACCES;
@@ -87,30 +100,30 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
        dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
 
        spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
-       ctrl_reg = rtc_dd->ctrl_reg;
 
-       if (ctrl_reg & PM8xxx_RTC_ALARM_ENABLE) {
+       rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg);
+       if (rc)
+               goto rtc_rw_fail;
+
+       if (ctrl_reg & regs->alarm_en) {
                alarm_enabled = 1;
-               ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
-               rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_base, ctrl_reg);
+               ctrl_reg &= ~regs->alarm_en;
+               rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
                if (rc) {
                        dev_err(dev, "Write to RTC control register failed\n");
                        goto rtc_rw_fail;
                }
-               rtc_dd->ctrl_reg = ctrl_reg;
-       } else {
-               spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
        }
 
        /* Write 0 to Byte[0] */
-       rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_write_base, 0);
+       rc = regmap_write(rtc_dd->regmap, regs->write, 0);
        if (rc) {
                dev_err(dev, "Write to RTC write data register failed\n");
                goto rtc_rw_fail;
        }
 
        /* Write Byte[1], Byte[2], Byte[3] */
-       rc = regmap_bulk_write(rtc_dd->regmap, rtc_dd->rtc_write_base + 1,
+       rc = regmap_bulk_write(rtc_dd->regmap, regs->write + 1,
                               &value[1], sizeof(value) - 1);
        if (rc) {
                dev_err(dev, "Write to RTC write data register failed\n");
@@ -118,25 +131,23 @@ static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
        }
 
        /* Write Byte[0] */
-       rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_write_base, value[0]);
+       rc = regmap_write(rtc_dd->regmap, regs->write, value[0]);
        if (rc) {
                dev_err(dev, "Write to RTC write data register failed\n");
                goto rtc_rw_fail;
        }
 
        if (alarm_enabled) {
-               ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE;
-               rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_base, ctrl_reg);
+               ctrl_reg |= regs->alarm_en;
+               rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
                if (rc) {
                        dev_err(dev, "Write to RTC control register failed\n");
                        goto rtc_rw_fail;
                }
-               rtc_dd->ctrl_reg = ctrl_reg;
        }
 
 rtc_rw_fail:
-       if (alarm_enabled)
-               spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+       spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
 
        return rc;
 }
@@ -148,9 +159,9 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
        unsigned long secs;
        unsigned int reg;
        struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+       const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
 
-       rc = regmap_bulk_read(rtc_dd->regmap, rtc_dd->rtc_read_base,
-                             value, sizeof(value));
+       rc = regmap_bulk_read(rtc_dd->regmap, regs->read, value, sizeof(value));
        if (rc) {
                dev_err(dev, "RTC read data register failed\n");
                return rc;
@@ -160,14 +171,14 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
         * Read the LSB again and check if there has been a carry over.
         * If there is, redo the read operation.
         */
-       rc = regmap_read(rtc_dd->regmap, rtc_dd->rtc_read_base, &reg);
+       rc = regmap_read(rtc_dd->regmap, regs->read, &reg);
        if (rc < 0) {
                dev_err(dev, "RTC read data register failed\n");
                return rc;
        }
 
        if (unlikely(reg < value[0])) {
-               rc = regmap_bulk_read(rtc_dd->regmap, rtc_dd->rtc_read_base,
+               rc = regmap_bulk_read(rtc_dd->regmap, regs->read,
                                      value, sizeof(value));
                if (rc) {
                        dev_err(dev, "RTC read data register failed\n");
@@ -195,9 +206,11 @@ static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
        int rc, i;
-       u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg;
+       u8 value[NUM_8_BIT_RTC_REGS];
+       unsigned int ctrl_reg;
        unsigned long secs, irq_flags;
        struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+       const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
 
        rtc_tm_to_time(&alarm->time, &secs);
 
@@ -208,28 +221,28 @@ static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 
        spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 
-       rc = regmap_bulk_write(rtc_dd->regmap, rtc_dd->alarm_rw_base, value,
+       rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value,
                               sizeof(value));
        if (rc) {
                dev_err(dev, "Write to RTC ALARM register failed\n");
                goto rtc_rw_fail;
        }
 
-       ctrl_reg = rtc_dd->ctrl_reg;
+       rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
+       if (rc)
+               goto rtc_rw_fail;
 
        if (alarm->enabled)
-               ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE;
+               ctrl_reg |= regs->alarm_en;
        else
-               ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+               ctrl_reg &= ~regs->alarm_en;
 
-       rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_base, ctrl_reg);
+       rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
        if (rc) {
-               dev_err(dev, "Write to RTC control register failed\n");
+               dev_err(dev, "Write to RTC alarm control register failed\n");
                goto rtc_rw_fail;
        }
 
-       rtc_dd->ctrl_reg = ctrl_reg;
-
        dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
                alarm->time.tm_hour, alarm->time.tm_min,
                alarm->time.tm_sec, alarm->time.tm_mday,
@@ -245,8 +258,9 @@ static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        u8 value[NUM_8_BIT_RTC_REGS];
        unsigned long secs;
        struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+       const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
 
-       rc = regmap_bulk_read(rtc_dd->regmap, rtc_dd->alarm_rw_base, value,
+       rc = regmap_bulk_read(rtc_dd->regmap, regs->alarm_rw, value,
                              sizeof(value));
        if (rc) {
                dev_err(dev, "RTC alarm time read failed\n");
@@ -276,25 +290,26 @@ static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
        int rc;
        unsigned long irq_flags;
        struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
-       u8 ctrl_reg;
+       const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
+       unsigned int ctrl_reg;
 
        spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 
-       ctrl_reg = rtc_dd->ctrl_reg;
+       rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
+       if (rc)
+               goto rtc_rw_fail;
 
        if (enable)
-               ctrl_reg |= PM8xxx_RTC_ALARM_ENABLE;
+               ctrl_reg |= regs->alarm_en;
        else
-               ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+               ctrl_reg &= ~regs->alarm_en;
 
-       rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_base, ctrl_reg);
+       rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
        if (rc) {
                dev_err(dev, "Write to RTC control register failed\n");
                goto rtc_rw_fail;
        }
 
-       rtc_dd->ctrl_reg = ctrl_reg;
-
 rtc_rw_fail:
        spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
        return rc;
@@ -311,6 +326,7 @@ static const struct rtc_class_ops pm8xxx_rtc_ops = {
 static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id)
 {
        struct pm8xxx_rtc *rtc_dd = dev_id;
+       const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
        unsigned int ctrl_reg;
        int rc;
        unsigned long irq_flags;
@@ -320,48 +336,100 @@ static irqreturn_t pm8xxx_alarm_trigger(int irq, void *dev_id)
        spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 
        /* Clear the alarm enable bit */
-       ctrl_reg = rtc_dd->ctrl_reg;
-       ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+       rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
+       if (rc) {
+               spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+               goto rtc_alarm_handled;
+       }
+
+       ctrl_reg &= ~regs->alarm_en;
 
-       rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_base, ctrl_reg);
+       rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
        if (rc) {
                spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
                dev_err(rtc_dd->rtc_dev,
-                       "Write to RTC control register failed\n");
+                       "Write to alarm control register failed\n");
                goto rtc_alarm_handled;
        }
 
-       rtc_dd->ctrl_reg = ctrl_reg;
        spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
 
        /* Clear RTC alarm register */
-       rc = regmap_read(rtc_dd->regmap,
-                        rtc_dd->rtc_base + PM8XXX_ALARM_CTRL_OFFSET,
-                        &ctrl_reg);
+       rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl2, &ctrl_reg);
        if (rc) {
                dev_err(rtc_dd->rtc_dev,
-                       "RTC Alarm control register read failed\n");
+                       "RTC Alarm control2 register read failed\n");
                goto rtc_alarm_handled;
        }
 
-       ctrl_reg &= ~PM8xxx_RTC_ALARM_CLEAR;
-       rc = regmap_write(rtc_dd->regmap,
-                         rtc_dd->rtc_base + PM8XXX_ALARM_CTRL_OFFSET,
-                         ctrl_reg);
+       ctrl_reg |= PM8xxx_RTC_ALARM_CLEAR;
+       rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl2, ctrl_reg);
        if (rc)
                dev_err(rtc_dd->rtc_dev,
-                       "Write to RTC Alarm control register failed\n");
+                       "Write to RTC Alarm control2 register failed\n");
 
 rtc_alarm_handled:
        return IRQ_HANDLED;
 }
 
+static int pm8xxx_rtc_enable(struct pm8xxx_rtc *rtc_dd)
+{
+       const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
+       unsigned int ctrl_reg;
+       int rc;
+
+       /* Check if the RTC is on, else turn it on */
+       rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg);
+       if (rc)
+               return rc;
+
+       if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) {
+               ctrl_reg |= PM8xxx_RTC_ENABLE;
+               rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static const struct pm8xxx_rtc_regs pm8921_regs = {
+       .ctrl           = 0x11d,
+       .write          = 0x11f,
+       .read           = 0x123,
+       .alarm_rw       = 0x127,
+       .alarm_ctrl     = 0x11d,
+       .alarm_ctrl2    = 0x11e,
+       .alarm_en       = BIT(1),
+};
+
+static const struct pm8xxx_rtc_regs pm8058_regs = {
+       .ctrl           = 0x1e8,
+       .write          = 0x1ea,
+       .read           = 0x1ee,
+       .alarm_rw       = 0x1f2,
+       .alarm_ctrl     = 0x1e8,
+       .alarm_ctrl2    = 0x1e9,
+       .alarm_en       = BIT(1),
+};
+
+static const struct pm8xxx_rtc_regs pm8941_regs = {
+       .ctrl           = 0x6046,
+       .write          = 0x6040,
+       .read           = 0x6048,
+       .alarm_rw       = 0x6140,
+       .alarm_ctrl     = 0x6146,
+       .alarm_ctrl2    = 0x6148,
+       .alarm_en       = BIT(7),
+};
+
 /*
  * Hardcoded RTC bases until IORESOURCE_REG mapping is figured out
  */
 static const struct of_device_id pm8xxx_id_table[] = {
-       { .compatible = "qcom,pm8921-rtc", .data = (void *) 0x11D },
-       { .compatible = "qcom,pm8058-rtc", .data = (void *) 0x1E8 },
+       { .compatible = "qcom,pm8921-rtc", .data = &pm8921_regs },
+       { .compatible = "qcom,pm8058-rtc", .data = &pm8058_regs },
+       { .compatible = "qcom,pm8941-rtc", .data = &pm8941_regs },
        { },
 };
 MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
@@ -369,7 +437,6 @@ MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
 static int pm8xxx_rtc_probe(struct platform_device *pdev)
 {
        int rc;
-       unsigned int ctrl_reg;
        struct pm8xxx_rtc *rtc_dd;
        const struct of_device_id *match;
 
@@ -399,33 +466,12 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
        rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node,
                                                      "allow-set-time");
 
-       rtc_dd->rtc_base = (long) match->data;
-
-       /* Setup RTC register addresses */
-       rtc_dd->rtc_write_base = rtc_dd->rtc_base + PM8XXX_RTC_WRITE_OFFSET;
-       rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET;
-       rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET;
-
+       rtc_dd->regs = match->data;
        rtc_dd->rtc_dev = &pdev->dev;
 
-       /* Check if the RTC is on, else turn it on */
-       rc = regmap_read(rtc_dd->regmap, rtc_dd->rtc_base, &ctrl_reg);
-       if (rc) {
-               dev_err(&pdev->dev, "RTC control register read failed!\n");
+       rc = pm8xxx_rtc_enable(rtc_dd);
+       if (rc)
                return rc;
-       }
-
-       if (!(ctrl_reg & PM8xxx_RTC_ENABLE)) {
-               ctrl_reg |= PM8xxx_RTC_ENABLE;
-               rc = regmap_write(rtc_dd->regmap, rtc_dd->rtc_base, ctrl_reg);
-               if (rc) {
-                       dev_err(&pdev->dev,
-                               "Write to RTC control register failed\n");
-                       return rc;
-               }
-       }
-
-       rtc_dd->ctrl_reg = ctrl_reg;
 
        platform_set_drvdata(pdev, rtc_dd);
 
index a6b1252c9941884a93dac49ed4c10c828ad0964d..806072238c00c4920e2eb344a651b8e604785b9f 100644 (file)
@@ -535,13 +535,15 @@ static int s3c_rtc_probe(struct platform_device *pdev)
        }
        clk_prepare_enable(info->rtc_clk);
 
-       info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
-       if (IS_ERR(info->rtc_src_clk)) {
-               dev_err(&pdev->dev, "failed to find rtc source clock\n");
-               return PTR_ERR(info->rtc_src_clk);
+       if (info->data->needs_src_clk) {
+               info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
+               if (IS_ERR(info->rtc_src_clk)) {
+                       dev_err(&pdev->dev,
+                               "failed to find rtc source clock\n");
+                       return PTR_ERR(info->rtc_src_clk);
+               }
+               clk_prepare_enable(info->rtc_src_clk);
        }
-       clk_prepare_enable(info->rtc_src_clk);
-
 
        /* check to see if everything is setup correctly */
        if (info->data->enable)
index dc24ecfac2d1600cb5cc4364a7e883c6d6368812..db2cb1f8a1b500f4166e1c5e110d81ae6b2b4ed8 100644 (file)
@@ -105,7 +105,7 @@ config SCLP_ASYNC
 config HMC_DRV
        def_tristate m
        prompt "Support for file transfers from HMC drive CD/DVD-ROM"
-       depends on 64BIT
+       depends on S390 && 64BIT
        select CRC16
        help
          This option enables support for file transfers from a Hardware
index 6cbe6ef3c889d14841e2c73aa848fa9f563b68ec..bda52f18e9670aefe1a7757209fdf038c866ad5a 100644 (file)
@@ -888,7 +888,6 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
        struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
        int i;
        struct virtqueue *vq;
-       struct virtio_driver *drv;
 
        if (!vcdev)
                return;
index 8004b071a9f2e59f5cb9bbe90993ff7b108f973c..01a73395a0171f4bd182fb45968fe0e0a76ea43a 100644 (file)
@@ -353,9 +353,11 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
        adapter->ccw_device = ccw_device;
 
        INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
-       INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
+       INIT_DELAYED_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
        INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
 
+       adapter->next_port_scan = jiffies;
+
        if (zfcp_qdio_setup(adapter))
                goto failed;
 
@@ -420,7 +422,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
 {
        struct ccw_device *cdev = adapter->ccw_device;
 
-       cancel_work_sync(&adapter->scan_work);
+       cancel_delayed_work_sync(&adapter->scan_work);
        cancel_work_sync(&adapter->stat_work);
        cancel_work_sync(&adapter->ns_up_work);
        zfcp_destroy_adapter_work_queue(adapter);
index f9879d400d0e609cb901e88587347d19b06bd453..54c7b48fdb4640167ee842ab3ef0f5149e656524 100644 (file)
@@ -56,8 +56,22 @@ static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
        zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
        zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
                                tag);
+
+       /*
+        * We want to scan ports here, with some random backoff and without
+        * rate limit. Recovery has already scheduled a port scan for us,
+        * but with both random delay and rate limit. Nevertheless we get
+        * what we want here by flushing the scheduled work after sleeping
+        * an equivalent random time.
+        * Let the port scan random delay elapse first. If recovery finishes
+        * up to that point in time, that would be perfect for both recovery
+        * and port scan. If not, i.e. recovery takes ages, there was no
+        * point in waiting a random delay on top of the time consumed by
+        * recovery.
+        */
+       msleep(zfcp_fc_port_scan_backoff());
        zfcp_erp_wait(adapter);
-       flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
+       flush_delayed_work(&adapter->scan_work);
 
        zfcp_ccw_adapter_put(adapter);
 
@@ -162,11 +176,19 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
        adapter->req_no = 0;
 
        zfcp_ccw_activate(cdev, 0, "ccsonl1");
-       /* scan for remote ports
-          either at the end of any successful adapter recovery
-          or only after the adapter recovery for setting a device online */
+
+       /*
+        * We want to scan ports here, always, with some random delay and
+        * without rate limit - basically what zfcp_ccw_activate() has
+        * achieved for us. Not quite! That port scan depended on
+        * !no_auto_port_rescan. So let's cover the no_auto_port_rescan
+        * case here to make sure a port scan is done unconditionally.
+        * Since zfcp_ccw_activate() has waited the desired random time,
+        * we can immediately schedule and flush a port scan for the
+        * remaining cases.
+        */
        zfcp_fc_inverse_conditional_port_scan(adapter);
-       flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
+       flush_delayed_work(&adapter->scan_work);
        zfcp_ccw_adapter_put(adapter);
        return 0;
 }
index d91173f326c5a51a71c19b150af1c3c0f64aa84b..b8e853e53546524bf5976e4af66345a7c25fe59a 100644 (file)
@@ -186,12 +186,13 @@ struct zfcp_adapter {
        struct fc_host_statistics *fc_stats;
        struct fsf_qtcb_bottom_port *stats_reset_data;
        unsigned long           stats_reset;
-       struct work_struct      scan_work;
+       struct delayed_work     scan_work;
        struct work_struct      ns_up_work;
        struct service_level    service_level;
        struct workqueue_struct *work_queue;
        struct device_dma_parameters dma_parms;
        struct zfcp_fc_events events;
+       unsigned long           next_port_scan;
 };
 
 struct zfcp_port {
index c82fe65c41286ae90af5d9d12452df32202e5504..2c5d4567d1da3d024a008112a5b4176ce9876e4d 100644 (file)
@@ -821,11 +821,6 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
        return ZFCP_ERP_CONTINUES;
 }
 
-static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
-{
-       atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &port->status);
-}
-
 static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
 {
        struct zfcp_port *port = erp_action->port;
@@ -833,7 +828,6 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
 
        switch (erp_action->step) {
        case ZFCP_ERP_STEP_UNINITIALIZED:
-               zfcp_erp_port_strategy_clearstati(port);
                if ((status & ZFCP_STATUS_PORT_PHYS_OPEN) &&
                    (status & ZFCP_STATUS_COMMON_OPEN))
                        return zfcp_erp_port_forced_strategy_close(erp_action);
@@ -933,7 +927,6 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
 
        switch (erp_action->step) {
        case ZFCP_ERP_STEP_UNINITIALIZED:
-               zfcp_erp_port_strategy_clearstati(port);
                if (p_status & ZFCP_STATUS_COMMON_OPEN)
                        return zfcp_erp_port_strategy_close(erp_action);
                break;
index a9c570a09b85595f9dc085e1016a66999fad7ea8..5b500652572b7c1395cc801c146f41535d310f31 100644 (file)
@@ -85,6 +85,7 @@ extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
 extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
 extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
 extern void zfcp_fc_sym_name_update(struct work_struct *);
+extern unsigned int zfcp_fc_port_scan_backoff(void);
 extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *);
 extern void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *);
 
index ca28e1c6611588a87ba0bd3272c36be6577f7875..25d49f32ca6380f52e27ab7b5e91334648558b56 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/utsname.h>
+#include <linux/random.h>
 #include <scsi/fc/fc_els.h>
 #include <scsi/libfc.h>
 #include "zfcp_ext.h"
@@ -31,12 +32,54 @@ module_param_named(no_auto_port_rescan, no_auto_port_rescan, bool, 0600);
 MODULE_PARM_DESC(no_auto_port_rescan,
                 "no automatic port_rescan (default off)");
 
+static unsigned int port_scan_backoff = 500;
+module_param(port_scan_backoff, uint, 0600);
+MODULE_PARM_DESC(port_scan_backoff,
+       "upper limit of port scan random backoff in msecs (default 500)");
+
+static unsigned int port_scan_ratelimit = 60000;
+module_param(port_scan_ratelimit, uint, 0600);
+MODULE_PARM_DESC(port_scan_ratelimit,
+       "minimum interval between port scans in msecs (default 60000)");
+
+unsigned int zfcp_fc_port_scan_backoff(void)
+{
+       if (!port_scan_backoff)
+               return 0;
+       return get_random_int() % port_scan_backoff;
+}
+
+static void zfcp_fc_port_scan_time(struct zfcp_adapter *adapter)
+{
+       unsigned long interval = msecs_to_jiffies(port_scan_ratelimit);
+       unsigned long backoff = msecs_to_jiffies(zfcp_fc_port_scan_backoff());
+
+       adapter->next_port_scan = jiffies + interval + backoff;
+}
+
+static void zfcp_fc_port_scan(struct zfcp_adapter *adapter)
+{
+       unsigned long now = jiffies;
+       unsigned long next = adapter->next_port_scan;
+       unsigned long delay = 0, max;
+
+       /* delay only needed within waiting period */
+       if (time_before(now, next)) {
+               delay = next - now;
+               /* paranoia: never ever delay scans longer than specified */
+               max = msecs_to_jiffies(port_scan_ratelimit + port_scan_backoff);
+               delay = min(delay, max);
+       }
+
+       queue_delayed_work(adapter->work_queue, &adapter->scan_work, delay);
+}
+
 void zfcp_fc_conditional_port_scan(struct zfcp_adapter *adapter)
 {
        if (no_auto_port_rescan)
                return;
 
-       queue_work(adapter->work_queue, &adapter->scan_work);
+       zfcp_fc_port_scan(adapter);
 }
 
 void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
@@ -44,7 +87,7 @@ void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
        if (!no_auto_port_rescan)
                return;
 
-       queue_work(adapter->work_queue, &adapter->scan_work);
+       zfcp_fc_port_scan(adapter);
 }
 
 /**
@@ -680,12 +723,15 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req,
  */
 void zfcp_fc_scan_ports(struct work_struct *work)
 {
-       struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
+       struct delayed_work *dw = to_delayed_work(work);
+       struct zfcp_adapter *adapter = container_of(dw, struct zfcp_adapter,
                                                    scan_work);
        int ret, i;
        struct zfcp_fc_req *fc_req;
        int chain, max_entries, buf_num, max_bytes;
 
+       zfcp_fc_port_scan_time(adapter);
+
        chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
        buf_num = chain ? ZFCP_FC_GPN_FT_NUM_BUFS : 1;
        max_entries = chain ? ZFCP_FC_GPN_FT_MAX_ENT : ZFCP_FC_GPN_FT_ENT_PAGE;
index b1d2024ed51367ef4c892a62ed00ecab267ed74b..df2b541c828720718a322003d43f7d54e2aef3eb 100644 (file)
@@ -212,8 +212,6 @@ static inline
 void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi,
                         u8 tm_flags)
 {
-       char tag[2];
-
        int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
 
        if (unlikely(tm_flags)) {
@@ -221,17 +219,7 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi,
                return;
        }
 
-       if (scsi_populate_tag_msg(scsi, tag)) {
-               switch (tag[0]) {
-               case MSG_ORDERED_TAG:
-                       fcp->fc_pri_ta |= FCP_PTA_ORDERED;
-                       break;
-               case MSG_SIMPLE_TAG:
-                       fcp->fc_pri_ta |= FCP_PTA_SIMPLE;
-                       break;
-               };
-       } else
-               fcp->fc_pri_ta = FCP_PTA_SIMPLE;
+       fcp->fc_pri_ta = FCP_PTA_SIMPLE;
 
        if (scsi->sc_data_direction == DMA_FROM_DEVICE)
                fcp->fc_flags |= FCP_CFL_RDDATA;
index 0fe8d5d951196425871d958c4003f773f8c4a3e2..21ec5e2f584ce44851560394870cf9b56163a3b1 100644 (file)
@@ -1396,8 +1396,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
                port->handle = header->port_handle;
                atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
                                ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
-               atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
-                                 ZFCP_STATUS_COMMON_ACCESS_BOXED,
+               atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
                                  &port->status);
                /* check whether D_ID has changed during open */
                /*
index 7b353647cb9087894ded09ec8b51234023adce85..75f4bfc2b98ad21570588844140bf6546701cc50 100644 (file)
@@ -32,25 +32,6 @@ static bool allow_lun_scan = 1;
 module_param(allow_lun_scan, bool, 0600);
 MODULE_PARM_DESC(allow_lun_scan, "For NPIV, scan and attach all storage LUNs");
 
-static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth,
-                                       int reason)
-{
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               scsi_track_queue_full(sdev, depth);
-               break;
-       case SCSI_QDEPTH_RAMP_UP:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-       return sdev->queue_depth;
-}
-
 static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
 {
        struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
@@ -66,9 +47,7 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
 static int zfcp_scsi_slave_configure(struct scsi_device *sdp)
 {
        if (sdp->tagged_supported)
-               scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, default_depth);
-       else
-               scsi_adjust_queue_depth(sdp, 0, 1);
+               scsi_change_queue_depth(sdp, default_depth);
        return 0;
 }
 
@@ -307,7 +286,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
        .slave_alloc             = zfcp_scsi_slave_alloc,
        .slave_configure         = zfcp_scsi_slave_configure,
        .slave_destroy           = zfcp_scsi_slave_destroy,
-       .change_queue_depth      = zfcp_scsi_change_queue_depth,
+       .change_queue_depth      = scsi_change_queue_depth,
        .proc_name               = "zfcp",
        .can_queue               = 4096,
        .this_id                 = -1,
@@ -322,6 +301,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
        .use_clustering          = 1,
        .shost_attrs             = zfcp_sysfs_shost_attrs,
        .sdev_attrs              = zfcp_sysfs_sdev_attrs,
+       .track_queue_depth       = 1,
 };
 
 /**
index 672b57219e115f780ce09b6948470e569d99b6b5..96a0be13e841def9f3ab3bd1d468d7ca700941f6 100644 (file)
@@ -73,9 +73,7 @@ ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
 ZFCP_DEFINE_ATTR(zfcp_port, port, in_recovery, "%d\n",
                 (atomic_read(&port->status) &
                  ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
-ZFCP_DEFINE_ATTR(zfcp_port, port, access_denied, "%d\n",
-                (atomic_read(&port->status) &
-                 ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+ZFCP_DEFINE_ATTR_CONST(port, access_denied, "%d\n", 0);
 
 ZFCP_DEFINE_ATTR(zfcp_unit, unit, status, "0x%08x\n",
                 zfcp_unit_sdev_status(unit));
@@ -223,9 +221,13 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
        if (!adapter)
                return -ENODEV;
 
-       /* sync the user-space- with the kernel-invocation of scan_work */
-       queue_work(adapter->work_queue, &adapter->scan_work);
-       flush_work(&adapter->scan_work);
+       /*
+        * Users wish is our command: immediately schedule and flush a
+        * worker to conduct a synchronous port scan, that is, neither
+        * a random delay nor a rate limit is applied here.
+        */
+       queue_delayed_work(adapter->work_queue, &adapter->scan_work, 0);
+       flush_delayed_work(&adapter->scan_work);
        zfcp_ccw_adapter_put(adapter);
 
        return (ssize_t) count;
@@ -439,16 +441,15 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
 {                                                                        \
        struct scsi_device *sdev = to_scsi_device(dev);                  \
        struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);            \
-       struct zfcp_port *port = zfcp_sdev->port;                        \
                                                                         \
        return sprintf(buf, _format, _value);                            \
 }                                                                        \
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
 
 ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
-                     dev_name(&port->adapter->ccw_device->dev));
+                     dev_name(&zfcp_sdev->port->adapter->ccw_device->dev));
 ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
-                     (unsigned long long) port->wwpn);
+                     (unsigned long long) zfcp_sdev->port->wwpn);
 
 static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
                                            struct device_attribute *attr,
@@ -460,6 +461,49 @@ static ssize_t zfcp_sysfs_scsi_fcp_lun_show(struct device *dev,
 }
 static DEVICE_ATTR(fcp_lun, S_IRUGO, zfcp_sysfs_scsi_fcp_lun_show, NULL);
 
+ZFCP_DEFINE_SCSI_ATTR(zfcp_access_denied, "%d\n",
+                     (atomic_read(&zfcp_sdev->status) &
+                      ZFCP_STATUS_COMMON_ACCESS_DENIED) != 0);
+
+static ssize_t zfcp_sysfs_scsi_zfcp_failed_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       unsigned int status = atomic_read(&sdev_to_zfcp(sdev)->status);
+       unsigned int failed = status & ZFCP_STATUS_COMMON_ERP_FAILED ? 1 : 0;
+
+       return sprintf(buf, "%d\n", failed);
+}
+
+static ssize_t zfcp_sysfs_scsi_zfcp_failed_store(struct device *dev,
+                                           struct device_attribute *attr,
+                                           const char *buf, size_t count)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       unsigned long val;
+
+       if (kstrtoul(buf, 0, &val) || val != 0)
+               return -EINVAL;
+
+       zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_RUNNING);
+       zfcp_erp_lun_reopen(sdev, ZFCP_STATUS_COMMON_ERP_FAILED,
+                           "syufai3");
+       zfcp_erp_wait(sdev_to_zfcp(sdev)->port->adapter);
+
+       return count;
+}
+static DEVICE_ATTR(zfcp_failed, S_IWUSR | S_IRUGO,
+                  zfcp_sysfs_scsi_zfcp_failed_show,
+                  zfcp_sysfs_scsi_zfcp_failed_store);
+
+ZFCP_DEFINE_SCSI_ATTR(zfcp_in_recovery, "%d\n",
+                     (atomic_read(&zfcp_sdev->status) &
+                      ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
+
+ZFCP_DEFINE_SCSI_ATTR(zfcp_status, "0x%08x\n",
+                     atomic_read(&zfcp_sdev->status));
+
 struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
        &dev_attr_fcp_lun,
        &dev_attr_wwpn,
@@ -467,6 +511,10 @@ struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
        &dev_attr_read_latency,
        &dev_attr_write_latency,
        &dev_attr_cmd_latency,
+       &dev_attr_zfcp_access_denied,
+       &dev_attr_zfcp_failed,
+       &dev_attr_zfcp_in_recovery,
+       &dev_attr_zfcp_status,
        NULL
 };
 
index 0a7325361d2958dceeae99da5959e518f8490985..cd4129ff7ae4cbb31d47fd87be6c5e2dab5685cf 100644 (file)
@@ -189,19 +189,6 @@ static ssize_t twa_show_stats(struct device *dev,
        return len;
 } /* End twa_show_stats() */
 
-/* This function will set a devices queue depth */
-static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth,
-                                 int reason)
-{
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
-       if (queue_depth > TW_Q_LENGTH-2)
-               queue_depth = TW_Q_LENGTH-2;
-       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-       return queue_depth;
-} /* End twa_change_queue_depth() */
-
 /* Create sysfs 'stats' entry */
 static struct device_attribute twa_host_stats_attr = {
        .attr = {
@@ -2016,7 +2003,7 @@ static struct scsi_host_template driver_template = {
        .queuecommand           = twa_scsi_queue,
        .eh_host_reset_handler  = twa_scsi_eh_reset,
        .bios_param             = twa_scsi_biosparam,
-       .change_queue_depth     = twa_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
        .can_queue              = TW_Q_LENGTH-2,
        .slave_configure        = twa_slave_configure,
        .this_id                = -1,
index 6da6cec9a65191882f141453c3ef18d73cb208f4..2361772d590966abf6f618d2e1228b0f3d424ebc 100644 (file)
@@ -191,19 +191,6 @@ static ssize_t twl_show_stats(struct device *dev,
        return len;
 } /* End twl_show_stats() */
 
-/* This function will set a devices queue depth */
-static int twl_change_queue_depth(struct scsi_device *sdev, int queue_depth,
-                                 int reason)
-{
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
-       if (queue_depth > TW_Q_LENGTH-2)
-               queue_depth = TW_Q_LENGTH-2;
-       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-       return queue_depth;
-} /* End twl_change_queue_depth() */
-
 /* stats sysfs attribute initializer */
 static struct device_attribute twl_host_stats_attr = {
        .attr = {
@@ -1590,7 +1577,7 @@ static struct scsi_host_template driver_template = {
        .queuecommand           = twl_scsi_queue,
        .eh_host_reset_handler  = twl_scsi_eh_reset,
        .bios_param             = twl_scsi_biosparam,
-       .change_queue_depth     = twl_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
        .can_queue              = TW_Q_LENGTH-2,
        .slave_configure        = twl_slave_configure,
        .this_id                = -1,
index 752624e6bc0022807c6265539cad6d8b42d1611f..c75f2048319f7ced2ba9f9956a2a56f41b181a24 100644 (file)
@@ -523,19 +523,6 @@ static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
        return len;
 } /* End tw_show_stats() */
 
-/* This function will set a devices queue depth */
-static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth,
-                                int reason)
-{
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
-       if (queue_depth > TW_Q_LENGTH-2)
-               queue_depth = TW_Q_LENGTH-2;
-       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-       return queue_depth;
-} /* End tw_change_queue_depth() */
-
 /* Create sysfs 'stats' entry */
 static struct device_attribute tw_host_stats_attr = {
        .attr = {
@@ -2270,7 +2257,7 @@ static struct scsi_host_template driver_template = {
        .queuecommand           = tw_scsi_queue,
        .eh_host_reset_handler  = tw_scsi_eh_reset,
        .bios_param             = tw_scsi_biosparam,
-       .change_queue_depth     = tw_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
        .can_queue              = TW_Q_LENGTH-2,
        .slave_configure        = tw_slave_configure,
        .this_id                = -1,
index fabd4be2c98552a7760b8c87d72891086b60dbf4..aa915da2a5e53c6a094b591e9effce404e813b21 100644 (file)
@@ -175,7 +175,7 @@ STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
 STATIC int NCR_700_slave_alloc(struct scsi_device *SDpnt);
 STATIC int NCR_700_slave_configure(struct scsi_device *SDpnt);
 STATIC void NCR_700_slave_destroy(struct scsi_device *SDpnt);
-static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth, int reason);
+static int NCR_700_change_queue_depth(struct scsi_device *SDpnt, int depth);
 static int NCR_700_change_queue_type(struct scsi_device *SDpnt, int depth);
 
 STATIC struct device_attribute *NCR_700_dev_attrs[];
@@ -327,6 +327,7 @@ NCR_700_detect(struct scsi_host_template *tpnt,
        tpnt->slave_alloc = NCR_700_slave_alloc;
        tpnt->change_queue_depth = NCR_700_change_queue_depth;
        tpnt->change_queue_type = NCR_700_change_queue_type;
+       tpnt->use_blk_tags = 1;
 
        if(tpnt->name == NULL)
                tpnt->name = "53c700";
@@ -592,19 +593,14 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
        hostdata->cmd = NULL;
 
        if(SCp != NULL) {
-               struct NCR_700_command_slot *slot = 
+               struct NCR_700_command_slot *slot =
                        (struct NCR_700_command_slot *)SCp->host_scribble;
-               
+
                dma_unmap_single(hostdata->dev, slot->pCmd,
                                 MAX_COMMAND_SIZE, DMA_TO_DEVICE);
                if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
                        char *cmnd = NCR_700_get_sense_cmnd(SCp->device);
-#ifdef NCR_700_DEBUG
-                       printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n",
-                              SCp, SCp->cmnd[7], result);
-                       scsi_print_sense("53c700", SCp);
 
-#endif
                        dma_unmap_single(hostdata->dev, slot->dma_handle,
                                         SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
                        /* restore the old result if the request sense was
@@ -906,8 +902,10 @@ process_message(struct Scsi_Host *host,    struct NCR_700_Host_Parameters *hostdata
                        /* we're done negotiating */
                        NCR_700_set_tag_neg_state(SCp->device, NCR_700_FINISHED_TAG_NEGOTIATION);
                        hostdata->tag_negotiated &= ~(1<<scmd_id(SCp));
+
                        SCp->device->tagged_supported = 0;
-                       scsi_deactivate_tcq(SCp->device, host->cmd_per_lun);
+                       scsi_change_queue_depth(SCp->device, host->cmd_per_lun);
+                       scsi_set_tag_type(SCp->device, 0);
                } else {
                        shost_printk(KERN_WARNING, host,
                                "(%d:%d) Unexpected REJECT Message %s\n",
@@ -1432,7 +1430,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
        if((hostdata->tag_negotiated & (1<<scmd_id(SCp)))
           && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE &&
               slot->flags != NCR_700_FLAG_AUTOSENSE)) {
-               count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]);
+               count += spi_populate_tag_msg(&hostdata->msgout[count], SCp);
        }
 
        if(hostdata->fast &&
@@ -1772,7 +1770,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
         */
        if(NCR_700_get_depth(SCp->device) != 0
           && (!(hostdata->tag_negotiated & (1<<scmd_id(SCp)))
-              || !blk_rq_tagged(SCp->request))) {
+              || !(SCp->flags & SCMD_TAGGED))) {
                CDEBUG(KERN_ERR, SCp, "has non zero depth %d\n",
                       NCR_700_get_depth(SCp->device));
                return SCSI_MLQUEUE_DEVICE_BUSY;
@@ -1800,7 +1798,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
        printk("53c700: scsi%d, command ", SCp->device->host->host_no);
        scsi_print_command(SCp);
 #endif
-       if(blk_rq_tagged(SCp->request)
+       if ((SCp->flags & SCMD_TAGGED)
           && (hostdata->tag_negotiated &(1<<scmd_id(SCp))) == 0
           && NCR_700_get_tag_neg_state(SCp->device) == NCR_700_START_TAG_NEGOTIATION) {
                scmd_printk(KERN_ERR, SCp, "Enabling Tag Command Queuing\n");
@@ -1814,7 +1812,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
         *
         * FIXME: This will royally screw up on multiple LUN devices
         * */
-       if(!blk_rq_tagged(SCp->request)
+       if (!(SCp->flags & SCMD_TAGGED)
           && (hostdata->tag_negotiated &(1<<scmd_id(SCp)))) {
                scmd_printk(KERN_INFO, SCp, "Disabling Tag Command Queuing\n");
                hostdata->tag_negotiated &= ~(1<<scmd_id(SCp));
@@ -1911,9 +1909,7 @@ NCR_700_abort(struct scsi_cmnd * SCp)
 {
        struct NCR_700_command_slot *slot;
 
-       scmd_printk(KERN_INFO, SCp,
-               "New error handler wants to abort command\n\t");
-       scsi_print_command(SCp);
+       scmd_printk(KERN_INFO, SCp, "abort command\n");
 
        slot = (struct NCR_700_command_slot *)SCp->host_scribble;
 
@@ -2056,13 +2052,10 @@ NCR_700_slave_configure(struct scsi_device *SDp)
 
        /* to do here: allocate memory; build a queue_full list */
        if(SDp->tagged_supported) {
-               scsi_set_tag_type(SDp, MSG_ORDERED_TAG);
-               scsi_activate_tcq(SDp, NCR_700_DEFAULT_TAGS);
+               scsi_change_queue_depth(SDp, NCR_700_DEFAULT_TAGS);
                NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION);
-       } else {
-               /* initialise to default depth */
-               scsi_adjust_queue_depth(SDp, 0, SDp->host->cmd_per_lun);
        }
+
        if(hostdata->fast) {
                /* Find the correct offset and period via domain validation */
                if (!spi_initial_dv(SDp->sdev_target))
@@ -2082,16 +2075,11 @@ NCR_700_slave_destroy(struct scsi_device *SDp)
 }
 
 static int
-NCR_700_change_queue_depth(struct scsi_device *SDp, int depth, int reason)
+NCR_700_change_queue_depth(struct scsi_device *SDp, int depth)
 {
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (depth > NCR_700_MAX_TAGS)
                depth = NCR_700_MAX_TAGS;
-
-       scsi_adjust_queue_depth(SDp, scsi_get_tag_type(SDp), depth);
-       return depth;
+       return scsi_change_queue_depth(SDp, depth);
 }
 
 static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
@@ -2101,8 +2089,6 @@ static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
        struct NCR_700_Host_Parameters *hostdata = 
                (struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
 
-       scsi_set_tag_type(SDp, tag_type);
-
        /* We have a global (per target) flag to track whether TCQ is
         * enabled, so we'll be turning it off for the entire target here.
         * our tag algorithm will fail if we mix tagged and untagged commands,
@@ -2110,15 +2096,16 @@ static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
        if (change_tag)
                scsi_target_quiesce(SDp->sdev_target);
 
+       scsi_set_tag_type(SDp, tag_type);
        if (!tag_type) {
                /* shift back to the default unqueued number of commands
                 * (the user can still raise this) */
-               scsi_deactivate_tcq(SDp, SDp->host->cmd_per_lun);
+               scsi_change_queue_depth(SDp, SDp->host->cmd_per_lun);
                hostdata->tag_negotiated &= ~(1 << sdev_id(SDp));
        } else {
                /* Here, we cleared the negotiation flag above, so this
                 * will force the driver to renegotiate */
-               scsi_activate_tcq(SDp, SDp->queue_depth);
+               scsi_change_queue_depth(SDp, SDp->queue_depth);
                if (change_tag)
                        NCR_700_set_tag_neg_state(SDp, NCR_700_START_TAG_NEGOTIATION);
        }
index 64c75143c89a24d6a3d46701e4d06c800b9faf16..8d66a6469e29758c96db343b3c20cffdff2bffe0 100644 (file)
@@ -2327,12 +2327,12 @@ static int blogic_slaveconfig(struct scsi_device *dev)
                if (qdepth == 0)
                        qdepth = BLOGIC_MAX_AUTO_TAG_DEPTH;
                adapter->qdepth[tgt_id] = qdepth;
-               scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, qdepth);
+               scsi_change_queue_depth(dev, qdepth);
        } else {
                adapter->tagq_ok &= ~(1 << tgt_id);
                qdepth = adapter->untag_qdepth;
                adapter->qdepth[tgt_id] = qdepth;
-               scsi_adjust_queue_depth(dev, 0, qdepth);
+               scsi_change_queue_depth(dev, qdepth);
        }
        qdepth = 0;
        for (tgt_id = 0; tgt_id < adapter->maxdev; tgt_id++)
index 3a820f61ce6594bf57be41df8808df346355eb38..86cf3d671eb99bdae4b9eb9baa75e451c852f6ff 100644 (file)
@@ -1341,13 +1341,15 @@ config SCSI_DC395x
          To compile this driver as a module, choose M here: the
          module will be called dc395x.
 
-config SCSI_DC390T
-       tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
+config SCSI_AM53C974
+       tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
        depends on PCI && SCSI
+       select SCSI_SPI_ATTRS
        ---help---
          This driver supports PCI SCSI host adapters based on the Am53C974A
          chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
          PCscsi/PCnet (Am53/79C974) solutions.
+         This is a new implementation base on the generic esp_scsi driver.
 
          Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
 
@@ -1355,7 +1357,7 @@ config SCSI_DC390T
          based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
 
          To compile this driver as a module, choose M here: the
-         module will be called tmscsim.
+         module will be called am53c974.
 
 config SCSI_T128
        tristate "Trantor T128/T128F/T228 SCSI support"
@@ -1451,6 +1453,14 @@ config SCSI_NSP32
          To compile this driver as a module, choose M here: the
          module will be called nsp32.
 
+config SCSI_WD719X
+       tristate "Western Digital WD7193/7197/7296 support"
+       depends on PCI && SCSI
+       select EEPROM_93CX6
+       ---help---
+         This is a driver for Western Digital WD7193, WD7197 and WD7296 PCI
+         SCSI controllers (based on WD33C296A chip).
+
 config SCSI_DEBUG
        tristate "SCSI debugging host simulator"
        depends on SCSI
@@ -1615,7 +1625,7 @@ config ATARI_SCSI_RESET_BOOT
          that leave the devices with SCSI operations partway completed.
 
 config MAC_SCSI
-       bool "Macintosh NCR5380 SCSI"
+       tristate "Macintosh NCR5380 SCSI"
        depends on MAC && SCSI=y
        select SCSI_SPI_ATTRS
        help
index 59f1ce6df2d6461af2136a784252f44d0dc351c1..58158f11ed7b5eb4f0d6c9dd30118510ed918022 100644 (file)
@@ -100,7 +100,7 @@ obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
 obj-$(CONFIG_SCSI_7000FASST)   += wd7000.o
 obj-$(CONFIG_SCSI_EATA)                += eata.o
 obj-$(CONFIG_SCSI_DC395x)      += dc395x.o
-obj-$(CONFIG_SCSI_DC390T)      += tmscsim.o
+obj-$(CONFIG_SCSI_AM53C974)    += esp_scsi.o   am53c974.o
 obj-$(CONFIG_MEGARAID_LEGACY)  += megaraid.o
 obj-$(CONFIG_MEGARAID_NEWGEN)  += megaraid/
 obj-$(CONFIG_MEGARAID_SAS)     += megaraid/
@@ -143,6 +143,7 @@ obj-$(CONFIG_SCSI_VIRTIO)   += virtio_scsi.o
 obj-$(CONFIG_VMWARE_PVSCSI)    += vmw_pvscsi.o
 obj-$(CONFIG_XEN_SCSI_FRONTEND)        += xen-scsifront.o
 obj-$(CONFIG_HYPERV_STORAGE)   += hv_storvsc.o
+obj-$(CONFIG_SCSI_WD719X)      += wd719x.o
 
 obj-$(CONFIG_ARM)              += arm/
 
index 45da3c8233226f78f49e7a2609707f9eba43d3bd..36244d63def2a9e957e645c3d0f26e6553e23de8 100644 (file)
@@ -11,8 +11,6 @@
  *      drew@colorado.edu
  *      +1 (303) 666-5836
  *
- * DISTRIBUTION RELEASE 6. 
- *
  * For more information, please consult 
  *
  * NCR 5380 Family
@@ -279,7 +277,7 @@ static void do_reset(struct Scsi_Host *host);
  *     Set up the internal fields in the SCSI command.
  */
 
-static __inline__ void initialize_SCp(Scsi_Cmnd * cmd)
+static inline void initialize_SCp(struct scsi_cmnd *cmd)
 {
        /* 
         * Initialize the Scsi Pointer field so that all of the commands in the 
@@ -574,12 +572,12 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
        int trying_irqs, i, mask;
        NCR5380_setup(instance);
 
-       for (trying_irqs = i = 0, mask = 1; i < 16; ++i, mask <<= 1)
+       for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1)
                if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0))
                        trying_irqs |= mask;
 
        timeout = jiffies + (250 * HZ / 1000);
-       probe_irq = SCSI_IRQ_NONE;
+       probe_irq = NO_IRQ;
 
        /*
         * A interrupt is triggered whenever BSY = false, SEL = true
@@ -596,13 +594,13 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
        NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
 
-       while (probe_irq == SCSI_IRQ_NONE && time_before(jiffies, timeout))
+       while (probe_irq == NO_IRQ && time_before(jiffies, timeout))
                schedule_timeout_uninterruptible(1);
        
        NCR5380_write(SELECT_ENABLE_REG, 0);
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
-       for (i = 0, mask = 1; i < 16; ++i, mask <<= 1)
+       for (i = 1, mask = 2; i < 16; ++i, mask <<= 1)
                if (trying_irqs & mask)
                        free_irq(i, NULL);
 
@@ -610,50 +608,70 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance,
 }
 
 /**
- *     NCR58380_print_options  -       show options
- *     @instance: unused for now
+ *     NCR58380_info - report driver and host information
+ *     @instance: relevant scsi host instance
  *
- *     Called by probe code indicating the NCR5380 driver options that 
- *     were selected. At some point this will switch to runtime options
- *     read from the adapter in question
+ *     For use as the host template info() handler.
  *
  *     Locks: none
  */
 
-static void __init __maybe_unused
-NCR5380_print_options(struct Scsi_Host *instance)
+static const char *NCR5380_info(struct Scsi_Host *instance)
 {
-       printk(" generic options"
-#ifdef AUTOPROBE_IRQ
-              " AUTOPROBE_IRQ"
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       return hostdata->info;
+}
+
+static void prepare_info(struct Scsi_Host *instance)
+{
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       snprintf(hostdata->info, sizeof(hostdata->info),
+                "%s, io_port 0x%lx, n_io_port %d, "
+                "base 0x%lx, irq %d, "
+                "can_queue %d, cmd_per_lun %d, "
+                "sg_tablesize %d, this_id %d, "
+                "flags { %s%s%s}, "
+#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG)
+                "USLEEP_POLL %d, USLEEP_WAITLONG %d, "
 #endif
-#ifdef AUTOSENSE
-              " AUTOSENSE"
+                "options { %s} ",
+                instance->hostt->name, instance->io_port, instance->n_io_port,
+                instance->base, instance->irq,
+                instance->can_queue, instance->cmd_per_lun,
+                instance->sg_tablesize, instance->this_id,
+                hostdata->flags & FLAG_NCR53C400     ? "NCR53C400 "     : "",
+                hostdata->flags & FLAG_DTC3181E      ? "DTC3181E "      : "",
+                hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
+#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG)
+                USLEEP_POLL, USLEEP_WAITLONG,
+#endif
+#ifdef AUTOPROBE_IRQ
+                "AUTOPROBE_IRQ "
 #endif
 #ifdef DIFFERENTIAL
-              " DIFFERENTIAL"
+                "DIFFERENTIAL "
 #endif
 #ifdef REAL_DMA
-              " REAL DMA"
+                "REAL_DMA "
 #endif
 #ifdef REAL_DMA_POLL
-              " REAL DMA POLL"
+                "REAL_DMA_POLL "
 #endif
 #ifdef PARITY
-              " PARITY"
+                "PARITY "
 #endif
 #ifdef PSEUDO_DMA
-              " PSEUDO DMA"
+                "PSEUDO_DMA "
 #endif
 #ifdef UNSAFE
-              UNSAFE "
+                "UNSAFE "
 #endif
-           );
-       printk(" USLEEP, USLEEP_POLL=%d USLEEP_SLEEP=%d", USLEEP_POLL, USLEEP_SLEEP);
-       printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
-       if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400) {
-               printk(" ncr53c400 release=%d", NCR53C400_PUBLIC_RELEASE);
-       }
+#ifdef NCR53C400
+                "NCR53C400 "
+#endif
+                "");
 }
 
 /**
@@ -672,6 +690,7 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
        NCR5380_dprint_phase(NDEBUG_ANY, instance);
 }
 
+#ifdef PSEUDO_DMA
 /******************************************/
 /*
  * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED]
@@ -689,19 +708,18 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
 static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
        char *buffer, int length)
 {
-#ifdef DTC_PUBLIC_RELEASE
-       dtc_wmaxi = dtc_maxi = 0;
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
-       pas_wmaxi = pas_maxi = 0;
-#endif
-       return (-ENOSYS);       /* Currently this is a no-op */
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       hostdata->spin_max_r = 0;
+       hostdata->spin_max_w = 0;
+       return 0;
 }
+#endif
 
 #undef SPRINTF
 #define SPRINTF(args...) seq_printf(m, ## args)
 static
-void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m);
+void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m);
 static
 void lprint_command(unsigned char *cmd, struct seq_file *m);
 static
@@ -711,56 +729,31 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,
        struct Scsi_Host *instance)
 {
        struct NCR5380_hostdata *hostdata;
-       Scsi_Cmnd *ptr;
+       struct scsi_cmnd *ptr;
 
        hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
-       SPRINTF("NCR5380 core release=%d.   ", NCR5380_PUBLIC_RELEASE);
-       if (((struct NCR5380_hostdata *) instance->hostdata)->flags & FLAG_NCR53C400)
-               SPRINTF("ncr53c400 release=%d.  ", NCR53C400_PUBLIC_RELEASE);
-#ifdef DTC_PUBLIC_RELEASE
-       SPRINTF("DTC 3180/3280 release %d", DTC_PUBLIC_RELEASE);
-#endif
-#ifdef T128_PUBLIC_RELEASE
-       SPRINTF("T128 release %d", T128_PUBLIC_RELEASE);
-#endif
-#ifdef GENERIC_NCR5380_PUBLIC_RELEASE
-       SPRINTF("Generic5380 release %d", GENERIC_NCR5380_PUBLIC_RELEASE);
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
-       SPRINTF("PAS16 release=%d", PAS16_PUBLIC_RELEASE);
-#endif
-
-       SPRINTF("\nBase Addr: 0x%05lX    ", (long) instance->base);
-       SPRINTF("io_port: %04x      ", (int) instance->io_port);
-       if (instance->irq == SCSI_IRQ_NONE)
-               SPRINTF("IRQ: None.\n");
-       else
-               SPRINTF("IRQ: %d.\n", instance->irq);
-
-#ifdef DTC_PUBLIC_RELEASE
-       SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", dtc_wmaxi, dtc_maxi);
-#endif
-#ifdef PAS16_PUBLIC_RELEASE
-       SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", pas_wmaxi, pas_maxi);
+#ifdef PSEUDO_DMA
+       SPRINTF("Highwater I/O busy spin counts: write %d, read %d\n",
+               hostdata->spin_max_w, hostdata->spin_max_r);
 #endif
        spin_lock_irq(instance->host_lock);
        if (!hostdata->connected)
                SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
        else
-               lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+               lprint_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected, m);
        SPRINTF("scsi%d: issue_queue\n", instance->host_no);
-       for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+       for (ptr = (struct scsi_cmnd *) hostdata->issue_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble)
                lprint_Scsi_Cmnd(ptr, m);
 
        SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
-       for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+       for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble)
                lprint_Scsi_Cmnd(ptr, m);
        spin_unlock_irq(instance->host_lock);
        return 0;
 }
 
-static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m)
+static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m)
 {
        SPRINTF("scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun);
        SPRINTF("        command = ");
@@ -836,18 +829,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
        
        INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main);
        
-#ifdef NCR5380_STATS
-       for (i = 0; i < 8; ++i) {
-               hostdata->time_read[i] = 0;
-               hostdata->time_write[i] = 0;
-               hostdata->bytes_read[i] = 0;
-               hostdata->bytes_write[i] = 0;
-       }
-       hostdata->timebase = 0;
-       hostdata->pendingw = 0;
-       hostdata->pendingr = 0;
-#endif
-
        /* The CHECK code seems to break the 53C400. Will check it later maybe */
        if (flags & FLAG_NCR53C400)
                hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags;
@@ -857,11 +838,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
        hostdata->host = instance;
        hostdata->time_expires = 0;
 
-#ifndef AUTOSENSE
-       if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
-                   printk(KERN_WARNING "scsi%d : WARNING : support for multiple outstanding commands enabled\n" "         without AUTOSENSE option, contingent allegiance conditions may\n"
-                          "         be incorrectly cleared.\n", instance->host_no);
-#endif                         /* def AUTOSENSE */
+       prepare_info(instance);
 
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
        NCR5380_write(MODE_REG, MR_BASE);
@@ -935,11 +912,11 @@ static void NCR5380_exit(struct Scsi_Host *instance)
  *     Locks: host lock taken by caller
  */
 
-static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
+static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct scsi_cmnd *))
 {
        struct Scsi_Host *instance = cmd->device->host;
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-       Scsi_Cmnd *tmp;
+       struct scsi_cmnd *tmp;
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
        switch (cmd->cmnd[0]) {
@@ -952,25 +929,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)
        }
 #endif                         /* (NDEBUG & NDEBUG_NO_WRITE) */
 
-#ifdef NCR5380_STATS
-       switch (cmd->cmnd[0]) {
-               case WRITE:
-               case WRITE_6:
-               case WRITE_10:
-                       hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
-                       hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);
-                       hostdata->pendingw++;
-                       break;
-               case READ:
-               case READ_6:
-               case READ_10:
-                       hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
-                       hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);
-                       hostdata->pendingr++;
-                       break;
-       }
-#endif
-
        /* 
         * We use the host_scribble field as a pointer to the next command  
         * in a queue 
@@ -992,7 +950,7 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)
                cmd->host_scribble = (unsigned char *) hostdata->issue_queue;
                hostdata->issue_queue = cmd;
        } else {
-               for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble);
+               for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (struct scsi_cmnd *) tmp->host_scribble);
                LIST(cmd, tmp);
                tmp->host_scribble = (unsigned char *) cmd;
        }
@@ -1023,7 +981,7 @@ static void NCR5380_main(struct work_struct *work)
        struct NCR5380_hostdata *hostdata =
                container_of(work, struct NCR5380_hostdata, coroutine.work);
        struct Scsi_Host *instance = hostdata->host;
-       Scsi_Cmnd *tmp, *prev;
+       struct scsi_cmnd *tmp, *prev;
        int done;
        
        spin_lock_irq(instance->host_lock);
@@ -1036,7 +994,7 @@ static void NCR5380_main(struct work_struct *work)
                         * Search through the issue_queue for a command destined
                         * for a target that's not busy.
                         */
-                       for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) 
+                       for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble)
                        {
                                if (prev != tmp)
                                    dprintk(NDEBUG_LISTS, "MAIN tmp=%p   target=%d   busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
@@ -1048,7 +1006,7 @@ static void NCR5380_main(struct work_struct *work)
                                                prev->host_scribble = tmp->host_scribble;
                                        } else {
                                                REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble);
-                                               hostdata->issue_queue = (Scsi_Cmnd *) tmp->host_scribble;
+                                               hostdata->issue_queue = (struct scsi_cmnd *) tmp->host_scribble;
                                        }
                                        tmp->host_scribble = NULL;
 
@@ -1073,14 +1031,14 @@ static void NCR5380_main(struct work_struct *work)
                                        hostdata->selecting = NULL;
                                        /* RvC: have to preset this to indicate a new command is being performed */
 
-                                       if (!NCR5380_select(instance, tmp,
-                                                           /* 
-                                                            * REQUEST SENSE commands are issued without tagged
-                                                            * queueing, even on SCSI-II devices because the 
-                                                            * contingent allegiance condition exists for the 
-                                                            * entire unit.
-                                                            */
-                                                           (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
+                                       /*
+                                        * REQUEST SENSE commands are issued without tagged
+                                        * queueing, even on SCSI-II devices because the
+                                        * contingent allegiance condition exists for the
+                                        * entire unit.
+                                        */
+
+                                       if (!NCR5380_select(instance, tmp)) {
                                                break;
                                        } else {
                                                LIST(tmp, hostdata->issue_queue);
@@ -1095,9 +1053,9 @@ static void NCR5380_main(struct work_struct *work)
                        /* exited locked */
                }       /* if (!hostdata->connected) */
                if (hostdata->selecting) {
-                       tmp = (Scsi_Cmnd *) hostdata->selecting;
+                       tmp = (struct scsi_cmnd *) hostdata->selecting;
                        /* Selection will drop and retake the lock */
-                       if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {
+                       if (!NCR5380_select(instance, tmp)) {
                                /* Ok ?? */
                        } else {
                                /* RvC: device failed, so we wait a long time
@@ -1216,47 +1174,16 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id)
 
 #endif 
 
-/**
- *     collect_stats           -       collect stats on a scsi command
- *     @hostdata: adapter 
- *     @cmd: command being issued
- *
- *     Update the statistical data by parsing the command in question
- */
-static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) 
-{
-#ifdef NCR5380_STATS
-       switch (cmd->cmnd[0]) {
-       case WRITE:
-       case WRITE_6:
-       case WRITE_10:
-               hostdata->time_write[scmd_id(cmd)] += (jiffies - hostdata->timebase);
-               hostdata->pendingw--;
-               break;
-       case READ:
-       case READ_6:
-       case READ_10:
-               hostdata->time_read[scmd_id(cmd)] += (jiffies - hostdata->timebase);
-               hostdata->pendingr--;
-               break;
-       }
-#endif
-}
-
-
 /* 
- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, 
- *      int tag);
+ * Function : int NCR5380_select(struct Scsi_Host *instance,
+ *                               struct scsi_cmnd *cmd)
  *
  * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
  *      including ARBITRATION, SELECTION, and initial message out for 
  *      IDENTIFY and queue messages. 
  *
  * Inputs : instance - instantiation of the 5380 driver on which this 
- *      target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for 
- *      new tag, TAG_NONE for untagged queueing, otherwise set to the tag for 
- *      the command that is presently connected.
+ *      target lives, cmd - SCSI command to execute.
  * 
  * Returns : -1 if selection could not execute for some reason,
  *      0 if selection succeeded or failed because the target 
@@ -1278,7 +1205,7 @@ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd)
  *     Locks: caller holds hostdata lock in IRQ mode
  */
  
-static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) 
+static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
 {
        NCR5380_local_declare();
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
@@ -1476,7 +1403,6 @@ part2:
                        return -1;
                }
                cmd->result = DID_BAD_TARGET << 16;
-               collect_stats(hostdata, cmd);
                cmd->scsi_done(cmd);
                NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
                dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", instance->host_no);
@@ -1513,7 +1439,7 @@ part2:
        }
 
        dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id);
-       tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
+       tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun);
 
        len = 1;
        cmd->tag = 0;
@@ -2086,7 +2012,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 #endif
        unsigned char *data;
        unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
-       Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+       struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected;
        /* RvC: we need to set the end of the polling time */
        unsigned long poll_time = jiffies + USLEEP_POLL;
 
@@ -2228,7 +2154,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                        cmd->next_link->tag = cmd->tag;
                                        cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
                                        dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun);
-                                       collect_stats(hostdata, cmd);
                                        cmd->scsi_done(cmd);
                                        cmd = hostdata->connected;
                                        break;
@@ -2263,7 +2188,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                        else if (status_byte(cmd->SCp.Status) != GOOD)
                                                cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
-#ifdef AUTOSENSE
                                        if ((cmd->cmnd[0] == REQUEST_SENSE) &&
                                                hostdata->ses.cmd_len) {
                                                scsi_eh_restore_cmnd(cmd, &hostdata->ses);
@@ -2278,12 +2202,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                                LIST(cmd, hostdata->issue_queue);
                                                cmd->host_scribble = (unsigned char *)
                                                    hostdata->issue_queue;
-                                               hostdata->issue_queue = (Scsi_Cmnd *) cmd;
+                                               hostdata->issue_queue = (struct scsi_cmnd *) cmd;
                                                dprintk(NDEBUG_QUEUES, "scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no);
-                                       } else
-#endif                         /* def AUTOSENSE */
-                                       {
-                                               collect_stats(hostdata, cmd);
+                                       } else {
                                                cmd->scsi_done(cmd);
                                        }
 
@@ -2430,7 +2351,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
                                        hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF));
                                        hostdata->connected = NULL;
                                        cmd->result = DID_ERROR << 16;
-                                       collect_stats(hostdata, cmd);
                                        cmd->scsi_done(cmd);
                                        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
                                        return;
@@ -2479,7 +2399,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
  * Function : void NCR5380_reselect (struct Scsi_Host *instance)
  *
  * Purpose : does reselection, initializing the instance->connected 
- *      field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q 
+ *      field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
  *      nexus has been reestablished,
  *      
  * Inputs : instance - this instance of the NCR5380.
@@ -2496,7 +2416,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
        int len;
        unsigned char msg[3];
        unsigned char *data;
-       Scsi_Cmnd *tmp = NULL, *prev;
+       struct scsi_cmnd *tmp = NULL, *prev;
        int abort = 0;
        NCR5380_setup(instance);
 
@@ -2562,7 +2482,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
                 */
 
 
-               for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble)
+               for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble)
                        if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)
                            ) {
                                if (prev) {
@@ -2570,7 +2490,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
                                        prev->host_scribble = tmp->host_scribble;
                                } else {
                                        REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble);
-                                       hostdata->disconnected_queue = (Scsi_Cmnd *) tmp->host_scribble;
+                                       hostdata->disconnected_queue = (struct scsi_cmnd *) tmp->host_scribble;
                                }
                                tmp->host_scribble = NULL;
                                break;
@@ -2601,7 +2521,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
  *
  * Inputs : instance - this instance of the NCR5380.
  *
- * Returns : pointer to the Scsi_Cmnd structure for which the I_T_L
+ * Returns : pointer to the scsi_cmnd structure for which the I_T_L
  *      nexus has been reestablished, on failure NULL is returned.
  */
 
@@ -2643,32 +2563,32 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) {
 #endif                         /* def REAL_DMA */
 
 /*
- * Function : int NCR5380_abort (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_abort (struct scsi_cmnd *cmd)
  *
  * Purpose : abort a command
  *
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the 
- *      host byte of the result field to, if zero DID_ABORTED is 
+ * Inputs : cmd - the scsi_cmnd to abort, code - code to set the
+ *      host byte of the result field to, if zero DID_ABORTED is
  *      used.
  *
- * Returns : 0 - success, -1 on failure.
+ * Returns : SUCCESS - success, FAILED on failure.
  *
- *     XXX - there is no way to abort the command that is currently 
- *     connected, you have to wait for it to complete.  If this is 
+ *     XXX - there is no way to abort the command that is currently
+ *     connected, you have to wait for it to complete.  If this is
  *     a problem, we could implement longjmp() / setjmp(), setjmp()
  *     called where the loop started in NCR5380_main().
  *
  * Locks: host lock taken by caller
  */
 
-static int NCR5380_abort(Scsi_Cmnd * cmd) {
+static int NCR5380_abort(struct scsi_cmnd *cmd)
+{
        NCR5380_local_declare();
        struct Scsi_Host *instance = cmd->device->host;
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
-       Scsi_Cmnd *tmp, **prev;
-       
-       printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
-       scsi_print_command(cmd);
+       struct scsi_cmnd *tmp, **prev;
+
+       scmd_printk(KERN_WARNING, cmd, "aborting command\n");
 
        NCR5380_print_status(instance);
 
@@ -2704,7 +2624,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
  * aborted flag and get back into our main loop.
  */
 
-               return 0;
+               return SUCCESS;
        }
 #endif
 
@@ -2714,10 +2634,10 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
  */
  
        dprintk(NDEBUG_ABORT, "scsi%d : abort going into loop.\n", instance->host_no);
-       for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
+       for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue), tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble)
                if (cmd == tmp) {
                        REMOVE(5, *prev, tmp, tmp->host_scribble);
-                       (*prev) = (Scsi_Cmnd *) tmp->host_scribble;
+                       (*prev) = (struct scsi_cmnd *) tmp->host_scribble;
                        tmp->host_scribble = NULL;
                        tmp->result = DID_ABORT << 16;
                        dprintk(NDEBUG_ABORT, "scsi%d : abort removed command from issue queue.\n", instance->host_no);
@@ -2770,20 +2690,20 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
  * it from the disconnected queue.
  */
 
-       for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
+       for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; tmp = (struct scsi_cmnd *) tmp->host_scribble)
                if (cmd == tmp) {
                        dprintk(NDEBUG_ABORT, "scsi%d : aborting disconnected command.\n", instance->host_no);
 
-                       if (NCR5380_select(instance, cmd, (int) cmd->tag))
+                       if (NCR5380_select(instance, cmd))
                                return FAILED;
                        dprintk(NDEBUG_ABORT, "scsi%d : nexus reestablished.\n", instance->host_no);
 
                        do_abort(instance);
 
-                       for (prev = (Scsi_Cmnd **) & (hostdata->disconnected_queue), tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble)
+                       for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue), tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble)
                                if (cmd == tmp) {
                                        REMOVE(5, *prev, tmp, tmp->host_scribble);
-                                       *prev = (Scsi_Cmnd *) tmp->host_scribble;
+                                       *prev = (struct scsi_cmnd *) tmp->host_scribble;
                                        tmp->host_scribble = NULL;
                                        tmp->result = DID_ABORT << 16;
                                        tmp->scsi_done(tmp);
@@ -2806,7 +2726,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
 
 
 /* 
- * Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_bus_reset (struct scsi_cmnd *cmd)
  * 
  * Purpose : reset the SCSI bus.
  *
@@ -2815,7 +2735,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
  * Locks: host lock taken by caller
  */
 
-static int NCR5380_bus_reset(Scsi_Cmnd * cmd)
+static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
 {
        struct Scsi_Host *instance = cmd->device->host;
 
index c79ddfa6f53c52d58ab814846fb5023ed821bf4a..162112dd1bf8eabeaf0c8bb029291742d6c55ce4 100644 (file)
@@ -7,8 +7,6 @@
  *     drew@colorado.edu
  *      +1 (303) 666-5836
  *
- * DISTRIBUTION RELEASE 7
- *
  * For more information, please consult 
  *
  * NCR 5380 Family
 #define NCR5380_H
 
 #include <linux/interrupt.h>
-
-#ifdef AUTOSENSE
 #include <scsi/scsi_eh.h>
-#endif
-
-#define NCR5380_PUBLIC_RELEASE 7
-#define NCR53C400_PUBLIC_RELEASE 2
 
 #define NDEBUG_ARBITRATION     0x1
 #define NDEBUG_AUTOSENSE       0x2
 #define DISCONNECT_LONG                2
 
 /* 
- * These are "special" values for the tag parameter passed to NCR5380_select.
+ * "Special" value for the (unsigned char) command tag, to indicate
+ * I_T_L nexus instead of I_T_L_Q.
  */
 
-#define TAG_NEXT       -1      /* Use next free tag */
-#define TAG_NONE       -2      /* 
-                                * Establish I_T_L nexus instead of I_T_L_Q
-                                * even on SCSI-II devices.
-                                */
+#define TAG_NONE       0xff
 
 /*
  * These are "special" values for the irq and dma_channel fields of the 
  * Scsi_Host structure
  */
 
-#define SCSI_IRQ_NONE  255
 #define DMA_NONE       255
 #define IRQ_AUTO       254
 #define DMA_AUTO       254
 #define PORT_AUTO      0xffff  /* autoprobe io port for 53c400a */
 
+#ifndef NO_IRQ
+#define NO_IRQ         0
+#endif
+
 #define FLAG_HAS_LAST_BYTE_SENT                1       /* NCR53c81 or better */
 #define FLAG_CHECK_LAST_BYTE_SENT      2       /* Only test once */
 #define FLAG_NCR53C400                 4       /* NCR53c400 */
 #define FLAG_NO_PSEUDO_DMA             8       /* Inhibit DMA */
 #define FLAG_DTC3181E                  16      /* DTC3181E */
+#define FLAG_LATE_DMA_SETUP            32      /* Setup NCR before DMA H/W */
+#define FLAG_TAGGED_QUEUING            64      /* as X3T9.2 spelled it */
 
 #ifndef ASM
+
+#ifdef SUPPORT_TAGS
+struct tag_alloc {
+       DECLARE_BITMAP(allocated, MAX_TAGS);
+       int nr_allocated;
+       int queue_size;
+};
+#endif
+
 struct NCR5380_hostdata {
        NCR5380_implementation_fields;          /* implementation specific */
        struct Scsi_Host *host;                 /* Host backpointer */
@@ -263,9 +266,9 @@ struct NCR5380_hostdata {
        volatile int dma_len;                   /* requested length of DMA */
 #endif
        volatile unsigned char last_message;    /* last message OUT */
-       volatile Scsi_Cmnd *connected;          /* currently connected command */
-       volatile Scsi_Cmnd *issue_queue;        /* waiting to be issued */
-       volatile Scsi_Cmnd *disconnected_queue; /* waiting for reconnect */
+       volatile struct scsi_cmnd *connected;   /* currently connected command */
+       volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */
+       volatile struct scsi_cmnd *disconnected_queue;  /* waiting for reconnect */
        volatile int restart_select;            /* we have disconnected,
                                                   used to restart 
                                                   NCR5380_select() */
@@ -273,19 +276,21 @@ struct NCR5380_hostdata {
        int flags;
        unsigned long time_expires;             /* in jiffies, set prior to sleeping */
        int select_time;                        /* timer in select for target response */
-       volatile Scsi_Cmnd *selecting;
+       volatile struct scsi_cmnd *selecting;
        struct delayed_work coroutine;          /* our co-routine */
-#ifdef NCR5380_STATS
-       unsigned timebase;                      /* Base for time calcs */
-       long time_read[8];                      /* time to do reads */
-       long time_write[8];                     /* time to do writes */
-       unsigned long bytes_read[8];            /* bytes read */
-       unsigned long bytes_write[8];           /* bytes written */
-       unsigned pendingr;
-       unsigned pendingw;
-#endif
-#ifdef AUTOSENSE
        struct scsi_eh_save ses;
+       char info[256];
+       int read_overruns;                /* number of bytes to cut from a
+                                          * transfer to handle chip overruns */
+       int retain_dma_intr;
+       struct work_struct main_task;
+       volatile int main_running;
+#ifdef SUPPORT_TAGS
+       struct tag_alloc TagAlloc[8][8];        /* 8 targets and 8 LUNs */
+#endif
+#ifdef PSEUDO_DMA
+       unsigned spin_max_r;
+       unsigned spin_max_w;
 #endif
 };
 
@@ -296,7 +301,8 @@ struct NCR5380_hostdata {
 #endif
 
 #define dprintk(flg, fmt, ...) \
-       do { if ((NDEBUG) & (flg)) pr_debug(fmt, ## __VA_ARGS__); } while (0)
+       do { if ((NDEBUG) & (flg)) \
+               printk(KERN_DEBUG fmt, ## __VA_ARGS__); } while (0)
 
 #if NDEBUG
 #define NCR5380_dprint(flg, arg) \
@@ -320,17 +326,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance);
 static irqreturn_t NCR5380_intr(int irq, void *dev_id);
 #endif
 static void NCR5380_main(struct work_struct *work);
-static void __maybe_unused NCR5380_print_options(struct Scsi_Host *instance);
-static int NCR5380_abort(Scsi_Cmnd * cmd);
-static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
-static int NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int __maybe_unused NCR5380_show_info(struct seq_file *,
-       struct Scsi_Host *);
-static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance,
-       char *buffer, int length);
-
+static const char *NCR5380_info(struct Scsi_Host *instance);
 static void NCR5380_reselect(struct Scsi_Host *instance);
-static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag);
+static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd);
 #if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL)
 static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
 #endif
index 681434e2dfe9b77a4da7487cdc9e9f8e2a293715..b32e77db0c48186e866b63b4a8d0abcef895ea7b 100644 (file)
@@ -2181,7 +2181,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                          (fsa_dev_ptr[cid].sense_data.sense_key ==
                           NOT_READY)) {
                                switch (scsicmd->cmnd[0]) {
-                               case SERVICE_ACTION_IN:
+                               case SERVICE_ACTION_IN_16:
                                        if (!(dev->raw_io_interface) ||
                                            !(dev->raw_io_64) ||
                                            ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
@@ -2309,7 +2309,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
                return aac_get_container_name(scsicmd);
        }
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                if (!(dev->raw_io_interface) ||
                    !(dev->raw_io_64) ||
                    ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
index a759cb2d4b15e65868b578a8c3110a7bd6f647b9..fdcdf9f781bc66997203ab58d2582d1f742d712a 100644 (file)
@@ -462,9 +462,9 @@ static int aac_slave_configure(struct scsi_device *sdev)
                        depth = 256;
                else if (depth < 2)
                        depth = 2;
-               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
+               scsi_change_queue_depth(sdev, depth);
        } else
-               scsi_adjust_queue_depth(sdev, 0, 1);
+               scsi_change_queue_depth(sdev, 1);
 
        return 0;
 }
@@ -478,12 +478,8 @@ static int aac_slave_configure(struct scsi_device *sdev)
  *     total capacity and the queue depth supported by the target device.
  */
 
-static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
-                                 int reason)
+static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
 {
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
            (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
                struct scsi_device * dev;
@@ -504,10 +500,10 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth,
                        depth = 256;
                else if (depth < 2)
                        depth = 2;
-               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
-       } else
-               scsi_adjust_queue_depth(sdev, 0, 1);
-       return sdev->queue_depth;
+               return scsi_change_queue_depth(sdev, depth);
+       }
+
+       return scsi_change_queue_depth(sdev, 1);
 }
 
 static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf)
@@ -555,7 +551,7 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
                AAC_DRIVERNAME,
                host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun);
        switch (cmd->cmnd[0]) {
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                if (!(aac->raw_io_interface) ||
                    !(aac->raw_io_64) ||
                    ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
index 43761c1c46f0730d5166b433e1c457ce8c476a0f..6719a3390ebd7ad9781a52552616859bf836b2ab 100644 (file)
@@ -7706,7 +7706,7 @@ advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
                                asc_dvc->cfg->can_tagged_qng |= tid_bit;
                                asc_dvc->use_tagged_qng |= tid_bit;
                        }
-                       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
+                       scsi_change_queue_depth(sdev, 
                                                asc_dvc->max_dvc_qng[sdev->id]);
                }
        } else {
@@ -7714,7 +7714,6 @@ advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
                        asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
                        asc_dvc->use_tagged_qng &= ~tid_bit;
                }
-               scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
        }
 
        if ((sdev->lun == 0) &&
@@ -7848,12 +7847,8 @@ advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
                }
        }
 
-       if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
-               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
-                                       adv_dvc->max_dvc_qng);
-       } else {
-               scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
-       }
+       if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported)
+               scsi_change_queue_depth(sdev, adv_dvc->max_dvc_qng);
 }
 
 /*
index e77b72f7800671539ddce4bf8dd5cb3b6efedf1f..2b960b326daf38cbcf9223758590887bc0827778 100644 (file)
  *
  *
  **************************************************************************
+
  see Documentation/scsi/aha152x.txt for configuration details
 
  **************************************************************************/
@@ -279,45 +279,11 @@ static LIST_HEAD(aha152x_host_list);
 #error define AUTOCONF or SETUP0
 #endif
 
-#if defined(AHA152X_DEBUG)
-#define DEBUG_DEFAULT debug_eh
-
-#define DPRINTK(when,msgs...) \
-       do { if(HOSTDATA(shpnt)->debug & (when)) printk(msgs); } while(0)
-
-#define DO_LOCK(flags) \
-       do { \
-               if(spin_is_locked(&QLOCK)) { \
-                       DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __func__, __LINE__, QLOCKER, QLOCKERL); \
-               } \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
-               spin_lock_irqsave(&QLOCK,flags); \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
-               QLOCKER=__func__; \
-               QLOCKERL=__LINE__; \
-       } while(0)
-
-#define DO_UNLOCK(flags)       \
-       do { \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __func__, __LINE__, QLOCKER, QLOCKERL); \
-               spin_unlock_irqrestore(&QLOCK,flags); \
-               DPRINTK(debug_locking, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __func__, __LINE__); \
-               QLOCKER="(not locked)"; \
-               QLOCKERL=0; \
-       } while(0)
-
-#else
-#define DPRINTK(when,msgs...)
 #define        DO_LOCK(flags)          spin_lock_irqsave(&QLOCK,flags)
 #define        DO_UNLOCK(flags)        spin_unlock_irqrestore(&QLOCK,flags)
-#endif
 
 #define LEAD           "(scsi%d:%d:%d) "
-#define WARN_LEAD      KERN_WARNING    LEAD
 #define INFO_LEAD      KERN_INFO       LEAD
-#define NOTE_LEAD      KERN_NOTICE     LEAD
-#define ERR_LEAD       KERN_ERR        LEAD
-#define DEBUG_LEAD     KERN_DEBUG      LEAD
 #define CMDINFO(cmd) \
                        (cmd) ? ((cmd)->device->host->host_no) : -1, \
                         (cmd) ? ((cmd)->device->id & 0x0f) : -1, \
@@ -345,10 +311,10 @@ CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
 
 enum {
        not_issued      = 0x0001,       /* command not yet issued */
-       selecting       = 0x0002,       /* target is beeing selected */
+       selecting       = 0x0002,       /* target is being selected */
        identified      = 0x0004,       /* IDENTIFY was sent */
        disconnected    = 0x0008,       /* target disconnected */
-       completed       = 0x0010,       /* target sent COMMAND COMPLETE */ 
+       completed       = 0x0010,       /* target sent COMMAND COMPLETE */
        aborted         = 0x0020,       /* ABORT was sent */
        resetted        = 0x0040,       /* BUS DEVICE RESET was sent */
        spiordy         = 0x0080,       /* waiting for SPIORDY to raise */
@@ -396,7 +362,6 @@ static int exttrans[] = {0, 0};
 module_param_array(exttrans, int, NULL, 0);
 MODULE_PARM_DESC(exttrans,"use extended translation");
 
-#if !defined(AHA152X_DEBUG)
 static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
 module_param_array(aha152x, int, NULL, 0);
 MODULE_PARM_DESC(aha152x, "parameters for first controller");
@@ -404,19 +369,6 @@ MODULE_PARM_DESC(aha152x, "parameters for first controller");
 static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
 module_param_array(aha152x1, int, NULL, 0);
 MODULE_PARM_DESC(aha152x1, "parameters for second controller");
-#else
-static int debug[] = {DEBUG_DEFAULT, DEBUG_DEFAULT};
-module_param_array(debug, int, NULL, 0);
-MODULE_PARM_DESC(debug, "flags for driver debugging");
-
-static int aha152x[]   = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
-module_param_array(aha152x, int, NULL, 0);
-MODULE_PARM_DESC(aha152x, "parameters for first controller");
-
-static int aha152x1[]  = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
-module_param_array(aha152x1, int, NULL, 0);
-MODULE_PARM_DESC(aha152x1, "parameters for second controller");
-#endif /* !defined(AHA152X_DEBUG) */
 #endif /* MODULE */
 
 #ifdef __ISAPNP__
@@ -446,7 +398,7 @@ static struct scsi_host_template aha152x_driver_template;
 /*
  * internal states of the host
  *
- */ 
+ */
 enum aha152x_state {
        idle=0,
        unknown,
@@ -485,24 +437,16 @@ struct aha152x_hostdata {
        spinlock_t lock;
                /* host lock */
 
-#if defined(AHA152X_DEBUG)
-       const char *locker;
-               /* which function has the lock */
-       int lockerl;    /* where did it get it */
-
-       int debug;      /* current debugging setting */
-#endif
-
 #if defined(AHA152X_STAT)
-       int           total_commands;
+       int           total_commands;
        int           disconnections;
        int           busfree_without_any_action;
        int           busfree_without_old_command;
        int           busfree_without_new_command;
        int           busfree_without_done_command;
        int           busfree_with_check_condition;
-       int           count[maxstate];
-       int           count_trans[maxstate];
+       int           count[maxstate];
+       int           count_trans[maxstate];
        unsigned long time[maxstate];
 #endif
 
@@ -514,7 +458,7 @@ struct aha152x_hostdata {
        int delay;              /* reset out delay */
        int ext_trans;          /* extended translation enabled */
 
-       int swint;              /* software-interrupt was fired during detect() */
+       int swint;              /* software-interrupt was fired during detect() */
        int service;            /* bh needs to be run */
        int in_intr;            /* bh is running */
 
@@ -543,7 +487,7 @@ struct aha152x_hostdata {
        unsigned char msgi[256];
                /* received message bytes */
 
-       int msgo_i, msgo_len;   
+       int msgo_i, msgo_len;
                /* number of sent bytes and length of current messages */
        unsigned char msgo[256];
                /* pending messages */
@@ -689,7 +633,6 @@ static void aha152x_error(struct Scsi_Host *shpnt, char *msg);
 static void done(struct Scsi_Host *shpnt, int error);
 
 /* diagnostics */
-static void disp_ports(struct Scsi_Host *shpnt);
 static void show_command(Scsi_Cmnd * ptr);
 static void show_queues(struct Scsi_Host *shpnt);
 static void disp_enintr(struct Scsi_Host *shpnt);
@@ -812,10 +755,6 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup)
        DELAY       = setup->delay;
        EXT_TRANS   = setup->ext_trans;
 
-#if defined(AHA152X_DEBUG)
-       HOSTDATA(shpnt)->debug = setup->debug;
-#endif
-
        SETPORT(SCSIID, setup->scsiid << 4);
        shpnt->this_id = setup->scsiid;
 
@@ -941,31 +880,24 @@ void aha152x_release(struct Scsi_Host *shpnt)
  * setup controller to generate interrupts depending
  * on current state (lock has to be acquired)
  *
- */ 
+ */
 static int setup_expected_interrupts(struct Scsi_Host *shpnt)
 {
        if(CURRENT_SC) {
                CURRENT_SC->SCp.phase |= 1 << 16;
-       
+
                if(CURRENT_SC->SCp.phase & selecting) {
-                       DPRINTK(debug_intr, DEBUG_LEAD "expecting: (seldo) (seltimo) (seldi)\n", CMDINFO(CURRENT_SC));
                        SETPORT(SSTAT1, SELTO);
                        SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
                        SETPORT(SIMODE1, ENSELTIMO);
                } else {
-                       DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (busfree) %s\n", CMDINFO(CURRENT_SC), CURRENT_SC->SCp.phase & spiordy ? "(spiordy)" : "");
                        SETPORT(SIMODE0, (CURRENT_SC->SCp.phase & spiordy) ? ENSPIORDY : 0);
-                       SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE); 
+                       SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
                }
        } else if(STATE==seldi) {
-               DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (identify)\n", CMDINFO(CURRENT_SC));
                SETPORT(SIMODE0, 0);
-               SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE); 
+               SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE);
        } else {
-               DPRINTK(debug_intr, DEBUG_LEAD "expecting: %s %s\n",
-                       CMDINFO(CURRENT_SC),
-                       DISCONNECTED_SC ? "(reselection)" : "",
-                       ISSUE_SC ? "(busfree)" : "");
                SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
                SETPORT(SIMODE1, ENSCSIRST | ( (ISSUE_SC||DONE_SC) ? ENBUSFREE : 0));
        }
@@ -977,7 +909,7 @@ static int setup_expected_interrupts(struct Scsi_Host *shpnt)
 }
 
 
-/* 
+/*
  *  Queue a command and setup interrupts for a free bus.
  */
 static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
@@ -986,15 +918,6 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
        struct Scsi_Host *shpnt = SCpnt->device->host;
        unsigned long flags;
 
-#if defined(AHA152X_DEBUG)
-       if (HOSTDATA(shpnt)->debug & debug_queue) {
-               printk(INFO_LEAD "queue: %p; cmd_len=%d pieces=%d size=%u cmnd=",
-                      CMDINFO(SCpnt), SCpnt, SCpnt->cmd_len,
-                      scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
-               __scsi_print_command(SCpnt->cmnd);
-       }
-#endif
-
        SCpnt->scsi_done        = done;
        SCpnt->SCp.phase        = not_issued | phase;
        SCpnt->SCp.Status       = 0x1; /* Ilegal status by SCSI standard */
@@ -1004,13 +927,13 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
 
        if(SCpnt->SCp.phase & (resetting|check_condition)) {
                if (!SCpnt->host_scribble || SCSEM(SCpnt) || SCNEXT(SCpnt)) {
-                       printk(ERR_LEAD "cannot reuse command\n", CMDINFO(SCpnt));
+                       scmd_printk(KERN_ERR, SCpnt, "cannot reuse command\n");
                        return FAILED;
                }
        } else {
                SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC);
                if(!SCpnt->host_scribble) {
-                       printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt));
+                       scmd_printk(KERN_ERR, SCpnt, "allocation failed\n");
                        return FAILED;
                }
        }
@@ -1066,15 +989,6 @@ static int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct completion *complete,
  */
 static int aha152x_queue_lck(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
-#if 0
-       if(*SCpnt->cmnd == REQUEST_SENSE) {
-               SCpnt->result = 0;
-               done(SCpnt);
-
-               return 0;
-       }
-#endif
-
        return aha152x_internal_queue(SCpnt, NULL, 0, done);
 }
 
@@ -1082,15 +996,10 @@ static DEF_SCSI_QCMD(aha152x_queue)
 
 
 /*
- *  
  *
  */
 static void reset_done(Scsi_Cmnd *SCpnt)
 {
-#if 0
-       struct Scsi_Host *shpnt = SCpnt->host;
-       DPRINTK(debug_eh, INFO_LEAD "reset_done called\n", CMDINFO(SCpnt));
-#endif
        if(SCSEM(SCpnt)) {
                complete(SCSEM(SCpnt));
        } else {
@@ -1108,20 +1017,11 @@ static int aha152x_abort(Scsi_Cmnd *SCpnt)
        Scsi_Cmnd *ptr;
        unsigned long flags;
 
-#if defined(AHA152X_DEBUG)
-       if(HOSTDATA(shpnt)->debug & debug_eh) {
-               printk(DEBUG_LEAD "abort(%p)", CMDINFO(SCpnt), SCpnt);
-               show_queues(shpnt);
-       }
-#endif
-
        DO_LOCK(flags);
 
        ptr=remove_SC(&ISSUE_SC, SCpnt);
 
        if(ptr) {
-               DPRINTK(debug_eh, DEBUG_LEAD "not yet issued - SUCCESS\n", CMDINFO(SCpnt));
-
                HOSTDATA(shpnt)->commands--;
                if (!HOSTDATA(shpnt)->commands)
                        SETPORT(PORTA, 0);
@@ -1131,7 +1031,7 @@ static int aha152x_abort(Scsi_Cmnd *SCpnt)
                SCpnt->host_scribble=NULL;
 
                return SUCCESS;
-       } 
+       }
 
        DO_UNLOCK(flags);
 
@@ -1142,7 +1042,8 @@ static int aha152x_abort(Scsi_Cmnd *SCpnt)
         *
         */
 
-       printk(ERR_LEAD "cannot abort running or disconnected command\n", CMDINFO(SCpnt));
+       scmd_printk(KERN_ERR, SCpnt,
+                   "cannot abort running or disconnected command\n");
 
        return FAILED;
 }
@@ -1160,15 +1061,8 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
        unsigned long flags;
        unsigned long timeleft;
 
-#if defined(AHA152X_DEBUG)
-       if(HOSTDATA(shpnt)->debug & debug_eh) {
-               printk(INFO_LEAD "aha152x_device_reset(%p)", CMDINFO(SCpnt), SCpnt);
-               show_queues(shpnt);
-       }
-#endif
-
        if(CURRENT_SC==SCpnt) {
-               printk(ERR_LEAD "cannot reset current device\n", CMDINFO(SCpnt));
+               scmd_printk(KERN_ERR, SCpnt, "cannot reset current device\n");
                return FAILED;
        }
 
@@ -1208,7 +1102,7 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
                } else if(disconnected) {
                        append_SC(&DISCONNECTED_SC, SCpnt);
                }
-       
+
                ret = FAILED;
        }
 
@@ -1227,12 +1121,12 @@ static void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs)
                if(SCDATA(ptr)) {
                        next = SCNEXT(ptr);
                } else {
-                       printk(DEBUG_LEAD "queue corrupted at %p\n", CMDINFO(ptr), ptr);
+                       scmd_printk(KERN_DEBUG, ptr,
+                                   "queue corrupted at %p\n", ptr);
                        next = NULL;
                }
 
                if (!ptr->device->soft_reset) {
-                       DPRINTK(debug_eh, DEBUG_LEAD "disconnected command %p removed\n", CMDINFO(ptr), ptr);
                        remove_SC(SCs, ptr);
                        HOSTDATA(shpnt)->commands--;
                        kfree(ptr->host_scribble);
@@ -1253,25 +1147,14 @@ static int aha152x_bus_reset_host(struct Scsi_Host *shpnt)
 
        DO_LOCK(flags);
 
-#if defined(AHA152X_DEBUG)
-       if(HOSTDATA(shpnt)->debug & debug_eh) {
-               printk(KERN_DEBUG "scsi%d: bus reset", shpnt->host_no);
-               show_queues(shpnt);
-       }
-#endif
-
        free_hard_reset_SCs(shpnt, &ISSUE_SC);
        free_hard_reset_SCs(shpnt, &DISCONNECTED_SC);
 
-       DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting bus\n", shpnt->host_no);
-
        SETPORT(SCSISEQ, SCSIRSTO);
        mdelay(256);
        SETPORT(SCSISEQ, 0);
        mdelay(DELAY);
 
-       DPRINTK(debug_eh, KERN_DEBUG "scsi%d: bus resetted\n", shpnt->host_no);
-
        setup_expected_interrupts(shpnt);
        if(HOSTDATA(shpnt)->commands==0)
                SETPORT(PORTA, 0);
@@ -1333,11 +1216,7 @@ static void reset_ports(struct Scsi_Host *shpnt)
  */
 int aha152x_host_reset_host(struct Scsi_Host *shpnt)
 {
-       DPRINTK(debug_eh, KERN_DEBUG "scsi%d: host reset\n", shpnt->host_no);
-
        aha152x_bus_reset_host(shpnt);
-
-       DPRINTK(debug_eh, KERN_DEBUG "scsi%d: resetting ports\n", shpnt->host_no);
        reset_ports(shpnt);
 
        return SUCCESS;
@@ -1345,7 +1224,7 @@ int aha152x_host_reset_host(struct Scsi_Host *shpnt)
 
 /*
  * Reset the host (bus and controller)
- * 
+ *
  */
 static int aha152x_host_reset(Scsi_Cmnd *SCpnt)
 {
@@ -1411,7 +1290,9 @@ static void done(struct Scsi_Host *shpnt, int error)
 {
        if (CURRENT_SC) {
                if(DONE_SC)
-                       printk(ERR_LEAD "there's already a completed command %p - will cause abort\n", CMDINFO(CURRENT_SC), DONE_SC);
+                       scmd_printk(KERN_ERR, CURRENT_SC,
+                                   "there's already a completed command %p "
+                                   "- will cause abort\n", DONE_SC);
 
                DONE_SC = CURRENT_SC;
                CURRENT_SC = NULL;
@@ -1466,7 +1347,7 @@ static irqreturn_t intr(int irqno, void *dev_id)
                return IRQ_NONE;
 
        if( TESTLO(DMASTAT, INTSTAT) )
-               return IRQ_NONE;        
+               return IRQ_NONE;
 
        /* no more interrupts from the controller, while we're busy.
           INTEN is restored by the BH handler */
@@ -1501,7 +1382,7 @@ static void busfree_run(struct Scsi_Host *shpnt)
        SETPORT(SXFRCTL0, CH1);
 
        SETPORT(SSTAT1, CLRBUSFREE);
-       
+
        if(CURRENT_SC) {
 #if defined(AHA152X_STAT)
                action++;
@@ -1513,19 +1394,13 @@ static void busfree_run(struct Scsi_Host *shpnt)
                        done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
 
                } else if(CURRENT_SC->SCp.phase & aborted) {
-                       DPRINTK(debug_eh, DEBUG_LEAD "ABORT sent\n", CMDINFO(CURRENT_SC));
                        done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_ABORT << 16));
 
                } else if(CURRENT_SC->SCp.phase & resetted) {
-                       DPRINTK(debug_eh, DEBUG_LEAD "BUS DEVICE RESET sent\n", CMDINFO(CURRENT_SC));
                        done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_RESET << 16));
 
                } else if(CURRENT_SC->SCp.phase & disconnected) {
                        /* target sent DISCONNECT */
-                       DPRINTK(debug_selection, DEBUG_LEAD "target disconnected at %d/%d\n",
-                               CMDINFO(CURRENT_SC),
-                               scsi_get_resid(CURRENT_SC),
-                               scsi_bufflen(CURRENT_SC));
 #if defined(AHA152X_STAT)
                        HOSTDATA(shpnt)->disconnections++;
 #endif
@@ -1553,13 +1428,6 @@ static void busfree_run(struct Scsi_Host *shpnt)
                        struct scsi_cmnd *cmd = HOSTDATA(shpnt)->done_SC;
                        struct aha152x_scdata *sc = SCDATA(cmd);
 
-#if 0
-                       if(HOSTDATA(shpnt)->debug & debug_eh) {
-                               printk(ERR_LEAD "received sense: ", CMDINFO(DONE_SC));
-                               scsi_print_sense("bh", DONE_SC);
-                       }
-#endif
-
                        scsi_eh_restore_cmnd(cmd, &sc->ses);
 
                        cmd->SCp.Status = SAM_STAT_CHECK_CONDITION;
@@ -1571,17 +1439,11 @@ static void busfree_run(struct Scsi_Host *shpnt)
 #if defined(AHA152X_STAT)
                        HOSTDATA(shpnt)->busfree_with_check_condition++;
 #endif
-#if 0
-                       DPRINTK(debug_eh, ERR_LEAD "CHECK CONDITION found\n", CMDINFO(DONE_SC));
-#endif
 
                        if(!(DONE_SC->SCp.phase & not_issued)) {
                                struct aha152x_scdata *sc;
                                Scsi_Cmnd *ptr = DONE_SC;
                                DONE_SC=NULL;
-#if 0
-                               DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(ptr));
-#endif
 
                                sc = SCDATA(ptr);
                                /* It was allocated in aha152x_internal_queue? */
@@ -1591,19 +1453,10 @@ static void busfree_run(struct Scsi_Host *shpnt)
                                DO_UNLOCK(flags);
                                aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done);
                                DO_LOCK(flags);
-#if 0
-                       } else {
-                               DPRINTK(debug_eh, ERR_LEAD "command not issued - CHECK CONDITION ignored\n", CMDINFO(DONE_SC));
-#endif
                        }
                }
 
                if(DONE_SC && DONE_SC->scsi_done) {
-#if defined(AHA152X_DEBUG)
-                       int hostno=DONE_SC->device->host->host_no;
-                       int id=DONE_SC->device->id & 0xf;
-                       int lun=((u8)DONE_SC->device->lun) & 0x7;
-#endif
                        Scsi_Cmnd *ptr = DONE_SC;
                        DONE_SC=NULL;
 
@@ -1618,9 +1471,7 @@ static void busfree_run(struct Scsi_Host *shpnt)
                        }
 
                        DO_UNLOCK(flags);
-                       DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", hostno, id, lun, ptr);
-                       ptr->scsi_done(ptr);
-                       DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", hostno, id, lun, ptr);
+                       ptr->scsi_done(ptr);
                        DO_LOCK(flags);
                }
 
@@ -1640,9 +1491,7 @@ static void busfree_run(struct Scsi_Host *shpnt)
 #if defined(AHA152X_STAT)
                action++;
 #endif
-               CURRENT_SC->SCp.phase |= selecting;
-
-               DPRINTK(debug_selection, DEBUG_LEAD "selecting target\n", CMDINFO(CURRENT_SC));
+               CURRENT_SC->SCp.phase |= selecting;
 
                /* clear selection timeout */
                SETPORT(SSTAT1, SELTO);
@@ -1674,18 +1523,19 @@ static void seldo_run(struct Scsi_Host *shpnt)
        SETPORT(SSTAT1, CLRBUSFREE);
        SETPORT(SSTAT1, CLRPHASECHG);
 
-       CURRENT_SC->SCp.phase &= ~(selecting|not_issued);
+       CURRENT_SC->SCp.phase &= ~(selecting|not_issued);
 
        SETPORT(SCSISEQ, 0);
 
        if (TESTLO(SSTAT0, SELDO)) {
-               printk(ERR_LEAD "aha152x: passing bus free condition\n", CMDINFO(CURRENT_SC));
+               scmd_printk(KERN_ERR, CURRENT_SC,
+                           "aha152x: passing bus free condition\n");
                done(shpnt, DID_NO_CONNECT << 16);
                return;
        }
 
        SETPORT(SSTAT0, CLRSELDO);
-       
+
        ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
 
        if (CURRENT_SC->SCp.phase & aborting) {
@@ -1693,7 +1543,7 @@ static void seldo_run(struct Scsi_Host *shpnt)
        } else if (CURRENT_SC->SCp.phase & resetting) {
                ADDMSGO(BUS_DEVICE_RESET);
        } else if (SYNCNEG==0 && SYNCHRONOUS) {
-               CURRENT_SC->SCp.phase |= syncneg;
+               CURRENT_SC->SCp.phase |= syncneg;
                MSGOLEN += spi_populate_sync_msg(&MSGO(MSGOLEN), 50, 8);
                SYNCNEG=1;              /* negotiation in progress */
        }
@@ -1708,29 +1558,21 @@ static void seldo_run(struct Scsi_Host *shpnt)
  */
 static void selto_run(struct Scsi_Host *shpnt)
 {
-       SETPORT(SCSISEQ, 0);            
+       SETPORT(SCSISEQ, 0);
        SETPORT(SSTAT1, CLRSELTIMO);
 
-       DPRINTK(debug_selection, DEBUG_LEAD "selection timeout\n", CMDINFO(CURRENT_SC));
-
-       if(!CURRENT_SC) {
-               DPRINTK(debug_selection, DEBUG_LEAD "!CURRENT_SC\n", CMDINFO(CURRENT_SC));
+       if (!CURRENT_SC)
                return;
-       }
 
-       CURRENT_SC->SCp.phase &= ~selecting;
+       CURRENT_SC->SCp.phase &= ~selecting;
 
-       if (CURRENT_SC->SCp.phase & aborted) {
-               DPRINTK(debug_selection, DEBUG_LEAD "aborted\n", CMDINFO(CURRENT_SC));
+       if (CURRENT_SC->SCp.phase & aborted)
                done(shpnt, DID_ABORT << 16);
-       } else if (TESTLO(SSTAT0, SELINGO)) {
-               DPRINTK(debug_selection, DEBUG_LEAD "arbitration not won\n", CMDINFO(CURRENT_SC));
+       else if (TESTLO(SSTAT0, SELINGO))
                done(shpnt, DID_BUS_BUSY << 16);
-       } else {
+       else
                /* ARBITRATION won, but SELECTION failed */
-               DPRINTK(debug_selection, DEBUG_LEAD "selection failed\n", CMDINFO(CURRENT_SC));
                done(shpnt, DID_NO_CONNECT << 16);
-       }
 }
 
 /*
@@ -1753,9 +1595,8 @@ static void seldi_run(struct Scsi_Host *shpnt)
 
        if(CURRENT_SC) {
                if(!(CURRENT_SC->SCp.phase & not_issued))
-                       printk(ERR_LEAD "command should not have been issued yet\n", CMDINFO(CURRENT_SC));
-
-               DPRINTK(debug_selection, ERR_LEAD "command requeued - reselection\n", CMDINFO(CURRENT_SC));
+                       scmd_printk(KERN_ERR, CURRENT_SC,
+                                   "command should not have been issued yet\n");
 
                DO_LOCK(flags);
                append_SC(&ISSUE_SC, CURRENT_SC);
@@ -1764,17 +1605,16 @@ static void seldi_run(struct Scsi_Host *shpnt)
                CURRENT_SC = NULL;
        }
 
-       if(!DISCONNECTED_SC) {
-               DPRINTK(debug_selection, DEBUG_LEAD "unexpected SELDI ", CMDINFO(CURRENT_SC));
+       if (!DISCONNECTED_SC)
                return;
-       }
 
        RECONN_TARGET=-1;
 
        selid = GETPORT(SELID) & ~(1 << shpnt->this_id);
 
        if (selid==0) {
-               printk("aha152x%d: target id unknown (%02x)\n", HOSTNO, selid);
+               shost_printk(KERN_INFO, shpnt,
+                            "target id unknown (%02x)\n", selid);
                return;
        }
 
@@ -1782,8 +1622,8 @@ static void seldi_run(struct Scsi_Host *shpnt)
                ;
 
        if(selid & ~(1 << target)) {
-               printk("aha152x%d: multiple targets reconnected (%02x)\n",
-                      HOSTNO, selid);
+               shost_printk(KERN_INFO, shpnt,
+                            "multiple targets reconnected (%02x)\n", selid);
        }
 
 
@@ -1793,7 +1633,6 @@ static void seldi_run(struct Scsi_Host *shpnt)
        SETRATE(HOSTDATA(shpnt)->syncrate[target]);
 
        RECONN_TARGET=target;
-       DPRINTK(debug_selection, DEBUG_LEAD "target %d reselected (%02x).\n", CMDINFO(CURRENT_SC), target, selid);
 }
 
 /*
@@ -1817,31 +1656,24 @@ static void msgi_run(struct Scsi_Host *shpnt)
                if(sstat1 & (PHASECHG|PHASEMIS|BUSFREE) || !(sstat1 & REQINIT))
                        return;
 
-               if(TESTLO(SSTAT0,SPIORDY)) {
-                       DPRINTK(debug_msgi, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC));
+               if (TESTLO(SSTAT0, SPIORDY))
                        return;
-               }       
 
                ADDMSGI(GETPORT(SCSIDAT));
 
-#if defined(AHA152X_DEBUG)
-               if (HOSTDATA(shpnt)->debug & debug_msgi) {
-                       printk(INFO_LEAD "inbound message %02x ", CMDINFO(CURRENT_SC), MSGI(0));
-                       spi_print_msg(&MSGI(0));
-                       printk("\n");
-               }
-#endif
-
                if(!CURRENT_SC) {
                        if(LASTSTATE!=seldi) {
-                               printk(KERN_ERR "aha152x%d: message in w/o current command not after reselection\n", HOSTNO);
+                               shost_printk(KERN_ERR, shpnt,
+                                            "message in w/o current command"
+                                            " not after reselection\n");
                        }
 
                        /*
-                        * Handle reselection
-                        */
+                        * Handle reselection
+                        */
                        if(!(MSGI(0) & IDENTIFY_BASE)) {
-                               printk(KERN_ERR "aha152x%d: target didn't identify after reselection\n", HOSTNO);
+                               shost_printk(KERN_ERR, shpnt,
+                                            "target didn't identify after reselection\n");
                                continue;
                        }
 
@@ -1849,12 +1681,13 @@ static void msgi_run(struct Scsi_Host *shpnt)
 
                        if (!CURRENT_SC) {
                                show_queues(shpnt);
-                               printk(KERN_ERR "aha152x%d: no disconnected command for target %d/%d\n", HOSTNO, RECONN_TARGET, MSGI(0) & 0x3f);
+                               shost_printk(KERN_ERR, shpnt,
+                                            "no disconnected command"
+                                            " for target %d/%d\n",
+                                            RECONN_TARGET, MSGI(0) & 0x3f);
                                continue;
                        }
 
-                       DPRINTK(debug_msgi, DEBUG_LEAD "target reconnected\n", CMDINFO(CURRENT_SC));
-
                        CURRENT_SC->SCp.Message = MSGI(0);
                        CURRENT_SC->SCp.phase &= ~disconnected;
 
@@ -1862,31 +1695,32 @@ static void msgi_run(struct Scsi_Host *shpnt)
 
                        /* next message if any */
                        continue;
-               } 
+               }
 
                CURRENT_SC->SCp.Message = MSGI(0);
 
                switch (MSGI(0)) {
                case DISCONNECT:
                        if (!RECONNECT)
-                               printk(WARN_LEAD "target was not allowed to disconnect\n", CMDINFO(CURRENT_SC));
+                               scmd_printk(KERN_WARNING, CURRENT_SC,
+                                           "target was not allowed to disconnect\n");
 
                        CURRENT_SC->SCp.phase |= disconnected;
                        break;
 
                case COMMAND_COMPLETE:
-                       if(CURRENT_SC->SCp.phase & completed)
-                               DPRINTK(debug_msgi, DEBUG_LEAD "again COMMAND COMPLETE\n", CMDINFO(CURRENT_SC));
-
                        CURRENT_SC->SCp.phase |= completed;
                        break;
 
                case MESSAGE_REJECT:
                        if (SYNCNEG==1) {
-                               printk(INFO_LEAD "Synchronous Data Transfer Request was rejected\n", CMDINFO(CURRENT_SC));
+                               scmd_printk(KERN_INFO, CURRENT_SC,
+                                           "Synchronous Data Transfer Request"
+                                           " was rejected\n");
                                SYNCNEG=2;      /* negotiation completed */
                        } else
-                               printk(INFO_LEAD "inbound message (MESSAGE REJECT)\n", CMDINFO(CURRENT_SC));
+                               scmd_printk(KERN_INFO, CURRENT_SC,
+                                           "inbound message (MESSAGE REJECT)\n");
                        break;
 
                case SAVE_POINTERS:
@@ -1907,7 +1741,8 @@ static void msgi_run(struct Scsi_Host *shpnt)
                                        long ticks;
 
                                        if (MSGI(1) != 3) {
-                                               printk(ERR_LEAD "SDTR message length!=3\n", CMDINFO(CURRENT_SC));
+                                               scmd_printk(KERN_ERR, CURRENT_SC,
+                                                           "SDTR message length!=3\n");
                                                break;
                                        }
 
@@ -1924,10 +1759,12 @@ static void msgi_run(struct Scsi_Host *shpnt)
                                                /* negotiation in progress */
                                                if (ticks > 9 || MSGI(4) < 1 || MSGI(4) > 8) {
                                                        ADDMSGO(MESSAGE_REJECT);
-                                                       printk(INFO_LEAD "received Synchronous Data Transfer Request invalid - rejected\n", CMDINFO(CURRENT_SC));
+                                                       scmd_printk(KERN_INFO,
+                                                                   CURRENT_SC,
+                                                                   "received Synchronous Data Transfer Request invalid - rejected\n");
                                                        break;
                                                }
-                                               
+
                                                SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
                                        } else if (ticks <= 9 && MSGI(4) >= 1) {
                                                ADDMSGO(EXTENDED_MESSAGE);
@@ -1947,11 +1784,14 @@ static void msgi_run(struct Scsi_Host *shpnt)
                                                SYNCRATE |= ((ticks - 2) << 4) + MSGI(4);
                                        } else {
                                                /* requested SDTR is too slow, do it asynchronously */
-                                               printk(INFO_LEAD "Synchronous Data Transfer Request too slow - Rejecting\n", CMDINFO(CURRENT_SC));
+                                               scmd_printk(KERN_INFO,
+                                                           CURRENT_SC,
+                                                           "Synchronous Data Transfer Request too slow - Rejecting\n");
                                                ADDMSGO(MESSAGE_REJECT);
                                        }
 
-                                       SYNCNEG=2;              /* negotiation completed */
+                                       /* negotiation completed */
+                                       SYNCNEG=2;
                                        SETRATE(SYNCRATE);
                                }
                                break;
@@ -1985,12 +1825,12 @@ static void msgi_run(struct Scsi_Host *shpnt)
 static void msgi_end(struct Scsi_Host *shpnt)
 {
        if(MSGILEN>0)
-               printk(WARN_LEAD "target left before message completed (%d)\n", CMDINFO(CURRENT_SC), MSGILEN);
+               scmd_printk(KERN_WARNING, CURRENT_SC,
+                           "target left before message completed (%d)\n",
+                           MSGILEN);
 
-       if (MSGOLEN > 0 && !(GETPORT(SSTAT1) & BUSFREE)) {
-               DPRINTK(debug_msgi, DEBUG_LEAD "msgo pending\n", CMDINFO(CURRENT_SC));
+       if (MSGOLEN > 0 && !(GETPORT(SSTAT1) & BUSFREE))
                SETPORT(SCSISIG, P_MSGI | SIG_ATNO);
-       } 
 }
 
 /*
@@ -2003,21 +1843,12 @@ static void msgo_init(struct Scsi_Host *shpnt)
                if((CURRENT_SC->SCp.phase & syncneg) && SYNCNEG==2 && SYNCRATE==0) {
                        ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->device->lun));
                } else {
-                       printk(INFO_LEAD "unexpected MESSAGE OUT phase; rejecting\n", CMDINFO(CURRENT_SC));
+                       scmd_printk(KERN_INFO, CURRENT_SC,
+                                   "unexpected MESSAGE OUT phase; rejecting\n");
                        ADDMSGO(MESSAGE_REJECT);
                }
        }
 
-#if defined(AHA152X_DEBUG)
-       if(HOSTDATA(shpnt)->debug & debug_msgo) {
-               int i;
-
-               printk(DEBUG_LEAD "messages( ", CMDINFO(CURRENT_SC));
-               for (i=0; i<MSGOLEN; i+=spi_print_msg(&MSGO(i)), printk(" "))
-                       ;
-               printk(")\n");
-       }
-#endif
 }
 
 /*
@@ -2026,16 +1857,9 @@ static void msgo_init(struct Scsi_Host *shpnt)
  */
 static void msgo_run(struct Scsi_Host *shpnt)
 {
-       if(MSGO_I==MSGOLEN)
-               DPRINTK(debug_msgo, DEBUG_LEAD "messages all sent (%d/%d)\n", CMDINFO(CURRENT_SC), MSGO_I, MSGOLEN);
-
        while(MSGO_I<MSGOLEN) {
-               DPRINTK(debug_msgo, DEBUG_LEAD "message byte %02x (%d/%d)\n", CMDINFO(CURRENT_SC), MSGO(MSGO_I), MSGO_I, MSGOLEN);
-
-               if(TESTLO(SSTAT0, SPIORDY)) {
-                       DPRINTK(debug_msgo, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC));
+               if (TESTLO(SSTAT0, SPIORDY))
                        return;
-               }
 
                if (MSGO_I==MSGOLEN-1) {
                        /* Leave MESSAGE OUT after transfer */
@@ -2059,36 +1883,33 @@ static void msgo_run(struct Scsi_Host *shpnt)
 static void msgo_end(struct Scsi_Host *shpnt)
 {
        if(MSGO_I<MSGOLEN) {
-               printk(ERR_LEAD "message sent incompletely (%d/%d)\n", CMDINFO(CURRENT_SC), MSGO_I, MSGOLEN);
+               scmd_printk(KERN_ERR, CURRENT_SC,
+                           "message sent incompletely (%d/%d)\n",
+                           MSGO_I, MSGOLEN);
                if(SYNCNEG==1) {
-                       printk(INFO_LEAD "Synchronous Data Transfer Request was rejected\n", CMDINFO(CURRENT_SC));
+                       scmd_printk(KERN_INFO, CURRENT_SC,
+                                   "Synchronous Data Transfer Request was rejected\n");
                        SYNCNEG=2;
                }
        }
-               
+
        MSGO_I  = 0;
        MSGOLEN = 0;
 }
 
-/* 
+/*
  * command phase
  *
  */
 static void cmd_init(struct Scsi_Host *shpnt)
 {
        if (CURRENT_SC->SCp.sent_command) {
-               printk(ERR_LEAD "command already sent\n", CMDINFO(CURRENT_SC));
+               scmd_printk(KERN_ERR, CURRENT_SC,
+                           "command already sent\n");
                done(shpnt, DID_ERROR << 16);
                return;
        }
 
-#if defined(AHA152X_DEBUG)
-       if (HOSTDATA(shpnt)->debug & debug_cmd) {
-               printk(DEBUG_LEAD "cmd_init: ", CMDINFO(CURRENT_SC));
-               __scsi_print_command(CURRENT_SC->cmnd);
-       }
-#endif
-
        CMD_I=0;
 }
 
@@ -2098,18 +1919,9 @@ static void cmd_init(struct Scsi_Host *shpnt)
  */
 static void cmd_run(struct Scsi_Host *shpnt)
 {
-       if(CMD_I==CURRENT_SC->cmd_len) {
-               DPRINTK(debug_cmd, DEBUG_LEAD "command already completely sent (%d/%d)", CMDINFO(CURRENT_SC), CMD_I, CURRENT_SC->cmd_len);
-               disp_ports(shpnt);
-       }
-
        while(CMD_I<CURRENT_SC->cmd_len) {
-               DPRINTK(debug_cmd, DEBUG_LEAD "command byte %02x (%d/%d)\n", CMDINFO(CURRENT_SC), CURRENT_SC->cmnd[CMD_I], CMD_I, CURRENT_SC->cmd_len);
-
-               if(TESTLO(SSTAT0, SPIORDY)) {
-                       DPRINTK(debug_cmd, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC));
+               if (TESTLO(SSTAT0, SPIORDY))
                        return;
-               }
 
                SETPORT(SCSIDAT, CURRENT_SC->cmnd[CMD_I++]);
        }
@@ -2118,7 +1930,9 @@ static void cmd_run(struct Scsi_Host *shpnt)
 static void cmd_end(struct Scsi_Host *shpnt)
 {
        if(CMD_I<CURRENT_SC->cmd_len)
-               printk(ERR_LEAD "command sent incompletely (%d/%d)\n", CMDINFO(CURRENT_SC), CMD_I, CURRENT_SC->cmd_len);
+               scmd_printk(KERN_ERR, CURRENT_SC,
+                           "command sent incompletely (%d/%d)\n",
+                           CMD_I, CURRENT_SC->cmd_len);
        else
                CURRENT_SC->SCp.sent_command++;
 }
@@ -2129,20 +1943,11 @@ static void cmd_end(struct Scsi_Host *shpnt)
  */
 static void status_run(struct Scsi_Host *shpnt)
 {
-       if(TESTLO(SSTAT0,SPIORDY)) {
-               DPRINTK(debug_status, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC));
+       if (TESTLO(SSTAT0, SPIORDY))
                return;
-       }
 
        CURRENT_SC->SCp.Status = GETPORT(SCSIDAT);
 
-#if defined(AHA152X_DEBUG)
-       if (HOSTDATA(shpnt)->debug & debug_status) {
-               printk(DEBUG_LEAD "inbound status %02x ", CMDINFO(CURRENT_SC), CURRENT_SC->SCp.Status);
-               scsi_print_status(CURRENT_SC->SCp.Status);
-               printk("\n");
-       }
-#endif
 }
 
 /*
@@ -2161,10 +1966,6 @@ static void datai_init(struct Scsi_Host *shpnt)
        SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE);
 
        DATA_LEN=0;
-       DPRINTK(debug_datai,
-               DEBUG_LEAD "datai_init: request_bufflen=%d resid=%d\n",
-               CMDINFO(CURRENT_SC), scsi_bufflen(CURRENT_SC),
-               scsi_get_resid(CURRENT_SC));
 }
 
 static void datai_run(struct Scsi_Host *shpnt)
@@ -2186,8 +1987,7 @@ static void datai_run(struct Scsi_Host *shpnt)
                        barrier();
 
                if(TESTLO(DMASTAT, DFIFOFULL|INTSTAT)) {
-                       printk(ERR_LEAD "datai timeout", CMDINFO(CURRENT_SC));
-                       disp_ports(shpnt);
+                       scmd_printk(KERN_ERR, CURRENT_SC, "datai timeout\n");
                        break;
                }
 
@@ -2199,8 +1999,8 @@ static void datai_run(struct Scsi_Host *shpnt)
                                barrier();
 
                        if(TESTLO(SSTAT2, SEMPTY)) {
-                               printk(ERR_LEAD "datai sempty timeout", CMDINFO(CURRENT_SC));
-                               disp_ports(shpnt);
+                               scmd_printk(KERN_ERR, CURRENT_SC,
+                                           "datai sempty timeout");
                                break;
                        }
 
@@ -2209,48 +2009,49 @@ static void datai_run(struct Scsi_Host *shpnt)
 
                if(CURRENT_SC->SCp.this_residual>0) {
                        while(fifodata>0 && CURRENT_SC->SCp.this_residual>0) {
-                               data_count = fifodata>CURRENT_SC->SCp.this_residual ?
+                               data_count = fifodata > CURRENT_SC->SCp.this_residual ?
                                                CURRENT_SC->SCp.this_residual :
                                                fifodata;
                                fifodata -= data_count;
 
-                               if(data_count & 1) {
-                                       DPRINTK(debug_datai, DEBUG_LEAD "8bit\n", CMDINFO(CURRENT_SC));
-                                       SETPORT(DMACNTRL0, ENDMA|_8BIT);
-                                       *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
-                                       CURRENT_SC->SCp.this_residual--;
-                                       DATA_LEN++;
-                                       SETPORT(DMACNTRL0, ENDMA);
-                               }
-       
-                               if(data_count > 1) {
-                                       DPRINTK(debug_datai, DEBUG_LEAD "16bit(%d)\n", CMDINFO(CURRENT_SC), data_count);
-                                       data_count >>= 1;
-                                       insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
-                                       CURRENT_SC->SCp.ptr           += 2 * data_count;
-                                       CURRENT_SC->SCp.this_residual -= 2 * data_count;
-                                       DATA_LEN                      += 2 * data_count;
-                               }
-       
-                               if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) {
-                                               /* advance to next buffer */
-                                               CURRENT_SC->SCp.buffers_residual--;
-                                               CURRENT_SC->SCp.buffer++;
-                                               CURRENT_SC->SCp.ptr           = SG_ADDRESS(CURRENT_SC->SCp.buffer);
-                                               CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
-                               } 
-                       }
-               } else if(fifodata>0) { 
-                       printk(ERR_LEAD "no buffers left for %d(%d) bytes (data overrun!?)\n", CMDINFO(CURRENT_SC), fifodata, GETPORT(FIFOSTAT));
-                        SETPORT(DMACNTRL0, ENDMA|_8BIT);
+                               if (data_count & 1) {
+                                       SETPORT(DMACNTRL0, ENDMA|_8BIT);
+                                       *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
+                                       CURRENT_SC->SCp.this_residual--;
+                                       DATA_LEN++;
+                                       SETPORT(DMACNTRL0, ENDMA);
+                               }
+
+                               if (data_count > 1) {
+                                       data_count >>= 1;
+                                       insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
+                                       CURRENT_SC->SCp.ptr += 2 * data_count;
+                                       CURRENT_SC->SCp.this_residual -= 2 * data_count;
+                                       DATA_LEN += 2 * data_count;
+                               }
+
+                               if (CURRENT_SC->SCp.this_residual == 0 &&
+                                   CURRENT_SC->SCp.buffers_residual > 0) {
+                                       /* advance to next buffer */
+                                       CURRENT_SC->SCp.buffers_residual--;
+                                       CURRENT_SC->SCp.buffer++;
+                                       CURRENT_SC->SCp.ptr           = SG_ADDRESS(CURRENT_SC->SCp.buffer);
+                                       CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
+                               }
+                       }
+               } else if (fifodata > 0) {
+                       scmd_printk(KERN_ERR, CURRENT_SC,
+                                   "no buffers left for %d(%d) bytes"
+                                   " (data overrun!?)\n",
+                                   fifodata, GETPORT(FIFOSTAT));
+                       SETPORT(DMACNTRL0, ENDMA|_8BIT);
                        while(fifodata>0) {
                                int data;
                                data=GETPORT(DATAPORT);
-                               DPRINTK(debug_datai, DEBUG_LEAD "data=%02x\n", CMDINFO(CURRENT_SC), data);
                                fifodata--;
                                DATA_LEN++;
                        }
-                        SETPORT(DMACNTRL0, ENDMA|_8BIT);
+                       SETPORT(DMACNTRL0, ENDMA|_8BIT);
                }
        }
 
@@ -2258,19 +2059,20 @@ static void datai_run(struct Scsi_Host *shpnt)
           TESTLO(DMASTAT, DFIFOEMP) ||
           TESTLO(SSTAT2, SEMPTY) ||
           GETPORT(FIFOSTAT)>0) {
-               /*
+               /*
                 * something went wrong, if there's something left in the fifos
                 * or the phase didn't change
                 */
-               printk(ERR_LEAD "fifos should be empty and phase should have changed\n", CMDINFO(CURRENT_SC));
-               disp_ports(shpnt);
+               scmd_printk(KERN_ERR, CURRENT_SC,
+                           "fifos should be empty and phase should have changed\n");
        }
 
        if(DATA_LEN!=GETSTCNT()) {
-               printk(ERR_LEAD
-                      "manual transfer count differs from automatic (count=%d;stcnt=%d;diff=%d;fifostat=%d)",
-                      CMDINFO(CURRENT_SC), DATA_LEN, GETSTCNT(), GETSTCNT()-DATA_LEN, GETPORT(FIFOSTAT));
-               disp_ports(shpnt);
+               scmd_printk(KERN_ERR, CURRENT_SC,
+                           "manual transfer count differs from automatic "
+                           "(count=%d;stcnt=%d;diff=%d;fifostat=%d)",
+                           DATA_LEN, GETSTCNT(), GETSTCNT()-DATA_LEN,
+                           GETPORT(FIFOSTAT));
                mdelay(10000);
        }
 }
@@ -2279,11 +2081,6 @@ static void datai_end(struct Scsi_Host *shpnt)
 {
        CMD_INC_RESID(CURRENT_SC, -GETSTCNT());
 
-       DPRINTK(debug_datai,
-               DEBUG_LEAD "datai_end: request_bufflen=%d resid=%d stcnt=%d\n",
-               CMDINFO(CURRENT_SC), scsi_bufflen(CURRENT_SC),
-               scsi_get_resid(CURRENT_SC), GETSTCNT());
-
        SETPORT(SXFRCTL0, CH1|CLRSTCNT);
        SETPORT(DMACNTRL0, 0);
 }
@@ -2304,11 +2101,6 @@ static void datao_init(struct Scsi_Host *shpnt)
        SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE );
 
        DATA_LEN = scsi_get_resid(CURRENT_SC);
-
-       DPRINTK(debug_datao,
-               DEBUG_LEAD "datao_init: request_bufflen=%d; resid=%d\n",
-               CMDINFO(CURRENT_SC), scsi_bufflen(CURRENT_SC),
-               scsi_get_resid(CURRENT_SC));
 }
 
 static void datao_run(struct Scsi_Host *shpnt)
@@ -2323,8 +2115,9 @@ static void datao_run(struct Scsi_Host *shpnt)
                        data_count=CURRENT_SC->SCp.this_residual;
 
                if(TESTLO(DMASTAT, DFIFOEMP)) {
-                       printk(ERR_LEAD "datao fifo not empty (%d)", CMDINFO(CURRENT_SC), GETPORT(FIFOSTAT));
-                       disp_ports(shpnt);
+                       scmd_printk(KERN_ERR, CURRENT_SC,
+                                   "datao fifo not empty (%d)",
+                                   GETPORT(FIFOSTAT));
                        break;
                }
 
@@ -2342,7 +2135,7 @@ static void datao_run(struct Scsi_Host *shpnt)
                        CURRENT_SC->SCp.ptr           += 2 * data_count;
                        CURRENT_SC->SCp.this_residual -= 2 * data_count;
                        CMD_INC_RESID(CURRENT_SC, -2 * data_count);
-               }
+               }
 
                if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) {
                        /* advance to next buffer */
@@ -2357,8 +2150,7 @@ static void datao_run(struct Scsi_Host *shpnt)
                        barrier();
 
                if(TESTLO(DMASTAT, DFIFOEMP|INTSTAT)) {
-                       printk(ERR_LEAD "dataout timeout", CMDINFO(CURRENT_SC));
-                       disp_ports(shpnt);
+                       scmd_printk(KERN_ERR, CURRENT_SC, "dataout timeout\n");
                        break;
                }
        }
@@ -2368,35 +2160,23 @@ static void datao_end(struct Scsi_Host *shpnt)
 {
        if(TESTLO(DMASTAT, DFIFOEMP)) {
                int data_count = (DATA_LEN - scsi_get_resid(CURRENT_SC)) -
-                                                                   GETSTCNT();
-
-               DPRINTK(debug_datao, DEBUG_LEAD "datao: %d bytes to resend (%d written, %d transferred)\n",
-                       CMDINFO(CURRENT_SC),
-                       data_count,
-                       DATA_LEN - scsi_get_resid(CURRENT_SC),
-                       GETSTCNT());
+                       GETSTCNT();
 
                CMD_INC_RESID(CURRENT_SC, data_count);
 
                data_count -= CURRENT_SC->SCp.ptr -
-                                            SG_ADDRESS(CURRENT_SC->SCp.buffer);
+                       SG_ADDRESS(CURRENT_SC->SCp.buffer);
                while(data_count>0) {
                        CURRENT_SC->SCp.buffer--;
                        CURRENT_SC->SCp.buffers_residual++;
                        data_count -= CURRENT_SC->SCp.buffer->length;
                }
                CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) -
-                                                                    data_count;
+                       data_count;
                CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length +
-                                                                    data_count;
+                       data_count;
        }
 
-       DPRINTK(debug_datao, DEBUG_LEAD "datao_end: request_bufflen=%d; resid=%d; stcnt=%d\n",
-               CMDINFO(CURRENT_SC),
-               scsi_bufflen(CURRENT_SC),
-               scsi_get_resid(CURRENT_SC),
-               GETSTCNT());
-
        SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
        SETPORT(SXFRCTL0, CH1);
 
@@ -2420,7 +2200,7 @@ static int update_state(struct Scsi_Host *shpnt)
                STATE=rsti;
                SETPORT(SCSISEQ,0);
                SETPORT(SSTAT1,SCSIRSTI);
-       } else if(stat0 & SELDI && PREVSTATE==busfree) {
+       } else if (stat0 & SELDI && PREVSTATE == busfree) {
                STATE=seldi;
        } else if(stat0 & SELDO && CURRENT_SC && (CURRENT_SC->SCp.phase & selecting)) {
                STATE=seldo;
@@ -2445,8 +2225,7 @@ static int update_state(struct Scsi_Host *shpnt)
        }
 
        if((stat0 & SELDI) && STATE!=seldi && !dataphase) {
-               printk(INFO_LEAD "reselection missed?", CMDINFO(CURRENT_SC));
-               disp_ports(shpnt);
+               scmd_printk(KERN_INFO, CURRENT_SC, "reselection missed?");
        }
 
        if(STATE!=PREVSTATE) {
@@ -2464,7 +2243,7 @@ static int update_state(struct Scsi_Host *shpnt)
  */
 static void parerr_run(struct Scsi_Host *shpnt)
 {
-       printk(ERR_LEAD "parity error\n", CMDINFO(CURRENT_SC));
+       scmd_printk(KERN_ERR, CURRENT_SC, "parity error\n");
        done(shpnt, DID_PARITY << 16);
 }
 
@@ -2476,8 +2255,8 @@ static void rsti_run(struct Scsi_Host *shpnt)
 {
        Scsi_Cmnd *ptr;
 
-       printk(KERN_NOTICE "aha152x%d: scsi reset in\n", HOSTNO);
-       
+       shost_printk(KERN_NOTICE, shpnt, "scsi reset in\n");
+
        ptr=DISCONNECTED_SC;
        while(ptr) {
                Scsi_Cmnd *next = SCNEXT(ptr);
@@ -2539,8 +2318,6 @@ static void is_complete(struct Scsi_Host *shpnt)
 
                dataphase=update_state(shpnt);
 
-               DPRINTK(debug_phases, LEAD "start %s %s(%s)\n", CMDINFO(CURRENT_SC), states[STATE].name, states[PREVSTATE].name, states[LASTSTATE].name);
-
                /*
                 * end previous state
                 *
@@ -2567,9 +2344,9 @@ static void is_complete(struct Scsi_Host *shpnt)
                if(dataphase) {
                        SETPORT(SSTAT0, REQINIT);
                        SETPORT(SCSISIG, GETPORT(SCSISIG) & P_MASK);
-                       SETPORT(SSTAT1, PHASECHG);  
+                       SETPORT(SSTAT1, PHASECHG);
                }
-               
+
                /*
                 * enable SPIO mode if previous didn't use it
                 * and this one does
@@ -2581,14 +2358,14 @@ static void is_complete(struct Scsi_Host *shpnt)
                        if(CURRENT_SC)
                                CURRENT_SC->SCp.phase |= spiordy;
                }
-               
+
                /*
                 * initialize for new state
                 *
                 */
                if(PREVSTATE!=STATE && states[STATE].init)
                        states[STATE].init(shpnt);
-               
+
                /*
                 * handle current state
                 *
@@ -2596,8 +2373,9 @@ static void is_complete(struct Scsi_Host *shpnt)
                if(states[STATE].run)
                        states[STATE].run(shpnt);
                else
-                       printk(ERR_LEAD "unexpected state (%x)\n", CMDINFO(CURRENT_SC), STATE);
-               
+                       scmd_printk(KERN_ERR, CURRENT_SC,
+                                   "unexpected state (%x)\n", STATE);
+
                /*
                 * setup controller to interrupt on
                 * the next expected condition and
@@ -2613,7 +2391,6 @@ static void is_complete(struct Scsi_Host *shpnt)
                HOSTDATA(shpnt)->time[STATE] += jiffies-start;
 #endif
 
-               DPRINTK(debug_phases, LEAD "end %s %s(%s)\n", CMDINFO(CURRENT_SC), states[STATE].name, states[PREVSTATE].name, states[LASTSTATE].name);
        } while(pending);
 
        /*
@@ -2626,289 +2403,42 @@ static void is_complete(struct Scsi_Host *shpnt)
 }
 
 
-/* 
+/*
  * Dump the current driver status and panic
  */
 static void aha152x_error(struct Scsi_Host *shpnt, char *msg)
 {
-       printk(KERN_EMERG "\naha152x%d: %s\n", HOSTNO, msg);
+       shost_printk(KERN_EMERG, shpnt, "%s\n", msg);
        show_queues(shpnt);
        panic("aha152x panic\n");
 }
 
-/*
- * Display registers of AIC-6260
- */
-static void disp_ports(struct Scsi_Host *shpnt)
-{
-#if defined(AHA152X_DEBUG)
-       int s;
-
-       printk("\n%s: %s(%s) ",
-               CURRENT_SC ? "busy" : "waiting",
-               states[STATE].name,
-               states[PREVSTATE].name);
-
-       s = GETPORT(SCSISEQ);
-       printk("SCSISEQ( ");
-       if (s & TEMODEO)
-               printk("TARGET MODE ");
-       if (s & ENSELO)
-               printk("SELO ");
-       if (s & ENSELI)
-               printk("SELI ");
-       if (s & ENRESELI)
-               printk("RESELI ");
-       if (s & ENAUTOATNO)
-               printk("AUTOATNO ");
-       if (s & ENAUTOATNI)
-               printk("AUTOATNI ");
-       if (s & ENAUTOATNP)
-               printk("AUTOATNP ");
-       if (s & SCSIRSTO)
-               printk("SCSIRSTO ");
-       printk(");");
-
-       printk(" SCSISIG(");
-       s = GETPORT(SCSISIG);
-       switch (s & P_MASK) {
-       case P_DATAO:
-               printk("DATA OUT");
-               break;
-       case P_DATAI:
-               printk("DATA IN");
-               break;
-       case P_CMD:
-               printk("COMMAND");
-               break;
-       case P_STATUS:
-               printk("STATUS");
-               break;
-       case P_MSGO:
-               printk("MESSAGE OUT");
-               break;
-       case P_MSGI:
-               printk("MESSAGE IN");
-               break;
-       default:
-               printk("*invalid*");
-               break;
-       }
-
-       printk("); ");
-
-       printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
-
-       printk("SSTAT( ");
-       s = GETPORT(SSTAT0);
-       if (s & TARGET)
-               printk("TARGET ");
-       if (s & SELDO)
-               printk("SELDO ");
-       if (s & SELDI)
-               printk("SELDI ");
-       if (s & SELINGO)
-               printk("SELINGO ");
-       if (s & SWRAP)
-               printk("SWRAP ");
-       if (s & SDONE)
-               printk("SDONE ");
-       if (s & SPIORDY)
-               printk("SPIORDY ");
-       if (s & DMADONE)
-               printk("DMADONE ");
-
-       s = GETPORT(SSTAT1);
-       if (s & SELTO)
-               printk("SELTO ");
-       if (s & ATNTARG)
-               printk("ATNTARG ");
-       if (s & SCSIRSTI)
-               printk("SCSIRSTI ");
-       if (s & PHASEMIS)
-               printk("PHASEMIS ");
-       if (s & BUSFREE)
-               printk("BUSFREE ");
-       if (s & SCSIPERR)
-               printk("SCSIPERR ");
-       if (s & PHASECHG)
-               printk("PHASECHG ");
-       if (s & REQINIT)
-               printk("REQINIT ");
-       printk("); ");
-
-
-       printk("SSTAT( ");
-
-       s = GETPORT(SSTAT0) & GETPORT(SIMODE0);
-
-       if (s & TARGET)
-               printk("TARGET ");
-       if (s & SELDO)
-               printk("SELDO ");
-       if (s & SELDI)
-               printk("SELDI ");
-       if (s & SELINGO)
-               printk("SELINGO ");
-       if (s & SWRAP)
-               printk("SWRAP ");
-       if (s & SDONE)
-               printk("SDONE ");
-       if (s & SPIORDY)
-               printk("SPIORDY ");
-       if (s & DMADONE)
-               printk("DMADONE ");
-
-       s = GETPORT(SSTAT1) & GETPORT(SIMODE1);
-
-       if (s & SELTO)
-               printk("SELTO ");
-       if (s & ATNTARG)
-               printk("ATNTARG ");
-       if (s & SCSIRSTI)
-               printk("SCSIRSTI ");
-       if (s & PHASEMIS)
-               printk("PHASEMIS ");
-       if (s & BUSFREE)
-               printk("BUSFREE ");
-       if (s & SCSIPERR)
-               printk("SCSIPERR ");
-       if (s & PHASECHG)
-               printk("PHASECHG ");
-       if (s & REQINIT)
-               printk("REQINIT ");
-       printk("); ");
-
-       printk("SXFRCTL0( ");
-
-       s = GETPORT(SXFRCTL0);
-       if (s & SCSIEN)
-               printk("SCSIEN ");
-       if (s & DMAEN)
-               printk("DMAEN ");
-       if (s & CH1)
-               printk("CH1 ");
-       if (s & CLRSTCNT)
-               printk("CLRSTCNT ");
-       if (s & SPIOEN)
-               printk("SPIOEN ");
-       if (s & CLRCH1)
-               printk("CLRCH1 ");
-       printk("); ");
-
-       printk("SIGNAL( ");
-
-       s = GETPORT(SCSISIG);
-       if (s & SIG_ATNI)
-               printk("ATNI ");
-       if (s & SIG_SELI)
-               printk("SELI ");
-       if (s & SIG_BSYI)
-               printk("BSYI ");
-       if (s & SIG_REQI)
-               printk("REQI ");
-       if (s & SIG_ACKI)
-               printk("ACKI ");
-       printk("); ");
-
-       printk("SELID (%02x), ", GETPORT(SELID));
-
-       printk("STCNT (%d), ", GETSTCNT());
-       
-       printk("SSTAT2( ");
-
-       s = GETPORT(SSTAT2);
-       if (s & SOFFSET)
-               printk("SOFFSET ");
-       if (s & SEMPTY)
-               printk("SEMPTY ");
-       if (s & SFULL)
-               printk("SFULL ");
-       printk("); SFCNT (%d); ", s & (SFULL | SFCNT));
-
-       s = GETPORT(SSTAT3);
-       printk("SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f);
-
-       printk("SSTAT4( ");
-       s = GETPORT(SSTAT4);
-       if (s & SYNCERR)
-               printk("SYNCERR ");
-       if (s & FWERR)
-               printk("FWERR ");
-       if (s & FRERR)
-               printk("FRERR ");
-       printk("); ");
-
-       printk("DMACNTRL0( ");
-       s = GETPORT(DMACNTRL0);
-       printk("%s ", s & _8BIT ? "8BIT" : "16BIT");
-       printk("%s ", s & DMA ? "DMA" : "PIO");
-       printk("%s ", s & WRITE_READ ? "WRITE" : "READ");
-       if (s & ENDMA)
-               printk("ENDMA ");
-       if (s & INTEN)
-               printk("INTEN ");
-       if (s & RSTFIFO)
-               printk("RSTFIFO ");
-       if (s & SWINT)
-               printk("SWINT ");
-       printk("); ");
-
-       printk("DMASTAT( ");
-       s = GETPORT(DMASTAT);
-       if (s & ATDONE)
-               printk("ATDONE ");
-       if (s & WORDRDY)
-               printk("WORDRDY ");
-       if (s & DFIFOFULL)
-               printk("DFIFOFULL ");
-       if (s & DFIFOEMP)
-               printk("DFIFOEMP ");
-       printk(")\n");
-#endif
-}
-
 /*
  * display enabled interrupts
  */
 static void disp_enintr(struct Scsi_Host *shpnt)
 {
-       int s;
-
-       printk(KERN_DEBUG "enabled interrupts ( ");
-
-       s = GETPORT(SIMODE0);
-       if (s & ENSELDO)
-               printk("ENSELDO ");
-       if (s & ENSELDI)
-               printk("ENSELDI ");
-       if (s & ENSELINGO)
-               printk("ENSELINGO ");
-       if (s & ENSWRAP)
-               printk("ENSWRAP ");
-       if (s & ENSDONE)
-               printk("ENSDONE ");
-       if (s & ENSPIORDY)
-               printk("ENSPIORDY ");
-       if (s & ENDMADONE)
-               printk("ENDMADONE ");
-
-       s = GETPORT(SIMODE1);
-       if (s & ENSELTIMO)
-               printk("ENSELTIMO ");
-       if (s & ENATNTARG)
-               printk("ENATNTARG ");
-       if (s & ENPHASEMIS)
-               printk("ENPHASEMIS ");
-       if (s & ENBUSFREE)
-               printk("ENBUSFREE ");
-       if (s & ENSCSIPERR)
-               printk("ENSCSIPERR ");
-       if (s & ENPHASECHG)
-               printk("ENPHASECHG ");
-       if (s & ENREQINIT)
-               printk("ENREQINIT ");
-       printk(")\n");
+       int s0, s1;
+
+       s0 = GETPORT(SIMODE0);
+       s1 = GETPORT(SIMODE1);
+
+       shost_printk(KERN_DEBUG, shpnt,
+                    "enabled interrupts (%s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
+                    (s0 & ENSELDO) ? "ENSELDO " : "",
+                    (s0 & ENSELDI) ? "ENSELDI " : "",
+                    (s0 & ENSELINGO) ? "ENSELINGO " : "",
+                    (s0 & ENSWRAP) ? "ENSWRAP " : "",
+                    (s0 & ENSDONE) ? "ENSDONE " : "",
+                    (s0 & ENSPIORDY) ? "ENSPIORDY " : "",
+                    (s0 & ENDMADONE) ? "ENDMADONE " : "",
+                    (s1 & ENSELTIMO) ? "ENSELTIMO " : "",
+                    (s1 & ENATNTARG) ? "ENATNTARG " : "",
+                    (s1 & ENPHASEMIS) ? "ENPHASEMIS " : "",
+                    (s1 & ENBUSFREE) ? "ENBUSFREE " : "",
+                    (s1 & ENSCSIPERR) ? "ENSCSIPERR " : "",
+                    (s1 & ENPHASECHG) ? "ENPHASECHG " : "",
+                    (s1 & ENREQINIT) ? "ENREQINIT " : "");
 }
 
 /*
@@ -2916,36 +2446,21 @@ static void disp_enintr(struct Scsi_Host *shpnt)
  */
 static void show_command(Scsi_Cmnd *ptr)
 {
-       scmd_printk(KERN_DEBUG, ptr, "%p: cmnd=(", ptr);
-
-       __scsi_print_command(ptr->cmnd);
-
-       printk(KERN_DEBUG "); request_bufflen=%d; resid=%d; phase |",
-              scsi_bufflen(ptr), scsi_get_resid(ptr));
-
-       if (ptr->SCp.phase & not_issued)
-               printk("not issued|");
-       if (ptr->SCp.phase & selecting)
-               printk("selecting|");
-       if (ptr->SCp.phase & identified)
-               printk("identified|");
-       if (ptr->SCp.phase & disconnected)
-               printk("disconnected|");
-       if (ptr->SCp.phase & completed)
-               printk("completed|");
-       if (ptr->SCp.phase & spiordy)
-               printk("spiordy|");
-       if (ptr->SCp.phase & syncneg)
-               printk("syncneg|");
-       if (ptr->SCp.phase & aborted)
-               printk("aborted|");
-       if (ptr->SCp.phase & resetted)
-               printk("resetted|");
-       if( SCDATA(ptr) ) {
-               printk("; next=0x%p\n", SCNEXT(ptr));
-       } else {
-               printk("; next=(host scribble NULL)\n");
-       }
+       scsi_print_command(ptr);
+       scmd_printk(KERN_DEBUG, ptr,
+                   "request_bufflen=%d; resid=%d; "
+                   "phase |%s%s%s%s%s%s%s%s%s; next=0x%p",
+                   scsi_bufflen(ptr), scsi_get_resid(ptr),
+                   (ptr->SCp.phase & not_issued) ? "not issued|" : "",
+                   (ptr->SCp.phase & selecting) ? "selecting|" : "",
+                   (ptr->SCp.phase & identified) ? "identified|" : "",
+                   (ptr->SCp.phase & disconnected) ? "disconnected|" : "",
+                   (ptr->SCp.phase & completed) ? "completed|" : "",
+                   (ptr->SCp.phase & spiordy) ? "spiordy|" : "",
+                   (ptr->SCp.phase & syncneg) ? "syncneg|" : "",
+                   (ptr->SCp.phase & aborted) ? "aborted|" : "",
+                   (ptr->SCp.phase & resetted) ? "resetted|" : "",
+                   (SCDATA(ptr)) ? SCNEXT(ptr) : NULL);
 }
 
 /*
@@ -2972,7 +2487,6 @@ static void show_queues(struct Scsi_Host *shpnt)
        for (ptr = DISCONNECTED_SC; ptr; ptr = SCDATA(ptr) ? SCNEXT(ptr) : NULL)
                show_command(ptr);
 
-       disp_ports(shpnt);
        disp_enintr(shpnt);
 }
 
@@ -3276,15 +2790,6 @@ static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
        if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0)
                return -EINVAL;
 
-#if defined(AHA152X_DEBUG)
-       if(length>14 && strncmp("debug ", buffer+8, 6)==0) {
-               int debug = HOSTDATA(shpnt)->debug;
-
-               HOSTDATA(shpnt)->debug = simple_strtoul(buffer+14, NULL, 0);
-
-               printk(KERN_INFO "aha152x%d: debugging options set to 0x%04x (were 0x%04x)\n", HOSTNO, HOSTDATA(shpnt)->debug, debug);
-       } else
-#endif
 #if defined(AHA152X_STAT)
        if(length>13 && strncmp("reset", buffer+8, 5)==0) {
                int i;
@@ -3302,7 +2807,7 @@ static int aha152x_set_info(struct Scsi_Host *shpnt, char *buffer, int length)
                        HOSTDATA(shpnt)->time[i]=0;
                }
 
-               printk(KERN_INFO "aha152x%d: stats reseted.\n", HOSTNO);
+               shost_printk(KERN_INFO, shpnt, "aha152x: stats reset.\n");
 
        } else
 #endif
@@ -3343,29 +2848,6 @@ static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
                                        (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50,
                                    HOSTDATA(shpnt)->syncrate[i] & 0x0f);
        }
-#if defined(AHA152X_DEBUG)
-#define PDEBUG(flags,txt) \
-       if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt);
-
-       SPRINTF("enabled debugging options: ");
-
-       PDEBUG(debug_procinfo, "procinfo");
-       PDEBUG(debug_queue, "queue");
-       PDEBUG(debug_intr, "interrupt");
-       PDEBUG(debug_selection, "selection");
-       PDEBUG(debug_msgo, "message out");
-       PDEBUG(debug_msgi, "message in");
-       PDEBUG(debug_status, "status");
-       PDEBUG(debug_cmd, "command");
-       PDEBUG(debug_datai, "data in");
-       PDEBUG(debug_datao, "data out");
-       PDEBUG(debug_eh, "eh");
-       PDEBUG(debug_locking, "locks");
-       PDEBUG(debug_phases, "phases");
-
-       SPRINTF("\n");
-#endif
-
        SPRINTF("\nqueue status:\n");
        DO_LOCK(flags);
        if (ISSUE_SC) {
@@ -3393,8 +2875,8 @@ static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
 
 #if defined(AHA152X_STAT)
        SPRINTF("statistics:\n"
-               "total commands:               %d\n"
-               "disconnections:               %d\n"
+               "total commands:               %d\n"
+               "disconnections:               %d\n"
                "busfree with check condition: %d\n"
                "busfree without old command:  %d\n"
                "busfree without new command:  %d\n"
@@ -3413,7 +2895,7 @@ static int aha152x_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
                HOSTDATA(shpnt)->busfree_without_any_action);
        for(i=0; i<maxstate; i++) {
                SPRINTF("%-10s %-12d %-12d %-12ld\n",
-                       states[i].name,
+                       states[i].name,
                        HOSTDATA(shpnt)->count_trans[i],
                        HOSTDATA(shpnt)->count[i],
                        HOSTDATA(shpnt)->time[i]);
@@ -3671,25 +3153,19 @@ static int __init aha152x_init(void)
                        setup[setup_count].synchronous = aha152x[5];
                        setup[setup_count].delay       = aha152x[6];
                        setup[setup_count].ext_trans   = aha152x[7];
-#if defined(AHA152X_DEBUG)
-                       setup[setup_count].debug       = aha152x[8];
-#endif
-               } else if(io[0]!=0 || irq[0]!=0) {
+               } else if (io[0] != 0 || irq[0] != 0) {
                        if(io[0]!=0)  setup[setup_count].io_port = io[0];
                        if(irq[0]!=0) setup[setup_count].irq     = irq[0];
 
-                       setup[setup_count].scsiid      = scsiid[0];
-                       setup[setup_count].reconnect   = reconnect[0];
-                       setup[setup_count].parity      = parity[0];
-                       setup[setup_count].synchronous = sync[0];
-                       setup[setup_count].delay       = delay[0];
-                       setup[setup_count].ext_trans   = exttrans[0];
-#if defined(AHA152X_DEBUG)
-                       setup[setup_count].debug       = debug[0];
-#endif
+                       setup[setup_count].scsiid      = scsiid[0];
+                       setup[setup_count].reconnect   = reconnect[0];
+                       setup[setup_count].parity      = parity[0];
+                       setup[setup_count].synchronous = sync[0];
+                       setup[setup_count].delay       = delay[0];
+                       setup[setup_count].ext_trans   = exttrans[0];
                }
 
-               if (checksetup(&setup[setup_count]))
+               if (checksetup(&setup[setup_count]))
                        setup_count++;
                else
                        printk(KERN_ERR "aha152x: invalid module params io=0x%x, irq=%d,scsiid=%d,reconnect=%d,parity=%d,sync=%d,delay=%d,exttrans=%d\n",
@@ -3714,22 +3190,16 @@ static int __init aha152x_init(void)
                        setup[setup_count].synchronous = aha152x1[5];
                        setup[setup_count].delay       = aha152x1[6];
                        setup[setup_count].ext_trans   = aha152x1[7];
-#if defined(AHA152X_DEBUG)
-                       setup[setup_count].debug       = aha152x1[8];
-#endif
-               } else if(io[1]!=0 || irq[1]!=0) {
+               } else if (io[1] != 0 || irq[1] != 0) {
                        if(io[1]!=0)  setup[setup_count].io_port = io[1];
                        if(irq[1]!=0) setup[setup_count].irq     = irq[1];
 
-                       setup[setup_count].scsiid      = scsiid[1];
-                       setup[setup_count].reconnect   = reconnect[1];
-                       setup[setup_count].parity      = parity[1];
-                       setup[setup_count].synchronous = sync[1];
-                       setup[setup_count].delay       = delay[1];
-                       setup[setup_count].ext_trans   = exttrans[1];
-#if defined(AHA152X_DEBUG)
-                       setup[setup_count].debug       = debug[1];
-#endif
+                       setup[setup_count].scsiid      = scsiid[1];
+                       setup[setup_count].reconnect   = reconnect[1];
+                       setup[setup_count].parity      = parity[1];
+                       setup[setup_count].synchronous = sync[1];
+                       setup[setup_count].delay       = delay[1];
+                       setup[setup_count].ext_trans   = exttrans[1];
                }
                if (checksetup(&setup[setup_count]))
                        setup_count++;
@@ -3776,9 +3246,6 @@ static int __init aha152x_init(void)
                        setup[setup_count].synchronous = 1;
                        setup[setup_count].delay       = DELAY_DEFAULT;
                        setup[setup_count].ext_trans   = 0;
-#if defined(AHA152X_DEBUG)
-                       setup[setup_count].debug       = DEBUG_DEFAULT;
-#endif
 #if defined(__ISAPNP__)
                        pnpdev[setup_count]            = dev;
 #endif
@@ -3847,9 +3314,6 @@ static int __init aha152x_init(void)
                        setup[setup_count].synchronous = conf.cf_syncneg;
                        setup[setup_count].delay = DELAY_DEFAULT;
                        setup[setup_count].ext_trans = 0;
-#if defined(AHA152X_DEBUG)
-                       setup[setup_count].debug = DEBUG_DEFAULT;
-#endif
                        setup_count++;
 
                }
@@ -3903,11 +3367,8 @@ module_exit(aha152x_exit);
 #if !defined(MODULE)
 static int __init aha152x_setup(char *str)
 {
-#if defined(AHA152X_DEBUG)
-       int ints[11];
-#else
        int ints[10];
-#endif
+
        get_options(str, ARRAY_SIZE(ints), ints);
 
        if(setup_count>=ARRAY_SIZE(setup)) {
@@ -3924,16 +3385,9 @@ static int __init aha152x_setup(char *str)
        setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
        setup[setup_count].delay       = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
        setup[setup_count].ext_trans   = ints[0] >= 8 ? ints[8] : 0;
-#if defined(AHA152X_DEBUG)
-       setup[setup_count].debug       = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT;
-       if (ints[0] > 9) {
-               printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
-                      "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>[,<DEBUG>]]]]]]]]\n");
-#else
        if (ints[0] > 8) {                                                /*}*/
                printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
                       "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
-#endif
        } else {
                setup_count++;
                return 0;
index 5f3101797c93977c98cf047797868df0d00da5c0..31ace4bef8fe98492d47a7134f1192b2d17b6647 100644 (file)
@@ -531,7 +531,7 @@ static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
  * quiet as possible...
  */
 
-       return 0;
+       return SUCCESS;
 }
 
 static struct scsi_host_template aha1740_template = {
index ed333669a7dccf811be095a270414974c37b3836..d5c7b193d8d3d6c86e3432d478ce1e6385ddbf06 100644 (file)
@@ -925,6 +925,7 @@ struct scsi_host_template aic79xx_driver_template = {
        .slave_configure        = ahd_linux_slave_configure,
        .target_alloc           = ahd_linux_target_alloc,
        .target_destroy         = ahd_linux_target_destroy,
+       .use_blk_tags           = 1,
 };
 
 /******************************** Bus DMA *************************************/
@@ -1468,12 +1469,9 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
 
        switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
        case AHD_DEV_Q_BASIC:
-               scsi_set_tag_type(sdev, MSG_SIMPLE_TASK);
-               scsi_activate_tcq(sdev, dev->openings + dev->active);
-               break;
        case AHD_DEV_Q_TAGGED:
-               scsi_set_tag_type(sdev, MSG_ORDERED_TASK);
-               scsi_activate_tcq(sdev, dev->openings + dev->active);
+               scsi_change_queue_depth(sdev,
+                               dev->openings + dev->active);
                break;
        default:
                /*
@@ -1482,7 +1480,7 @@ ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
                 * serially on the controller/device.  This should
                 * remove some latency.
                 */
-               scsi_deactivate_tcq(sdev, 1);
+               scsi_change_queue_depth(sdev, 1);
                break;
        }
 }
@@ -1619,15 +1617,6 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
        }
 
        if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
-               int     msg_bytes;
-               uint8_t tag_msgs[2];
-
-               msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
-               if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
-                       hscb->control |= tag_msgs[0];
-                       if (tag_msgs[0] == MSG_ORDERED_TASK)
-                               dev->commands_since_idle_or_otag = 0;
-               } else
                if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
                 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
                        hscb->control |= MSG_ORDERED_TASK;
index d2c9bf39033d2dfd2d427ef1be833d96167ad94e..88360116dbcb05787aff6323a41f20411ea53d69 100644 (file)
@@ -812,6 +812,7 @@ struct scsi_host_template aic7xxx_driver_template = {
        .slave_configure        = ahc_linux_slave_configure,
        .target_alloc           = ahc_linux_target_alloc,
        .target_destroy         = ahc_linux_target_destroy,
+       .use_blk_tags           = 1,
 };
 
 /**************************** Tasklet Handler *********************************/
@@ -1334,13 +1335,9 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
        }
        switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
        case AHC_DEV_Q_BASIC:
-               scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
-               scsi_activate_tcq(sdev, dev->openings + dev->active);
-               break;
        case AHC_DEV_Q_TAGGED:
-               scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
-               scsi_activate_tcq(sdev, dev->openings + dev->active);
-               break;
+               scsi_change_queue_depth(sdev,
+                               dev->openings + dev->active);
        default:
                /*
                 * We allow the OS to queue 2 untagged transactions to
@@ -1348,7 +1345,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
                 * serially on the controller/device.  This should
                 * remove some latency.
                 */
-               scsi_deactivate_tcq(sdev, 2);
+               scsi_change_queue_depth(sdev, 2);
                break;
        }
 }
@@ -1447,7 +1444,7 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
         * we are storing a full busy target *lun*
         * table in SCB space.
         */
-       if (!blk_rq_tagged(cmd->request)
+       if (!(cmd->flags & SCMD_TAGGED)
            && (ahc->features & AHC_SCB_BTT) == 0) {
                int target_offset;
 
@@ -1501,15 +1498,7 @@ ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
        }
 
        if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
-               int     msg_bytes;
-               uint8_t tag_msgs[2];
-               
-               msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
-               if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
-                       hscb->control |= tag_msgs[0];
-                       if (tag_msgs[0] == MSG_ORDERED_TASK)
-                               dev->commands_since_idle_or_otag = 0;
-               } else if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
+               if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
                                && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
                        hscb->control |= MSG_ORDERED_TASK;
                        dev->commands_since_idle_or_otag = 0;
index 66cda669b417b56ee84fb9c441a2b0a2fc342021..26d4ad9ede2e8f074319a320a504f727f6fb1658 100644 (file)
@@ -78,7 +78,7 @@ void asd_dev_gone(struct domain_device *dev);
 
 void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id);
 
-int  asd_execute_task(struct sas_task *, int num, gfp_t gfp_flags);
+int  asd_execute_task(struct sas_task *task, gfp_t gfp_flags);
 
 void asd_set_dmamode(struct domain_device *dev);
 
index 4df867e07b2022df773ce0f7f0115e2b7bf4a5e7..9f636a34d5957c82e155fc63002301a4fbee8c3c 100644 (file)
@@ -1200,8 +1200,7 @@ static void asd_start_scb_timers(struct list_head *list)
  * Case A: we can send the whole batch at once.  Increment "pending"
  * in the beginning of this function, when it is checked, in order to
  * eliminate races when this function is called by multiple processes.
- * Case B: should never happen if the managing layer considers
- * lldd_queue_size.
+ * Case B: should never happen.
  */
 int asd_post_ascb_list(struct asd_ha_struct *asd_ha, struct asd_ascb *ascb,
                       int num)
index c56741fc4b994ad38138261b63444d28f22c3fc8..14fc018436c235cc3d2267fb889d4831f4dc60ce 100644 (file)
@@ -49,14 +49,6 @@ MODULE_PARM_DESC(use_msi, "\n"
        "\tEnable(1) or disable(0) using PCI MSI.\n"
        "\tDefault: 0");
 
-static int lldd_max_execute_num = 0;
-module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
-MODULE_PARM_DESC(collector, "\n"
-       "\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
-       "\tMode.  If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
-       "\tThe aic94xx SAS LLDD supports both modes.\n"
-       "\tDefault: 0 (Direct Mode).\n");
-
 static struct scsi_transport_template *aic94xx_transport_template;
 static int asd_scan_finished(struct Scsi_Host *, unsigned long);
 static void asd_scan_start(struct Scsi_Host *);
@@ -83,6 +75,8 @@ static struct scsi_host_template aic94xx_sht = {
        .eh_bus_reset_handler   = sas_eh_bus_reset_handler,
        .target_destroy         = sas_target_destroy,
        .ioctl                  = sas_ioctl,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 static int asd_map_memio(struct asd_ha_struct *asd_ha)
@@ -709,9 +703,6 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha)
        asd_ha->sas_ha.sas_port= sas_ports;
        asd_ha->sas_ha.num_phys= ASD_MAX_PHYS;
 
-       asd_ha->sas_ha.lldd_queue_size = asd_ha->seq.can_queue;
-       asd_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num;
-
        return sas_register_ha(&asd_ha->sas_ha);
 }
 
index 59b86e260ce977821c21fea8164fc936d3f4df70..5ff1ce7ba1f438a102cdd187c57c8ac8073caddb 100644 (file)
@@ -543,8 +543,7 @@ static int asd_can_queue(struct asd_ha_struct *asd_ha, int num)
        return res;
 }
 
-int asd_execute_task(struct sas_task *task, const int num,
-                    gfp_t gfp_flags)
+int asd_execute_task(struct sas_task *task, gfp_t gfp_flags)
 {
        int res = 0;
        LIST_HEAD(alist);
@@ -553,11 +552,11 @@ int asd_execute_task(struct sas_task *task, const int num,
        struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
        unsigned long flags;
 
-       res = asd_can_queue(asd_ha, num);
+       res = asd_can_queue(asd_ha, 1);
        if (res)
                return res;
 
-       res = num;
+       res = 1;
        ascb = asd_ascb_alloc_list(asd_ha, &res, gfp_flags);
        if (res) {
                res = -ENOMEM;
@@ -568,7 +567,7 @@ int asd_execute_task(struct sas_task *task, const int num,
        list_for_each_entry(a, &alist, list) {
                a->uldd_task = t;
                t->lldd_task = a;
-               t = list_entry(t->list.next, struct sas_task, list);
+               break;
        }
        list_for_each_entry(a, &alist, list) {
                t = a->uldd_task;
@@ -601,7 +600,7 @@ int asd_execute_task(struct sas_task *task, const int num,
        }
        list_del_init(&alist);
 
-       res = asd_post_ascb_list(asd_ha, ascb, num);
+       res = asd_post_ascb_list(asd_ha, ascb, 1);
        if (unlikely(res)) {
                a = NULL;
                __list_add(&alist, ascb->list.prev, &ascb->list);
@@ -639,6 +638,6 @@ out_err_unmap:
 out_err:
        if (ascb)
                asd_ascb_free_list(ascb);
-       asd_can_dequeue(asd_ha, num);
+       asd_can_dequeue(asd_ha, 1);
        return res;
 }
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
new file mode 100644 (file)
index 0000000..aa3e2c7
--- /dev/null
@@ -0,0 +1,586 @@
+/*
+ * AMD am53c974 driver.
+ * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include <scsi/scsi_host.h>
+
+#include "esp_scsi.h"
+
+#define DRV_MODULE_NAME "am53c974"
+#define DRV_MODULE_VERSION "1.00"
+
+static bool am53c974_debug;
+static bool am53c974_fenab = true;
+
+#define esp_dma_log(f, a...)                                           \
+       do {                                                            \
+               if (am53c974_debug)                                     \
+                       shost_printk(KERN_DEBUG, esp->host, f, ##a);    \
+       } while (0)
+
+#define ESP_DMA_CMD 0x10
+#define ESP_DMA_STC 0x11
+#define ESP_DMA_SPA 0x12
+#define ESP_DMA_WBC 0x13
+#define ESP_DMA_WAC 0x14
+#define ESP_DMA_STATUS 0x15
+#define ESP_DMA_SMDLA 0x16
+#define ESP_DMA_WMAC 0x17
+
+#define ESP_DMA_CMD_IDLE 0x00
+#define ESP_DMA_CMD_BLAST 0x01
+#define ESP_DMA_CMD_ABORT 0x02
+#define ESP_DMA_CMD_START 0x03
+#define ESP_DMA_CMD_MASK  0x03
+#define ESP_DMA_CMD_DIAG 0x04
+#define ESP_DMA_CMD_MDL 0x10
+#define ESP_DMA_CMD_INTE_P 0x20
+#define ESP_DMA_CMD_INTE_D 0x40
+#define ESP_DMA_CMD_DIR 0x80
+
+#define ESP_DMA_STAT_PWDN 0x01
+#define ESP_DMA_STAT_ERROR 0x02
+#define ESP_DMA_STAT_ABORT 0x04
+#define ESP_DMA_STAT_DONE 0x08
+#define ESP_DMA_STAT_SCSIINT 0x10
+#define ESP_DMA_STAT_BCMPLT 0x20
+
+/* EEPROM is accessed with 16-bit values */
+#define DC390_EEPROM_READ 0x80
+#define DC390_EEPROM_LEN 0x40
+
+/*
+ * DC390 EEPROM
+ *
+ * 8 * 4 bytes of per-device options
+ * followed by HBA specific options
+ */
+
+/* Per-device options */
+#define DC390_EE_MODE1 0x00
+#define DC390_EE_SPEED 0x01
+
+/* HBA-specific options */
+#define DC390_EE_ADAPT_SCSI_ID 0x40
+#define DC390_EE_MODE2 0x41
+#define DC390_EE_DELAY 0x42
+#define DC390_EE_TAG_CMD_NUM 0x43
+
+#define DC390_EE_MODE1_PARITY_CHK   0x01
+#define DC390_EE_MODE1_SYNC_NEGO    0x02
+#define DC390_EE_MODE1_EN_DISC      0x04
+#define DC390_EE_MODE1_SEND_START   0x08
+#define DC390_EE_MODE1_TCQ          0x10
+
+#define DC390_EE_MODE2_MORE_2DRV    0x01
+#define DC390_EE_MODE2_GREATER_1G   0x02
+#define DC390_EE_MODE2_RST_SCSI_BUS 0x04
+#define DC390_EE_MODE2_ACTIVE_NEGATION 0x08
+#define DC390_EE_MODE2_NO_SEEK      0x10
+#define DC390_EE_MODE2_LUN_CHECK    0x20
+
+struct pci_esp_priv {
+       struct esp *esp;
+       u8 dma_status;
+};
+
+static void pci_esp_dma_drain(struct esp *esp);
+
+static inline struct pci_esp_priv *pci_esp_get_priv(struct esp *esp)
+{
+       struct pci_dev *pdev = esp->dev;
+
+       return pci_get_drvdata(pdev);
+}
+
+static void pci_esp_write8(struct esp *esp, u8 val, unsigned long reg)
+{
+       iowrite8(val, esp->regs + (reg * 4UL));
+}
+
+static u8 pci_esp_read8(struct esp *esp, unsigned long reg)
+{
+       return ioread8(esp->regs + (reg * 4UL));
+}
+
+static void pci_esp_write32(struct esp *esp, u32 val, unsigned long reg)
+{
+       return iowrite32(val, esp->regs + (reg * 4UL));
+}
+
+static dma_addr_t pci_esp_map_single(struct esp *esp, void *buf,
+                                    size_t sz, int dir)
+{
+       return pci_map_single(esp->dev, buf, sz, dir);
+}
+
+static int pci_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+                         int num_sg, int dir)
+{
+       return pci_map_sg(esp->dev, sg, num_sg, dir);
+}
+
+static void pci_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+                                size_t sz, int dir)
+{
+       pci_unmap_single(esp->dev, addr, sz, dir);
+}
+
+static void pci_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+                            int num_sg, int dir)
+{
+       pci_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int pci_esp_irq_pending(struct esp *esp)
+{
+       struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+       pep->dma_status = pci_esp_read8(esp, ESP_DMA_STATUS);
+       esp_dma_log("dma intr dreg[%02x]\n", pep->dma_status);
+
+       if (pep->dma_status & (ESP_DMA_STAT_ERROR |
+                              ESP_DMA_STAT_ABORT |
+                              ESP_DMA_STAT_DONE |
+                              ESP_DMA_STAT_SCSIINT))
+               return 1;
+
+       return 0;
+}
+
+static void pci_esp_reset_dma(struct esp *esp)
+{
+       /* Nothing to do ? */
+}
+
+static void pci_esp_dma_drain(struct esp *esp)
+{
+       u8 resid;
+       int lim = 1000;
+
+
+       if ((esp->sreg & ESP_STAT_PMASK) == ESP_DOP ||
+           (esp->sreg & ESP_STAT_PMASK) == ESP_DIP)
+               /* Data-In or Data-Out, nothing to be done */
+               return;
+
+       while (--lim > 0) {
+               resid = pci_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES;
+               if (resid <= 1)
+                       break;
+               cpu_relax();
+       }
+       if (resid > 1) {
+               /* FIFO not cleared */
+               shost_printk(KERN_INFO, esp->host,
+                            "FIFO not cleared, %d bytes left\n",
+                            resid);
+       }
+
+       /*
+        * When there is a residual BCMPLT will never be set
+        * (obviously). But we still have to issue the BLAST
+        * command, otherwise the data will not being transferred.
+        * But we'll never know when the BLAST operation is
+        * finished. So check for some time and give up eventually.
+        */
+       lim = 1000;
+       pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_BLAST, ESP_DMA_CMD);
+       while (pci_esp_read8(esp, ESP_DMA_STATUS) & ESP_DMA_STAT_BCMPLT) {
+               if (--lim == 0)
+                       break;
+               cpu_relax();
+       }
+       pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+       esp_dma_log("DMA blast done (%d tries, %d bytes left)\n", lim, resid);
+       /* BLAST residual handling is currently untested */
+       if (WARN_ON_ONCE(resid == 1)) {
+               struct esp_cmd_entry *ent = esp->active_cmd;
+
+               ent->flags |= ESP_CMD_FLAG_RESIDUAL;
+       }
+}
+
+static void pci_esp_dma_invalidate(struct esp *esp)
+{
+       struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+       esp_dma_log("invalidate DMA\n");
+
+       pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+       pep->dma_status = 0;
+}
+
+static int pci_esp_dma_error(struct esp *esp)
+{
+       struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+       if (pep->dma_status & ESP_DMA_STAT_ERROR) {
+               u8 dma_cmd = pci_esp_read8(esp, ESP_DMA_CMD);
+
+               if ((dma_cmd & ESP_DMA_CMD_MASK) == ESP_DMA_CMD_START)
+                       pci_esp_write8(esp, ESP_DMA_CMD_ABORT, ESP_DMA_CMD);
+
+               return 1;
+       }
+       if (pep->dma_status & ESP_DMA_STAT_ABORT) {
+               pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+               pep->dma_status = pci_esp_read8(esp, ESP_DMA_CMD);
+               return 1;
+       }
+       return 0;
+}
+
+static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+                                u32 dma_count, int write, u8 cmd)
+{
+       struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+       u32 val = 0;
+
+       BUG_ON(!(cmd & ESP_CMD_DMA));
+
+       pep->dma_status = 0;
+
+       /* Set DMA engine to IDLE */
+       if (write)
+               /* DMA write direction logic is inverted */
+               val |= ESP_DMA_CMD_DIR;
+       pci_esp_write8(esp, ESP_DMA_CMD_IDLE | val, ESP_DMA_CMD);
+
+       pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+       pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+       if (esp->config2 & ESP_CONFIG2_FENAB)
+               pci_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+       pci_esp_write32(esp, esp_count, ESP_DMA_STC);
+       pci_esp_write32(esp, addr, ESP_DMA_SPA);
+
+       esp_dma_log("start dma addr[%x] count[%d:%d]\n",
+                   addr, esp_count, dma_count);
+
+       scsi_esp_cmd(esp, cmd);
+       /* Send DMA Start command */
+       pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
+}
+
+static u32 pci_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
+{
+       int dma_limit = 16;
+       u32 base, end;
+
+       /*
+        * If CONFIG2_FENAB is set we can
+        * handle up to 24 bit addresses
+        */
+       if (esp->config2 & ESP_CONFIG2_FENAB)
+               dma_limit = 24;
+
+       if (dma_len > (1U << dma_limit))
+               dma_len = (1U << dma_limit);
+
+       /*
+        * Prevent crossing a 24-bit address boundary.
+        */
+       base = dma_addr & ((1U << 24) - 1U);
+       end = base + dma_len;
+       if (end > (1U << 24))
+               end = (1U <<24);
+       dma_len = end - base;
+
+       return dma_len;
+}
+
+static const struct esp_driver_ops pci_esp_ops = {
+       .esp_write8     =       pci_esp_write8,
+       .esp_read8      =       pci_esp_read8,
+       .map_single     =       pci_esp_map_single,
+       .map_sg         =       pci_esp_map_sg,
+       .unmap_single   =       pci_esp_unmap_single,
+       .unmap_sg       =       pci_esp_unmap_sg,
+       .irq_pending    =       pci_esp_irq_pending,
+       .reset_dma      =       pci_esp_reset_dma,
+       .dma_drain      =       pci_esp_dma_drain,
+       .dma_invalidate =       pci_esp_dma_invalidate,
+       .send_dma_cmd   =       pci_esp_send_dma_cmd,
+       .dma_error      =       pci_esp_dma_error,
+       .dma_length_limit =     pci_esp_dma_length_limit,
+};
+
+/*
+ * Read DC-390 eeprom
+ */
+static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
+{
+       u8 carry_flag = 1, j = 0x80, bval;
+       int i;
+
+       for (i = 0; i < 9; i++) {
+               if (carry_flag) {
+                       pci_write_config_byte(pdev, 0x80, 0x40);
+                       bval = 0xc0;
+               } else
+                       bval = 0x80;
+
+               udelay(160);
+               pci_write_config_byte(pdev, 0x80, bval);
+               udelay(160);
+               pci_write_config_byte(pdev, 0x80, 0);
+               udelay(160);
+
+               carry_flag = (cmd & j) ? 1 : 0;
+               j >>= 1;
+       }
+}
+
+static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
+{
+       int i;
+       u16 wval = 0;
+       u8 bval;
+
+       for (i = 0; i < 16; i++) {
+               wval <<= 1;
+
+               pci_write_config_byte(pdev, 0x80, 0x80);
+               udelay(160);
+               pci_write_config_byte(pdev, 0x80, 0x40);
+               udelay(160);
+               pci_read_config_byte(pdev, 0x00, &bval);
+
+               if (bval == 0x22)
+                       wval |= 1;
+       }
+
+       return wval;
+}
+
+static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
+{
+       u8 cmd = DC390_EEPROM_READ, i;
+
+       for (i = 0; i < DC390_EEPROM_LEN; i++) {
+               pci_write_config_byte(pdev, 0xc0, 0);
+               udelay(160);
+
+               dc390_eeprom_prepare_read(pdev, cmd++);
+               *ptr++ = dc390_eeprom_get_data(pdev);
+
+               pci_write_config_byte(pdev, 0x80, 0);
+               pci_write_config_byte(pdev, 0x80, 0);
+               udelay(160);
+       }
+}
+
+static void dc390_check_eeprom(struct esp *esp)
+{
+       u8 EEbuf[128];
+       u16 *ptr = (u16 *)EEbuf, wval = 0;
+       int i;
+
+       dc390_read_eeprom((struct pci_dev *)esp->dev, ptr);
+
+       for (i = 0; i < DC390_EEPROM_LEN; i++, ptr++)
+               wval += *ptr;
+
+       /* no Tekram EEprom found */
+       if (wval != 0x1234) {
+               struct pci_dev *pdev = esp->dev;
+               dev_printk(KERN_INFO, &pdev->dev,
+                          "No valid Tekram EEprom found\n");
+               return;
+       }
+       esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
+       esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
+       if (EEbuf[DC390_EE_MODE2] & DC390_EE_MODE2_ACTIVE_NEGATION)
+               esp->config4 |= ESP_CONFIG4_RADE | ESP_CONFIG4_RAE;
+}
+
+static int pci_esp_probe_one(struct pci_dev *pdev,
+                             const struct pci_device_id *id)
+{
+       struct scsi_host_template *hostt = &scsi_esp_template;
+       int err = -ENODEV;
+       struct Scsi_Host *shost;
+       struct esp *esp;
+       struct pci_esp_priv *pep;
+
+       if (pci_enable_device(pdev)) {
+               dev_printk(KERN_INFO, &pdev->dev, "cannot enable device\n");
+               return -ENODEV;
+       }
+
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               dev_printk(KERN_INFO, &pdev->dev,
+                          "failed to set 32bit DMA mask\n");
+               goto fail_disable_device;
+       }
+
+       shost = scsi_host_alloc(hostt, sizeof(struct esp));
+       if (!shost) {
+               dev_printk(KERN_INFO, &pdev->dev,
+                          "failed to allocate scsi host\n");
+               err = -ENOMEM;
+               goto fail_disable_device;
+       }
+
+       pep = kzalloc(sizeof(struct pci_esp_priv), GFP_KERNEL);
+       if (!pep) {
+               dev_printk(KERN_INFO, &pdev->dev,
+                          "failed to allocate esp_priv\n");
+               err = -ENOMEM;
+               goto fail_host_alloc;
+       }
+
+       esp = shost_priv(shost);
+       esp->host = shost;
+       esp->dev = pdev;
+       esp->ops = &pci_esp_ops;
+       /*
+        * The am53c974 HBA has a design flaw of generating
+        * spurious DMA completion interrupts when using
+        * DMA for command submission.
+        */
+       esp->flags |= ESP_FLAG_USE_FIFO;
+       /*
+        * Enable CONFIG2_FENAB to allow for large DMA transfers
+        */
+       if (am53c974_fenab)
+               esp->config2 |= ESP_CONFIG2_FENAB;
+
+       pep->esp = esp;
+
+       if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "pci memory selection failed\n");
+               goto fail_priv_alloc;
+       }
+
+       esp->regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+       if (!esp->regs) {
+               dev_printk(KERN_ERR, &pdev->dev, "pci I/O map failed\n");
+               err = -EINVAL;
+               goto fail_release_regions;
+       }
+       esp->dma_regs = esp->regs;
+
+       pci_set_master(pdev);
+
+       esp->command_block = pci_alloc_consistent(pdev, 16,
+                                                 &esp->command_block_dma);
+       if (!esp->command_block) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "failed to allocate command block\n");
+               err = -ENOMEM;
+               goto fail_unmap_regs;
+       }
+
+       err = request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
+                         DRV_MODULE_NAME, esp);
+       if (err < 0) {
+               dev_printk(KERN_ERR, &pdev->dev, "failed to register IRQ\n");
+               goto fail_unmap_command_block;
+       }
+
+       esp->scsi_id = 7;
+       dc390_check_eeprom(esp);
+
+       shost->this_id = esp->scsi_id;
+       shost->max_id = 8;
+       shost->irq = pdev->irq;
+       shost->io_port = pci_resource_start(pdev, 0);
+       shost->n_io_port = pci_resource_len(pdev, 0);
+       shost->unique_id = shost->io_port;
+       esp->scsi_id_mask = (1 << esp->scsi_id);
+       /* Assume 40MHz clock */
+       esp->cfreq = 40000000;
+
+       pci_set_drvdata(pdev, pep);
+
+       err = scsi_esp_register(esp, &pdev->dev);
+       if (err)
+               goto fail_free_irq;
+
+       return 0;
+
+fail_free_irq:
+       free_irq(pdev->irq, esp);
+fail_unmap_command_block:
+       pci_free_consistent(pdev, 16, esp->command_block,
+                           esp->command_block_dma);
+fail_unmap_regs:
+       pci_iounmap(pdev, esp->regs);
+fail_release_regions:
+       pci_release_regions(pdev);
+fail_priv_alloc:
+       kfree(pep);
+fail_host_alloc:
+       scsi_host_put(shost);
+fail_disable_device:
+       pci_disable_device(pdev);
+
+       return err;
+}
+
+static void pci_esp_remove_one(struct pci_dev *pdev)
+{
+       struct pci_esp_priv *pep = pci_get_drvdata(pdev);
+       struct esp *esp = pep->esp;
+
+       scsi_esp_unregister(esp);
+       free_irq(pdev->irq, esp);
+       pci_free_consistent(pdev, 16, esp->command_block,
+                           esp->command_block_dma);
+       pci_iounmap(pdev, esp->regs);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       kfree(pep);
+
+       scsi_host_put(esp->host);
+}
+
+static struct pci_device_id am53c974_pci_tbl[] = {
+       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, am53c974_pci_tbl);
+
+static struct pci_driver am53c974_driver = {
+       .name           = DRV_MODULE_NAME,
+       .id_table       = am53c974_pci_tbl,
+       .probe          = pci_esp_probe_one,
+       .remove         = pci_esp_remove_one,
+};
+
+static int __init am53c974_module_init(void)
+{
+       return pci_register_driver(&am53c974_driver);
+}
+
+static void __exit am53c974_module_exit(void)
+{
+       pci_unregister_driver(&am53c974_driver);
+}
+
+MODULE_DESCRIPTION("AM53C974 SCSI driver");
+MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_ALIAS("tmscsim");
+
+module_param(am53c974_debug, bool, 0644);
+MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
+
+module_param(am53c974_fenab, bool, 0444);
+MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
+
+module_init(am53c974_module_init);
+module_exit(am53c974_module_exit);
index 0b44fb5ee4852044a5e7ba52724408bfdcfe7f1d..914c39f9f3882481c6f8e9df02aea3bddac24c69 100644 (file)
@@ -114,16 +114,11 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb);
 static const char *arcmsr_info(struct Scsi_Host *);
 static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
 static void arcmsr_free_irq(struct pci_dev *, struct AdapterControlBlock *);
-static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
-                                         int queue_depth, int reason)
+static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth)
 {
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
                queue_depth = ARCMSR_MAX_CMD_PERLUN;
-       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-       return queue_depth;
+       return scsi_change_queue_depth(sdev, queue_depth);
 }
 
 static struct scsi_host_template arcmsr_scsi_host_template = {
index d89b9b4deb3cdd659b615cd870541d726bb61a42..deaaf84989cd15d9ea4a306828e03623b364ccec 100644 (file)
@@ -850,13 +850,13 @@ static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp,
                        break;
 
                    default:
-                       printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=",
-                               host->host->host_no, SCpnt->result);
-                       __scsi_print_command(SCpnt->cmnd);
+                       scmd_printk(KERN_ERR, SCpnt,
+                                   "incomplete data transfer detected: "
+                                   "result=%08X", SCpnt->result);
+                       scsi_print_command(SCpnt);
                        acornscsi_dumpdma(host, "done");
-                       acornscsi_dumplog(host, SCpnt->device->id);
-                       SCpnt->result &= 0xffff;
-                       SCpnt->result |= DID_ERROR << 16;
+                       acornscsi_dumplog(host, SCpnt->device->id);
+                       set_host_byte(SCpnt, DID_ERROR);
                    }
                }
        }
index 8ef810a4476ec15f163069005ceae6b3f6b0f089..d28d6c0f18c0b76acd384f53ed6132a54f13fa57 100644 (file)
 #include <asm/ecard.h>
 #include <asm/io.h>
 
-#include "../scsi.h"
 #include <scsi/scsi_host.h>
 
 #include <scsi/scsicam.h>
 
-#define AUTOSENSE
 #define PSEUDO_DMA
 
-#define CUMANASCSI_PUBLIC_RELEASE 1
-
 #define priv(host)                     ((struct NCR5380_hostdata *)(host)->hostdata)
 #define NCR5380_local_declare()                struct Scsi_Host *_instance
 #define NCR5380_setup(instance)                _instance = instance
@@ -30,6 +26,7 @@
 #define NCR5380_write(reg, value)      cumanascsi_write(_instance, reg, value)
 #define NCR5380_intr                   cumanascsi_intr
 #define NCR5380_queue_command          cumanascsi_queue_command
+#define NCR5380_info                   cumanascsi_info
 
 #define NCR5380_implementation_fields  \
        unsigned ctrl;                  \
@@ -42,11 +39,6 @@ void cumanascsi_setup(char *str, int *ints)
 {
 }
 
-const char *cumanascsi_info(struct Scsi_Host *spnt)
-{
-       return "";
-}
-
 #define CTRL   0x16fc
 #define STAT   0x2004
 #define L(v)   (((v)<<16)|((v) & 0x0000ffff))
@@ -267,14 +259,6 @@ static int cumanascsi1_probe(struct expansion_card *ec,
                goto out_unmap;
        }
 
-       printk("scsi%d: at port 0x%08lx irq %d",
-               host->host_no, host->io_port, host->irq);
-       printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
-               host->can_queue, host->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
-       printk("\nscsi%d:", host->host_no);
-       NCR5380_print_options(host);
-       printk("\n");
-
        ret = scsi_add_host(host, &ec->dev);
        if (ret)
                goto out_free_irq;
index 71cfb1e504c4648a0a412b99cd09d51e969414a0..e64c3af7c1a0166d47ffe18dba3b5c2754385c74 100644 (file)
@@ -308,8 +308,7 @@ static void fas216_log_command(FAS216_Info *info, int level,
        fas216_do_log(info, '0' + SCpnt->device->id, fmt, args);
        va_end(args);
 
-       printk(" CDB: ");
-       __scsi_print_command(SCpnt->cmnd);
+       scsi_print_command(SCpnt);
 }
 
 static void
@@ -2079,14 +2078,12 @@ fas216_std_done(FAS216_Info *info, struct scsi_cmnd *SCpnt, unsigned int result)
                        break;
 
                default:
-                       printk(KERN_ERR "scsi%d.%c: incomplete data transfer "
-                               "detected: res=%08X ptr=%p len=%X CDB: ",
-                               info->host->host_no, '0' + SCpnt->device->id,
-                               SCpnt->result, info->scsi.SCp.ptr,
-                               info->scsi.SCp.this_residual);
-                       __scsi_print_command(SCpnt->cmnd);
-                       SCpnt->result &= ~(255 << 16);
-                       SCpnt->result |= DID_BAD_TARGET << 16;
+                       scmd_printk(KERN_ERR, SCpnt,
+                                   "incomplete data transfer detected: res=%08X ptr=%p len=%X\n",
+                                   SCpnt->result, info->scsi.SCp.ptr,
+                                   info->scsi.SCp.this_residual);
+                       scsi_print_command(SCpnt);
+                       set_host_byte(SCpnt, DID_ERROR);
                        goto request_sense;
                }
        }
@@ -2158,12 +2155,11 @@ static void fas216_done(FAS216_Info *info, unsigned int result)
         * to transfer, we should not have a valid pointer.
         */
        if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) {
-               printk("scsi%d.%c: zero bytes left to transfer, but "
-                      "buffer pointer still valid: ptr=%p len=%08x CDB: ",
-                      info->host->host_no, '0' + SCpnt->device->id,
-                      info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
+               scmd_printk(KERN_INFO, SCpnt,
+                           "zero bytes left to transfer, but buffer pointer still valid: ptr=%p len=%08x\n",
+                           info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
                info->scsi.SCp.ptr = NULL;
-               __scsi_print_command(SCpnt->cmnd);
+               scsi_print_command(SCpnt);
        }
 
        /*
@@ -2427,14 +2423,11 @@ int fas216_eh_abort(struct scsi_cmnd *SCpnt)
 
        info->stats.aborts += 1;
 
-       printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no);
-       __scsi_print_command(SCpnt->cmnd);
+       scmd_printk(KERN_WARNING, SCpnt, "abort command\n");
 
        print_debug_list();
        fas216_dumpstate(info);
 
-       printk(KERN_WARNING "scsi%d: abort %p ", info->host->host_no, SCpnt);
-
        switch (fas216_find_command(info, SCpnt)) {
        /*
         * We found the command, and cleared it out.  Either
@@ -2442,7 +2435,7 @@ int fas216_eh_abort(struct scsi_cmnd *SCpnt)
         * target, or the busylun bit is not set.
         */
        case res_success:
-               printk("success\n");
+               scmd_printk(KERN_WARNING, SCpnt, "abort %p success\n", SCpnt);
                result = SUCCESS;
                break;
 
@@ -2452,14 +2445,13 @@ int fas216_eh_abort(struct scsi_cmnd *SCpnt)
         * if the bus is free.
         */
        case res_hw_abort:
-               
 
        /*
         * We are unable to abort the command for some reason.
         */
        default:
        case res_failed:
-               printk("failed\n");
+               scmd_printk(KERN_WARNING, SCpnt, "abort %p failed\n", SCpnt);
                break;
        }
 
@@ -2664,8 +2656,7 @@ int fas216_eh_host_reset(struct scsi_cmnd *SCpnt)
 
        fas216_checkmagic(info);
 
-       printk("scsi%d.%c: %s: resetting host\n",
-               info->host->host_no, '0' + SCpnt->device->id, __func__);
+       fas216_log(info, LOG_ERROR, "resetting host");
 
        /*
         * Reset the SCSI chip.
index 188e734c7ff006bb9b7e891ddca23ae00c884b3d..7c6fa1479c9c1f4c92cd98c891e800d8b7a12ecb 100644 (file)
 #include <asm/ecard.h>
 #include <asm/io.h>
 
-#include "../scsi.h"
 #include <scsi/scsi_host.h>
 
-#define AUTOSENSE
 /*#define PSEUDO_DMA*/
-
-#define OAKSCSI_PUBLIC_RELEASE 1
 #define DONT_USE_INTR
 
 #define priv(host)                     ((struct NCR5380_hostdata *)(host)->hostdata)
 
 #define NCR5380_read(reg)              readb(_base + ((reg) << 2))
 #define NCR5380_write(reg, value)      writeb(value, _base + ((reg) << 2))
-#define NCR5380_intr                   oakscsi_intr
 #define NCR5380_queue_command          oakscsi_queue_command
+#define NCR5380_info                   oakscsi_info
 #define NCR5380_show_info              oakscsi_show_info
-#define NCR5380_write_info             oakscsi_write_info
 
 #define NCR5380_implementation_fields  \
        void __iomem *base
 #undef START_DMA_INITIATOR_RECEIVE_REG
 #define START_DMA_INITIATOR_RECEIVE_REG        (128 + 7)
 
-const char * oakscsi_info (struct Scsi_Host *spnt)
-{
-       return "";
-}
-
 #define STAT   ((128 + 16) << 2)
 #define DATA   ((128 + 8) << 2)
 
@@ -114,7 +104,6 @@ printk("reading %p len %d\n", addr, len);
 static struct scsi_host_template oakscsi_template = {
        .module                 = THIS_MODULE,
        .show_info              = oakscsi_show_info,
-       .write_info             = oakscsi_write_info,
        .name                   = "Oak 16-bit SCSI",
        .info                   = oakscsi_info,
        .queuecommand           = oakscsi_queue_command,
@@ -150,19 +139,11 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
                goto unreg;
        }
 
-       host->irq = IRQ_NONE;
+       host->irq = NO_IRQ;
        host->n_io_port = 255;
 
        NCR5380_init(host, 0);
 
-       printk("scsi%d: at port 0x%08lx irqs disabled",
-               host->host_no, host->io_port);
-       printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
-               host->can_queue, host->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
-       printk("\nscsi%d:", host->host_no);
-       NCR5380_print_options(host);
-       printk("\n");
-
        ret = scsi_add_host(host, &ec->dev);
        if (ret)
                goto out_unmap;
index 79e6f045c2a911348a99dfd02a87ab2603b7168c..6daed6b386d4c8b47cb3094754d59b162039802c 100644 (file)
@@ -11,8 +11,6 @@
  *     drew@colorado.edu
  *     +1 (303) 666-5836
  *
- * DISTRIBUTION RELEASE 6.
- *
  * For more information, please consult
  *
  * NCR 5380 Family
@@ -73,6 +71,9 @@
  * 1.  Test linked command handling code after Eric is ready with
  *     the high level code.
  */
+
+/* Adapted for the sun3 by Sam Creasey. */
+
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_transport_spi.h>
 
 
 /*
  * Design
- * Issues :
- *
- * The other Linux SCSI drivers were written when Linux was Intel PC-only,
- * and specifically for each board rather than each chip.  This makes their
- * adaptation to platforms like the Mac (Some of which use NCR5380's)
- * more difficult than it has to be.
  *
- * Also, many of the SCSI drivers were written before the command queuing
- * routines were implemented, meaning their implementations of queued
- * commands were hacked on rather than designed in from the start.
- *
- * When I designed the Linux SCSI drivers I figured that
- * while having two different SCSI boards in a system might be useful
- * for debugging things, two of the same type wouldn't be used.
- * Well, I was wrong and a number of users have mailed me about running
- * multiple high-performance SCSI boards in a server.
- *
- * Finally, when I get questions from users, I have no idea what
- * revision of my driver they are running.
- *
- * This driver attempts to address these problems :
  * This is a generic 5380 driver.  To use it on a different platform,
  * one simply writes appropriate system specific macros (ie, data
  * transfer - some PC's will use the I/O bus, 68K's must use
  * allowing multiple commands to propagate all the way to a SCSI-II device
  * while a command is already executing.
  *
- * To solve the multiple-boards-in-the-same-system problem,
- * there is a separate instance structure for each instance
- * of a 5380 in the system.  So, multiple NCR5380 drivers will
- * be able to coexist with appropriate changes to the high level
- * SCSI code.
- *
- * A NCR5380_PUBLIC_REVISION macro is provided, with the release
- * number (updated for each public release) printed by the
- * NCR5380_print_options command, which should be called from the
- * wrapper detect function, so that I know what release of the driver
- * users are using.
  *
  * Issues specific to the NCR5380 :
  *
  * Architecture :
  *
  * At the heart of the design is a coroutine, NCR5380_main,
- * which is started when not running by the interrupt handler,
- * timer, and queue command function.  It attempts to establish
- * I_T_L or I_T_L_Q nexuses by removing the commands from the
- * issue queue and calling NCR5380_select() if a nexus
- * is not established.
+ * which is started from a workqueue for each NCR5380 host in the
+ * system.  It attempts to establish I_T_L or I_T_L_Q nexuses by
+ * removing the commands from the issue queue and calling
+ * NCR5380_select() if a nexus is not established.
  *
  * Once a nexus is established, the NCR5380_information_transfer()
  * phase goes through the various phases as instructed by the target.
  * if the target goes into MSG IN and sends a DISCONNECT message,
  * the command structure is placed into the per instance disconnected
- * queue, and NCR5380_main tries to find more work.  If USLEEP
- * was defined, and the target is idle for too long, the system
- * will try to sleep.
+ * queue, and NCR5380_main tries to find more work.  If the target is
+ * idle for too long, the system will try to sleep.
  *
  * If a command has disconnected, eventually an interrupt will trigger,
  * calling NCR5380_intr()  which will in turn call NCR5380_reselect
  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
  *     for commands that return with a CHECK CONDITION status.
  *
+ * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
+ *     transceivers.
+ *
  * LINKED - if defined, linked commands are supported.
  *
  * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
  *
  * NCR5380_write(register, value) - write to the specific register
  *
+ * NCR5380_implementation_fields  - additional fields needed for this
+ *      specific implementation of the NCR5380
+ *
  * Either real DMA *or* pseudo DMA may be implemented
  * REAL functions :
  * NCR5380_REAL_DMA should be defined if real DMA is to be used.
  * NCR5380_pwrite(instance, src, count)
  * NCR5380_pread(instance, dst, count);
  *
- * If nothing specific to this implementation needs doing (ie, with external
- * hardware), you must also define
- *
- * NCR5380_queue_command
- * NCR5380_reset
- * NCR5380_abort
- * NCR5380_proc_info
- *
- * to be the global entry points into the specific driver, ie
- * #define NCR5380_queue_command t128_queue_command.
- *
- * If this is not done, the routines will be defined as static functions
- * with the NCR5380* names and the user must provide a globally
- * accessible wrapper function.
- *
  * The generic driver is initialized by calling NCR5380_init(instance),
  * after setting the appropriate host specific fields and ID.  If the
  * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
- * possible) function may be used.  Before the specific driver initialization
- * code finishes, NCR5380_print_options should be called.
+ * possible) function may be used.
  */
 
-static struct Scsi_Host *first_instance = NULL;
-static struct scsi_host_template *the_template = NULL;
-
 /* Macros ease life... :-) */
 #define        SETUP_HOSTDATA(in)                              \
     struct NCR5380_hostdata *hostdata =                        \
        (struct NCR5380_hostdata *)(in)->hostdata
 #define        HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
 
-#define        NEXT(cmd)               ((Scsi_Cmnd *)(cmd)->host_scribble)
+#define        NEXT(cmd)               ((struct scsi_cmnd *)(cmd)->host_scribble)
 #define        SET_NEXT(cmd,next)      ((cmd)->host_scribble = (void *)(next))
-#define        NEXTADDR(cmd)           ((Scsi_Cmnd **)&(cmd)->host_scribble)
+#define        NEXTADDR(cmd)           ((struct scsi_cmnd **)&(cmd)->host_scribble)
 
 #define        HOSTNO          instance->host_no
 #define        H_NO(cmd)       (cmd)->device->host->host_no
@@ -316,30 +271,17 @@ static struct scsi_host_template *the_template = NULL;
  * important: the tag bit must be cleared before 'nr_allocated' is decreased.
  */
 
-/* -1 for TAG_NONE is not possible with unsigned char cmd->tag */
-#undef TAG_NONE
-#define TAG_NONE 0xff
-
-typedef struct {
-       DECLARE_BITMAP(allocated, MAX_TAGS);
-       int nr_allocated;
-       int queue_size;
-} TAG_ALLOC;
-
-static TAG_ALLOC TagAlloc[8][8];       /* 8 targets and 8 LUNs */
-
-
-static void __init init_tags(void)
+static void __init init_tags(struct NCR5380_hostdata *hostdata)
 {
        int target, lun;
-       TAG_ALLOC *ta;
+       struct tag_alloc *ta;
 
-       if (!setup_use_tagged_queuing)
+       if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
                return;
 
        for (target = 0; target < 8; ++target) {
                for (lun = 0; lun < 8; ++lun) {
-                       ta = &TagAlloc[target][lun];
+                       ta = &hostdata->TagAlloc[target][lun];
                        bitmap_zero(ta->allocated, MAX_TAGS);
                        ta->nr_allocated = 0;
                        /* At the beginning, assume the maximum queue size we could
@@ -359,7 +301,7 @@ static void __init init_tags(void)
  * conditions.
  */
 
-static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
+static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged)
 {
        u8 lun = cmd->device->lun;
        SETUP_HOSTDATA(cmd->device->host);
@@ -367,10 +309,11 @@ static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
        if (hostdata->busy[cmd->device->id] & (1 << lun))
                return 1;
        if (!should_be_tagged ||
-           !setup_use_tagged_queuing || !cmd->device->tagged_supported)
+           !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
+           !cmd->device->tagged_supported)
                return 0;
-       if (TagAlloc[cmd->device->id][lun].nr_allocated >=
-           TagAlloc[cmd->device->id][lun].queue_size) {
+       if (hostdata->TagAlloc[scmd_id(cmd)][lun].nr_allocated >=
+           hostdata->TagAlloc[scmd_id(cmd)][lun].queue_size) {
                dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n",
                           H_NO(cmd), cmd->device->id, lun);
                return 1;
@@ -384,7 +327,7 @@ static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged)
  * untagged.
  */
 
-static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
+static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged)
 {
        u8 lun = cmd->device->lun;
        SETUP_HOSTDATA(cmd->device->host);
@@ -393,13 +336,14 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
         * an untagged command.
         */
        if (!should_be_tagged ||
-           !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
+           !(hostdata->flags & FLAG_TAGGED_QUEUING) ||
+           !cmd->device->tagged_supported) {
                cmd->tag = TAG_NONE;
                hostdata->busy[cmd->device->id] |= (1 << lun);
                dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged "
                           "command\n", H_NO(cmd), cmd->device->id, lun);
        } else {
-               TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
+               struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun];
 
                cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS);
                set_bit(cmd->tag, ta->allocated);
@@ -416,7 +360,7 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged)
  * unlock the LUN.
  */
 
-static void cmd_free_tag(Scsi_Cmnd *cmd)
+static void cmd_free_tag(struct scsi_cmnd *cmd)
 {
        u8 lun = cmd->device->lun;
        SETUP_HOSTDATA(cmd->device->host);
@@ -429,7 +373,7 @@ static void cmd_free_tag(Scsi_Cmnd *cmd)
                printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
                       H_NO(cmd), cmd->tag);
        } else {
-               TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
+               struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun];
                clear_bit(cmd->tag, ta->allocated);
                ta->nr_allocated--;
                dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n",
@@ -438,17 +382,17 @@ static void cmd_free_tag(Scsi_Cmnd *cmd)
 }
 
 
-static void free_all_tags(void)
+static void free_all_tags(struct NCR5380_hostdata *hostdata)
 {
        int target, lun;
-       TAG_ALLOC *ta;
+       struct tag_alloc *ta;
 
-       if (!setup_use_tagged_queuing)
+       if (!(hostdata->flags & FLAG_TAGGED_QUEUING))
                return;
 
        for (target = 0; target < 8; ++target) {
                for (lun = 0; lun < 8; ++lun) {
-                       ta = &TagAlloc[target][lun];
+                       ta = &hostdata->TagAlloc[target][lun];
                        bitmap_zero(ta->allocated, MAX_TAGS);
                        ta->nr_allocated = 0;
                }
@@ -459,19 +403,20 @@ static void free_all_tags(void)
 
 
 /*
- * Function: void merge_contiguous_buffers( Scsi_Cmnd *cmd )
+ * Function: void merge_contiguous_buffers( struct scsi_cmnd *cmd )
  *
  * Purpose: Try to merge several scatter-gather requests into one DMA
  *    transfer. This is possible if the scatter buffers lie on
  *    physical contiguous addresses.
  *
- * Parameters: Scsi_Cmnd *cmd
+ * Parameters: struct scsi_cmnd *cmd
  *    The command to work on. The first scatter buffer's data are
  *    assumed to be already transferred into ptr/this_residual.
  */
 
-static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
+static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
 {
+#if !defined(CONFIG_SUN3)
        unsigned long endaddr;
 #if (NDEBUG & NDEBUG_MERGING)
        unsigned long oldlen = cmd->SCp.this_residual;
@@ -496,18 +441,17 @@ static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
                dprintk(NDEBUG_MERGING, "merged %d buffers from %p, new length %08x\n",
                           cnt, cmd->SCp.ptr, cmd->SCp.this_residual);
 #endif
+#endif /* !defined(CONFIG_SUN3) */
 }
 
-/*
- * Function : void initialize_SCp(Scsi_Cmnd *cmd)
+/**
+ * initialize_SCp - init the scsi pointer field
+ * @cmd: command block to set up
  *
- * Purpose : initialize the saved data pointers for cmd to point to the
- *     start of the buffer.
- *
- * Inputs : cmd - Scsi_Cmnd structure to have pointers reset.
+ * Set up the internal fields in the SCSI command.
  */
 
-static inline void initialize_SCp(Scsi_Cmnd *cmd)
+static inline void initialize_SCp(struct scsi_cmnd *cmd)
 {
        /*
         * Initialize the Scsi Pointer field so that all of the commands in the
@@ -557,12 +501,11 @@ static struct {
        {0, NULL}
 };
 
-/*
- * Function : void NCR5380_print(struct Scsi_Host *instance)
+/**
+ * NCR5380_print - print scsi bus signals
+ * @instance: adapter state to dump
  *
- * Purpose : print the SCSI bus signals for debugging purposes
- *
- * Input : instance - which NCR5380
+ * Print the SCSI bus signals for debugging purposes
  */
 
 static void NCR5380_print(struct Scsi_Host *instance)
@@ -605,12 +548,13 @@ static struct {
        {PHASE_UNKNOWN, "UNKNOWN"}
 };
 
-/*
- * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
+/**
+ * NCR5380_print_phase - show SCSI phase
+ * @instance: adapter to dump
  *
- * Purpose : print the current SCSI phase for debugging purposes
+ * Print the current SCSI phase for debugging purposes
  *
- * Input : instance - which NCR5380
+ * Locks: none
  */
 
 static void NCR5380_print_phase(struct Scsi_Host *instance)
@@ -648,71 +592,75 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 
-static volatile int main_running;
-static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
-
-static inline void queue_main(void)
+static inline void queue_main(struct NCR5380_hostdata *hostdata)
 {
-       if (!main_running) {
+       if (!hostdata->main_running) {
                /* If in interrupt and NCR5380_main() not already running,
                   queue it on the 'immediate' task queue, to be processed
                   immediately after the current interrupt processing has
                   finished. */
-               schedule_work(&NCR5380_tqueue);
+               schedule_work(&hostdata->main_task);
        }
        /* else: nothing to do: the running NCR5380_main() will pick up
           any newly queued command. */
 }
 
-
-static inline void NCR5380_all_init(void)
-{
-       static int done = 0;
-       if (!done) {
-               dprintk(NDEBUG_INIT, "scsi : NCR5380_all_init()\n");
-               done = 1;
-       }
-}
-
-
-/*
- * Function : void NCR58380_print_options (struct Scsi_Host *instance)
+/**
+ * NCR58380_info - report driver and host information
+ * @instance: relevant scsi host instance
  *
- * Purpose : called by probe code indicating the NCR5380 driver
- *          options that were selected.
+ * For use as the host template info() handler.
  *
- * Inputs : instance, pointer to this instance.  Unused.
+ * Locks: none
  */
 
-static void __init NCR5380_print_options(struct Scsi_Host *instance)
+static const char *NCR5380_info(struct Scsi_Host *instance)
+{
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       return hostdata->info;
+}
+
+static void prepare_info(struct Scsi_Host *instance)
 {
-       printk(" generic options"
-#ifdef AUTOSENSE
-              " AUTOSENSE"
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       snprintf(hostdata->info, sizeof(hostdata->info),
+                "%s, io_port 0x%lx, n_io_port %d, "
+                "base 0x%lx, irq %d, "
+                "can_queue %d, cmd_per_lun %d, "
+                "sg_tablesize %d, this_id %d, "
+                "flags { %s}, "
+                "options { %s} ",
+                instance->hostt->name, instance->io_port, instance->n_io_port,
+                instance->base, instance->irq,
+                instance->can_queue, instance->cmd_per_lun,
+                instance->sg_tablesize, instance->this_id,
+                hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "",
+#ifdef DIFFERENTIAL
+                "DIFFERENTIAL "
 #endif
 #ifdef REAL_DMA
-              " REAL DMA"
+                "REAL_DMA "
 #endif
 #ifdef PARITY
-              " PARITY"
+                "PARITY "
 #endif
 #ifdef SUPPORT_TAGS
-              " SCSI-2 TAGGED QUEUING"
+                "SUPPORT_TAGS "
 #endif
-              );
-       printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
+                "");
 }
 
-/*
- * Function : void NCR5380_print_status (struct Scsi_Host *instance)
+/**
+ * NCR5380_print_status - dump controller info
+ * @instance: controller to dump
  *
- * Purpose : print commands in the various queues, called from
- *     NCR5380_abort and NCR5380_debug to aid debugging.
- *
- * Inputs : instance, pointer to this instance.
+ * Print commands in the various queues, called from NCR5380_abort
+ * to aid debugging.
  */
 
-static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
+static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd)
 {
        int i, s;
        unsigned char *command;
@@ -729,7 +677,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
 static void NCR5380_print_status(struct Scsi_Host *instance)
 {
        struct NCR5380_hostdata *hostdata;
-       Scsi_Cmnd *ptr;
+       struct scsi_cmnd *ptr;
        unsigned long flags;
 
        NCR5380_dprint(NDEBUG_ANY, instance);
@@ -737,20 +685,19 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
 
        hostdata = (struct NCR5380_hostdata *)instance->hostdata;
 
-       printk("\nNCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
        local_irq_save(flags);
        printk("NCR5380: coroutine is%s running.\n",
-               main_running ? "" : "n't");
+               hostdata->main_running ? "" : "n't");
        if (!hostdata->connected)
                printk("scsi%d: no currently connected command\n", HOSTNO);
        else
-               lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected);
+               lprint_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected);
        printk("scsi%d: issue_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+       for (ptr = (struct scsi_cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
                lprint_Scsi_Cmnd(ptr);
 
        printk("scsi%d: disconnected_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+       for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr;
             ptr = NEXT(ptr))
                lprint_Scsi_Cmnd(ptr);
 
@@ -758,7 +705,7 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
        printk("\n");
 }
 
-static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
+static void show_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m)
 {
        int i, s;
        unsigned char *command;
@@ -772,28 +719,28 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
        seq_printf(m, "\n");
 }
 
-static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
+static int __maybe_unused NCR5380_show_info(struct seq_file *m,
+                                            struct Scsi_Host *instance)
 {
        struct NCR5380_hostdata *hostdata;
-       Scsi_Cmnd *ptr;
+       struct scsi_cmnd *ptr;
        unsigned long flags;
 
        hostdata = (struct NCR5380_hostdata *)instance->hostdata;
 
-       seq_printf(m, "NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
        local_irq_save(flags);
        seq_printf(m, "NCR5380: coroutine is%s running.\n",
-               main_running ? "" : "n't");
+               hostdata->main_running ? "" : "n't");
        if (!hostdata->connected)
                seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
        else
-               show_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
+               show_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected, m);
        seq_printf(m, "scsi%d: issue_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+       for (ptr = (struct scsi_cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
                show_Scsi_Cmnd(ptr, m);
 
        seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
+       for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr;
             ptr = NEXT(ptr))
                show_Scsi_Cmnd(ptr, m);
 
@@ -801,16 +748,18 @@ static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
        return 0;
 }
 
-/*
- * Function : void NCR5380_init (struct Scsi_Host *instance)
+/**
+ * NCR5380_init - initialise an NCR5380
+ * @instance: adapter to configure
+ * @flags: control flags
  *
- * Purpose : initializes *instance and corresponding 5380 chip.
- *
- * Inputs : instance - instantiation of the 5380 driver.
+ * Initializes *instance and corresponding 5380 chip,
+ * with flags OR'd into the initial flags value.
  *
  * Notes : I assume that the host, hostno, and id bits have been
- *     set correctly.  I don't care about the irq and other fields.
+ * set correctly. I don't care about the irq and other fields.
  *
+ * Returns 0 for success
  */
 
 static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
@@ -818,8 +767,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        int i;
        SETUP_HOSTDATA(instance);
 
-       NCR5380_all_init();
-
+       hostdata->host = instance;
        hostdata->aborted = 0;
        hostdata->id_mask = 1 << instance->this_id;
        hostdata->id_higher_mask = 0;
@@ -829,7 +777,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        for (i = 0; i < 8; ++i)
                hostdata->busy[i] = 0;
 #ifdef SUPPORT_TAGS
-       init_tags();
+       init_tags(hostdata);
 #endif
 #if defined (REAL_DMA)
        hostdata->dma_len = 0;
@@ -838,19 +786,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        hostdata->connected = NULL;
        hostdata->issue_queue = NULL;
        hostdata->disconnected_queue = NULL;
-       hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
+       hostdata->flags = flags;
 
-       if (!the_template) {
-               the_template = instance->hostt;
-               first_instance = instance;
-       }
+       INIT_WORK(&hostdata->main_task, NCR5380_main);
 
-#ifndef AUTOSENSE
-       if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
-               printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
-                      "        without AUTOSENSE option, contingent allegiance conditions may\n"
-                      "        be incorrectly cleared.\n", HOSTNO);
-#endif /* def AUTOSENSE */
+       prepare_info(instance);
 
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
        NCR5380_write(MODE_REG, MR_BASE);
@@ -860,33 +800,35 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
        return 0;
 }
 
+/**
+ * NCR5380_exit - remove an NCR5380
+ * @instance: adapter to remove
+ *
+ * Assumes that no more work can be queued (e.g. by NCR5380_intr).
+ */
+
 static void NCR5380_exit(struct Scsi_Host *instance)
 {
-       /* Empty, as we didn't schedule any delayed work */
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       cancel_work_sync(&hostdata->main_task);
 }
 
-/*
- * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
- *     void (*done)(Scsi_Cmnd *))
- *
- * Purpose :  enqueues a SCSI command
- *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- *     a pointer to the command descriptor.
- *
- * Returns : 0
- *
- * Side effects :
- *      cmd is added to the per instance issue_queue, with minor
- *     twiddling done to the host specific fields of cmd.  If the
- *     main coroutine is not running, it is restarted.
+/**
+ * NCR5380_queue_command - queue a command
+ * @instance: the relevant SCSI adapter
+ * @cmd: SCSI command
  *
+ * cmd is added to the per instance issue_queue, with minor
+ * twiddling done to the host specific fields of cmd.  If the
+ * main coroutine is not running, it is restarted.
  */
 
-static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static int NCR5380_queue_command(struct Scsi_Host *instance,
+                                 struct scsi_cmnd *cmd)
 {
-       SETUP_HOSTDATA(cmd->device->host);
-       Scsi_Cmnd *tmp;
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+       struct scsi_cmnd *tmp;
        unsigned long flags;
 
 #if (NDEBUG & NDEBUG_NO_WRITE)
@@ -896,47 +838,17 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
                printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
                       H_NO(cmd));
                cmd->result = (DID_ERROR << 16);
-               done(cmd);
+               cmd->scsi_done(cmd);
                return 0;
        }
 #endif /* (NDEBUG & NDEBUG_NO_WRITE) */
 
-#ifdef NCR5380_STATS
-# if 0
-       if (!hostdata->connected && !hostdata->issue_queue &&
-           !hostdata->disconnected_queue) {
-               hostdata->timebase = jiffies;
-       }
-# endif
-# ifdef NCR5380_STAT_LIMIT
-       if (scsi_bufflen(cmd) > NCR5380_STAT_LIMIT)
-# endif
-               switch (cmd->cmnd[0]) {
-               case WRITE:
-               case WRITE_6:
-               case WRITE_10:
-                       hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
-                       hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);
-                       hostdata->pendingw++;
-                       break;
-               case READ:
-               case READ_6:
-               case READ_10:
-                       hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
-                       hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);
-                       hostdata->pendingr++;
-                       break;
-               }
-#endif
-
        /*
         * We use the host_scribble field as a pointer to the next command
         * in a queue
         */
 
        SET_NEXT(cmd, NULL);
-       cmd->scsi_done = done;
-
        cmd->result = 0;
 
        /*
@@ -946,7 +858,6 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
         * sense data is only guaranteed to be valid while the condition exists.
         */
 
-       local_irq_save(flags);
        /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
         * Otherwise a running NCR5380_main may steal the lock.
         * Lock before actually inserting due to fairness reasons explained in
@@ -959,17 +870,24 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
         * because also a timer int can trigger an abort or reset, which would
         * alter queues and touch the lock.
         */
-       if (!IS_A_TT()) {
-               /* perhaps stop command timer here */
-               falcon_get_lock();
-               /* perhaps restart command timer here */
-       }
+       if (!NCR5380_acquire_dma_irq(instance))
+               return SCSI_MLQUEUE_HOST_BUSY;
+
+       local_irq_save(flags);
+
+       /*
+        * Insert the cmd into the issue queue. Note that REQUEST SENSE
+        * commands are added to the head of the queue since any command will
+        * clear the contingent allegiance condition that exists and the
+        * sense data is only guaranteed to be valid while the condition exists.
+        */
+
        if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
                LIST(cmd, hostdata->issue_queue);
                SET_NEXT(cmd, hostdata->issue_queue);
                hostdata->issue_queue = cmd;
        } else {
-               for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+               for (tmp = (struct scsi_cmnd *)hostdata->issue_queue;
                     NEXT(tmp); tmp = NEXT(tmp))
                        ;
                LIST(cmd, tmp);
@@ -987,32 +905,42 @@ static int NCR5380_queue_command_lck(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
         * If we're not in an interrupt, we can call NCR5380_main()
         * unconditionally, because it cannot be already running.
         */
-       if (in_interrupt() || ((flags >> 8) & 7) >= 6)
-               queue_main();
+       if (in_interrupt() || irqs_disabled())
+               queue_main(hostdata);
        else
-               NCR5380_main(NULL);
+               NCR5380_main(&hostdata->main_task);
        return 0;
 }
 
-static DEF_SCSI_QCMD(NCR5380_queue_command)
+static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
+{
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+       /* Caller does the locking needed to set & test these data atomically */
+       if (!hostdata->disconnected_queue &&
+           !hostdata->issue_queue &&
+           !hostdata->connected &&
+           !hostdata->retain_dma_intr)
+               NCR5380_release_dma_irq(instance);
+}
 
-/*
- * Function : NCR5380_main (void)
+/**
+ * NCR5380_main - NCR state machines
  *
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can
- *     be done on the NCR5380 host adapters in a system.  Both
- *     NCR5380_queue_command() and NCR5380_intr() will try to start it
- *     in case it is not running.
+ * NCR5380_main is a coroutine that runs as long as more work can
+ * be done on the NCR5380 host adapters in a system.  Both
+ * NCR5380_queue_command() and NCR5380_intr() will try to start it
+ * in case it is not running.
  *
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
- *  reenable them.  This prevents reentrancy and kernel stack overflow.
+ * Locks: called as its own thread with no locks held.
  */
 
 static void NCR5380_main(struct work_struct *work)
 {
-       Scsi_Cmnd *tmp, *prev;
-       struct Scsi_Host *instance = first_instance;
-       struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
+       struct NCR5380_hostdata *hostdata =
+               container_of(work, struct NCR5380_hostdata, main_task);
+       struct Scsi_Host *instance = hostdata->host;
+       struct scsi_cmnd *tmp, *prev;
        int done;
        unsigned long flags;
 
@@ -1037,9 +965,9 @@ static void NCR5380_main(struct work_struct *work)
           'main_running' is set here, and queues/executes main via the
           task queue, it doesn't do any harm, just this instance of main
           won't find any work left to do. */
-       if (main_running)
+       if (hostdata->main_running)
                return;
-       main_running = 1;
+       hostdata->main_running = 1;
 
        local_save_flags(flags);
        do {
@@ -1053,7 +981,7 @@ static void NCR5380_main(struct work_struct *work)
                         * for a target that's not busy.
                         */
 #if (NDEBUG & NDEBUG_LISTS)
-                       for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;
+                       for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL;
                             tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
                                ;
                        /*printk("%p  ", tmp);*/
@@ -1061,16 +989,14 @@ static void NCR5380_main(struct work_struct *work)
                                printk(" LOOP\n");
                        /* else printk("\n"); */
 #endif
-                       for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,
+                       for (tmp = (struct scsi_cmnd *) hostdata->issue_queue,
                             prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) {
                                u8 lun = tmp->device->lun;
 
-#if (NDEBUG & NDEBUG_LISTS)
-                               if (prev != tmp)
-                                       printk("MAIN tmp=%p   target=%d   busy=%d lun=%llu\n",
-                                              tmp, tmp->device->id, hostdata->busy[tmp->device->id],
-                                              lun);
-#endif
+                               dprintk(NDEBUG_LISTS,
+                                       "MAIN tmp=%p target=%d busy=%d lun=%d\n",
+                                       tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)],
+                                       lun);
                                /*  When we find one, remove it from the issue queue. */
                                /* ++guenther: possible race with Falcon locking */
                                if (
@@ -1090,7 +1016,7 @@ static void NCR5380_main(struct work_struct *work)
                                                hostdata->issue_queue = NEXT(tmp);
                                        }
                                        SET_NEXT(tmp, NULL);
-                                       falcon_dont_release++;
+                                       hostdata->retain_dma_intr++;
 
                                        /* reenable interrupts after finding one */
                                        local_irq_restore(flags);
@@ -1117,12 +1043,12 @@ static void NCR5380_main(struct work_struct *work)
 #ifdef SUPPORT_TAGS
                                        cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE);
 #endif
-                                       if (!NCR5380_select(instance, tmp,
-                                           (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE :
-                                           TAG_NEXT)) {
-                                               falcon_dont_release--;
+                                       if (!NCR5380_select(instance, tmp)) {
+                                               local_irq_disable();
+                                               hostdata->retain_dma_intr--;
                                                /* release if target did not response! */
-                                               falcon_release_lock_if_possible(hostdata);
+                                               maybe_release_dma_irq(instance);
+                                               local_irq_restore(flags);
                                                break;
                                        } else {
                                                local_irq_disable();
@@ -1132,7 +1058,7 @@ static void NCR5380_main(struct work_struct *work)
 #ifdef SUPPORT_TAGS
                                                cmd_free_tag(tmp);
 #endif
-                                               falcon_dont_release--;
+                                               hostdata->retain_dma_intr--;
                                                local_irq_restore(flags);
                                                dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, "
                                                            "returned to issue_queue\n", HOSTNO);
@@ -1160,7 +1086,7 @@ static void NCR5380_main(struct work_struct *work)
        /* Better allow ints _after_ 'main_running' has been cleared, else
           an interrupt could believe we'll pick up the work it left for
           us, but we won't see it anymore here... */
-       main_running = 0;
+       hostdata->main_running = 0;
        local_irq_restore(flags);
 }
 
@@ -1179,9 +1105,11 @@ static void NCR5380_main(struct work_struct *work)
 static void NCR5380_dma_complete(struct Scsi_Host *instance)
 {
        SETUP_HOSTDATA(instance);
-       int transfered, saved_data = 0, overrun = 0, cnt, toPIO;
-       unsigned char **data, p;
+       int transferred;
+       unsigned char **data;
        volatile int *count;
+       int saved_data = 0, overrun = 0;
+       unsigned char p;
 
        if (!hostdata->connected) {
                printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
@@ -1189,7 +1117,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
                return;
        }
 
-       if (atari_read_overruns) {
+       if (hostdata->read_overruns) {
                p = hostdata->connected->SCp.phase;
                if (p & SR_IO) {
                        udelay(10);
@@ -1207,21 +1135,41 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
                   HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
                   NCR5380_read(STATUS_REG));
 
+#if defined(CONFIG_SUN3)
+       if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) {
+               pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n",
+                      instance->host_no);
+               BUG();
+       }
+
+       /* make sure we're not stuck in a data phase */
+       if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) ==
+           (BASR_PHASE_MATCH | BASR_ACK)) {
+               pr_err("scsi%d: BASR %02x\n", instance->host_no,
+                      NCR5380_read(BUS_AND_STATUS_REG));
+               pr_err("scsi%d: bus stuck in data phase -- probably a single byte overrun!\n",
+                      instance->host_no);
+               BUG();
+       }
+#endif
+
        (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
        NCR5380_write(MODE_REG, MR_BASE);
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
-       transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
+       transferred = hostdata->dma_len - NCR5380_dma_residual(instance);
        hostdata->dma_len = 0;
 
        data = (unsigned char **)&hostdata->connected->SCp.ptr;
        count = &hostdata->connected->SCp.this_residual;
-       *data += transfered;
-       *count -= transfered;
+       *data += transferred;
+       *count -= transferred;
+
+       if (hostdata->read_overruns) {
+               int cnt, toPIO;
 
-       if (atari_read_overruns) {
                if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
-                       cnt = toPIO = atari_read_overruns;
+                       cnt = toPIO = hostdata->read_overruns;
                        if (overrun) {
                                dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n");
                                *(*data)++ = saved_data;
@@ -1238,20 +1186,19 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
 #endif /* REAL_DMA */
 
 
-/*
- * Function : void NCR5380_intr (int irq)
- *
- * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
- *     from the disconnected queue, and restarting NCR5380_main()
- *     as required.
- *
- * Inputs : int irq, irq that caused this interrupt.
+/**
+ * NCR5380_intr - generic NCR5380 irq handler
+ * @irq: interrupt number
+ * @dev_id: device info
  *
+ * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
+ * from the disconnected queue, and restarting NCR5380_main()
+ * as required.
  */
 
 static irqreturn_t NCR5380_intr(int irq, void *dev_id)
 {
-       struct Scsi_Host *instance = first_instance;
+       struct Scsi_Host *instance = dev_id;
        int done = 1, handled = 0;
        unsigned char basr;
 
@@ -1265,7 +1212,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
                NCR5380_dprint(NDEBUG_INTR, instance);
                if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
                        done = 0;
-                       ENABLE_IRQ();
                        dprintk(NDEBUG_INTR, "scsi%d: SEL interrupt\n", HOSTNO);
                        NCR5380_reselect(instance);
                        (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
@@ -1295,17 +1241,19 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
                                dprintk(NDEBUG_INTR, "scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
                                NCR5380_dma_complete( instance );
                                done = 0;
-                               ENABLE_IRQ();
                        } else
 #endif /* REAL_DMA */
                        {
 /* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
                                if (basr & BASR_PHASE_MATCH)
-                                       printk(KERN_NOTICE "scsi%d: unknown interrupt, "
+                                       dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt, "
                                               "BASR 0x%x, MR 0x%x, SR 0x%x\n",
                                               HOSTNO, basr, NCR5380_read(MODE_REG),
                                               NCR5380_read(STATUS_REG));
                                (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+#ifdef SUN3_SCSI_VME
+                               dregs->csr |= CSR_DMA_ENABLE;
+#endif
                        }
                } /* if !(SELECTION || PARITY) */
                handled = 1;
@@ -1314,53 +1262,29 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id)
                       "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
                       NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
                (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+#ifdef SUN3_SCSI_VME
+               dregs->csr |= CSR_DMA_ENABLE;
+#endif
        }
 
        if (!done) {
                dprintk(NDEBUG_INTR, "scsi%d: in int routine, calling main\n", HOSTNO);
                /* Put a call to NCR5380_main() on the queue... */
-               queue_main();
+               queue_main(shost_priv(instance));
        }
        return IRQ_RETVAL(handled);
 }
 
-#ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
-{
-# ifdef NCR5380_STAT_LIMIT
-       if (scsi_bufflen(cmd) > NCR5380_STAT_LIMIT)
-# endif
-               switch (cmd->cmnd[0]) {
-               case WRITE:
-               case WRITE_6:
-               case WRITE_10:
-                       hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
-                       /*hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);*/
-                       hostdata->pendingw--;
-                       break;
-               case READ:
-               case READ_6:
-               case READ_10:
-                       hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
-                       /*hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);*/
-                       hostdata->pendingr--;
-                       break;
-               }
-}
-#endif
-
 /*
- * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,
- *     int tag);
+ * Function : int NCR5380_select(struct Scsi_Host *instance,
+ *                               struct scsi_cmnd *cmd)
  *
  * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
  *     including ARBITRATION, SELECTION, and initial message out for
  *     IDENTIFY and queue messages.
  *
  * Inputs : instance - instantiation of the 5380 driver on which this
- *     target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for
- *     new tag, TAG_NONE for untagged queueing, otherwise set to the tag for
- *     the command that is presently connected.
+ *     target lives, cmd - SCSI command to execute.
  *
  * Returns : -1 if selection could not execute for some reason,
  *     0 if selection succeeded or failed because the target
@@ -1380,7 +1304,7 @@ static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd)
  *             cmd->result host byte set to DID_BAD_TARGET.
  */
 
-static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
+static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
 {
        SETUP_HOSTDATA(instance);
        unsigned char tmp[3], phase;
@@ -1562,7 +1486,7 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
         * selection.
         */
 
-       timeout = jiffies + 25;
+       timeout = jiffies + (250 * HZ / 1000);
 
        /*
         * XXX very interesting - we're seeing a bounce where the BSY we
@@ -1616,9 +1540,6 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
                        return -1;
                }
                cmd->result = DID_BAD_TARGET << 16;
-#ifdef NCR5380_STATS
-               collect_stats(hostdata, cmd);
-#endif
 #ifdef SUPPORT_TAGS
                cmd_free_tag(cmd);
 #endif
@@ -1676,6 +1597,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
 #ifndef SUPPORT_TAGS
        hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 #endif
+#ifdef SUN3_SCSI_VME
+       dregs->csr |= CSR_INTR;
+#endif
 
        initialize_SCp(cmd);
 
@@ -1826,7 +1750,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
  * Returns : 0 on success, -1 on failure.
  */
 
-static int do_abort(struct Scsi_Host *host)
+static int do_abort(struct Scsi_Host *instance)
 {
        unsigned char tmp, *msgptr, phase;
        int len;
@@ -1861,7 +1785,7 @@ static int do_abort(struct Scsi_Host *host)
        msgptr = &tmp;
        len = 1;
        phase = PHASE_MSGOUT;
-       NCR5380_transfer_pio(host, &phase, &len, &msgptr);
+       NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
 
        /*
         * If we got here, and the command completed successfully,
@@ -1899,17 +1823,62 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
        SETUP_HOSTDATA(instance);
        register int c = *count;
        register unsigned char p = *phase;
+       unsigned long flags;
+
+#if defined(CONFIG_SUN3)
+       /* sanity check */
+       if (!sun3_dma_setup_done) {
+               pr_err("scsi%d: transfer_dma without setup!\n",
+                      instance->host_no);
+               BUG();
+       }
+       hostdata->dma_len = c;
+
+       dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
+               instance->host_no, (p & SR_IO) ? "reading" : "writing",
+               c, (p & SR_IO) ? "to" : "from", *data);
+
+       /* netbsd turns off ints here, why not be safe and do it too */
+       local_irq_save(flags);
+
+       /* send start chain */
+       sun3scsi_dma_start(c, *data);
+
+       if (p & SR_IO) {
+               NCR5380_write(TARGET_COMMAND_REG, 1);
+               NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+               NCR5380_write(INITIATOR_COMMAND_REG, 0);
+               NCR5380_write(MODE_REG,
+                             (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
+               NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
+       } else {
+               NCR5380_write(TARGET_COMMAND_REG, 0);
+               NCR5380_read(RESET_PARITY_INTERRUPT_REG);
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_DATA);
+               NCR5380_write(MODE_REG,
+                             (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
+               NCR5380_write(START_DMA_SEND_REG, 0);
+       }
+
+#ifdef SUN3_SCSI_VME
+       dregs->csr |= CSR_DMA_ENABLE;
+#endif
+
+       local_irq_restore(flags);
+
+       sun3_dma_active = 1;
+
+#else /* !defined(CONFIG_SUN3) */
        register unsigned char *d = *data;
        unsigned char tmp;
-       unsigned long flags;
 
        if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {
                *phase = tmp;
                return -1;
        }
 
-       if (atari_read_overruns && (p & SR_IO))
-               c -= atari_read_overruns;
+       if (hostdata->read_overruns && (p & SR_IO))
+               c -= hostdata->read_overruns;
 
        dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
                   HOSTNO, (p & SR_IO) ? "reading" : "writing",
@@ -1921,7 +1890,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
        NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
 #endif /* def REAL_DMA  */
 
-       if (IS_A_TT()) {
+       if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) {
                /* On the Medusa, it is a must to initialize the DMA before
                 * starting the NCR. This is also the cleaner way for the TT.
                 */
@@ -1939,7 +1908,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
                NCR5380_write(START_DMA_SEND_REG, 0);
        }
 
-       if (!IS_A_TT()) {
+       if (hostdata->flags & FLAG_LATE_DMA_SETUP) {
                /* On the Falcon, the DMA setup must be done after the last */
                /* NCR access, else the DMA setup gets trashed!
                 */
@@ -1949,6 +1918,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
                        NCR5380_dma_write_setup(instance, d, c);
                local_irq_restore(flags);
        }
+#endif /* !defined(CONFIG_SUN3) */
+
        return 0;
 }
 #endif /* defined(REAL_DMA) */
@@ -1982,7 +1953,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
 #endif
        unsigned char *data;
        unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
-       Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;
+       struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected;
+
+#ifdef SUN3_SCSI_VME
+       dregs->csr |= CSR_INTR;
+#endif
 
        while (1) {
                tmp = NCR5380_read(STATUS_REG);
@@ -1993,6 +1968,33 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                old_phase = phase;
                                NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
                        }
+#if defined(CONFIG_SUN3)
+                       if (phase == PHASE_CMDOUT) {
+#if defined(REAL_DMA)
+                               void *d;
+                               unsigned long count;
+
+                               if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
+                                       count = cmd->SCp.buffer->length;
+                                       d = sg_virt(cmd->SCp.buffer);
+                               } else {
+                                       count = cmd->SCp.this_residual;
+                                       d = cmd->SCp.ptr;
+                               }
+                               /* this command setup for dma yet? */
+                               if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != cmd)) {
+                                       if (cmd->request->cmd_type == REQ_TYPE_FS) {
+                                               sun3scsi_dma_setup(d, count,
+                                                                  rq_data_dir(cmd->request));
+                                               sun3_dma_setup_done = cmd;
+                                       }
+                               }
+#endif
+#ifdef SUN3_SCSI_VME
+                               dregs->csr |= CSR_INTR;
+#endif
+                       }
+#endif /* CONFIG_SUN3 */
 
                        if (sink && (phase != PHASE_MSGOUT)) {
                                NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
@@ -2054,8 +2056,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                 */
 
 #if defined(REAL_DMA)
-                               if (!cmd->device->borken &&
-                                   (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) {
+                               if (
+#if !defined(CONFIG_SUN3)
+                                   !cmd->device->borken &&
+#endif
+                                   (transfersize = NCR5380_dma_xfer_len(instance, cmd, phase)) >= DMA_MIN_SIZE) {
                                        len = transfersize;
                                        cmd->SCp.phase = phase;
                                        if (NCR5380_transfer_dma(instance, &phase,
@@ -2064,9 +2069,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                                 * If the watchdog timer fires, all future
                                                 * accesses to this device will use the
                                                 * polled-IO. */
-                                               printk(KERN_NOTICE "scsi%d: switching target %d "
-                                                          "lun %llu to slow handshake\n", HOSTNO,
-                                                          cmd->device->id, cmd->device->lun);
+                                               scmd_printk(KERN_INFO, cmd,
+                                                       "switching to slow handshake\n");
                                                cmd->device->borken = 1;
                                                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
                                                        ICR_ASSERT_ATN);
@@ -2092,6 +2096,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                        NCR5380_transfer_pio(instance, &phase,
                                                             (int *)&cmd->SCp.this_residual,
                                                             (unsigned char **)&cmd->SCp.ptr);
+#if defined(CONFIG_SUN3) && defined(REAL_DMA)
+                               /* if we had intended to dma that command clear it */
+                               if (sun3_dma_setup_done == cmd)
+                                       sun3_dma_setup_done = NULL;
+#endif
                                break;
                        case PHASE_MSGIN:
                                len = 1;
@@ -2145,9 +2154,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                        dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request "
                                                   "done, calling scsi_done().\n",
                                                   HOSTNO, cmd->device->id, cmd->device->lun);
-#ifdef NCR5380_STATS
-                                       collect_stats(hostdata, cmd);
-#endif
                                        cmd->scsi_done(cmd);
                                        cmd = hostdata->connected;
                                        break;
@@ -2156,11 +2162,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                case COMMAND_COMPLETE:
                                        /* Accept message by clearing ACK */
                                        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                                       /* ++guenther: possible race with Falcon locking */
-                                       falcon_dont_release++;
-                                       hostdata->connected = NULL;
                                        dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
                                                  "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
+
+                                       local_irq_save(flags);
+                                       hostdata->retain_dma_intr++;
+                                       hostdata->connected = NULL;
 #ifdef SUPPORT_TAGS
                                        cmd_free_tag(cmd);
                                        if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
@@ -2172,7 +2179,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                                 */
                                                /* ++Andreas: the mid level code knows about
                                                   QUEUE_FULL now. */
-                                               TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
+                                               struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][cmd->device->lun];
                                                dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned "
                                                           "QUEUE_FULL after %d commands\n",
                                                           HOSTNO, cmd->device->id, cmd->device->lun,
@@ -2207,7 +2214,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                        else if (status_byte(cmd->SCp.Status) != GOOD)
                                                cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
 
-#ifdef AUTOSENSE
                                        if ((cmd->cmnd[0] == REQUEST_SENSE) &&
                                                hostdata->ses.cmd_len) {
                                                scsi_eh_restore_cmnd(cmd, &hostdata->ses);
@@ -2220,22 +2226,17 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
 
                                                dprintk(NDEBUG_AUTOSENSE, "scsi%d: performing request sense\n", HOSTNO);
 
-                                               local_irq_save(flags);
                                                LIST(cmd,hostdata->issue_queue);
                                                SET_NEXT(cmd, hostdata->issue_queue);
-                                               hostdata->issue_queue = (Scsi_Cmnd *) cmd;
-                                               local_irq_restore(flags);
+                                               hostdata->issue_queue = (struct scsi_cmnd *) cmd;
                                                dprintk(NDEBUG_QUEUES, "scsi%d: REQUEST SENSE added to head of "
                                                          "issue queue\n", H_NO(cmd));
-                                       } else
-#endif /* def AUTOSENSE */
-                                       {
-#ifdef NCR5380_STATS
-                                               collect_stats(hostdata, cmd);
-#endif
+                                       } else {
                                                cmd->scsi_done(cmd);
                                        }
 
+                                       local_irq_restore(flags);
+
                                        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
                                        /*
                                         * Restore phase bits to 0 so an interrupted selection,
@@ -2246,12 +2247,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                        while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
                                                barrier();
 
-                                       falcon_dont_release--;
+                                       local_irq_save(flags);
+                                       hostdata->retain_dma_intr--;
                                        /* ++roman: For Falcon SCSI, release the lock on the
                                         * ST-DMA here if no other commands are waiting on the
                                         * disconnected queue.
                                         */
-                                       falcon_release_lock_if_possible(hostdata);
+                                       maybe_release_dma_irq(instance);
+                                       local_irq_restore(flags);
                                        return;
                                case MESSAGE_REJECT:
                                        /* Accept message by clearing ACK */
@@ -2303,6 +2306,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                        /* Wait for bus free to avoid nasty timeouts */
                                        while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
                                                barrier();
+#ifdef SUN3_SCSI_VME
+                                       dregs->csr |= CSR_DMA_ENABLE;
+#endif
                                        return;
                                        /*
                                         * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
@@ -2384,20 +2390,18 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                         */
                                default:
                                        if (!tmp) {
-                                               printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
+                                               printk(KERN_INFO "scsi%d: rejecting message ",
+                                                      instance->host_no);
                                                spi_print_msg(extended_msg);
                                                printk("\n");
                                        } else if (tmp != EXTENDED_MESSAGE)
-                                               printk(KERN_DEBUG "scsi%d: rejecting unknown "
-                                                      "message %02x from target %d, lun %llu\n",
-                                                      HOSTNO, tmp, cmd->device->id, cmd->device->lun);
+                                               scmd_printk(KERN_INFO, cmd,
+                                                           "rejecting unknown message %02x\n",
+                                                           tmp);
                                        else
-                                               printk(KERN_DEBUG "scsi%d: rejecting unknown "
-                                                      "extended message "
-                                                      "code %02x, length %d from target %d, lun %llu\n",
-                                                      HOSTNO, extended_msg[1], extended_msg[0],
-                                                      cmd->device->id, cmd->device->lun);
-
+                                               scmd_printk(KERN_INFO, cmd,
+                                                           "rejecting unknown extended message code %02x, length %d\n",
+                                                           extended_msg[1], extended_msg[0]);
 
                                        msgout = MESSAGE_REJECT;
                                        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
@@ -2410,6 +2414,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
                                hostdata->last_message = msgout;
                                NCR5380_transfer_pio(instance, &phase, &len, &data);
                                if (msgout == ABORT) {
+                                       local_irq_save(flags);
 #ifdef SUPPORT_TAGS
                                        cmd_free_tag(cmd);
 #else
@@ -2417,12 +2422,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
 #endif
                                        hostdata->connected = NULL;
                                        cmd->result = DID_ERROR << 16;
-#ifdef NCR5380_STATS
-                                       collect_stats(hostdata, cmd);
-#endif
-                                       cmd->scsi_done(cmd);
                                        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                                       falcon_release_lock_if_possible(hostdata);
+                                       maybe_release_dma_irq(instance);
+                                       local_irq_restore(flags);
+                                       cmd->scsi_done(cmd);
                                        return;
                                }
                                msgout = NOP;
@@ -2455,7 +2458,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
  * Function : void NCR5380_reselect (struct Scsi_Host *instance)
  *
  * Purpose : does reselection, initializing the instance->connected
- *     field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q
+ *     field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q
  *     nexus has been reestablished,
  *
  * Inputs : instance - this instance of the NCR5380.
@@ -2463,19 +2466,21 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
  */
 
 
+/* it might eventually prove necessary to do a dma setup on
+   reselection, but it doesn't seem to be needed now -- sam */
+
 static void NCR5380_reselect(struct Scsi_Host *instance)
 {
        SETUP_HOSTDATA(instance);
        unsigned char target_mask;
-       unsigned char lun, phase;
-       int len;
+       unsigned char lun;
 #ifdef SUPPORT_TAGS
        unsigned char tag;
 #endif
        unsigned char msg[3];
-       unsigned char *data;
-       Scsi_Cmnd *tmp = NULL, *prev;
-/*     unsigned long flags; */
+       int __maybe_unused len;
+       unsigned char __maybe_unused *data, __maybe_unused phase;
+       struct scsi_cmnd *tmp = NULL, *prev;
 
        /*
         * Disable arbitration, etc. since the host adapter obviously
@@ -2511,10 +2516,18 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
        while (!(NCR5380_read(STATUS_REG) & SR_REQ))
                ;
 
+#if defined(CONFIG_SUN3) && defined(REAL_DMA)
+       /* acknowledge toggle to MSGIN */
+       NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN));
+
+       /* peek at the byte without really hitting the bus */
+       msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG);
+#else
        len = 1;
        data = msg;
        phase = PHASE_MSGIN;
        NCR5380_transfer_pio(instance, &phase, &len, &data);
+#endif
 
        if (!(msg[0] & 0x80)) {
                printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
@@ -2524,13 +2537,13 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
        }
        lun = (msg[0] & 0x07);
 
-#ifdef SUPPORT_TAGS
+#if defined(SUPPORT_TAGS) && !defined(CONFIG_SUN3)
        /* If the phase is still MSGIN, the target wants to send some more
         * messages. In case it supports tagged queuing, this is probably a
         * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
         */
        tag = TAG_NONE;
-       if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+       if (phase == PHASE_MSGIN && (hostdata->flags & FLAG_TAGGED_QUEUING)) {
                /* Accept previous IDENTIFY message by clearing ACK */
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
                len = 2;
@@ -2548,15 +2561,13 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
         * just reestablished, and remove it from the disconnected queue.
         */
 
-       for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL;
+       for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL;
             tmp; prev = tmp, tmp = NEXT(tmp)) {
                if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
 #ifdef SUPPORT_TAGS
                    && (tag == tmp->tag)
 #endif
                    ) {
-                       /* ++guenther: prevent race with falcon_release_lock */
-                       falcon_dont_release++;
                        if (prev) {
                                REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
                                SET_NEXT(prev, NEXT(tmp));
@@ -2588,26 +2599,67 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
                return;
        }
 
+#if defined(CONFIG_SUN3) && defined(REAL_DMA)
+       /* engage dma setup for the command we just saw */
+       {
+               void *d;
+               unsigned long count;
+
+               if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) {
+                       count = tmp->SCp.buffer->length;
+                       d = sg_virt(tmp->SCp.buffer);
+               } else {
+                       count = tmp->SCp.this_residual;
+                       d = tmp->SCp.ptr;
+               }
+               /* setup this command for dma if not already */
+               if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != tmp)) {
+                       sun3scsi_dma_setup(d, count, rq_data_dir(tmp->request));
+                       sun3_dma_setup_done = tmp;
+               }
+       }
+
+       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
+#endif
+
        /* Accept message by clearing ACK */
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
+#if defined(SUPPORT_TAGS) && defined(CONFIG_SUN3)
+       /* If the phase is still MSGIN, the target wants to send some more
+        * messages. In case it supports tagged queuing, this is probably a
+        * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
+        */
+       tag = TAG_NONE;
+       if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
+               /* Accept previous IDENTIFY message by clearing ACK */
+               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
+               len = 2;
+               data = msg + 1;
+               if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
+                   msg[1] == SIMPLE_QUEUE_TAG)
+                       tag = msg[2];
+               dprintk(NDEBUG_TAGS, "scsi%d: target mask %02x, lun %d sent tag %d at reselection\n"
+                       HOSTNO, target_mask, lun, tag);
+       }
+#endif
+
        hostdata->connected = tmp;
        dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
                   HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
-       falcon_dont_release--;
 }
 
 
 /*
- * Function : int NCR5380_abort (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_abort (struct scsi_cmnd *cmd)
  *
  * Purpose : abort a command
  *
- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the
+ * Inputs : cmd - the scsi_cmnd to abort, code - code to set the
  *     host byte of the result field to, if zero DID_ABORTED is
  *     used.
  *
- * Returns : 0 - success, -1 on failure.
+ * Returns : SUCCESS - success, FAILED on failure.
  *
  * XXX - there is no way to abort the command that is currently
  *      connected, you have to wait for it to complete.  If this is
@@ -2616,24 +2668,19 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
  */
 
 static
-int NCR5380_abort(Scsi_Cmnd *cmd)
+int NCR5380_abort(struct scsi_cmnd *cmd)
 {
        struct Scsi_Host *instance = cmd->device->host;
        SETUP_HOSTDATA(instance);
-       Scsi_Cmnd *tmp, **prev;
+       struct scsi_cmnd *tmp, **prev;
        unsigned long flags;
 
-       printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
-       scsi_print_command(cmd);
+       scmd_printk(KERN_NOTICE, cmd, "aborting command\n");
 
        NCR5380_print_status(instance);
 
        local_irq_save(flags);
 
-       if (!IS_A_TT() && !falcon_got_lock)
-               printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
-                      HOSTNO);
-
        dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
                    NCR5380_read(BUS_AND_STATUS_REG),
                    NCR5380_read(STATUS_REG));
@@ -2674,12 +2721,12 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
 #else
                        hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
+                       maybe_release_dma_irq(instance);
                        local_irq_restore(flags);
                        cmd->scsi_done(cmd);
-                       falcon_release_lock_if_possible(hostdata);
                        return SUCCESS;
                } else {
-/*                     local_irq_restore(flags); */
+                       local_irq_restore(flags);
                        printk("scsi%d: abort of connected command failed!\n", HOSTNO);
                        return FAILED;
                }
@@ -2690,21 +2737,21 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
         * Case 2 : If the command hasn't been issued yet, we simply remove it
         *          from the issue queue.
         */
-       for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue),
-            tmp = (Scsi_Cmnd *)hostdata->issue_queue;
+       for (prev = (struct scsi_cmnd **)&(hostdata->issue_queue),
+            tmp = (struct scsi_cmnd *)hostdata->issue_queue;
             tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
                if (cmd == tmp) {
                        REMOVE(5, *prev, tmp, NEXT(tmp));
                        (*prev) = NEXT(tmp);
                        SET_NEXT(tmp, NULL);
                        tmp->result = DID_ABORT << 16;
+                       maybe_release_dma_irq(instance);
                        local_irq_restore(flags);
                        dprintk(NDEBUG_ABORT, "scsi%d: abort removed command from issue queue.\n",
                                    HOSTNO);
                        /* Tagged queuing note: no tag to free here, hasn't been assigned
                         * yet... */
                        tmp->scsi_done(tmp);
-                       falcon_release_lock_if_possible(hostdata);
                        return SUCCESS;
                }
        }
@@ -2751,13 +2798,13 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
         * it from the disconnected queue.
         */
 
-       for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
+       for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp;
             tmp = NEXT(tmp)) {
                if (cmd == tmp) {
                        local_irq_restore(flags);
                        dprintk(NDEBUG_ABORT, "scsi%d: aborting disconnected command.\n", HOSTNO);
 
-                       if (NCR5380_select(instance, cmd, (int)cmd->tag))
+                       if (NCR5380_select(instance, cmd))
                                return FAILED;
 
                        dprintk(NDEBUG_ABORT, "scsi%d: nexus reestablished.\n", HOSTNO);
@@ -2765,8 +2812,8 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
                        do_abort(instance);
 
                        local_irq_save(flags);
-                       for (prev = (Scsi_Cmnd **)&(hostdata->disconnected_queue),
-                            tmp = (Scsi_Cmnd *)hostdata->disconnected_queue;
+                       for (prev = (struct scsi_cmnd **)&(hostdata->disconnected_queue),
+                            tmp = (struct scsi_cmnd *)hostdata->disconnected_queue;
                             tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) {
                                if (cmd == tmp) {
                                        REMOVE(5, *prev, tmp, NEXT(tmp));
@@ -2782,15 +2829,22 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
 #else
                                        hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
 #endif
+                                       maybe_release_dma_irq(instance);
                                        local_irq_restore(flags);
                                        tmp->scsi_done(tmp);
-                                       falcon_release_lock_if_possible(hostdata);
                                        return SUCCESS;
                                }
                        }
                }
        }
 
+       /* Maybe it is sufficient just to release the ST-DMA lock... (if
+        * possible at all) At least, we should check if the lock could be
+        * released after the abort, in case it is kept due to some bug.
+        */
+       maybe_release_dma_irq(instance);
+       local_irq_restore(flags);
+
        /*
         * Case 5 : If we reached this point, the command was not found in any of
         *          the queues.
@@ -2801,21 +2855,14 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
         * broke.
         */
 
-       local_irq_restore(flags);
        printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO);
 
-       /* Maybe it is sufficient just to release the ST-DMA lock... (if
-        * possible at all) At least, we should check if the lock could be
-        * released after the abort, in case it is kept due to some bug.
-        */
-       falcon_release_lock_if_possible(hostdata);
-
        return FAILED;
 }
 
 
 /*
- * Function : int NCR5380_reset (Scsi_Cmnd *cmd)
+ * Function : int NCR5380_reset (struct scsi_cmnd *cmd)
  *
  * Purpose : reset the SCSI bus.
  *
@@ -2823,20 +2870,14 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
  *
  */
 
-static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
+static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
 {
-       SETUP_HOSTDATA(cmd->device->host);
+       struct Scsi_Host *instance = cmd->device->host;
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        int i;
        unsigned long flags;
-#if defined(RESET_RUN_DONE)
-       Scsi_Cmnd *connected, *disconnected_queue;
-#endif
-
-       if (!IS_A_TT() && !falcon_got_lock)
-               printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
-                      H_NO(cmd));
 
-       NCR5380_print_status(cmd->device->host);
+       NCR5380_print_status(instance);
 
        /* get in phase */
        NCR5380_write(TARGET_COMMAND_REG,
@@ -2853,89 +2894,6 @@ static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
         * through anymore ... */
        (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 
-       /* MSch 20140115 - looking at the generic NCR5380 driver, all of this
-        * should go.
-        * Catch-22: if we don't clear all queues, the SCSI driver lock will
-        * not be reset by atari_scsi_reset()!
-        */
-
-#if defined(RESET_RUN_DONE)
-       /* XXX Should now be done by midlevel code, but it's broken XXX */
-       /* XXX see below                                            XXX */
-
-       /* MSch: old-style reset: actually abort all command processing here */
-
-       /* After the reset, there are no more connected or disconnected commands
-        * and no busy units; to avoid problems with re-inserting the commands
-        * into the issue_queue (via scsi_done()), the aborted commands are
-        * remembered in local variables first.
-        */
-       local_irq_save(flags);
-       connected = (Scsi_Cmnd *)hostdata->connected;
-       hostdata->connected = NULL;
-       disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
-       hostdata->disconnected_queue = NULL;
-#ifdef SUPPORT_TAGS
-       free_all_tags();
-#endif
-       for (i = 0; i < 8; ++i)
-               hostdata->busy[i] = 0;
-#ifdef REAL_DMA
-       hostdata->dma_len = 0;
-#endif
-       local_irq_restore(flags);
-
-       /* In order to tell the mid-level code which commands were aborted,
-        * set the command status to DID_RESET and call scsi_done() !!!
-        * This ultimately aborts processing of these commands in the mid-level.
-        */
-
-       if ((cmd = connected)) {
-               dprintk(NDEBUG_ABORT, "scsi%d: reset aborted a connected command\n", H_NO(cmd));
-               cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-               cmd->scsi_done(cmd);
-       }
-
-       for (i = 0; (cmd = disconnected_queue); ++i) {
-               disconnected_queue = NEXT(cmd);
-               SET_NEXT(cmd, NULL);
-               cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-               cmd->scsi_done(cmd);
-       }
-       if (i > 0)
-               dprintk(NDEBUG_ABORT, "scsi: reset aborted %d disconnected command(s)\n", i);
-
-       /* The Falcon lock should be released after a reset...
-        */
-       /* ++guenther: moved to atari_scsi_reset(), to prevent a race between
-        * unlocking and enabling dma interrupt.
-        */
-/*     falcon_release_lock_if_possible( hostdata );*/
-
-       /* since all commands have been explicitly terminated, we need to tell
-        * the midlevel code that the reset was SUCCESSFUL, and there is no
-        * need to 'wake up' the commands by a request_sense
-        */
-       return SUCCESS;
-#else /* 1 */
-
-       /* MSch: new-style reset handling: let the mid-level do what it can */
-
-       /* ++guenther: MID-LEVEL IS STILL BROKEN.
-        * Mid-level is supposed to requeue all commands that were active on the
-        * various low-level queues. In fact it does this, but that's not enough
-        * because all these commands are subject to timeout. And if a timeout
-        * happens for any removed command, *_abort() is called but all queues
-        * are now empty. Abort then gives up the falcon lock, which is fatal,
-        * since the mid-level will queue more commands and must have the lock
-        * (it's all happening inside timer interrupt handler!!).
-        * Even worse, abort will return NOT_RUNNING for all those commands not
-        * on any queue, so they won't be retried ...
-        *
-        * Conclusion: either scsi.c disables timeout for all resetted commands
-        * immediately, or we lose!  As of linux-2.0.20 it doesn't.
-        */
-
        /* After the reset, there are no more connected or disconnected commands
         * and no busy units; so clear the low-level status here to avoid
         * conflicts when the mid-level code tries to wake up the affected
@@ -2954,16 +2912,16 @@ static int NCR5380_bus_reset(Scsi_Cmnd *cmd)
        hostdata->connected = NULL;
        hostdata->disconnected_queue = NULL;
 #ifdef SUPPORT_TAGS
-       free_all_tags();
+       free_all_tags(hostdata);
 #endif
        for (i = 0; i < 8; ++i)
                hostdata->busy[i] = 0;
 #ifdef REAL_DMA
        hostdata->dma_len = 0;
 #endif
+
+       maybe_release_dma_irq(instance);
        local_irq_restore(flags);
 
-       /* we did no complete reset of all commands, so a wakeup is required */
        return SUCCESS;
-#endif /* 1 */
 }
index b522134528d6185bb54ab4afbc3b9fcc02b881c4..d1c37a386947b03d080524dac5f18c244580bd08 100644 (file)
 /**************************************************************************/
 
 
-
 #include <linux/module.h>
-
-#define AUTOSENSE
-/* For the Atari version, use only polled IO or REAL_DMA */
-#define        REAL_DMA
-/* Support tagged queuing? (on devices that are able to... :-) */
-#define        SUPPORT_TAGS
-#define        MAX_TAGS 32
-
 #include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/ctype.h>
 #include <linux/delay.h>
-#include <linux/mm.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/nvram.h>
 #include <linux/bitops.h>
 #include <linux/wait.h>
+#include <linux/platform_device.h>
 
 #include <asm/setup.h>
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/traps.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "atari_scsi.h"
-#include "NCR5380.h"
 #include <asm/atari_stdma.h>
 #include <asm/atari_stram.h>
 #include <asm/io.h>
 
-#include <linux/stat.h>
+#include <scsi/scsi_host.h>
+
+/* Definitions for the core NCR5380 driver. */
+
+#define REAL_DMA
+#define SUPPORT_TAGS
+#define MAX_TAGS                        32
+#define DMA_MIN_SIZE                    32
+
+#define NCR5380_implementation_fields   /* none */
+
+#define NCR5380_read(reg)               atari_scsi_reg_read(reg)
+#define NCR5380_write(reg, value)       atari_scsi_reg_write(reg, value)
+
+#define NCR5380_queue_command           atari_scsi_queue_command
+#define NCR5380_abort                   atari_scsi_abort
+#define NCR5380_show_info               atari_scsi_show_info
+#define NCR5380_info                    atari_scsi_info
+
+#define NCR5380_dma_read_setup(instance, data, count) \
+        atari_scsi_dma_setup(instance, data, count, 0)
+#define NCR5380_dma_write_setup(instance, data, count) \
+        atari_scsi_dma_setup(instance, data, count, 1)
+#define NCR5380_dma_residual(instance) \
+        atari_scsi_dma_residual(instance)
+#define NCR5380_dma_xfer_len(instance, cmd, phase) \
+        atari_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO))
+
+#define NCR5380_acquire_dma_irq(instance)      falcon_get_lock(instance)
+#define NCR5380_release_dma_irq(instance)      falcon_release_lock()
+
+#include "NCR5380.h"
+
 
 #define        IS_A_TT()       ATARIHW_PRESENT(TT_SCSI)
 
@@ -149,23 +161,6 @@ static inline unsigned long SCSI_DMA_GETADR(void)
        return adr;
 }
 
-static inline void ENABLE_IRQ(void)
-{
-       if (IS_A_TT())
-               atari_enable_irq(IRQ_TT_MFP_SCSI);
-       else
-               atari_enable_irq(IRQ_MFP_FSCSI);
-}
-
-static inline void DISABLE_IRQ(void)
-{
-       if (IS_A_TT())
-               atari_disable_irq(IRQ_TT_MFP_SCSI);
-       else
-               atari_disable_irq(IRQ_MFP_FSCSI);
-}
-
-
 #define HOSTDATA_DMALEN                (((struct NCR5380_hostdata *) \
                                (atari_scsi_host->hostdata))->dma_len)
 
@@ -178,30 +173,9 @@ static inline void DISABLE_IRQ(void)
 #define        AFTER_RESET_DELAY       (5*HZ/2)
 #endif
 
-/***************************** Prototypes *****************************/
-
 #ifdef REAL_DMA
-static int scsi_dma_is_ignored_buserr(unsigned char dma_stat);
 static void atari_scsi_fetch_restbytes(void);
-static long atari_scsi_dma_residual(struct Scsi_Host *instance);
-static int falcon_classify_cmd(Scsi_Cmnd *cmd);
-static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
-                                       Scsi_Cmnd *cmd, int write_flag);
-#endif
-static irqreturn_t scsi_tt_intr(int irq, void *dummy);
-static irqreturn_t scsi_falcon_intr(int irq, void *dummy);
-static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata);
-static void falcon_get_lock(void);
-#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
-static void atari_scsi_reset_boot(void);
 #endif
-static unsigned char atari_scsi_tt_reg_read(unsigned char reg);
-static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value);
-static unsigned char atari_scsi_falcon_reg_read(unsigned char reg);
-static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value);
-
-/************************* End of Prototypes **************************/
-
 
 static struct Scsi_Host *atari_scsi_host;
 static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
@@ -226,8 +200,6 @@ static char         *atari_dma_orig_addr;
 /* mask for address bits that can't be used with the ST-DMA */
 static unsigned long   atari_dma_stram_mask;
 #define STRAM_ADDR(a)  (((a) & atari_dma_stram_mask) == 0)
-/* number of bytes to cut from a transfer to handle NCR overruns */
-static int atari_read_overruns;
 #endif
 
 static int setup_can_queue = -1;
@@ -386,10 +358,6 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy)
 
        NCR5380_intr(irq, dummy);
 
-#if 0
-       /* To be sure the int is not masked */
-       atari_enable_irq(IRQ_TT_MFP_SCSI);
-#endif
        return IRQ_HANDLED;
 }
 
@@ -480,257 +448,35 @@ static void atari_scsi_fetch_restbytes(void)
 #endif /* REAL_DMA */
 
 
-static int falcon_got_lock = 0;
-static DECLARE_WAIT_QUEUE_HEAD(falcon_fairness_wait);
-static int falcon_trying_lock = 0;
-static DECLARE_WAIT_QUEUE_HEAD(falcon_try_wait);
-static int falcon_dont_release = 0;
-
 /* This function releases the lock on the DMA chip if there is no
- * connected command and the disconnected queue is empty. On
- * releasing, instances of falcon_get_lock are awoken, that put
- * themselves to sleep for fairness. They can now try to get the lock
- * again (but others waiting longer more probably will win).
+ * connected command and the disconnected queue is empty.
  */
 
-static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata)
+static void falcon_release_lock(void)
 {
-       unsigned long flags;
-
        if (IS_A_TT())
                return;
 
-       local_irq_save(flags);
-
-       if (falcon_got_lock && !hostdata->disconnected_queue &&
-           !hostdata->issue_queue && !hostdata->connected) {
-
-               if (falcon_dont_release) {
-#if 0
-                       printk("WARNING: Lock release not allowed. Ignored\n");
-#endif
-                       local_irq_restore(flags);
-                       return;
-               }
-               falcon_got_lock = 0;
+       if (stdma_is_locked_by(scsi_falcon_intr))
                stdma_release();
-               wake_up(&falcon_fairness_wait);
-       }
-
-       local_irq_restore(flags);
 }
 
 /* This function manages the locking of the ST-DMA.
  * If the DMA isn't locked already for SCSI, it tries to lock it by
  * calling stdma_lock(). But if the DMA is locked by the SCSI code and
  * there are other drivers waiting for the chip, we do not issue the
- * command immediately but wait on 'falcon_fairness_queue'. We will be
- * waked up when the DMA is unlocked by some SCSI interrupt. After that
- * we try to get the lock again.
- * But we must be prepared that more than one instance of
- * falcon_get_lock() is waiting on the fairness queue. They should not
- * try all at once to call stdma_lock(), one is enough! For that, the
- * first one sets 'falcon_trying_lock', others that see that variable
- * set wait on the queue 'falcon_try_wait'.
- * Complicated, complicated.... Sigh...
+ * command immediately but tell the SCSI mid-layer to defer.
  */
 
-static void falcon_get_lock(void)
+static int falcon_get_lock(struct Scsi_Host *instance)
 {
-       unsigned long flags;
-
        if (IS_A_TT())
-               return;
-
-       local_irq_save(flags);
-
-       wait_event_cmd(falcon_fairness_wait,
-               in_interrupt() || !falcon_got_lock || !stdma_others_waiting(),
-               local_irq_restore(flags),
-               local_irq_save(flags));
-
-       while (!falcon_got_lock) {
-               if (in_irq())
-                       panic("Falcon SCSI hasn't ST-DMA lock in interrupt");
-               if (!falcon_trying_lock) {
-                       falcon_trying_lock = 1;
-                       stdma_lock(scsi_falcon_intr, NULL);
-                       falcon_got_lock = 1;
-                       falcon_trying_lock = 0;
-                       wake_up(&falcon_try_wait);
-               } else {
-                       wait_event_cmd(falcon_try_wait,
-                               falcon_got_lock && !falcon_trying_lock,
-                               local_irq_restore(flags),
-                               local_irq_save(flags));
-               }
-       }
-
-       local_irq_restore(flags);
-       if (!falcon_got_lock)
-               panic("Falcon SCSI: someone stole the lock :-(\n");
-}
-
-
-static int __init atari_scsi_detect(struct scsi_host_template *host)
-{
-       static int called = 0;
-       struct Scsi_Host *instance;
-
-       if (!MACH_IS_ATARI ||
-           (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) ||
-           called)
-               return 0;
-
-       host->proc_name = "Atari";
-
-       atari_scsi_reg_read  = IS_A_TT() ? atari_scsi_tt_reg_read :
-                                          atari_scsi_falcon_reg_read;
-       atari_scsi_reg_write = IS_A_TT() ? atari_scsi_tt_reg_write :
-                                          atari_scsi_falcon_reg_write;
-
-       /* setup variables */
-       host->can_queue =
-               (setup_can_queue > 0) ? setup_can_queue :
-               IS_A_TT() ? ATARI_TT_CAN_QUEUE : ATARI_FALCON_CAN_QUEUE;
-       host->cmd_per_lun =
-               (setup_cmd_per_lun > 0) ? setup_cmd_per_lun :
-               IS_A_TT() ? ATARI_TT_CMD_PER_LUN : ATARI_FALCON_CMD_PER_LUN;
-       /* Force sg_tablesize to 0 on a Falcon! */
-       host->sg_tablesize =
-               !IS_A_TT() ? ATARI_FALCON_SG_TABLESIZE :
-               (setup_sg_tablesize >= 0) ? setup_sg_tablesize : ATARI_TT_SG_TABLESIZE;
-
-       if (setup_hostid >= 0)
-               host->this_id = setup_hostid;
-       else {
-               /* use 7 as default */
-               host->this_id = 7;
-               /* Test if a host id is set in the NVRam */
-               if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
-                       unsigned char b = nvram_read_byte( 14 );
-                       /* Arbitration enabled? (for TOS) If yes, use configured host ID */
-                       if (b & 0x80)
-                               host->this_id = b & 7;
-               }
-       }
+               return 1;
 
-#ifdef SUPPORT_TAGS
-       if (setup_use_tagged_queuing < 0)
-               setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
-#endif
-#ifdef REAL_DMA
-       /* If running on a Falcon and if there's TT-Ram (i.e., more than one
-        * memory block, since there's always ST-Ram in a Falcon), then allocate a
-        * STRAM_BUFFER_SIZE byte dribble buffer for transfers from/to alternative
-        * Ram.
-        */
-       if (MACH_IS_ATARI && ATARIHW_PRESENT(ST_SCSI) &&
-           !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) {
-               atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
-               if (!atari_dma_buffer) {
-                       printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM "
-                                       "double buffer\n");
-                       return 0;
-               }
-               atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
-               atari_dma_orig_addr = 0;
-       }
-#endif
-       instance = scsi_register(host, sizeof(struct NCR5380_hostdata));
-       if (instance == NULL) {
-               atari_stram_free(atari_dma_buffer);
-               atari_dma_buffer = 0;
-               return 0;
-       }
-       atari_scsi_host = instance;
-       /*
-        * Set irq to 0, to avoid that the mid-level code disables our interrupt
-        * during queue_command calls. This is completely unnecessary, and even
-        * worse causes bad problems on the Falcon, where the int is shared with
-        * IDE and floppy!
-        */
-       instance->irq = 0;
-
-#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
-       atari_scsi_reset_boot();
-#endif
-       NCR5380_init(instance, 0);
-
-       if (IS_A_TT()) {
-
-               /* This int is actually "pseudo-slow", i.e. it acts like a slow
-                * interrupt after having cleared the pending flag for the DMA
-                * interrupt. */
-               if (request_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr, IRQ_TYPE_SLOW,
-                                "SCSI NCR5380", instance)) {
-                       printk(KERN_ERR "atari_scsi_detect: cannot allocate irq %d, aborting",IRQ_TT_MFP_SCSI);
-                       scsi_unregister(atari_scsi_host);
-                       atari_stram_free(atari_dma_buffer);
-                       atari_dma_buffer = 0;
-                       return 0;
-               }
-               tt_mfp.active_edge |= 0x80;             /* SCSI int on L->H */
-#ifdef REAL_DMA
-               tt_scsi_dma.dma_ctrl = 0;
-               atari_dma_residual = 0;
-
-               if (MACH_IS_MEDUSA) {
-                       /* While the read overruns (described by Drew Eckhardt in
-                        * NCR5380.c) never happened on TTs, they do in fact on the Medusa
-                        * (This was the cause why SCSI didn't work right for so long
-                        * there.) Since handling the overruns slows down a bit, I turned
-                        * the #ifdef's into a runtime condition.
-                        *
-                        * In principle it should be sufficient to do max. 1 byte with
-                        * PIO, but there is another problem on the Medusa with the DMA
-                        * rest data register. So 'atari_read_overruns' is currently set
-                        * to 4 to avoid having transfers that aren't a multiple of 4. If
-                        * the rest data bug is fixed, this can be lowered to 1.
-                        */
-                       atari_read_overruns = 4;
-               }
-#endif /*REAL_DMA*/
-       } else { /* ! IS_A_TT */
-
-               /* Nothing to do for the interrupt: the ST-DMA is initialized
-                * already by atari_init_INTS()
-                */
-
-#ifdef REAL_DMA
-               atari_dma_residual = 0;
-               atari_dma_active = 0;
-               atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
-                                       : 0xff000000);
-#endif
-       }
+       if (in_interrupt())
+               return stdma_try_lock(scsi_falcon_intr, instance);
 
-       printk(KERN_INFO "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCAT-GAT=%d "
-#ifdef SUPPORT_TAGS
-                       "TAGGED-QUEUING=%s "
-#endif
-                       "HOSTID=%d",
-                       instance->host_no, instance->hostt->can_queue,
-                       instance->hostt->cmd_per_lun,
-                       instance->hostt->sg_tablesize,
-#ifdef SUPPORT_TAGS
-                       setup_use_tagged_queuing ? "yes" : "no",
-#endif
-                       instance->hostt->this_id );
-       NCR5380_print_options(instance);
-       printk("\n");
-
-       called = 1;
-       return 1;
-}
-
-static int atari_scsi_release(struct Scsi_Host *sh)
-{
-       if (IS_A_TT())
-               free_irq(IRQ_TT_MFP_SCSI, sh);
-       if (atari_dma_buffer)
-               atari_stram_free(atari_dma_buffer);
-       NCR5380_exit(sh);
+       stdma_lock(scsi_falcon_intr, instance);
        return 1;
 }
 
@@ -739,7 +485,7 @@ static int __init atari_scsi_setup(char *str)
 {
        /* Format of atascsi parameter is:
         *   atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
-        * Defaults depend on TT or Falcon, hostid determined at run time.
+        * Defaults depend on TT or Falcon, determined at run time.
         * Negative values mean don't change.
         */
        int ints[6];
@@ -750,36 +496,17 @@ static int __init atari_scsi_setup(char *str)
                printk("atari_scsi_setup: no arguments!\n");
                return 0;
        }
-
-       if (ints[0] >= 1) {
-               if (ints[1] > 0)
-                       /* no limits on this, just > 0 */
-                       setup_can_queue = ints[1];
-       }
-       if (ints[0] >= 2) {
-               if (ints[2] > 0)
-                       setup_cmd_per_lun = ints[2];
-       }
-       if (ints[0] >= 3) {
-               if (ints[3] >= 0) {
-                       setup_sg_tablesize = ints[3];
-                       /* Must be <= SG_ALL (255) */
-                       if (setup_sg_tablesize > SG_ALL)
-                               setup_sg_tablesize = SG_ALL;
-               }
-       }
-       if (ints[0] >= 4) {
-               /* Must be between 0 and 7 */
-               if (ints[4] >= 0 && ints[4] <= 7)
-                       setup_hostid = ints[4];
-               else if (ints[4] > 7)
-                       printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]);
-       }
+       if (ints[0] >= 1)
+               setup_can_queue = ints[1];
+       if (ints[0] >= 2)
+               setup_cmd_per_lun = ints[2];
+       if (ints[0] >= 3)
+               setup_sg_tablesize = ints[3];
+       if (ints[0] >= 4)
+               setup_hostid = ints[4];
 #ifdef SUPPORT_TAGS
-       if (ints[0] >= 5) {
-               if (ints[5] >= 0)
-                       setup_use_tagged_queuing = !!ints[5];
-       }
+       if (ints[0] >= 5)
+               setup_use_tagged_queuing = ints[5];
 #endif
 
        return 1;
@@ -788,45 +515,6 @@ static int __init atari_scsi_setup(char *str)
 __setup("atascsi=", atari_scsi_setup);
 #endif /* !MODULE */
 
-static int atari_scsi_bus_reset(Scsi_Cmnd *cmd)
-{
-       int rv;
-       struct NCR5380_hostdata *hostdata =
-               (struct NCR5380_hostdata *)cmd->device->host->hostdata;
-
-       /* For doing the reset, SCSI interrupts must be disabled first,
-        * since the 5380 raises its IRQ line while _RST is active and we
-        * can't disable interrupts completely, since we need the timer.
-        */
-       /* And abort a maybe active DMA transfer */
-       if (IS_A_TT()) {
-               atari_turnoff_irq(IRQ_TT_MFP_SCSI);
-#ifdef REAL_DMA
-               tt_scsi_dma.dma_ctrl = 0;
-#endif /* REAL_DMA */
-       } else {
-               atari_turnoff_irq(IRQ_MFP_FSCSI);
-#ifdef REAL_DMA
-               st_dma.dma_mode_status = 0x90;
-               atari_dma_active = 0;
-               atari_dma_orig_addr = NULL;
-#endif /* REAL_DMA */
-       }
-
-       rv = NCR5380_bus_reset(cmd);
-
-       /* Re-enable ints */
-       if (IS_A_TT()) {
-               atari_turnon_irq(IRQ_TT_MFP_SCSI);
-       } else {
-               atari_turnon_irq(IRQ_MFP_FSCSI);
-       }
-       if (rv == SUCCESS)
-               falcon_release_lock_if_possible(hostdata);
-
-       return rv;
-}
-
 
 #ifdef CONFIG_ATARI_SCSI_RESET_BOOT
 static void __init atari_scsi_reset_boot(void)
@@ -860,15 +548,6 @@ static void __init atari_scsi_reset_boot(void)
 }
 #endif
 
-
-static const char *atari_scsi_info(struct Scsi_Host *host)
-{
-       /* atari_scsi_detect() is verbose enough... */
-       static const char string[] = "Atari native SCSI";
-       return string;
-}
-
-
 #if defined(REAL_DMA)
 
 static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance,
@@ -949,7 +628,7 @@ static long atari_scsi_dma_residual(struct Scsi_Host *instance)
 #define        CMD_SURELY_BYTE_MODE    1
 #define        CMD_MODE_UNKNOWN                2
 
-static int falcon_classify_cmd(Scsi_Cmnd *cmd)
+static int falcon_classify_cmd(struct scsi_cmnd *cmd)
 {
        unsigned char opcode = cmd->cmnd[0];
 
@@ -981,7 +660,7 @@ static int falcon_classify_cmd(Scsi_Cmnd *cmd)
  */
 
 static unsigned long atari_dma_xfer_len(unsigned long wanted_len,
-                                       Scsi_Cmnd *cmd, int write_flag)
+                                       struct scsi_cmnd *cmd, int write_flag)
 {
        unsigned long   possible_len, limit;
 
@@ -1099,23 +778,247 @@ static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value)
 
 #include "atari_NCR5380.c"
 
-static struct scsi_host_template driver_template = {
+static int atari_scsi_bus_reset(struct scsi_cmnd *cmd)
+{
+       int rv;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+#ifdef REAL_DMA
+       /* Abort a maybe active DMA transfer */
+       if (IS_A_TT()) {
+               tt_scsi_dma.dma_ctrl = 0;
+       } else {
+               st_dma.dma_mode_status = 0x90;
+               atari_dma_active = 0;
+               atari_dma_orig_addr = NULL;
+       }
+#endif
+
+       rv = NCR5380_bus_reset(cmd);
+
+       /* The 5380 raises its IRQ line while _RST is active but the ST DMA
+        * "lock" has been released so this interrupt may end up handled by
+        * floppy or IDE driver (if one of them holds the lock). The NCR5380
+        * interrupt flag has been cleared already.
+        */
+
+       local_irq_restore(flags);
+
+       return rv;
+}
+
+#define DRV_MODULE_NAME         "atari_scsi"
+#define PFX                     DRV_MODULE_NAME ": "
+
+static struct scsi_host_template atari_scsi_template = {
+       .module                 = THIS_MODULE,
+       .proc_name              = DRV_MODULE_NAME,
        .show_info              = atari_scsi_show_info,
        .name                   = "Atari native SCSI",
-       .detect                 = atari_scsi_detect,
-       .release                = atari_scsi_release,
        .info                   = atari_scsi_info,
        .queuecommand           = atari_scsi_queue_command,
        .eh_abort_handler       = atari_scsi_abort,
        .eh_bus_reset_handler   = atari_scsi_bus_reset,
-       .can_queue              = 0, /* initialized at run-time */
-       .this_id                = 0, /* initialized at run-time */
-       .sg_tablesize           = 0, /* initialized at run-time */
-       .cmd_per_lun            = 0, /* initialized at run-time */
+       .this_id                = 7,
        .use_clustering         = DISABLE_CLUSTERING
 };
 
+static int __init atari_scsi_probe(struct platform_device *pdev)
+{
+       struct Scsi_Host *instance;
+       int error;
+       struct resource *irq;
+       int host_flags = 0;
+
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq)
+               return -ENODEV;
+
+       if (ATARIHW_PRESENT(TT_SCSI)) {
+               atari_scsi_reg_read  = atari_scsi_tt_reg_read;
+               atari_scsi_reg_write = atari_scsi_tt_reg_write;
+       } else {
+               atari_scsi_reg_read  = atari_scsi_falcon_reg_read;
+               atari_scsi_reg_write = atari_scsi_falcon_reg_write;
+       }
+
+       /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary.
+        * Higher values should work, too; try it!
+        * (But cmd_per_lun costs memory!)
+        *
+        * But there seems to be a bug somewhere that requires CAN_QUEUE to be
+        * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since
+        * changed CMD_PER_LUN...
+        *
+        * Note: The Falcon currently uses 8/1 setting due to unsolved problems
+        * with cmd_per_lun != 1
+        */
+       if (ATARIHW_PRESENT(TT_SCSI)) {
+               atari_scsi_template.can_queue    = 16;
+               atari_scsi_template.cmd_per_lun  = 8;
+               atari_scsi_template.sg_tablesize = SG_ALL;
+       } else {
+               atari_scsi_template.can_queue    = 8;
+               atari_scsi_template.cmd_per_lun  = 1;
+               atari_scsi_template.sg_tablesize = SG_NONE;
+       }
+
+       if (setup_can_queue > 0)
+               atari_scsi_template.can_queue = setup_can_queue;
+
+       if (setup_cmd_per_lun > 0)
+               atari_scsi_template.cmd_per_lun = setup_cmd_per_lun;
+
+       /* Leave sg_tablesize at 0 on a Falcon! */
+       if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0)
+               atari_scsi_template.sg_tablesize = setup_sg_tablesize;
+
+       if (setup_hostid >= 0) {
+               atari_scsi_template.this_id = setup_hostid & 7;
+       } else {
+               /* Test if a host id is set in the NVRam */
+               if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
+                       unsigned char b = nvram_read_byte(14);
+
+                       /* Arbitration enabled? (for TOS)
+                        * If yes, use configured host ID
+                        */
+                       if (b & 0x80)
+                               atari_scsi_template.this_id = b & 7;
+               }
+       }
+
+
+#ifdef REAL_DMA
+       /* If running on a Falcon and if there's TT-Ram (i.e., more than one
+        * memory block, since there's always ST-Ram in a Falcon), then
+        * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers
+        * from/to alternative Ram.
+        */
+       if (ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) &&
+           m68k_num_memory > 1) {
+               atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
+               if (!atari_dma_buffer) {
+                       pr_err(PFX "can't allocate ST-RAM double buffer\n");
+                       return -ENOMEM;
+               }
+               atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
+               atari_dma_orig_addr = 0;
+       }
+#endif
+
+       instance = scsi_host_alloc(&atari_scsi_template,
+                                  sizeof(struct NCR5380_hostdata));
+       if (!instance) {
+               error = -ENOMEM;
+               goto fail_alloc;
+       }
+       atari_scsi_host = instance;
+
+#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
+       atari_scsi_reset_boot();
+#endif
+
+       instance->irq = irq->start;
+
+       host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP;
+
+#ifdef SUPPORT_TAGS
+       host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
+#endif
+
+       NCR5380_init(instance, host_flags);
+
+       if (IS_A_TT()) {
+               error = request_irq(instance->irq, scsi_tt_intr, 0,
+                                   "NCR5380", instance);
+               if (error) {
+                       pr_err(PFX "request irq %d failed, aborting\n",
+                              instance->irq);
+                       goto fail_irq;
+               }
+               tt_mfp.active_edge |= 0x80;     /* SCSI int on L->H */
+#ifdef REAL_DMA
+               tt_scsi_dma.dma_ctrl = 0;
+               atari_dma_residual = 0;
+
+               /* While the read overruns (described by Drew Eckhardt in
+                * NCR5380.c) never happened on TTs, they do in fact on the
+                * Medusa (This was the cause why SCSI didn't work right for
+                * so long there.) Since handling the overruns slows down
+                * a bit, I turned the #ifdef's into a runtime condition.
+                *
+                * In principle it should be sufficient to do max. 1 byte with
+                * PIO, but there is another problem on the Medusa with the DMA
+                * rest data register. So read_overruns is currently set
+                * to 4 to avoid having transfers that aren't a multiple of 4.
+                * If the rest data bug is fixed, this can be lowered to 1.
+                */
+               if (MACH_IS_MEDUSA) {
+                       struct NCR5380_hostdata *hostdata =
+                               shost_priv(instance);
+
+                       hostdata->read_overruns = 4;
+               }
+#endif
+       } else {
+               /* Nothing to do for the interrupt: the ST-DMA is initialized
+                * already.
+                */
+#ifdef REAL_DMA
+               atari_dma_residual = 0;
+               atari_dma_active = 0;
+               atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
+                                       : 0xff000000);
+#endif
+       }
+
+       error = scsi_add_host(instance, NULL);
+       if (error)
+               goto fail_host;
+
+       platform_set_drvdata(pdev, instance);
+
+       scsi_scan_host(instance);
+       return 0;
+
+fail_host:
+       if (IS_A_TT())
+               free_irq(instance->irq, instance);
+fail_irq:
+       NCR5380_exit(instance);
+       scsi_host_put(instance);
+fail_alloc:
+       if (atari_dma_buffer)
+               atari_stram_free(atari_dma_buffer);
+       return error;
+}
+
+static int __exit atari_scsi_remove(struct platform_device *pdev)
+{
+       struct Scsi_Host *instance = platform_get_drvdata(pdev);
+
+       scsi_remove_host(instance);
+       if (IS_A_TT())
+               free_irq(instance->irq, instance);
+       NCR5380_exit(instance);
+       scsi_host_put(instance);
+       if (atari_dma_buffer)
+               atari_stram_free(atari_dma_buffer);
+       return 0;
+}
+
+static struct platform_driver atari_scsi_driver = {
+       .remove = __exit_p(atari_scsi_remove),
+       .driver = {
+               .name   = DRV_MODULE_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
 
-#include "scsi_module.c"
+module_platform_driver_probe(atari_scsi_driver, atari_scsi_probe);
 
+MODULE_ALIAS("platform:" DRV_MODULE_NAME);
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
deleted file mode 100644 (file)
index 3299d91..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * atari_scsi.h -- Header file for the Atari native SCSI driver
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * (Loosely based on the work of Robert De Vries' team)
- *
- * 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 ATARI_SCSI_H
-#define ATARI_SCSI_H
-
-/* (I_HAVE_OVERRUNS stuff removed) */
-
-#ifndef ASM
-/* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher
- * values should work, too; try it! (but cmd_per_lun costs memory!) */
-
-/* But there seems to be a bug somewhere that requires CAN_QUEUE to be
- * 2*CMD_PER_LUN. At least on a TT, no spurious timeouts seen since
- * changed CMD_PER_LUN... */
-
-/* Note: The Falcon currently uses 8/1 setting due to unsolved problems with
- * cmd_per_lun != 1 */
-
-#define ATARI_TT_CAN_QUEUE             16
-#define ATARI_TT_CMD_PER_LUN           8
-#define ATARI_TT_SG_TABLESIZE          SG_ALL
-
-#define ATARI_FALCON_CAN_QUEUE         8
-#define ATARI_FALCON_CMD_PER_LUN       1
-#define ATARI_FALCON_SG_TABLESIZE      SG_NONE
-
-#define        DEFAULT_USE_TAGGED_QUEUING      0
-
-
-#define        NCR5380_implementation_fields   /* none */
-
-#define NCR5380_read(reg)                atari_scsi_reg_read( reg )
-#define NCR5380_write(reg, value) atari_scsi_reg_write( reg, value )
-
-#define NCR5380_intr atari_scsi_intr
-#define NCR5380_queue_command atari_scsi_queue_command
-#define NCR5380_abort atari_scsi_abort
-#define NCR5380_show_info atari_scsi_show_info
-#define NCR5380_dma_read_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 0)
-#define NCR5380_dma_write_setup(inst,d,c) atari_scsi_dma_setup (inst, d, c, 1)
-#define NCR5380_dma_residual(inst) atari_scsi_dma_residual( inst )
-#define        NCR5380_dma_xfer_len(i,cmd,phase) \
-       atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
-
-#endif /* ndef ASM */
-#endif /* ATARI_SCSI_H */
-
-
index 30d74a06b9935c5ec760ce3f7f6788a7600d5a33..f3193406776cb94aa1a43df76a230cc1fed8b753 100644 (file)
@@ -556,7 +556,7 @@ static struct scsi_host_template beiscsi_sht = {
        .name = "Emulex 10Gbe open-iscsi Initiator Driver",
        .proc_name = DRV_NAME,
        .queuecommand = iscsi_queuecommand,
-       .change_queue_depth = iscsi_change_queue_depth,
+       .change_queue_depth = scsi_change_queue_depth,
        .slave_configure = beiscsi_slave_configure,
        .target_alloc = iscsi_target_alloc,
        .eh_abort_handler = beiscsi_eh_abort,
@@ -570,7 +570,7 @@ static struct scsi_host_template beiscsi_sht = {
        .cmd_per_lun = BEISCSI_CMD_PER_LUN,
        .use_clustering = ENABLE_CLUSTERING,
        .vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID,
-
+       .track_queue_depth = 1,
 };
 
 static struct scsi_transport_template *beiscsi_scsi_transport;
index 8e83d0474fe7c57560714dd488d4db1fcc1f4d15..74a307c0a2407c45af6ad42796d4944a3bec2bed 100644 (file)
@@ -260,18 +260,9 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
        unsigned long flags;
        void *kern_buf;
 
-       kern_buf = kzalloc(nbytes, GFP_KERNEL);
-
-       if (!kern_buf) {
-               printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
-                               bfad->inst_no);
-               return -ENOMEM;
-       }
-
-       if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) {
-               kfree(kern_buf);
-               return -ENOMEM;
-       }
+       kern_buf = memdup_user(buf, nbytes);
+       if (IS_ERR(kern_buf))
+               return PTR_ERR(kern_buf);
 
        rc = sscanf(kern_buf, "%x:%x", &addr, &len);
        if (rc < 2) {
@@ -336,18 +327,9 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
        unsigned long flags;
        void *kern_buf;
 
-       kern_buf = kzalloc(nbytes, GFP_KERNEL);
-
-       if (!kern_buf) {
-               printk(KERN_INFO "bfad[%d]: Failed to allocate buffer\n",
-                               bfad->inst_no);
-               return -ENOMEM;
-       }
-
-       if (copy_from_user(kern_buf, (void  __user *)buf, nbytes)) {
-               kfree(kern_buf);
-               return -ENOMEM;
-       }
+       kern_buf = memdup_user(buf, nbytes);
+       if (IS_ERR(kern_buf))
+               return PTR_ERR(kern_buf);
 
        rc = sscanf(kern_buf, "%x:%x", &addr, &val);
        if (rc < 2) {
index f067332bf7635901d393189fde960616ffb21c52..7223b00067405171191aaae4d4156a7b9061f230 100644 (file)
@@ -776,11 +776,7 @@ bfad_thread_workq(struct bfad_s *bfad)
 static int
 bfad_im_slave_configure(struct scsi_device *sdev)
 {
-       if (sdev->tagged_supported)
-               scsi_activate_tcq(sdev, bfa_lun_queue_depth);
-       else
-               scsi_deactivate_tcq(sdev, bfa_lun_queue_depth);
-
+       scsi_change_queue_depth(sdev, bfa_lun_queue_depth);
        return 0;
 }
 
@@ -804,6 +800,7 @@ struct scsi_host_template bfad_im_scsi_host_template = {
        .shost_attrs = bfad_im_host_attrs,
        .max_sectors = BFAD_MAX_SECTORS,
        .vendor_id = BFA_PCI_VENDOR_ID_BROCADE,
+       .use_blk_tags = 1,
 };
 
 struct scsi_host_template bfad_im_vport_template = {
@@ -825,6 +822,7 @@ struct scsi_host_template bfad_im_vport_template = {
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = bfad_im_vport_attrs,
        .max_sectors = BFAD_MAX_SECTORS,
+       .use_blk_tags = 1,
 };
 
 bfa_status_t
@@ -868,14 +866,8 @@ bfad_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev)
                        if (bfa_lun_queue_depth > tmp_sdev->queue_depth) {
                                if (tmp_sdev->id != sdev->id)
                                        continue;
-                               if (tmp_sdev->ordered_tags)
-                                       scsi_adjust_queue_depth(tmp_sdev,
-                                               MSG_ORDERED_TAG,
-                                               tmp_sdev->queue_depth + 1);
-                               else
-                                       scsi_adjust_queue_depth(tmp_sdev,
-                                               MSG_SIMPLE_TAG,
-                                               tmp_sdev->queue_depth + 1);
+                               scsi_change_queue_depth(tmp_sdev,
+                                       tmp_sdev->queue_depth + 1);
 
                                itnim->last_ramp_up_time = jiffies;
                        }
index ca75c7ca25590cdb15ae562bd9bd87cd28fcce9b..ef355c13ccc47c9a9f05cde438408e4e56b3eb3d 100644 (file)
@@ -480,9 +480,7 @@ void bnx2fc_rec_compl(struct bnx2fc_els_cb_arg *cb_arg)
                        bnx2fc_initiate_cleanup(orig_io_req);
                        /* Post a new IO req with the same sc_cmd */
                        BNX2FC_IO_DBG(rec_req, "Post IO request again\n");
-                       spin_unlock_bh(&tgt->tgt_lock);
                        rc = bnx2fc_post_io_req(tgt, new_io_req);
-                       spin_lock_bh(&tgt->tgt_lock);
                        if (!rc)
                                goto free_frame;
                        BNX2FC_IO_DBG(rec_req, "REC: io post err\n");
index 79e5c94107a9cc44fe8269f55ab72e8150005e0b..e861f286b42e494339eb46d5e58510911f7d43c8 100644 (file)
@@ -412,6 +412,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
        struct fc_frame_header *fh;
        struct fcoe_rcv_info *fr;
        struct fcoe_percpu_s *bg;
+       struct sk_buff *tmp_skb;
        unsigned short oxid;
 
        interface = container_of(ptype, struct bnx2fc_interface,
@@ -424,6 +425,12 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
                goto err;
        }
 
+       tmp_skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!tmp_skb)
+               goto err;
+
+       skb = tmp_skb;
+
        if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
                printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n");
                goto err;
@@ -1081,7 +1088,7 @@ static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
        mutex_unlock(&bnx2fc_dev_lock);
        rtnl_unlock();
 
-       if (IS_ERR(vn_port)) {
+       if (!vn_port) {
                printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n",
                        netdev->name);
                return -EIO;
@@ -2195,6 +2202,7 @@ static int _bnx2fc_create(struct net_device *netdev,
        interface = bnx2fc_interface_create(hba, netdev, fip_mode);
        if (!interface) {
                printk(KERN_ERR PFX "bnx2fc_interface_create failed\n");
+               rc = -ENOMEM;
                goto ifput_err;
        }
 
@@ -2783,13 +2791,15 @@ static struct scsi_host_template bnx2fc_shost_template = {
        .eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */
        .eh_host_reset_handler  = fc_eh_host_reset,
        .slave_alloc            = fc_slave_alloc,
-       .change_queue_depth     = fc_change_queue_depth,
-       .change_queue_type      = fc_change_queue_type,
+       .change_queue_depth     = scsi_change_queue_depth,
+       .change_queue_type      = scsi_change_queue_type,
        .this_id                = -1,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
        .sg_tablesize           = BNX2FC_MAX_BDS_PER_CMD,
        .max_sectors            = 1024,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
index 0679782d9d15e05b5d536c95b25dd643249f142e..4b56858c1df29f17fb5867158ec50eb683ae8b44 100644 (file)
@@ -1725,7 +1725,6 @@ void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
                                  struct fcp_cmnd *fcp_cmnd)
 {
        struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
-       char tag[2];
 
        memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
 
@@ -1739,21 +1738,10 @@ void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
        fcp_cmnd->fc_tm_flags = io_req->mp_req.tm_flags;
        fcp_cmnd->fc_flags = io_req->io_req_flags;
 
-       if (scsi_populate_tag_msg(sc_cmd, tag)) {
-               switch (tag[0]) {
-               case HEAD_OF_QUEUE_TAG:
-                       fcp_cmnd->fc_pri_ta = FCP_PTA_HEADQ;
-                       break;
-               case ORDERED_QUEUE_TAG:
-                       fcp_cmnd->fc_pri_ta = FCP_PTA_ORDERED;
-                       break;
-               default:
-                       fcp_cmnd->fc_pri_ta = FCP_PTA_SIMPLE;
-                       break;
-               }
-       } else {
+       if (sc_cmd->flags & SCMD_TAGGED)
+               fcp_cmnd->fc_pri_ta = FCP_PTA_SIMPLE;
+       else
                fcp_cmnd->fc_pri_ta = 0;
-       }
 }
 
 static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
@@ -1894,18 +1882,24 @@ int bnx2fc_queuecommand(struct Scsi_Host *host,
                        goto exit_qcmd;
                }
        }
+
+       spin_lock_bh(&tgt->tgt_lock);
+
        io_req = bnx2fc_cmd_alloc(tgt);
        if (!io_req) {
                rc = SCSI_MLQUEUE_HOST_BUSY;
-               goto exit_qcmd;
+               goto exit_qcmd_tgtlock;
        }
        io_req->sc_cmd = sc_cmd;
 
        if (bnx2fc_post_io_req(tgt, io_req)) {
                printk(KERN_ERR PFX "Unable to post io_req\n");
                rc = SCSI_MLQUEUE_HOST_BUSY;
-               goto exit_qcmd;
+               goto exit_qcmd_tgtlock;
        }
+
+exit_qcmd_tgtlock:
+       spin_unlock_bh(&tgt->tgt_lock);
 exit_qcmd:
        return rc;
 }
@@ -2020,6 +2014,8 @@ int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
        int task_idx, index;
        u16 xid;
 
+       /* bnx2fc_post_io_req() is called with the tgt_lock held */
+
        /* Initialize rest of io_req fields */
        io_req->cmd_type = BNX2FC_SCSI_CMD;
        io_req->port = port;
@@ -2047,9 +2043,7 @@ int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
        /* Build buffer descriptor list for firmware from sg list */
        if (bnx2fc_build_bd_list_from_sg(io_req)) {
                printk(KERN_ERR PFX "BD list creation failed\n");
-               spin_lock_bh(&tgt->tgt_lock);
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
-               spin_unlock_bh(&tgt->tgt_lock);
                return -EAGAIN;
        }
 
@@ -2061,19 +2055,15 @@ int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
        task = &(task_page[index]);
        bnx2fc_init_task(io_req, task);
 
-       spin_lock_bh(&tgt->tgt_lock);
-
        if (tgt->flush_in_prog) {
                printk(KERN_ERR PFX "Flush in progress..Host Busy\n");
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
-               spin_unlock_bh(&tgt->tgt_lock);
                return -EAGAIN;
        }
 
        if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
                printk(KERN_ERR PFX "Session not ready...post_io\n");
                kref_put(&io_req->refcount, bnx2fc_cmd_release);
-               spin_unlock_bh(&tgt->tgt_lock);
                return -EAGAIN;
        }
 
@@ -2091,6 +2081,5 @@ int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
 
        /* Ring doorbell */
        bnx2fc_ring_doorbell(tgt);
-       spin_unlock_bh(&tgt->tgt_lock);
        return 0;
 }
index 7a36388822aab7241baab2bbe0c751ce1526a384..e53078d033099ce8a3942e1151e9b9044fea0c8d 100644 (file)
@@ -2259,7 +2259,7 @@ static struct scsi_host_template bnx2i_host_template = {
        .eh_abort_handler       = iscsi_eh_abort,
        .eh_device_reset_handler = iscsi_eh_device_reset,
        .eh_target_reset_handler = iscsi_eh_recover_target,
-       .change_queue_depth     = iscsi_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
        .target_alloc           = iscsi_target_alloc,
        .can_queue              = 2048,
        .max_sectors            = 127,
@@ -2268,6 +2268,7 @@ static struct scsi_host_template bnx2i_host_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .sg_tablesize           = ISCSI_MAX_BDS_PER_CMD,
        .shost_attrs            = bnx2i_dev_attributes,
+       .track_queue_depth      = 1,
 };
 
 struct iscsi_transport bnx2i_iscsi_transport = {
index ef5ae0d0361676af1afee8e86b709ec5cabf7000..6bac8a746ee2edc49dad2dd0643d65ba00805508 100644 (file)
@@ -85,8 +85,7 @@ static const char * vendor_labels[CH_TYPES-4] = {
 // module_param_string_array(vendor_labels, NULL, 0444);
 
 #define ch_printk(prefix, ch, fmt, a...) \
-       sdev_printk(prefix, (ch)->device, "[%s] " fmt, \
-                   (ch)->name, ##a)
+       sdev_prefix_printk(prefix, (ch)->device, (ch)->name, fmt, ##a)
 
 #define DPRINTK(fmt, arg...)                                           \
 do {                                                                   \
@@ -183,7 +182,7 @@ static int ch_find_errno(struct scsi_sense_hdr *sshdr)
 }
 
 static int
-ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
+ch_do_scsi(scsi_changer *ch, unsigned char *cmd, int cmd_len,
           void *buffer, unsigned buflength,
           enum dma_data_direction direction)
 {
@@ -197,7 +196,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
        errno = 0;
        if (debug) {
                DPRINTK("command: ");
-               __scsi_print_command(cmd);
+               __scsi_print_command(cmd, cmd_len);
        }
 
        result = scsi_execute_req(ch->device, cmd, direction, buffer,
@@ -207,7 +206,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
        DPRINTK("result: 0x%x\n",result);
        if (driver_byte(result) & DRIVER_SENSE) {
                if (debug)
-                       scsi_print_sense_hdr(ch->name, &sshdr);
+                       scsi_print_sense_hdr(ch->device, ch->name, &sshdr);
                errno = ch_find_errno(&sshdr);
 
                switch(sshdr.sense_key) {
@@ -258,7 +257,8 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
        cmd[3] = elem        & 0xff;
        cmd[5] = 1;
        cmd[9] = 255;
-       if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
+       if (0 == (result = ch_do_scsi(ch, cmd, 12,
+                                     buffer, 256, DMA_FROM_DEVICE))) {
                if (((buffer[16] << 8) | buffer[17]) != elem) {
                        DPRINTK("asked for element 0x%02x, got 0x%02x\n",
                                elem,(buffer[16] << 8) | buffer[17]);
@@ -288,7 +288,7 @@ ch_init_elem(scsi_changer *ch)
        memset(cmd,0,sizeof(cmd));
        cmd[0] = INITIALIZE_ELEMENT_STATUS;
        cmd[1] = (ch->device->lun & 0x7) << 5;
-       err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
+       err = ch_do_scsi(ch, cmd, 6, NULL, 0, DMA_NONE);
        VPRINTK(KERN_INFO, "... finished\n");
        return err;
 }
@@ -310,10 +310,10 @@ ch_readconfig(scsi_changer *ch)
        cmd[1] = (ch->device->lun & 0x7) << 5;
        cmd[2] = 0x1d;
        cmd[4] = 255;
-       result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
+       result = ch_do_scsi(ch, cmd, 10, buffer, 255, DMA_FROM_DEVICE);
        if (0 != result) {
                cmd[1] |= (1<<3);
-               result  = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
+               result  = ch_do_scsi(ch, cmd, 10, buffer, 255, DMA_FROM_DEVICE);
        }
        if (0 == result) {
                ch->firsts[CHET_MT] =
@@ -438,7 +438,7 @@ ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
        cmd[4]  = (elem  >> 8) & 0xff;
        cmd[5]  =  elem        & 0xff;
        cmd[8]  = rotate ? 1 : 0;
-       return ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
+       return ch_do_scsi(ch, cmd, 10, NULL, 0, DMA_NONE);
 }
 
 static int
@@ -459,7 +459,7 @@ ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
        cmd[6]  = (dest  >> 8) & 0xff;
        cmd[7]  =  dest        & 0xff;
        cmd[10] = rotate ? 1 : 0;
-       return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
+       return ch_do_scsi(ch, cmd, 12, NULL,0, DMA_NONE);
 }
 
 static int
@@ -485,7 +485,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src,
        cmd[9]  =  dest2       & 0xff;
        cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
 
-       return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
+       return ch_do_scsi(ch, cmd, 12, NULL, 0, DMA_NONE);
 }
 
 static void
@@ -535,7 +535,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
        memcpy(buffer,tag,32);
        ch_check_voltag(buffer);
 
-       result = ch_do_scsi(ch, cmd, buffer, 256, DMA_TO_DEVICE);
+       result = ch_do_scsi(ch, cmd, 12, buffer, 256, DMA_TO_DEVICE);
        kfree(buffer);
        return result;
 }
@@ -616,6 +616,11 @@ static long ch_ioctl(struct file *file,
        int retval;
        void __user *argp = (void __user *)arg;
 
+       retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
+                       file->f_flags & O_NDELAY);
+       if (retval)
+               return retval;
+
        switch (cmd) {
        case CHIOGPARAMS:
        {
@@ -766,7 +771,8 @@ static long ch_ioctl(struct file *file,
                ch_cmd[5] = 1;
                ch_cmd[9] = 255;
 
-               result = ch_do_scsi(ch, ch_cmd, buffer, 256, DMA_FROM_DEVICE);
+               result = ch_do_scsi(ch, ch_cmd, 12,
+                                   buffer, 256, DMA_FROM_DEVICE);
                if (!result) {
                        cge.cge_status = buffer[18];
                        cge.cge_flags = 0;
@@ -966,9 +972,9 @@ static int ch_remove(struct device *dev)
 }
 
 static struct scsi_driver ch_template = {
-       .owner          = THIS_MODULE,
        .gendrv         = {
                .name   = "ch",
+               .owner  = THIS_MODULE,
                .probe  = ch_probe,
                .remove = ch_remove,
        },
index d35a5d6c8d7c8219f5b142b82a02a8f79009a48d..e2068a2621c4ee12302c9d745f5c5aca988dccf7 100644 (file)
 
 
 /* Commands with service actions that change the command name */
-#define SERVICE_ACTION_IN_12 0xab
-#define SERVICE_ACTION_OUT_12 0xa9
-#define SERVICE_ACTION_BIDIRECTIONAL 0x9d
-#define SERVICE_ACTION_IN_16 0x9e
-#define SERVICE_ACTION_OUT_16 0x9f
 #define THIRD_PARTY_COPY_OUT 0x83
 #define THIRD_PARTY_COPY_IN 0x84
 
+#define VENDOR_SPECIFIC_CDB 0xc0
 
+struct sa_name_list {
+       int opcode;
+       const struct value_name_pair *arr;
+       int arr_sz;
+};
+
+struct value_name_pair {
+       int value;
+       const char * name;
+};
 
 #ifdef CONFIG_SCSI_CONSTANTS
 static const char * cdb_byte0_names[] = {
@@ -102,11 +108,6 @@ static const char * cdb_byte0_names[] = {
             "Volume set (out), Send DVD structure",
 };
 
-struct value_name_pair {
-       int value;
-       const char * name;
-};
-
 static const struct value_name_pair maint_in_arr[] = {
        {0x5, "Report identifying information"},
        {0xa, "Report target port groups"},
@@ -244,170 +245,119 @@ static const struct value_name_pair variable_length_arr[] = {
 };
 #define VARIABLE_LENGTH_SZ ARRAY_SIZE(variable_length_arr)
 
-static const char * get_sa_name(const struct value_name_pair * arr,
-                               int arr_sz, int service_action)
-{
-       int k;
+static struct sa_name_list sa_names_arr[] = {
+       {VARIABLE_LENGTH_CMD, variable_length_arr, VARIABLE_LENGTH_SZ},
+       {MAINTENANCE_IN, maint_in_arr, MAINT_IN_SZ},
+       {MAINTENANCE_OUT, maint_out_arr, MAINT_OUT_SZ},
+       {PERSISTENT_RESERVE_IN, pr_in_arr, PR_IN_SZ},
+       {PERSISTENT_RESERVE_OUT, pr_out_arr, PR_OUT_SZ},
+       {SERVICE_ACTION_IN_12, serv_in12_arr, SERV_IN12_SZ},
+       {SERVICE_ACTION_OUT_12, serv_out12_arr, SERV_OUT12_SZ},
+       {SERVICE_ACTION_BIDIRECTIONAL, serv_bidi_arr, SERV_BIDI_SZ},
+       {SERVICE_ACTION_IN_16, serv_in16_arr, SERV_IN16_SZ},
+       {SERVICE_ACTION_OUT_16, serv_out16_arr, SERV_OUT16_SZ},
+       {THIRD_PARTY_COPY_IN, tpc_in_arr, TPC_IN_SZ},
+       {THIRD_PARTY_COPY_OUT, tpc_out_arr, TPC_OUT_SZ},
+       {0, NULL, 0},
+};
 
-       for (k = 0; k < arr_sz; ++k, ++arr) {
-               if (service_action == arr->value)
-                       break;
-       }
-       return (k < arr_sz) ? arr->name : NULL;
-}
+#else /* ifndef CONFIG_SCSI_CONSTANTS */
+static const char *cdb_byte0_names[0];
+
+static struct sa_name_list sa_names_arr[] = {
+       {VARIABLE_LENGTH_CMD, NULL, 0},
+       {MAINTENANCE_IN, NULL, 0},
+       {MAINTENANCE_OUT, NULL, 0},
+       {PERSISTENT_RESERVE_IN, NULL, 0},
+       {PERSISTENT_RESERVE_OUT, NULL, 0},
+       {SERVICE_ACTION_IN_12, NULL, 0},
+       {SERVICE_ACTION_OUT_12, NULL, 0},
+       {SERVICE_ACTION_BIDIRECTIONAL, NULL, 0},
+       {SERVICE_ACTION_IN_16, NULL, 0},
+       {SERVICE_ACTION_OUT_16, NULL, 0},
+       {THIRD_PARTY_COPY_IN, NULL, 0},
+       {THIRD_PARTY_COPY_OUT, NULL, 0},
+       {0, NULL, 0},
+};
+#endif /* CONFIG_SCSI_CONSTANTS */
 
-/* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */
-static void print_opcode_name(unsigned char * cdbp, int cdb_len)
+static bool scsi_opcode_sa_name(int opcode, int service_action,
+                               const char **cdb_name, const char **sa_name)
 {
-       int sa, len, cdb0;
-       int fin_name = 0;
-       const char * name;
+       struct sa_name_list *sa_name_ptr;
+       const struct value_name_pair *arr = NULL;
+       int arr_sz, k;
 
-       cdb0 = cdbp[0];
-       switch(cdb0) {
-       case VARIABLE_LENGTH_CMD:
-               len = scsi_varlen_cdb_length(cdbp);
-               if (len < 10) {
-                       printk("short variable length command, "
-                              "len=%d ext_len=%d", len, cdb_len);
-                       break;
-               }
-               sa = (cdbp[8] << 8) + cdbp[9];
-               name = get_sa_name(variable_length_arr, VARIABLE_LENGTH_SZ,
-                                  sa);
-               if (name)
-                       printk("%s", name);
-               else
-                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+       *cdb_name = NULL;
+       if (opcode >= VENDOR_SPECIFIC_CDB)
+               return false;
 
-               if ((cdb_len > 0) && (len != cdb_len))
-                       printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
+       if (opcode < ARRAY_SIZE(cdb_byte0_names))
+               *cdb_name = cdb_byte0_names[opcode];
 
-               break;
-       case MAINTENANCE_IN:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(maint_in_arr, MAINT_IN_SZ, sa);
-               fin_name = 1;
-               break;
-       case MAINTENANCE_OUT:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(maint_out_arr, MAINT_OUT_SZ, sa);
-               fin_name = 1;
-               break;
-       case PERSISTENT_RESERVE_IN:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(pr_in_arr, PR_IN_SZ, sa);
-               fin_name = 1;
-               break;
-       case PERSISTENT_RESERVE_OUT:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(pr_out_arr, PR_OUT_SZ, sa);
-               fin_name = 1;
-               break;
-       case SERVICE_ACTION_IN_12:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(serv_in12_arr, SERV_IN12_SZ, sa);
-               fin_name = 1;
-               break;
-       case SERVICE_ACTION_OUT_12:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(serv_out12_arr, SERV_OUT12_SZ, sa);
-               fin_name = 1;
-               break;
-       case SERVICE_ACTION_BIDIRECTIONAL:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(serv_bidi_arr, SERV_BIDI_SZ, sa);
-               fin_name = 1;
-               break;
-       case SERVICE_ACTION_IN_16:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(serv_in16_arr, SERV_IN16_SZ, sa);
-               fin_name = 1;
-               break;
-       case SERVICE_ACTION_OUT_16:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(serv_out16_arr, SERV_OUT16_SZ, sa);
-               fin_name = 1;
-               break;
-       case THIRD_PARTY_COPY_IN:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(tpc_in_arr, TPC_IN_SZ, sa);
-               fin_name = 1;
-               break;
-       case THIRD_PARTY_COPY_OUT:
-               sa = cdbp[1] & 0x1f;
-               name = get_sa_name(tpc_out_arr, TPC_OUT_SZ, sa);
-               fin_name = 1;
-               break;
-       default:
-               if (cdb0 < 0xc0) {
-                       name = cdb_byte0_names[cdb0];
-                       if (name)
-                               printk("%s", name);
-                       else
-                               printk("cdb[0]=0x%x (reserved)", cdb0);
-               } else
-                       printk("cdb[0]=0x%x (vendor)", cdb0);
-               break;
+       for (sa_name_ptr = sa_names_arr; sa_name_ptr->arr; ++sa_name_ptr) {
+               if (sa_name_ptr->opcode == opcode) {
+                       arr = sa_name_ptr->arr;
+                       arr_sz = sa_name_ptr->arr_sz;
+                       break;
+               }
        }
-       if (fin_name) {
-               if (name)
-                       printk("%s", name);
-               else
-                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+       if (!arr)
+               return false;
+
+       for (k = 0; k < arr_sz; ++k, ++arr) {
+               if (service_action == arr->value)
+                       break;
        }
-}
+       if (k < arr_sz)
+               *sa_name = arr->name;
 
-#else /* ifndef CONFIG_SCSI_CONSTANTS */
+       return true;
+}
 
-static void print_opcode_name(unsigned char * cdbp, int cdb_len)
+static void print_opcode_name(const unsigned char *cdbp, size_t cdb_len)
 {
-       int sa, len, cdb0;
+       int sa, cdb0;
+       const char *cdb_name = NULL, *sa_name = NULL;
 
        cdb0 = cdbp[0];
-       switch(cdb0) {
-       case VARIABLE_LENGTH_CMD:
-               len = scsi_varlen_cdb_length(cdbp);
-               if (len < 10) {
-                       printk("short opcode=0x%x command, len=%d "
-                              "ext_len=%d", cdb0, len, cdb_len);
-                       break;
+       if (cdb0 == VARIABLE_LENGTH_CMD) {
+               if (cdb_len < 10) {
+                       printk("short variable length command, len=%zu",
+                              cdb_len);
+                       return;
                }
                sa = (cdbp[8] << 8) + cdbp[9];
-               printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
-               if (len != cdb_len)
-                       printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
-               break;
-       case MAINTENANCE_IN:
-       case MAINTENANCE_OUT:
-       case PERSISTENT_RESERVE_IN:
-       case PERSISTENT_RESERVE_OUT:
-       case SERVICE_ACTION_IN_12:
-       case SERVICE_ACTION_OUT_12:
-       case SERVICE_ACTION_BIDIRECTIONAL:
-       case SERVICE_ACTION_IN_16:
-       case SERVICE_ACTION_OUT_16:
-       case THIRD_PARTY_COPY_IN:
-       case THIRD_PARTY_COPY_OUT:
+       } else
                sa = cdbp[1] & 0x1f;
-               printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
-               break;
-       default:
-               if (cdb0 < 0xc0)
+
+       if (!scsi_opcode_sa_name(cdb0, sa, &cdb_name, &sa_name)) {
+               if (cdb_name)
+                       printk("%s", cdb_name);
+               else if (cdb0 >= VENDOR_SPECIFIC_CDB)
+                       printk("cdb[0]=0x%x (vendor)", cdb0);
+               else if (cdb0 >= 0x60 && cdb0 < 0x7e)
+                       printk("cdb[0]=0x%x (reserved)", cdb0);
+               else
                        printk("cdb[0]=0x%x", cdb0);
+       } else {
+               if (sa_name)
+                       printk("%s", sa_name);
+               else if (cdb_name)
+                       printk("%s, sa=0x%x", cdb_name, sa);
                else
-                       printk("cdb[0]=0x%x (vendor)", cdb0);
-               break;
+                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
        }
 }
-#endif
 
-void __scsi_print_command(unsigned char *cdb)
+void __scsi_print_command(const unsigned char *cdb, size_t cdb_len)
 {
        int k, len;
 
-       print_opcode_name(cdb, 0);
+       print_opcode_name(cdb, cdb_len);
        len = scsi_command_size(cdb);
+       if (cdb_len < len)
+               len = cdb_len;
        /* print out all bytes in cdb */
        for (k = 0; k < len; ++k)
                printk(" %02x", cdb[k]);
@@ -433,41 +383,6 @@ void scsi_print_command(struct scsi_cmnd *cmd)
 }
 EXPORT_SYMBOL(scsi_print_command);
 
-/**
- *     scsi_print_status - print scsi status description
- *     @scsi_status: scsi status value
- *
- *     If the status is recognized, the description is printed.
- *     Otherwise "Unknown status" is output. No trailing space.
- *     If CONFIG_SCSI_CONSTANTS is not set, then print status in hex
- *     (e.g. "0x2" for Check Condition).
- **/
-void
-scsi_print_status(unsigned char scsi_status) {
-#ifdef CONFIG_SCSI_CONSTANTS
-       const char * ccp;
-
-       switch (scsi_status) {
-       case 0:    ccp = "Good"; break;
-       case 0x2:  ccp = "Check Condition"; break;
-       case 0x4:  ccp = "Condition Met"; break;
-       case 0x8:  ccp = "Busy"; break;
-       case 0x10: ccp = "Intermediate"; break;
-       case 0x14: ccp = "Intermediate-Condition Met"; break;
-       case 0x18: ccp = "Reservation Conflict"; break;
-       case 0x22: ccp = "Command Terminated"; break;   /* obsolete */
-       case 0x28: ccp = "Task set Full"; break;        /* was: Queue Full */
-       case 0x30: ccp = "ACA Active"; break;
-       case 0x40: ccp = "Task Aborted"; break;
-       default:   ccp = "Unknown status";
-       }
-       printk(KERN_INFO "%s", ccp);
-#else
-       printk(KERN_INFO "0x%0x", scsi_status);
-#endif
-}
-EXPORT_SYMBOL(scsi_print_status);
-
 #ifdef CONFIG_SCSI_CONSTANTS
 
 struct error_info {
@@ -1292,18 +1207,19 @@ static const struct error_info additional[] =
 
 struct error_info2 {
        unsigned char code1, code2_min, code2_max;
+       const char * str;
        const char * fmt;
 };
 
 static const struct error_info2 additional2[] =
 {
-       {0x40, 0x00, 0x7f, "Ram failure (%x)"},
-       {0x40, 0x80, 0xff, "Diagnostic failure on component (%x)"},
-       {0x41, 0x00, 0xff, "Data path failure (%x)"},
-       {0x42, 0x00, 0xff, "Power-on or self-test failure (%x)"},
-       {0x4D, 0x00, 0xff, "Tagged overlapped commands (task tag %x)"},
-       {0x70, 0x00, 0xff, "Decompression exception short algorithm id of %x"},
-       {0, 0, 0, NULL}
+       {0x40, 0x00, 0x7f, "Ram failure", ""},
+       {0x40, 0x80, 0xff, "Diagnostic failure on component", ""},
+       {0x41, 0x00, 0xff, "Data path failure", ""},
+       {0x42, 0x00, 0xff, "Power-on or self-test failure", ""},
+       {0x4D, 0x00, 0xff, "Tagged overlapped commands", "task tag "},
+       {0x70, 0x00, 0xff, "Decompression exception", "short algorithm id of "},
+       {0, 0, 0, NULL, NULL}
 };
 
 /* description of the sense key values */
@@ -1349,69 +1265,79 @@ EXPORT_SYMBOL(scsi_sense_key_string);
  * This string may contain a "%x" and should be printed with ascq as arg.
  */
 const char *
-scsi_extd_sense_format(unsigned char asc, unsigned char ascq) {
+scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt)
+{
 #ifdef CONFIG_SCSI_CONSTANTS
        int i;
        unsigned short code = ((asc << 8) | ascq);
 
+       *fmt = NULL;
        for (i = 0; additional[i].text; i++)
                if (additional[i].code12 == code)
                        return additional[i].text;
        for (i = 0; additional2[i].fmt; i++) {
                if (additional2[i].code1 == asc &&
                    ascq >= additional2[i].code2_min &&
-                   ascq <= additional2[i].code2_max)
-                       return additional2[i].fmt;
+                   ascq <= additional2[i].code2_max) {
+                       *fmt = additional2[i].fmt;
+                       return additional2[i].str;
+               }
        }
+#else
+       *fmt = NULL;
 #endif
        return NULL;
 }
 EXPORT_SYMBOL(scsi_extd_sense_format);
 
 void
-scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
+scsi_show_extd_sense(const struct scsi_device *sdev, const char *name,
+                    unsigned char asc, unsigned char ascq)
 {
-        const char *extd_sense_fmt = scsi_extd_sense_format(asc, ascq);
-
-       if (extd_sense_fmt) {
-               if (strstr(extd_sense_fmt, "%x")) {
-                       printk("Add. Sense: ");
-                       printk(extd_sense_fmt, ascq);
-               } else
-                       printk("Add. Sense: %s", extd_sense_fmt);
-       } else {
-               if (asc >= 0x80)
-                       printk("<<vendor>> ASC=0x%x ASCQ=0x%x", asc,
-                              ascq);
-               if (ascq >= 0x80)
-                       printk("ASC=0x%x <<vendor>> ASCQ=0x%x", asc,
-                              ascq);
+       const char *extd_sense_fmt = NULL;
+       const char *extd_sense_str = scsi_extd_sense_format(asc, ascq,
+                                                           &extd_sense_fmt);
+
+       if (extd_sense_str) {
+               if (extd_sense_fmt)
+                       sdev_prefix_printk(KERN_INFO, sdev, name,
+                                          "Add. Sense: %s (%s%x)",
+                                          extd_sense_str, extd_sense_fmt,
+                                          ascq);
                else
-                       printk("ASC=0x%x ASCQ=0x%x", asc, ascq);
-       }
+                       sdev_prefix_printk(KERN_INFO, sdev, name,
+                                          "Add. Sense: %s", extd_sense_str);
 
-       printk("\n");
+       } else {
+               sdev_prefix_printk(KERN_INFO, sdev, name,
+                                  "%sASC=0x%x %sASCQ=0x%x\n",
+                                  asc >= 0x80 ? "<<vendor>> " : "", asc,
+                                  ascq >= 0x80 ? "<<vendor>> " : "", ascq);
+       }
 }
 EXPORT_SYMBOL(scsi_show_extd_sense);
 
 void
-scsi_show_sense_hdr(struct scsi_sense_hdr *sshdr)
+scsi_show_sense_hdr(const struct scsi_device *sdev, const char *name,
+                   const struct scsi_sense_hdr *sshdr)
 {
        const char *sense_txt;
 
        sense_txt = scsi_sense_key_string(sshdr->sense_key);
        if (sense_txt)
-               printk("Sense Key : %s ", sense_txt);
+               sdev_prefix_printk(KERN_INFO, sdev, name,
+                                  "Sense Key : %s [%s]%s\n", sense_txt,
+                                  scsi_sense_is_deferred(sshdr) ?
+                                  "deferred" : "current",
+                                  sshdr->response_code >= 0x72 ?
+                                  " [descriptor]" : "");
        else
-               printk("Sense Key : 0x%x ", sshdr->sense_key);
-
-       printk("%s", scsi_sense_is_deferred(sshdr) ? "[deferred] " :
-              "[current] ");
-
-       if (sshdr->response_code >= 0x72)
-               printk("[descriptor]");
-
-       printk("\n");
+               sdev_prefix_printk(KERN_INFO, sdev, name,
+                                  "Sense Key : 0x%x [%s]%s", sshdr->sense_key,
+                                  scsi_sense_is_deferred(sshdr) ?
+                                  "deferred" : "current",
+                                  sshdr->response_code >= 0x72 ?
+                                  " [descriptor]" : "");
 }
 EXPORT_SYMBOL(scsi_show_sense_hdr);
 
@@ -1419,141 +1345,55 @@ EXPORT_SYMBOL(scsi_show_sense_hdr);
  * Print normalized SCSI sense header with a prefix.
  */
 void
-scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr)
+scsi_print_sense_hdr(const struct scsi_device *sdev, const char *name,
+                    const struct scsi_sense_hdr *sshdr)
 {
-       printk(KERN_INFO "%s: ", name);
-       scsi_show_sense_hdr(sshdr);
-       printk(KERN_INFO "%s: ", name);
-       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+       scsi_show_sense_hdr(sdev, name, sshdr);
+       scsi_show_extd_sense(sdev, name, sshdr->asc, sshdr->ascq);
 }
 EXPORT_SYMBOL(scsi_print_sense_hdr);
 
-/*
- * Print normalized SCSI sense header with device information and a prefix.
- */
-void
-scsi_cmd_print_sense_hdr(struct scsi_cmnd *scmd, const char *desc,
-                         struct scsi_sense_hdr *sshdr)
-{
-       scmd_printk(KERN_INFO, scmd, "%s: ", desc);
-       scsi_show_sense_hdr(sshdr);
-       scmd_printk(KERN_INFO, scmd, "%s: ", desc);
-       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
-}
-EXPORT_SYMBOL(scsi_cmd_print_sense_hdr);
-
 static void
-scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len,
-                      struct scsi_sense_hdr *sshdr)
+scsi_dump_sense_buffer(const unsigned char *sense_buffer, int sense_len)
 {
-       int k, num, res;
-
-       res = scsi_normalize_sense(sense_buffer, sense_len, sshdr);
-       if (0 == res) {
-               /* this may be SCSI-1 sense data */
-               num = (sense_len < 32) ? sense_len : 32;
-               printk("Unrecognized sense data (in hex):");
-               for (k = 0; k < num; ++k) {
-                       if (0 == (k % 16)) {
-                               printk("\n");
-                               printk(KERN_INFO "        ");
-                       }
-                       printk("%02x ", sense_buffer[k]);
+       int k, num;
+
+       num = (sense_len < 32) ? sense_len : 32;
+       printk("Unrecognized sense data (in hex):");
+       for (k = 0; k < num; ++k) {
+               if (0 == (k % 16)) {
+                       printk("\n");
+                       printk(KERN_INFO "        ");
                }
-               printk("\n");
-               return;
+               printk("%02x ", sense_buffer[k]);
        }
-}
-
-static void
-scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len,
-                        struct scsi_sense_hdr *sshdr)
-{
-       int k, num, res;
-
-       if (sshdr->response_code < 0x72)
-       {
-               /* only decode extras for "fixed" format now */
-               char buff[80];
-               int blen, fixed_valid;
-               unsigned int info;
-
-               fixed_valid = sense_buffer[0] & 0x80;
-               info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) |
-                       (sense_buffer[5] << 8) | sense_buffer[6]);
-               res = 0;
-               memset(buff, 0, sizeof(buff));
-               blen = sizeof(buff) - 1;
-               if (fixed_valid)
-                       res += snprintf(buff + res, blen - res,
-                                       "Info fld=0x%x", info);
-               if (sense_buffer[2] & 0x80) {
-                       /* current command has read a filemark */
-                       if (res > 0)
-                               res += snprintf(buff + res, blen - res, ", ");
-                       res += snprintf(buff + res, blen - res, "FMK");
-               }
-               if (sense_buffer[2] & 0x40) {
-                       /* end-of-medium condition exists */
-                       if (res > 0)
-                               res += snprintf(buff + res, blen - res, ", ");
-                       res += snprintf(buff + res, blen - res, "EOM");
-               }
-               if (sense_buffer[2] & 0x20) {
-                       /* incorrect block length requested */
-                       if (res > 0)
-                               res += snprintf(buff + res, blen - res, ", ");
-                       res += snprintf(buff + res, blen - res, "ILI");
-               }
-               if (res > 0)
-                       printk("%s\n", buff);
-       } else if (sshdr->additional_length > 0) {
-               /* descriptor format with sense descriptors */
-               num = 8 + sshdr->additional_length;
-               num = (sense_len < num) ? sense_len : num;
-               printk("Descriptor sense data with sense descriptors "
-                      "(in hex):");
-               for (k = 0; k < num; ++k) {
-                       if (0 == (k % 16)) {
-                               printk("\n");
-                               printk(KERN_INFO "        ");
-                       }
-                       printk("%02x ", sense_buffer[k]);
-               }
-
-               printk("\n");
-       }
-
+       printk("\n");
+       return;
 }
 
 /* Normalize and print sense buffer with name prefix */
-void __scsi_print_sense(const char *name, const unsigned char *sense_buffer,
-                       int sense_len)
+void __scsi_print_sense(const struct scsi_device *sdev, const char *name,
+                       const unsigned char *sense_buffer, int sense_len)
 {
        struct scsi_sense_hdr sshdr;
 
-       printk(KERN_INFO "%s: ", name);
-       scsi_decode_sense_buffer(sense_buffer, sense_len, &sshdr);
-       scsi_show_sense_hdr(&sshdr);
-       scsi_decode_sense_extras(sense_buffer, sense_len, &sshdr);
-       printk(KERN_INFO "%s: ", name);
-       scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
+       if (!scsi_normalize_sense(sense_buffer, sense_len, &sshdr)) {
+               scsi_dump_sense_buffer(sense_buffer, sense_len);
+               return;
+       }
+       scsi_show_sense_hdr(sdev, name, &sshdr);
+       scsi_show_extd_sense(sdev, name, sshdr.asc, sshdr.ascq);
 }
 EXPORT_SYMBOL(__scsi_print_sense);
 
 /* Normalize and print sense buffer in SCSI command */
-void scsi_print_sense(char *name, struct scsi_cmnd *cmd)
+void scsi_print_sense(const struct scsi_cmnd *cmd)
 {
-       struct scsi_sense_hdr sshdr;
+       struct gendisk *disk = cmd->request->rq_disk;
+       const char *disk_name = disk ? disk->disk_name : NULL;
 
-       scmd_printk(KERN_INFO, cmd, " ");
-       scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
-                                &sshdr);
-       scsi_show_sense_hdr(&sshdr);
-       scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
-                                &sshdr);
-       scmd_printk(KERN_INFO, cmd, " ");
-       scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
+       __scsi_print_sense(cmd->device, disk_name, cmd->sense_buffer,
+                          SCSI_SENSE_BUFFERSIZE);
 }
 EXPORT_SYMBOL(scsi_print_sense);
 
@@ -1565,38 +1405,87 @@ static const char * const hostbyte_table[]={
 "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE",
 "DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE",
 "DID_NEXUS_FAILURE" };
-#define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
 
 static const char * const driverbyte_table[]={
 "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR",
 "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
-#define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table)
 
-void scsi_show_result(int result)
+#endif
+
+const char *scsi_hostbyte_string(int result)
 {
+       const char *hb_string = NULL;
+#ifdef CONFIG_SCSI_CONSTANTS
        int hb = host_byte(result);
-       int db = driver_byte(result);
 
-       printk("Result: hostbyte=%s driverbyte=%s\n",
-              (hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb]     : "invalid"),
-              (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"));
+       if (hb < ARRAY_SIZE(hostbyte_table))
+               hb_string = hostbyte_table[hb];
+#endif
+       return hb_string;
 }
+EXPORT_SYMBOL(scsi_hostbyte_string);
 
-#else
-
-void scsi_show_result(int result)
+const char *scsi_driverbyte_string(int result)
 {
-       printk("Result: hostbyte=0x%02x driverbyte=0x%02x\n",
-              host_byte(result), driver_byte(result));
+       const char *db_string = NULL;
+#ifdef CONFIG_SCSI_CONSTANTS
+       int db = driver_byte(result);
+
+       if (db < ARRAY_SIZE(driverbyte_table))
+               db_string = driverbyte_table[db];
+#endif
+       return db_string;
 }
+EXPORT_SYMBOL(scsi_driverbyte_string);
 
+#ifdef CONFIG_SCSI_CONSTANTS
+#define scsi_mlreturn_name(result)     { result, #result }
+static const struct value_name_pair scsi_mlreturn_arr[] = {
+       scsi_mlreturn_name(NEEDS_RETRY),
+       scsi_mlreturn_name(SUCCESS),
+       scsi_mlreturn_name(FAILED),
+       scsi_mlreturn_name(QUEUED),
+       scsi_mlreturn_name(SOFT_ERROR),
+       scsi_mlreturn_name(ADD_TO_MLQUEUE),
+       scsi_mlreturn_name(TIMEOUT_ERROR),
+       scsi_mlreturn_name(SCSI_RETURN_NOT_HANDLED),
+       scsi_mlreturn_name(FAST_IO_FAIL)
+};
 #endif
-EXPORT_SYMBOL(scsi_show_result);
 
+const char *scsi_mlreturn_string(int result)
+{
+#ifdef CONFIG_SCSI_CONSTANTS
+       const struct value_name_pair *arr = scsi_mlreturn_arr;
+       int k;
 
-void scsi_print_result(struct scsi_cmnd *cmd)
+       for (k = 0; k < ARRAY_SIZE(scsi_mlreturn_arr); ++k, ++arr) {
+               if (result == arr->value)
+                       return arr->name;
+       }
+#endif
+       return NULL;
+}
+EXPORT_SYMBOL(scsi_mlreturn_string);
+
+void scsi_print_result(struct scsi_cmnd *cmd, const char *msg, int disposition)
 {
-       scmd_printk(KERN_INFO, cmd, " ");
-       scsi_show_result(cmd->result);
+       const char *mlret_string = scsi_mlreturn_string(disposition);
+       const char *hb_string = scsi_hostbyte_string(cmd->result);
+       const char *db_string = scsi_driverbyte_string(cmd->result);
+
+       if (hb_string || db_string)
+               scmd_printk(KERN_INFO, cmd,
+                           "%s%s Result: hostbyte=%s driverbyte=%s",
+                           msg ? msg : "",
+                           mlret_string ? mlret_string : "UNKNOWN",
+                           hb_string ? hb_string : "invalid",
+                           db_string ? db_string : "invalid");
+       else
+               scmd_printk(KERN_INFO, cmd,
+                           "%s%s Result: hostbyte=0x%02x driverbyte=0x%02x",
+                           msg ? msg : "",
+                           mlret_string ? mlret_string : "UNKNOWN",
+                           host_byte(cmd->result), driver_byte(cmd->result));
 }
 EXPORT_SYMBOL(scsi_print_result);
index 86103c8475d8ed649b456b4e9f83b954a3b04e31..4d0b6ce55f20ee8190bd2b7126d643471710e8fa 100644 (file)
@@ -152,28 +152,6 @@ csio_scsi_itnexus_loss_error(uint16_t error)
        return 0;
 }
 
-static inline void
-csio_scsi_tag(struct scsi_cmnd *scmnd, uint8_t *tag, uint8_t hq,
-             uint8_t oq, uint8_t sq)
-{
-       char stag[2];
-
-       if (scsi_populate_tag_msg(scmnd, stag)) {
-               switch (stag[0]) {
-               case HEAD_OF_QUEUE_TAG:
-                       *tag = hq;
-                       break;
-               case ORDERED_QUEUE_TAG:
-                       *tag = oq;
-                       break;
-               default:
-                       *tag = sq;
-                       break;
-               }
-       } else
-               *tag = 0;
-}
-
 /*
  * csio_scsi_fcp_cmnd - Frame the SCSI FCP command paylod.
  * @req: IO req structure.
@@ -192,11 +170,12 @@ csio_scsi_fcp_cmnd(struct csio_ioreq *req, void *addr)
                int_to_scsilun(scmnd->device->lun, &fcp_cmnd->fc_lun);
                fcp_cmnd->fc_tm_flags = 0;
                fcp_cmnd->fc_cmdref = 0;
-               fcp_cmnd->fc_pri_ta = 0;
 
                memcpy(fcp_cmnd->fc_cdb, scmnd->cmnd, 16);
-               csio_scsi_tag(scmnd, &fcp_cmnd->fc_pri_ta,
-                             FCP_PTA_HEADQ, FCP_PTA_ORDERED, FCP_PTA_SIMPLE);
+               if (scmnd->flags & SCMD_TAGGED)
+                       fcp_cmnd->fc_pri_ta = FCP_PTA_SIMPLE;
+               else
+                       fcp_cmnd->fc_pri_ta = 0;
                fcp_cmnd->fc_dl = cpu_to_be32(scsi_bufflen(scmnd));
 
                if (req->nsge)
@@ -2262,11 +2241,7 @@ csio_slave_alloc(struct scsi_device *sdev)
 static int
 csio_slave_configure(struct scsi_device *sdev)
 {
-       if (sdev->tagged_supported)
-               scsi_activate_tcq(sdev, csio_lun_qdepth);
-       else
-               scsi_deactivate_tcq(sdev, csio_lun_qdepth);
-
+       scsi_change_queue_depth(sdev, csio_lun_qdepth);
        return 0;
 }
 
@@ -2311,6 +2286,7 @@ struct scsi_host_template csio_fcoe_shost_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = csio_fcoe_lport_attrs,
        .max_sectors            = CSIO_MAX_SECTOR_SIZE,
+       .use_blk_tags           = 1,
 };
 
 struct scsi_host_template csio_fcoe_shost_vport_template = {
@@ -2330,6 +2306,7 @@ struct scsi_host_template csio_fcoe_shost_vport_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = csio_fcoe_vport_attrs,
        .max_sectors            = CSIO_MAX_SECTOR_SIZE,
+       .use_blk_tags           = 1,
 };
 
 /*
index 49692a1ac44a59cc6a46d6a75bd2a25eca2b355c..3db4c63978c55c1e7e623d199b6c623c6cea3597 100644 (file)
@@ -86,7 +86,7 @@ static struct scsi_host_template cxgb3i_host_template = {
        .proc_name      = DRV_MODULE_NAME,
        .can_queue      = CXGB3I_SCSI_HOST_QDEPTH,
        .queuecommand   = iscsi_queuecommand,
-       .change_queue_depth = iscsi_change_queue_depth,
+       .change_queue_depth = scsi_change_queue_depth,
        .sg_tablesize   = SG_ALL,
        .max_sectors    = 0xFFFF,
        .cmd_per_lun    = ISCSI_DEF_CMD_PER_LUN,
@@ -96,6 +96,7 @@ static struct scsi_host_template cxgb3i_host_template = {
        .target_alloc   = iscsi_target_alloc,
        .use_clustering = DISABLE_CLUSTERING,
        .this_id        = -1,
+       .track_queue_depth = 1,
 };
 
 static struct iscsi_transport cxgb3i_iscsi_transport = {
index 3e0a0d315f72acc6b7088ded6d27465ff14b2840..e6c3f55d9d36f989381d93772065da2c27663813 100644 (file)
@@ -89,7 +89,7 @@ static struct scsi_host_template cxgb4i_host_template = {
        .proc_name      = DRV_MODULE_NAME,
        .can_queue      = CXGB4I_SCSI_HOST_QDEPTH,
        .queuecommand   = iscsi_queuecommand,
-       .change_queue_depth = iscsi_change_queue_depth,
+       .change_queue_depth = scsi_change_queue_depth,
        .sg_tablesize   = SG_ALL,
        .max_sectors    = 0xFFFF,
        .cmd_per_lun    = ISCSI_DEF_CMD_PER_LUN,
@@ -99,6 +99,7 @@ static struct scsi_host_template cxgb4i_host_template = {
        .target_alloc   = iscsi_target_alloc,
        .use_clustering = DISABLE_CLUSTERING,
        .this_id        = -1,
+       .track_queue_depth = 1,
 };
 
 static struct iscsi_transport cxgb4i_iscsi_transport = {
@@ -828,6 +829,8 @@ static void do_act_open_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
        if (status == CPL_ERR_RTX_NEG_ADVICE)
                goto rel_skb;
 
+       module_put(THIS_MODULE);
+
        if (status && status != CPL_ERR_TCAM_FULL &&
            status != CPL_ERR_CONN_EXIST &&
            status != CPL_ERR_ARP_MISS)
@@ -936,20 +939,23 @@ static void do_abort_req_rss(struct cxgbi_device *cdev, struct sk_buff *skb)
        cxgbi_sock_get(csk);
        spin_lock_bh(&csk->lock);
 
-       if (!cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD)) {
-               cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
-               cxgbi_sock_set_state(csk, CTP_ABORTING);
-               goto done;
+       cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+
+       if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) {
+               send_tx_flowc_wr(csk);
+               cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
        }
 
-       cxgbi_sock_clear_flag(csk, CTPF_ABORT_REQ_RCVD);
+       cxgbi_sock_set_flag(csk, CTPF_ABORT_REQ_RCVD);
+       cxgbi_sock_set_state(csk, CTP_ABORTING);
+
        send_abort_rpl(csk, rst_status);
 
        if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
                csk->err = abort_status_to_errno(csk, req->status, &rst_status);
                cxgbi_sock_closed(csk);
        }
-done:
+
        spin_unlock_bh(&csk->lock);
        cxgbi_sock_put(csk);
 rel_skb:
index 54fa6e0bc1bbb595e3683cc77b56ae084bfff908..7da59c38a69ec97cf15507876122151222e52fe1 100644 (file)
@@ -399,6 +399,35 @@ EXPORT_SYMBOL_GPL(cxgbi_hbas_add);
  *   If the source port is outside our allocation range, the caller is
  *   responsible for keeping track of their port usage.
  */
+
+static struct cxgbi_sock *find_sock_on_port(struct cxgbi_device *cdev,
+                                           unsigned char port_id)
+{
+       struct cxgbi_ports_map *pmap = &cdev->pmap;
+       unsigned int i;
+       unsigned int used;
+
+       if (!pmap->max_connect || !pmap->used)
+               return NULL;
+
+       spin_lock_bh(&pmap->lock);
+       used = pmap->used;
+       for (i = 0; used && i < pmap->max_connect; i++) {
+               struct cxgbi_sock *csk = pmap->port_csk[i];
+
+               if (csk) {
+                       if (csk->port_id == port_id) {
+                               spin_unlock_bh(&pmap->lock);
+                               return csk;
+                       }
+                       used--;
+               }
+       }
+       spin_unlock_bh(&pmap->lock);
+
+       return NULL;
+}
+
 static int sock_get_port(struct cxgbi_sock *csk)
 {
        struct cxgbi_device *cdev = csk->cdev;
@@ -749,6 +778,7 @@ static struct cxgbi_sock *cxgbi_check_route6(struct sockaddr *dst_addr)
        csk->daddr6.sin6_addr = daddr6->sin6_addr;
        csk->daddr6.sin6_port = daddr6->sin6_port;
        csk->daddr6.sin6_family = daddr6->sin6_family;
+       csk->saddr6.sin6_family = daddr6->sin6_family;
        csk->saddr6.sin6_addr = pref_saddr;
 
        neigh_release(n);
@@ -786,7 +816,7 @@ static void cxgbi_inform_iscsi_conn_closing(struct cxgbi_sock *csk)
                read_lock_bh(&csk->callback_lock);
                if (csk->user_data)
                        iscsi_conn_failure(csk->user_data,
-                                       ISCSI_ERR_CONN_FAILED);
+                                       ISCSI_ERR_TCP_CONN_CLOSE);
                read_unlock_bh(&csk->callback_lock);
        }
 }
@@ -875,18 +905,16 @@ void cxgbi_sock_rcv_abort_rpl(struct cxgbi_sock *csk)
 {
        cxgbi_sock_get(csk);
        spin_lock_bh(&csk->lock);
+
+       cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_RCVD);
        if (cxgbi_sock_flag(csk, CTPF_ABORT_RPL_PENDING)) {
-               if (!cxgbi_sock_flag(csk, CTPF_ABORT_RPL_RCVD))
-                       cxgbi_sock_set_flag(csk, CTPF_ABORT_RPL_RCVD);
-               else {
-                       cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_RCVD);
-                       cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_PENDING);
-                       if (cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD))
-                               pr_err("csk 0x%p,%u,0x%lx,%u,ABT_RPL_RSS.\n",
-                                       csk, csk->state, csk->flags, csk->tid);
-                       cxgbi_sock_closed(csk);
-               }
+               cxgbi_sock_clear_flag(csk, CTPF_ABORT_RPL_PENDING);
+               if (cxgbi_sock_flag(csk, CTPF_ABORT_REQ_RCVD))
+                       pr_err("csk 0x%p,%u,0x%lx,%u,ABT_RPL_RSS.\n",
+                              csk, csk->state, csk->flags, csk->tid);
+               cxgbi_sock_closed(csk);
        }
+
        spin_unlock_bh(&csk->lock);
        cxgbi_sock_put(csk);
 }
@@ -2647,12 +2675,14 @@ int cxgbi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param,
                break;
        case ISCSI_HOST_PARAM_IPADDRESS:
        {
-               __be32 addr;
-
-               addr = cxgbi_get_iscsi_ipv4(chba);
-               len = sprintf(buf, "%pI4", &addr);
+               struct cxgbi_sock *csk = find_sock_on_port(chba->cdev,
+                                                          chba->port_id);
+               if (csk) {
+                       len = sprintf(buf, "%pIS",
+                                     (struct sockaddr *)&csk->saddr);
+               }
                log_debug(1 << CXGBI_DBG_ISCSI,
-                       "hba %s, ipv4 %pI4.\n", chba->ndev->name, &addr);
+                         "hba %s, addr %s.\n", chba->ndev->name, buf);
                break;
        }
        default:
index 1d98fad6a0ab7198ae81ef0e8f5765fabc72f0b9..2c7cb1c0c453d307418afc2eb4d73bb103c6c1f0 100644 (file)
@@ -700,11 +700,6 @@ static inline void cxgbi_set_iscsi_ipv4(struct cxgbi_hba *chba, __be32 ipaddr)
                        chba->ndev->name);
 }
 
-static inline __be32 cxgbi_get_iscsi_ipv4(struct cxgbi_hba *chba)
-{
-       return chba->ipv4addr;
-}
-
 struct cxgbi_device *cxgbi_device_register(unsigned int, unsigned int);
 void cxgbi_device_unregister(struct cxgbi_device *);
 void cxgbi_device_unregister_all(unsigned int flag);
index 33e422e7583500001acc1fbe272c950ede8aff92..1dba62c5cf6a0b364df79805f5e8ee857ba36b46 100644 (file)
@@ -98,27 +98,51 @@ device_handler_match(struct scsi_device_handler *scsi_dh,
 static int scsi_dh_handler_attach(struct scsi_device *sdev,
                                  struct scsi_device_handler *scsi_dh)
 {
-       int err = 0;
+       struct scsi_dh_data *d;
 
        if (sdev->scsi_dh_data) {
                if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
-                       err = -EBUSY;
-               else
-                       kref_get(&sdev->scsi_dh_data->kref);
-       } else if (scsi_dh->attach) {
-               err = scsi_dh->attach(sdev);
-               if (!err) {
-                       kref_init(&sdev->scsi_dh_data->kref);
-                       sdev->scsi_dh_data->sdev = sdev;
-               }
+                       return -EBUSY;
+
+               kref_get(&sdev->scsi_dh_data->kref);
+               return 0;
        }
-       return err;
+
+       if (!try_module_get(scsi_dh->module))
+               return -EINVAL;
+
+       d = scsi_dh->attach(sdev);
+       if (IS_ERR(d)) {
+               sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%ld)\n",
+                           scsi_dh->name, PTR_ERR(d));
+               module_put(scsi_dh->module);
+               return PTR_ERR(d);
+       }
+
+       d->scsi_dh = scsi_dh;
+       kref_init(&d->kref);
+       d->sdev = sdev;
+
+       spin_lock_irq(sdev->request_queue->queue_lock);
+       sdev->scsi_dh_data = d;
+       spin_unlock_irq(sdev->request_queue->queue_lock);
+       return 0;
 }
 
 static void __detach_handler (struct kref *kref)
 {
-       struct scsi_dh_data *scsi_dh_data = container_of(kref, struct scsi_dh_data, kref);
-       scsi_dh_data->scsi_dh->detach(scsi_dh_data->sdev);
+       struct scsi_dh_data *scsi_dh_data =
+               container_of(kref, struct scsi_dh_data, kref);
+       struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh;
+       struct scsi_device *sdev = scsi_dh_data->sdev;
+
+       spin_lock_irq(sdev->request_queue->queue_lock);
+       sdev->scsi_dh_data = NULL;
+       spin_unlock_irq(sdev->request_queue->queue_lock);
+
+       scsi_dh->detach(sdev);
+       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name);
+       module_put(scsi_dh->module);
 }
 
 /*
@@ -141,7 +165,7 @@ static void scsi_dh_handler_detach(struct scsi_device *sdev,
        if (!scsi_dh)
                scsi_dh = sdev->scsi_dh_data->scsi_dh;
 
-       if (scsi_dh && scsi_dh->detach)
+       if (scsi_dh)
                kref_put(&sdev->scsi_dh_data->kref, __detach_handler);
 }
 
@@ -330,6 +354,9 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
        if (get_device_handler(scsi_dh->name))
                return -EBUSY;
 
+       if (!scsi_dh->attach || !scsi_dh->detach)
+               return -EINVAL;
+
        spin_lock(&list_lock);
        list_add(&scsi_dh->list, &scsi_dh_list);
        spin_unlock(&list_lock);
index e99507ed0e3c9ab5ad36cf19f26814d61a78ec76..854b568b993157938b7a02d28ab40af072508268 100644 (file)
@@ -62,6 +62,7 @@
 #define ALUA_OPTIMIZE_STPG             1
 
 struct alua_dh_data {
+       struct scsi_dh_data     dh_data;
        int                     group_id;
        int                     rel_port;
        int                     tpgs;
@@ -87,9 +88,7 @@ static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
 
 static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
-       BUG_ON(scsi_dh_data == NULL);
-       return ((struct alua_dh_data *) scsi_dh_data->buf);
+       return container_of(sdev->scsi_dh_data, struct alua_dh_data, dh_data);
 }
 
 static int realloc_buffer(struct alua_dh_data *h, unsigned len)
@@ -474,6 +473,13 @@ static int alua_check_sense(struct scsi_device *sdev,
                         * LUN Not Ready -- Offline
                         */
                        return SUCCESS;
+               if (sdev->allow_restart &&
+                   sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x02)
+                       /*
+                        * if the device is not started, we need to wake
+                        * the error handler to start the motor
+                        */
+                       return FAILED;
                break;
        case UNIT_ATTENTION:
                if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
@@ -818,42 +824,18 @@ static bool alua_match(struct scsi_device *sdev)
        return (scsi_device_tpgs(sdev) != 0);
 }
 
-static int alua_bus_attach(struct scsi_device *sdev);
-static void alua_bus_detach(struct scsi_device *sdev);
-
-static struct scsi_device_handler alua_dh = {
-       .name = ALUA_DH_NAME,
-       .module = THIS_MODULE,
-       .attach = alua_bus_attach,
-       .detach = alua_bus_detach,
-       .prep_fn = alua_prep_fn,
-       .check_sense = alua_check_sense,
-       .activate = alua_activate,
-       .set_params = alua_set_params,
-       .match = alua_match,
-};
-
 /*
  * alua_bus_attach - Attach device handler
  * @sdev: device to be attached to
  */
-static int alua_bus_attach(struct scsi_device *sdev)
+static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data;
        struct alua_dh_data *h;
-       unsigned long flags;
-       int err = SCSI_DH_OK;
-
-       scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
-                              + sizeof(*h) , GFP_KERNEL);
-       if (!scsi_dh_data) {
-               sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
-                           ALUA_DH_NAME);
-               return -ENOMEM;
-       }
+       int err;
 
-       scsi_dh_data->scsi_dh = &alua_dh;
-       h = (struct alua_dh_data *) scsi_dh_data->buf;
+       h = kzalloc(sizeof(*h) , GFP_KERNEL);
+       if (!h)
+               return ERR_PTR(-ENOMEM);
        h->tpgs = TPGS_MODE_UNINITIALIZED;
        h->state = TPGS_STATE_OPTIMIZED;
        h->group_id = -1;
@@ -863,23 +845,14 @@ static int alua_bus_attach(struct scsi_device *sdev)
        h->sdev = sdev;
 
        err = alua_initialize(sdev, h);
-       if ((err != SCSI_DH_OK) && (err != SCSI_DH_DEV_OFFLINED))
+       if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED)
                goto failed;
 
-       if (!try_module_get(THIS_MODULE))
-               goto failed;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       sdev->scsi_dh_data = scsi_dh_data;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
        sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME);
-
-       return 0;
-
+       return &h->dh_data;
 failed:
-       kfree(scsi_dh_data);
-       sdev_printk(KERN_ERR, sdev, "%s: not attached\n", ALUA_DH_NAME);
-       return -EINVAL;
+       kfree(h);
+       return ERR_PTR(-EINVAL);
 }
 
 /*
@@ -888,23 +861,25 @@ failed:
  */
 static void alua_bus_detach(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data;
-       struct alua_dh_data *h;
-       unsigned long flags;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       scsi_dh_data = sdev->scsi_dh_data;
-       sdev->scsi_dh_data = NULL;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+       struct alua_dh_data *h = get_alua_data(sdev);
 
-       h = (struct alua_dh_data *) scsi_dh_data->buf;
        if (h->buff && h->inq != h->buff)
                kfree(h->buff);
-       kfree(scsi_dh_data);
-       module_put(THIS_MODULE);
-       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", ALUA_DH_NAME);
+       kfree(h);
 }
 
+static struct scsi_device_handler alua_dh = {
+       .name = ALUA_DH_NAME,
+       .module = THIS_MODULE,
+       .attach = alua_bus_attach,
+       .detach = alua_bus_detach,
+       .prep_fn = alua_prep_fn,
+       .check_sense = alua_check_sense,
+       .activate = alua_activate,
+       .set_params = alua_set_params,
+       .match = alua_match,
+};
+
 static int __init alua_init(void)
 {
        int r;
index 84765384c47ca4486caf3a7e4366521af193be3f..6ed1caadbc6abacf2a26ab82cf745f69876fba11 100644 (file)
@@ -72,6 +72,7 @@ static const char * lun_state[] =
 };
 
 struct clariion_dh_data {
+       struct scsi_dh_data dh_data;
        /*
         * Flags:
         *  CLARIION_SHORT_TRESPASS
@@ -116,9 +117,8 @@ struct clariion_dh_data {
 static inline struct clariion_dh_data
                        *get_clariion_data(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
-       BUG_ON(scsi_dh_data == NULL);
-       return ((struct clariion_dh_data *) scsi_dh_data->buf);
+       return container_of(sdev->scsi_dh_data, struct clariion_dh_data,
+                       dh_data);
 }
 
 /*
@@ -622,7 +622,10 @@ done:
        return result;
 }
 
-static const struct scsi_dh_devlist clariion_dev_list[] = {
+static const struct {
+       char *vendor;
+       char *model;
+} clariion_dev_list[] = {
        {"DGC", "RAID"},
        {"DGC", "DISK"},
        {"DGC", "VRAID"},
@@ -647,39 +650,14 @@ static bool clariion_match(struct scsi_device *sdev)
        return false;
 }
 
-static int clariion_bus_attach(struct scsi_device *sdev);
-static void clariion_bus_detach(struct scsi_device *sdev);
-
-static struct scsi_device_handler clariion_dh = {
-       .name           = CLARIION_NAME,
-       .module         = THIS_MODULE,
-       .devlist        = clariion_dev_list,
-       .attach         = clariion_bus_attach,
-       .detach         = clariion_bus_detach,
-       .check_sense    = clariion_check_sense,
-       .activate       = clariion_activate,
-       .prep_fn        = clariion_prep_fn,
-       .set_params     = clariion_set_params,
-       .match          = clariion_match,
-};
-
-static int clariion_bus_attach(struct scsi_device *sdev)
+static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data;
        struct clariion_dh_data *h;
-       unsigned long flags;
        int err;
 
-       scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
-                              + sizeof(*h) , GFP_KERNEL);
-       if (!scsi_dh_data) {
-               sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
-                           CLARIION_NAME);
-               return -ENOMEM;
-       }
-
-       scsi_dh_data->scsi_dh = &clariion_dh;
-       h = (struct clariion_dh_data *) scsi_dh_data->buf;
+       h = kzalloc(sizeof(*h) , GFP_KERNEL);
+       if (!h)
+               return ERR_PTR(-ENOMEM);
        h->lun_state = CLARIION_LUN_UNINITIALIZED;
        h->default_sp = CLARIION_UNBOUND_LU;
        h->current_sp = CLARIION_UNBOUND_LU;
@@ -692,45 +670,37 @@ static int clariion_bus_attach(struct scsi_device *sdev)
        if (err != SCSI_DH_OK)
                goto failed;
 
-       if (!try_module_get(THIS_MODULE))
-               goto failed;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       sdev->scsi_dh_data = scsi_dh_data;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-
        sdev_printk(KERN_INFO, sdev,
                    "%s: connected to SP %c Port %d (%s, default SP %c)\n",
                    CLARIION_NAME, h->current_sp + 'A',
                    h->port, lun_state[h->lun_state],
                    h->default_sp + 'A');
-
-       return 0;
+       return &h->dh_data;
 
 failed:
-       kfree(scsi_dh_data);
-       sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
-                   CLARIION_NAME);
-       return -EINVAL;
+       kfree(h);
+       return ERR_PTR(-EINVAL);
 }
 
 static void clariion_bus_detach(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data;
-       unsigned long flags;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       scsi_dh_data = sdev->scsi_dh_data;
-       sdev->scsi_dh_data = NULL;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-
-       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n",
-                   CLARIION_NAME);
+       struct clariion_dh_data *h = get_clariion_data(sdev);
 
-       kfree(scsi_dh_data);
-       module_put(THIS_MODULE);
+       kfree(h);
 }
 
+static struct scsi_device_handler clariion_dh = {
+       .name           = CLARIION_NAME,
+       .module         = THIS_MODULE,
+       .attach         = clariion_bus_attach,
+       .detach         = clariion_bus_detach,
+       .check_sense    = clariion_check_sense,
+       .activate       = clariion_activate,
+       .prep_fn        = clariion_prep_fn,
+       .set_params     = clariion_set_params,
+       .match          = clariion_match,
+};
+
 static int __init clariion_init(void)
 {
        int r;
index 4ee2759f5299a531b62ff15e24eb89079bffb7e7..485d99544a1566f099f3c2c3a472134b986a9c5d 100644 (file)
@@ -38,6 +38,7 @@
 #define HP_SW_PATH_PASSIVE             1
 
 struct hp_sw_dh_data {
+       struct scsi_dh_data dh_data;
        unsigned char sense[SCSI_SENSE_BUFFERSIZE];
        int path_state;
        int retries;
@@ -51,9 +52,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *);
 
 static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
-       BUG_ON(scsi_dh_data == NULL);
-       return ((struct hp_sw_dh_data *) scsi_dh_data->buf);
+       return container_of(sdev->scsi_dh_data, struct hp_sw_dh_data, dh_data);
 }
 
 /*
@@ -312,7 +311,10 @@ static int hp_sw_activate(struct scsi_device *sdev,
        return 0;
 }
 
-static const struct scsi_dh_devlist hp_sw_dh_data_list[] = {
+static const struct {
+       char *vendor;
+       char *model;
+} hp_sw_dh_data_list[] = {
        {"COMPAQ", "MSA1000 VOLUME"},
        {"COMPAQ", "HSV110"},
        {"HP", "HSV100"},
@@ -338,37 +340,14 @@ static bool hp_sw_match(struct scsi_device *sdev)
        return false;
 }
 
-static int hp_sw_bus_attach(struct scsi_device *sdev);
-static void hp_sw_bus_detach(struct scsi_device *sdev);
-
-static struct scsi_device_handler hp_sw_dh = {
-       .name           = HP_SW_NAME,
-       .module         = THIS_MODULE,
-       .devlist        = hp_sw_dh_data_list,
-       .attach         = hp_sw_bus_attach,
-       .detach         = hp_sw_bus_detach,
-       .activate       = hp_sw_activate,
-       .prep_fn        = hp_sw_prep_fn,
-       .match          = hp_sw_match,
-};
-
-static int hp_sw_bus_attach(struct scsi_device *sdev)
+static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data;
        struct hp_sw_dh_data *h;
-       unsigned long flags;
        int ret;
 
-       scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
-                              + sizeof(*h) , GFP_KERNEL);
-       if (!scsi_dh_data) {
-               sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n",
-                           HP_SW_NAME);
-               return 0;
-       }
-
-       scsi_dh_data->scsi_dh = &hp_sw_dh;
-       h = (struct hp_sw_dh_data *) scsi_dh_data->buf;
+       h = kzalloc(sizeof(*h), GFP_KERNEL);
+       if (!h)
+               return ERR_PTR(-ENOMEM);
        h->path_state = HP_SW_PATH_UNINITIALIZED;
        h->retries = HP_SW_RETRIES;
        h->sdev = sdev;
@@ -377,42 +356,32 @@ static int hp_sw_bus_attach(struct scsi_device *sdev)
        if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED)
                goto failed;
 
-       if (!try_module_get(THIS_MODULE))
-               goto failed;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       sdev->scsi_dh_data = scsi_dh_data;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-
        sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n",
                    HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE?
                    "active":"passive");
-
-       return 0;
-
+       return &h->dh_data;
 failed:
-       kfree(scsi_dh_data);
-       sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
-                   HP_SW_NAME);
-       return -EINVAL;
+       kfree(h);
+       return ERR_PTR(-EINVAL);
 }
 
 static void hp_sw_bus_detach( struct scsi_device *sdev )
 {
-       struct scsi_dh_data *scsi_dh_data;
-       unsigned long flags;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       scsi_dh_data = sdev->scsi_dh_data;
-       sdev->scsi_dh_data = NULL;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-       module_put(THIS_MODULE);
-
-       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", HP_SW_NAME);
+       struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
 
-       kfree(scsi_dh_data);
+       kfree(h);
 }
 
+static struct scsi_device_handler hp_sw_dh = {
+       .name           = HP_SW_NAME,
+       .module         = THIS_MODULE,
+       .attach         = hp_sw_bus_attach,
+       .detach         = hp_sw_bus_detach,
+       .activate       = hp_sw_activate,
+       .prep_fn        = hp_sw_prep_fn,
+       .match          = hp_sw_match,
+};
+
 static int __init hp_sw_init(void)
 {
        return scsi_register_device_handler(&hp_sw_dh);
index 1b5bc9293e37d416769974055dbe122d38ef0c8c..b46ace3d4bf0cd9c23f62f3422ca6b9eb7026435 100644 (file)
@@ -181,6 +181,7 @@ struct c2_inquiry {
 };
 
 struct rdac_dh_data {
+       struct scsi_dh_data     dh_data;
        struct rdac_controller  *ctlr;
 #define UNINITIALIZED_LUN      (1 << 8)
        unsigned                lun;
@@ -261,9 +262,7 @@ do { \
 
 static inline struct rdac_dh_data *get_rdac_data(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
-       BUG_ON(scsi_dh_data == NULL);
-       return ((struct rdac_dh_data *) scsi_dh_data->buf);
+       return container_of(sdev->scsi_dh_data, struct rdac_dh_data, dh_data);
 }
 
 static struct request *get_rdac_req(struct scsi_device *sdev,
@@ -779,7 +778,10 @@ static int rdac_check_sense(struct scsi_device *sdev,
        return SCSI_RETURN_NOT_HANDLED;
 }
 
-static const struct scsi_dh_devlist rdac_dev_list[] = {
+static const struct {
+       char *vendor;
+       char *model;
+} rdac_dev_list[] = {
        {"IBM", "1722"},
        {"IBM", "1724"},
        {"IBM", "1726"},
@@ -825,40 +827,16 @@ static bool rdac_match(struct scsi_device *sdev)
        return false;
 }
 
-static int rdac_bus_attach(struct scsi_device *sdev);
-static void rdac_bus_detach(struct scsi_device *sdev);
-
-static struct scsi_device_handler rdac_dh = {
-       .name = RDAC_NAME,
-       .module = THIS_MODULE,
-       .devlist = rdac_dev_list,
-       .prep_fn = rdac_prep_fn,
-       .check_sense = rdac_check_sense,
-       .attach = rdac_bus_attach,
-       .detach = rdac_bus_detach,
-       .activate = rdac_activate,
-       .match = rdac_match,
-};
-
-static int rdac_bus_attach(struct scsi_device *sdev)
+static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev)
 {
-       struct scsi_dh_data *scsi_dh_data;
        struct rdac_dh_data *h;
-       unsigned long flags;
        int err;
        char array_name[ARRAY_LABEL_LEN];
        char array_id[UNIQUE_ID_LEN];
 
-       scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
-                              + sizeof(*h) , GFP_KERNEL);
-       if (!scsi_dh_data) {
-               sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
-                           RDAC_NAME);
-               return -ENOMEM;
-       }
-
-       scsi_dh_data->scsi_dh = &rdac_dh;
-       h = (struct rdac_dh_data *) scsi_dh_data->buf;
+       h = kzalloc(sizeof(*h) , GFP_KERNEL);
+       if (!h)
+               return ERR_PTR(-ENOMEM);
        h->lun = UNINITIALIZED_LUN;
        h->state = RDAC_STATE_ACTIVE;
 
@@ -878,19 +856,12 @@ static int rdac_bus_attach(struct scsi_device *sdev)
        if (err != SCSI_DH_OK)
                goto clean_ctlr;
 
-       if (!try_module_get(THIS_MODULE))
-               goto clean_ctlr;
-
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       sdev->scsi_dh_data = scsi_dh_data;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-
        sdev_printk(KERN_NOTICE, sdev,
                    "%s: LUN %d (%s) (%s)\n",
                    RDAC_NAME, h->lun, mode[(int)h->mode],
                    lun_state[(int)h->lun_state]);
 
-       return 0;
+       return &h->dh_data;
 
 clean_ctlr:
        spin_lock(&list_lock);
@@ -898,37 +869,34 @@ clean_ctlr:
        spin_unlock(&list_lock);
 
 failed:
-       kfree(scsi_dh_data);
-       sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
-                   RDAC_NAME);
-       return -EINVAL;
+       kfree(h);
+       return ERR_PTR(-EINVAL);
 }
 
 static void rdac_bus_detach( struct scsi_device *sdev )
 {
-       struct scsi_dh_data *scsi_dh_data;
-       struct rdac_dh_data *h;
-       unsigned long flags;
+       struct rdac_dh_data *h = get_rdac_data(sdev);
 
-       scsi_dh_data = sdev->scsi_dh_data;
-       h = (struct rdac_dh_data *) scsi_dh_data->buf;
        if (h->ctlr && h->ctlr->ms_queued)
                flush_workqueue(kmpath_rdacd);
 
-       spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
-       sdev->scsi_dh_data = NULL;
-       spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
-
        spin_lock(&list_lock);
        if (h->ctlr)
                kref_put(&h->ctlr->kref, release_controller);
        spin_unlock(&list_lock);
-       kfree(scsi_dh_data);
-       module_put(THIS_MODULE);
-       sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
+       kfree(h);
 }
 
-
+static struct scsi_device_handler rdac_dh = {
+       .name = RDAC_NAME,
+       .module = THIS_MODULE,
+       .prep_fn = rdac_prep_fn,
+       .check_sense = rdac_check_sense,
+       .attach = rdac_bus_attach,
+       .detach = rdac_bus_detach,
+       .activate = rdac_activate,
+       .match = rdac_match,
+};
 
 static int __init rdac_init(void)
 {
index 4b0dd8c567077e53583a0d59b85a2aa8db7e93b7..3e088125a8be6a339757dc1380f1c73418952bfc 100644 (file)
 /*
  * Definitions for the generic 5380 driver.
  */
-#define AUTOSENSE
+
+#define DONT_USE_INTR
 
 #define NCR5380_read(reg)              inb(port + reg)
 #define NCR5380_write(reg, value)      outb(value, port + reg)
 
-#define NCR5380_implementation_fields  unsigned int port
-#define NCR5380_local_declare()                NCR5380_implementation_fields
+#define NCR5380_implementation_fields  /* none */
+#define NCR5380_local_declare()                unsigned int port
 #define NCR5380_setup(instance)                port = instance->io_port
 
 /*
  * Includes needed for NCR5380.[ch] (XXX: Move them to NCR5380.h)
  */
 #include <linux/delay.h>
-#include "scsi.h"
 
 #include "NCR5380.h"
 #include "NCR5380.c"
@@ -58,6 +58,7 @@
 static struct scsi_host_template dmx3191d_driver_template = {
        .proc_name              = DMX3191D_DRIVER_NAME,
        .name                   = "Domex DMX3191D",
+       .info                   = NCR5380_info,
        .queuecommand           = NCR5380_queue_command,
        .eh_abort_handler       = NCR5380_abort,
        .eh_bus_reset_handler   = NCR5380_bus_reset,
@@ -90,31 +91,23 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
        if (!shost)
                goto out_release_region;       
        shost->io_port = io;
-       shost->irq = pdev->irq;
 
-       NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
+       /* This card does not seem to raise an interrupt on pdev->irq.
+        * Steam-powered SCSI controllers run without an IRQ anyway.
+        */
+       shost->irq = NO_IRQ;
 
-       if (request_irq(pdev->irq, NCR5380_intr, IRQF_SHARED,
-                               DMX3191D_DRIVER_NAME, shost)) {
-               /*
-                * Steam powered scsi controllers run without an IRQ anyway
-                */
-               printk(KERN_WARNING "dmx3191: IRQ %d not available - "
-                                   "switching to polled mode.\n", pdev->irq);
-               shost->irq = SCSI_IRQ_NONE;
-       }
+       NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
 
        pci_set_drvdata(pdev, shost);
 
        error = scsi_add_host(shost, &pdev->dev);
        if (error)
-               goto out_free_irq;
+               goto out_release_region;
 
        scsi_scan_host(shost);
        return 0;
 
- out_free_irq:
-       free_irq(shost->irq, shost);
  out_release_region:
        release_region(io, DMX3191D_REGION_LEN);
  out_disable_device:
@@ -131,8 +124,6 @@ static void dmx3191d_remove_one(struct pci_dev *pdev)
 
        NCR5380_exit(shost);
 
-       if (shost->irq != SCSI_IRQ_NONE)
-               free_irq(shost->irq, shost);
        release_region(shost->io_port, DMX3191D_REGION_LEN);
        pci_disable_device(pdev);
 
index 072f0ec2851e252d8ccaf2a1dd1d0b26742079fc..0bf976936a103bc197b74e7a9ef8036ed91093b9 100644 (file)
@@ -415,10 +415,8 @@ static int adpt_slave_configure(struct scsi_device * device)
        pHba = (adpt_hba *) host->hostdata[0];
 
        if (host->can_queue && device->tagged_supported) {
-               scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
+               scsi_change_queue_depth(device,
                                host->can_queue - 1);
-       } else {
-               scsi_adjust_queue_depth(device, 0, 1);
        }
        return 0;
 }
index 0a667fe05006aa29046e00b3e84bcd375afbc91a..4c74c7ba2dff7cf6829684176c484ecbf356cea1 100644 (file)
@@ -1,5 +1,4 @@
 
-#define AUTOSENSE
 #define PSEUDO_DMA
 #define DONT_USE_INTR
 #define UNSAFE                 /* Leave interrupts enabled during pseudo-dma I/O */
  *     (Unix and Linux consulting and custom programming)
  *     drew@colorado.edu
  *      +1 (303) 440-4894
- *
- * DISTRIBUTION RELEASE 1.
- *
- * For more information, please consult 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
-*/
+ */
 
 /*
- * Options : 
- * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- *      for commands that return with a CHECK CONDITION status. 
- *
- * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
- * increase compared to polled I/O.
- *
- * PARITY - enable parity checking.  Not supported.
- *
- * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. 
- *             You probably want this.
- *
  * The card is detected and initialized in one of several ways : 
  * 1.  Autoprobe (default) - since the board is memory mapped, 
  *     a BIOS signature is scanned for to locate the registers.
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include "dtc.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
 
-
-#define DTC_PUBLIC_RELEASE 2
-
 /*
  * The DTC3180 & 3280 boards are memory mapped.
  * 
@@ -173,10 +148,13 @@ static const struct signature {
  *
  */
 
-static void __init dtc_setup(char *str, int *ints)
+static int __init dtc_setup(char *str)
 {
        static int commandline_current = 0;
        int i;
+       int ints[10];
+
+       get_options(str, ARRAY_SIZE(ints), ints);
        if (ints[0] != 2)
                printk("dtc_setup: usage dtc=address,irq\n");
        else if (commandline_current < NO_OVERRIDES) {
@@ -189,7 +167,10 @@ static void __init dtc_setup(char *str, int *ints)
                        }
                ++commandline_current;
        }
+       return 1;
 }
+
+__setup("dtc=", dtc_setup);
 #endif
 
 /* 
@@ -213,10 +194,6 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
        void __iomem *base;
        int sig, count;
 
-       tpnt->proc_name = "dtc3x80";
-       tpnt->show_info = dtc_show_info;
-       tpnt->write_info = dtc_write_info;
-
        for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
                addr = 0;
                base = NULL;
@@ -271,38 +248,33 @@ found:
                else
                        instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
 
+               /* Compatibility with documented NCR5380 kernel parameters */
+               if (instance->irq == 255)
+                       instance->irq = NO_IRQ;
+
 #ifndef DONT_USE_INTR
                /* With interrupts enabled, it will sometimes hang when doing heavy
                 * reads. So better not enable them until I finger it out. */
-               if (instance->irq != SCSI_IRQ_NONE)
+               if (instance->irq != NO_IRQ)
                        if (request_irq(instance->irq, dtc_intr, 0,
                                        "dtc", instance)) {
                                printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
-                               instance->irq = SCSI_IRQ_NONE;
+                               instance->irq = NO_IRQ;
                        }
 
-               if (instance->irq == SCSI_IRQ_NONE) {
+               if (instance->irq == NO_IRQ) {
                        printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
                        printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
                }
 #else
-               if (instance->irq != SCSI_IRQ_NONE)
+               if (instance->irq != NO_IRQ)
                        printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
-               instance->irq = SCSI_IRQ_NONE;
+               instance->irq = NO_IRQ;
 #endif
 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
                printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
 #endif
 
-               printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
-               if (instance->irq == SCSI_IRQ_NONE)
-                       printk(" interrupts disabled");
-               else
-                       printk(" irq %d", instance->irq);
-               printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
-               NCR5380_print_options(instance);
-               printk("\n");
-
                ++current_override;
                ++count;
        }
@@ -354,20 +326,18 @@ static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev,
  *     timeout.
 */
 
-static int dtc_maxi = 0;
-static int dtc_wmaxi = 0;
-
 static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
 {
        unsigned char *d = dst;
        int i;                  /* For counting time spent in the poll-loop */
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        NCR5380_local_declare();
        NCR5380_setup(instance);
 
        i = 0;
        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
        NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
-       if (instance->irq == SCSI_IRQ_NONE)
+       if (instance->irq == NO_IRQ)
                NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
        else
                NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
@@ -391,8 +361,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
        NCR5380_write(MODE_REG, 0);     /* Clear the operating mode */
        rtrc(0);
        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-       if (i > dtc_maxi)
-               dtc_maxi = i;
+       if (i > hostdata->spin_max_r)
+               hostdata->spin_max_r = i;
        return (0);
 }
 
@@ -412,13 +382,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
 static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
 {
        int i;
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
        NCR5380_local_declare();
        NCR5380_setup(instance);
 
        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
        NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
        /* set direction (write) */
-       if (instance->irq == SCSI_IRQ_NONE)
+       if (instance->irq == NO_IRQ)
                NCR5380_write(DTC_CONTROL_REG, 0);
        else
                NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
@@ -444,8 +415,8 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
        /* Check for parity error here. fixme. */
        NCR5380_write(MODE_REG, 0);     /* Clear the operating mode */
        rtrc(0);
-       if (i > dtc_wmaxi)
-               dtc_wmaxi = i;
+       if (i > hostdata->spin_max_w)
+               hostdata->spin_max_w = i;
        return (0);
 }
 
@@ -457,7 +428,7 @@ static int dtc_release(struct Scsi_Host *shost)
 {
        NCR5380_local_declare();
        NCR5380_setup(shost);
-       if (shost->irq)
+       if (shost->irq != NO_IRQ)
                free_irq(shost->irq, shost);
        NCR5380_exit(shost);
        if (shost->io_port && shost->n_io_port)
@@ -471,6 +442,10 @@ static struct scsi_host_template driver_template = {
        .name                           = "DTC 3180/3280 ",
        .detect                         = dtc_detect,
        .release                        = dtc_release,
+       .proc_name                      = "dtc3x80",
+       .show_info                      = dtc_show_info,
+       .write_info                     = dtc_write_info,
+       .info                           = dtc_info,
        .queuecommand                   = dtc_queue_command,
        .eh_abort_handler               = dtc_abort,
        .eh_bus_reset_handler           = dtc_bus_reset,
index 92d7cfc3f4fcd0c706c412438f39b3a58cecae24..78a2332e9064ee6b58372943ec0c327d2a74b26f 100644 (file)
@@ -5,24 +5,6 @@
  *     (Unix and Linux consulting and custom programming)
  *     drew@colorado.edu
  *      +1 (303) 440-4894
- *
- * DISTRIBUTION RELEASE 2. 
- *
- * For more information, please consult 
- *
- * 
- * 
- * and 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 #ifndef DTC3280_H
 #define DTCDEBUG_INIT  0x1
 #define DTCDEBUG_TRANSFER 0x2
 
-static int dtc_abort(Scsi_Cmnd *);
-static int dtc_biosparam(struct scsi_device *, struct block_device *,
-                        sector_t, int*);
-static int dtc_detect(struct scsi_host_template *);
-static int dtc_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int dtc_bus_reset(Scsi_Cmnd *);
-
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 2
 #endif
@@ -88,6 +63,7 @@ static int dtc_bus_reset(Scsi_Cmnd *);
 #define NCR5380_queue_command          dtc_queue_command
 #define NCR5380_abort                  dtc_abort
 #define NCR5380_bus_reset              dtc_bus_reset
+#define NCR5380_info                   dtc_info
 #define NCR5380_show_info              dtc_show_info 
 #define NCR5380_write_info             dtc_write_info 
 
index 943ad3a19661a4a00fba774ba4d9d978bf5d3d41..227dd2c2ec2f16d1cec7e7b2bb5894fa84862b5e 100644 (file)
@@ -946,20 +946,18 @@ static int eata2x_slave_configure(struct scsi_device *dev)
 
        if (TLDEV(dev->type) && dev->tagged_supported) {
                if (tag_mode == TAG_SIMPLE) {
-                       scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, tqd);
                        tag_suffix = ", simple tags";
                } else if (tag_mode == TAG_ORDERED) {
-                       scsi_adjust_queue_depth(dev, MSG_ORDERED_TAG, tqd);
                        tag_suffix = ", ordered tags";
                } else {
-                       scsi_adjust_queue_depth(dev, 0, tqd);
                        tag_suffix = ", no tags";
                }
+               scsi_change_queue_depth(dev, tqd);
        } else if (TLDEV(dev->type) && linked_comm) {
-               scsi_adjust_queue_depth(dev, 0, tqd);
+               scsi_change_queue_depth(dev, tqd);
                tag_suffix = ", untagged";
        } else {
-               scsi_adjust_queue_depth(dev, 0, utqd);
+               scsi_change_queue_depth(dev, utqd);
                tag_suffix = "";
        }
 
index 3fd305d6b67d893f77e299b49269e5e7035ca43f..b6030e3edd016459262928c96eac923f1dd1dd8c 100644 (file)
@@ -972,11 +972,6 @@ u8 handle_hba_ioctl(struct esas2r_adapter *a,
                    struct atto_ioctl *ioctl_hba);
 int esas2r_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd);
 int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh);
-int esas2r_slave_alloc(struct scsi_device *dev);
-int esas2r_slave_configure(struct scsi_device *dev);
-void esas2r_slave_destroy(struct scsi_device *dev);
-int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason);
-int esas2r_change_queue_type(struct scsi_device *dev, int type);
 long esas2r_proc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
 
 /* SCSI error handler (eh) functions */
index d89a0277a8e189f02af169c0d3476267dc8dc135..baf913047b488d43cef1bf04afd9e3e6e5697329 100644 (file)
@@ -117,9 +117,8 @@ static void do_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
 
        rq = esas2r_alloc_request(a);
        if (rq == NULL) {
-               up(&a->fm_api_semaphore);
                fi->status = FI_STAT_BUSY;
-               return;
+               goto free_sem;
        }
 
        if (fi == &a->firmware.header) {
@@ -135,7 +134,7 @@ static void do_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi)
                if (a->firmware.header_buff == NULL) {
                        esas2r_debug("failed to allocate header buffer!");
                        fi->status = FI_STAT_BUSY;
-                       return;
+                       goto free_req;
                }
 
                memcpy(a->firmware.header_buff, fi,
@@ -171,9 +170,10 @@ all_done:
                                  a->firmware.header_buff,
                                  (dma_addr_t)a->firmware.header_buff_phys);
        }
-
-       up(&a->fm_api_semaphore);
+free_req:
        esas2r_free_request(a, (struct esas2r_request *)rq);
+free_sem:
+       up(&a->fm_api_semaphore);
        return;
 
 }
@@ -1420,9 +1420,10 @@ int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg)
 
                rq = esas2r_alloc_request(a);
                if (rq == NULL) {
-                       up(&a->nvram_semaphore);
-                       ioctl->data.prw.code = 0;
-                       break;
+                       kfree(ioctl);
+                       esas2r_log(ESAS2R_LOG_WARN,
+                          "could not allocate an internal request");
+                       return -ENOMEM;
                }
 
                code = esas2r_write_params(a, rq,
@@ -1523,9 +1524,12 @@ ioctl_done:
                case -EINVAL:
                        ioctl->header.return_code = IOCTL_INVALID_PARAM;
                        break;
+
+               default:
+                       ioctl->header.return_code = IOCTL_GENERAL_ERROR;
+                       break;
                }
 
-               ioctl->header.return_code = IOCTL_GENERAL_ERROR;
        }
 
        /* Always copy the buffer back, if only to pick up the status */
index 6504a195c874fbae42d49e60f8bc9cf56682a3b6..593ff8a63c706a85e8ca61df243160244cccf991 100644 (file)
@@ -254,12 +254,10 @@ static struct scsi_host_template driver_template = {
        .use_clustering                 = ENABLE_CLUSTERING,
        .emulated                       = 0,
        .proc_name                      = ESAS2R_DRVR_NAME,
-       .slave_configure                = esas2r_slave_configure,
-       .slave_alloc                    = esas2r_slave_alloc,
-       .slave_destroy                  = esas2r_slave_destroy,
-       .change_queue_depth             = esas2r_change_queue_depth,
-       .change_queue_type              = esas2r_change_queue_type,
+       .change_queue_depth             = scsi_change_queue_depth,
+       .change_queue_type              = scsi_change_queue_type,
        .max_sectors                    = 0xFFFF,
+       .use_blk_tags                   = 1,
 };
 
 int sgl_page_size = 512;
@@ -1057,7 +1055,7 @@ int esas2r_eh_abort(struct scsi_cmnd *cmd)
 
                cmd->scsi_done(cmd);
 
-               return 0;
+               return SUCCESS;
        }
 
        spin_lock_irqsave(&a->queue_lock, flags);
@@ -1259,60 +1257,6 @@ int esas2r_target_reset(struct scsi_cmnd *cmd)
        return esas2r_dev_targ_reset(cmd, true);
 }
 
-int esas2r_change_queue_depth(struct scsi_device *dev, int depth, int reason)
-{
-       esas2r_log(ESAS2R_LOG_INFO, "change_queue_depth %p, %d", dev, depth);
-
-       scsi_adjust_queue_depth(dev, scsi_get_tag_type(dev), depth);
-
-       return dev->queue_depth;
-}
-
-int esas2r_change_queue_type(struct scsi_device *dev, int type)
-{
-       esas2r_log(ESAS2R_LOG_INFO, "change_queue_type %p, %d", dev, type);
-
-       if (dev->tagged_supported) {
-               scsi_set_tag_type(dev, type);
-
-               if (type)
-                       scsi_activate_tcq(dev, dev->queue_depth);
-               else
-                       scsi_deactivate_tcq(dev, dev->queue_depth);
-       } else {
-               type = 0;
-       }
-
-       return type;
-}
-
-int esas2r_slave_alloc(struct scsi_device *dev)
-{
-       return 0;
-}
-
-int esas2r_slave_configure(struct scsi_device *dev)
-{
-       esas2r_log_dev(ESAS2R_LOG_INFO, &(dev->sdev_gendev),
-                      "esas2r_slave_configure()");
-
-       if (dev->tagged_supported) {
-               scsi_set_tag_type(dev, MSG_SIMPLE_TAG);
-               scsi_activate_tcq(dev, cmd_per_lun);
-       } else {
-               scsi_set_tag_type(dev, 0);
-               scsi_deactivate_tcq(dev, cmd_per_lun);
-       }
-
-       return 0;
-}
-
-void esas2r_slave_destroy(struct scsi_device *dev)
-{
-       esas2r_log_dev(ESAS2R_LOG_INFO, &(dev->sdev_gendev),
-                      "esas2r_slave_destroy()");
-}
-
 void esas2r_log_request_failure(struct esas2r_adapter *a,
                                struct esas2r_request *rq)
 {
index 55548dc5cec39da14ec4b23c33ae4d1a609d30e6..ce5bd52fe692463f78bce7d7104f7c22c4b56690 100644 (file)
@@ -49,55 +49,67 @@ static u32 esp_debug;
 #define ESP_DEBUG_DATADONE     0x00000100
 #define ESP_DEBUG_RECONNECT    0x00000200
 #define ESP_DEBUG_AUTOSENSE    0x00000400
+#define ESP_DEBUG_EVENT                0x00000800
+#define ESP_DEBUG_COMMAND      0x00001000
 
 #define esp_log_intr(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_INTR) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_reset(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_RESET) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_msgin(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_MSGIN) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_msgout(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_MSGOUT) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_cmddone(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_CMDDONE) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_disconnect(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_DISCONNECT) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_datastart(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_DATASTART) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_datadone(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_DATADONE) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_reconnect(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_RECONNECT) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_log_autosense(f, a...) \
 do {   if (esp_debug & ESP_DEBUG_AUTOSENSE) \
-               printk(f, ## a); \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
+} while (0)
+
+#define esp_log_event(f, a...) \
+do {   if (esp_debug & ESP_DEBUG_EVENT)        \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
+} while (0)
+
+#define esp_log_command(f, a...) \
+do {   if (esp_debug & ESP_DEBUG_COMMAND)      \
+               shost_printk(KERN_DEBUG, esp->host, f, ## a);   \
 } while (0)
 
 #define esp_read8(REG)         esp->ops->esp_read8(esp, REG)
@@ -126,10 +138,29 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
 
        esp->esp_event_cur = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
 
+       esp_log_command("cmd[%02x]\n", val);
        esp_write8(val, ESP_CMD);
 }
 EXPORT_SYMBOL(scsi_esp_cmd);
 
+static void esp_send_dma_cmd(struct esp *esp, int len, int max_len, int cmd)
+{
+       if (esp->flags & ESP_FLAG_USE_FIFO) {
+               int i;
+
+               scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+               for (i = 0; i < len; i++)
+                       esp_write8(esp->command_block[i], ESP_FDATA);
+               scsi_esp_cmd(esp, cmd);
+       } else {
+               if (esp->rev == FASHME)
+                       scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+               cmd |= ESP_CMD_DMA;
+               esp->ops->send_dma_cmd(esp, esp->command_block_dma,
+                                      len, max_len, 0, cmd);
+       }
+}
+
 static void esp_event(struct esp *esp, u8 val)
 {
        struct esp_event_ent *p;
@@ -150,19 +181,17 @@ static void esp_dump_cmd_log(struct esp *esp)
        int idx = esp->esp_event_cur;
        int stop = idx;
 
-       printk(KERN_INFO PFX "esp%d: Dumping command log\n",
-              esp->host->unique_id);
+       shost_printk(KERN_INFO, esp->host, "Dumping command log\n");
        do {
                struct esp_event_ent *p = &esp->esp_event_log[idx];
 
-               printk(KERN_INFO PFX "esp%d: ent[%d] %s ",
-                      esp->host->unique_id, idx,
-                      p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT");
-
-               printk("val[%02x] sreg[%02x] seqreg[%02x] "
-                      "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
-                      p->val, p->sreg, p->seqreg,
-                      p->sreg2, p->ireg, p->select_state, p->event);
+               shost_printk(KERN_INFO, esp->host,
+                            "ent[%d] %s val[%02x] sreg[%02x] seqreg[%02x] "
+                            "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
+                            idx,
+                            p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT",
+                            p->val, p->sreg, p->seqreg,
+                            p->sreg2, p->ireg, p->select_state, p->event);
 
                idx = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
        } while (idx != stop);
@@ -176,9 +205,8 @@ static void esp_flush_fifo(struct esp *esp)
 
                while (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) {
                        if (--lim == 0) {
-                               printk(KERN_ALERT PFX "esp%d: ESP_FF_BYTES "
-                                      "will not clear!\n",
-                                      esp->host->unique_id);
+                               shost_printk(KERN_ALERT, esp->host,
+                                            "ESP_FF_BYTES will not clear!\n");
                                break;
                        }
                        udelay(1);
@@ -240,6 +268,19 @@ static void esp_reset_esp(struct esp *esp)
        } else {
                esp->min_period = ((5 * esp->ccycle) / 1000);
        }
+       if (esp->rev == FAS236) {
+               /*
+                * The AM53c974 chip returns the same ID as FAS236;
+                * try to configure glitch eater.
+                */
+               u8 config4 = ESP_CONFIG4_GE1;
+               esp_write8(config4, ESP_CFG4);
+               config4 = esp_read8(ESP_CFG4);
+               if (config4 & ESP_CONFIG4_GE1) {
+                       esp->rev = PCSCSI;
+                       esp_write8(esp->config4, ESP_CFG4);
+               }
+       }
        esp->max_period = (esp->max_period + 3)>>2;
        esp->min_period = (esp->min_period + 3)>>2;
 
@@ -265,7 +306,8 @@ static void esp_reset_esp(struct esp *esp)
                /* fallthrough... */
 
        case FAS236:
-               /* Fast 236 or HME */
+       case PCSCSI:
+               /* Fast 236, AM53c974 or HME */
                esp_write8(esp->config2, ESP_CFG2);
                if (esp->rev == FASHME) {
                        u8 cfg3 = esp->target[0].esp_config3;
@@ -383,12 +425,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent,
        p->cur_residue -= len;
        p->tot_residue -= len;
        if (p->cur_residue < 0 || p->tot_residue < 0) {
-               printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n",
-                      esp->host->unique_id);
-               printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] "
-                      "len[%u]\n",
-                      esp->host->unique_id,
-                      p->cur_residue, p->tot_residue, len);
+               shost_printk(KERN_ERR, esp->host,
+                            "Data transfer overflow.\n");
+               shost_printk(KERN_ERR, esp->host,
+                            "cur_residue[%d] tot_residue[%d] len[%u]\n",
+                            p->cur_residue, p->tot_residue, len);
                p->cur_residue = 0;
                p->tot_residue = 0;
        }
@@ -604,9 +645,8 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
 
 
        if (!ent->sense_ptr) {
-               esp_log_autosense("esp%d: Doing auto-sense for "
-                                 "tgt[%d] lun[%d]\n",
-                                 esp->host->unique_id, tgt, lun);
+               esp_log_autosense("Doing auto-sense for tgt[%d] lun[%d]\n",
+                                 tgt, lun);
 
                ent->sense_ptr = cmd->sense_buffer;
                ent->sense_dma = esp->ops->map_single(esp,
@@ -642,10 +682,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
 
        val = (p - esp->command_block);
 
-       if (esp->rev == FASHME)
-               scsi_esp_cmd(esp, ESP_CMD_FLUSH);
-       esp->ops->send_dma_cmd(esp, esp->command_block_dma,
-                              val, 16, 0, ESP_CMD_DMA | ESP_CMD_SELA);
+       esp_send_dma_cmd(esp, val, 16, ESP_CMD_SELA);
 }
 
 static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
@@ -663,7 +700,7 @@ static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
                        return ent;
                }
 
-               if (!scsi_populate_tag_msg(cmd, &ent->tag[0])) {
+               if (!spi_populate_tag_msg(&ent->tag[0], cmd)) {
                        ent->tag[0] = 0;
                        ent->tag[1] = 0;
                }
@@ -781,12 +818,12 @@ build_identify:
        }
 
        if (!(esp->flags & ESP_FLAG_DOING_SLOWCMD)) {
-               start_cmd = ESP_CMD_DMA | ESP_CMD_SELA;
+               start_cmd = ESP_CMD_SELA;
                if (ent->tag[0]) {
                        *p++ = ent->tag[0];
                        *p++ = ent->tag[1];
 
-                       start_cmd = ESP_CMD_DMA | ESP_CMD_SA3;
+                       start_cmd = ESP_CMD_SA3;
                }
 
                for (i = 0; i < cmd->cmd_len; i++)
@@ -806,7 +843,7 @@ build_identify:
                        esp->msg_out_len += 2;
                }
 
-               start_cmd = ESP_CMD_DMA | ESP_CMD_SELAS;
+               start_cmd = ESP_CMD_SELAS;
                esp->select_state = ESP_SELECT_MSGOUT;
        }
        val = tgt;
@@ -826,10 +863,7 @@ build_identify:
                printk("]\n");
        }
 
-       if (esp->rev == FASHME)
-               scsi_esp_cmd(esp, ESP_CMD_FLUSH);
-       esp->ops->send_dma_cmd(esp, esp->command_block_dma,
-                              val, 16, 0, start_cmd);
+       esp_send_dma_cmd(esp, val, 16, start_cmd);
 }
 
 static struct esp_cmd_entry *esp_get_ent(struct esp *esp)
@@ -953,8 +987,8 @@ static int esp_check_gross_error(struct esp *esp)
                 * - DMA programmed with wrong direction
                 * - improper phase change
                 */
-               printk(KERN_ERR PFX "esp%d: Gross error sreg[%02x]\n",
-                      esp->host->unique_id, esp->sreg);
+               shost_printk(KERN_ERR, esp->host,
+                            "Gross error sreg[%02x]\n", esp->sreg);
                /* XXX Reset the chip. XXX */
                return 1;
        }
@@ -974,7 +1008,6 @@ static int esp_check_spur_intr(struct esp *esp)
 
        default:
                if (!(esp->sreg & ESP_STAT_INTR)) {
-                       esp->ireg = esp_read8(ESP_INTRPT);
                        if (esp->ireg & ESP_INTR_SR)
                                return 1;
 
@@ -982,14 +1015,13 @@ static int esp_check_spur_intr(struct esp *esp)
                         * ESP is not, the only possibility is a DMA error.
                         */
                        if (!esp->ops->dma_error(esp)) {
-                               printk(KERN_ERR PFX "esp%d: Spurious irq, "
-                                      "sreg=%02x.\n",
-                                      esp->host->unique_id, esp->sreg);
+                               shost_printk(KERN_ERR, esp->host,
+                                            "Spurious irq, sreg=%02x.\n",
+                                            esp->sreg);
                                return -1;
                        }
 
-                       printk(KERN_ERR PFX "esp%d: DMA error\n",
-                              esp->host->unique_id);
+                       shost_printk(KERN_ERR, esp->host, "DMA error\n");
 
                        /* XXX Reset the chip. XXX */
                        return -1;
@@ -1002,7 +1034,7 @@ static int esp_check_spur_intr(struct esp *esp)
 
 static void esp_schedule_reset(struct esp *esp)
 {
-       esp_log_reset("ESP: esp_schedule_reset() from %pf\n",
+       esp_log_reset("esp_schedule_reset() from %pf\n",
                      __builtin_return_address(0));
        esp->flags |= ESP_FLAG_RESETTING;
        esp_event(esp, ESP_EVENT_RESET);
@@ -1019,20 +1051,20 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
        int i;
 
        if (!lp->num_tagged) {
-               printk(KERN_ERR PFX "esp%d: Reconnect w/num_tagged==0\n",
-                      esp->host->unique_id);
+               shost_printk(KERN_ERR, esp->host,
+                            "Reconnect w/num_tagged==0\n");
                return NULL;
        }
 
-       esp_log_reconnect("ESP: reconnect tag, ");
+       esp_log_reconnect("reconnect tag, ");
 
        for (i = 0; i < ESP_QUICKIRQ_LIMIT; i++) {
                if (esp->ops->irq_pending(esp))
                        break;
        }
        if (i == ESP_QUICKIRQ_LIMIT) {
-               printk(KERN_ERR PFX "esp%d: Reconnect IRQ1 timeout\n",
-                      esp->host->unique_id);
+               shost_printk(KERN_ERR, esp->host,
+                            "Reconnect IRQ1 timeout\n");
                return NULL;
        }
 
@@ -1043,14 +1075,14 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
                          i, esp->ireg, esp->sreg);
 
        if (esp->ireg & ESP_INTR_DC) {
-               printk(KERN_ERR PFX "esp%d: Reconnect, got disconnect.\n",
-                      esp->host->unique_id);
+               shost_printk(KERN_ERR, esp->host,
+                            "Reconnect, got disconnect.\n");
                return NULL;
        }
 
        if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) {
-               printk(KERN_ERR PFX "esp%d: Reconnect, not MIP sreg[%02x].\n",
-                      esp->host->unique_id, esp->sreg);
+               shost_printk(KERN_ERR, esp->host,
+                            "Reconnect, not MIP sreg[%02x].\n", esp->sreg);
                return NULL;
        }
 
@@ -1073,8 +1105,7 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
                udelay(1);
        }
        if (i == ESP_RESELECT_TAG_LIMIT) {
-               printk(KERN_ERR PFX "esp%d: Reconnect IRQ2 timeout\n",
-                      esp->host->unique_id);
+               shost_printk(KERN_ERR, esp->host, "Reconnect IRQ2 timeout\n");
                return NULL;
        }
        esp->ops->dma_drain(esp);
@@ -1087,17 +1118,17 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
 
        if (esp->command_block[0] < SIMPLE_QUEUE_TAG ||
            esp->command_block[0] > ORDERED_QUEUE_TAG) {
-               printk(KERN_ERR PFX "esp%d: Reconnect, bad tag "
-                      "type %02x.\n",
-                      esp->host->unique_id, esp->command_block[0]);
+               shost_printk(KERN_ERR, esp->host,
+                            "Reconnect, bad tag type %02x.\n",
+                            esp->command_block[0]);
                return NULL;
        }
 
        ent = lp->tagged_cmds[esp->command_block[1]];
        if (!ent) {
-               printk(KERN_ERR PFX "esp%d: Reconnect, no entry for "
-                      "tag %02x.\n",
-                      esp->host->unique_id, esp->command_block[1]);
+               shost_printk(KERN_ERR, esp->host,
+                            "Reconnect, no entry for tag %02x.\n",
+                            esp->command_block[1]);
                return NULL;
        }
 
@@ -1163,9 +1194,9 @@ static int esp_reconnect(struct esp *esp)
        tp = &esp->target[target];
        dev = __scsi_device_lookup_by_target(tp->starget, lun);
        if (!dev) {
-               printk(KERN_ERR PFX "esp%d: Reconnect, no lp "
-                      "tgt[%u] lun[%u]\n",
-                      esp->host->unique_id, target, lun);
+               shost_printk(KERN_ERR, esp->host,
+                            "Reconnect, no lp tgt[%u] lun[%u]\n",
+                            target, lun);
                goto do_reset;
        }
        lp = dev->hostdata;
@@ -1291,8 +1322,8 @@ static int esp_finish_select(struct esp *esp)
                return 0;
        }
 
-       printk("ESP: Unexpected selection completion ireg[%x].\n",
-              esp->ireg);
+       shost_printk(KERN_INFO, esp->host,
+                    "Unexpected selection completion ireg[%x]\n", esp->ireg);
        esp_schedule_reset(esp);
        return 0;
 }
@@ -1312,11 +1343,42 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
                          (((unsigned int)esp_read8(ESP_TCMED)) << 8));
                if (esp->rev == FASHME)
                        ecount |= ((unsigned int)esp_read8(FAS_RLO)) << 16;
+               if (esp->rev == PCSCSI && (esp->config2 & ESP_CONFIG2_FENAB))
+                       ecount |= ((unsigned int)esp_read8(ESP_TCHI)) << 16;
        }
 
        bytes_sent = esp->data_dma_len;
        bytes_sent -= ecount;
 
+       /*
+        * The am53c974 has a DMA 'pecularity'. The doc states:
+        * In some odd byte conditions, one residual byte will
+        * be left in the SCSI FIFO, and the FIFO Flags will
+        * never count to '0 '. When this happens, the residual
+        * byte should be retrieved via PIO following completion
+        * of the BLAST operation.
+        */
+       if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) {
+               size_t count = 1;
+               size_t offset = bytes_sent;
+               u8 bval = esp_read8(ESP_FDATA);
+
+               if (ent->flags & ESP_CMD_FLAG_AUTOSENSE)
+                       ent->sense_ptr[bytes_sent] = bval;
+               else {
+                       struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd);
+                       u8 *ptr;
+
+                       ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg,
+                                                 &offset, &count);
+                       if (likely(ptr)) {
+                               *(ptr + offset) = bval;
+                               scsi_kunmap_atomic_sg(ptr);
+                       }
+               }
+               bytes_sent += fifo_cnt;
+               ent->flags &= ~ESP_CMD_FLAG_RESIDUAL;
+       }
        if (!(ent->flags & ESP_CMD_FLAG_WRITE))
                bytes_sent -= fifo_cnt;
 
@@ -1556,8 +1618,8 @@ static void esp_msgin_extended(struct esp *esp)
                return;
        }
 
-       printk("ESP: Unexpected extended msg type %x\n",
-              esp->msg_in[2]);
+       shost_printk(KERN_INFO, esp->host,
+                    "Unexpected extended msg type %x\n", esp->msg_in[2]);
 
        esp->msg_out[0] = ABORT_TASK_SET;
        esp->msg_out_len = 1;
@@ -1574,7 +1636,8 @@ static int esp_msgin_process(struct esp *esp)
 
        if (msg0 & 0x80) {
                /* Identify */
-               printk("ESP: Unexpected msgin identify\n");
+               shost_printk(KERN_INFO, esp->host,
+                            "Unexpected msgin identify\n");
                return 0;
        }
 
@@ -1640,10 +1703,12 @@ static int esp_msgin_process(struct esp *esp)
 
 static int esp_process_event(struct esp *esp)
 {
-       int write;
+       int write, i;
 
 again:
        write = 0;
+       esp_log_event("process event %d phase %x\n",
+                     esp->event, esp->sreg & ESP_STAT_PMASK);
        switch (esp->event) {
        case ESP_EVENT_CHECK_PHASE:
                switch (esp->sreg & ESP_STAT_PMASK) {
@@ -1673,8 +1738,9 @@ again:
                        break;
 
                default:
-                       printk("ESP: Unexpected phase, sreg=%02x\n",
-                              esp->sreg);
+                       shost_printk(KERN_INFO, esp->host,
+                                    "Unexpected phase, sreg=%02x\n",
+                                    esp->sreg);
                        esp_schedule_reset(esp);
                        return 0;
                }
@@ -1708,18 +1774,17 @@ again:
                esp->data_dma_len = dma_len;
 
                if (!dma_len) {
-                       printk(KERN_ERR PFX "esp%d: DMA length is zero!\n",
-                              esp->host->unique_id);
-                       printk(KERN_ERR PFX "esp%d: cur adr[%08llx] len[%08x]\n",
-                              esp->host->unique_id,
-                              (unsigned long long)esp_cur_dma_addr(ent, cmd),
-                              esp_cur_dma_len(ent, cmd));
+                       shost_printk(KERN_ERR, esp->host,
+                                    "DMA length is zero!\n");
+                       shost_printk(KERN_ERR, esp->host,
+                                    "cur adr[%08llx] len[%08x]\n",
+                                    (unsigned long long)esp_cur_dma_addr(ent, cmd),
+                                    esp_cur_dma_len(ent, cmd));
                        esp_schedule_reset(esp);
                        return 0;
                }
 
-               esp_log_datastart("ESP: start data addr[%08llx] len[%u] "
-                                 "write(%d)\n",
+               esp_log_datastart("start data addr[%08llx] len[%u] write(%d)\n",
                                  (unsigned long long)dma_addr, dma_len, write);
 
                esp->ops->send_dma_cmd(esp, dma_addr, dma_len, dma_len,
@@ -1733,7 +1798,8 @@ again:
                int bytes_sent;
 
                if (esp->ops->dma_error(esp)) {
-                       printk("ESP: data done, DMA error, resetting\n");
+                       shost_printk(KERN_INFO, esp->host,
+                                    "data done, DMA error, resetting\n");
                        esp_schedule_reset(esp);
                        return 0;
                }
@@ -1749,14 +1815,15 @@ again:
                        /* We should always see exactly a bus-service
                         * interrupt at the end of a successful transfer.
                         */
-                       printk("ESP: data done, not BSERV, resetting\n");
+                       shost_printk(KERN_INFO, esp->host,
+                                    "data done, not BSERV, resetting\n");
                        esp_schedule_reset(esp);
                        return 0;
                }
 
                bytes_sent = esp_data_bytes_sent(esp, ent, cmd);
 
-               esp_log_datadone("ESP: data done flgs[%x] sent[%d]\n",
+               esp_log_datadone("data done flgs[%x] sent[%d]\n",
                                 ent->flags, bytes_sent);
 
                if (bytes_sent < 0) {
@@ -1785,8 +1852,9 @@ again:
                }
 
                if (ent->message != COMMAND_COMPLETE) {
-                       printk("ESP: Unexpected message %x in status\n",
-                              ent->message);
+                       shost_printk(KERN_INFO, esp->host,
+                                    "Unexpected message %x in status\n",
+                                    ent->message);
                        esp_schedule_reset(esp);
                        return 0;
                }
@@ -1804,8 +1872,7 @@ again:
                        scsi_esp_cmd(esp, ESP_CMD_ESEL);
 
                if (ent->message == COMMAND_COMPLETE) {
-                       esp_log_cmddone("ESP: Command done status[%x] "
-                                       "message[%x]\n",
+                       esp_log_cmddone("Command done status[%x] message[%x]\n",
                                        ent->status, ent->message);
                        if (ent->status == SAM_STAT_TASK_SET_FULL)
                                esp_event_queue_full(esp, ent);
@@ -1821,16 +1888,16 @@ again:
                                                               DID_OK));
                        }
                } else if (ent->message == DISCONNECT) {
-                       esp_log_disconnect("ESP: Disconnecting tgt[%d] "
-                                          "tag[%x:%x]\n",
+                       esp_log_disconnect("Disconnecting tgt[%d] tag[%x:%x]\n",
                                           cmd->device->id,
                                           ent->tag[0], ent->tag[1]);
 
                        esp->active_cmd = NULL;
                        esp_maybe_execute_command(esp);
                } else {
-                       printk("ESP: Unexpected message %x in freebus\n",
-                              ent->message);
+                       shost_printk(KERN_INFO, esp->host,
+                                    "Unexpected message %x in freebus\n",
+                                    ent->message);
                        esp_schedule_reset(esp);
                        return 0;
                }
@@ -1862,6 +1929,10 @@ again:
                        if (esp->msg_out_len == 1) {
                                esp_write8(esp->msg_out[0], ESP_FDATA);
                                scsi_esp_cmd(esp, ESP_CMD_TI);
+                       } else if (esp->flags & ESP_FLAG_USE_FIFO) {
+                               for (i = 0; i < esp->msg_out_len; i++)
+                                       esp_write8(esp->msg_out[i], ESP_FDATA);
+                               scsi_esp_cmd(esp, ESP_CMD_TI);
                        } else {
                                /* Use DMA. */
                                memcpy(esp->command_block,
@@ -1917,7 +1988,7 @@ again:
                                val = esp_read8(ESP_FDATA);
                        esp->msg_in[esp->msg_in_len++] = val;
 
-                       esp_log_msgin("ESP: Got msgin byte %x\n", val);
+                       esp_log_msgin("Got msgin byte %x\n", val);
 
                        if (!esp_msgin_process(esp))
                                esp->msg_in_len = 0;
@@ -1930,7 +2001,8 @@ again:
                        if (esp->event != ESP_EVENT_FREE_BUS)
                                esp_event(esp, ESP_EVENT_CHECK_PHASE);
                } else {
-                       printk("ESP: MSGIN neither BSERV not FDON, resetting");
+                       shost_printk(KERN_INFO, esp->host,
+                                    "MSGIN neither BSERV not FDON, resetting");
                        esp_schedule_reset(esp);
                        return 0;
                }
@@ -1938,11 +2010,7 @@ again:
        case ESP_EVENT_CMD_START:
                memcpy(esp->command_block, esp->cmd_bytes_ptr,
                       esp->cmd_bytes_left);
-               if (esp->rev == FASHME)
-                       scsi_esp_cmd(esp, ESP_CMD_FLUSH);
-               esp->ops->send_dma_cmd(esp, esp->command_block_dma,
-                                      esp->cmd_bytes_left, 16, 0,
-                                      ESP_CMD_DMA | ESP_CMD_TI);
+               esp_send_dma_cmd(esp, esp->cmd_bytes_left, 16, ESP_CMD_TI);
                esp_event(esp, ESP_EVENT_CMD_DONE);
                esp->flags |= ESP_FLAG_QUICKIRQ_CHECK;
                break;
@@ -1961,8 +2029,8 @@ again:
                break;
 
        default:
-               printk("ESP: Unexpected event %x, resetting\n",
-                      esp->event);
+               shost_printk(KERN_INFO, esp->host,
+                            "Unexpected event %x, resetting\n", esp->event);
                esp_schedule_reset(esp);
                return 0;
                break;
@@ -2044,7 +2112,12 @@ static void __esp_interrupt(struct esp *esp)
        int finish_reset, intr_done;
        u8 phase;
 
+       /*
+       * Once INTRPT is read STATUS and SSTEP are cleared.
+       */
        esp->sreg = esp_read8(ESP_STATUS);
+       esp->seqreg = esp_read8(ESP_SSTEP);
+       esp->ireg = esp_read8(ESP_INTRPT);
 
        if (esp->flags & ESP_FLAG_RESETTING) {
                finish_reset = 1;
@@ -2057,8 +2130,6 @@ static void __esp_interrupt(struct esp *esp)
                        return;
        }
 
-       esp->ireg = esp_read8(ESP_INTRPT);
-
        if (esp->ireg & ESP_INTR_SR)
                finish_reset = 1;
 
@@ -2085,14 +2156,15 @@ static void __esp_interrupt(struct esp *esp)
                }
        }
 
-       esp_log_intr("ESP: intr sreg[%02x] seqreg[%02x] "
+       esp_log_intr("intr sreg[%02x] seqreg[%02x] "
                     "sreg2[%02x] ireg[%02x]\n",
                     esp->sreg, esp->seqreg, esp->sreg2, esp->ireg);
 
        intr_done = 0;
 
        if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN | ESP_INTR_IC)) {
-               printk("ESP: unexpected IREG %02x\n", esp->ireg);
+               shost_printk(KERN_INFO, esp->host,
+                            "unexpected IREG %02x\n", esp->ireg);
                if (esp->ireg & ESP_INTR_IC)
                        esp_dump_cmd_log(esp);
 
@@ -2149,46 +2221,50 @@ static void esp_get_revision(struct esp *esp)
        u8 val;
 
        esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
-       esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+       if (esp->config2 == 0) {
+               esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+               esp_write8(esp->config2, ESP_CFG2);
+
+               val = esp_read8(ESP_CFG2);
+               val &= ~ESP_CONFIG2_MAGIC;
+
+               esp->config2 = 0;
+               if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
+                       /*
+                        * If what we write to cfg2 does not come back,
+                        * cfg2 is not implemented.
+                        * Therefore this must be a plain esp100.
+                        */
+                       esp->rev = ESP100;
+                       return;
+               }
+       }
+
+       esp_set_all_config3(esp, 5);
+       esp->prev_cfg3 = 5;
        esp_write8(esp->config2, ESP_CFG2);
+       esp_write8(0, ESP_CFG3);
+       esp_write8(esp->prev_cfg3, ESP_CFG3);
 
-       val = esp_read8(ESP_CFG2);
-       val &= ~ESP_CONFIG2_MAGIC;
-       if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
-               /* If what we write to cfg2 does not come back, cfg2 is not
-                * implemented, therefore this must be a plain esp100.
+       val = esp_read8(ESP_CFG3);
+       if (val != 5) {
+               /* The cfg2 register is implemented, however
+                * cfg3 is not, must be esp100a.
                 */
-               esp->rev = ESP100;
+               esp->rev = ESP100A;
        } else {
-               esp->config2 = 0;
-               esp_set_all_config3(esp, 5);
-               esp->prev_cfg3 = 5;
-               esp_write8(esp->config2, ESP_CFG2);
-               esp_write8(0, ESP_CFG3);
+               esp_set_all_config3(esp, 0);
+               esp->prev_cfg3 = 0;
                esp_write8(esp->prev_cfg3, ESP_CFG3);
 
-               val = esp_read8(ESP_CFG3);
-               if (val != 5) {
-                       /* The cfg2 register is implemented, however
-                        * cfg3 is not, must be esp100a.
-                        */
-                       esp->rev = ESP100A;
+               /* All of cfg{1,2,3} implemented, must be one of
+                * the fas variants, figure out which one.
+                */
+               if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
+                       esp->rev = FAST;
+                       esp->sync_defp = SYNC_DEFP_FAST;
                } else {
-                       esp_set_all_config3(esp, 0);
-                       esp->prev_cfg3 = 0;
-                       esp_write8(esp->prev_cfg3, ESP_CFG3);
-
-                       /* All of cfg{1,2,3} implemented, must be one of
-                        * the fas variants, figure out which one.
-                        */
-                       if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
-                               esp->rev = FAST;
-                               esp->sync_defp = SYNC_DEFP_FAST;
-                       } else {
-                               esp->rev = ESP236;
-                       }
-                       esp->config2 = 0;
-                       esp_write8(esp->config2, ESP_CFG2);
+                       esp->rev = ESP236;
                }
        }
 }
@@ -2308,6 +2384,7 @@ static const char *esp_chip_names[] = {
        "FAS100A",
        "FAST",
        "FASHME",
+       "AM53C974",
 };
 
 static struct scsi_transport_template *esp_transport_template;
@@ -2317,6 +2394,10 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
        static int instance;
        int err;
 
+       if (!esp->num_tags)
+               esp->num_tags = ESP_DEFAULT_TAGS;
+       else if (esp->num_tags >= ESP_MAX_TAG)
+               esp->num_tags = ESP_MAX_TAG - 1;
        esp->host->transportt = esp_transport_template;
        esp->host->max_lun = ESP_MAX_LUN;
        esp->host->cmd_per_lun = 2;
@@ -2330,12 +2411,13 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
 
        esp_bootup_reset(esp);
 
-       printk(KERN_INFO PFX "esp%u, regs[%1p:%1p] irq[%u]\n",
-              esp->host->unique_id, esp->regs, esp->dma_regs,
-              esp->host->irq);
-       printk(KERN_INFO PFX "esp%u is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
-              esp->host->unique_id, esp_chip_names[esp->rev],
-              esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
+       dev_printk(KERN_INFO, dev, "esp%u: regs[%1p:%1p] irq[%u]\n",
+                  esp->host->unique_id, esp->regs, esp->dma_regs,
+                  esp->host->irq);
+       dev_printk(KERN_INFO, dev,
+                  "esp%u: is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
+                  esp->host->unique_id, esp_chip_names[esp->rev],
+                  esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
 
        /* Let the SCSI bus reset settle. */
        ssleep(esp_bus_reset_settle);
@@ -2402,28 +2484,10 @@ static int esp_slave_configure(struct scsi_device *dev)
 {
        struct esp *esp = shost_priv(dev->host);
        struct esp_target_data *tp = &esp->target[dev->id];
-       int goal_tags, queue_depth;
-
-       goal_tags = 0;
 
-       if (dev->tagged_supported) {
-               /* XXX make this configurable somehow XXX */
-               goal_tags = ESP_DEFAULT_TAGS;
-
-               if (goal_tags > ESP_MAX_TAG)
-                       goal_tags = ESP_MAX_TAG;
-       }
+       if (dev->tagged_supported)
+               scsi_change_queue_depth(dev, esp->num_tags);
 
-       queue_depth = goal_tags;
-       if (queue_depth < dev->host->cmd_per_lun)
-               queue_depth = dev->host->cmd_per_lun;
-
-       if (goal_tags) {
-               scsi_set_tag_type(dev, MSG_ORDERED_TAG);
-               scsi_activate_tcq(dev, queue_depth);
-       } else {
-               scsi_deactivate_tcq(dev, queue_depth);
-       }
        tp->flags |= ESP_TGT_DISCONNECT;
 
        if (!spi_initial_dv(dev->sdev_target))
@@ -2451,19 +2515,20 @@ static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
         * XXX much for the final driver.
         */
        spin_lock_irqsave(esp->host->host_lock, flags);
-       printk(KERN_ERR PFX "esp%d: Aborting command [%p:%02x]\n",
-              esp->host->unique_id, cmd, cmd->cmnd[0]);
+       shost_printk(KERN_ERR, esp->host, "Aborting command [%p:%02x]\n",
+                    cmd, cmd->cmnd[0]);
        ent = esp->active_cmd;
        if (ent)
-               printk(KERN_ERR PFX "esp%d: Current command [%p:%02x]\n",
-                      esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+               shost_printk(KERN_ERR, esp->host,
+                            "Current command [%p:%02x]\n",
+                            ent->cmd, ent->cmd->cmnd[0]);
        list_for_each_entry(ent, &esp->queued_cmds, list) {
-               printk(KERN_ERR PFX "esp%d: Queued command [%p:%02x]\n",
-                      esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+               shost_printk(KERN_ERR, esp->host, "Queued command [%p:%02x]\n",
+                            ent->cmd, ent->cmd->cmnd[0]);
        }
        list_for_each_entry(ent, &esp->active_cmds, list) {
-               printk(KERN_ERR PFX "esp%d: Active command [%p:%02x]\n",
-                      esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+               shost_printk(KERN_ERR, esp->host, " Active command [%p:%02x]\n",
+                            ent->cmd, ent->cmd->cmnd[0]);
        }
        esp_dump_cmd_log(esp);
        spin_unlock_irqrestore(esp->host->host_lock, flags);
@@ -2631,6 +2696,7 @@ struct scsi_host_template scsi_esp_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .max_sectors            = 0xffff,
        .skip_settle_delay      = 1,
+       .use_blk_tags           = 1,
 };
 EXPORT_SYMBOL(scsi_esp_template);
 
index cd68805e8d787e1d2ca9acaedd667d87bc201eb7..84dcbe4a6268bf740e02ac6d948890cbb2723ccb 100644 (file)
@@ -1,4 +1,4 @@
-/* esp_scsi.h: Defines and structures for the ESP drier.
+/* esp_scsi.h: Defines and structures for the ESP driver.
  *
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
@@ -25,6 +25,7 @@
 #define ESP_CTEST      0x0aUL          /* wo  Chip test register      0x28  */
 #define ESP_CFG2       0x0bUL          /* rw  Second cfg register     0x2c  */
 #define ESP_CFG3       0x0cUL          /* rw  Third cfg register      0x30  */
+#define ESP_CFG4       0x0dUL          /* rw  Fourth cfg register     0x34  */
 #define ESP_TCHI       0x0eUL          /* rw  High bits transf count  0x38  */
 #define ESP_UID                ESP_TCHI        /* ro  Unique ID code          0x38  */
 #define FAS_RLO                ESP_TCHI        /* rw  HME extended counter    0x38  */
 #define ESP_CONFIG3_IMS       0x80     /* ID msg chk'ng        (esp/fas236)  */
 #define ESP_CONFIG3_OBPUSH    0x80     /* Push odd-byte to dma (hme)         */
 
+/* ESP config register 4 read-write, found only on am53c974 chips */
+#define ESP_CONFIG4_RADE      0x04     /* Active negation */
+#define ESP_CONFIG4_RAE       0x08     /* Active negation on REQ and ACK */
+#define ESP_CONFIG4_PWD       0x20     /* Reduced power feature */
+#define ESP_CONFIG4_GE0       0x40     /* Glitch eater bit 0 */
+#define ESP_CONFIG4_GE1       0x80     /* Glitch eater bit 1 */
+
+#define ESP_CONFIG_GE_12NS    (0)
+#define ESP_CONFIG_GE_25NS    (ESP_CONFIG_GE1)
+#define ESP_CONFIG_GE_35NS    (ESP_CONFIG_GE0)
+#define ESP_CONFIG_GE_0NS     (ESP_CONFIG_GE0 | ESP_CONFIG_GE1)
+
 /* ESP command register read-write */
 /* Group 1 commands:  These may be sent at any point in time to the ESP
  *                    chip.  None of them can generate interrupts 'cept
@@ -254,6 +267,7 @@ enum esp_rev {
        FAS100A    = 0x04,
        FAST       = 0x05,
        FASHME     = 0x06,
+       PCSCSI     = 0x07,  /* AM53c974 */
 };
 
 struct esp_cmd_entry {
@@ -269,6 +283,7 @@ struct esp_cmd_entry {
 #define ESP_CMD_FLAG_WRITE     0x01 /* DMA is a write */
 #define ESP_CMD_FLAG_ABORT     0x02 /* being aborted */
 #define ESP_CMD_FLAG_AUTOSENSE 0x04 /* Doing automatic REQUEST_SENSE */
+#define ESP_CMD_FLAG_RESIDUAL  0x08 /* AM53c974 BLAST residual */
 
        u8                      tag[2];
        u8                      orig_tag[2];
@@ -283,7 +298,6 @@ struct esp_cmd_entry {
        struct completion       *eh_done;
 };
 
-/* XXX make this configurable somehow XXX */
 #define ESP_DEFAULT_TAGS       16
 
 #define ESP_MAX_TARGET         16
@@ -445,7 +459,7 @@ struct esp {
        u8                      prev_soff;
        u8                      prev_stp;
        u8                      prev_cfg3;
-       u8                      __pad;
+       u8                      num_tags;
 
        struct list_head        esp_cmd_pool;
 
@@ -466,6 +480,7 @@ struct esp {
        u8                      bursts;
        u8                      config1;
        u8                      config2;
+       u8                      config4;
 
        u8                      scsi_id;
        u32                     scsi_id_mask;
@@ -479,6 +494,7 @@ struct esp {
 #define ESP_FLAG_WIDE_CAPABLE  0x00000008
 #define ESP_FLAG_QUICKIRQ_CHECK        0x00000010
 #define ESP_FLAG_DISABLE_SYNC  0x00000020
+#define ESP_FLAG_USE_FIFO      0x00000040
 
        u8                      select_state;
 #define ESP_SELECT_NONE                0x00 /* Not selecting */
index 4a8ac7d8c76b25467e5f51087f3f2ff6d6e2f5dd..308a016fdaeafd99c984788465a23983a1c71425 100644 (file)
@@ -280,14 +280,16 @@ static struct scsi_host_template fcoe_shost_template = {
        .eh_device_reset_handler = fc_eh_device_reset,
        .eh_host_reset_handler = fc_eh_host_reset,
        .slave_alloc = fc_slave_alloc,
-       .change_queue_depth = fc_change_queue_depth,
-       .change_queue_type = fc_change_queue_type,
+       .change_queue_depth = scsi_change_queue_depth,
+       .change_queue_type = scsi_change_queue_type,
        .this_id = -1,
        .cmd_per_lun = 3,
        .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
        .use_clustering = ENABLE_CLUSTERING,
        .sg_tablesize = SG_ALL,
        .max_sectors = 0xffff,
+       .use_blk_tags = 1,
+       .track_queue_depth = 1,
 };
 
 /**
index bf8d34c26f13ffb99dcb6c6d616303a80076cc5e..3b73b96619e2deeb82e203927f57904913a51dff 100644 (file)
@@ -39,7 +39,7 @@
 
 #define DRV_NAME               "fnic"
 #define DRV_DESCRIPTION                "Cisco FCoE HBA Driver"
-#define DRV_VERSION            "1.6.0.11"
+#define DRV_VERSION            "1.6.0.16"
 #define PFX                    DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
index f3984b48f8e96e19f92bd07f11467a625f3eae0c..bf0bbd42efb5d9d13b3289ee24c7ba6e852df6df 100644 (file)
@@ -135,6 +135,11 @@ void fnic_handle_link(struct work_struct *work)
                        fnic->lport->host->host_no, FNIC_FC_LE,
                        "Link Status: UP_DOWN",
                        strlen("Link Status: UP_DOWN"));
+               if (fnic->config.flags & VFCF_FIP_CAPABLE) {
+                       FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
+                               "deleting fip-timer during link-down\n");
+                       del_timer_sync(&fnic->fip_timer);
+               }
                fcoe_ctlr_link_down(&fnic->ctlr);
        }
 
index 8c56fdc3a4560adf69a82332545a1ed768bde1e7..0c1f8177b5b72abf8f0c4d3d0b587dbb85a85226 100644 (file)
@@ -95,12 +95,10 @@ static int fnic_slave_alloc(struct scsi_device *sdev)
 {
        struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
 
-       sdev->tagged_supported = 1;
-
        if (!rport || fc_remote_port_chkready(rport))
                return -ENXIO;
 
-       scsi_activate_tcq(sdev, fnic_max_qdepth);
+       scsi_change_queue_depth(sdev, fnic_max_qdepth);
        return 0;
 }
 
@@ -112,8 +110,8 @@ static struct scsi_host_template fnic_host_template = {
        .eh_device_reset_handler = fnic_device_reset,
        .eh_host_reset_handler = fnic_host_reset,
        .slave_alloc = fnic_slave_alloc,
-       .change_queue_depth = fc_change_queue_depth,
-       .change_queue_type = fc_change_queue_type,
+       .change_queue_depth = scsi_change_queue_depth,
+       .change_queue_type = scsi_change_queue_type,
        .this_id = -1,
        .cmd_per_lun = 3,
        .can_queue = FNIC_DFLT_IO_REQ,
@@ -121,6 +119,8 @@ static struct scsi_host_template fnic_host_template = {
        .sg_tablesize = FNIC_MAX_SG_DESC_CNT,
        .max_sectors = 0xffff,
        .shost_attrs = fnic_attrs,
+       .use_blk_tags = 1,
+       .track_queue_depth = 1,
 };
 
 static void
@@ -438,21 +438,30 @@ static int fnic_dev_wait(struct vnic_dev *vdev,
        unsigned long time;
        int done;
        int err;
+       int count;
+
+       count = 0;
 
        err = start(vdev, arg);
        if (err)
                return err;
 
-       /* Wait for func to complete...2 seconds max */
+       /* Wait for func to complete.
+       * Sometime schedule_timeout_uninterruptible take long time
+       * to wake up so we do not retry as we are only waiting for
+       * 2 seconds in while loop. By adding count, we make sure
+       * we try atleast three times before returning -ETIMEDOUT
+       */
        time = jiffies + (HZ * 2);
        do {
                err = finished(vdev, &done);
+               count++;
                if (err)
                        return err;
                if (done)
                        return 0;
                schedule_timeout_uninterruptible(HZ / 10);
-       } while (time_after(time, jiffies));
+       } while (time_after(time, jiffies) || (count < 3));
 
        return -ETIMEDOUT;
 }
index 961bdf5d31cd9ddfb9f14fbbf2ffcbeb685482c2..2097de42a14775c1b164485482e834198a77f474 100644 (file)
@@ -325,13 +325,11 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
        struct fc_rport_libfc_priv *rp = rport->dd_data;
        struct host_sg_desc *desc;
        struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
-       u8 pri_tag = 0;
        unsigned int i;
        unsigned long intr_flags;
        int flags;
        u8 exch_flags;
        struct scsi_lun fc_lun;
-       char msg[2];
 
        if (sg_count) {
                /* For each SGE, create a device desc entry */
@@ -357,12 +355,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
 
        int_to_scsilun(sc->device->lun, &fc_lun);
 
-       pri_tag = FCPIO_ICMND_PTA_SIMPLE;
-       msg[0] = MSG_SIMPLE_TAG;
-       scsi_populate_tag_msg(sc, msg);
-       if (msg[0] == MSG_ORDERED_TAG)
-               pri_tag = FCPIO_ICMND_PTA_ORDERED;
-
        /* Enqueue the descriptor in the Copy WQ */
        spin_lock_irqsave(&fnic->wq_copy_lock[0], intr_flags);
 
@@ -394,7 +386,8 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
                                         io_req->sgl_list_pa,
                                         io_req->sense_buf_pa,
                                         0, /* scsi cmd ref, always 0 */
-                                        pri_tag, /* scsi pri and tag */
+                                        FCPIO_ICMND_PTA_SIMPLE,
+                                               /* scsi pri and tag */
                                         flags, /* command flags */
                                         sc->cmnd, sc->cmd_len,
                                         scsi_bufflen(sc),
@@ -428,8 +421,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
        int ret;
        u64 cmd_trace;
        int sg_count = 0;
-       unsigned long flags;
+       unsigned long flags = 0;
        unsigned long ptr;
+       struct fc_rport_priv *rdata;
+       spinlock_t *io_lock = NULL;
 
        if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
                return SCSI_MLQUEUE_HOST_BUSY;
@@ -443,6 +438,16 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
                return 0;
        }
 
+       rdata = lp->tt.rport_lookup(lp, rport->port_id);
+       if (!rdata || (rdata->rp_state == RPORT_ST_DELETE)) {
+               FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+                       "returning IO as rport is removed\n");
+               atomic64_inc(&fnic_stats->misc_stats.rport_not_ready);
+               sc->result = DID_NO_CONNECT;
+               done(sc);
+               return 0;
+       }
+
        if (lp->state != LPORT_ST_READY || !(lp->link_up))
                return SCSI_MLQUEUE_HOST_BUSY;
 
@@ -505,6 +510,13 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
                }
        }
 
+       /*
+       * Will acquire lock defore setting to IO initialized.
+       */
+
+       io_lock = fnic_io_lock_hash(fnic, sc);
+       spin_lock_irqsave(io_lock, flags);
+
        /* initialize rest of io_req */
        io_req->port_id = rport->port_id;
        io_req->start_time = jiffies;
@@ -521,11 +533,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
                 * In case another thread cancelled the request,
                 * refetch the pointer under the lock.
                 */
-               spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc);
                FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
                          sc->request->tag, sc, 0, 0, 0,
                          (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
-               spin_lock_irqsave(io_lock, flags);
                io_req = (struct fnic_io_req *)CMD_SP(sc);
                CMD_SP(sc) = NULL;
                CMD_STATE(sc) = FNIC_IOREQ_CMD_COMPLETE;
@@ -534,6 +544,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
                        fnic_release_ioreq_buf(fnic, io_req, sc);
                        mempool_free(io_req, fnic->io_req_pool);
                }
+               atomic_dec(&fnic->in_flight);
+               /* acquire host lock before returning to SCSI */
+               spin_lock(lp->host->host_lock);
+               return ret;
        } else {
                atomic64_inc(&fnic_stats->io_stats.active_ios);
                atomic64_inc(&fnic_stats->io_stats.num_ios);
@@ -555,6 +569,11 @@ out:
                  sc->request->tag, sc, io_req,
                  sg_count, cmd_trace,
                  (((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
+
+       /* if only we issued IO, will we have the io lock */
+       if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED)
+               spin_unlock_irqrestore(io_lock, flags);
+
        atomic_dec(&fnic->in_flight);
        /* acquire host lock before returning to SCSI */
        spin_lock(lp->host->host_lock);
index acf1f95cb5c5363a10d09bb12eb2365e13541f09..65a9bde26974bd9a5b98b33d7f456b16c9b5c10b 100644 (file)
@@ -624,12 +624,12 @@ int fnic_fc_trace_set_data(u32 host_no, u8 frame_type,
        if (frame_type == FNIC_FC_RECV) {
                eth_fcoe_hdr_len = sizeof(struct ethhdr) +
                                        sizeof(struct fcoe_hdr);
-               fc_trc_frame_len = fc_trc_frame_len + eth_fcoe_hdr_len;
                memset((char *)fc_trace, 0xff, eth_fcoe_hdr_len);
                /* Copy the rest of data frame */
                memcpy((char *)(fc_trace + eth_fcoe_hdr_len), (void *)frame,
                min_t(u8, fc_trc_frame_len,
-                       (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)));
+                       (u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE
+                                               - eth_fcoe_hdr_len)));
        } else {
                memcpy((char *)fc_trace, (void *)frame,
                min_t(u8, fc_trc_frame_len,
index b331272e93bc4d8f77a51aadd184fb49ec7ce5f6..f35792f7051c0884e71fa8cbf4041172e5ddadf3 100644 (file)
  *
  * Added ISAPNP support for DTC436 adapters,
  * Thomas Sailer, sailer@ife.ee.ethz.ch
- *
- * ALPHA RELEASE 1. 
- *
- * For more information, please consult 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 /* 
  */
 
 /*
- * Options :
- *
- * PARITY - enable parity checking.  Not supported.
- *
- * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
- *
- * USLEEP - enable support for devices that don't disconnect.  Untested.
- *
  * The card is detected and initialized in one of several ways : 
  * 1.  With command line overrides - NCR5380=port,irq may be 
  *     used on the LILO command line to override the defaults.
  */
 
 /* settings for DTC3181E card with only Mustek scanner attached */
-#define USLEEP
 #define USLEEP_POLL    1
 #define USLEEP_SLEEP   20
 #define USLEEP_WAITLONG        500
 
 #define AUTOPROBE_IRQ
-#define AUTOSENSE
-
 
 #ifdef CONFIG_SCSI_GENERIC_NCR53C400
 #define NCR53C400_PSEUDO_DMA 1
 #define PSEUDO_DMA
 #define NCR53C400
-#define NCR5380_STATS
-#undef NCR5380_STAT_LIMIT
 #endif
 
 #include <asm/io.h>
 #include <linux/signal.h>
 #include <linux/blkdev.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include "g_NCR5380.h"
 #include "NCR5380.h"
@@ -277,7 +249,7 @@ static int __init do_DTC3181E_setup(char *str)
  *     Locks: none
  */
 
-int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
+static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
 {
        static int current_override = 0;
        int count;
@@ -335,7 +307,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
                        if (pnp_irq_valid(dev, 0))
                                overrides[count].irq = pnp_irq(dev, 0);
                        else
-                               overrides[count].irq = SCSI_IRQ_NONE;
+                               overrides[count].irq = NO_IRQ;
                        if (pnp_dma_valid(dev, 0))
                                overrides[count].dma = pnp_dma(dev, 0);
                        else
@@ -455,46 +427,28 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt)
                else
                        instance->irq = NCR5380_probe_irq(instance, 0xffff);
 
-               if (instance->irq != SCSI_IRQ_NONE)
+               /* Compatibility with documented NCR5380 kernel parameters */
+               if (instance->irq == 255)
+                       instance->irq = NO_IRQ;
+
+               if (instance->irq != NO_IRQ)
                        if (request_irq(instance->irq, generic_NCR5380_intr,
                                        0, "NCR5380", instance)) {
                                printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
-                               instance->irq = SCSI_IRQ_NONE;
+                               instance->irq = NO_IRQ;
                        }
 
-               if (instance->irq == SCSI_IRQ_NONE) {
+               if (instance->irq == NO_IRQ) {
                        printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
                        printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
                }
 
-               printk(KERN_INFO "scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int) instance->NCR5380_instance_name);
-               if (instance->irq == SCSI_IRQ_NONE)
-                       printk(" interrupts disabled");
-               else
-                       printk(" irq %d", instance->irq);
-               printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE);
-               NCR5380_print_options(instance);
-               printk("\n");
-
                ++current_override;
                ++count;
        }
        return count;
 }
 
-/**
- *     generic_NCR5380_info    -       reporting string
- *     @host: NCR5380 to report on
- *
- *     Report driver information for the NCR5380
- */
-       
-const char *generic_NCR5380_info(struct Scsi_Host *host)
-{
-       static const char string[] = "Generic NCR5380/53C400 Driver";
-       return string;
-}
-
 /**
  *     generic_NCR5380_release_resources       -       free resources
  *     @instance: host adapter to clean up 
@@ -504,12 +458,12 @@ const char *generic_NCR5380_info(struct Scsi_Host *host)
  *     Locks: none
  */
  
-int generic_NCR5380_release_resources(struct Scsi_Host *instance)
+static int generic_NCR5380_release_resources(struct Scsi_Host *instance)
 {
        NCR5380_local_declare();
        NCR5380_setup(instance);
        
-       if (instance->irq != SCSI_IRQ_NONE)
+       if (instance->irq != NO_IRQ)
                free_irq(instance->irq, instance);
        NCR5380_exit(instance);
 
@@ -741,163 +695,9 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
  
 #include "NCR5380.c"
 
-#define PRINTP(x) seq_printf(m, x)
-#define ANDP ,
-
-static void sprint_opcode(struct seq_file *m, int opcode)
-{
-       PRINTP("0x%02x " ANDP opcode);
-}
-
-static void sprint_command(struct seq_file *m, unsigned char *command)
-{
-       int i, s;
-       sprint_opcode(m, command[0]);
-       for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-               PRINTP("%02x " ANDP command[i]);
-       PRINTP("\n");
-}
-
-/**
- *     sprintf_Scsi_Cmnd       -       print a scsi command
- *     @m: seq_fil to print into
- *     @cmd: SCSI command block
- *     
- *     Print out the target and command data in hex
- */
-
-static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd)
-{
-       PRINTP("host number %d destination target %d, lun %llu\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun);
-       PRINTP("        command = ");
-       sprint_command(m, cmd->cmnd);
-}
-
-/**
- *     generic_NCR5380_proc_info       -       /proc for NCR5380 driver
- *     @buffer: buffer to print into
- *     @start: start position
- *     @offset: offset into buffer
- *     @len: length
- *     @hostno: instance to affect
- *     @inout: read/write
- *
- *     Provide the procfs information for the 5380 controller. We fill
- *     this with useful debugging information including the commands
- *     being executed, disconnected command queue and the statistical
- *     data
- *
- *     Locks: global cli/lock for queue walk
- */
-static int generic_NCR5380_show_info(struct seq_file *m, struct Scsi_Host *scsi_ptr)
-{
-       NCR5380_local_declare();
-       unsigned long flags;
-       unsigned char status;
-       int i;
-       Scsi_Cmnd *ptr;
-       struct NCR5380_hostdata *hostdata;
-#ifdef NCR5380_STATS
-       struct scsi_device *dev;
-#endif
-
-       NCR5380_setup(scsi_ptr);
-       hostdata = (struct NCR5380_hostdata *) scsi_ptr->hostdata;
-
-       spin_lock_irqsave(scsi_ptr->host_lock, flags);
-       PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
-       PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
-       PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
-#ifdef NCR53C400
-       PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
-       PRINTP("NCR53C400 card%s detected\n" ANDP(((struct NCR5380_hostdata *) scsi_ptr->hostdata)->flags & FLAG_NCR53C400) ? "" : " not");
-# if NCR53C400_PSEUDO_DMA
-       PRINTP("NCR53C400 pseudo DMA used\n");
-# endif
-#else
-       PRINTP("NO NCR53C400 driver extensions\n");
-#endif
-       PRINTP("Using %s mapping at %s 0x%lx, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
-       if (scsi_ptr->irq == SCSI_IRQ_NONE)
-               PRINTP("no interrupt\n");
-       else
-               PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
-
-#ifdef NCR5380_STATS
-       if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
-               PRINTP("There are commands pending, transfer rates may be crud\n");
-       if (hostdata->pendingr)
-               PRINTP("  %d pending reads" ANDP hostdata->pendingr);
-       if (hostdata->pendingw)
-               PRINTP("  %d pending writes" ANDP hostdata->pendingw);
-       if (hostdata->pendingr || hostdata->pendingw)
-               PRINTP("\n");
-       shost_for_each_device(dev, scsi_ptr) {
-               unsigned long br = hostdata->bytes_read[dev->id];
-               unsigned long bw = hostdata->bytes_write[dev->id];
-               long tr = hostdata->time_read[dev->id] / HZ;
-               long tw = hostdata->time_write[dev->id] / HZ;
-
-               PRINTP("  T:%d %s " ANDP dev->id ANDP scsi_device_type(dev->type));
-               for (i = 0; i < 8; i++)
-                       if (dev->vendor[i] >= 0x20)
-                               seq_putc(m, dev->vendor[i]);
-               seq_putc(m, ' ');
-               for (i = 0; i < 16; i++)
-                       if (dev->model[i] >= 0x20)
-                               seq_putc(m, dev->model[i]);
-               seq_putc(m, ' ');
-               for (i = 0; i < 4; i++)
-                       if (dev->rev[i] >= 0x20)
-                               seq_putc(m, dev->rev[i]);
-               seq_putc(m, ' ');
-
-               PRINTP("\n%10ld kb read    in %5ld secs" ANDP br / 1024 ANDP tr);
-               if (tr)
-                       PRINTP(" @ %5ld bps" ANDP br / tr);
-
-               PRINTP("\n%10ld kb written in %5ld secs" ANDP bw / 1024 ANDP tw);
-               if (tw)
-                       PRINTP(" @ %5ld bps" ANDP bw / tw);
-               PRINTP("\n");
-       }
-#endif
-
-       status = NCR5380_read(STATUS_REG);
-       if (!(status & SR_REQ))
-               PRINTP("REQ not asserted, phase unknown.\n");
-       else {
-               for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i);
-               PRINTP("Phase %s\n" ANDP phases[i].name);
-       }
-
-       if (!hostdata->connected) {
-               PRINTP("No currently connected command\n");
-       } else {
-               sprint_Scsi_Cmnd(m, (Scsi_Cmnd *) hostdata->connected);
-       }
-
-       PRINTP("issue_queue\n");
-
-       for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-               sprint_Scsi_Cmnd(m, ptr);
-
-       PRINTP("disconnected_queue\n");
-
-       for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-               sprint_Scsi_Cmnd(m, ptr);
-
-       spin_unlock_irqrestore(scsi_ptr->host_lock, flags);
-       return 0;
-}
-
-#undef PRINTP
-#undef ANDP
-
 static struct scsi_host_template driver_template = {
        .show_info              = generic_NCR5380_show_info,
-       .name                   = "Generic NCR5380/NCR53C400 Scsi Driver",
+       .name                   = "Generic NCR5380/NCR53C400 SCSI",
        .detect                 = generic_NCR5380_detect,
        .release                = generic_NCR5380_release_resources,
        .info                   = generic_NCR5380_info,
index 703adf78e0b2578532e899ca778044162c2eaec3..bea1a3b9b862dfd4b944072af3fbab22344bd66c 100644 (file)
@@ -9,28 +9,11 @@
  *
  * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
  *    K.Lentin@cs.monash.edu.au
- *
- * ALPHA RELEASE 1. 
- *
- * For more information, please consult 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 #ifndef GENERIC_NCR5380_H
 #define GENERIC_NCR5380_H
 
-
-#define GENERIC_NCR5380_PUBLIC_RELEASE 1
-
 #ifdef NCR53C400
 #define BIOSPARAM
 #define NCR5380_BIOSPARAM generic_NCR5380_biosparam
 #endif
 
 #ifndef ASM
-static int generic_NCR5380_abort(Scsi_Cmnd *);
-static int generic_NCR5380_detect(struct scsi_host_template *);
-static int generic_NCR5380_release_resources(struct Scsi_Host *);
-static int generic_NCR5380_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int generic_NCR5380_bus_reset(Scsi_Cmnd *);
-static const char* generic_NCR5380_info(struct Scsi_Host *);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 2
@@ -118,7 +95,8 @@ static const char* generic_NCR5380_info(struct Scsi_Host *);
 #define NCR5380_bus_reset generic_NCR5380_bus_reset
 #define NCR5380_pread generic_NCR5380_pread
 #define NCR5380_pwrite generic_NCR5380_pwrite
-#define NCR5380_proc_info notyet_generic_proc_info
+#define NCR5380_info generic_NCR5380_info
+#define NCR5380_show_info generic_NCR5380_show_info
 
 #define BOARD_NCR5380  0
 #define BOARD_NCR53C400        1
index 0f1ae13ce7c762e802ad16353927f2ad7d73b563..71e1380443797d7ed38d26dba6f01d335b4068bb 100644 (file)
@@ -2159,7 +2159,7 @@ static void gdth_next(gdth_ha_str *ha)
               case VERIFY:
               case START_STOP:
               case MODE_SENSE:
-              case SERVICE_ACTION_IN:
+              case SERVICE_ACTION_IN_16:
                 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                        nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                        nscp->cmnd[4],nscp->cmnd[5]));
@@ -2391,7 +2391,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
         gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data));
         break;
 
-      case SERVICE_ACTION_IN:
+      case SERVICE_ACTION_IN_16:
         if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 &&
             (ha->cache_feat & GDT_64BIT)) {
             gdth_rdcap16_data rdc16;
@@ -4661,7 +4661,6 @@ static void gdth_flush(gdth_ha_str *ha)
 /* configure lun */
 static int gdth_slave_configure(struct scsi_device *sdev)
 {
-    scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
     sdev->skip_ms_page_3f = 1;
     sdev->skip_ms_page_8 = 1;
     return 0;
index 6de80e3528719446e04355037453d0dad911feb5..8bb173e01084efb40b80121cda098651375ed3ce 100644 (file)
@@ -418,7 +418,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        shost->cmd_per_lun = sht->cmd_per_lun;
        shost->unchecked_isa_dma = sht->unchecked_isa_dma;
        shost->use_clustering = sht->use_clustering;
-       shost->ordered_tag = sht->ordered_tag;
        shost->no_write_same = sht->no_write_same;
 
        if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler)
@@ -485,8 +484,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
                                            WQ_UNBOUND | WQ_MEM_RECLAIM,
                                           1, shost->host_no);
        if (!shost->tmf_work_q) {
-               printk(KERN_WARNING "scsi%d: failed to create tmf workq\n",
-                      shost->host_no);
+               shost_printk(KERN_WARNING, shost,
+                            "failed to create tmf workq\n");
                goto fail_kthread;
        }
        scsi_proc_hostdir_add(shost->hostt);
index cef5d49b59cd248d124e81bb568f0e3c198cc1df..6bb4611b238a8421813ab761ac1ecaa53a20cd6d 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/bitmap.h>
 #include <linux/atomic.h>
 #include <linux/jiffies.h>
+#include <linux/percpu-defs.h>
 #include <linux/percpu.h>
 #include <asm/div64.h>
 #include "hpsa_cmd.h"
@@ -103,7 +104,6 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSH,     0x103C, 0x1922},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSH,     0x103C, 0x1923},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSH,     0x103C, 0x1924},
-       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSH,     0x103C, 0x1925},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSH,     0x103C, 0x1926},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSH,     0x103C, 0x1928},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSH,     0x103C, 0x1929},
@@ -149,6 +149,7 @@ static struct board_type products[] = {
        {0x3249103C, "Smart Array P812", &SA5_access},
        {0x324A103C, "Smart Array P712m", &SA5_access},
        {0x324B103C, "Smart Array P711m", &SA5_access},
+       {0x3233103C, "HP StorageWorks 1210m", &SA5_access}, /* alias of 333f */
        {0x3350103C, "Smart Array P222", &SA5_access},
        {0x3351103C, "Smart Array P420", &SA5_access},
        {0x3352103C, "Smart Array P421", &SA5_access},
@@ -193,12 +194,13 @@ static int number_of_controllers;
 
 static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id);
 static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
-static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg);
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 static void lock_and_start_io(struct ctlr_info *h);
 static void start_io(struct ctlr_info *h, unsigned long *flags);
 
 #ifdef CONFIG_COMPAT
-static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg);
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd,
+       void __user *arg);
 #endif
 
 static void cmd_free(struct ctlr_info *h, struct CommandList *c);
@@ -214,8 +216,6 @@ static int hpsa_scsi_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd);
 static void hpsa_scan_start(struct Scsi_Host *);
 static int hpsa_scan_finished(struct Scsi_Host *sh,
        unsigned long elapsed_time);
-static int hpsa_change_queue_depth(struct scsi_device *sdev,
-       int qdepth, int reason);
 
 static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
 static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd);
@@ -274,12 +274,12 @@ static int check_for_unit_attention(struct ctlr_info *h,
                        "detected, command retried\n", h->ctlr);
                break;
        case LUN_FAILED:
-               dev_warn(&h->pdev->dev, HPSA "%d: LUN failure "
-                       "detected, action required\n", h->ctlr);
+               dev_warn(&h->pdev->dev,
+                       HPSA "%d: LUN failure detected\n", h->ctlr);
                break;
        case REPORT_LUNS_CHANGED:
-               dev_warn(&h->pdev->dev, HPSA "%d: report LUN data "
-                       "changed, action required\n", h->ctlr);
+               dev_warn(&h->pdev->dev,
+                       HPSA "%d: report LUN data changed\n", h->ctlr);
        /*
         * Note: this REPORT_LUNS_CHANGED condition only occurs on the external
         * target (array) devices.
@@ -392,7 +392,8 @@ static ssize_t host_show_commands_outstanding(struct device *dev,
        struct Scsi_Host *shost = class_to_shost(dev);
        struct ctlr_info *h = shost_to_hba(shost);
 
-       return snprintf(buf, 20, "%d\n", h->commands_outstanding);
+       return snprintf(buf, 20, "%d\n",
+                       atomic_read(&h->commands_outstanding));
 }
 
 static ssize_t host_show_transport_mode(struct device *dev,
@@ -670,7 +671,7 @@ static struct scsi_host_template hpsa_driver_template = {
        .queuecommand           = hpsa_scsi_queue_command,
        .scan_start             = hpsa_scan_start,
        .scan_finished          = hpsa_scan_finished,
-       .change_queue_depth     = hpsa_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
        .this_id                = -1,
        .use_clustering         = ENABLE_CLUSTERING,
        .eh_abort_handler       = hpsa_eh_abort_handler,
@@ -698,7 +699,6 @@ static inline u32 next_command(struct ctlr_info *h, u8 q)
 {
        u32 a;
        struct reply_queue_buffer *rq = &h->reply_queue[q];
-       unsigned long flags;
 
        if (h->transMethod & CFGTBL_Trans_io_accel1)
                return h->access.command_completed(h, q);
@@ -709,9 +709,7 @@ static inline u32 next_command(struct ctlr_info *h, u8 q)
        if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
                a = rq->head[rq->current_entry];
                rq->current_entry++;
-               spin_lock_irqsave(&h->lock, flags);
-               h->commands_outstanding--;
-               spin_unlock_irqrestore(&h->lock, flags);
+               atomic_dec(&h->commands_outstanding);
        } else {
                a = FIFO_EMPTY;
        }
@@ -1500,22 +1498,22 @@ static int hpsa_map_sg_chain_block(struct ctlr_info *h,
 {
        struct SGDescriptor *chain_sg, *chain_block;
        u64 temp64;
+       u32 chain_len;
 
        chain_sg = &c->SG[h->max_cmd_sg_entries - 1];
        chain_block = h->cmd_sg_list[c->cmdindex];
-       chain_sg->Ext = HPSA_SG_CHAIN;
-       chain_sg->Len = sizeof(*chain_sg) *
+       chain_sg->Ext = cpu_to_le32(HPSA_SG_CHAIN);
+       chain_len = sizeof(*chain_sg) *
                (c->Header.SGTotal - h->max_cmd_sg_entries);
-       temp64 = pci_map_single(h->pdev, chain_block, chain_sg->Len,
+       chain_sg->Len = cpu_to_le32(chain_len);
+       temp64 = pci_map_single(h->pdev, chain_block, chain_len,
                                PCI_DMA_TODEVICE);
        if (dma_mapping_error(&h->pdev->dev, temp64)) {
                /* prevent subsequent unmapping */
-               chain_sg->Addr.lower = 0;
-               chain_sg->Addr.upper = 0;
+               chain_sg->Addr = cpu_to_le64(0);
                return -1;
        }
-       chain_sg->Addr.lower = (u32) (temp64 & 0x0FFFFFFFFULL);
-       chain_sg->Addr.upper = (u32) ((temp64 >> 32) & 0x0FFFFFFFFULL);
+       chain_sg->Addr = cpu_to_le64(temp64);
        return 0;
 }
 
@@ -1523,15 +1521,13 @@ static void hpsa_unmap_sg_chain_block(struct ctlr_info *h,
        struct CommandList *c)
 {
        struct SGDescriptor *chain_sg;
-       union u64bit temp64;
 
-       if (c->Header.SGTotal <= h->max_cmd_sg_entries)
+       if (le16_to_cpu(c->Header.SGTotal) <= h->max_cmd_sg_entries)
                return;
 
        chain_sg = &c->SG[h->max_cmd_sg_entries - 1];
-       temp64.val32.lower = chain_sg->Addr.lower;
-       temp64.val32.upper = chain_sg->Addr.upper;
-       pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
+       pci_unmap_single(h->pdev, le64_to_cpu(chain_sg->Addr),
+                       le32_to_cpu(chain_sg->Len), PCI_DMA_TODEVICE);
 }
 
 
@@ -1732,8 +1728,7 @@ static void complete_scsi_command(struct CommandList *cp)
                struct io_accel1_cmd *c = &h->ioaccel_cmd_pool[cp->cmdindex];
                cp->Header.SGList = cp->Header.SGTotal = scsi_sg_count(cmd);
                cp->Request.CDBLen = c->io_flags & IOACCEL1_IOFLAGS_CDBLEN_MASK;
-               cp->Header.Tag.lower = c->Tag.lower;
-               cp->Header.Tag.upper = c->Tag.upper;
+               cp->Header.tag = c->tag;
                memcpy(cp->Header.LUN.LunAddrBytes, c->CISS_LUN, 8);
                memcpy(cp->Request.CDB, c->CDB, cp->Request.CDBLen);
 
@@ -1763,72 +1758,13 @@ static void complete_scsi_command(struct CommandList *cp)
                        /* Get addition sense code qualifier */
                        ascq = ei->SenseInfo[13];
                }
-
                if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
-                       if (check_for_unit_attention(h, cp))
-                               break;
-                       if (sense_key == ILLEGAL_REQUEST) {
-                               /*
-                                * SCSI REPORT_LUNS is commonly unsupported on
-                                * Smart Array.  Suppress noisy complaint.
-                                */
-                               if (cp->Request.CDB[0] == REPORT_LUNS)
-                                       break;
-
-                               /* If ASC/ASCQ indicate Logical Unit
-                                * Not Supported condition,
-                                */
-                               if ((asc == 0x25) && (ascq == 0x0)) {
-                                       dev_warn(&h->pdev->dev, "cp %p "
-                                               "has check condition\n", cp);
-                                       break;
-                               }
-                       }
-
-                       if (sense_key == NOT_READY) {
-                               /* If Sense is Not Ready, Logical Unit
-                                * Not ready, Manual Intervention
-                                * required
-                                */
-                               if ((asc == 0x04) && (ascq == 0x03)) {
-                                       dev_warn(&h->pdev->dev, "cp %p "
-                                               "has check condition: unit "
-                                               "not ready, manual "
-                                               "intervention required\n", cp);
-                                       break;
-                               }
-                       }
                        if (sense_key == ABORTED_COMMAND) {
-                               /* Aborted command is retryable */
-                               dev_warn(&h->pdev->dev, "cp %p "
-                                       "has check condition: aborted command: "
-                                       "ASC: 0x%x, ASCQ: 0x%x\n",
-                                       cp, asc, ascq);
                                cmd->result |= DID_SOFT_ERROR << 16;
                                break;
                        }
-                       /* Must be some other type of check condition */
-                       dev_dbg(&h->pdev->dev, "cp %p has check condition: "
-                                       "unknown type: "
-                                       "Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
-                                       "Returning result: 0x%x, "
-                                       "cmd=[%02x %02x %02x %02x %02x "
-                                       "%02x %02x %02x %02x %02x %02x "
-                                       "%02x %02x %02x %02x %02x]\n",
-                                       cp, sense_key, asc, ascq,
-                                       cmd->result,
-                                       cmd->cmnd[0], cmd->cmnd[1],
-                                       cmd->cmnd[2], cmd->cmnd[3],
-                                       cmd->cmnd[4], cmd->cmnd[5],
-                                       cmd->cmnd[6], cmd->cmnd[7],
-                                       cmd->cmnd[8], cmd->cmnd[9],
-                                       cmd->cmnd[10], cmd->cmnd[11],
-                                       cmd->cmnd[12], cmd->cmnd[13],
-                                       cmd->cmnd[14], cmd->cmnd[15]);
                        break;
                }
-
-
                /* Problem was not a check condition
                 * Pass it up to the upper layers...
                 */
@@ -1934,14 +1870,11 @@ static void hpsa_pci_unmap(struct pci_dev *pdev,
        struct CommandList *c, int sg_used, int data_direction)
 {
        int i;
-       union u64bit addr64;
 
-       for (i = 0; i < sg_used; i++) {
-               addr64.val32.lower = c->SG[i].Addr.lower;
-               addr64.val32.upper = c->SG[i].Addr.upper;
-               pci_unmap_single(pdev, (dma_addr_t) addr64.val, c->SG[i].Len,
-                       data_direction);
-       }
+       for (i = 0; i < sg_used; i++)
+               pci_unmap_single(pdev, (dma_addr_t) le64_to_cpu(c->SG[i].Addr),
+                               le32_to_cpu(c->SG[i].Len),
+                               data_direction);
 }
 
 static int hpsa_map_one(struct pci_dev *pdev,
@@ -1954,25 +1887,22 @@ static int hpsa_map_one(struct pci_dev *pdev,
 
        if (buflen == 0 || data_direction == PCI_DMA_NONE) {
                cp->Header.SGList = 0;
-               cp->Header.SGTotal = 0;
+               cp->Header.SGTotal = cpu_to_le16(0);
                return 0;
        }
 
-       addr64 = (u64) pci_map_single(pdev, buf, buflen, data_direction);
+       addr64 = pci_map_single(pdev, buf, buflen, data_direction);
        if (dma_mapping_error(&pdev->dev, addr64)) {
                /* Prevent subsequent unmap of something never mapped */
                cp->Header.SGList = 0;
-               cp->Header.SGTotal = 0;
+               cp->Header.SGTotal = cpu_to_le16(0);
                return -1;
        }
-       cp->SG[0].Addr.lower =
-         (u32) (addr64 & (u64) 0x00000000FFFFFFFF);
-       cp->SG[0].Addr.upper =
-         (u32) ((addr64 >> 32) & (u64) 0x00000000FFFFFFFF);
-       cp->SG[0].Len = buflen;
-       cp->SG[0].Ext = HPSA_SG_LAST; /* we are not chaining */
-       cp->Header.SGList = (u8) 1;   /* no. SGs contig in this cmd */
-       cp->Header.SGTotal = (u16) 1; /* total sgs in this cmd list */
+       cp->SG[0].Addr = cpu_to_le64(addr64);
+       cp->SG[0].Len = cpu_to_le32(buflen);
+       cp->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* we are not chaining */
+       cp->Header.SGList = 1;   /* no. SGs contig in this cmd */
+       cp->Header.SGTotal = cpu_to_le16(1); /* total sgs in cmd list */
        return 0;
 }
 
@@ -2830,8 +2760,8 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
        if (d == NULL)
                return 0; /* no match */
 
-       it_nexus = cpu_to_le32((u32) d->ioaccel_handle);
-       scsi_nexus = cpu_to_le32((u32) c2a->scsi_nexus);
+       it_nexus = cpu_to_le32(d->ioaccel_handle);
+       scsi_nexus = cpu_to_le32(c2a->scsi_nexus);
        find = c2a->scsi_nexus;
 
        if (h->raid_offload_debug > 0)
@@ -2891,7 +2821,7 @@ static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
  * Returns 0 on success, -1 otherwise.
  */
 static int hpsa_gather_lun_info(struct ctlr_info *h,
-       int reportlunsize,
+       int reportphyslunsize, int reportloglunsize,
        struct ReportLUNdata *physdev, u32 *nphysicals, int *physical_mode,
        struct ReportLUNdata *logdev, u32 *nlogicals)
 {
@@ -2905,7 +2835,7 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
                *physical_mode = HPSA_REPORT_PHYS_EXTENDED;
                physical_entry_size = 24;
        }
-       if (hpsa_scsi_do_report_phys_luns(h, physdev, reportlunsize,
+       if (hpsa_scsi_do_report_phys_luns(h, physdev, reportphyslunsize,
                                                        *physical_mode)) {
                dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
                return -1;
@@ -2918,7 +2848,7 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
                        *nphysicals - HPSA_MAX_PHYS_LUN);
                *nphysicals = HPSA_MAX_PHYS_LUN;
        }
-       if (hpsa_scsi_do_report_log_luns(h, logdev, reportlunsize)) {
+       if (hpsa_scsi_do_report_log_luns(h, logdev, reportloglunsize)) {
                dev_err(&h->pdev->dev, "report logical LUNs failed.\n");
                return -1;
        }
@@ -2941,8 +2871,8 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
        return 0;
 }
 
-u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i,
-       int nphysicals, int nlogicals,
+static u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position,
+       int i, int nphysicals, int nlogicals,
        struct ReportExtendedLUNdata *physdev_list,
        struct ReportLUNdata *logdev_list)
 {
@@ -3011,15 +2941,14 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
        u32 ndev_allocated = 0;
        struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
        int ncurrent = 0;
-       int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 24;
        int i, n_ext_target_devs, ndevs_to_allocate;
        int raid_ctlr_position;
        int rescan_hba_mode;
        DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);
 
        currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
-       physdev_list = kzalloc(reportlunsize, GFP_KERNEL);
-       logdev_list = kzalloc(reportlunsize, GFP_KERNEL);
+       physdev_list = kzalloc(sizeof(*physdev_list), GFP_KERNEL);
+       logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL);
        tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
 
        if (!currentsd || !physdev_list || !logdev_list || !tmpdevice) {
@@ -3039,7 +2968,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 
        h->hba_mode_enabled = rescan_hba_mode;
 
-       if (hpsa_gather_lun_info(h, reportlunsize,
+       if (hpsa_gather_lun_info(h,
+                       sizeof(*physdev_list), sizeof(*logdev_list),
                        (struct ReportLUNdata *) physdev_list, &nphysicals,
                        &physical_mode, logdev_list, &nlogicals))
                goto out;
@@ -3210,19 +3140,19 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
                }
                addr64 = (u64) sg_dma_address(sg);
                len  = sg_dma_len(sg);
-               curr_sg->Addr.lower = (u32) (addr64 & 0x0FFFFFFFFULL);
-               curr_sg->Addr.upper = (u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
-               curr_sg->Len = len;
-               curr_sg->Ext = (i < scsi_sg_count(cmd) - 1) ? 0 : HPSA_SG_LAST;
+               curr_sg->Addr = cpu_to_le64(addr64);
+               curr_sg->Len = cpu_to_le32(len);
+               curr_sg->Ext = cpu_to_le32(0);
                curr_sg++;
        }
+       (--curr_sg)->Ext = cpu_to_le32(HPSA_SG_LAST);
 
        if (use_sg + chained > h->maxSG)
                h->maxSG = use_sg + chained;
 
        if (chained) {
                cp->Header.SGList = h->max_cmd_sg_entries;
-               cp->Header.SGTotal = (u16) (use_sg + 1);
+               cp->Header.SGTotal = cpu_to_le16(use_sg + 1);
                if (hpsa_map_sg_chain_block(h, cp)) {
                        scsi_dma_unmap(cmd);
                        return -1;
@@ -3233,7 +3163,7 @@ static int hpsa_scatter_gather(struct ctlr_info *h,
 sglist_finished:
 
        cp->Header.SGList = (u8) use_sg;   /* no. SGs contig in this cmd */
-       cp->Header.SGTotal = (u16) use_sg; /* total sgs in this cmd list */
+       cp->Header.SGTotal = cpu_to_le16(use_sg); /* total sgs in this cmd list */
        return 0;
 }
 
@@ -3325,17 +3255,12 @@ static int hpsa_scsi_ioaccel1_queue_command(struct ctlr_info *h,
                        addr64 = (u64) sg_dma_address(sg);
                        len  = sg_dma_len(sg);
                        total_len += len;
-                       curr_sg->Addr.lower = (u32) (addr64 & 0x0FFFFFFFFULL);
-                       curr_sg->Addr.upper =
-                               (u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
-                       curr_sg->Len = len;
-
-                       if (i == (scsi_sg_count(cmd) - 1))
-                               curr_sg->Ext = HPSA_SG_LAST;
-                       else
-                               curr_sg->Ext = 0;  /* we are not chaining */
+                       curr_sg->Addr = cpu_to_le64(addr64);
+                       curr_sg->Len = cpu_to_le32(len);
+                       curr_sg->Ext = cpu_to_le32(0);
                        curr_sg++;
                }
+               (--curr_sg)->Ext = cpu_to_le32(HPSA_SG_LAST);
 
                switch (cmd->sc_data_direction) {
                case DMA_TO_DEVICE:
@@ -3592,7 +3517,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
        cp->data_len = cpu_to_le32(total_len);
        cp->err_ptr = cpu_to_le64(c->busaddr +
                        offsetof(struct io_accel2_cmd, error_data));
-       cp->err_len = cpu_to_le32((u32) sizeof(cp->error_data));
+       cp->err_len = cpu_to_le32(sizeof(cp->error_data));
 
        enqueue_cmd_and_start_io(h, c);
        return 0;
@@ -3809,11 +3734,6 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
                offload_to_mirror =
                        (offload_to_mirror >= map->layout_map_count - 1)
                        ? 0 : offload_to_mirror + 1;
-               /* FIXME: remove after debug/dev */
-               BUG_ON(offload_to_mirror >= map->layout_map_count);
-               dev_warn(&h->pdev->dev,
-                       "DEBUG: Using physical disk map index %d from mirror group %d\n",
-                       map_index, offload_to_mirror);
                dev->offload_to_mirror = offload_to_mirror;
                /* Avoid direct use of dev->offload_to_mirror within this
                 * function since multiple threads might simultaneously
@@ -3959,8 +3879,11 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
                                                dev->scsi3addr);
 }
 
-static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
-       void (*done)(struct scsi_cmnd *))
+/*
+ * Running in struct Scsi_Host->host_lock less mode using LLD internal
+ * struct ctlr_info *h->lock w/ spin_lock_irqsave() protection.
+ */
+static int hpsa_scsi_queue_command(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 {
        struct ctlr_info *h;
        struct hpsa_scsi_dev_t *dev;
@@ -3973,14 +3896,14 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
        dev = cmd->device->hostdata;
        if (!dev) {
                cmd->result = DID_NO_CONNECT << 16;
-               done(cmd);
+               cmd->scsi_done(cmd);
                return 0;
        }
        memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
 
        if (unlikely(lockup_detected(h))) {
                cmd->result = DID_ERROR << 16;
-               done(cmd);
+               cmd->scsi_done(cmd);
                return 0;
        }
        c = cmd_alloc(h);
@@ -3990,9 +3913,6 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
        }
 
        /* Fill in the command list header */
-
-       cmd->scsi_done = done;    /* save this for use by completion code */
-
        /* save c in case we have to abort it  */
        cmd->host_scribble = (unsigned char *) c;
 
@@ -4026,8 +3946,8 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
 
        c->Header.ReplyQueue = 0;  /* unused in simple mode */
        memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
-       c->Header.Tag.lower = (c->cmdindex << DIRECT_LOOKUP_SHIFT);
-       c->Header.Tag.lower |= DIRECT_LOOKUP_BIT;
+       c->Header.tag = cpu_to_le64((c->cmdindex << DIRECT_LOOKUP_SHIFT) |
+                                       DIRECT_LOOKUP_BIT);
 
        /* Fill in the request block... */
 
@@ -4036,17 +3956,18 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
        BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
        c->Request.CDBLen = cmd->cmd_len;
        memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
-       c->Request.Type.Type = TYPE_CMD;
-       c->Request.Type.Attribute = ATTR_SIMPLE;
        switch (cmd->sc_data_direction) {
        case DMA_TO_DEVICE:
-               c->Request.Type.Direction = XFER_WRITE;
+               c->Request.type_attr_dir =
+                       TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_WRITE);
                break;
        case DMA_FROM_DEVICE:
-               c->Request.Type.Direction = XFER_READ;
+               c->Request.type_attr_dir =
+                       TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_READ);
                break;
        case DMA_NONE:
-               c->Request.Type.Direction = XFER_NONE;
+               c->Request.type_attr_dir =
+                       TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_NONE);
                break;
        case DMA_BIDIRECTIONAL:
                /* This can happen if a buggy application does a scsi passthru
@@ -4054,7 +3975,8 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
                 * ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
                 */
 
-               c->Request.Type.Direction = XFER_RSVD;
+               c->Request.type_attr_dir =
+                       TYPE_ATTR_DIR(TYPE_CMD, ATTR_SIMPLE, XFER_RSVD);
                /* This is technically wrong, and hpsa controllers should
                 * reject it with CMD_INVALID, which is the most correct
                 * response, but non-fibre backends appear to let it
@@ -4081,8 +4003,6 @@ static int hpsa_scsi_queue_command_lck(struct scsi_cmnd *cmd,
        return 0;
 }
 
-static DEF_SCSI_QCMD(hpsa_scsi_queue_command)
-
 static int do_not_scan_if_controller_locked_up(struct ctlr_info *h)
 {
        unsigned long flags;
@@ -4152,23 +4072,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh,
        return finished;
 }
 
-static int hpsa_change_queue_depth(struct scsi_device *sdev,
-       int qdepth, int reason)
-{
-       struct ctlr_info *h = sdev_to_hba(sdev);
-
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -ENOTSUPP;
-
-       if (qdepth < 1)
-               qdepth = 1;
-       else
-               if (qdepth > h->nr_cmds)
-                       qdepth = h->nr_cmds;
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-       return sdev->queue_depth;
-}
-
 static void hpsa_unregister_scsi(struct ctlr_info *h)
 {
        /* we are being forcibly unloaded, and may not refuse. */
@@ -4329,8 +4232,8 @@ static void hpsa_get_tag(struct ctlr_info *h,
        if (c->cmd_type == CMD_IOACCEL1) {
                struct io_accel1_cmd *cm1 = (struct io_accel1_cmd *)
                        &h->ioaccel_cmd_pool[c->cmdindex];
-               *tagupper = cm1->Tag.upper;
-               *taglower = cm1->Tag.lower;
+               *tagupper = (u32) (cm1->tag >> 32);
+               *taglower = (u32) (cm1->tag & 0x0ffffffffULL);
                return;
        }
        if (c->cmd_type == CMD_IOACCEL2) {
@@ -4341,11 +4244,10 @@ static void hpsa_get_tag(struct ctlr_info *h,
                *taglower = cm2->Tag;
                return;
        }
-       *tagupper = c->Header.Tag.upper;
-       *taglower = c->Header.Tag.lower;
+       *tagupper = (u32) (c->Header.tag >> 32);
+       *taglower = (u32) (c->Header.tag & 0x0ffffffffULL);
 }
 
-
 static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
        struct CommandList *abort, int swizzle)
 {
@@ -4410,7 +4312,7 @@ static struct CommandList *hpsa_find_cmd_in_queue(struct ctlr_info *h,
        struct CommandList *c = NULL;   /* ptr into cmpQ */
 
        if (!find)
-               return 0;
+               return NULL;
        spin_lock_irqsave(&h->lock, flags);
        list_for_each_entry(c, queue_head, list) {
                if (c->scsi_cmd == NULL) /* e.g.: passthru ioctl */
@@ -4432,7 +4334,7 @@ static struct CommandList *hpsa_find_cmd_in_queue_by_tag(struct ctlr_info *h,
 
        spin_lock_irqsave(&h->lock, flags);
        list_for_each_entry(c, queue_head, list) {
-               if (memcmp(&c->Header.Tag, tag, 8) != 0)
+               if (memcmp(&c->Header.tag, tag, 8) != 0)
                        continue;
                spin_unlock_irqrestore(&h->lock, flags);
                return c;
@@ -4686,19 +4588,32 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
        int i;
        union u64bit temp64;
        dma_addr_t cmd_dma_handle, err_dma_handle;
-       unsigned long flags;
+       int loopcount;
+
+       /* There is some *extremely* small but non-zero chance that that
+        * multiple threads could get in here, and one thread could
+        * be scanning through the list of bits looking for a free
+        * one, but the free ones are always behind him, and other
+        * threads sneak in behind him and eat them before he can
+        * get to them, so that while there is always a free one, a
+        * very unlucky thread might be starved anyway, never able to
+        * beat the other threads.  In reality, this happens so
+        * infrequently as to be indistinguishable from never.
+        */
 
-       spin_lock_irqsave(&h->lock, flags);
+       loopcount = 0;
        do {
                i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
-               if (i == h->nr_cmds) {
-                       spin_unlock_irqrestore(&h->lock, flags);
-                       return NULL;
-               }
-       } while (test_and_set_bit
-                (i & (BITS_PER_LONG - 1),
-                 h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
-       spin_unlock_irqrestore(&h->lock, flags);
+               if (i == h->nr_cmds)
+                       i = 0;
+               loopcount++;
+       } while (test_and_set_bit(i & (BITS_PER_LONG - 1),
+                 h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0 &&
+               loopcount < 10);
+
+       /* Thread got starved?  We do not expect this to ever happen. */
+       if (loopcount >= 10)
+               return NULL;
 
        c = h->cmd_pool + i;
        memset(c, 0, sizeof(*c));
@@ -4714,9 +4629,8 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
        INIT_LIST_HEAD(&c->list);
        c->busaddr = (u32) cmd_dma_handle;
        temp64.val = (u64) err_dma_handle;
-       c->ErrDesc.Addr.lower = temp64.val32.lower;
-       c->ErrDesc.Addr.upper = temp64.val32.upper;
-       c->ErrDesc.Len = sizeof(*c->err_info);
+       c->ErrDesc.Addr = cpu_to_le64(err_dma_handle);
+       c->ErrDesc.Len = cpu_to_le32(sizeof(*c->err_info));
 
        c->h = h;
        return c;
@@ -4729,7 +4643,6 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
 {
        struct CommandList *c;
-       union u64bit temp64;
        dma_addr_t cmd_dma_handle, err_dma_handle;
 
        c = pci_zalloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle);
@@ -4750,10 +4663,8 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
 
        INIT_LIST_HEAD(&c->list);
        c->busaddr = (u32) cmd_dma_handle;
-       temp64.val = (u64) err_dma_handle;
-       c->ErrDesc.Addr.lower = temp64.val32.lower;
-       c->ErrDesc.Addr.upper = temp64.val32.upper;
-       c->ErrDesc.Len = sizeof(*c->err_info);
+       c->ErrDesc.Addr = cpu_to_le64(err_dma_handle);
+       c->ErrDesc.Len = cpu_to_le32(sizeof(*c->err_info));
 
        c->h = h;
        return c;
@@ -4762,30 +4673,25 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
 static void cmd_free(struct ctlr_info *h, struct CommandList *c)
 {
        int i;
-       unsigned long flags;
 
        i = c - h->cmd_pool;
-       spin_lock_irqsave(&h->lock, flags);
        clear_bit(i & (BITS_PER_LONG - 1),
                  h->cmd_pool_bits + (i / BITS_PER_LONG));
-       spin_unlock_irqrestore(&h->lock, flags);
 }
 
 static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
 {
-       union u64bit temp64;
-
-       temp64.val32.lower = c->ErrDesc.Addr.lower;
-       temp64.val32.upper = c->ErrDesc.Addr.upper;
        pci_free_consistent(h->pdev, sizeof(*c->err_info),
-                           c->err_info, (dma_addr_t) temp64.val);
+                           c->err_info,
+                           (dma_addr_t) le64_to_cpu(c->ErrDesc.Addr));
        pci_free_consistent(h->pdev, sizeof(*c),
                            c, (dma_addr_t) (c->busaddr & DIRECT_LOOKUP_MASK));
 }
 
 #ifdef CONFIG_COMPAT
 
-static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
+static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd,
+       void __user *arg)
 {
        IOCTL32_Command_struct __user *arg32 =
            (IOCTL32_Command_struct __user *) arg;
@@ -4810,7 +4716,7 @@ static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
        if (err)
                return -EFAULT;
 
-       err = hpsa_ioctl(dev, CCISS_PASSTHRU, (void *)p);
+       err = hpsa_ioctl(dev, CCISS_PASSTHRU, p);
        if (err)
                return err;
        err |= copy_in_user(&arg32->error_info, &p->error_info,
@@ -4821,7 +4727,7 @@ static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
 }
 
 static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
-       int cmd, void *arg)
+       int cmd, void __user *arg)
 {
        BIG_IOCTL32_Command_struct __user *arg32 =
            (BIG_IOCTL32_Command_struct __user *) arg;
@@ -4848,7 +4754,7 @@ static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
        if (err)
                return -EFAULT;
 
-       err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, (void *)p);
+       err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, p);
        if (err)
                return err;
        err |= copy_in_user(&arg32->error_info, &p->error_info,
@@ -4858,7 +4764,7 @@ static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
        return err;
 }
 
-static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg)
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 {
        switch (cmd) {
        case CCISS_GETPCIINFO:
@@ -4932,7 +4838,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
        IOCTL_Command_struct iocommand;
        struct CommandList *c;
        char *buff = NULL;
-       union u64bit temp64;
+       u64 temp64;
        int rc = 0;
 
        if (!argp)
@@ -4971,14 +4877,14 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
        c->Header.ReplyQueue = 0; /* unused in simple mode */
        if (iocommand.buf_size > 0) {   /* buffer to fill */
                c->Header.SGList = 1;
-               c->Header.SGTotal = 1;
+               c->Header.SGTotal = cpu_to_le16(1);
        } else  { /* no buffers to fill */
                c->Header.SGList = 0;
-               c->Header.SGTotal = 0;
+               c->Header.SGTotal = cpu_to_le16(0);
        }
        memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN));
        /* use the kernel address the cmd block for tag */
-       c->Header.Tag.lower = c->busaddr;
+       c->Header.tag = c->busaddr;
 
        /* Fill in Request block */
        memcpy(&c->Request, &iocommand.Request,
@@ -4986,19 +4892,17 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 
        /* Fill in the scatter gather information */
        if (iocommand.buf_size > 0) {
-               temp64.val = pci_map_single(h->pdev, buff,
+               temp64 = pci_map_single(h->pdev, buff,
                        iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
-               if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
-                       c->SG[0].Addr.lower = 0;
-                       c->SG[0].Addr.upper = 0;
-                       c->SG[0].Len = 0;
+               if (dma_mapping_error(&h->pdev->dev, (dma_addr_t) temp64)) {
+                       c->SG[0].Addr = cpu_to_le64(0);
+                       c->SG[0].Len = cpu_to_le32(0);
                        rc = -ENOMEM;
                        goto out;
                }
-               c->SG[0].Addr.lower = temp64.val32.lower;
-               c->SG[0].Addr.upper = temp64.val32.upper;
-               c->SG[0].Len = iocommand.buf_size;
-               c->SG[0].Ext = HPSA_SG_LAST; /* we are not chaining*/
+               c->SG[0].Addr = cpu_to_le64(temp64);
+               c->SG[0].Len = cpu_to_le32(iocommand.buf_size);
+               c->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* not chaining */
        }
        hpsa_scsi_do_simple_cmd_core_if_no_lockup(h, c);
        if (iocommand.buf_size > 0)
@@ -5033,7 +4937,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
        struct CommandList *c;
        unsigned char **buff = NULL;
        int *buff_size = NULL;
-       union u64bit temp64;
+       u64 temp64;
        BYTE sg_used = 0;
        int status = 0;
        int i;
@@ -5107,29 +5011,30 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
        }
        c->cmd_type = CMD_IOCTL_PEND;
        c->Header.ReplyQueue = 0;
-       c->Header.SGList = c->Header.SGTotal = sg_used;
+       c->Header.SGList = (u8) sg_used;
+       c->Header.SGTotal = cpu_to_le16(sg_used);
        memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
-       c->Header.Tag.lower = c->busaddr;
+       c->Header.tag = c->busaddr;
        memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
        if (ioc->buf_size > 0) {
                int i;
                for (i = 0; i < sg_used; i++) {
-                       temp64.val = pci_map_single(h->pdev, buff[i],
+                       temp64 = pci_map_single(h->pdev, buff[i],
                                    buff_size[i], PCI_DMA_BIDIRECTIONAL);
-                       if (dma_mapping_error(&h->pdev->dev, temp64.val)) {
-                               c->SG[i].Addr.lower = 0;
-                               c->SG[i].Addr.upper = 0;
-                               c->SG[i].Len = 0;
+                       if (dma_mapping_error(&h->pdev->dev,
+                                                       (dma_addr_t) temp64)) {
+                               c->SG[i].Addr = cpu_to_le64(0);
+                               c->SG[i].Len = cpu_to_le32(0);
                                hpsa_pci_unmap(h->pdev, c, i,
                                        PCI_DMA_BIDIRECTIONAL);
                                status = -ENOMEM;
                                goto cleanup0;
                        }
-                       c->SG[i].Addr.lower = temp64.val32.lower;
-                       c->SG[i].Addr.upper = temp64.val32.upper;
-                       c->SG[i].Len = buff_size[i];
-                       c->SG[i].Ext = i < sg_used - 1 ? 0 : HPSA_SG_LAST;
+                       c->SG[i].Addr = cpu_to_le64(temp64);
+                       c->SG[i].Len = cpu_to_le32(buff_size[i]);
+                       c->SG[i].Ext = cpu_to_le32(0);
                }
+               c->SG[--i].Ext = cpu_to_le32(HPSA_SG_LAST);
        }
        hpsa_scsi_do_simple_cmd_core_if_no_lockup(h, c);
        if (sg_used)
@@ -5206,7 +5111,7 @@ static void decrement_passthru_count(struct ctlr_info *h)
 /*
  * ioctl
  */
-static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
 {
        struct ctlr_info *h;
        void __user *argp = (void __user *)arg;
@@ -5268,20 +5173,20 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 {
        int pci_dir = XFER_NONE;
        struct CommandList *a; /* for commands to be aborted */
+       u32 tupper, tlower;
 
        c->cmd_type = CMD_IOCTL_PEND;
        c->Header.ReplyQueue = 0;
        if (buff != NULL && size > 0) {
                c->Header.SGList = 1;
-               c->Header.SGTotal = 1;
+               c->Header.SGTotal = cpu_to_le16(1);
        } else {
                c->Header.SGList = 0;
-               c->Header.SGTotal = 0;
+               c->Header.SGTotal = cpu_to_le16(0);
        }
-       c->Header.Tag.lower = c->busaddr;
+       c->Header.tag = c->busaddr;
        memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8);
 
-       c->Request.Type.Type = cmd_type;
        if (cmd_type == TYPE_CMD) {
                switch (cmd) {
                case HPSA_INQUIRY:
@@ -5291,8 +5196,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                                c->Request.CDB[2] = (page_code & 0xff);
                        }
                        c->Request.CDBLen = 6;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
                        c->Request.Timeout = 0;
                        c->Request.CDB[0] = HPSA_INQUIRY;
                        c->Request.CDB[4] = size & 0xFF;
@@ -5303,8 +5208,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                           mode = 00 target = 0.  Nothing to write.
                         */
                        c->Request.CDBLen = 12;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
                        c->Request.Timeout = 0;
                        c->Request.CDB[0] = cmd;
                        c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */
@@ -5314,8 +5219,9 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        break;
                case HPSA_CACHE_FLUSH:
                        c->Request.CDBLen = 12;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_WRITE;
+                       c->Request.type_attr_dir =
+                                       TYPE_ATTR_DIR(cmd_type,
+                                               ATTR_SIMPLE, XFER_WRITE);
                        c->Request.Timeout = 0;
                        c->Request.CDB[0] = BMIC_WRITE;
                        c->Request.CDB[6] = BMIC_CACHE_FLUSH;
@@ -5324,14 +5230,14 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        break;
                case TEST_UNIT_READY:
                        c->Request.CDBLen = 6;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_NONE;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
                        c->Request.Timeout = 0;
                        break;
                case HPSA_GET_RAID_MAP:
                        c->Request.CDBLen = 12;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
                        c->Request.Timeout = 0;
                        c->Request.CDB[0] = HPSA_CISS_READ;
                        c->Request.CDB[1] = cmd;
@@ -5342,8 +5248,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        break;
                case BMIC_SENSE_CONTROLLER_PARAMETERS:
                        c->Request.CDBLen = 10;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_READ;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ);
                        c->Request.Timeout = 0;
                        c->Request.CDB[0] = BMIC_READ;
                        c->Request.CDB[6] = BMIC_SENSE_CONTROLLER_PARAMETERS;
@@ -5360,9 +5266,8 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
 
                case  HPSA_DEVICE_RESET_MSG:
                        c->Request.CDBLen = 16;
-                       c->Request.Type.Type =  1; /* It is a MSG not a CMD */
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_NONE;
+                       c->Request.type_attr_dir =
+                               TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_NONE);
                        c->Request.Timeout = 0; /* Don't time out */
                        memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
                        c->Request.CDB[0] =  cmd;
@@ -5376,27 +5281,28 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                        break;
                case  HPSA_ABORT_MSG:
                        a = buff;       /* point to command to be aborted */
-                       dev_dbg(&h->pdev->dev, "Abort Tag:0x%08x:%08x using request Tag:0x%08x:%08x\n",
-                               a->Header.Tag.upper, a->Header.Tag.lower,
-                               c->Header.Tag.upper, c->Header.Tag.lower);
+                       dev_dbg(&h->pdev->dev, "Abort Tag:0x%016llx using request Tag:0x%016llx",
+                               a->Header.tag, c->Header.tag);
+                       tlower = (u32) (a->Header.tag >> 32);
+                       tupper = (u32) (a->Header.tag & 0x0ffffffffULL);
                        c->Request.CDBLen = 16;
-                       c->Request.Type.Type = TYPE_MSG;
-                       c->Request.Type.Attribute = ATTR_SIMPLE;
-                       c->Request.Type.Direction = XFER_WRITE;
+                       c->Request.type_attr_dir =
+                                       TYPE_ATTR_DIR(cmd_type,
+                                               ATTR_SIMPLE, XFER_WRITE);
                        c->Request.Timeout = 0; /* Don't time out */
                        c->Request.CDB[0] = HPSA_TASK_MANAGEMENT;
                        c->Request.CDB[1] = HPSA_TMF_ABORT_TASK;
                        c->Request.CDB[2] = 0x00; /* reserved */
                        c->Request.CDB[3] = 0x00; /* reserved */
                        /* Tag to abort goes in CDB[4]-CDB[11] */
-                       c->Request.CDB[4] = a->Header.Tag.lower & 0xFF;
-                       c->Request.CDB[5] = (a->Header.Tag.lower >> 8) & 0xFF;
-                       c->Request.CDB[6] = (a->Header.Tag.lower >> 16) & 0xFF;
-                       c->Request.CDB[7] = (a->Header.Tag.lower >> 24) & 0xFF;
-                       c->Request.CDB[8] = a->Header.Tag.upper & 0xFF;
-                       c->Request.CDB[9] = (a->Header.Tag.upper >> 8) & 0xFF;
-                       c->Request.CDB[10] = (a->Header.Tag.upper >> 16) & 0xFF;
-                       c->Request.CDB[11] = (a->Header.Tag.upper >> 24) & 0xFF;
+                       c->Request.CDB[4] = tlower & 0xFF;
+                       c->Request.CDB[5] = (tlower >> 8) & 0xFF;
+                       c->Request.CDB[6] = (tlower >> 16) & 0xFF;
+                       c->Request.CDB[7] = (tlower >> 24) & 0xFF;
+                       c->Request.CDB[8] = tupper & 0xFF;
+                       c->Request.CDB[9] = (tupper >> 8) & 0xFF;
+                       c->Request.CDB[10] = (tupper >> 16) & 0xFF;
+                       c->Request.CDB[11] = (tupper >> 24) & 0xFF;
                        c->Request.CDB[12] = 0x00; /* reserved */
                        c->Request.CDB[13] = 0x00; /* reserved */
                        c->Request.CDB[14] = 0x00; /* reserved */
@@ -5412,7 +5318,7 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
                BUG();
        }
 
-       switch (c->Request.Type.Direction) {
+       switch (GET_DIR(c->Request.type_attr_dir)) {
        case XFER_READ:
                pci_dir = PCI_DMA_FROMDEVICE;
                break;
@@ -5467,15 +5373,9 @@ static void start_io(struct ctlr_info *h, unsigned long *flags)
 
                /* Put job onto the completed Q */
                addQ(&h->cmpQ, c);
-
-               /* Must increment commands_outstanding before unlocking
-                * and submitting to avoid race checking for fifo full
-                * condition.
-                */
-               h->commands_outstanding++;
-
-               /* Tell the controller execute command */
+               atomic_inc(&h->commands_outstanding);
                spin_unlock_irqrestore(&h->lock, *flags);
+               /* Tell the controller execute command */
                h->access.submit_command(h, c);
                spin_lock_irqsave(&h->lock, *flags);
        }
@@ -5521,6 +5421,7 @@ static inline void finish_cmd(struct CommandList *c)
        unsigned long flags;
        int io_may_be_stalled = 0;
        struct ctlr_info *h = c->h;
+       int count;
 
        spin_lock_irqsave(&h->lock, flags);
        removeQ(c);
@@ -5541,11 +5442,10 @@ static inline void finish_cmd(struct CommandList *c)
         * want to get in a cycle where we call start_io every time
         * through here.
         */
-       if (unlikely(h->fifo_recently_full) &&
-               h->commands_outstanding < 5)
-               io_may_be_stalled = 1;
-
+       count = atomic_read(&h->commands_outstanding);
        spin_unlock_irqrestore(&h->lock, flags);
+       if (unlikely(h->fifo_recently_full) && count < 5)
+               io_may_be_stalled = 1;
 
        dial_up_lockup_detection_on_fw_flash_complete(c->h, c);
        if (likely(c->cmd_type == CMD_IOACCEL1 || c->cmd_type == CMD_SCSI
@@ -5765,22 +5665,20 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 
        cmd->CommandHeader.ReplyQueue = 0;
        cmd->CommandHeader.SGList = 0;
-       cmd->CommandHeader.SGTotal = 0;
-       cmd->CommandHeader.Tag.lower = paddr32;
-       cmd->CommandHeader.Tag.upper = 0;
+       cmd->CommandHeader.SGTotal = cpu_to_le16(0);
+       cmd->CommandHeader.tag = paddr32;
        memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
 
        cmd->Request.CDBLen = 16;
-       cmd->Request.Type.Type = TYPE_MSG;
-       cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE;
-       cmd->Request.Type.Direction = XFER_NONE;
+       cmd->Request.type_attr_dir =
+                       TYPE_ATTR_DIR(TYPE_MSG, ATTR_HEADOFQUEUE, XFER_NONE);
        cmd->Request.Timeout = 0; /* Don't time out */
        cmd->Request.CDB[0] = opcode;
        cmd->Request.CDB[1] = type;
        memset(&cmd->Request.CDB[2], 0, 14); /* rest of the CDB is reserved */
-       cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(*cmd);
-       cmd->ErrorDescriptor.Addr.upper = 0;
-       cmd->ErrorDescriptor.Len = sizeof(struct ErrorInfo);
+       cmd->ErrorDescriptor.Addr =
+                       cpu_to_le64((paddr32 + sizeof(*cmd)));
+       cmd->ErrorDescriptor.Len = cpu_to_le32(sizeof(struct ErrorInfo));
 
        writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
 
@@ -5818,7 +5716,7 @@ static int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 #define hpsa_noop(p) hpsa_message(p, 3, 0)
 
 static int hpsa_controller_hard_reset(struct pci_dev *pdev,
-       void * __iomem vaddr, u32 use_doorbell)
+       void __iomem *vaddr, u32 use_doorbell)
 {
        u16 pmcsr;
        int pos;
@@ -6056,7 +5954,7 @@ unmap_vaddr:
  *   the io functions.
  *   This is for debug only.
  */
-static void print_cfg_table(struct device *dev, struct CfgTable *tb)
+static void print_cfg_table(struct device *dev, struct CfgTable __iomem *tb)
 {
 #ifdef HPSA_DEBUG
        int i;
@@ -6323,11 +6221,11 @@ static void hpsa_find_board_params(struct ctlr_info *h)
        h->max_cmd_sg_entries = 31;
        if (h->maxsgentries > 512) {
                h->max_cmd_sg_entries = 32;
-               h->chainsize = h->maxsgentries - h->max_cmd_sg_entries + 1;
+               h->chainsize = h->maxsgentries - h->max_cmd_sg_entries;
                h->maxsgentries--; /* save one for chain pointer */
        } else {
-               h->maxsgentries = 31; /* default to traditional values */
                h->chainsize = 0;
+               h->maxsgentries = 31; /* default to traditional values */
        }
 
        /* Find out what task management functions are supported and cache */
@@ -6456,15 +6354,15 @@ static int hpsa_pci_init(struct ctlr_info *h)
                return err;
        }
 
-       /* Enable bus mastering (pci_disable_device may disable this) */
-       pci_set_master(h->pdev);
-
        err = pci_request_regions(h->pdev, HPSA);
        if (err) {
                dev_err(&h->pdev->dev,
                        "cannot obtain PCI resources, aborting\n");
                return err;
        }
+
+       pci_set_master(h->pdev);
+
        hpsa_interrupt_mode(h);
        err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr);
        if (err)
@@ -6544,7 +6442,9 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev)
                dev_warn(&pdev->dev, "failed to enable device.\n");
                return -ENODEV;
        }
+
        pci_set_master(pdev);
+
        /* Reset the controller with a PCI power-cycle or via doorbell */
        rc = hpsa_kdump_hard_reset_controller(pdev);
 
@@ -7431,13 +7331,12 @@ static void hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
                        cp->host_context_flags = IOACCEL1_HCFLAGS_CISS_FORMAT;
                        cp->timeout_sec = 0;
                        cp->ReplyQueue = 0;
-                       cp->Tag.lower = (i << DIRECT_LOOKUP_SHIFT) |
-                                               DIRECT_LOOKUP_BIT;
-                       cp->Tag.upper = 0;
-                       cp->host_addr.lower =
-                               (u32) (h->ioaccel_cmd_pool_dhandle +
+                       cp->tag =
+                               cpu_to_le64((i << DIRECT_LOOKUP_SHIFT) |
+                                               DIRECT_LOOKUP_BIT);
+                       cp->host_addr =
+                               cpu_to_le64(h->ioaccel_cmd_pool_dhandle +
                                        (i * sizeof(struct io_accel1_cmd)));
-                       cp->host_addr.upper = 0;
                }
        } else if (trans_support & CFGTBL_Trans_io_accel2) {
                u64 cfg_offset, cfg_base_addr_index;
@@ -7711,7 +7610,7 @@ static void __attribute__((unused)) verify_offsets(void)
        VERIFY_OFFSET(timeout_sec, 0x62);
        VERIFY_OFFSET(ReplyQueue, 0x64);
        VERIFY_OFFSET(reserved9, 0x65);
-       VERIFY_OFFSET(Tag, 0x68);
+       VERIFY_OFFSET(tag, 0x68);
        VERIFY_OFFSET(host_addr, 0x70);
        VERIFY_OFFSET(CISS_LUN, 0x78);
        VERIFY_OFFSET(SG, 0x78 + 8);
index 24472cec7de34dce8e975c545f45d8c502cf9afb..8e06d9e280ec7dc033f3bf56e8c268393b6c3275 100644 (file)
@@ -118,7 +118,7 @@ struct ctlr_info {
        struct CfgTable __iomem *cfgtable;
        int     interrupts_enabled;
        int     max_commands;
-       int     commands_outstanding;
+       atomic_t commands_outstanding;
 #      define PERF_MODE_INT    0
 #      define DOORBELL_INT     1
 #      define SIMPLE_MODE_INT  2
@@ -164,7 +164,7 @@ struct ctlr_info {
         */
        u32 trans_support;
        u32 trans_offset;
-       struct TransTable_struct *transtable;
+       struct TransTable_struct __iomem *transtable;
        unsigned long transMethod;
 
        /* cap concurrent passthrus at some reasonable maximum */
@@ -181,7 +181,7 @@ struct ctlr_info {
        u32 *blockFetchTable;
        u32 *ioaccel1_blockFetchTable;
        u32 *ioaccel2_blockFetchTable;
-       u32 *ioaccel2_bft2_regs;
+       u32 __iomem *ioaccel2_bft2_regs;
        unsigned char *hba_inquiry_data;
        u32 driver_support;
        u32 fw_support;
@@ -192,7 +192,7 @@ struct ctlr_info {
        u64 last_heartbeat_timestamp;
        u32 heartbeat_sample_interval;
        atomic_t firmware_flash_in_progress;
-       u32 *lockup_detected;
+       u32 __percpu *lockup_detected;
        struct delayed_work monitor_ctlr_work;
        int remove_in_progress;
        u32 fifo_recently_full;
@@ -395,7 +395,7 @@ static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
 static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
 {
        struct reply_queue_buffer *rq = &h->reply_queue[q];
-       unsigned long flags, register_value = FIFO_EMPTY;
+       unsigned long register_value = FIFO_EMPTY;
 
        /* msi auto clears the interrupt pending bit. */
        if (!(h->msi_vector || h->msix_vector)) {
@@ -413,9 +413,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
        if ((rq->head[rq->current_entry] & 1) == rq->wraparound) {
                register_value = rq->head[rq->current_entry];
                rq->current_entry++;
-               spin_lock_irqsave(&h->lock, flags);
-               h->commands_outstanding--;
-               spin_unlock_irqrestore(&h->lock, flags);
+               atomic_dec(&h->commands_outstanding);
        } else {
                register_value = FIFO_EMPTY;
        }
@@ -433,11 +431,7 @@ static unsigned long SA5_performant_completed(struct ctlr_info *h, u8 q)
  */
 static unsigned long SA5_fifo_full(struct ctlr_info *h)
 {
-       if (h->commands_outstanding >= h->max_commands)
-               return 1;
-       else
-               return 0;
-
+       return atomic_read(&h->commands_outstanding) >= h->max_commands;
 }
 /*
  *   returns value read from hardware.
@@ -448,13 +442,9 @@ static unsigned long SA5_completed(struct ctlr_info *h,
 {
        unsigned long register_value
                = readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
-       unsigned long flags;
 
-       if (register_value != FIFO_EMPTY) {
-               spin_lock_irqsave(&h->lock, flags);
-               h->commands_outstanding--;
-               spin_unlock_irqrestore(&h->lock, flags);
-       }
+       if (register_value != FIFO_EMPTY)
+               atomic_dec(&h->commands_outstanding);
 
 #ifdef HPSA_DEBUG
        if (register_value != FIFO_EMPTY)
@@ -510,7 +500,6 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
 {
        u64 register_value;
        struct reply_queue_buffer *rq = &h->reply_queue[q];
-       unsigned long flags;
 
        BUG_ON(q >= h->nreply_queues);
 
@@ -528,9 +517,7 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
                wmb();
                writel((q << 24) | rq->current_entry, h->vaddr +
                                IOACCEL_MODE1_CONSUMER_INDEX);
-               spin_lock_irqsave(&h->lock, flags);
-               h->commands_outstanding--;
-               spin_unlock_irqrestore(&h->lock, flags);
+               atomic_dec(&h->commands_outstanding);
        }
        return (unsigned long) register_value;
 }
index b5125dc3143912233213ff8f83c0d86ddd78efaf..cb988c41cad9153e66134d42ad006ed33cb66380 100644 (file)
@@ -252,7 +252,7 @@ struct ReportExtendedLUNdata {
        u8 LUNListLength[4];
        u8 extended_response_flag;
        u8 reserved[3];
-       struct ext_report_lun_entry LUN[HPSA_MAX_LUN];
+       struct ext_report_lun_entry LUN[HPSA_MAX_PHYS_LUN];
 };
 
 struct SenseSubsystem_info {
@@ -314,28 +314,36 @@ struct CommandListHeader {
        u8              ReplyQueue;
        u8              SGList;
        u16             SGTotal;
-       struct vals32     Tag;
+       u64             tag;
        union LUNAddr     LUN;
 };
 
 struct RequestBlock {
        u8   CDBLen;
-       struct {
-               u8 Type:3;
-               u8 Attribute:3;
-               u8 Direction:2;
-       } Type;
+       /*
+        * type_attr_dir:
+        * type: low 3 bits
+        * attr: middle 3 bits
+        * dir: high 2 bits
+        */
+       u8      type_attr_dir;
+#define TYPE_ATTR_DIR(t, a, d) ((((d) & 0x03) << 6) |\
+                               (((a) & 0x07) << 3) |\
+                               ((t) & 0x07))
+#define GET_TYPE(tad) ((tad) & 0x07)
+#define GET_ATTR(tad) (((tad) >> 3) & 0x07)
+#define GET_DIR(tad) (((tad) >> 6) & 0x03)
        u16  Timeout;
        u8   CDB[16];
 };
 
 struct ErrDescriptor {
-       struct vals32 Addr;
+       u64 Addr;
        u32  Len;
 };
 
 struct SGDescriptor {
-       struct vals32 Addr;
+       u64 Addr;
        u32  Len;
        u32  Ext;
 };
@@ -434,8 +442,8 @@ struct io_accel1_cmd {
        u16 timeout_sec;                /* 0x62 - 0x63 */
        u8  ReplyQueue;                 /* 0x64 */
        u8  reserved9[3];               /* 0x65 - 0x67 */
-       struct vals32 Tag;              /* 0x68 - 0x6F */
-       struct vals32 host_addr;        /* 0x70 - 0x77 */
+       u64 tag;                        /* 0x68 - 0x6F */
+       u64 host_addr;                  /* 0x70 - 0x77 */
        u8  CISS_LUN[8];                /* 0x78 - 0x7F */
        struct SGDescriptor SG[IOACCEL1_MAXSGENTRIES];
 } __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT);
@@ -555,8 +563,8 @@ struct hpsa_tmf_struct {
        u8 reserved1;           /* byte 3 Reserved */
        u32 it_nexus;           /* SCSI I-T Nexus */
        u8 lun_id[8];           /* LUN ID for TMF request */
-       struct vals32 Tag;      /* cciss tag associated w/ request */
-       struct vals32 abort_tag;/* cciss tag of SCSI cmd or task to abort */
+       u64 tag;                /* cciss tag associated w/ request */
+       u64 abort_tag;          /* cciss tag of SCSI cmd or task to abort */
        u64 error_ptr;          /* Error Pointer */
        u32 error_len;          /* Error Length */
 };
index dedb62c21b296f08c86cb9be52f99c2bf7bde253..e995218476edd6677afa2979f4e7dec73bf05c8d 100644 (file)
@@ -1118,17 +1118,13 @@ static int hptiop_reset(struct scsi_cmnd *scp)
 }
 
 static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
-                                         int queue_depth, int reason)
+                                         int queue_depth)
 {
        struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
 
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (queue_depth > hba->max_requests)
                queue_depth = hba->max_requests;
-       scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-       return queue_depth;
+       return scsi_change_queue_depth(sdev, queue_depth);
 }
 
 static ssize_t hptiop_show_version(struct device *dev,
index 598c42cba5a86ab939f8a81ade1057dd8eb512f7..f58c6d8e02644fcae6d2b82d0e6858c24faa3664 100644 (file)
@@ -1643,19 +1643,9 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
        int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
        memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
 
-       if (scsi_populate_tag_msg(cmnd, tag)) {
-               vfc_cmd->task_tag = cpu_to_be64(tag[1]);
-               switch (tag[0]) {
-               case MSG_SIMPLE_TAG:
-                       vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK;
-                       break;
-               case MSG_HEAD_TAG:
-                       vfc_cmd->iu.pri_task_attr = IBMVFC_HEAD_OF_QUEUE;
-                       break;
-               case MSG_ORDERED_TAG:
-                       vfc_cmd->iu.pri_task_attr = IBMVFC_ORDERED_TASK;
-                       break;
-               };
+       if (cmnd->flags & SCMD_TAGGED) {
+               vfc_cmd->task_tag = cpu_to_be64(cmnd->tag);
+               vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK;
        }
 
        if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev))))
@@ -2897,12 +2887,6 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
        spin_lock_irqsave(shost->host_lock, flags);
        if (sdev->type == TYPE_DISK)
                sdev->allow_restart = 1;
-
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
-               scsi_activate_tcq(sdev, sdev->queue_depth);
-       } else
-               scsi_deactivate_tcq(sdev, sdev->queue_depth);
        spin_unlock_irqrestore(shost->host_lock, flags);
        return 0;
 }
@@ -2916,40 +2900,12 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev)
  * Return value:
  *     actual depth set
  **/
-static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth,
-                                    int reason)
+static int ibmvfc_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (qdepth > IBMVFC_MAX_CMDS_PER_LUN)
                qdepth = IBMVFC_MAX_CMDS_PER_LUN;
 
-       scsi_adjust_queue_depth(sdev, 0, qdepth);
-       return sdev->queue_depth;
-}
-
-/**
- * ibmvfc_change_queue_type - Change the device's queue type
- * @sdev:              scsi device struct
- * @tag_type:  type of tags to use
- *
- * Return value:
- *     actual queue type set
- **/
-static int ibmvfc_change_queue_type(struct scsi_device *sdev, int tag_type)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag_type);
-
-               if (tag_type)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag_type = 0;
-
-       return tag_type;
+       return scsi_change_queue_depth(sdev, qdepth);
 }
 
 static ssize_t ibmvfc_show_host_partition_name(struct device *dev,
@@ -3133,7 +3089,7 @@ static struct scsi_host_template driver_template = {
        .target_alloc = ibmvfc_target_alloc,
        .scan_finished = ibmvfc_scan_finished,
        .change_queue_depth = ibmvfc_change_queue_depth,
-       .change_queue_type = ibmvfc_change_queue_type,
+       .change_queue_type = scsi_change_queue_type,
        .cmd_per_lun = 16,
        .can_queue = IBMVFC_MAX_REQUESTS_DEFAULT,
        .this_id = -1,
@@ -3141,6 +3097,8 @@ static struct scsi_host_template driver_template = {
        .max_sectors = IBMVFC_MAX_SECTORS,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = ibmvfc_attrs,
+       .use_blk_tags = 1,
+       .track_queue_depth = 1,
 };
 
 /**
index 7b23f21f22f1717ad77094c21874661f4f535e88..acea5d6eebd0ddf1bbd40b12814479c9382a8168 100644 (file)
@@ -1929,7 +1929,6 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
                blk_queue_rq_timeout(sdev->request_queue, 120 * HZ);
        }
        spin_unlock_irqrestore(shost->host_lock, lock_flags);
-       scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
        return 0;
 }
 
@@ -1942,17 +1941,11 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev)
  * Return value:
  *     actual depth set
  **/
-static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth,
-                                      int reason)
+static int ibmvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (qdepth > IBMVSCSI_MAX_CMDS_PER_LUN)
                qdepth = IBMVSCSI_MAX_CMDS_PER_LUN;
-
-       scsi_adjust_queue_depth(sdev, 0, qdepth);
-       return sdev->queue_depth;
+       return scsi_change_queue_depth(sdev, qdepth);
 }
 
 /* ------------------------------------------------------------
index 2a9578c116b7a8f879b386a58c937bdf2b4d1fc1..5402943893559cb47d3f16a33ebf7db294ee2b74 100644 (file)
@@ -3942,8 +3942,9 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg,
                return -EIO;
        }
 
-       sglist->num_dma_sg = pci_map_sg(ioa_cfg->pdev, sglist->scatterlist,
-                                       sglist->num_sg, DMA_TO_DEVICE);
+       sglist->num_dma_sg = dma_map_sg(&ioa_cfg->pdev->dev,
+                                       sglist->scatterlist, sglist->num_sg,
+                                       DMA_TO_DEVICE);
 
        if (!sglist->num_dma_sg) {
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -4327,16 +4328,12 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
  * Return value:
  *     actual depth set
  **/
-static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
-                                 int reason)
+static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
        struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
        struct ipr_resource_entry *res;
        unsigned long lock_flags = 0;
 
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
        res = (struct ipr_resource_entry *)sdev->hostdata;
 
@@ -4344,7 +4341,7 @@ static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth,
                qdepth = IPR_MAX_CMD_PER_ATA_LUN;
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+       scsi_change_queue_depth(sdev, qdepth);
        return sdev->queue_depth;
 }
 
@@ -4364,24 +4361,10 @@ static int ipr_change_queue_type(struct scsi_device *sdev, int tag_type)
 
        spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
        res = (struct ipr_resource_entry *)sdev->hostdata;
-
-       if (res) {
-               if (ipr_is_gscsi(res) && sdev->tagged_supported) {
-                       /*
-                        * We don't bother quiescing the device here since the
-                        * adapter firmware does it for us.
-                        */
-                       scsi_set_tag_type(sdev, tag_type);
-
-                       if (tag_type)
-                               scsi_activate_tcq(sdev, sdev->queue_depth);
-                       else
-                               scsi_deactivate_tcq(sdev, sdev->queue_depth);
-               } else
-                       tag_type = 0;
-       } else
+       if (res && ipr_is_gscsi(res))
+               tag_type = scsi_change_queue_type(sdev, tag_type);
+       else
                tag_type = 0;
-
        spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
        return tag_type;
 }
@@ -4765,10 +4748,10 @@ static int ipr_slave_configure(struct scsi_device *sdev)
                spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
                if (ap) {
-                       scsi_adjust_queue_depth(sdev, 0, IPR_MAX_CMD_PER_ATA_LUN);
+                       scsi_change_queue_depth(sdev, IPR_MAX_CMD_PER_ATA_LUN);
                        ata_sas_slave_configure(sdev, ap);
-               } else
-                       scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+               }
+
                if (ioa_cfg->sis64)
                        sdev_printk(KERN_INFO, sdev, "Resource path: %s\n",
                                    ipr_format_res_path(ioa_cfg,
@@ -5585,7 +5568,7 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg,
        nseg = scsi_dma_map(scsi_cmd);
        if (nseg < 0) {
                if (printk_ratelimit())
-                       dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+                       dev_err(&ioa_cfg->pdev->dev, "scsi_dma_map failed!\n");
                return -1;
        }
 
@@ -5636,7 +5619,7 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
 
        nseg = scsi_dma_map(scsi_cmd);
        if (nseg < 0) {
-               dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n");
+               dev_err(&ioa_cfg->pdev->dev, "scsi_dma_map failed!\n");
                return -1;
        }
 
@@ -5672,35 +5655,6 @@ static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg,
        return 0;
 }
 
-/**
- * ipr_get_task_attributes - Translate SPI Q-Tag to task attributes
- * @scsi_cmd:  scsi command struct
- *
- * Return value:
- *     task attributes
- **/
-static u8 ipr_get_task_attributes(struct scsi_cmnd *scsi_cmd)
-{
-       u8 tag[2];
-       u8 rc = IPR_FLAGS_LO_UNTAGGED_TASK;
-
-       if (scsi_populate_tag_msg(scsi_cmd, tag)) {
-               switch (tag[0]) {
-               case MSG_SIMPLE_TAG:
-                       rc = IPR_FLAGS_LO_SIMPLE_TASK;
-                       break;
-               case MSG_HEAD_TAG:
-                       rc = IPR_FLAGS_LO_HEAD_OF_Q_TASK;
-                       break;
-               case MSG_ORDERED_TAG:
-                       rc = IPR_FLAGS_LO_ORDERED_TASK;
-                       break;
-               };
-       }
-
-       return rc;
-}
-
 /**
  * ipr_erp_done - Process completion of ERP for a device
  * @ipr_cmd:           ipr command struct
@@ -6236,7 +6190,10 @@ static int ipr_queuecommand(struct Scsi_Host *shost,
                        ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST;
                }
                ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR;
-               ioarcb->cmd_pkt.flags_lo |= ipr_get_task_attributes(scsi_cmd);
+               if (scsi_cmd->flags & SCMD_TAGGED)
+                       ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_SIMPLE_TASK;
+               else
+                       ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_UNTAGGED_TASK;
        }
 
        if (scsi_cmd->cmnd[0] >= 0xC0 &&
@@ -6357,6 +6314,7 @@ static struct scsi_host_template driver_template = {
        .sdev_attrs = ipr_dev_attrs,
        .proc_name = IPR_NAME,
        .no_write_same = 1,
+       .use_blk_tags = 1,
 };
 
 /**
@@ -8431,7 +8389,7 @@ static int ipr_reset_ucode_download_done(struct ipr_cmnd *ipr_cmd)
        struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
        struct ipr_sglist *sglist = ioa_cfg->ucode_sglist;
 
-       pci_unmap_sg(ioa_cfg->pdev, sglist->scatterlist,
+       dma_unmap_sg(&ioa_cfg->pdev->dev, sglist->scatterlist,
                     sglist->num_sg, DMA_TO_DEVICE);
 
        ipr_cmd->job_step = ipr_reset_alert;
@@ -8871,7 +8829,7 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
 
        for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
                if (ioa_cfg->ipr_cmnd_list[i])
-                       pci_pool_free(ioa_cfg->ipr_cmd_pool,
+                       dma_pool_free(ioa_cfg->ipr_cmd_pool,
                                      ioa_cfg->ipr_cmnd_list[i],
                                      ioa_cfg->ipr_cmnd_list_dma[i]);
 
@@ -8879,7 +8837,7 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
        }
 
        if (ioa_cfg->ipr_cmd_pool)
-               pci_pool_destroy(ioa_cfg->ipr_cmd_pool);
+               dma_pool_destroy(ioa_cfg->ipr_cmd_pool);
 
        kfree(ioa_cfg->ipr_cmnd_list);
        kfree(ioa_cfg->ipr_cmnd_list_dma);
@@ -8900,25 +8858,24 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
        int i;
 
        kfree(ioa_cfg->res_entries);
-       pci_free_consistent(ioa_cfg->pdev, sizeof(struct ipr_misc_cbs),
-                           ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
+       dma_free_coherent(&ioa_cfg->pdev->dev, sizeof(struct ipr_misc_cbs),
+                         ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
        ipr_free_cmd_blks(ioa_cfg);
 
        for (i = 0; i < ioa_cfg->hrrq_num; i++)
-               pci_free_consistent(ioa_cfg->pdev,
-                                       sizeof(u32) * ioa_cfg->hrrq[i].size,
-                                       ioa_cfg->hrrq[i].host_rrq,
-                                       ioa_cfg->hrrq[i].host_rrq_dma);
+               dma_free_coherent(&ioa_cfg->pdev->dev,
+                                 sizeof(u32) * ioa_cfg->hrrq[i].size,
+                                 ioa_cfg->hrrq[i].host_rrq,
+                                 ioa_cfg->hrrq[i].host_rrq_dma);
 
-       pci_free_consistent(ioa_cfg->pdev, ioa_cfg->cfg_table_size,
-                           ioa_cfg->u.cfg_table,
-                           ioa_cfg->cfg_table_dma);
+       dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size,
+                         ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma);
 
        for (i = 0; i < IPR_NUM_HCAMS; i++) {
-               pci_free_consistent(ioa_cfg->pdev,
-                                   sizeof(struct ipr_hostrcb),
-                                   ioa_cfg->hostrcb[i],
-                                   ioa_cfg->hostrcb_dma[i]);
+               dma_free_coherent(&ioa_cfg->pdev->dev,
+                                 sizeof(struct ipr_hostrcb),
+                                 ioa_cfg->hostrcb[i],
+                                 ioa_cfg->hostrcb_dma[i]);
        }
 
        ipr_free_dump(ioa_cfg);
@@ -8979,7 +8936,7 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
        dma_addr_t dma_addr;
        int i, entries_each_hrrq, hrrq_id = 0;
 
-       ioa_cfg->ipr_cmd_pool = pci_pool_create(IPR_NAME, ioa_cfg->pdev,
+       ioa_cfg->ipr_cmd_pool = dma_pool_create(IPR_NAME, &ioa_cfg->pdev->dev,
                                                sizeof(struct ipr_cmnd), 512, 0);
 
        if (!ioa_cfg->ipr_cmd_pool)
@@ -9029,7 +8986,7 @@ static int ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
        }
 
        for (i = 0; i < IPR_NUM_CMD_BLKS; i++) {
-               ipr_cmd = pci_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
+               ipr_cmd = dma_pool_alloc(ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr);
 
                if (!ipr_cmd) {
                        ipr_free_cmd_blks(ioa_cfg);
@@ -9100,9 +9057,10 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
                ioa_cfg->res_entries[i].ioa_cfg = ioa_cfg;
        }
 
-       ioa_cfg->vpd_cbs = pci_alloc_consistent(ioa_cfg->pdev,
-                                               sizeof(struct ipr_misc_cbs),
-                                               &ioa_cfg->vpd_cbs_dma);
+       ioa_cfg->vpd_cbs = dma_alloc_coherent(&pdev->dev,
+                                             sizeof(struct ipr_misc_cbs),
+                                             &ioa_cfg->vpd_cbs_dma,
+                                             GFP_KERNEL);
 
        if (!ioa_cfg->vpd_cbs)
                goto out_free_res_entries;
@@ -9111,13 +9069,14 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
                goto out_free_vpd_cbs;
 
        for (i = 0; i < ioa_cfg->hrrq_num; i++) {
-               ioa_cfg->hrrq[i].host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
+               ioa_cfg->hrrq[i].host_rrq = dma_alloc_coherent(&pdev->dev,
                                        sizeof(u32) * ioa_cfg->hrrq[i].size,
-                                       &ioa_cfg->hrrq[i].host_rrq_dma);
+                                       &ioa_cfg->hrrq[i].host_rrq_dma,
+                                       GFP_KERNEL);
 
                if (!ioa_cfg->hrrq[i].host_rrq)  {
                        while (--i > 0)
-                               pci_free_consistent(pdev,
+                               dma_free_coherent(&pdev->dev,
                                        sizeof(u32) * ioa_cfg->hrrq[i].size,
                                        ioa_cfg->hrrq[i].host_rrq,
                                        ioa_cfg->hrrq[i].host_rrq_dma);
@@ -9126,17 +9085,19 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
                ioa_cfg->hrrq[i].ioa_cfg = ioa_cfg;
        }
 
-       ioa_cfg->u.cfg_table = pci_alloc_consistent(ioa_cfg->pdev,
-                                                   ioa_cfg->cfg_table_size,
-                                                   &ioa_cfg->cfg_table_dma);
+       ioa_cfg->u.cfg_table = dma_alloc_coherent(&pdev->dev,
+                                                 ioa_cfg->cfg_table_size,
+                                                 &ioa_cfg->cfg_table_dma,
+                                                 GFP_KERNEL);
 
        if (!ioa_cfg->u.cfg_table)
                goto out_free_host_rrq;
 
        for (i = 0; i < IPR_NUM_HCAMS; i++) {
-               ioa_cfg->hostrcb[i] = pci_alloc_consistent(ioa_cfg->pdev,
-                                                          sizeof(struct ipr_hostrcb),
-                                                          &ioa_cfg->hostrcb_dma[i]);
+               ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev,
+                                                        sizeof(struct ipr_hostrcb),
+                                                        &ioa_cfg->hostrcb_dma[i],
+                                                        GFP_KERNEL);
 
                if (!ioa_cfg->hostrcb[i])
                        goto out_free_hostrcb_dma;
@@ -9160,25 +9121,24 @@ out:
 
 out_free_hostrcb_dma:
        while (i-- > 0) {
-               pci_free_consistent(pdev, sizeof(struct ipr_hostrcb),
-                                   ioa_cfg->hostrcb[i],
-                                   ioa_cfg->hostrcb_dma[i]);
+               dma_free_coherent(&pdev->dev, sizeof(struct ipr_hostrcb),
+                                 ioa_cfg->hostrcb[i],
+                                 ioa_cfg->hostrcb_dma[i]);
        }
-       pci_free_consistent(pdev, ioa_cfg->cfg_table_size,
-                           ioa_cfg->u.cfg_table,
-                           ioa_cfg->cfg_table_dma);
+       dma_free_coherent(&pdev->dev, ioa_cfg->cfg_table_size,
+                         ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma);
 out_free_host_rrq:
        for (i = 0; i < ioa_cfg->hrrq_num; i++) {
-               pci_free_consistent(pdev,
-                               sizeof(u32) * ioa_cfg->hrrq[i].size,
-                               ioa_cfg->hrrq[i].host_rrq,
-                               ioa_cfg->hrrq[i].host_rrq_dma);
+               dma_free_coherent(&pdev->dev,
+                                 sizeof(u32) * ioa_cfg->hrrq[i].size,
+                                 ioa_cfg->hrrq[i].host_rrq,
+                                 ioa_cfg->hrrq[i].host_rrq_dma);
        }
 out_ipr_free_cmd_blocks:
        ipr_free_cmd_blks(ioa_cfg);
 out_free_vpd_cbs:
-       pci_free_consistent(pdev, sizeof(struct ipr_misc_cbs),
-                           ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
+       dma_free_coherent(&pdev->dev, sizeof(struct ipr_misc_cbs),
+                         ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
 out_free_res_entries:
        kfree(ioa_cfg->res_entries);
        goto out;
@@ -9618,16 +9578,17 @@ static int ipr_probe_ioa(struct pci_dev *pdev,
        ipr_init_regs(ioa_cfg);
 
        if (ioa_cfg->sis64) {
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+               rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
                if (rc < 0) {
-                       dev_dbg(&pdev->dev, "Failed to set 64 bit PCI DMA mask\n");
-                       rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+                       dev_dbg(&pdev->dev, "Failed to set 64 bit DMA mask\n");
+                       rc = dma_set_mask_and_coherent(&pdev->dev,
+                                                      DMA_BIT_MASK(32));
                }
        } else
-               rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
 
        if (rc < 0) {
-               dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
+               dev_err(&pdev->dev, "Failed to set DMA mask\n");
                goto cleanup_nomem;
        }
 
index d0201ceb4aacd12018523a6e3fcac7586862ffab..9ebdebd944e7b3cf94a970ab41117b6e8aacadbe 100644 (file)
@@ -1549,7 +1549,7 @@ struct ipr_ioa_cfg {
        struct ipr_misc_cbs *vpd_cbs;
        dma_addr_t vpd_cbs_dma;
 
-       struct pci_pool *ipr_cmd_pool;
+       struct dma_pool *ipr_cmd_pool;
 
        struct ipr_cmnd *reset_cmd;
        int (*reset) (struct ipr_cmnd *);
index e5afc3884d74a68a3f180188edb3fb75c5fba762..e5c28435d768113aa1f63ccffaa46f29749312b5 100644 (file)
@@ -1210,7 +1210,7 @@ ips_slave_configure(struct scsi_device * SDptr)
                min = ha->max_cmds / 2;
                if (ha->enq->ucLogDriveCount <= 2)
                        min = ha->max_cmds - 1;
-               scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
+               scsi_change_queue_depth(SDptr, min);
        }
 
        SDptr->skip_ms_page_8 = 1;
index 2e890b1e2526ba256a86d2228ac01ede29aa8abf..724c6265b667a559c762c5b930caa60c6558f962 100644 (file)
@@ -172,6 +172,8 @@ static struct scsi_host_template isci_sht = {
        .target_destroy                 = sas_target_destroy,
        .ioctl                          = sas_ioctl,
        .shost_attrs                    = isci_host_attrs,
+       .use_blk_tags                   = 1,
+       .track_queue_depth              = 1,
 };
 
 static struct sas_domain_function_template isci_transport_ops  = {
@@ -258,8 +260,6 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
        sas_ha->sas_port = sas_ports;
        sas_ha->num_phys = SCI_MAX_PHYS;
 
-       sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL;
-       sas_ha->lldd_max_execute_num = 1;
        sas_ha->strict_wide_ports = 1;
 
        sas_register_ha(sas_ha);
index 5d6fda72d659770d080e2c4201c4d3e6c7af1adc..3f63c6318b0d928216f995b2fcc4aa31844ca8be 100644 (file)
@@ -117,104 +117,97 @@ static inline int isci_device_io_ready(struct isci_remote_device *idev,
  *    functions. This function is called by libsas to send a task down to
  *    hardware.
  * @task: This parameter specifies the SAS task to send.
- * @num: This parameter specifies the number of tasks to queue.
  * @gfp_flags: This parameter specifies the context of this call.
  *
  * status, zero indicates success.
  */
-int isci_task_execute_task(struct sas_task *task, int num, gfp_t gfp_flags)
+int isci_task_execute_task(struct sas_task *task, gfp_t gfp_flags)
 {
        struct isci_host *ihost = dev_to_ihost(task->dev);
        struct isci_remote_device *idev;
        unsigned long flags;
+       enum sci_status status = SCI_FAILURE;
        bool io_ready;
        u16 tag;
 
-       dev_dbg(&ihost->pdev->dev, "%s: num=%d\n", __func__, num);
+       spin_lock_irqsave(&ihost->scic_lock, flags);
+       idev = isci_lookup_device(task->dev);
+       io_ready = isci_device_io_ready(idev, task);
+       tag = isci_alloc_tag(ihost);
+       spin_unlock_irqrestore(&ihost->scic_lock, flags);
 
-       for_each_sas_task(num, task) {
-               enum sci_status status = SCI_FAILURE;
+       dev_dbg(&ihost->pdev->dev,
+               "task: %p, dev: %p idev: %p:%#lx cmd = %p\n",
+               task, task->dev, idev, idev ? idev->flags : 0,
+               task->uldd_task);
 
-               spin_lock_irqsave(&ihost->scic_lock, flags);
-               idev = isci_lookup_device(task->dev);
-               io_ready = isci_device_io_ready(idev, task);
-               tag = isci_alloc_tag(ihost);
-               spin_unlock_irqrestore(&ihost->scic_lock, flags);
+       if (!idev) {
+               isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
+                                SAS_DEVICE_UNKNOWN);
+       } else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
+               /* Indicate QUEUE_FULL so that the scsi midlayer
+                * retries.
+                 */
+               isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
+                                SAS_QUEUE_FULL);
+       } else {
+               /* There is a device and it's ready for I/O. */
+               spin_lock_irqsave(&task->task_state_lock, flags);
 
-               dev_dbg(&ihost->pdev->dev,
-                       "task: %p, num: %d dev: %p idev: %p:%#lx cmd = %p\n",
-                       task, num, task->dev, idev, idev ? idev->flags : 0,
-                       task->uldd_task);
-
-               if (!idev) {
-                       isci_task_refuse(ihost, task, SAS_TASK_UNDELIVERED,
-                                        SAS_DEVICE_UNKNOWN);
-               } else if (!io_ready || tag == SCI_CONTROLLER_INVALID_IO_TAG) {
-                       /* Indicate QUEUE_FULL so that the scsi midlayer
-                        * retries.
-                         */
-                       isci_task_refuse(ihost, task, SAS_TASK_COMPLETE,
-                                        SAS_QUEUE_FULL);
+               if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+                       /* The I/O was aborted. */
+                       spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+                       isci_task_refuse(ihost, task,
+                                        SAS_TASK_UNDELIVERED,
+                                        SAM_STAT_TASK_ABORTED);
                } else {
-                       /* There is a device and it's ready for I/O. */
-                       spin_lock_irqsave(&task->task_state_lock, flags);
-
-                       if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
-                               /* The I/O was aborted. */
-                               spin_unlock_irqrestore(&task->task_state_lock,
-                                                      flags);
-
-                               isci_task_refuse(ihost, task,
-                                                SAS_TASK_UNDELIVERED,
-                                                SAM_STAT_TASK_ABORTED);
-                       } else {
-                               task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+                       task->task_state_flags |= SAS_TASK_AT_INITIATOR;
+                       spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+                       /* build and send the request. */
+                       status = isci_request_execute(ihost, idev, task, tag);
+
+                       if (status != SCI_SUCCESS) {
+                               spin_lock_irqsave(&task->task_state_lock, flags);
+                               /* Did not really start this command. */
+                               task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
                                spin_unlock_irqrestore(&task->task_state_lock, flags);
 
-                               /* build and send the request. */
-                               status = isci_request_execute(ihost, idev, task, tag);
-
-                               if (status != SCI_SUCCESS) {
-
-                                       spin_lock_irqsave(&task->task_state_lock, flags);
-                                       /* Did not really start this command. */
-                                       task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
-                                       spin_unlock_irqrestore(&task->task_state_lock, flags);
-
-                                       if (test_bit(IDEV_GONE, &idev->flags)) {
-
-                                               /* Indicate that the device
-                                                * is gone.
-                                                */
-                                               isci_task_refuse(ihost, task,
-                                                       SAS_TASK_UNDELIVERED,
-                                                       SAS_DEVICE_UNKNOWN);
-                                       } else {
-                                               /* Indicate QUEUE_FULL so that
-                                                * the scsi midlayer retries.
-                                                * If the request failed for
-                                                * remote device reasons, it
-                                                * gets returned as
-                                                * SAS_TASK_UNDELIVERED next
-                                                * time through.
-                                                */
-                                               isci_task_refuse(ihost, task,
-                                                       SAS_TASK_COMPLETE,
-                                                       SAS_QUEUE_FULL);
-                                       }
+                               if (test_bit(IDEV_GONE, &idev->flags)) {
+                                       /* Indicate that the device
+                                        * is gone.
+                                        */
+                                       isci_task_refuse(ihost, task,
+                                               SAS_TASK_UNDELIVERED,
+                                               SAS_DEVICE_UNKNOWN);
+                               } else {
+                                       /* Indicate QUEUE_FULL so that
+                                        * the scsi midlayer retries.
+                                        * If the request failed for
+                                        * remote device reasons, it
+                                        * gets returned as
+                                        * SAS_TASK_UNDELIVERED next
+                                        * time through.
+                                        */
+                                       isci_task_refuse(ihost, task,
+                                               SAS_TASK_COMPLETE,
+                                               SAS_QUEUE_FULL);
                                }
                        }
                }
-               if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) {
-                       spin_lock_irqsave(&ihost->scic_lock, flags);
-                       /* command never hit the device, so just free
-                        * the tci and skip the sequence increment
-                        */
-                       isci_tci_free(ihost, ISCI_TAG_TCI(tag));
-                       spin_unlock_irqrestore(&ihost->scic_lock, flags);
-               }
-               isci_put_device(idev);
        }
+
+       if (status != SCI_SUCCESS && tag != SCI_CONTROLLER_INVALID_IO_TAG) {
+               spin_lock_irqsave(&ihost->scic_lock, flags);
+               /* command never hit the device, so just free
+                * the tci and skip the sequence increment
+                */
+               isci_tci_free(ihost, ISCI_TAG_TCI(tag));
+               spin_unlock_irqrestore(&ihost->scic_lock, flags);
+       }
+
+       isci_put_device(idev);
        return 0;
 }
 
index 9c06cbad1d26cad25e99a3cc4a33969193379ca7..8f4531f22ac29372332c0b4be250dc5b28b6851c 100644 (file)
@@ -131,7 +131,6 @@ static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)
 
 int isci_task_execute_task(
        struct sas_task *task,
-       int num,
        gfp_t gfp_flags);
 
 int isci_task_abort_task(
index 427af0f24b0f2bdde43e39cdf3334518f89d2b8e..0b8af186e70783e9c8318d9158b177ba25890ff3 100644 (file)
@@ -952,7 +952,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
        .module                 = THIS_MODULE,
        .name                   = "iSCSI Initiator over TCP/IP",
        .queuecommand           = iscsi_queuecommand,
-       .change_queue_depth     = iscsi_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
        .can_queue              = ISCSI_DEF_XMIT_CMDS_MAX - 1,
        .sg_tablesize           = 4096,
        .max_sectors            = 0xFFFF,
@@ -966,6 +966,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
        .target_alloc           = iscsi_target_alloc,
        .proc_name              = "iscsi_tcp",
        .this_id                = -1,
+       .track_queue_depth      = 1,
 };
 
 static struct iscsi_transport iscsi_sw_tcp_transport = {
index 1d7e76e8b447c7d8a6e42eb652a8f607277f070d..c6795941b45d98579cd6117cc5b72f8c5c4d0bf9 100644 (file)
@@ -2160,61 +2160,11 @@ int fc_slave_alloc(struct scsi_device *sdev)
        if (!rport || fc_remote_port_chkready(rport))
                return -ENXIO;
 
-       if (sdev->tagged_supported)
-               scsi_activate_tcq(sdev, FC_FCP_DFLT_QUEUE_DEPTH);
-       else
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev),
-                                       FC_FCP_DFLT_QUEUE_DEPTH);
-
+       scsi_change_queue_depth(sdev, FC_FCP_DFLT_QUEUE_DEPTH);
        return 0;
 }
 EXPORT_SYMBOL(fc_slave_alloc);
 
-/**
- * fc_change_queue_depth() - Change a device's queue depth
- * @sdev:   The SCSI device whose queue depth is to change
- * @qdepth: The new queue depth
- * @reason: The resason for the change
- */
-int fc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               scsi_track_queue_full(sdev, qdepth);
-               break;
-       case SCSI_QDEPTH_RAMP_UP:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-       return sdev->queue_depth;
-}
-EXPORT_SYMBOL(fc_change_queue_depth);
-
-/**
- * fc_change_queue_type() - Change a device's queue type
- * @sdev:     The SCSI device whose queue depth is to change
- * @tag_type: Identifier for queue type
- */
-int fc_change_queue_type(struct scsi_device *sdev, int tag_type)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag_type);
-               if (tag_type)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag_type = 0;
-
-       return tag_type;
-}
-EXPORT_SYMBOL(fc_change_queue_type);
-
 /**
  * fc_fcp_destory() - Tear down the FCP layer for a given local port
  * @lport: The local port that no longer needs the FCP layer
index 0d8bc6c666508a3c1ee3ab8b6b3a14379c4526eb..8053f24f03499335112721cd50c2816da40393a6 100644 (file)
@@ -1771,25 +1771,6 @@ fault:
 }
 EXPORT_SYMBOL_GPL(iscsi_queuecommand);
 
-int iscsi_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
-{
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               scsi_track_queue_full(sdev, depth);
-               break;
-       case SCSI_QDEPTH_RAMP_UP:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-       return sdev->queue_depth;
-}
-EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
-
 int iscsi_target_alloc(struct scsi_target *starget)
 {
        struct iscsi_cls_session *cls_session = starget_to_session(starget);
index 766098af4eb79aebf8f080b6906db8aeade896e7..577770fdee8673aadb3ce1d62b308d52018e87f7 100644 (file)
@@ -171,7 +171,6 @@ static void sas_ata_task_done(struct sas_task *task)
        spin_unlock_irqrestore(ap->lock, flags);
 
 qc_already_gone:
-       list_del_init(&task->list);
        sas_free_task(task);
 }
 
@@ -244,12 +243,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
        if (qc->scsicmd)
                ASSIGN_SAS_TASK(qc->scsicmd, task);
 
-       if (sas_ha->lldd_max_execute_num < 2)
-               ret = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
-       else
-               ret = sas_queue_up(task);
-
-       /* Examine */
+       ret = i->dft->lldd_execute_task(task, GFP_ATOMIC);
        if (ret) {
                SAS_DPRINTK("lldd_execute_task returned: %d\n", ret);
 
@@ -485,7 +479,6 @@ static void sas_ata_internal_abort(struct sas_task *task)
 
        return;
  out:
-       list_del_init(&task->list);
        sas_free_task(task);
 }
 
index 0cac7d8fd0f7cac75b0ecc2d63662d18eeda4a56..022bb6e10d985b69839753ac9521f9b5b1562320 100644 (file)
@@ -96,7 +96,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
                task->slow_task->timer.expires = jiffies + SMP_TIMEOUT*HZ;
                add_timer(&task->slow_task->timer);
 
-               res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL);
+               res = i->dft->lldd_execute_task(task, GFP_KERNEL);
 
                if (res) {
                        del_timer(&task->slow_task->timer);
index dbc8a793fd867dcd1f24e55e1d79aab836530b0f..362da44f2948eb3533cef40cb1b72da0625f1b05 100644 (file)
@@ -45,7 +45,6 @@ struct sas_task *sas_alloc_task(gfp_t flags)
        struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
 
        if (task) {
-               INIT_LIST_HEAD(&task->list);
                spin_lock_init(&task->task_state_lock);
                task->task_state_flags = SAS_TASK_STATE_PENDING;
        }
@@ -77,7 +76,6 @@ EXPORT_SYMBOL_GPL(sas_alloc_slow_task);
 void sas_free_task(struct sas_task *task)
 {
        if (task) {
-               BUG_ON(!list_empty(&task->list));
                kfree(task->slow_task);
                kmem_cache_free(sas_task_cache, task);
        }
@@ -127,11 +125,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
        spin_lock_init(&sas_ha->phy_port_lock);
        sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr);
 
-       if (sas_ha->lldd_queue_size == 0)
-               sas_ha->lldd_queue_size = 1;
-       else if (sas_ha->lldd_queue_size == -1)
-               sas_ha->lldd_queue_size = 128; /* Sanity */
-
        set_bit(SAS_HA_REGISTERED, &sas_ha->state);
        spin_lock_init(&sas_ha->lock);
        mutex_init(&sas_ha->drain_mutex);
@@ -157,15 +150,6 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
                goto Undo_ports;
        }
 
-       if (sas_ha->lldd_max_execute_num > 1) {
-               error = sas_init_queue(sas_ha);
-               if (error) {
-                       printk(KERN_NOTICE "couldn't start queue thread:%d, "
-                              "running in direct mode\n", error);
-                       sas_ha->lldd_max_execute_num = 1;
-               }
-       }
-
        INIT_LIST_HEAD(&sas_ha->eh_done_q);
        INIT_LIST_HEAD(&sas_ha->eh_ata_q);
 
@@ -201,11 +185,6 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
        __sas_drain_work(sas_ha);
        mutex_unlock(&sas_ha->drain_mutex);
 
-       if (sas_ha->lldd_max_execute_num > 1) {
-               sas_shutdown_queue(sas_ha);
-               sas_ha->lldd_max_execute_num = 1;
-       }
-
        return 0;
 }
 
index 7e7ba83f0a2139c565f692fa93d0b3f5954abcce..9cf0bc260b0e78ac3c929aafc00315cbad819caa 100644 (file)
@@ -66,9 +66,7 @@ void sas_unregister_ports(struct sas_ha_struct *sas_ha);
 
 enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
 
-int  sas_init_queue(struct sas_ha_struct *sas_ha);
 int  sas_init_events(struct sas_ha_struct *sas_ha);
-void sas_shutdown_queue(struct sas_ha_struct *sas_ha);
 void sas_disable_revalidation(struct sas_ha_struct *ha);
 void sas_enable_revalidation(struct sas_ha_struct *ha);
 void __sas_drain_work(struct sas_ha_struct *ha);
index 24e477d2ea701d97a9afe69bf48831cbb8c8cf66..72918d227ead30811a0b43f95d6942f7b7d191fe 100644 (file)
@@ -112,7 +112,6 @@ static void sas_end_task(struct scsi_cmnd *sc, struct sas_task *task)
 
        sc->result = (hs << 16) | stat;
        ASSIGN_SAS_TASK(sc, NULL);
-       list_del_init(&task->list);
        sas_free_task(task);
 }
 
@@ -138,7 +137,6 @@ static void sas_scsi_task_done(struct sas_task *task)
 
        if (unlikely(!sc)) {
                SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n");
-               list_del_init(&task->list);
                sas_free_task(task);
                return;
        }
@@ -179,31 +177,10 @@ static struct sas_task *sas_create_task(struct scsi_cmnd *cmd,
        return task;
 }
 
-int sas_queue_up(struct sas_task *task)
-{
-       struct sas_ha_struct *sas_ha = task->dev->port->ha;
-       struct scsi_core *core = &sas_ha->core;
-       unsigned long flags;
-       LIST_HEAD(list);
-
-       spin_lock_irqsave(&core->task_queue_lock, flags);
-       if (sas_ha->lldd_queue_size < core->task_queue_size + 1) {
-               spin_unlock_irqrestore(&core->task_queue_lock, flags);
-               return -SAS_QUEUE_FULL;
-       }
-       list_add_tail(&task->list, &core->task_queue);
-       core->task_queue_size += 1;
-       spin_unlock_irqrestore(&core->task_queue_lock, flags);
-       wake_up_process(core->queue_thread);
-
-       return 0;
-}
-
 int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 {
        struct sas_internal *i = to_sas_internal(host->transportt);
        struct domain_device *dev = cmd_to_domain_dev(cmd);
-       struct sas_ha_struct *sas_ha = dev->port->ha;
        struct sas_task *task;
        int res = 0;
 
@@ -224,12 +201,7 @@ int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
        if (!task)
                return SCSI_MLQUEUE_HOST_BUSY;
 
-       /* Queue up, Direct Mode or Task Collector Mode. */
-       if (sas_ha->lldd_max_execute_num < 2)
-               res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
-       else
-               res = sas_queue_up(task);
-
+       res = i->dft->lldd_execute_task(task, GFP_ATOMIC);
        if (res)
                goto out_free_task;
        return 0;
@@ -323,37 +295,17 @@ enum task_disposition {
        TASK_IS_DONE,
        TASK_IS_ABORTED,
        TASK_IS_AT_LU,
-       TASK_IS_NOT_AT_HA,
        TASK_IS_NOT_AT_LU,
        TASK_ABORT_FAILED,
 };
 
 static enum task_disposition sas_scsi_find_task(struct sas_task *task)
 {
-       struct sas_ha_struct *ha = task->dev->port->ha;
        unsigned long flags;
        int i, res;
        struct sas_internal *si =
                to_sas_internal(task->dev->port->ha->core.shost->transportt);
 
-       if (ha->lldd_max_execute_num > 1) {
-               struct scsi_core *core = &ha->core;
-               struct sas_task *t, *n;
-
-               mutex_lock(&core->task_queue_flush);
-               spin_lock_irqsave(&core->task_queue_lock, flags);
-               list_for_each_entry_safe(t, n, &core->task_queue, list)
-                       if (task == t) {
-                               list_del_init(&t->list);
-                               break;
-                       }
-               spin_unlock_irqrestore(&core->task_queue_lock, flags);
-               mutex_unlock(&core->task_queue_flush);
-
-               if (task == t)
-                       return TASK_IS_NOT_AT_HA;
-       }
-
        for (i = 0; i < 5; i++) {
                SAS_DPRINTK("%s: aborting task 0x%p\n", __func__, task);
                res = si->dft->lldd_abort_task(task);
@@ -667,14 +619,6 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head *
                cmd->eh_eflags = 0;
 
                switch (res) {
-               case TASK_IS_NOT_AT_HA:
-                       SAS_DPRINTK("%s: task 0x%p is not at ha: %s\n",
-                                   __func__, task,
-                                   cmd->retries ? "retry" : "aborted");
-                       if (cmd->retries)
-                               cmd->retries--;
-                       sas_eh_finish_cmd(cmd);
-                       continue;
                case TASK_IS_DONE:
                        SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
                                    task);
@@ -836,9 +780,6 @@ retry:
                scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
 
 out:
-       if (ha->lldd_max_execute_num > 1)
-               wake_up_process(ha->core.queue_thread);
-
        sas_eh_handle_resets(shost);
 
        /* now link into libata eh --- if we have any ata devices */
@@ -940,15 +881,12 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
        sas_read_port_mode_page(scsi_dev);
 
        if (scsi_dev->tagged_supported) {
-               scsi_set_tag_type(scsi_dev, MSG_SIMPLE_TAG);
-               scsi_activate_tcq(scsi_dev, SAS_DEF_QD);
+               scsi_change_queue_depth(scsi_dev, SAS_DEF_QD);
        } else {
                SAS_DPRINTK("device %llx, LUN %llx doesn't support "
                            "TCQ\n", SAS_ADDR(dev->sas_addr),
                            scsi_dev->lun);
-               scsi_dev->tagged_supported = 0;
-               scsi_set_tag_type(scsi_dev, 0);
-               scsi_deactivate_tcq(scsi_dev, 1);
+               scsi_change_queue_depth(scsi_dev, 1);
        }
 
        scsi_dev->allow_restart = 1;
@@ -956,47 +894,23 @@ int sas_slave_configure(struct scsi_device *scsi_dev)
        return 0;
 }
 
-int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
+int sas_change_queue_depth(struct scsi_device *sdev, int depth)
 {
        struct domain_device *dev = sdev_to_domain_dev(sdev);
 
        if (dev_is_sata(dev))
-               return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth,
-                                               reason);
-
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-       case SCSI_QDEPTH_RAMP_UP:
-               if (!sdev->tagged_supported)
-                       depth = 1;
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               scsi_track_queue_full(sdev, depth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
+               return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
 
-       return depth;
+       if (!sdev->tagged_supported)
+               depth = 1;
+       return scsi_change_queue_depth(sdev, depth);
 }
 
-int sas_change_queue_type(struct scsi_device *scsi_dev, int qt)
+int sas_change_queue_type(struct scsi_device *scsi_dev, int type)
 {
-       struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
-
-       if (dev_is_sata(dev))
+       if (dev_is_sata(sdev_to_domain_dev(scsi_dev)))
                return -EINVAL;
-
-       if (!scsi_dev->tagged_supported)
-               return 0;
-
-       scsi_deactivate_tcq(scsi_dev, 1);
-
-       scsi_set_tag_type(scsi_dev, qt);
-       scsi_activate_tcq(scsi_dev, scsi_dev->queue_depth);
-
-       return qt;
+       return scsi_change_queue_type(scsi_dev, type);
 }
 
 int sas_bios_param(struct scsi_device *scsi_dev,
@@ -1011,121 +925,6 @@ int sas_bios_param(struct scsi_device *scsi_dev,
        return 0;
 }
 
-/* ---------- Task Collector Thread implementation ---------- */
-
-static void sas_queue(struct sas_ha_struct *sas_ha)
-{
-       struct scsi_core *core = &sas_ha->core;
-       unsigned long flags;
-       LIST_HEAD(q);
-       int can_queue;
-       int res;
-       struct sas_internal *i = to_sas_internal(core->shost->transportt);
-
-       mutex_lock(&core->task_queue_flush);
-       spin_lock_irqsave(&core->task_queue_lock, flags);
-       while (!kthread_should_stop() &&
-              !list_empty(&core->task_queue) &&
-              !test_bit(SAS_HA_FROZEN, &sas_ha->state)) {
-
-               can_queue = sas_ha->lldd_queue_size - core->task_queue_size;
-               if (can_queue >= 0) {
-                       can_queue = core->task_queue_size;
-                       list_splice_init(&core->task_queue, &q);
-               } else {
-                       struct list_head *a, *n;
-
-                       can_queue = sas_ha->lldd_queue_size;
-                       list_for_each_safe(a, n, &core->task_queue) {
-                               list_move_tail(a, &q);
-                               if (--can_queue == 0)
-                                       break;
-                       }
-                       can_queue = sas_ha->lldd_queue_size;
-               }
-               core->task_queue_size -= can_queue;
-               spin_unlock_irqrestore(&core->task_queue_lock, flags);
-               {
-                       struct sas_task *task = list_entry(q.next,
-                                                          struct sas_task,
-                                                          list);
-                       list_del_init(&q);
-                       res = i->dft->lldd_execute_task(task, can_queue,
-                                                       GFP_KERNEL);
-                       if (unlikely(res))
-                               __list_add(&q, task->list.prev, &task->list);
-               }
-               spin_lock_irqsave(&core->task_queue_lock, flags);
-               if (res) {
-                       list_splice_init(&q, &core->task_queue); /*at head*/
-                       core->task_queue_size += can_queue;
-               }
-       }
-       spin_unlock_irqrestore(&core->task_queue_lock, flags);
-       mutex_unlock(&core->task_queue_flush);
-}
-
-/**
- * sas_queue_thread -- The Task Collector thread
- * @_sas_ha: pointer to struct sas_ha
- */
-static int sas_queue_thread(void *_sas_ha)
-{
-       struct sas_ha_struct *sas_ha = _sas_ha;
-
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-               sas_queue(sas_ha);
-               if (kthread_should_stop())
-                       break;
-       }
-
-       return 0;
-}
-
-int sas_init_queue(struct sas_ha_struct *sas_ha)
-{
-       struct scsi_core *core = &sas_ha->core;
-
-       spin_lock_init(&core->task_queue_lock);
-       mutex_init(&core->task_queue_flush);
-       core->task_queue_size = 0;
-       INIT_LIST_HEAD(&core->task_queue);
-
-       core->queue_thread = kthread_run(sas_queue_thread, sas_ha,
-                                        "sas_queue_%d", core->shost->host_no);
-       if (IS_ERR(core->queue_thread))
-               return PTR_ERR(core->queue_thread);
-       return 0;
-}
-
-void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
-{
-       unsigned long flags;
-       struct scsi_core *core = &sas_ha->core;
-       struct sas_task *task, *n;
-
-       kthread_stop(core->queue_thread);
-
-       if (!list_empty(&core->task_queue))
-               SAS_DPRINTK("HA: %llx: scsi core task queue is NOT empty!?\n",
-                           SAS_ADDR(sas_ha->sas_addr));
-
-       spin_lock_irqsave(&core->task_queue_lock, flags);
-       list_for_each_entry_safe(task, n, &core->task_queue, list) {
-               struct scsi_cmnd *cmd = task->uldd_task;
-
-               list_del_init(&task->list);
-
-               ASSIGN_SAS_TASK(cmd, NULL);
-               sas_free_task(task);
-               cmd->result = DID_ABORT << 16;
-               cmd->scsi_done(cmd);
-       }
-       spin_unlock_irqrestore(&core->task_queue_lock, flags);
-}
-
 /*
  * Tell an upper layer that it needs to initiate an abort for a given task.
  * This should only ever be called by an LLDD.
index b99399fe25488095d82911e34e8dab82091cb0e6..fd85952b621d6e76d8db7d00682671d1458a2c78 100644 (file)
@@ -242,128 +242,6 @@ lpfc_update_stats(struct lpfc_hba *phba, struct  lpfc_scsi_buf *lpfc_cmd)
        spin_unlock_irqrestore(shost->host_lock, flags);
 }
 
-/**
- * lpfc_send_sdev_queuedepth_change_event - Posts a queuedepth change event
- * @phba: Pointer to HBA context object.
- * @vport: Pointer to vport object.
- * @ndlp: Pointer to FC node associated with the target.
- * @lun: Lun number of the scsi device.
- * @old_val: Old value of the queue depth.
- * @new_val: New value of the queue depth.
- *
- * This function sends an event to the mgmt application indicating
- * there is a change in the scsi device queue depth.
- **/
-static void
-lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
-               struct lpfc_vport  *vport,
-               struct lpfc_nodelist *ndlp,
-               uint64_t lun,
-               uint32_t old_val,
-               uint32_t new_val)
-{
-       struct lpfc_fast_path_event *fast_path_evt;
-       unsigned long flags;
-
-       fast_path_evt = lpfc_alloc_fast_evt(phba);
-       if (!fast_path_evt)
-               return;
-
-       fast_path_evt->un.queue_depth_evt.scsi_event.event_type =
-               FC_REG_SCSI_EVENT;
-       fast_path_evt->un.queue_depth_evt.scsi_event.subcategory =
-               LPFC_EVENT_VARQUEDEPTH;
-
-       /* Report all luns with change in queue depth */
-       fast_path_evt->un.queue_depth_evt.scsi_event.lun = lun;
-       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
-               memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwpn,
-                       &ndlp->nlp_portname, sizeof(struct lpfc_name));
-               memcpy(&fast_path_evt->un.queue_depth_evt.scsi_event.wwnn,
-                       &ndlp->nlp_nodename, sizeof(struct lpfc_name));
-       }
-
-       fast_path_evt->un.queue_depth_evt.oldval = old_val;
-       fast_path_evt->un.queue_depth_evt.newval = new_val;
-       fast_path_evt->vport = vport;
-
-       fast_path_evt->work_evt.evt = LPFC_EVT_FASTPATH_MGMT_EVT;
-       spin_lock_irqsave(&phba->hbalock, flags);
-       list_add_tail(&fast_path_evt->work_evt.evt_listp, &phba->work_list);
-       spin_unlock_irqrestore(&phba->hbalock, flags);
-       lpfc_worker_wake_up(phba);
-
-       return;
-}
-
-/**
- * lpfc_change_queue_depth - Alter scsi device queue depth
- * @sdev: Pointer the scsi device on which to change the queue depth.
- * @qdepth: New queue depth to set the sdev to.
- * @reason: The reason for the queue depth change.
- *
- * This function is called by the midlayer and the LLD to alter the queue
- * depth for a scsi device. This function sets the queue depth to the new
- * value and sends an event out to log the queue depth change.
- **/
-static int
-lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
-       struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
-       struct lpfc_hba   *phba = vport->phba;
-       struct lpfc_rport_data *rdata;
-       unsigned long new_queue_depth, old_queue_depth;
-
-       old_queue_depth = sdev->queue_depth;
-
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-               /* change request from sysfs, fall through */
-       case SCSI_QDEPTH_RAMP_UP:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               if (scsi_track_queue_full(sdev, qdepth) == 0)
-                       return sdev->queue_depth;
-
-               lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
-                                "0711 detected queue full - lun queue "
-                                "depth adjusted to %d.\n", sdev->queue_depth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       new_queue_depth = sdev->queue_depth;
-       rdata = lpfc_rport_data_from_scsi_device(sdev);
-       if (rdata)
-               lpfc_send_sdev_queuedepth_change_event(phba, vport,
-                                                      rdata->pnode, sdev->lun,
-                                                      old_queue_depth,
-                                                      new_queue_depth);
-       return sdev->queue_depth;
-}
-
-/**
- * lpfc_change_queue_type() - Change a device's scsi tag queuing type
- * @sdev: Pointer the scsi device whose queue depth is to change
- * @tag_type: Identifier for queue tag type
- */
-static int
-lpfc_change_queue_type(struct scsi_device *sdev, int tag_type)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag_type);
-               if (tag_type)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag_type = 0;
-
-       return tag_type;
-}
-
 /**
  * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
  * @phba: The Hba for which this call is being executed.
@@ -449,8 +327,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
                                else
                                        new_queue_depth = sdev->queue_depth -
                                                                new_queue_depth;
-                               lpfc_change_queue_depth(sdev, new_queue_depth,
-                                                       SCSI_QDEPTH_DEFAULT);
+                               scsi_change_queue_depth(sdev, new_queue_depth);
                        }
                }
        lpfc_destroy_vport_work_array(phba, vports);
@@ -4286,7 +4163,6 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
        IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
        struct lpfc_iocbq *piocbq = &(lpfc_cmd->cur_iocbq);
        int datadir = scsi_cmnd->sc_data_direction;
-       char tag[2];
        uint8_t *ptr;
        bool sli4;
        uint32_t fcpdl;
@@ -4308,20 +4184,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
                memset(ptr, 0, (LPFC_FCP_CDB_LEN - scsi_cmnd->cmd_len));
        }
 
-       if (scsi_populate_tag_msg(scsi_cmnd, tag)) {
-               switch (tag[0]) {
-               case HEAD_OF_QUEUE_TAG:
-                       fcp_cmnd->fcpCntl1 = HEAD_OF_Q;
-                       break;
-               case ORDERED_QUEUE_TAG:
-                       fcp_cmnd->fcpCntl1 = ORDERED_Q;
-                       break;
-               default:
-                       fcp_cmnd->fcpCntl1 = SIMPLE_Q;
-                       break;
-               }
-       } else
-               fcp_cmnd->fcpCntl1 = SIMPLE_Q;
+       fcp_cmnd->fcpCntl1 = SIMPLE_Q;
 
        sli4 = (phba->sli_rev == LPFC_SLI_REV4);
        piocbq->iocb.un.fcpi.fcpi_XRdy = 0;
@@ -5632,10 +5495,7 @@ lpfc_slave_configure(struct scsi_device *sdev)
        struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata;
        struct lpfc_hba   *phba = vport->phba;
 
-       if (sdev->tagged_supported)
-               scsi_activate_tcq(sdev, vport->cfg_lun_queue_depth);
-       else
-               scsi_deactivate_tcq(sdev, vport->cfg_lun_queue_depth);
+       scsi_change_queue_depth(sdev, vport->cfg_lun_queue_depth);
 
        if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
                lpfc_sli_handle_fast_ring_event(phba,
@@ -6018,8 +5878,10 @@ struct scsi_host_template lpfc_template = {
        .shost_attrs            = lpfc_hba_attrs,
        .max_sectors            = 0xFFFF,
        .vendor_id              = LPFC_NL_VENDOR_ID,
-       .change_queue_depth     = lpfc_change_queue_depth,
-       .change_queue_type      = lpfc_change_queue_type,
+       .change_queue_depth     = scsi_change_queue_depth,
+       .change_queue_type      = scsi_change_queue_type,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 struct scsi_host_template lpfc_vport_template = {
@@ -6041,6 +5903,8 @@ struct scsi_host_template lpfc_vport_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .shost_attrs            = lpfc_vport_attrs,
        .max_sectors            = 0xFFFF,
-       .change_queue_depth     = lpfc_change_queue_depth,
-       .change_queue_type      = lpfc_change_queue_type,
+       .change_queue_depth     = scsi_change_queue_depth,
+       .change_queue_type      = scsi_change_queue_type,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
index 6a039eb1cbce3e808533ec4dabf2041696aa5ed5..953fd9b953c7b1432e3e84333763a425e83649db 100644 (file)
@@ -9,69 +9,62 @@
  * Generic Generic NCR5380 driver
  *
  * Copyright 1995, Russell King
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 #include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/ctype.h>
 #include <linux/delay.h>
-
 #include <linux/module.h>
-#include <linux/signal.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
+#include <linux/platform_device.h>
 
+#include <asm/hwtest.h>
 #include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm/macintosh.h>
 #include <asm/macints.h>
-#include <asm/mac_via.h>
+#include <asm/setup.h>
 
-#include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "mac_scsi.h"
 
-/* These control the behaviour of the generic 5380 core */
-#define AUTOSENSE
+/* Definitions for the core NCR5380 driver. */
+
 #define PSEUDO_DMA
 
-#include "NCR5380.h"
+#define NCR5380_implementation_fields   unsigned char *pdma_base
+#define NCR5380_local_declare()         struct Scsi_Host *_instance
+#define NCR5380_setup(instance)         _instance = instance
 
-#define RESET_BOOT
-#define DRIVER_SETUP
+#define NCR5380_read(reg)               macscsi_read(_instance, reg)
+#define NCR5380_write(reg, value)       macscsi_write(_instance, reg, value)
 
-extern void via_scsi_clear(void);
+#define NCR5380_pread                   macscsi_pread
+#define NCR5380_pwrite                  macscsi_pwrite
 
-#ifdef RESET_BOOT
-static void mac_scsi_reset_boot(struct Scsi_Host *instance);
-#endif
+#define NCR5380_intr                    macscsi_intr
+#define NCR5380_queue_command           macscsi_queue_command
+#define NCR5380_abort                   macscsi_abort
+#define NCR5380_bus_reset               macscsi_bus_reset
+#define NCR5380_info                    macscsi_info
+#define NCR5380_show_info               macscsi_show_info
+#define NCR5380_write_info              macscsi_write_info
+
+#include "NCR5380.h"
+
+#define RESET_BOOT
 
-static int setup_called = 0;
 static int setup_can_queue = -1;
+module_param(setup_can_queue, int, 0);
 static int setup_cmd_per_lun = -1;
+module_param(setup_cmd_per_lun, int, 0);
 static int setup_sg_tablesize = -1;
+module_param(setup_sg_tablesize, int, 0);
 static int setup_use_pdma = -1;
-#ifdef SUPPORT_TAGS
+module_param(setup_use_pdma, int, 0);
 static int setup_use_tagged_queuing = -1;
-#endif
+module_param(setup_use_tagged_queuing, int, 0);
 static int setup_hostid = -1;
+module_param(setup_hostid, int, 0);
 
 /* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
  * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
@@ -84,232 +77,48 @@ static int setup_hostid = -1;
 #define        AFTER_RESET_DELAY       (HZ/2)
 #endif
 
-static volatile unsigned char *mac_scsi_regp = NULL;
-static volatile unsigned char *mac_scsi_drq  = NULL;
-static volatile unsigned char *mac_scsi_nodrq = NULL;
-
-
 /*
  * NCR 5380 register access functions
  */
 
-#if 0
-/* Debug versions */
-#define CTRL(p,v) (*ctrl = (v))
-
-static char macscsi_read(struct Scsi_Host *instance, int reg)
+static inline char macscsi_read(struct Scsi_Host *instance, int reg)
 {
-  int iobase = instance->io_port;
-  int i;
-  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
-
-  CTRL(iobase, 0);
-  i = in_8(iobase + (reg<<4));
-  CTRL(iobase, 0x40);
-
-  return i;
+       return in_8(instance->base + (reg << 4));
 }
 
-static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
-{
-  int iobase = instance->io_port;
-  int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
-
-  CTRL(iobase, 0);
-  out_8(iobase + (reg<<4), value);
-  CTRL(iobase, 0x40);
-}
-#else
-
-/* Fast versions */
-static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg)
+static inline void macscsi_write(struct Scsi_Host *instance, int reg, int value)
 {
-  return in_8(instance->io_port + (reg<<4));
+       out_8(instance->base + (reg << 4), value);
 }
 
-static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value)
+#ifndef MODULE
+static int __init mac_scsi_setup(char *str)
 {
-  out_8(instance->io_port + (reg<<4), value);
-}
-#endif
-
+       int ints[7];
 
-/*
- * Function : mac_scsi_setup(char *str)
- *
- * Purpose : booter command line initialization of the overrides array,
- *
- * Inputs : str - comma delimited list of options
- *
- */
+       (void)get_options(str, ARRAY_SIZE(ints), ints);
 
-static int __init mac_scsi_setup(char *str) {
-#ifdef DRIVER_SETUP    
-       int ints[7];
-       
-       (void)get_options( str, ARRAY_SIZE(ints), ints);
-       
-       if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
-           printk(KERN_WARNING "scsi: <mac5380>"
-               " Usage: mac5380=<can_queue>[,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>,<use_pdma>]\n");
-           printk(KERN_ALERT "scsi: <mac5380> Bad Penguin parameters?\n");
-           return 0;
-       }
-           
-       if (ints[0] >= 1) {
-               if (ints[1] > 0)
-                       /* no limits on this, just > 0 */
-                       setup_can_queue = ints[1];
-       }
-       if (ints[0] >= 2) {
-               if (ints[2] > 0)
-                       setup_cmd_per_lun = ints[2];
-       }
-       if (ints[0] >= 3) {
-               if (ints[3] >= 0) {
-                       setup_sg_tablesize = ints[3];
-                       /* Must be <= SG_ALL (255) */
-                       if (setup_sg_tablesize > SG_ALL)
-                               setup_sg_tablesize = SG_ALL;
-               }
-       }
-       if (ints[0] >= 4) {
-               /* Must be between 0 and 7 */
-               if (ints[4] >= 0 && ints[4] <= 7)
-                       setup_hostid = ints[4];
-               else if (ints[4] > 7)
-                       printk(KERN_WARNING "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
-       }
-#ifdef SUPPORT_TAGS    
-       if (ints[0] >= 5) {
-               if (ints[5] >= 0)
-                       setup_use_tagged_queuing = !!ints[5];
+       if (ints[0] < 1 || ints[0] > 6) {
+               pr_err("Usage: mac5380=<can_queue>[,<cmd_per_lun>[,<sg_tablesize>[,<hostid>[,<use_tags>[,<use_pdma>]]]]]\n");
+               return 0;
        }
-       
-       if (ints[0] == 6) {
-           if (ints[6] >= 0)
+       if (ints[0] >= 1)
+               setup_can_queue = ints[1];
+       if (ints[0] >= 2)
+               setup_cmd_per_lun = ints[2];
+       if (ints[0] >= 3)
+               setup_sg_tablesize = ints[3];
+       if (ints[0] >= 4)
+               setup_hostid = ints[4];
+       if (ints[0] >= 5)
+               setup_use_tagged_queuing = ints[5];
+       if (ints[0] >= 6)
                setup_use_pdma = ints[6];
-       }
-#else
-       if (ints[0] == 5) {
-           if (ints[5] >= 0)
-               setup_use_pdma = ints[5];
-       }
-#endif /* SUPPORT_TAGS */
-       
-#endif /* DRIVER_SETUP */
        return 1;
 }
 
 __setup("mac5380=", mac_scsi_setup);
-
-/*
- * Function : int macscsi_detect(struct scsi_host_template * tpnt)
- *
- * Purpose : initializes mac NCR5380 driver based on the
- *     command line / compile time port and irq definitions.
- *
- * Inputs : tpnt - template for this SCSI adapter.
- *
- * Returns : 1 if a host adapter was found, 0 if not.
- *
- */
-int __init macscsi_detect(struct scsi_host_template * tpnt)
-{
-    static int called = 0;
-    int flags = 0;
-    struct Scsi_Host *instance;
-
-    if (!MACH_IS_MAC || called)
-       return( 0 );
-
-    if (macintosh_config->scsi_type != MAC_SCSI_OLD)
-       return( 0 );
-
-    /* setup variables */
-    tpnt->can_queue =
-       (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
-    tpnt->cmd_per_lun =
-       (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
-    tpnt->sg_tablesize = 
-       (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
-
-    if (setup_hostid >= 0)
-       tpnt->this_id = setup_hostid;
-    else {
-       /* use 7 as default */
-       tpnt->this_id = 7;
-    }
-
-#ifdef SUPPORT_TAGS
-    if (setup_use_tagged_queuing < 0)
-       setup_use_tagged_queuing = USE_TAGGED_QUEUING;
-#endif
-
-    /* Once we support multiple 5380s (e.g. DuoDock) we'll do
-       something different here */
-    instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-    if (instance == NULL)
-       return 0;
-
-    if (macintosh_config->ident == MAC_MODEL_IIFX) {
-       mac_scsi_regp  = via1+0x8000;
-       mac_scsi_drq   = via1+0xE000;
-       mac_scsi_nodrq = via1+0xC000;
-       /* The IIFX should be able to do true DMA, but pseudo-dma doesn't work */
-       flags = FLAG_NO_PSEUDO_DMA;
-    } else {
-       mac_scsi_regp  = via1+0x10000;
-       mac_scsi_drq   = via1+0x6000;
-       mac_scsi_nodrq = via1+0x12000;
-    }
-
-    if (! setup_use_pdma)
-       flags = FLAG_NO_PSEUDO_DMA;
-       
-    instance->io_port = (unsigned long) mac_scsi_regp;
-    instance->irq = IRQ_MAC_SCSI;
-
-#ifdef RESET_BOOT   
-    mac_scsi_reset_boot(instance);
-#endif
-    
-    NCR5380_init(instance, flags);
-
-    instance->n_io_port = 255;
-
-    ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
-
-    if (instance->irq != SCSI_IRQ_NONE)
-       if (request_irq(instance->irq, NCR5380_intr, 0, "ncr5380", instance)) {
-           printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
-                  instance->host_no, instance->irq);
-           instance->irq = SCSI_IRQ_NONE;
-       }
-
-    printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
-    if (instance->irq == SCSI_IRQ_NONE)
-       printk (KERN_INFO "s disabled");
-    else
-       printk (KERN_INFO " %d", instance->irq);
-    printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
-          instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
-    printk(KERN_INFO "\nscsi%d:", instance->host_no);
-    NCR5380_print_options(instance);
-    printk("\n");
-    called = 1;
-    return 1;
-}
-
-int macscsi_release (struct Scsi_Host *shpnt)
-{
-       if (shpnt->irq != SCSI_IRQ_NONE)
-               free_irq(shpnt->irq, shpnt);
-       NCR5380_exit(shpnt);
-
-       return 0;
-}
+#endif /* !MODULE */
 
 #ifdef RESET_BOOT
 /*
@@ -349,10 +158,7 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
 }
 #endif
 
-const char * macscsi_info (struct Scsi_Host *spnt) {
-       return "";
-}
-
+#ifdef PSEUDO_DMA
 /* 
    Pseudo-DMA: (Ove Edlund)
    The code attempts to catch bus errors that occur if one for example
@@ -422,38 +228,39 @@ __asm__ __volatile__                                      \
      : "0"(s), "1"(d), "2"(len)                                \
      : "d0")
 
-
-static int macscsi_pread (struct Scsi_Host *instance,
-                         unsigned char *dst, int len)
+static int macscsi_pread(struct Scsi_Host *instance,
+                         unsigned char *dst, int len)
 {
-   unsigned char *d;
-   volatile unsigned char *s;
-
-   NCR5380_local_declare();
-   NCR5380_setup(instance);
-
-   s = mac_scsi_drq+0x60;
-   d = dst;
-
-/* These conditions are derived from MacOS */
-
-   while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) 
-         && !(NCR5380_read(STATUS_REG) & SR_REQ))
-      ;
-   if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) 
-         && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
-      printk(KERN_ERR "Error in macscsi_pread\n");
-      return -1;
-   }
-
-   CP_IO_TO_MEM(s, d, len);
-   
-   if (len != 0) {
-      printk(KERN_NOTICE "Bus error in macscsi_pread\n");
-      return -1;
-   }
-   
-   return 0;
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+       unsigned char *d;
+       unsigned char *s;
+
+       NCR5380_local_declare();
+       NCR5380_setup(instance);
+
+       s = hostdata->pdma_base + (INPUT_DATA_REG << 4);
+       d = dst;
+
+       /* These conditions are derived from MacOS */
+
+       while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
+              !(NCR5380_read(STATUS_REG) & SR_REQ))
+               ;
+
+       if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
+           (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
+               pr_err("Error in macscsi_pread\n");
+               return -1;
+       }
+
+       CP_IO_TO_MEM(s, d, len);
+
+       if (len != 0) {
+               pr_notice("Bus error in macscsi_pread\n");
+               return -1;
+       }
+
+       return 0;
 }
 
 
@@ -515,59 +322,172 @@ __asm__ __volatile__                                     \
      : "0"(s), "1"(d), "2"(len)                                \
      : "d0")
 
-static int macscsi_pwrite (struct Scsi_Host *instance,
-                                 unsigned char *src, int len)
+static int macscsi_pwrite(struct Scsi_Host *instance,
+                          unsigned char *src, int len)
 {
-   unsigned char *s;
-   volatile unsigned char *d;
-
-   NCR5380_local_declare();
-   NCR5380_setup(instance);
-
-   s = src;
-   d = mac_scsi_drq;
-   
-/* These conditions are derived from MacOS */
-
-   while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) 
-         && (!(NCR5380_read(STATUS_REG) & SR_REQ) 
-            || (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))) 
-      ;
-   if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
-      printk(KERN_ERR "Error in macscsi_pwrite\n");
-      return -1;
-   }
-
-   CP_MEM_TO_IO(s, d, len);   
-
-   if (len != 0) {
-      printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
-      return -1;
-   }
-   
-   return 0;
-}
+       struct NCR5380_hostdata *hostdata = shost_priv(instance);
+       unsigned char *s;
+       unsigned char *d;
+
+       NCR5380_local_declare();
+       NCR5380_setup(instance);
+
+       s = src;
+       d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4);
+
+       /* These conditions are derived from MacOS */
+
+       while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) &&
+              (!(NCR5380_read(STATUS_REG) & SR_REQ) ||
+               (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
+               ;
+
+       if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
+               pr_err("Error in macscsi_pwrite\n");
+               return -1;
+       }
+
+       CP_MEM_TO_IO(s, d, len);
+
+       if (len != 0) {
+               pr_notice("Bus error in macscsi_pwrite\n");
+               return -1;
+       }
 
+       return 0;
+}
+#endif
 
 #include "NCR5380.c"
 
-static struct scsi_host_template driver_template = {
-       .proc_name                      = "Mac5380",
+#define DRV_MODULE_NAME         "mac_scsi"
+#define PFX                     DRV_MODULE_NAME ": "
+
+static struct scsi_host_template mac_scsi_template = {
+       .module                         = THIS_MODULE,
+       .proc_name                      = DRV_MODULE_NAME,
        .show_info                      = macscsi_show_info,
        .write_info                     = macscsi_write_info,
        .name                           = "Macintosh NCR5380 SCSI",
-       .detect                         = macscsi_detect,
-       .release                        = macscsi_release,
        .info                           = macscsi_info,
        .queuecommand                   = macscsi_queue_command,
        .eh_abort_handler               = macscsi_abort,
        .eh_bus_reset_handler           = macscsi_bus_reset,
-       .can_queue                      = CAN_QUEUE,
+       .can_queue                      = 16,
        .this_id                        = 7,
        .sg_tablesize                   = SG_ALL,
-       .cmd_per_lun                    = CMD_PER_LUN,
+       .cmd_per_lun                    = 2,
        .use_clustering                 = DISABLE_CLUSTERING
 };
 
+static int __init mac_scsi_probe(struct platform_device *pdev)
+{
+       struct Scsi_Host *instance;
+       int error;
+       int host_flags = 0;
+       struct resource *irq, *pio_mem, *pdma_mem = NULL;
+
+       pio_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!pio_mem)
+               return -ENODEV;
+
+#ifdef PSEUDO_DMA
+       pdma_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+#endif
+
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+       if (!hwreg_present((unsigned char *)pio_mem->start +
+                          (STATUS_REG << 4))) {
+               pr_info(PFX "no device detected at %pap\n", &pio_mem->start);
+               return -ENODEV;
+       }
+
+       if (setup_can_queue > 0)
+               mac_scsi_template.can_queue = setup_can_queue;
+       if (setup_cmd_per_lun > 0)
+               mac_scsi_template.cmd_per_lun = setup_cmd_per_lun;
+       if (setup_sg_tablesize >= 0)
+               mac_scsi_template.sg_tablesize = setup_sg_tablesize;
+       if (setup_hostid >= 0)
+               mac_scsi_template.this_id = setup_hostid & 7;
+       if (setup_use_pdma < 0)
+               setup_use_pdma = 0;
+
+       instance = scsi_host_alloc(&mac_scsi_template,
+                                  sizeof(struct NCR5380_hostdata));
+       if (!instance)
+               return -ENOMEM;
+
+       instance->base = pio_mem->start;
+       if (irq)
+               instance->irq = irq->start;
+       else
+               instance->irq = NO_IRQ;
+
+       if (pdma_mem && setup_use_pdma) {
+               struct NCR5380_hostdata *hostdata = shost_priv(instance);
+
+               hostdata->pdma_base = (unsigned char *)pdma_mem->start;
+       } else
+               host_flags |= FLAG_NO_PSEUDO_DMA;
+
+#ifdef RESET_BOOT
+       mac_scsi_reset_boot(instance);
+#endif
+
+#ifdef SUPPORT_TAGS
+       host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
+#endif
+
+       NCR5380_init(instance, host_flags);
+
+       if (instance->irq != NO_IRQ) {
+               error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED,
+                                   "NCR5380", instance);
+               if (error)
+                       goto fail_irq;
+       }
+
+       error = scsi_add_host(instance, NULL);
+       if (error)
+               goto fail_host;
+
+       platform_set_drvdata(pdev, instance);
+
+       scsi_scan_host(instance);
+       return 0;
+
+fail_host:
+       if (instance->irq != NO_IRQ)
+               free_irq(instance->irq, instance);
+fail_irq:
+       NCR5380_exit(instance);
+       scsi_host_put(instance);
+       return error;
+}
+
+static int __exit mac_scsi_remove(struct platform_device *pdev)
+{
+       struct Scsi_Host *instance = platform_get_drvdata(pdev);
+
+       scsi_remove_host(instance);
+       if (instance->irq != NO_IRQ)
+               free_irq(instance->irq, instance);
+       NCR5380_exit(instance);
+       scsi_host_put(instance);
+       return 0;
+}
+
+static struct platform_driver mac_scsi_driver = {
+       .remove = __exit_p(mac_scsi_remove),
+       .driver = {
+               .name   = DRV_MODULE_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver_probe(mac_scsi_driver, mac_scsi_probe);
 
-#include "scsi_module.c"
+MODULE_ALIAS("platform:" DRV_MODULE_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
deleted file mode 100644 (file)
index 06969b0..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Cumana Generic NCR5380 driver defines
- *
- * Copyright 1993, Drew Eckhardt
- *     Visionary Computing
- *     (Unix and Linux consulting and custom programming)
- *     drew@colorado.edu
- *      +1 (303) 440-4894
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-#ifndef MAC_NCR5380_H
-#define MAC_NCR5380_H
-
-#define MACSCSI_PUBLIC_RELEASE 2
-
-#ifndef ASM
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#ifndef SG_TABLESIZE
-#define SG_TABLESIZE SG_NONE
-#endif
-
-#ifndef USE_TAGGED_QUEUING
-#define        USE_TAGGED_QUEUING 0
-#endif
-
-#include <scsi/scsicam.h>
-
-#define NCR5380_implementation_fields \
-    int port, ctrl
-
-#define NCR5380_local_declare() \
-        struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
-        _instance = instance
-
-#define NCR5380_read(reg) macscsi_read(_instance, reg)
-#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value)
-
-#define NCR5380_pread  macscsi_pread
-#define NCR5380_pwrite         macscsi_pwrite
-       
-#define NCR5380_intr macscsi_intr
-#define NCR5380_queue_command macscsi_queue_command
-#define NCR5380_abort macscsi_abort
-#define NCR5380_bus_reset macscsi_bus_reset
-#define NCR5380_show_info macscsi_show_info
-#define NCR5380_write_info macscsi_write_info
-
-#endif /* ndef ASM */
-#endif /* MAC_NCR5380_H */
-
index ac5d94cfd52f22cdfbbe162f8a8868a8d4d6fe20..2485255f341499a686914c15d1bff2efb59c81c5 100644 (file)
@@ -1945,7 +1945,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
             cmd->device->id, (u32)cmd->device->lun);
 
        if(list_empty(&adapter->pending_list))
-               return FALSE;
+               return FAILED;
 
        list_for_each_safe(pos, next, &adapter->pending_list) {
 
@@ -1968,7 +1968,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
                                        (aor==SCB_ABORT) ? "ABORTING":"RESET",
                                        scb->idx);
 
-                               return FALSE;
+                               return FAILED;
                        }
                        else {
 
@@ -1993,12 +1993,12 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
                                list_add_tail(SCSI_LIST(cmd),
                                                &adapter->completed_list);
 
-                               return TRUE;
+                               return SUCCESS;
                        }
                }
        }
 
-       return FALSE;
+       return FAILED;
 }
 
 static inline int
index 531dce419c18103d3ad78b3a7fcc6329432cfe87..f0987f22ea70be2f13cf434120155112fcbcc9dc 100644 (file)
@@ -332,27 +332,6 @@ static struct device_attribute *megaraid_sdev_attrs[] = {
        NULL,
 };
 
-/**
- * megaraid_change_queue_depth - Change the device's queue depth
- * @sdev:      scsi device struct
- * @qdepth:    depth to set
- * @reason:    calling context
- *
- * Return value:
- *     actual depth set
- */
-static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth,
-                                      int reason)
-{
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
-       if (qdepth > MBOX_MAX_SCSI_CMDS)
-               qdepth = MBOX_MAX_SCSI_CMDS;
-       scsi_adjust_queue_depth(sdev, 0, qdepth);
-       return sdev->queue_depth;
-}
-
 /*
  * Scsi host template for megaraid unified driver
  */
@@ -365,7 +344,7 @@ static struct scsi_host_template megaraid_template_g = {
        .eh_device_reset_handler        = megaraid_reset_handler,
        .eh_bus_reset_handler           = megaraid_reset_handler,
        .eh_host_reset_handler          = megaraid_reset_handler,
-       .change_queue_depth             = megaraid_change_queue_depth,
+       .change_queue_depth             = scsi_change_queue_depth,
        .use_clustering                 = ENABLE_CLUSTERING,
        .no_write_same                  = 1,
        .sdev_attrs                     = megaraid_sdev_attrs,
index a49914de4b954806fb988d0e4e12d96d753126a5..0d44d91c2fceddb863b470534155960902657057 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2003-2012  LSI Corporation.
+ *  Copyright (c) 2003-2013  LSI Corporation
+ *  Copyright (c) 2013-2014  Avago Technologies
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  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
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  FILE: megaraid_sas.h
  *
- *  Authors: LSI Corporation
+ *  Authors: Avago Technologies
+ *           Kashyap Desai <kashyap.desai@avagotech.com>
+ *           Sumit Saxena <sumit.saxena@avagotech.com>
  *
- *  Send feedback to: <megaraidlinux@lsi.com>
+ *  Send feedback to: megaraidlinux.pdl@avagotech.com
  *
- *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- *     ATTN: Linuxraid
+ *  Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ *  San Jose, California 95131
  */
 
 #ifndef LSI_MEGARAID_SAS_H
@@ -33,9 +35,7 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION                                "06.805.06.00-rc1"
-#define MEGASAS_RELDATE                                "Sep. 4, 2014"
-#define MEGASAS_EXT_VERSION                    "Thu. Sep. 4 17:00:00 PDT 2014"
+#define MEGASAS_VERSION                                "06.805.06.01-rc1"
 
 /*
  * Device IDs
@@ -1931,8 +1931,7 @@ u16 get_updated_dev_handle(struct megasas_instance *instance,
        struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info);
 void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
        struct LD_LOAD_BALANCE_INFO *lbInfo);
-int megasas_get_ctrl_info(struct megasas_instance *instance,
-       struct megasas_ctrl_info *ctrl_info);
+int megasas_get_ctrl_info(struct megasas_instance *instance);
 int megasas_set_crash_dump_params(struct megasas_instance *instance,
        u8 crash_buf_state);
 void megasas_free_host_crash_buffer(struct megasas_instance *instance);
index f6a69a3b1b3f0c8fb1bd805e8970beb2800feaef..f05580e693d010d9405eec8b007a7709e655ea09 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2003-2012  LSI Corporation.
+ *  Copyright (c) 2003-2013  LSI Corporation
+ *  Copyright (c) 2013-2014  Avago Technologies
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  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
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
- *  FILE: megaraid_sas_base.c
- *  Version : 06.805.06.00-rc1
- *
- *  Authors: LSI Corporation
+ *  Authors: Avago Technologies
  *           Sreenivas Bagalkote
  *           Sumant Patro
  *           Bo Yang
- *           Adam Radford <linuxraid@lsi.com>
+ *           Adam Radford
+ *           Kashyap Desai <kashyap.desai@avagotech.com>
+ *           Sumit Saxena <sumit.saxena@avagotech.com>
  *
- *  Send feedback to: <megaraidlinux@lsi.com>
+ *  Send feedback to: megaraidlinux.pdl@avagotech.com
  *
- *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- *     ATTN: Linuxraid
+ *  Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ *  San Jose, California 95131
  */
 
 #include <linux/kernel.h>
@@ -1008,7 +1007,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
                cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
 
        cmd->sync_cmd = 1;
-       cmd->cmd_status = 0xFF;
+       cmd->cmd_status = ENODATA;
 
        instance->instancet->issue_dcmd(instance, cmd);
 
@@ -1572,6 +1571,12 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
        instance = (struct megasas_instance *)
            scmd->device->host->hostdata;
 
+       if (instance->unload == 1) {
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               return 0;
+       }
+
        if (instance->issuepend_done == 0)
                return SCSI_MLQUEUE_HOST_BUSY;
 
@@ -2586,20 +2591,6 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
        }
 }
 
-static int megasas_change_queue_depth(struct scsi_device *sdev,
-                                     int queue_depth, int reason)
-{
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
-       if (queue_depth > sdev->host->can_queue)
-               queue_depth = sdev->host->can_queue;
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev),
-                               queue_depth);
-
-       return queue_depth;
-}
-
 static ssize_t
 megasas_fw_crash_buffer_store(struct device *cdev,
        struct device_attribute *attr, const char *buf, size_t count)
@@ -2764,7 +2755,7 @@ static struct scsi_host_template megasas_template = {
        .shost_attrs = megaraid_host_attrs,
        .bios_param = megasas_bios_param,
        .use_clustering = ENABLE_CLUSTERING,
-       .change_queue_depth = megasas_change_queue_depth,
+       .change_queue_depth = scsi_change_queue_depth,
        .no_write_same = 1,
 };
 
@@ -4028,25 +4019,83 @@ megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
        return ret;
 }
 
+/*
+ * megasas_update_ext_vd_details : Update details w.r.t Extended VD
+ * instance                     : Controller's instance
+*/
+static void megasas_update_ext_vd_details(struct megasas_instance *instance)
+{
+       struct fusion_context *fusion;
+       u32 old_map_sz;
+       u32 new_map_sz;
+
+       fusion = instance->ctrl_context;
+       /* For MFI based controllers return dummy success */
+       if (!fusion)
+               return;
+
+       instance->supportmax256vd =
+               instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
+       /* Below is additional check to address future FW enhancement */
+       if (instance->ctrl_info->max_lds > 64)
+               instance->supportmax256vd = 1;
+
+       instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
+                                       * MEGASAS_MAX_DEV_PER_CHANNEL;
+       instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
+                                       * MEGASAS_MAX_DEV_PER_CHANNEL;
+       if (instance->supportmax256vd) {
+               instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
+               instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+       } else {
+               instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
+               instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
+       }
+       dev_info(&instance->pdev->dev, "Firmware supports %d VD %d PD\n",
+               instance->fw_supported_vd_count,
+               instance->fw_supported_pd_count);
+       dev_info(&instance->pdev->dev, "Driver supports %d VD  %d PD\n",
+               instance->drv_supported_vd_count,
+               instance->drv_supported_pd_count);
+
+       old_map_sz =  sizeof(struct MR_FW_RAID_MAP) +
+                               (sizeof(struct MR_LD_SPAN_MAP) *
+                               (instance->fw_supported_vd_count - 1));
+       new_map_sz =  sizeof(struct MR_FW_RAID_MAP_EXT);
+       fusion->drv_map_sz =  sizeof(struct MR_DRV_RAID_MAP) +
+                               (sizeof(struct MR_LD_SPAN_MAP) *
+                               (instance->drv_supported_vd_count - 1));
+
+       fusion->max_map_sz = max(old_map_sz, new_map_sz);
+
+
+       if (instance->supportmax256vd)
+               fusion->current_map_sz = new_map_sz;
+       else
+               fusion->current_map_sz = old_map_sz;
+
+}
+
 /**
  * megasas_get_controller_info -       Returns FW's controller structure
  * @instance:                          Adapter soft state
- * @ctrl_info:                         Controller information structure
  *
  * Issues an internal command (DCMD) to get the FW's controller structure.
  * This information is mainly used to find out the maximum IO transfer per
  * command supported by the FW.
  */
 int
-megasas_get_ctrl_info(struct megasas_instance *instance,
-                     struct megasas_ctrl_info *ctrl_info)
+megasas_get_ctrl_info(struct megasas_instance *instance)
 {
        int ret = 0;
        struct megasas_cmd *cmd;
        struct megasas_dcmd_frame *dcmd;
        struct megasas_ctrl_info *ci;
+       struct megasas_ctrl_info *ctrl_info;
        dma_addr_t ci_h = 0;
 
+       ctrl_info = instance->ctrl_info;
+
        cmd = megasas_get_cmd(instance);
 
        if (!cmd) {
@@ -4086,8 +4135,13 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
        else
                ret = megasas_issue_polled(instance, cmd);
 
-       if (!ret)
+       if (!ret) {
                memcpy(ctrl_info, ci, sizeof(struct megasas_ctrl_info));
+               le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
+               le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
+               le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
+               megasas_update_ext_vd_details(instance);
+       }
 
        pci_free_consistent(instance->pdev, sizeof(struct megasas_ctrl_info),
                            ci, ci_h);
@@ -4289,7 +4343,7 @@ megasas_init_adapter_mfi(struct megasas_instance *instance)
        if (megasas_issue_init_mfi(instance))
                goto fail_fw_init;
 
-       if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
+       if (megasas_get_ctrl_info(instance)) {
                dev_err(&instance->pdev->dev, "(%d): Could get controller info "
                        "Fail from %s %d\n", instance->unique_id,
                        __func__, __LINE__);
@@ -4453,7 +4507,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
                        instance->msixentry[i].entry = i;
                i = pci_enable_msix_range(instance->pdev, instance->msixentry,
                                          1, instance->msix_vectors);
-               if (i)
+               if (i > 0)
                        instance->msix_vectors = i;
                else
                        instance->msix_vectors = 0;
@@ -4527,12 +4581,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
                dev_info(&instance->pdev->dev,
                        "Controller type: iMR\n");
        }
-       /* OnOffProperties are converted into CPU arch*/
-       le32_to_cpus((u32 *)&ctrl_info->properties.OnOffProperties);
        instance->disableOnlineCtrlReset =
        ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
-       /* adapterOperations2 are converted into CPU arch*/
-       le32_to_cpus((u32 *)&ctrl_info->adapterOperations2);
        instance->mpio = ctrl_info->adapterOperations2.mpio;
        instance->UnevenSpanSupport =
                ctrl_info->adapterOperations2.supportUnevenSpans;
@@ -4562,7 +4612,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
                       "requestorId %d\n", instance->requestorId);
        }
 
-       le32_to_cpus((u32 *)&ctrl_info->adapterOperations3);
        instance->crash_dump_fw_support =
                ctrl_info->adapterOperations3.supportCrashDump;
        instance->crash_dump_drv_support =
@@ -4587,8 +4636,6 @@ static int megasas_init_fw(struct megasas_instance *instance)
        if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
                instance->max_sectors_per_req = tmp_sectors;
 
-       kfree(ctrl_info);
-
        /* Check for valid throttlequeuedepth module parameter */
        if (instance->is_imr) {
                if (throttlequeuedepth > (instance->max_fw_cmds -
@@ -4957,10 +5004,6 @@ static int megasas_io_attach(struct megasas_instance *instance)
                return -ENODEV;
        }
 
-       /*
-        * Trigger SCSI to scan our drives
-        */
-       scsi_scan_host(host);
        return 0;
 }
 
@@ -5083,6 +5126,8 @@ static int megasas_probe_one(struct pci_dev *pdev,
                        goto fail_alloc_dma_buf;
                }
                fusion = instance->ctrl_context;
+               memset(fusion, 0,
+                       ((1 << PAGE_SHIFT) << instance->ctrl_context_pages));
                INIT_LIST_HEAD(&fusion->cmd_pool);
                spin_lock_init(&fusion->mpt_pool_lock);
                memset(fusion->load_balance_info, 0,
@@ -5288,6 +5333,10 @@ retry_irq_register:
                goto fail_io_attach;
 
        instance->unload = 0;
+       /*
+        * Trigger SCSI to scan our drives
+        */
+       scsi_scan_host(host);
 
        /*
         * Initiate AEN (Asynchronous Event Notification)
@@ -6051,6 +6100,11 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        megasas_issue_blocked_cmd(instance, cmd, 0);
        cmd->sync_cmd = 0;
 
+       if (instance->unload == 1) {
+               dev_info(&instance->pdev->dev, "Driver unload is in progress "
+                       "don't submit data to application\n");
+               goto out;
+       }
        /*
         * copy out the kernel buffers to user buffers
         */
@@ -6399,16 +6453,6 @@ static ssize_t megasas_sysfs_show_version(struct device_driver *dd, char *buf)
 
 static DRIVER_ATTR(version, S_IRUGO, megasas_sysfs_show_version, NULL);
 
-static ssize_t
-megasas_sysfs_show_release_date(struct device_driver *dd, char *buf)
-{
-       return snprintf(buf, strlen(MEGASAS_RELDATE) + 2, "%s\n",
-                       MEGASAS_RELDATE);
-}
-
-static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date,
-                  NULL);
-
 static ssize_t
 megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
 {
@@ -6712,8 +6756,7 @@ static int __init megasas_init(void)
        /*
         * Announce driver version and other information
         */
-       printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
-              MEGASAS_EXT_VERSION);
+       pr_info("megasas: %s\n", MEGASAS_VERSION);
 
        spin_lock_init(&poll_aen_lock);
 
@@ -6748,10 +6791,6 @@ static int __init megasas_init(void)
                                  &driver_attr_version);
        if (rval)
                goto err_dcf_attr_ver;
-       rval = driver_create_file(&megasas_pci_driver.driver,
-                                 &driver_attr_release_date);
-       if (rval)
-               goto err_dcf_rel_date;
 
        rval = driver_create_file(&megasas_pci_driver.driver,
                                &driver_attr_support_poll_for_event);
@@ -6775,12 +6814,7 @@ err_dcf_support_device_change:
 err_dcf_dbg_lvl:
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_poll_for_event);
-
 err_dcf_support_poll_for_event:
-       driver_remove_file(&megasas_pci_driver.driver,
-                          &driver_attr_release_date);
-
-err_dcf_rel_date:
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 err_dcf_attr_ver:
        pci_unregister_driver(&megasas_pci_driver);
@@ -6800,8 +6834,6 @@ static void __exit megasas_exit(void)
                        &driver_attr_support_poll_for_event);
        driver_remove_file(&megasas_pci_driver.driver,
                        &driver_attr_support_device_change);
-       driver_remove_file(&megasas_pci_driver.driver,
-                          &driver_attr_release_date);
        driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
 
        pci_unregister_driver(&megasas_pci_driver);
index 685e6f391fe4ed256f62ff2be724a3ed5a97c552..460c6a3d4aded153523bb27b9184f455f7fa0a41 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2012  LSI Corporation.
+ *  Copyright (c) 2009-2013  LSI Corporation
+ *  Copyright (c) 2013-2014  Avago Technologies
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  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
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  FILE: megaraid_sas_fp.c
  *
- *  Authors: LSI Corporation
+ *  Authors: Avago Technologies
  *           Sumant Patro
  *           Varad Talamacki
  *           Manoj Jose
+ *           Kashyap Desai <kashyap.desai@avagotech.com>
+ *           Sumit Saxena <sumit.saxena@avagotech.com>
  *
- *  Send feedback to: <megaraidlinux@lsi.com>
+ *  Send feedback to: megaraidlinux.pdl@avagotech.com
  *
- *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- *     ATTN: Linuxraid
+ *  Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ *  San Jose, California 95131
  */
 
 #include <linux/kernel.h>
@@ -183,14 +185,15 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
                /* New Raid map will not set totalSize, so keep expected value
                 * for legacy code in ValidateMapInfo
                 */
-               pDrvRaidMap->totalSize = sizeof(struct MR_FW_RAID_MAP_EXT);
+               pDrvRaidMap->totalSize =
+                       cpu_to_le32(sizeof(struct MR_FW_RAID_MAP_EXT));
        } else {
                fw_map_old = (struct MR_FW_RAID_MAP_ALL *)
                        fusion->ld_map[(instance->map_id & 1)];
                pFwRaidMap = &fw_map_old->raidMap;
 
 #if VD_EXT_DEBUG
-               for (i = 0; i < pFwRaidMap->ldCount; i++) {
+               for (i = 0; i < le16_to_cpu(pFwRaidMap->ldCount); i++) {
                        dev_dbg(&instance->pdev->dev, "(%d) :Index 0x%x "
                                "Target Id 0x%x Seq Num 0x%x Size 0/%llx\n",
                                instance->unique_id, i,
@@ -202,12 +205,12 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
 
                memset(drv_map, 0, fusion->drv_map_sz);
                pDrvRaidMap->totalSize = pFwRaidMap->totalSize;
-               pDrvRaidMap->ldCount = pFwRaidMap->ldCount;
+               pDrvRaidMap->ldCount = (__le16)pFwRaidMap->ldCount;
                pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec;
                for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++)
                        pDrvRaidMap->ldTgtIdToLd[i] =
                                (u8)pFwRaidMap->ldTgtIdToLd[i];
-               for (i = 0; i < pDrvRaidMap->ldCount; i++) {
+               for (i = 0; i < le16_to_cpu(pDrvRaidMap->ldCount); i++) {
                        pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i];
 #if VD_EXT_DEBUG
                        dev_dbg(&instance->pdev->dev,
@@ -268,7 +271,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
        else
                expected_size =
                        (sizeof(struct MR_FW_RAID_MAP) - sizeof(struct MR_LD_SPAN_MAP) +
-                       (sizeof(struct MR_LD_SPAN_MAP) * le32_to_cpu(pDrvRaidMap->ldCount)));
+                       (sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount)));
 
        if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) {
                dev_err(&instance->pdev->dev, "map info structure size 0x%x is not matching with ld count\n",
@@ -284,7 +287,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
 
        mr_update_load_balance_params(drv_map, lbInfo);
 
-       num_lds = le32_to_cpu(drv_map->raidMap.ldCount);
+       num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
 
        /*Convert Raid capability values to CPU arch */
        for (ldCount = 0; ldCount < num_lds; ldCount++) {
@@ -457,7 +460,7 @@ u32 mr_spanset_get_span_block(struct megasas_instance *instance,
                                quad = &map->raidMap.ldSpanMap[ld].
                                        spanBlock[span].
                                        block_span_info.quad[info];
-                               if (le32_to_cpu(quad->diff == 0))
+                               if (le32_to_cpu(quad->diff) == 0)
                                        return SPAN_INVALID;
                                if (le64_to_cpu(quad->logStart) <= row  &&
                                        row <= le64_to_cpu(quad->logEnd)  &&
@@ -520,7 +523,7 @@ static u64  get_row_from_strip(struct megasas_instance *instance,
                                span_set->span_row_data_width) * span_set->diff;
                for (span = 0, span_offset = 0; span < raid->spanDepth; span++)
                        if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].
-                               block_span_info.noElements >= info+1)) {
+                               block_span_info.noElements) >= info+1) {
                                if (strip_offset >=
                                        span_set->strip_offset[span])
                                        span_offset++;
index f37eed682c750bb2b8cae43b0ec0b25d66d5f9b6..71557f64bb5e6e4936cfe2dc642097dc8bdc6ba0 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2012  LSI Corporation.
+ *  Copyright (c) 2009-2013  LSI Corporation
+ *  Copyright (c) 2013-2014  Avago Technologies
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  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
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  FILE: megaraid_sas_fusion.c
  *
- *  Authors: LSI Corporation
+ *  Authors: Avago Technologies
  *           Sumant Patro
- *           Adam Radford <linuxraid@lsi.com>
+ *           Adam Radford
+ *           Kashyap Desai <kashyap.desai@avagotech.com>
+ *           Sumit Saxena <sumit.saxena@avagotech.com>
  *
- *  Send feedback to: <megaraidlinux@lsi.com>
+ *  Send feedback to: megaraidlinux.pdl@avagotech.com
  *
- *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- *     ATTN: Linuxraid
+ *  Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ *  San Jose, California 95131
  */
 
 #include <linux/kernel.h>
@@ -880,7 +882,7 @@ megasas_sync_map_info(struct megasas_instance *instance)
 
        map = fusion->ld_drv_map[instance->map_id & 1];
 
-       num_lds = le32_to_cpu(map->raidMap.ldCount);
+       num_lds = le16_to_cpu(map->raidMap.ldCount);
 
        dcmd = &cmd->frame->dcmd;
 
@@ -1065,48 +1067,16 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
                goto fail_ioc_init;
 
        megasas_display_intel_branding(instance);
-       if (megasas_get_ctrl_info(instance, instance->ctrl_info)) {
+       if (megasas_get_ctrl_info(instance)) {
                dev_err(&instance->pdev->dev,
                        "Could not get controller info. Fail from %s %d\n",
                        __func__, __LINE__);
                goto fail_ioc_init;
        }
 
-       instance->supportmax256vd =
-               instance->ctrl_info->adapterOperations3.supportMaxExtLDs;
-       /* Below is additional check to address future FW enhancement */
-       if (instance->ctrl_info->max_lds > 64)
-               instance->supportmax256vd = 1;
-       instance->drv_supported_vd_count = MEGASAS_MAX_LD_CHANNELS
-                                       * MEGASAS_MAX_DEV_PER_CHANNEL;
-       instance->drv_supported_pd_count = MEGASAS_MAX_PD_CHANNELS
-                                       * MEGASAS_MAX_DEV_PER_CHANNEL;
-       if (instance->supportmax256vd) {
-               instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES_EXT;
-               instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
-       } else {
-               instance->fw_supported_vd_count = MAX_LOGICAL_DRIVES;
-               instance->fw_supported_pd_count = MAX_PHYSICAL_DEVICES;
-       }
-       dev_info(&instance->pdev->dev, "Firmware supports %d VDs %d PDs\n"
-               "Driver supports %d VDs  %d PDs\n",
-               instance->fw_supported_vd_count,
-               instance->fw_supported_pd_count,
-               instance->drv_supported_vd_count,
-               instance->drv_supported_pd_count);
-
        instance->flag_ieee = 1;
        fusion->fast_path_io = 0;
 
-       fusion->old_map_sz =
-               sizeof(struct MR_FW_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
-               (instance->fw_supported_vd_count - 1));
-       fusion->new_map_sz =
-               sizeof(struct MR_FW_RAID_MAP_EXT);
-       fusion->drv_map_sz =
-               sizeof(struct MR_DRV_RAID_MAP) + (sizeof(struct MR_LD_SPAN_MAP) *
-               (instance->drv_supported_vd_count - 1));
-
        fusion->drv_map_pages = get_order(fusion->drv_map_sz);
        for (i = 0; i < 2; i++) {
                fusion->ld_map[i] = NULL;
@@ -1121,16 +1091,10 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
                                        fusion->drv_map_pages);
                        goto fail_ioc_init;
                }
+               memset(fusion->ld_drv_map[i], 0,
+                       ((1 << PAGE_SHIFT) << fusion->drv_map_pages));
        }
 
-       fusion->max_map_sz = max(fusion->old_map_sz, fusion->new_map_sz);
-
-       if (instance->supportmax256vd)
-               fusion->current_map_sz = fusion->new_map_sz;
-       else
-               fusion->current_map_sz = fusion->old_map_sz;
-
-
        for (i = 0; i < 2; i++) {
                fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev,
                                                       fusion->max_map_sz,
@@ -1173,9 +1137,10 @@ megasas_fire_cmd_fusion(struct megasas_instance *instance,
                        struct megasas_register_set __iomem *regs)
 {
 #if defined(writeq) && defined(CONFIG_64BIT)
-       u64 req_data = (((u64)req_desc_hi << 32) | (u32)req_desc_lo);
+       u64 req_data = (((u64)le32_to_cpu(req_desc_hi) << 32) |
+                       le32_to_cpu(req_desc_lo));
 
-       writeq(le64_to_cpu(req_data), &(regs)->inbound_low_queue_port);
+       writeq(req_data, &(regs)->inbound_low_queue_port);
 #else
        unsigned long flags;
 
@@ -1373,7 +1338,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
                /* Logical block reference tag */
                io_request->CDB.EEDP32.PrimaryReferenceTag =
                        cpu_to_be32(ref_tag);
-               io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff;
+               io_request->CDB.EEDP32.PrimaryApplicationTagMask = cpu_to_be16(0xffff);
                io_request->IoFlags = cpu_to_le16(32); /* Specify 32-byte cdb */
 
                /* Transfer length */
@@ -1769,7 +1734,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
 
                /* set RAID context values */
                pRAID_Context->regLockFlags     = REGION_TYPE_SHARED_READ;
-               pRAID_Context->timeoutValue     = raid->fpIoTimeoutForLd;
+               pRAID_Context->timeoutValue     = cpu_to_le16(raid->fpIoTimeoutForLd);
                pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
                pRAID_Context->regLockRowLBA    = 0;
                pRAID_Context->regLockLength    = 0;
@@ -2254,7 +2219,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
         * megasas_complete_cmd
         */
 
-       if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE)
+       if (frame_hdr->flags & cpu_to_le16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE))
                cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
 
        fusion = instance->ctrl_context;
@@ -2385,6 +2350,8 @@ megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
                                "memory allocation failed at index %d\n", i);
                        break;
                }
+               memset(instance->crash_buf[i], 0,
+                       ((1 << PAGE_SHIFT) << instance->crash_buf_pages));
        }
        instance->drv_buf_alloc = i;
 }
@@ -2837,11 +2804,15 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
                                }
                        }
 
-                       clear_bit(MEGASAS_FUSION_IN_RESET,
-                                 &instance->reset_flags);
-                       instance->instancet->enable_intr(instance);
-                       instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
-
+                       if (megasas_get_ctrl_info(instance)) {
+                               dev_info(&instance->pdev->dev,
+                                       "Failed from %s %d\n",
+                                       __func__, __LINE__);
+                               instance->adprecovery =
+                                       MEGASAS_HW_CRITICAL_ERROR;
+                               megaraid_sas_kill_hba(instance);
+                               retval = FAILED;
+                       }
                        /* Reset load balance info */
                        memset(fusion->load_balance_info, 0,
                               sizeof(struct LD_LOAD_BALANCE_INFO)
@@ -2850,6 +2821,11 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
                        if (!megasas_get_map_info(instance))
                                megasas_sync_map_info(instance);
 
+                       clear_bit(MEGASAS_FUSION_IN_RESET,
+                                 &instance->reset_flags);
+                       instance->instancet->enable_intr(instance);
+                       instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
+
                        /* Restart SR-IOV heartbeat */
                        if (instance->requestorId) {
                                if (!megasas_sriov_start_heartbeat(instance, 0))
@@ -2866,14 +2842,14 @@ int megasas_reset_fusion(struct Scsi_Host *shost, int iotimeout)
                               "successful for scsi%d.\n",
                                instance->host->host_no);
 
-                       if (instance->crash_dump_drv_support) {
-                               if (instance->crash_dump_app_support)
-                                       megasas_set_crash_dump_params(instance,
-                                               MR_CRASH_BUF_TURN_ON);
-                               else
-                                       megasas_set_crash_dump_params(instance,
-                                               MR_CRASH_BUF_TURN_OFF);
-                       }
+                       if (instance->crash_dump_drv_support &&
+                               instance->crash_dump_app_support)
+                               megasas_set_crash_dump_params(instance,
+                                       MR_CRASH_BUF_TURN_ON);
+                       else
+                               megasas_set_crash_dump_params(instance,
+                                       MR_CRASH_BUF_TURN_OFF);
+
                        retval = SUCCESS;
                        goto out;
                }
index 0d183d521bdd9bf83b6590fc6555af2dbc434094..5ab7daee11be708b6057b317bc082d808f0bb274 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  Linux MegaRAID driver for SAS based RAID controllers
  *
- *  Copyright (c) 2009-2012  LSI Corporation.
+ *  Copyright (c) 2009-2013  LSI Corporation
+ *  Copyright (c) 2013-2014  Avago Technologies
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  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
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  FILE: megaraid_sas_fusion.h
  *
- *  Authors: LSI Corporation
+ *  Authors: Avago Technologies
  *           Manoj Jose
  *           Sumant Patro
+ *           Kashyap Desai <kashyap.desai@avagotech.com>
+ *           Sumit Saxena <sumit.saxena@avagotech.com>
  *
- *  Send feedback to: <megaraidlinux@lsi.com>
+ *  Send feedback to: megaraidlinux.pdl@avagotech.com
  *
- *  Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
- *     ATTN: Linuxraid
+ *  Mail to: Avago Technologies, 350 West Trimble Road, Building 90,
+ *  San Jose, California 95131
  */
 
 #ifndef _MEGARAID_SAS_FUSION_H_
@@ -834,8 +836,6 @@ struct fusion_context {
 
        u32 max_map_sz;
        u32 current_map_sz;
-       u32 old_map_sz;
-       u32 new_map_sz;
        u32 drv_map_sz;
        u32 drv_map_pages;
        u8 fast_path_io;
index c80ed0482649c4ca92452c0ecd16fe6ccb89c48c..8431eb10bbb1fa4f89bdbfbbdb2e5a74b3c10086 100644 (file)
@@ -1179,15 +1179,14 @@ _scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
 }
 
 /**
- * _scsih_adjust_queue_depth - setting device queue depth
+ * _scsih_change_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
  *
- *
- * Returns nothing
+ * Returns queue depth.
  */
-static void
-_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
+static int
+_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
        struct Scsi_Host *shost = sdev->host;
        int max_depth;
@@ -1217,63 +1216,11 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
  not_sata:
-
        if (!sdev->tagged_supported)
                max_depth = 1;
        if (qdepth > max_depth)
                qdepth = max_depth;
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-}
-
-/**
- * _scsih_change_queue_depth - setting device queue depth
- * @sdev: scsi device struct
- * @qdepth: requested queue depth
- * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
- * (see include/scsi/scsi_host.h for definition)
- *
- * Returns queue depth.
- */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
-       if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
-               _scsih_adjust_queue_depth(sdev, qdepth);
-       else if (reason == SCSI_QDEPTH_QFULL)
-               scsi_track_queue_full(sdev, qdepth);
-       else
-               return -EOPNOTSUPP;
-
-       if (sdev->inquiry_len > 7)
-               sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
-               "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
-               sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
-               sdev->ordered_tags, sdev->scsi_level,
-               (sdev->inquiry[7] & 2) >> 1);
-
-       return sdev->queue_depth;
-}
-
-/**
- * _scsih_change_queue_type - changing device queue tag type
- * @sdev: scsi device struct
- * @tag_type: requested tag type
- *
- * Returns queue tag type.
- */
-static int
-_scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag_type);
-               if (tag_type)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag_type = 0;
-
-       return tag_type;
+       return scsi_change_queue_depth(sdev, qdepth);
 }
 
 /**
@@ -2104,7 +2051,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
                            r_level, raid_device->handle,
                            (unsigned long long)raid_device->wwid,
                            raid_device->num_pds, ds);
-               _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+               _scsih_change_queue_depth(sdev, qdepth);
                /* raid transport support */
                if (!ioc->is_warpdrive)
                        _scsih_set_level(sdev, raid_device->volume_type);
@@ -2169,7 +2116,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
                _scsih_display_sata_capabilities(ioc, handle, sdev);
 
 
-       _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+       _scsih_change_queue_depth(sdev, qdepth);
 
        if (ssp_target) {
                sas_read_port_mode_page(sdev);
@@ -3966,16 +3913,8 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
                mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
 
        /* set tags */
-       if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
-               if (scmd->device->tagged_supported) {
-                       if (scmd->device->ordered_tags)
-                               mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
-                       else
-                               mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
-               } else
-                       mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
-       } else
-               mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+       mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+
        /* Make sure Device is not raid volume.
         * We do not expose raid functionality to upper layer for warpdrive.
         */
@@ -7653,7 +7592,7 @@ static struct scsi_host_template scsih_driver_template = {
        .scan_finished                  = _scsih_scan_finished,
        .scan_start                     = _scsih_scan_start,
        .change_queue_depth             = _scsih_change_queue_depth,
-       .change_queue_type              = _scsih_change_queue_type,
+       .change_queue_type              = scsi_change_queue_type,
        .eh_abort_handler               = _scsih_abort,
        .eh_device_reset_handler        = _scsih_dev_reset,
        .eh_target_reset_handler        = _scsih_target_reset,
@@ -7667,6 +7606,7 @@ static struct scsi_host_template scsih_driver_template = {
        .use_clustering                 = ENABLE_CLUSTERING,
        .shost_attrs                    = mpt2sas_host_attrs,
        .sdev_attrs                     = mpt2sas_dev_attrs,
+       .track_queue_depth              = 1,
 };
 
 /**
index 857276b8880f4b94e8578bdc237cc9683d180c29..a2b60991efd4f5651f0eab185156c08e3db1a26c 100644 (file)
@@ -1053,9 +1053,15 @@ _scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
        return found;
 }
 
-
-static void
-_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
+/**
+ * _scsih_change_queue_depth - setting device queue depth
+ * @sdev: scsi device struct
+ * @qdepth: requested queue depth
+ *
+ * Returns queue depth.
+ */
+static int
+_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
        struct Scsi_Host *shost = sdev->host;
        int max_depth;
@@ -1090,61 +1096,9 @@ _scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth)
                max_depth = 1;
        if (qdepth > max_depth)
                qdepth = max_depth;
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+       return scsi_change_queue_depth(sdev, qdepth);
 }
 
-/**
- * _scsih_change_queue_depth - setting device queue depth
- * @sdev: scsi device struct
- * @qdepth: requested queue depth
- * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP
- * (see include/scsi/scsi_host.h for definition)
- *
- * Returns queue depth.
- */
-static int
-_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
-       if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP)
-               _scsih_adjust_queue_depth(sdev, qdepth);
-       else if (reason == SCSI_QDEPTH_QFULL)
-               scsi_track_queue_full(sdev, qdepth);
-       else
-               return -EOPNOTSUPP;
-
-       if (sdev->inquiry_len > 7)
-               sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " \
-               "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
-               sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
-               sdev->ordered_tags, sdev->scsi_level,
-               (sdev->inquiry[7] & 2) >> 1);
-
-       return sdev->queue_depth;
-}
-
-/**
- * _scsih_change_queue_type - changing device queue tag type
- * @sdev: scsi device struct
- * @tag_type: requested tag type
- *
- * Returns queue tag type.
- */
-static int
-_scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag_type);
-               if (tag_type)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag_type = 0;
-
-       return tag_type;
-}
-
-
 /**
  * _scsih_target_alloc - target add routine
  * @starget: scsi target struct
@@ -1762,7 +1716,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
                         raid_device->num_pds, ds);
 
 
-               _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+               _scsih_change_queue_depth(sdev, qdepth);
 
 /* raid transport support */
                _scsih_set_level(sdev, raid_device->volume_type);
@@ -1828,7 +1782,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
                _scsih_display_sata_capabilities(ioc, handle, sdev);
 
 
-       _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT);
+       _scsih_change_queue_depth(sdev, qdepth);
 
        if (ssp_target) {
                sas_read_port_mode_page(sdev);
@@ -3586,16 +3540,7 @@ _scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
                mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
 
        /* set tags */
-       if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
-               if (scmd->device->tagged_supported) {
-                       if (scmd->device->ordered_tags)
-                               mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
-                       else
-                               mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
-               } else
-                       mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
-       } else
-               mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+       mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
 
        if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
            scmd->cmd_len != 32)
@@ -7284,7 +7229,7 @@ static struct scsi_host_template scsih_driver_template = {
        .scan_finished                  = _scsih_scan_finished,
        .scan_start                     = _scsih_scan_start,
        .change_queue_depth             = _scsih_change_queue_depth,
-       .change_queue_type              = _scsih_change_queue_type,
+       .change_queue_type              = scsi_change_queue_type,
        .eh_abort_handler               = _scsih_abort,
        .eh_device_reset_handler        = _scsih_dev_reset,
        .eh_target_reset_handler        = _scsih_target_reset,
@@ -7298,6 +7243,7 @@ static struct scsi_host_template scsih_driver_template = {
        .use_clustering                 = ENABLE_CLUSTERING,
        .shost_attrs                    = mpt3sas_host_attrs,
        .sdev_attrs                     = mpt3sas_dev_attrs,
+       .track_queue_depth              = 1,
 };
 
 /**
index eacee48a955c56903b98b3f1c61b55219df0e2c9..f15df3de6790eeea406dd5593f3e87e74c83957f 100644 (file)
 
 #include "mv_sas.h"
 
-static int lldd_max_execute_num = 1;
-module_param_named(collector, lldd_max_execute_num, int, S_IRUGO);
-MODULE_PARM_DESC(collector, "\n"
-       "\tIf greater than one, tells the SAS Layer to run in Task Collector\n"
-       "\tMode.  If 1 or 0, tells the SAS Layer to run in Direct Mode.\n"
-       "\tThe mvsas SAS LLDD supports both modes.\n"
-       "\tDefault: 1 (Direct Mode).\n");
-
 int interrupt_coalescing = 0x80;
 
 static struct scsi_transport_template *mvs_stt;
-struct kmem_cache *mvs_task_list_cache;
 static const struct mvs_chip_info mvs_chips[] = {
        [chip_6320] =   { 1, 2, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
        [chip_6440] =   { 1, 4, 0x400, 17, 16, 6,  9, &mvs_64xx_dispatch, },
@@ -76,6 +67,8 @@ static struct scsi_host_template mvs_sht = {
        .target_destroy         = sas_target_destroy,
        .ioctl                  = sas_ioctl,
        .shost_attrs            = mvst_host_attrs,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 static struct sas_domain_function_template mvs_transport_ops = {
@@ -511,14 +504,11 @@ static void  mvs_post_sas_ha_init(struct Scsi_Host *shost,
 
        sha->num_phys = nr_core * chip_info->n_phy;
 
-       sha->lldd_max_execute_num = lldd_max_execute_num;
-
        if (mvi->flags & MVF_FLAG_SOC)
                can_queue = MVS_SOC_CAN_QUEUE;
        else
                can_queue = MVS_CHIP_SLOT_SZ;
 
-       sha->lldd_queue_size = can_queue;
        shost->sg_tablesize = min_t(u16, SG_ALL, MVS_MAX_SG);
        shost->can_queue = can_queue;
        mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
@@ -831,16 +821,7 @@ static int __init mvs_init(void)
        if (!mvs_stt)
                return -ENOMEM;
 
-       mvs_task_list_cache = kmem_cache_create("mvs_task_list", sizeof(struct mvs_task_list),
-                                                        0, SLAB_HWCACHE_ALIGN, NULL);
-       if (!mvs_task_list_cache) {
-               rc = -ENOMEM;
-               mv_printk("%s: mvs_task_list_cache alloc failed! \n", __func__);
-               goto err_out;
-       }
-
        rc = pci_register_driver(&mvs_pci_driver);
-
        if (rc)
                goto err_out;
 
@@ -855,7 +836,6 @@ static void __exit mvs_exit(void)
 {
        pci_unregister_driver(&mvs_pci_driver);
        sas_release_transport(mvs_stt);
-       kmem_cache_destroy(mvs_task_list_cache);
 }
 
 struct device_attribute *mvst_host_attrs[] = {
index ac52f7c99513fae638379cb188371947642f0a87..85d86a5cdb60ecf708e49169f19bde250c7cba0b 100644 (file)
@@ -852,43 +852,7 @@ prep_out:
        return rc;
 }
 
-static struct mvs_task_list *mvs_task_alloc_list(int *num, gfp_t gfp_flags)
-{
-       struct mvs_task_list *first = NULL;
-
-       for (; *num > 0; --*num) {
-               struct mvs_task_list *mvs_list = kmem_cache_zalloc(mvs_task_list_cache, gfp_flags);
-
-               if (!mvs_list)
-                       break;
-
-               INIT_LIST_HEAD(&mvs_list->list);
-               if (!first)
-                       first = mvs_list;
-               else
-                       list_add_tail(&mvs_list->list, &first->list);
-
-       }
-
-       return first;
-}
-
-static inline void mvs_task_free_list(struct mvs_task_list *mvs_list)
-{
-       LIST_HEAD(list);
-       struct list_head *pos, *a;
-       struct mvs_task_list *mlist = NULL;
-
-       __list_add(&list, mvs_list->list.prev, &mvs_list->list);
-
-       list_for_each_safe(pos, a, &list) {
-               list_del_init(pos);
-               mlist = list_entry(pos, struct mvs_task_list, list);
-               kmem_cache_free(mvs_task_list_cache, mlist);
-       }
-}
-
-static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
+static int mvs_task_exec(struct sas_task *task, gfp_t gfp_flags,
                                struct completion *completion, int is_tmf,
                                struct mvs_tmf_task *tmf)
 {
@@ -912,74 +876,9 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
        return rc;
 }
 
-static int mvs_collector_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
-                               struct completion *completion, int is_tmf,
-                               struct mvs_tmf_task *tmf)
+int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags)
 {
-       struct domain_device *dev = task->dev;
-       struct mvs_prv_info *mpi = dev->port->ha->lldd_ha;
-       struct mvs_info *mvi = NULL;
-       struct sas_task *t = task;
-       struct mvs_task_list *mvs_list = NULL, *a;
-       LIST_HEAD(q);
-       int pass[2] = {0};
-       u32 rc = 0;
-       u32 n = num;
-       unsigned long flags = 0;
-
-       mvs_list = mvs_task_alloc_list(&n, gfp_flags);
-       if (n) {
-               printk(KERN_ERR "%s: mvs alloc list failed.\n", __func__);
-               rc = -ENOMEM;
-               goto free_list;
-       }
-
-       __list_add(&q, mvs_list->list.prev, &mvs_list->list);
-
-       list_for_each_entry(a, &q, list) {
-               a->task = t;
-               t = list_entry(t->list.next, struct sas_task, list);
-       }
-
-       list_for_each_entry(a, &q , list) {
-
-               t = a->task;
-               mvi = ((struct mvs_device *)t->dev->lldd_dev)->mvi_info;
-
-               spin_lock_irqsave(&mvi->lock, flags);
-               rc = mvs_task_prep(t, mvi, is_tmf, tmf, &pass[mvi->id]);
-               if (rc)
-                       dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
-               spin_unlock_irqrestore(&mvi->lock, flags);
-       }
-
-       if (likely(pass[0]))
-                       MVS_CHIP_DISP->start_delivery(mpi->mvi[0],
-                               (mpi->mvi[0]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
-
-       if (likely(pass[1]))
-                       MVS_CHIP_DISP->start_delivery(mpi->mvi[1],
-                               (mpi->mvi[1]->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
-
-       list_del_init(&q);
-
-free_list:
-       if (mvs_list)
-               mvs_task_free_list(mvs_list);
-
-       return rc;
-}
-
-int mvs_queue_command(struct sas_task *task, const int num,
-                       gfp_t gfp_flags)
-{
-       struct mvs_device *mvi_dev = task->dev->lldd_dev;
-       struct sas_ha_struct *sas = mvi_dev->mvi_info->sas;
-
-       if (sas->lldd_max_execute_num < 2)
-               return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL);
-       else
-               return mvs_collector_task_exec(task, num, gfp_flags, NULL, 0, NULL);
+       return mvs_task_exec(task, gfp_flags, NULL, 0, NULL);
 }
 
 static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
@@ -1411,7 +1310,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
                task->slow_task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
                add_timer(&task->slow_task->timer);
 
-               res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf);
+               res = mvs_task_exec(task, GFP_KERNEL, NULL, 1, tmf);
 
                if (res) {
                        del_timer(&task->slow_task->timer);
index d6b19dc80bee522a934bb1bb64dd56c1ecad0c51..dc409c04747ae668c629ffe468965302fcc853ac 100644 (file)
@@ -65,7 +65,6 @@ extern struct mvs_tgt_initiator mvs_tgt;
 extern struct mvs_info *tgt_mvi;
 extern const struct mvs_dispatch mvs_64xx_dispatch;
 extern const struct mvs_dispatch mvs_94xx_dispatch;
-extern struct kmem_cache *mvs_task_list_cache;
 
 #define DEV_IS_EXPANDER(type)  \
        ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE))
@@ -440,12 +439,6 @@ struct mvs_task_exec_info {
        int n_elem;
 };
 
-struct mvs_task_list {
-       struct sas_task *task;
-       struct list_head list;
-};
-
-
 /******************** function prototype *********************/
 void mvs_get_sas_addr(void *buf, u32 buflen);
 void mvs_tag_clear(struct mvs_info *mvi, u32 tag);
@@ -462,8 +455,7 @@ void mvs_set_sas_addr(struct mvs_info *mvi, int port_id, u32 off_lo,
                      u32 off_hi, u64 sas_addr);
 void mvs_scan_start(struct Scsi_Host *shost);
 int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
-int mvs_queue_command(struct sas_task *task, const int num,
-                       gfp_t gfp_flags);
+int mvs_queue_command(struct sas_task *task, gfp_t gfp_flags);
 int mvs_abort_task(struct sas_task *task);
 int mvs_abort_task_set(struct domain_device *dev, u8 *lun);
 int mvs_clear_aca(struct domain_device *dev, u8 *lun);
index a7305ffc359d2f098647253be030ae33243e631a..5b93ed810f6ef099e265a5e45305ef26224ee4bd 100644 (file)
@@ -7997,10 +7997,7 @@ static int ncr53c8xx_slave_configure(struct scsi_device *device)
        if (depth_to_use > MAX_TAGS)
                depth_to_use = MAX_TAGS;
 
-       scsi_adjust_queue_depth(device,
-                               (device->tagged_supported ?
-                                MSG_SIMPLE_TAG : 0),
-                               depth_to_use);
+       scsi_change_queue_depth(device, depth_to_use);
 
        /*
        **      Since the queue depth is not tunable under Linux,
index 5fd73d77c3af86b17344c1e544dd4ed22bdd6105..58cecd45b0f5d828e7e25c0e9f725e3c677fafa7 100644 (file)
@@ -4,7 +4,7 @@
 # Copyright (C) 2008 Panasas Inc.  All rights reserved.
 #
 # Authors:
-#   Boaz Harrosh <bharrosh@panasas.com>
+#   Boaz Harrosh <ooo@electrozaur.com>
 #   Benny Halevy <bhalevy@panasas.com>
 #
 # This program is free software; you can redistribute it and/or modify
index a0703514eb0f9ce7af8d5b896764b9c2f71b359e..347cc5e337494e86621853063e8ec59bfab8d540 100644 (file)
@@ -4,7 +4,7 @@
 # Copyright (C) 2008 Panasas Inc.  All rights reserved.
 #
 # Authors:
-#   Boaz Harrosh <bharrosh@panasas.com>
+#   Boaz Harrosh <ooo@electrozaur.com>
 #   Benny Halevy <bhalevy@panasas.com>
 #
 # This program is free software; you can redistribute it and/or modify
index 579e491f11dfe80ee7eb6285e581ff53b987116d..26341261bb5c1a22db6820df9dbc7f3bfef01b90 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
index fd19fd8468acf37a895d09121a62326cc0911f90..488c3929f19a95b84377d9ae522fb9b236857d3c 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -57,7 +57,7 @@
 
 enum { OSD_REQ_RETRIES = 1 };
 
-MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_AUTHOR("Boaz Harrosh <ooo@electrozaur.com>");
 MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
 MODULE_LICENSE("GPL");
 
index e1d9a4c4c4b3b256677e3f2987d97dcf95cdf2a9..243eab3d10d094e6dffff35f793f1c518e49fc15 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -74,7 +74,7 @@
 static const char osd_name[] = "osd";
 static const char *osd_version_string = "open-osd 0.2.1";
 
-MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_AUTHOR("Boaz Harrosh <ooo@electrozaur.com>");
 MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
@@ -540,9 +540,9 @@ static int osd_remove(struct device *dev)
  */
 
 static struct scsi_driver osd_driver = {
-       .owner                  = THIS_MODULE,
        .gendrv = {
                .name           = osd_name,
+               .owner          = THIS_MODULE,
                .probe          = osd_probe,
                .remove         = osd_remove,
        }
index dff37a250d7906ab7c203099e6938bd197d1bb04..5033223f6287703c3f74b8eb5b8048d37845b44a 100644 (file)
@@ -172,9 +172,9 @@ static int osst_probe(struct device *);
 static int osst_remove(struct device *);
 
 static struct scsi_driver osst_template = {
-       .owner                  = THIS_MODULE,
        .gendrv = {
                .name           =  "osst",
+               .owner          = THIS_MODULE,
                .probe          = osst_probe,
                .remove         = osst_remove,
        }
@@ -259,9 +259,10 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
                   SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
                   SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
                if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
-                               name, scode, sense[12], sense[13]);
+                                 name, scode, sense[12], sense[13]);
                if (cmdstatp->have_sense)
-                       __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
+                       __scsi_print_sense(STp->device, name,
+                                          SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
        }
        else
 #endif
@@ -275,7 +276,8 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
                 SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
                if (cmdstatp->have_sense) {
                        printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
-                       __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
+                       __scsi_print_sense(STp->device, name,
+                                          SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
                }
                else {
                        static  int     notyetprinted = 1;
@@ -3325,19 +3327,18 @@ static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpn
 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
 static int do_door_lock(struct osst_tape * STp, int do_lock)
 {
-       int retval, cmd;
+       int retval;
 
-       cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
 #if DEBUG
        printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
 #endif
-       retval = scsi_ioctl(STp->device, cmd, NULL);
-       if (!retval) {
+
+       retval = scsi_set_medium_removal(STp->device,
+                       do_lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
+       if (!retval)
                STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
-       }
-       else {
+       else
                STp->door_locked = ST_LOCK_FAILS;
-       }
        return retval;
 }
 
@@ -4967,10 +4968,10 @@ static long osst_ioctl(struct file * file,
         * may try and take the device offline, in which case all further
         * access to the device is prohibited.
         */
-       if( !scsi_block_when_processing_errors(STp->device) ) {
-               retval = (-ENXIO);
+       retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in,
+                       file->f_flags & O_NDELAY);
+       if (retval)
                goto out;
-       }
 
        cmd_type = _IOC_TYPE(cmd_in);
        cmd_nr   = _IOC_NR(cmd_in);
index 80bacb5dc1d4170aeb4fa1d8c6a786ced42433ba..e81eadd08afc776d6be23b2e2af8f550841da1b4 100644 (file)
@@ -1,6 +1,4 @@
-#define AUTOSENSE
 #define PSEUDO_DMA
-#define FOO
 #define UNSAFE  /* Not unsafe for PAS16 -- use it */
 #define PDEBUG 0
 
  * Media Vision
  * (510) 770-8600
  * (800) 348-7116
- * 
- * and 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 /*
- * Options : 
- * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- *      for commands that return with a CHECK CONDITION status. 
- *
- * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512
- *      bytes at a time.  Since interrupts are disabled by default during
- *      these transfers, we might need this to give reasonable interrupt
- *      service time if the transfer size gets too large.
- *
- * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
- * increase compared to polled I/O.
- *
- * PARITY - enable parity checking.  Not supported.
- * 
- * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
- *
- * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  This
- *         parameter comes from the NCR5380 code.  It is NOT unsafe with
- *         the PAS16 and you should use it.  If you don't you will have
- *         a problem with dropped characters during high speed
- *         communications during SCSI transfers.  If you really don't
- *         want to use UNSAFE you can try defining LIMIT_TRANSFERSIZE or
- *         twiddle with the transfer size in the high level code.
- *
- * USLEEP - enable support for devices that don't disconnect.  Untested.
- *
  * The card is detected and initialized in one of several ways : 
  * 1.  Autoprobe (default) - There are many different models of
  *     the Pro Audio Spectrum/Studio 16, and I only have one of
  *   If you have problems with your card not being recognized, use
  *   the LILO command line override.  Try to get it recognized without
  *   interrupts.  Ie, for a board at the default 0x388 base port,
- *   boot: linux pas16=0x388,255
+ *   boot: linux pas16=0x388,0
  *
- *   SCSI_IRQ_NONE (255) should be specified for no interrupt,
+ *   NO_IRQ (0) should be specified for no interrupt,
  *   IRQ_AUTO (254) to autoprobe for an IRQ line if overridden
  *   on the command line.
- *
- *   (IRQ_AUTO == 254, SCSI_IRQ_NONE == 255 in NCR5380.h)
  */
  
 #include <linux/module.h>
 #include <linux/stat.h>
 #include <linux/init.h>
 
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include "pas16.h"
 #define AUTOPROBE_IRQ
 #include "NCR5380.h"
 
 
-static int pas_maxi = 0;
-static int pas_wmaxi = 0;
 static unsigned short pas16_addr = 0;
 static int pas16_irq = 0;
  
@@ -337,6 +292,7 @@ static int __init
 }
 
 
+#ifndef MODULE
 /*
  * Function : pas16_setup(char *str, int *ints)
  *
@@ -347,10 +303,13 @@ static int __init
  *
  */
 
-void __init pas16_setup(char *str, int *ints)
+static int __init pas16_setup(char *str)
 {
     static int commandline_current = 0;
     int i;
+    int ints[10];
+
+    get_options(str, ARRAY_SIZE(ints), ints);
     if (ints[0] != 2) 
        printk("pas16_setup : usage pas16=io_port,irq\n");
     else 
@@ -364,8 +323,12 @@ void __init pas16_setup(char *str, int *ints)
                }
            ++commandline_current;
        }
+    return 1;
 }
 
+__setup("pas16=", pas16_setup);
+#endif
+
 /* 
  * Function : int pas16_detect(struct scsi_host_template * tpnt)
  *
@@ -379,7 +342,7 @@ void __init pas16_setup(char *str, int *ints)
  *
  */
 
-int __init pas16_detect(struct scsi_host_template * tpnt)
+static int __init pas16_detect(struct scsi_host_template *tpnt)
 {
     static int current_override = 0;
     static unsigned short current_base = 0;
@@ -387,10 +350,6 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
     unsigned short io_port;
     int  count;
 
-    tpnt->proc_name = "pas16";
-    tpnt->show_info = pas16_show_info;
-    tpnt->write_info = pas16_write_info;
-
     if (pas16_addr != 0) {
        overrides[0].io_port = pas16_addr;
        /*
@@ -452,15 +411,19 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
        else 
            instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
 
-       if (instance->irq != SCSI_IRQ_NONE) 
+       /* Compatibility with documented NCR5380 kernel parameters */
+       if (instance->irq == 255)
+               instance->irq = NO_IRQ;
+
+       if (instance->irq != NO_IRQ)
            if (request_irq(instance->irq, pas16_intr, 0,
                            "pas16", instance)) {
                printk("scsi%d : IRQ%d not free, interrupts disabled\n", 
                    instance->host_no, instance->irq);
-               instance->irq = SCSI_IRQ_NONE;
+               instance->irq = NO_IRQ;
            } 
 
-       if (instance->irq == SCSI_IRQ_NONE) {
+       if (instance->irq == NO_IRQ) {
            printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
            printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
            /* Disable 5380 interrupts, leave drive params the same */
@@ -472,17 +435,6 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
        printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
 #endif
 
-       printk("scsi%d : at 0x%04x", instance->host_no, (int) 
-           instance->io_port);
-       if (instance->irq == SCSI_IRQ_NONE)
-           printk (" interrupts disabled");
-       else 
-           printk (" irq %d", instance->irq);
-       printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
-           CAN_QUEUE, CMD_PER_LUN, PAS16_PUBLIC_RELEASE);
-       NCR5380_print_options(instance);
-       printk("\n");
-
        ++current_override;
        ++count;
     }
@@ -509,8 +461,8 @@ int __init pas16_detect(struct scsi_host_template * tpnt)
  * and matching the H_C_S coordinates to what DOS uses.
  */
 
-int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev,
-               sector_t capacity, int * ip)
+static int pas16_biosparam(struct scsi_device *sdev, struct block_device *dev,
+                           sector_t capacity, int *ip)
 {
   int size = capacity;
   ip[0] = 64;
@@ -547,6 +499,7 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
        P_DATA_REG_OFFSET);
     register int i = len;
     int ii = 0;
+    struct NCR5380_hostdata *hostdata = shost_priv(instance);
 
     while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) )
         ++ii;
@@ -559,8 +512,8 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
            instance->host_no);
        return -1;
     }
-   if (ii > pas_maxi)
-      pas_maxi = ii;
+    if (ii > hostdata->spin_max_r)
+        hostdata->spin_max_r = ii;
     return 0;
 }
 
@@ -583,6 +536,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
     register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET);
     register int i = len;
     int ii = 0;
+    struct NCR5380_hostdata *hostdata = shost_priv(instance);
 
     while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) )
         ++ii;
@@ -595,8 +549,8 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
            instance->host_no);
        return -1;
     }
-    if (ii > pas_maxi)
-        pas_wmaxi = ii;
+    if (ii > hostdata->spin_max_w)
+        hostdata->spin_max_w = ii;
     return 0;
 }
 
@@ -604,7 +558,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
 
 static int pas16_release(struct Scsi_Host *shost)
 {
-       if (shost->irq)
+       if (shost->irq != NO_IRQ)
                free_irq(shost->irq, shost);
        NCR5380_exit(shost);
        if (shost->io_port && shost->n_io_port)
@@ -617,6 +571,10 @@ static struct scsi_host_template driver_template = {
        .name           = "Pro Audio Spectrum-16 SCSI",
        .detect         = pas16_detect,
        .release        = pas16_release,
+       .proc_name      = "pas16",
+       .show_info      = pas16_show_info,
+       .write_info     = pas16_write_info,
+       .info           = pas16_info,
        .queuecommand   = pas16_queue_command,
        .eh_abort_handler = pas16_abort,
        .eh_bus_reset_handler = pas16_bus_reset,
index aa528f53c5339582bcf74fd15aaa4a009cf82e83..c6109c80050bdf59d2b6933ba43579f8afa896ed 100644 (file)
  * Media Vision
  * (510) 770-8600
  * (800) 348-7116
- * 
- * and 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 
 #ifndef PAS16_H
 #define PAS16_H
 
-#define PAS16_PUBLIC_RELEASE 3
-
 #define PDEBUG_INIT    0x1
 #define PDEBUG_TRANSFER 0x2
 
 
 
 #ifndef ASM
-static int pas16_abort(Scsi_Cmnd *);
-static int pas16_biosparam(struct scsi_device *, struct block_device *,
-                          sector_t, int*);
-static int pas16_detect(struct scsi_host_template *);
-static int pas16_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int pas16_bus_reset(Scsi_Cmnd *);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 2
@@ -161,6 +141,7 @@ static int pas16_bus_reset(Scsi_Cmnd *);
 #define NCR5380_queue_command pas16_queue_command
 #define NCR5380_abort pas16_abort
 #define NCR5380_bus_reset pas16_bus_reset
+#define NCR5380_info pas16_info
 #define NCR5380_show_info pas16_show_info
 #define NCR5380_write_info pas16_write_info
 
index 666bf5af06e2d29d26fae7b563a111740c14c9ce..329aba0083aba7f3556610a7d924241c218ae812 100644 (file)
@@ -89,6 +89,8 @@ static struct scsi_host_template pm8001_sht = {
        .target_destroy         = sas_target_destroy,
        .ioctl                  = sas_ioctl,
        .shost_attrs            = pm8001_host_attrs,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 /**
@@ -599,8 +601,6 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host *shost,
        sha->lldd_module = THIS_MODULE;
        sha->sas_addr = &pm8001_ha->sas_addr[0];
        sha->num_phys = chip_info->n_phy;
-       sha->lldd_max_execute_num = 1;
-       sha->lldd_queue_size = PM8001_CAN_QUEUE;
        sha->core.shost = shost;
 }
 
index 76570e6a547d26df5cfaffa715c9f49310085467..b93f289b42b3629ed4125fa8ffcf56d5e717f842 100644 (file)
@@ -350,7 +350,7 @@ static int sas_find_local_port_id(struct domain_device *dev)
   */
 #define DEV_IS_GONE(pm8001_dev)        \
        ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
-static int pm8001_task_exec(struct sas_task *task, const int num,
+static int pm8001_task_exec(struct sas_task *task,
        gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
 {
        struct domain_device *dev = task->dev;
@@ -360,7 +360,6 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
        struct sas_task *t = task;
        struct pm8001_ccb_info *ccb;
        u32 tag = 0xdeadbeef, rc, n_elem = 0;
-       u32 n = num;
        unsigned long flags = 0;
 
        if (!dev->port) {
@@ -387,18 +386,12 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
                                spin_unlock_irqrestore(&pm8001_ha->lock, flags);
                                t->task_done(t);
                                spin_lock_irqsave(&pm8001_ha->lock, flags);
-                               if (n > 1)
-                                       t = list_entry(t->list.next,
-                                                       struct sas_task, list);
                                continue;
                        } else {
                                struct task_status_struct *ts = &t->task_status;
                                ts->resp = SAS_TASK_UNDELIVERED;
                                ts->stat = SAS_PHY_DOWN;
                                t->task_done(t);
-                               if (n > 1)
-                                       t = list_entry(t->list.next,
-                                                       struct sas_task, list);
                                continue;
                        }
                }
@@ -460,9 +453,7 @@ static int pm8001_task_exec(struct sas_task *task, const int num,
                t->task_state_flags |= SAS_TASK_AT_INITIATOR;
                spin_unlock(&t->task_state_lock);
                pm8001_dev->running_req++;
-               if (n > 1)
-                       t = list_entry(t->list.next, struct sas_task, list);
-       } while (--n);
+       } while (0);
        rc = 0;
        goto out_done;
 
@@ -483,14 +474,11 @@ out_done:
   * pm8001_queue_command - register for upper layer used, all IO commands sent
   * to HBA are from this interface.
   * @task: the task to be execute.
-  * @num: if can_queue great than 1, the task can be queued up. for SMP task,
-  * we always execute one one time
   * @gfp_flags: gfp_flags
   */
-int pm8001_queue_command(struct sas_task *task, const int num,
-               gfp_t gfp_flags)
+int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
 {
-       return pm8001_task_exec(task, num, gfp_flags, 0, NULL);
+       return pm8001_task_exec(task, gfp_flags, 0, NULL);
 }
 
 /**
@@ -708,7 +696,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev,
                task->slow_task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
                add_timer(&task->slow_task->timer);
 
-               res = pm8001_task_exec(task, 1, GFP_KERNEL, 1, tmf);
+               res = pm8001_task_exec(task, GFP_KERNEL, 1, tmf);
 
                if (res) {
                        del_timer(&task->slow_task->timer);
index f6b2ac59dae4f66dd99c1455cf7674e6113eb5bc..8dd8b7840f04259293180e8e77c44c51507fe7e4 100644 (file)
@@ -623,8 +623,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
        void *funcdata);
 void pm8001_scan_start(struct Scsi_Host *shost);
 int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time);
-int pm8001_queue_command(struct sas_task *task, const int num,
-       gfp_t gfp_flags);
+int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags);
 int pm8001_abort_task(struct sas_task *task);
 int pm8001_abort_task_set(struct domain_device *dev, u8 *lun);
 int pm8001_clear_aca(struct domain_device *dev, u8 *lun);
index bcb64eb1387f0565976449eb9a45941ec7186514..b1b1f66b1ab7817f739da1308f1cd92932c164dc 100644 (file)
@@ -249,15 +249,11 @@ static int pmcraid_slave_configure(struct scsi_device *scsi_dev)
                                      PMCRAID_VSET_MAX_SECTORS);
        }
 
-       if (scsi_dev->tagged_supported &&
-           (RES_IS_GSCSI(res->cfg_entry) || RES_IS_VSET(res->cfg_entry))) {
-               scsi_activate_tcq(scsi_dev, scsi_dev->queue_depth);
-               scsi_adjust_queue_depth(scsi_dev, MSG_SIMPLE_TAG,
-                                       scsi_dev->host->cmd_per_lun);
-       } else {
-               scsi_adjust_queue_depth(scsi_dev, 0,
-                                       scsi_dev->host->cmd_per_lun);
-       }
+       /*
+        * We never want to report TCQ support for these types of devices.
+        */
+       if (!RES_IS_GSCSI(res->cfg_entry) && !RES_IS_VSET(res->cfg_entry))
+               scsi_dev->tagged_supported = 0;
 
        return 0;
 }
@@ -289,54 +285,17 @@ static void pmcraid_slave_destroy(struct scsi_device *scsi_dev)
  * pmcraid_change_queue_depth - Change the device's queue depth
  * @scsi_dev: scsi device struct
  * @depth: depth to set
- * @reason: calling context
  *
  * Return value
  *     actual depth set
  */
-static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth,
-                                     int reason)
+static int pmcraid_change_queue_depth(struct scsi_device *scsi_dev, int depth)
 {
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               return -EOPNOTSUPP;
-
        if (depth > PMCRAID_MAX_CMD_PER_LUN)
                depth = PMCRAID_MAX_CMD_PER_LUN;
-
-       scsi_adjust_queue_depth(scsi_dev, scsi_get_tag_type(scsi_dev), depth);
-
-       return scsi_dev->queue_depth;
+       return scsi_change_queue_depth(scsi_dev, depth);
 }
 
-/**
- * pmcraid_change_queue_type - Change the device's queue type
- * @scsi_dev: scsi device struct
- * @tag: type of tags to use
- *
- * Return value:
- *     actual queue type set
- */
-static int pmcraid_change_queue_type(struct scsi_device *scsi_dev, int tag)
-{
-       struct pmcraid_resource_entry *res;
-
-       res = (struct pmcraid_resource_entry *)scsi_dev->hostdata;
-
-       if ((res) && scsi_dev->tagged_supported &&
-           (RES_IS_GSCSI(res->cfg_entry) || RES_IS_VSET(res->cfg_entry))) {
-               scsi_set_tag_type(scsi_dev, tag);
-
-               if (tag)
-                       scsi_activate_tcq(scsi_dev, scsi_dev->queue_depth);
-               else
-                       scsi_deactivate_tcq(scsi_dev, scsi_dev->queue_depth);
-       } else
-               tag = 0;
-
-       return tag;
-}
-
-
 /**
  * pmcraid_init_cmdblk - initializes a command block
  *
@@ -3174,36 +3133,6 @@ static int pmcraid_eh_host_reset_handler(struct scsi_cmnd *scmd)
        return pmcraid_reset_bringup(pinstance) == 0 ? SUCCESS : FAILED;
 }
 
-/**
- * pmcraid_task_attributes - Translate SPI Q-Tags to task attributes
- * @scsi_cmd:   scsi command struct
- *
- * Return value
- *       number of tags or 0 if the task is not tagged
- */
-static u8 pmcraid_task_attributes(struct scsi_cmnd *scsi_cmd)
-{
-       char tag[2];
-       u8 rc = 0;
-
-       if (scsi_populate_tag_msg(scsi_cmd, tag)) {
-               switch (tag[0]) {
-               case MSG_SIMPLE_TAG:
-                       rc = TASK_TAG_SIMPLE;
-                       break;
-               case MSG_HEAD_TAG:
-                       rc = TASK_TAG_QUEUE_HEAD;
-                       break;
-               case MSG_ORDERED_TAG:
-                       rc = TASK_TAG_ORDERED;
-                       break;
-               };
-       }
-
-       return rc;
-}
-
-
 /**
  * pmcraid_init_ioadls - initializes IOADL related fields in IOARCB
  * @cmd: pmcraid command struct
@@ -3559,7 +3488,9 @@ static int pmcraid_queuecommand_lck(
                }
 
                ioarcb->request_flags0 |= NO_LINK_DESCS;
-               ioarcb->request_flags1 |= pmcraid_task_attributes(scsi_cmd);
+
+               if (scsi_cmd->flags & SCMD_TAGGED)
+                       ioarcb->request_flags1 |= TASK_TAG_SIMPLE;
 
                if (RES_IS_GSCSI(res->cfg_entry))
                        ioarcb->request_flags1 |= DELAY_AFTER_RESET;
@@ -4320,7 +4251,7 @@ static struct scsi_host_template pmcraid_host_template = {
        .slave_configure = pmcraid_slave_configure,
        .slave_destroy = pmcraid_slave_destroy,
        .change_queue_depth = pmcraid_change_queue_depth,
-       .change_queue_type  = pmcraid_change_queue_type,
+       .change_queue_type  = scsi_change_queue_type,
        .can_queue = PMCRAID_MAX_IO_CMD,
        .this_id = -1,
        .sg_tablesize = PMCRAID_MAX_IOADLS,
@@ -4329,7 +4260,8 @@ static struct scsi_host_template pmcraid_host_template = {
        .cmd_per_lun = PMCRAID_MAX_CMD_PER_LUN,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = pmcraid_host_attrs,
-       .proc_name = PMCRAID_DRIVER_NAME
+       .proc_name = PMCRAID_DRIVER_NAME,
+       .use_blk_tags = 1,
 };
 
 /*
index ef23fabe3924ea138db50d14c354d0fb6a55c6ae..b3b48b5a984c54021e45aa5056efdf58500e2617 100644 (file)
@@ -220,10 +220,6 @@ static int ps3rom_queuecommand_lck(struct scsi_cmnd *cmd,
        unsigned char opcode;
        int res;
 
-#ifdef DEBUG
-       scsi_print_command(cmd);
-#endif
-
        priv->curr_cmd = cmd;
        cmd->scsi_done = done;
 
index 158020522dfbcfbded2bf0c1a22b7a94920d8d76..c68a66e8cfc195ec1e78e2022efed4d9d87f6845 100644 (file)
@@ -1224,10 +1224,9 @@ qla1280_slave_configure(struct scsi_device *device)
 
        if (device->tagged_supported &&
            (ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) {
-               scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
-                                       ha->bus_settings[bus].hiwat);
+               scsi_change_queue_depth(device, ha->bus_settings[bus].hiwat);
        } else {
-               scsi_adjust_queue_depth(device, 0, default_depth);
+               scsi_change_queue_depth(device, default_depth);
        }
 
        nv->bus[bus].target[target].parameter.enable_sync = device->sdtr;
index b1865a72ce59ab9172878efff5d3f7ffc4352aa2..7686bfe9a4a9e7ac42022c99321d20e0ff4c55f5 100644 (file)
@@ -752,8 +752,6 @@ extern void qla8044_set_idc_dontreset(struct scsi_qla_host *ha);
 extern int qla8044_rd_direct(struct scsi_qla_host *vha, const uint32_t crb_reg);
 extern void qla8044_wr_direct(struct scsi_qla_host *vha,
                              const uint32_t crb_reg, const uint32_t value);
-extern inline void qla8044_set_qsnt_ready(struct scsi_qla_host *vha);
-extern inline void qla8044_need_reset_handler(struct scsi_qla_host *vha);
 extern int qla8044_device_state_handler(struct scsi_qla_host *vha);
 extern void qla8044_clear_qsnt_ready(struct scsi_qla_host *vha);
 extern void qla8044_clear_drv_active(struct qla_hw_data *);
index f0edb07f3198f5597ddd09a41ee148e35e7d025c..a1ab25fca8742d2fcef03ca2a8646990799810cb 100644 (file)
@@ -325,7 +325,6 @@ qla2x00_start_scsi(srb_t *sp)
        struct qla_hw_data *ha;
        struct req_que *req;
        struct rsp_que *rsp;
-       char            tag[2];
 
        /* Setup device pointers. */
        ret = 0;
@@ -404,26 +403,7 @@ qla2x00_start_scsi(srb_t *sp)
        /* Set target ID and LUN number*/
        SET_TARGET_ID(ha, cmd_pkt->target, sp->fcport->loop_id);
        cmd_pkt->lun = cpu_to_le16(cmd->device->lun);
-
-       /* Update tagged queuing modifier */
-       if (scsi_populate_tag_msg(cmd, tag)) {
-               switch (tag[0]) {
-               case HEAD_OF_QUEUE_TAG:
-                       cmd_pkt->control_flags =
-                           __constant_cpu_to_le16(CF_HEAD_TAG);
-                       break;
-               case ORDERED_QUEUE_TAG:
-                       cmd_pkt->control_flags =
-                           __constant_cpu_to_le16(CF_ORDERED_TAG);
-                       break;
-               default:
-                       cmd_pkt->control_flags =
-                           __constant_cpu_to_le16(CF_SIMPLE_TAG);
-                       break;
-               }
-       } else {
-               cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
-       }
+       cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
 
        /* Load SCSI command packet. */
        memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len);
@@ -1264,7 +1244,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
        uint16_t                fcp_cmnd_len;
        struct fcp_cmnd         *fcp_cmnd;
        dma_addr_t              crc_ctx_dma;
-       char                    tag[2];
 
        cmd = GET_CMD_SP(sp);
 
@@ -1356,25 +1335,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
        cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32(
            MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
        fcp_cmnd->task_management = 0;
-
-       /*
-        * Update tagged queuing modifier if using command tag queuing
-        */
-       if (scsi_populate_tag_msg(cmd, tag)) {
-               switch (tag[0]) {
-               case HEAD_OF_QUEUE_TAG:
-                   fcp_cmnd->task_attribute = TSK_HEAD_OF_QUEUE;
-                   break;
-               case ORDERED_QUEUE_TAG:
-                   fcp_cmnd->task_attribute = TSK_ORDERED;
-                   break;
-               default:
-                   fcp_cmnd->task_attribute = TSK_SIMPLE;
-                   break;
-               }
-       } else {
-               fcp_cmnd->task_attribute = TSK_SIMPLE;
-       }
+       fcp_cmnd->task_attribute = TSK_SIMPLE;
 
        cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
 
@@ -1495,7 +1456,6 @@ qla24xx_start_scsi(srb_t *sp)
        struct scsi_cmnd *cmd = GET_CMD_SP(sp);
        struct scsi_qla_host *vha = sp->fcport->vha;
        struct qla_hw_data *ha = vha->hw;
-       char            tag[2];
 
        /* Setup device pointers. */
        ret = 0;
@@ -1578,22 +1538,7 @@ qla24xx_start_scsi(srb_t *sp)
        int_to_scsilun(cmd->device->lun, &cmd_pkt->lun);
        host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
-       /* Update tagged queuing modifier -- default is TSK_SIMPLE (0). */
-       if (scsi_populate_tag_msg(cmd, tag)) {
-               switch (tag[0]) {
-               case HEAD_OF_QUEUE_TAG:
-                       cmd_pkt->task = TSK_HEAD_OF_QUEUE;
-                       break;
-               case ORDERED_QUEUE_TAG:
-                       cmd_pkt->task = TSK_ORDERED;
-                       break;
-               default:
-                   cmd_pkt->task = TSK_SIMPLE;
-                   break;
-               }
-       } else {
-               cmd_pkt->task = TSK_SIMPLE;
-       }
+       cmd_pkt->task = TSK_SIMPLE;
 
        /* Load SCSI command packet. */
        memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
@@ -2310,7 +2255,6 @@ qla82xx_start_scsi(srb_t *sp)
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req = NULL;
        struct rsp_que *rsp = NULL;
-       char tag[2];
 
        /* Setup device pointers. */
        ret = 0;
@@ -2489,22 +2433,6 @@ sufficient_dsds:
                else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
                        ctx->fcp_cmnd->additional_cdb_len |= 2;
 
-               /*
-                * Update tagged queuing modifier -- default is TSK_SIMPLE (0).
-                */
-               if (scsi_populate_tag_msg(cmd, tag)) {
-                       switch (tag[0]) {
-                       case HEAD_OF_QUEUE_TAG:
-                               ctx->fcp_cmnd->task_attribute =
-                                   TSK_HEAD_OF_QUEUE;
-                               break;
-                       case ORDERED_QUEUE_TAG:
-                               ctx->fcp_cmnd->task_attribute =
-                                   TSK_ORDERED;
-                               break;
-                       }
-               }
-
                /* Populate the FCP_PRIO. */
                if (ha->flags.fcp_prio_enabled)
                        ctx->fcp_cmnd->task_attribute |=
@@ -2565,20 +2493,6 @@ sufficient_dsds:
                host_to_fcp_swap((uint8_t *)&cmd_pkt->lun,
                    sizeof(cmd_pkt->lun));
 
-               /*
-                * Update tagged queuing modifier -- default is TSK_SIMPLE (0).
-                */
-               if (scsi_populate_tag_msg(cmd, tag)) {
-                       switch (tag[0]) {
-                       case HEAD_OF_QUEUE_TAG:
-                               cmd_pkt->task = TSK_HEAD_OF_QUEUE;
-                               break;
-                       case ORDERED_QUEUE_TAG:
-                               cmd_pkt->task = TSK_ORDERED;
-                               break;
-                       }
-               }
-
                /* Populate the FCP_PRIO. */
                if (ha->flags.fcp_prio_enabled)
                        cmd_pkt->task |= sp->fcport->fcp_prio << 3;
index 80867599527d20b5dea861b9f3ce1d2dc1d0bc9b..6d190b4b82a072b2657e03ede8caa2d0a45e5d52 100644 (file)
@@ -3086,7 +3086,6 @@ qlafx00_start_scsi(srb_t *sp)
        struct cmd_type_7_fx00 *cmd_pkt;
        struct cmd_type_7_fx00 lcmd_pkt;
        struct scsi_lun llun;
-       char            tag[2];
 
        /* Setup device pointers. */
        ret = 0;
@@ -3157,18 +3156,6 @@ qlafx00_start_scsi(srb_t *sp)
        host_to_adap((uint8_t *)&llun, (uint8_t *)&lcmd_pkt.lun,
            sizeof(lcmd_pkt.lun));
 
-       /* Update tagged queuing modifier -- default is TSK_SIMPLE (0). */
-       if (scsi_populate_tag_msg(cmd, tag)) {
-               switch (tag[0]) {
-               case HEAD_OF_QUEUE_TAG:
-                       lcmd_pkt.task = TSK_HEAD_OF_QUEUE;
-                       break;
-               case ORDERED_QUEUE_TAG:
-                       lcmd_pkt.task = TSK_ORDERED;
-                       break;
-               }
-       }
-
        /* Load SCSI command packet. */
        host_to_adap(cmd->cmnd, lcmd_pkt.fcp_cdb, sizeof(lcmd_pkt.fcp_cdb));
        lcmd_pkt.byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
index 24a852828b5d726cac2c8d1378b0d664dd8b814a..ed4d6b6b53e3613b3a7f35e03f5f341655b2ab7c 100644 (file)
@@ -238,7 +238,7 @@ qla8044_rmw_crb_reg(struct scsi_qla_host *vha,
        return;
 }
 
-inline void
+static inline void
 qla8044_set_qsnt_ready(struct scsi_qla_host *vha)
 {
        uint32_t qsnt_state;
index db3dbd999cb6b1aec722c7ead94769d8eebb91a4..6b4d9235368a716b596b7af112312cdcaf7b494d 100644 (file)
@@ -236,8 +236,6 @@ static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
 static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
 static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
 
-static int qla2x00_change_queue_depth(struct scsi_device *, int, int);
-static int qla2x00_change_queue_type(struct scsi_device *, int);
 static void qla2x00_clear_drv_active(struct qla_hw_data *);
 static void qla2x00_free_device(scsi_qla_host_t *);
 static void qla83xx_disable_laser(scsi_qla_host_t *vha);
@@ -259,8 +257,8 @@ struct scsi_host_template qla2xxx_driver_template = {
        .slave_destroy          = qla2xxx_slave_destroy,
        .scan_finished          = qla2xxx_scan_finished,
        .scan_start             = qla2xxx_scan_start,
-       .change_queue_depth     = qla2x00_change_queue_depth,
-       .change_queue_type      = qla2x00_change_queue_type,
+       .change_queue_depth     = scsi_change_queue_depth,
+       .change_queue_type      = scsi_change_queue_type,
        .this_id                = -1,
        .cmd_per_lun            = 3,
        .use_clustering         = ENABLE_CLUSTERING,
@@ -270,6 +268,8 @@ struct scsi_host_template qla2xxx_driver_template = {
        .shost_attrs            = qla2x00_host_attrs,
 
        .supported_mode         = MODE_INITIATOR,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 static struct scsi_transport_template *qla2xxx_transport_template = NULL;
@@ -1405,10 +1405,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
        if (IS_T10_PI_CAPABLE(vha->hw))
                blk_queue_update_dma_alignment(sdev->request_queue, 0x7);
 
-       if (sdev->tagged_supported)
-               scsi_activate_tcq(sdev, req->max_q_depth);
-       else
-               scsi_deactivate_tcq(sdev, req->max_q_depth);
+       scsi_change_queue_depth(sdev, req->max_q_depth);
        return 0;
 }
 
@@ -1418,76 +1415,6 @@ qla2xxx_slave_destroy(struct scsi_device *sdev)
        sdev->hostdata = NULL;
 }
 
-static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
-{
-       fc_port_t *fcport = (struct fc_port *) sdev->hostdata;
-
-       if (!scsi_track_queue_full(sdev, qdepth))
-               return;
-
-       ql_dbg(ql_dbg_io, fcport->vha, 0x3029,
-           "Queue depth adjusted-down to %d for nexus=%ld:%d:%llu.\n",
-           sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
-}
-
-static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
-{
-       fc_port_t *fcport = sdev->hostdata;
-       struct scsi_qla_host *vha = fcport->vha;
-       struct req_que *req = NULL;
-
-       req = vha->req;
-       if (!req)
-               return;
-
-       if (req->max_q_depth <= sdev->queue_depth || req->max_q_depth < qdepth)
-               return;
-
-       if (sdev->ordered_tags)
-               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, qdepth);
-       else
-               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth);
-
-       ql_dbg(ql_dbg_io, vha, 0x302a,
-           "Queue depth adjusted-up to %d for nexus=%ld:%d:%llu.\n",
-           sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun);
-}
-
-static int
-qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
-{
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               qla2x00_handle_queue_full(sdev, qdepth);
-               break;
-       case SCSI_QDEPTH_RAMP_UP:
-               qla2x00_adjust_sdev_qdepth_up(sdev, qdepth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       return sdev->queue_depth;
-}
-
-static int
-qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag_type);
-               if (tag_type)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag_type = 0;
-
-       return tag_type;
-}
-
 /**
  * qla2x00_config_dma_addressing() - Configure OS DMA addressing method.
  * @ha: HA context
index 829752cfd73fe87a6d5325cb4c9399e022ec92f7..a902fa1db7aff1a0fd3ca8622040b56f6e03cef1 100644 (file)
@@ -112,6 +112,7 @@ static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
        struct qla_tgt_cmd *cmd);
 static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
        struct atio_from_isp *atio, uint16_t status, int qfull);
+static void qlt_disable_vha(struct scsi_qla_host *vha);
 /*
  * Global Variables
  */
@@ -210,7 +211,7 @@ static inline void qlt_decr_num_pend_cmds(struct scsi_qla_host *vha)
        spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
 }
 
-void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
+static void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
        struct atio_from_isp *atio)
 {
        ql_dbg(ql_dbg_tgt, vha, 0xe072,
@@ -433,7 +434,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
 #if 0 /* FIXME: Re-enable Global event handling.. */
                /* Global event */
                atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count);
-               qlt_clear_tgt_db(ha->tgt.qla_tgt, 1);
+               qlt_clear_tgt_db(ha->tgt.qla_tgt);
                if (!list_empty(&ha->tgt.qla_tgt->sess_list)) {
                        sess = list_entry(ha->tgt.qla_tgt->sess_list.next,
                            typeof(*sess), sess_list_entry);
@@ -515,7 +516,7 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess,
 }
 
 /* ha->hardware_lock supposed to be held on entry */
-static void qlt_clear_tgt_db(struct qla_tgt *tgt, bool local_only)
+static void qlt_clear_tgt_db(struct qla_tgt *tgt)
 {
        struct qla_tgt_sess *sess;
 
@@ -867,7 +868,7 @@ int qlt_stop_phase1(struct qla_tgt *tgt)
        mutex_lock(&vha->vha_tgt.tgt_mutex);
        spin_lock_irqsave(&ha->hardware_lock, flags);
        tgt->tgt_stop = 1;
-       qlt_clear_tgt_db(tgt, true);
+       qlt_clear_tgt_db(tgt);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
        mutex_unlock(&vha->vha_tgt.tgt_mutex);
        mutex_unlock(&qla_tgt_mutex);
@@ -1462,12 +1463,13 @@ out_err:
        return -1;
 }
 
-static inline void qlt_unmap_sg(struct scsi_qla_host *vha,
-       struct qla_tgt_cmd *cmd)
+static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
 {
        struct qla_hw_data *ha = vha->hw;
 
-       BUG_ON(!cmd->sg_mapped);
+       if (!cmd->sg_mapped)
+               return;
+
        pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
        cmd->sg_mapped = 0;
 
@@ -2428,8 +2430,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
        return 0;
 
 out_unmap_unlock:
-       if (cmd->sg_mapped)
-               qlt_unmap_sg(vha, cmd);
+       qlt_unmap_sg(vha, cmd);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        return res;
@@ -2506,8 +2507,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
        return res;
 
 out_unlock_free_unmap:
-       if (cmd->sg_mapped)
-               qlt_unmap_sg(vha, cmd);
+       qlt_unmap_sg(vha, cmd);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        return res;
@@ -2741,8 +2741,7 @@ done:
                if (!ha_locked && !in_interrupt())
                        msleep(250); /* just in case */
 
-               if (cmd->sg_mapped)
-                       qlt_unmap_sg(vha, cmd);
+               qlt_unmap_sg(vha, cmd);
                vha->hw->tgt.tgt_ops->free_cmd(cmd);
        }
        return;
@@ -3087,8 +3086,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
        tfo = se_cmd->se_tfo;
        cmd->cmd_sent_to_fw = 0;
 
-       if (cmd->sg_mapped)
-               qlt_unmap_sg(vha, cmd);
+       qlt_unmap_sg(vha, cmd);
 
        if (unlikely(status != CTIO_SUCCESS)) {
                switch (status & 0xFFFF) {
@@ -5343,7 +5341,7 @@ void qlt_lport_deregister(struct scsi_qla_host *vha)
 EXPORT_SYMBOL(qlt_lport_deregister);
 
 /* Must be called under HW lock */
-void qlt_set_mode(struct scsi_qla_host *vha)
+static void qlt_set_mode(struct scsi_qla_host *vha)
 {
        struct qla_hw_data *ha = vha->hw;
 
@@ -5364,7 +5362,7 @@ void qlt_set_mode(struct scsi_qla_host *vha)
 }
 
 /* Must be called under HW lock */
-void qlt_clear_mode(struct scsi_qla_host *vha)
+static void qlt_clear_mode(struct scsi_qla_host *vha)
 {
        struct qla_hw_data *ha = vha->hw;
 
@@ -5428,8 +5426,7 @@ EXPORT_SYMBOL(qlt_enable_vha);
  *
  * Disable Target Mode and reset the adapter
  */
-void
-qlt_disable_vha(struct scsi_qla_host *vha)
+static void qlt_disable_vha(struct scsi_qla_host *vha)
 {
        struct qla_hw_data *ha = vha->hw;
        struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
index 8ff330f7d6f55863b2ceb8af62e1ae2ef556ea42..332086776dfe94db4be404cca5c621518d600b1f 100644 (file)
@@ -1001,11 +1001,11 @@ struct qla_tgt_prm {
        struct qla_tgt *tgt;
        void *pkt;
        struct scatterlist *sg; /* cmd data buffer SG vector */
+       unsigned char *sense_buffer;
        int seg_cnt;
        int req_cnt;
        uint16_t rq_result;
        uint16_t scsi_status;
-       unsigned char *sense_buffer;
        int sense_buffer_len;
        int residual;
        int add_status_pkt;
@@ -1033,10 +1033,6 @@ struct qla_tgt_srr_ctio {
 
 
 extern struct qla_tgt_data qla_target;
-/*
- * Internal function prototypes
- */
-void qlt_disable_vha(struct scsi_qla_host *);
 
 /*
  * Function prototypes for qla_target.c logic used by qla2xxx LLD code.
@@ -1049,8 +1045,6 @@ extern void qlt_lport_deregister(struct scsi_qla_host *);
 extern void qlt_unreg_sess(struct qla_tgt_sess *);
 extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
 extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *);
-extern void qlt_set_mode(struct scsi_qla_host *ha);
-extern void qlt_clear_mode(struct scsi_qla_host *ha);
 extern int __init qlt_init(void);
 extern void qlt_exit(void);
 extern void qlt_update_vp_map(struct scsi_qla_host *, int);
@@ -1083,13 +1077,9 @@ static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
 /*
  * Exported symbols from qla_target.c LLD logic used by qla2xxx code..
  */
-extern void qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *,
-       struct atio_from_isp *);
 extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
 extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
 extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
-extern int qlt_rdy_to_xfer_dif(struct qla_tgt_cmd *);
-extern int qlt_xmit_response_dif(struct qla_tgt_cmd *, int, uint8_t);
 extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
 extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
 extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
index 031b2961c6b72c9ff445898f61eb21ba526706cc..73f9feecda72b71552b63eb28b7bec9106f6fd4e 100644 (file)
@@ -786,7 +786,16 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct qla_tgt_sess *sess)
        pr_debug("fc_rport domain: port_id 0x%06x\n", nacl->nport_id);
 
        node = btree_remove32(&lport->lport_fcport_map, nacl->nport_id);
-       WARN_ON(node && (node != se_nacl));
+       if (WARN_ON(node && (node != se_nacl))) {
+               /*
+                * The nacl no longer matches what we think it should be.
+                * Most likely a new dynamic acl has been added while
+                * someone dropped the hardware lock.  It clearly is a
+                * bug elsewhere, but this bit can't make things worse.
+                */
+               btree_insert32(&lport->lport_fcport_map, nacl->nport_id,
+                              node, GFP_ATOMIC);
+       }
 
        pr_debug("Removed from fcport_map: %p for WWNN: 0x%016LX, port_id: 0x%06x\n",
            se_nacl, nacl->nport_wwnn, nacl->nport_id);
index 08ab6dac226db61d1b1327eec463afa7190f0ccb..17222eb497622991ccdbd2473b3653c893661cac 100644 (file)
@@ -280,7 +280,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
        uint16_t req_cnt;
        unsigned long flags;
        uint32_t index;
-       char tag[2];
 
        /* Get real lun and adapter */
        ddb_entry = srb->ddb;
@@ -352,15 +351,6 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
 
        /* Set tagged queueing control flags */
        cmd_entry->control_flags |= CF_SIMPLE_TAG;
-       if (scsi_populate_tag_msg(cmd, tag))
-               switch (tag[0]) {
-               case MSG_HEAD_TAG:
-                       cmd_entry->control_flags |= CF_HEAD_TAG;
-                       break;
-               case MSG_ORDERED_TAG:
-                       cmd_entry->control_flags |= CF_ORDERED_TAG;
-                       break;
-               }
 
        qla4xxx_advance_req_ring_ptr(ha);
        qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds);
index 199fcf79a051870c654429c4a9bc92d6baa8b4e5..6d25879d87c8550893cdd8671db68d542cde64cb 100644 (file)
@@ -162,12 +162,8 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
 static int qla4xxx_slave_alloc(struct scsi_device *device);
-static int qla4xxx_slave_configure(struct scsi_device *device);
-static void qla4xxx_slave_destroy(struct scsi_device *sdev);
 static umode_t qla4_attr_is_visible(int param_type, int param);
 static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);
-static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
-                                     int reason);
 
 /*
  * iSCSI Flash DDB sysfs entry points
@@ -204,10 +200,8 @@ static struct scsi_host_template qla4xxx_driver_template = {
        .eh_host_reset_handler  = qla4xxx_eh_host_reset,
        .eh_timed_out           = qla4xxx_eh_cmd_timed_out,
 
-       .slave_configure        = qla4xxx_slave_configure,
        .slave_alloc            = qla4xxx_slave_alloc,
-       .slave_destroy          = qla4xxx_slave_destroy,
-       .change_queue_depth     = qla4xxx_change_queue_depth,
+       .change_queue_depth     = scsi_change_queue_depth,
 
        .this_id                = -1,
        .cmd_per_lun            = 3,
@@ -218,6 +212,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
        .shost_attrs            = qla4xxx_host_attrs,
        .host_reset             = qla4xxx_host_reset,
        .vendor_id              = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,
+       .use_blk_tags           = 1,
 };
 
 static struct iscsi_transport qla4xxx_iscsi_transport = {
@@ -9060,35 +9055,14 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev)
        ddb = sess->dd_data;
 
        sdev->hostdata = ddb;
-       sdev->tagged_supported = 1;
 
        if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)
                queue_depth = ql4xmaxqdepth;
 
-       scsi_activate_tcq(sdev, queue_depth);
+       scsi_change_queue_depth(sdev, queue_depth);
        return 0;
 }
 
-static int qla4xxx_slave_configure(struct scsi_device *sdev)
-{
-       sdev->tagged_supported = 1;
-       return 0;
-}
-
-static void qla4xxx_slave_destroy(struct scsi_device *sdev)
-{
-       scsi_deactivate_tcq(sdev, 1);
-}
-
-static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth,
-                                     int reason)
-{
-       if (!ql4xqfulltracking)
-               return -EOPNOTSUPP;
-
-       return iscsi_change_queue_depth(sdev, qdepth, reason);
-}
-
 /**
  * qla4xxx_del_from_active_array - returns an active srb
  * @ha: Pointer to host adapter structure.
@@ -9888,6 +9862,9 @@ static int __init qla4xxx_module_init(void)
 {
        int ret;
 
+       if (ql4xqfulltracking)
+               qla4xxx_driver_template.track_queue_depth = 1;
+
        /* Allocate cache for SRBs. */
        srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,
                                       SLAB_HWCACHE_ALIGN, NULL);
index 79c77b485a67298ed5fb912fe86c33813732157b..1ad0c36375b8043646bf9bf4078acad9b2c96619 100644 (file)
@@ -527,9 +527,9 @@ void scsi_log_send(struct scsi_cmnd *cmd)
         *
         * 1: nothing (match completion)
         *
-        * 2: log opcode + command of all commands
+        * 2: log opcode + command of all commands + cmd address
         *
-        * 3: same as 2 plus dump cmd address
+        * 3: same as 2
         *
         * 4: same as 3 plus dump extra junk
         */
@@ -537,10 +537,8 @@ void scsi_log_send(struct scsi_cmnd *cmd)
                level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT,
                                       SCSI_LOG_MLQUEUE_BITS);
                if (level > 1) {
-                       scmd_printk(KERN_INFO, cmd, "Send: ");
-                       if (level > 2)
-                               printk("0x%p ", cmd);
-                       printk("\n");
+                       scmd_printk(KERN_INFO, cmd,
+                                   "Send: scmd 0x%p\n", cmd);
                        scsi_print_command(cmd);
                        if (level > 3) {
                                printk(KERN_INFO "buffer = 0x%p, bufflen = %d,"
@@ -565,7 +563,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
         *
         * 2: same as 1 but for all command completions.
         *
-        * 3: same as 2 plus dump cmd address
+        * 3: same as 2
         *
         * 4: same as 3 plus dump extra junk
         */
@@ -574,39 +572,10 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
                                       SCSI_LOG_MLCOMPLETE_BITS);
                if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||
                    (level > 1)) {
-                       scmd_printk(KERN_INFO, cmd, "Done: ");
-                       if (level > 2)
-                               printk("0x%p ", cmd);
-                       /*
-                        * Dump truncated values, so we usually fit within
-                        * 80 chars.
-                        */
-                       switch (disposition) {
-                       case SUCCESS:
-                               printk("SUCCESS\n");
-                               break;
-                       case NEEDS_RETRY:
-                               printk("RETRY\n");
-                               break;
-                       case ADD_TO_MLQUEUE:
-                               printk("MLQUEUE\n");
-                               break;
-                       case FAILED:
-                               printk("FAILED\n");
-                               break;
-                       case TIMEOUT_ERROR:
-                               /* 
-                                * If called via scsi_times_out.
-                                */
-                               printk("TIMEOUT\n");
-                               break;
-                       default:
-                               printk("UNKNOWN\n");
-                       }
-                       scsi_print_result(cmd);
+                       scsi_print_result(cmd, "Done: ", disposition);
                        scsi_print_command(cmd);
                        if (status_byte(cmd->result) & CHECK_CONDITION)
-                               scsi_print_sense("", cmd);
+                               scsi_print_sense(cmd);
                        if (level > 3)
                                scmd_printk(KERN_INFO, cmd,
                                            "scsi host busy %d failed %d\n",
@@ -633,87 +602,6 @@ void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 }
 EXPORT_SYMBOL(scsi_cmd_get_serial);
 
-/**
- * scsi_dispatch_command - Dispatch a command to the low-level driver.
- * @cmd: command block we are dispatching.
- *
- * Return: nonzero return request was rejected and device's queue needs to be
- * plugged.
- */
-int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
-{
-       struct Scsi_Host *host = cmd->device->host;
-       int rtn = 0;
-
-       atomic_inc(&cmd->device->iorequest_cnt);
-
-       /* check if the device is still usable */
-       if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
-               /* in SDEV_DEL we error all commands. DID_NO_CONNECT
-                * returns an immediate error upwards, and signals
-                * that the device is no longer present */
-               cmd->result = DID_NO_CONNECT << 16;
-               goto done;
-       }
-
-       /* Check to see if the scsi lld made this device blocked. */
-       if (unlikely(scsi_device_blocked(cmd->device))) {
-               /*
-                * in blocked state, the command is just put back on
-                * the device queue.  The suspend state has already
-                * blocked the queue so future requests should not
-                * occur until the device transitions out of the
-                * suspend state.
-                */
-               SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
-                       "queuecommand : device blocked\n"));
-               return SCSI_MLQUEUE_DEVICE_BUSY;
-       }
-
-       /* Store the LUN value in cmnd, if needed. */
-       if (cmd->device->lun_in_cdb)
-               cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
-                              (cmd->device->lun << 5 & 0xe0);
-
-       scsi_log_send(cmd);
-
-       /*
-        * Before we queue this command, check if the command
-        * length exceeds what the host adapter can handle.
-        */
-       if (cmd->cmd_len > cmd->device->host->max_cmd_len) {
-               SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
-                              "queuecommand : command too long. "
-                              "cdb_size=%d host->max_cmd_len=%d\n",
-                              cmd->cmd_len, cmd->device->host->max_cmd_len));
-               cmd->result = (DID_ABORT << 16);
-               goto done;
-       }
-
-       if (unlikely(host->shost_state == SHOST_DEL)) {
-               cmd->result = (DID_NO_CONNECT << 16);
-               goto done;
-
-       }
-
-       trace_scsi_dispatch_cmd_start(cmd);
-       rtn = host->hostt->queuecommand(host, cmd);
-       if (rtn) {
-               trace_scsi_dispatch_cmd_error(cmd, rtn);
-               if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
-                   rtn != SCSI_MLQUEUE_TARGET_BUSY)
-                       rtn = SCSI_MLQUEUE_HOST_BUSY;
-
-               SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
-                       "queuecommand : request rejected\n"));
-       }
-
-       return rtn;
- done:
-       cmd->scsi_done(cmd);
-       return 0;
-}
-
 /**
  * scsi_finish_command - cleanup and pass command back to upper layer
  * @cmd: the command
@@ -773,32 +661,18 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
 }
 
 /**
- * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth
+ * scsi_change_queue_depth - change a device's queue depth
  * @sdev: SCSI Device in question
- * @tagged: Do we use tagged queueing (non-0) or do we treat
- *          this device as an untagged device (0)
- * @tags: Number of tags allowed if tagged queueing enabled,
- *        or number of commands the low level driver can
- *        queue up in non-tagged mode (as per cmd_per_lun).
- *
- * Returns:    Nothing
+ * @depth: number of commands allowed to be queued to the driver
  *
- * Lock Status:        None held on entry
- *
- * Notes:      Low level drivers may call this at any time and we will do
- *             the right thing depending on whether or not the device is
- *             currently active and whether or not it even has the
- *             command blocks built yet.
+ * Sets the device queue depth and returns the new value.
  */
-void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
+int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
 {
        unsigned long flags;
 
-       /*
-        * refuse to set tagged depth to an unworkable size
-        */
-       if (tags <= 0)
-               return;
+       if (depth <= 0)
+               goto out;
 
        spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
 
@@ -813,35 +687,17 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
         */
        if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {
                if (blk_queue_tagged(sdev->request_queue) &&
-                   blk_queue_resize_tags(sdev->request_queue, tags) != 0)
-                       goto out;
+                   blk_queue_resize_tags(sdev->request_queue, depth) != 0)
+                       goto out_unlock;
        }
 
-       sdev->queue_depth = tags;
-       switch (tagged) {
-               case 0:
-                       sdev->ordered_tags = 0;
-                       sdev->simple_tags = 0;
-                       break;
-               case MSG_ORDERED_TAG:
-                       sdev->ordered_tags = 1;
-                       sdev->simple_tags = 1;
-                       break;
-               case MSG_SIMPLE_TAG:
-                       sdev->ordered_tags = 0;
-                       sdev->simple_tags = 1;
-                       break;
-               default:
-                       sdev->ordered_tags = 0;
-                       sdev->simple_tags = 0;
-                       sdev_printk(KERN_WARNING, sdev,
-                                   "scsi_adjust_queue_depth, bad queue type, "
-                                   "disabled\n");
-       }
- out:
+       sdev->queue_depth = depth;
+out_unlock:
        spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
+out:
+       return sdev->queue_depth;
 }
-EXPORT_SYMBOL(scsi_adjust_queue_depth);
+EXPORT_SYMBOL(scsi_change_queue_depth);
 
 /**
  * scsi_track_queue_full - track QUEUE_FULL events to adjust queue depth
@@ -885,18 +741,31 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth)
                return 0;
        if (sdev->last_queue_full_depth < 8) {
                /* Drop back to untagged */
-               scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+               scsi_set_tag_type(sdev, 0);
+               scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun);
                return -1;
        }
-       
-       if (sdev->ordered_tags)
-               scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
-       else
-               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
-       return depth;
+
+       return scsi_change_queue_depth(sdev, depth);
 }
 EXPORT_SYMBOL(scsi_track_queue_full);
 
+/**
+ * scsi_change_queue_type() - Change a device's queue type
+ * @sdev:     The SCSI device whose queue depth is to change
+ * @tag_type: Identifier for queue type
+ */
+int scsi_change_queue_type(struct scsi_device *sdev, int tag_type)
+{
+       if (!sdev->tagged_supported)
+               return 0;
+
+       scsi_set_tag_type(sdev, tag_type);
+       return tag_type;
+
+}
+EXPORT_SYMBOL(scsi_change_queue_type);
+
 /**
  * scsi_vpd_inquiry - Request a device provide us with a VPD page
  * @sdev: The device to ask
index 238e06f13b8a1c977146699d95f1783bbef571e7..aa4b6b80aadee31c85d9678d82160472e518a907 100644 (file)
@@ -63,8 +63,8 @@
 #include "sd.h"
 #include "scsi_logging.h"
 
-#define SCSI_DEBUG_VERSION "1.84"
-static const char *scsi_debug_version_date = "20140706";
+#define SCSI_DEBUG_VERSION "1.85"
+static const char *scsi_debug_version_date = "20141022";
 
 #define MY_NAME "scsi_debug"
 
@@ -75,19 +75,22 @@ static const char *scsi_debug_version_date = "20140706";
 #define UNRECOVERED_READ_ERR 0x11
 #define PARAMETER_LIST_LENGTH_ERR 0x1a
 #define INVALID_OPCODE 0x20
-#define ADDR_OUT_OF_RANGE 0x21
-#define INVALID_COMMAND_OPCODE 0x20
+#define LBA_OUT_OF_RANGE 0x21
 #define INVALID_FIELD_IN_CDB 0x24
 #define INVALID_FIELD_IN_PARAM_LIST 0x26
 #define UA_RESET_ASC 0x29
 #define UA_CHANGED_ASC 0x2a
+#define INSUFF_RES_ASC 0x55
+#define INSUFF_RES_ASCQ 0x3
 #define POWER_ON_RESET_ASCQ 0x0
 #define BUS_RESET_ASCQ 0x2     /* scsi bus reset occurred */
 #define MODE_CHANGED_ASCQ 0x1  /* mode parameters changed */
+#define CAPACITY_CHANGED_ASCQ 0x9
 #define SAVING_PARAMS_UNSUP 0x39
 #define TRANSPORT_PROBLEM 0x4b
 #define THRESHOLD_EXCEEDED 0x5d
 #define LOW_POWER_COND_ON 0x5e
+#define MISCOMPARE_VERIFY_ASC 0x1d
 
 /* Additional Sense Code Qualifier (ASCQ) */
 #define ACK_NAK_TO 0x3
@@ -133,6 +136,7 @@ static const char *scsi_debug_version_date = "20140706";
 #define DEF_VIRTUAL_GB   0
 #define DEF_VPD_USE_HOSTNO 1
 #define DEF_WRITESAME_LENGTH 0xFFFF
+#define DEF_STRICT 0
 #define DELAY_OVERRIDDEN -9999
 
 /* bit mask values for scsi_debug_opts */
@@ -176,11 +180,12 @@ static const char *scsi_debug_version_date = "20140706";
 #define SDEBUG_UA_POR 0                /* Power on, reset, or bus device reset */
 #define SDEBUG_UA_BUS_RESET 1
 #define SDEBUG_UA_MODE_CHANGED 2
-#define SDEBUG_NUM_UAS 3
+#define SDEBUG_UA_CAPACITY_CHANGED 3
+#define SDEBUG_NUM_UAS 4
 
 /* for check_readiness() */
-#define UAS_ONLY 1
-#define UAS_TUR 0
+#define UAS_ONLY 1     /* check for UAs only */
+#define UAS_TUR 0      /* if no UAs then check if media access possible */
 
 /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
  * sector on read commands: */
@@ -206,6 +211,301 @@ static const char *scsi_debug_version_date = "20140706";
 #warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE"
 #endif
 
+/* SCSI opcodes (first byte of cdb) mapped onto these indexes */
+enum sdeb_opcode_index {
+       SDEB_I_INVALID_OPCODE = 0,
+       SDEB_I_INQUIRY = 1,
+       SDEB_I_REPORT_LUNS = 2,
+       SDEB_I_REQUEST_SENSE = 3,
+       SDEB_I_TEST_UNIT_READY = 4,
+       SDEB_I_MODE_SENSE = 5,          /* 6, 10 */
+       SDEB_I_MODE_SELECT = 6,         /* 6, 10 */
+       SDEB_I_LOG_SENSE = 7,
+       SDEB_I_READ_CAPACITY = 8,       /* 10; 16 is in SA_IN(16) */
+       SDEB_I_READ = 9,                /* 6, 10, 12, 16 */
+       SDEB_I_WRITE = 10,              /* 6, 10, 12, 16 */
+       SDEB_I_START_STOP = 11,
+       SDEB_I_SERV_ACT_IN = 12,        /* 12, 16 */
+       SDEB_I_SERV_ACT_OUT = 13,       /* 12, 16 */
+       SDEB_I_MAINT_IN = 14,
+       SDEB_I_MAINT_OUT = 15,
+       SDEB_I_VERIFY = 16,             /* 10 only */
+       SDEB_I_VARIABLE_LEN = 17,
+       SDEB_I_RESERVE = 18,            /* 6, 10 */
+       SDEB_I_RELEASE = 19,            /* 6, 10 */
+       SDEB_I_ALLOW_REMOVAL = 20,      /* PREVENT ALLOW MEDIUM REMOVAL */
+       SDEB_I_REZERO_UNIT = 21,        /* REWIND in SSC */
+       SDEB_I_ATA_PT = 22,             /* 12, 16 */
+       SDEB_I_SEND_DIAG = 23,
+       SDEB_I_UNMAP = 24,
+       SDEB_I_XDWRITEREAD = 25,        /* 10 only */
+       SDEB_I_WRITE_BUFFER = 26,
+       SDEB_I_WRITE_SAME = 27,         /* 10, 16 */
+       SDEB_I_SYNC_CACHE = 28,         /* 10 only */
+       SDEB_I_COMP_WRITE = 29,
+       SDEB_I_LAST_ELEMENT = 30,       /* keep this last */
+};
+
+static const unsigned char opcode_ind_arr[256] = {
+/* 0x0; 0x0->0x1f: 6 byte cdbs */
+       SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
+           0, 0, 0, 0,
+       SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,
+       0, 0, SDEB_I_INQUIRY, 0, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
+           SDEB_I_RELEASE,
+       0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,
+           SDEB_I_ALLOW_REMOVAL, 0,
+/* 0x20; 0x20->0x3f: 10 byte cdbs */
+       0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0,
+       SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY,
+       0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0,
+       0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0,
+/* 0x40; 0x40->0x5f: 10 byte cdbs */
+       0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, SDEB_I_LOG_SENSE, 0, 0,
+       0, 0, 0, SDEB_I_XDWRITEREAD, 0, SDEB_I_MODE_SELECT, SDEB_I_RESERVE,
+           SDEB_I_RELEASE,
+       0, 0, SDEB_I_MODE_SENSE, 0, 0, 0, 0, 0,
+/* 0x60; 0x60->0x7d are reserved */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, SDEB_I_VARIABLE_LEN,
+/* 0x80; 0x80->0x9f: 16 byte cdbs */
+       0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
+       SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
+       0, 0, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN, SDEB_I_SERV_ACT_OUT,
+/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
+       SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
+            SDEB_I_MAINT_OUT, 0, 0, 0,
+       SDEB_I_READ, SDEB_I_SERV_ACT_OUT, SDEB_I_WRITE, SDEB_I_SERV_ACT_IN,
+            0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0,
+/* 0xc0; 0xc0->0xff: vendor specific */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+#define F_D_IN                 1
+#define F_D_OUT                        2
+#define F_D_OUT_MAYBE          4       /* WRITE SAME, NDOB bit */
+#define F_D_UNKN               8
+#define F_RL_WLUN_OK           0x10
+#define F_SKIP_UA              0x20
+#define F_DELAY_OVERR          0x40
+#define F_SA_LOW               0x80    /* cdb byte 1, bits 4 to 0 */
+#define F_SA_HIGH              0x100   /* as used by variable length cdbs */
+#define F_INV_OP               0x200
+#define F_FAKE_RW              0x400
+#define F_M_ACCESS             0x800   /* media access */
+
+#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
+#define FF_DIRECT_IO (F_M_ACCESS | F_FAKE_RW)
+#define FF_SA (F_SA_HIGH | F_SA_LOW)
+
+struct sdebug_dev_info;
+static int resp_inquiry(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_report_luns(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_requests(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_mode_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_mode_select(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_log_sense(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_readcap(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_read_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_write_dt0(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_xdwriteread_10(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
+
+struct opcode_info_t {
+       u8 num_attached;        /* 0 if this is it (i.e. a leaf); use 0xff
+                                * for terminating element */
+       u8 opcode;              /* if num_attached > 0, preferred */
+       u16 sa;                 /* service action */
+       u32 flags;              /* OR-ed set of SDEB_F_* */
+       int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
+       const struct opcode_info_t *arrp;  /* num_attached elements or NULL */
+       u8 len_mask[16];        /* len=len_mask[0], then mask for cdb[1]... */
+                               /* ignore cdb bytes after position 15 */
+};
+
+static const struct opcode_info_t msense_iarr[1] = {
+       {0, 0x1a, 0, F_D_IN, NULL, NULL,
+           {6,  0xe8, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t mselect_iarr[1] = {
+       {0, 0x15, 0, F_D_OUT, NULL, NULL,
+           {6,  0xf1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t read_iarr[3] = {
+       {0, 0x28, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(10) */
+           {10,  0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
+            0, 0, 0, 0} },
+       {0, 0x8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL, /* READ(6) */
+           {6,  0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0xa8, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, NULL,/* READ(12) */
+           {12,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
+            0xc7, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t write_iarr[3] = {
+       {0, 0x2a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL,   /* 10 */
+           {10,  0xfb, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
+            0, 0, 0, 0} },
+       {0, 0xa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL,    /* 6 */
+           {6,  0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0xaa, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, NULL,   /* 12 */
+           {12,  0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f,
+            0xc7, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t sa_in_iarr[1] = {
+       {0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
+           {16,  0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff, 0xff, 0, 0xc7} },
+};
+
+static const struct opcode_info_t vl_iarr[1] = {       /* VARIABLE LENGTH */
+       {0, 0x7f, 0xb, F_SA_HIGH | F_D_OUT | FF_DIRECT_IO, resp_write_dt0,
+           NULL, {32,  0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0xb, 0xfa,
+                  0, 0xff, 0xff, 0xff, 0xff} },        /* WRITE(32) */
+};
+
+static const struct opcode_info_t maint_in_iarr[2] = {
+       {0, 0xa3, 0xc, F_SA_LOW | F_D_IN, resp_rsup_opcodes, NULL,
+           {12,  0xc, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
+            0xc7, 0, 0, 0, 0} },
+       {0, 0xa3, 0xd, F_SA_LOW | F_D_IN, resp_rsup_tmfs, NULL,
+           {12,  0xd, 0x80, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
+            0, 0} },
+};
+
+static const struct opcode_info_t write_same_iarr[1] = {
+       {0, 0x93, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_16, NULL,
+           {16,  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff, 0xff, 0x1f, 0xc7} },
+};
+
+static const struct opcode_info_t reserve_iarr[1] = {
+       {0, 0x16, 0, F_D_OUT, NULL, NULL,       /* RESERVE(6) */
+           {6,  0x1f, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+static const struct opcode_info_t release_iarr[1] = {
+       {0, 0x17, 0, F_D_OUT, NULL, NULL,       /* RELEASE(6) */
+           {6,  0x1f, 0xff, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+
+/* This array is accessed via SDEB_I_* values. Make sure all are mapped,
+ * plus the terminating elements for logic that scans this table such as
+ * REPORT SUPPORTED OPERATION CODES. */
+static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
+/* 0 */
+       {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL,
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0x12, 0, FF_RESPOND | F_D_IN, resp_inquiry, NULL,
+           {6,  0xe3, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0xa0, 0, FF_RESPOND | F_D_IN, resp_report_luns, NULL,
+           {12,  0xe3, 0xff, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0,
+            0, 0} },
+       {0, 0x3, 0, FF_RESPOND | F_D_IN, resp_requests, NULL,
+           {6,  0xe1, 0, 0, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0x0, 0, F_M_ACCESS | F_RL_WLUN_OK, NULL, NULL,/* TEST UNIT READY */
+           {6,  0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {1, 0x5a, 0, F_D_IN, resp_mode_sense, msense_iarr,
+           {10,  0xf8, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
+            0} },
+       {1, 0x55, 0, F_D_OUT, resp_mode_select, mselect_iarr,
+           {10,  0xf1, 0, 0, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
+       {0, 0x4d, 0, F_D_IN, resp_log_sense, NULL,
+           {10,  0xe3, 0xff, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0,
+            0, 0, 0} },
+       {0, 0x25, 0, F_D_IN, resp_readcap, NULL,
+           {10,  0xe1, 0xff, 0xff, 0xff, 0xff, 0, 0, 0x1, 0xc7, 0, 0, 0, 0,
+            0, 0} },
+       {3, 0x88, 0, F_D_IN | FF_DIRECT_IO, resp_read_dt0, read_iarr,
+           {16,  0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff, 0xff, 0x9f, 0xc7} },           /* READ(16) */
+/* 10 */
+       {3, 0x8a, 0, F_D_OUT | FF_DIRECT_IO, resp_write_dt0, write_iarr,
+           {16,  0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff, 0xff, 0x9f, 0xc7} },           /* WRITE(16) */
+       {0, 0x1b, 0, 0, resp_start_stop, NULL,          /* START STOP UNIT */
+           {6,  0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {1, 0x9e, 0x10, F_SA_LOW | F_D_IN, resp_readcap16, sa_in_iarr,
+           {16,  0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff, 0xff, 0x1, 0xc7} },    /* READ CAPACITY(16) */
+       {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* SA OUT */
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {2, 0xa3, 0xa, F_SA_LOW | F_D_IN, resp_report_tgtpgs, maint_in_iarr,
+           {12,  0xea, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xc7, 0, 0, 0,
+            0} },
+       {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* VERIFY */
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {1, 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_DIRECT_IO, resp_read_dt0,
+           vl_iarr, {32,  0xc7, 0, 0, 0, 0, 0x1f, 0x18, 0x0, 0x9, 0xfe, 0,
+                     0xff, 0xff, 0xff, 0xff} },/* VARIABLE LENGTH, READ(32) */
+       {1, 0x56, 0, F_D_OUT, NULL, reserve_iarr, /* RESERVE(10) */
+           {10,  0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
+            0} },
+       {1, 0x57, 0, F_D_OUT, NULL, release_iarr, /* RELEASE(10) */
+           {10,  0x13, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0,
+            0} },
+/* 20 */
+       {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ALLOW REMOVAL */
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0x1, 0, 0, resp_start_stop, NULL, /* REWIND ?? */
+           {6,  0x1, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* ATA_PT */
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0x1d, F_D_OUT, 0, NULL, NULL,       /* SEND DIAGNOSTIC */
+           {6,  0xf7, 0, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {0, 0x42, 0, F_D_OUT | FF_DIRECT_IO, resp_unmap, NULL, /* UNMAP */
+           {10,  0x1, 0, 0, 0, 0, 0x1f, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
+       {0, 0x53, 0, F_D_IN | F_D_OUT | FF_DIRECT_IO, resp_xdwriteread_10,
+           NULL, {10,  0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7,
+                  0, 0, 0, 0, 0, 0} },
+       {0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* WRITE_BUFFER */
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+       {1, 0x41, 0, F_D_OUT_MAYBE | FF_DIRECT_IO, resp_write_same_10,
+           write_same_iarr, {10,  0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
+                             0xff, 0xc7, 0, 0, 0, 0, 0, 0} },
+       {0, 0x35, 0, F_DELAY_OVERR | FF_DIRECT_IO, NULL, NULL, /* SYNC_CACHE */
+           {10,  0x7, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xc7, 0, 0,
+            0, 0, 0, 0} },
+       {0, 0x89, 0, F_D_OUT | FF_DIRECT_IO, resp_comp_write, NULL,
+           {16,  0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
+            0, 0xff, 0x1f, 0xc7} },            /* COMPARE AND WRITE */
+
+/* 30 */
+       {0xff, 0, 0, 0, NULL, NULL,             /* terminating element */
+           {0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+};
+
+struct sdebug_scmd_extra_t {
+       bool inj_recovered;
+       bool inj_transport;
+       bool inj_dif;
+       bool inj_dix;
+       bool inj_short;
+};
+
 static int scsi_debug_add_host = DEF_NUM_HOST;
 static int scsi_debug_ato = DEF_ATO;
 static int scsi_debug_delay = DEF_DELAY;
@@ -245,6 +545,8 @@ static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
 static bool scsi_debug_removable = DEF_REMOVABLE;
 static bool scsi_debug_clustering;
 static bool scsi_debug_host_lock = DEF_HOST_LOCK;
+static bool scsi_debug_strict = DEF_STRICT;
+static bool sdebug_any_injecting_opt;
 
 static atomic_t sdebug_cmnd_count;
 static atomic_t sdebug_completions;
@@ -277,11 +579,10 @@ struct sdebug_dev_info {
        unsigned int target;
        u64 lun;
        struct sdebug_host_info *sdbg_host;
-       u64 wlun;
        unsigned long uas_bm[1];
        atomic_t num_in_q;
-       char stopped;
-       char used;
+       char stopped;           /* TODO: should be atomic */
+       bool used;
 };
 
 struct sdebug_host_info {
@@ -394,6 +695,50 @@ static void sdebug_max_tgts_luns(void)
        spin_unlock(&sdebug_host_list_lock);
 }
 
+enum sdeb_cmd_data {SDEB_IN_DATA = 0, SDEB_IN_CDB = 1};
+
+/* Set in_bit to -1 to indicate no bit position of invalid field */
+static void
+mk_sense_invalid_fld(struct scsi_cmnd *scp, enum sdeb_cmd_data c_d,
+                    int in_byte, int in_bit)
+{
+       unsigned char *sbuff;
+       u8 sks[4];
+       int sl, asc;
+
+       sbuff = scp->sense_buffer;
+       if (!sbuff) {
+               sdev_printk(KERN_ERR, scp->device,
+                           "%s: sense_buffer is NULL\n", __func__);
+               return;
+       }
+       asc = c_d ? INVALID_FIELD_IN_CDB : INVALID_FIELD_IN_PARAM_LIST;
+       memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE);
+       scsi_build_sense_buffer(scsi_debug_dsense, sbuff, ILLEGAL_REQUEST,
+                               asc, 0);
+       memset(sks, 0, sizeof(sks));
+       sks[0] = 0x80;
+       if (c_d)
+               sks[0] |= 0x40;
+       if (in_bit >= 0) {
+               sks[0] |= 0x8;
+               sks[0] |= 0x7 & in_bit;
+       }
+       put_unaligned_be16(in_byte, sks + 1);
+       if (scsi_debug_dsense) {
+               sl = sbuff[7] + 8;
+               sbuff[7] = sl;
+               sbuff[sl] = 0x2;
+               sbuff[sl + 1] = 0x6;
+               memcpy(sbuff + sl + 4, sks, 3);
+       } else
+               memcpy(sbuff + 15, sks, 3);
+       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
+               sdev_printk(KERN_INFO, scp->device, "%s:  [sense_key,asc,ascq"
+                           "]: [0x5,0x%x,0x0] %c byte=%d, bit=%d\n",
+                           my_name, asc, c_d ? 'C' : 'D', in_byte, in_bit);
+}
+
 static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
 {
        unsigned char *sbuff;
@@ -414,63 +759,10 @@ static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq)
                            my_name, key, asc, asq);
 }
 
-static void get_data_transfer_info(unsigned char *cmd,
-                                  unsigned long long *lba, unsigned int *num,
-                                  u32 *ei_lba)
+static void
+mk_sense_invalid_opcode(struct scsi_cmnd *scp)
 {
-       *ei_lba = 0;
-
-       switch (*cmd) {
-       case VARIABLE_LENGTH_CMD:
-               *lba = (u64)cmd[19] | (u64)cmd[18] << 8 |
-                       (u64)cmd[17] << 16 | (u64)cmd[16] << 24 |
-                       (u64)cmd[15] << 32 | (u64)cmd[14] << 40 |
-                       (u64)cmd[13] << 48 | (u64)cmd[12] << 56;
-
-               *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 |
-                       (u32)cmd[21] << 16 | (u32)cmd[20] << 24;
-
-               *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 |
-                       (u32)cmd[28] << 24;
-               break;
-
-       case WRITE_SAME_16:
-       case WRITE_16:
-       case READ_16:
-               *lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
-                       (u64)cmd[7] << 16 | (u64)cmd[6] << 24 |
-                       (u64)cmd[5] << 32 | (u64)cmd[4] << 40 |
-                       (u64)cmd[3] << 48 | (u64)cmd[2] << 56;
-
-               *num = (u32)cmd[13] | (u32)cmd[12] << 8 | (u32)cmd[11] << 16 |
-                       (u32)cmd[10] << 24;
-               break;
-       case WRITE_12:
-       case READ_12:
-               *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
-                       (u32)cmd[2] << 24;
-
-               *num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
-                       (u32)cmd[6] << 24;
-               break;
-       case WRITE_SAME:
-       case WRITE_10:
-       case READ_10:
-       case XDWRITEREAD_10:
-               *lba = (u32)cmd[5] | (u32)cmd[4] << 8 | (u32)cmd[3] << 16 |
-                       (u32)cmd[2] << 24;
-
-               *num = (u32)cmd[8] | (u32)cmd[7] << 8;
-               break;
-       case WRITE_6:
-       case READ_6:
-               *lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
-                       (u32)(cmd[1] & 0x1f) << 16;
-               *num = (0 == cmd[4]) ? 256 : cmd[4];
-               break;
-       default:
-               break;
-       }
+       mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
 }
 
 static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg)
@@ -520,6 +812,11 @@ static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only,
                        if (debug)
                                cp = "mode parameters changed";
                        break;
+               case SDEBUG_UA_CAPACITY_CHANGED:
+                       mk_sense_buffer(SCpnt, UNIT_ATTENTION,
+                                       UA_CHANGED_ASC, CAPACITY_CHANGED_ASCQ);
+                       if (debug)
+                               cp = "capacity data changed";
                default:
                        pr_warn("%s: unexpected unit attention code=%d\n",
                                __func__, k);
@@ -924,19 +1221,20 @@ static int inquiry_evpd_b2(unsigned char *arr)
 #define SDEBUG_LONG_INQ_SZ 96
 #define SDEBUG_MAX_INQ_ARR_SZ 584
 
-static int resp_inquiry(struct scsi_cmnd *scp, int target,
-                       struct sdebug_dev_info * devip)
+static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
        unsigned char pq_pdt;
        unsigned char * arr;
        unsigned char *cmd = scp->cmnd;
        int alloc_len, n, ret;
+       bool have_wlun;
 
        alloc_len = (cmd[3] << 8) + cmd[4];
        arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
        if (! arr)
                return DID_REQUEUE << 16;
-       if (devip->wlun)
+       have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS);
+       if (have_wlun)
                pq_pdt = 0x1e;  /* present, wlun */
        else if (scsi_debug_no_lun_0 && (0 == devip->lun))
                pq_pdt = 0x7f;  /* not present, no device type */
@@ -944,8 +1242,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target,
                pq_pdt = (scsi_debug_ptype & 0x1f);
        arr[0] = pq_pdt;
        if (0x2 & cmd[1]) {  /* CMDDT bit set */
-               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
                kfree(arr);
                return check_condition_result;
        } else if (0x1 & cmd[1]) {  /* EVPD bit set */
@@ -957,7 +1254,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target,
                    (devip->channel & 0x7f);
                if (0 == scsi_debug_vpd_use_hostno)
                        host_no = 0;
-               lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) +
+               lu_id_num = have_wlun ? -1 : (((host_no + 1) * 2000) +
                            (devip->target * 1000) + devip->lun);
                target_dev_id = ((host_no + 1) * 2000) +
                                 (devip->target * 1000) - 3;
@@ -1029,9 +1326,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, int target,
                        arr[1] = cmd[2];        /*sanity */
                        arr[3] = inquiry_evpd_b2(&arr[4]);
                } else {
-                       /* Illegal request, invalid field in cdb */
-                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                                       INVALID_FIELD_IN_CDB, 0);
+                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
                        kfree(arr);
                        return check_condition_result;
                }
@@ -1077,18 +1372,20 @@ static int resp_requests(struct scsi_cmnd * scp,
        unsigned char * sbuff;
        unsigned char *cmd = scp->cmnd;
        unsigned char arr[SCSI_SENSE_BUFFERSIZE];
-       int want_dsense;
+       bool dsense, want_dsense;
        int len = 18;
 
        memset(arr, 0, sizeof(arr));
-       want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense;
+       dsense = !!(cmd[1] & 1);
+       want_dsense = dsense || scsi_debug_dsense;
        sbuff = scp->sense_buffer;
        if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
-               if (want_dsense) {
+               if (dsense) {
                        arr[0] = 0x72;
                        arr[1] = 0x0;           /* NO_SENSE in sense_key */
                        arr[2] = THRESHOLD_EXCEEDED;
                        arr[3] = 0xff;          /* TEST set and MRIE==6 */
+                       len = 8;
                } else {
                        arr[0] = 0x70;
                        arr[2] = 0x0;           /* NO_SENSE in sense_key */
@@ -1098,15 +1395,34 @@ static int resp_requests(struct scsi_cmnd * scp,
                }
        } else {
                memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
-               if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
-                       /* DESC bit set and sense_buff in fixed format */
-                       memset(arr, 0, sizeof(arr));
+               if (arr[0] >= 0x70 && dsense == scsi_debug_dsense)
+                       ;       /* have sense and formats match */
+               else if (arr[0] <= 0x70) {
+                       if (dsense) {
+                               memset(arr, 0, 8);
+                               arr[0] = 0x72;
+                               len = 8;
+                       } else {
+                               memset(arr, 0, 18);
+                               arr[0] = 0x70;
+                               arr[7] = 0xa;
+                       }
+               } else if (dsense) {
+                       memset(arr, 0, 8);
                        arr[0] = 0x72;
                        arr[1] = sbuff[2];     /* sense key */
                        arr[2] = sbuff[12];    /* asc */
                        arr[3] = sbuff[13];    /* ascq */
                        len = 8;
+               } else {
+                       memset(arr, 0, 18);
+                       arr[0] = 0x70;
+                       arr[2] = sbuff[1];
+                       arr[7] = 0xa;
+                       arr[12] = sbuff[1];
+                       arr[13] = sbuff[3];
                }
+
        }
        mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
        return fill_from_dev_buffer(scp, arr, len);
@@ -1116,15 +1432,11 @@ static int resp_start_stop(struct scsi_cmnd * scp,
                           struct sdebug_dev_info * devip)
 {
        unsigned char *cmd = scp->cmnd;
-       int power_cond, errsts, start;
+       int power_cond, start;
 
-       errsts = check_readiness(scp, UAS_ONLY, devip);
-       if (errsts)
-               return errsts;
        power_cond = (cmd[4] & 0xf0) >> 4;
        if (power_cond) {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
                return check_condition_result;
        }
        start = cmd[4] & 1;
@@ -1148,11 +1460,7 @@ static int resp_readcap(struct scsi_cmnd * scp,
 {
        unsigned char arr[SDEBUG_READCAP_ARR_SZ];
        unsigned int capac;
-       int errsts;
 
-       errsts = check_readiness(scp, UAS_ONLY, devip);
-       if (errsts)
-               return errsts;
        /* following just in case virtual_gb changed */
        sdebug_capacity = get_sdebug_capacity();
        memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
@@ -1180,11 +1488,8 @@ static int resp_readcap16(struct scsi_cmnd * scp,
        unsigned char *cmd = scp->cmnd;
        unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
        unsigned long long capac;
-       int errsts, k, alloc_len;
+       int k, alloc_len;
 
-       errsts = check_readiness(scp, UAS_ONLY, devip);
-       if (errsts)
-               return errsts;
        alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8)
                     + cmd[13]);
        /* following just in case virtual_gb changed */
@@ -1300,6 +1605,184 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
        return ret;
 }
 
+static int
+resp_rsup_opcodes(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+       bool rctd;
+       u8 reporting_opts, req_opcode, sdeb_i, supp;
+       u16 req_sa, u;
+       u32 alloc_len, a_len;
+       int k, offset, len, errsts, count, bump, na;
+       const struct opcode_info_t *oip;
+       const struct opcode_info_t *r_oip;
+       u8 *arr;
+       u8 *cmd = scp->cmnd;
+
+       rctd = !!(cmd[2] & 0x80);
+       reporting_opts = cmd[2] & 0x7;
+       req_opcode = cmd[3];
+       req_sa = get_unaligned_be16(cmd + 4);
+       alloc_len = get_unaligned_be32(cmd + 6);
+       if (alloc_len < 4 && alloc_len > 0xffff) {
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
+               return check_condition_result;
+       }
+       if (alloc_len > 8192)
+               a_len = 8192;
+       else
+               a_len = alloc_len;
+       arr = kzalloc((a_len < 256) ? 320 : a_len + 64, GFP_KERNEL);
+       if (NULL == arr) {
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+                               INSUFF_RES_ASCQ);
+               return check_condition_result;
+       }
+       switch (reporting_opts) {
+       case 0: /* all commands */
+               /* count number of commands */
+               for (count = 0, oip = opcode_info_arr;
+                    oip->num_attached != 0xff; ++oip) {
+                       if (F_INV_OP & oip->flags)
+                               continue;
+                       count += (oip->num_attached + 1);
+               }
+               bump = rctd ? 20 : 8;
+               put_unaligned_be32(count * bump, arr);
+               for (offset = 4, oip = opcode_info_arr;
+                    oip->num_attached != 0xff && offset < a_len; ++oip) {
+                       if (F_INV_OP & oip->flags)
+                               continue;
+                       na = oip->num_attached;
+                       arr[offset] = oip->opcode;
+                       put_unaligned_be16(oip->sa, arr + offset + 2);
+                       if (rctd)
+                               arr[offset + 5] |= 0x2;
+                       if (FF_SA & oip->flags)
+                               arr[offset + 5] |= 0x1;
+                       put_unaligned_be16(oip->len_mask[0], arr + offset + 6);
+                       if (rctd)
+                               put_unaligned_be16(0xa, arr + offset + 8);
+                       r_oip = oip;
+                       for (k = 0, oip = oip->arrp; k < na; ++k, ++oip) {
+                               if (F_INV_OP & oip->flags)
+                                       continue;
+                               offset += bump;
+                               arr[offset] = oip->opcode;
+                               put_unaligned_be16(oip->sa, arr + offset + 2);
+                               if (rctd)
+                                       arr[offset + 5] |= 0x2;
+                               if (FF_SA & oip->flags)
+                                       arr[offset + 5] |= 0x1;
+                               put_unaligned_be16(oip->len_mask[0],
+                                                  arr + offset + 6);
+                               if (rctd)
+                                       put_unaligned_be16(0xa,
+                                                          arr + offset + 8);
+                       }
+                       oip = r_oip;
+                       offset += bump;
+               }
+               break;
+       case 1: /* one command: opcode only */
+       case 2: /* one command: opcode plus service action */
+       case 3: /* one command: if sa==0 then opcode only else opcode+sa */
+               sdeb_i = opcode_ind_arr[req_opcode];
+               oip = &opcode_info_arr[sdeb_i];
+               if (F_INV_OP & oip->flags) {
+                       supp = 1;
+                       offset = 4;
+               } else {
+                       if (1 == reporting_opts) {
+                               if (FF_SA & oip->flags) {
+                                       mk_sense_invalid_fld(scp, SDEB_IN_CDB,
+                                                            2, 2);
+                                       kfree(arr);
+                                       return check_condition_result;
+                               }
+                               req_sa = 0;
+                       } else if (2 == reporting_opts &&
+                                  0 == (FF_SA & oip->flags)) {
+                               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
+                               kfree(arr);     /* point at requested sa */
+                               return check_condition_result;
+                       }
+                       if (0 == (FF_SA & oip->flags) &&
+                           req_opcode == oip->opcode)
+                               supp = 3;
+                       else if (0 == (FF_SA & oip->flags)) {
+                               na = oip->num_attached;
+                               for (k = 0, oip = oip->arrp; k < na;
+                                    ++k, ++oip) {
+                                       if (req_opcode == oip->opcode)
+                                               break;
+                               }
+                               supp = (k >= na) ? 1 : 3;
+                       } else if (req_sa != oip->sa) {
+                               na = oip->num_attached;
+                               for (k = 0, oip = oip->arrp; k < na;
+                                    ++k, ++oip) {
+                                       if (req_sa == oip->sa)
+                                               break;
+                               }
+                               supp = (k >= na) ? 1 : 3;
+                       } else
+                               supp = 3;
+                       if (3 == supp) {
+                               u = oip->len_mask[0];
+                               put_unaligned_be16(u, arr + 2);
+                               arr[4] = oip->opcode;
+                               for (k = 1; k < u; ++k)
+                                       arr[4 + k] = (k < 16) ?
+                                                oip->len_mask[k] : 0xff;
+                               offset = 4 + u;
+                       } else
+                               offset = 4;
+               }
+               arr[1] = (rctd ? 0x80 : 0) | supp;
+               if (rctd) {
+                       put_unaligned_be16(0xa, arr + offset);
+                       offset += 12;
+               }
+               break;
+       default:
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2);
+               kfree(arr);
+               return check_condition_result;
+       }
+       offset = (offset < a_len) ? offset : a_len;
+       len = (offset < alloc_len) ? offset : alloc_len;
+       errsts = fill_from_dev_buffer(scp, arr, len);
+       kfree(arr);
+       return errsts;
+}
+
+static int
+resp_rsup_tmfs(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+       bool repd;
+       u32 alloc_len, len;
+       u8 arr[16];
+       u8 *cmd = scp->cmnd;
+
+       memset(arr, 0, sizeof(arr));
+       repd = !!(cmd[2] & 0x80);
+       alloc_len = get_unaligned_be32(cmd + 6);
+       if (alloc_len < 4) {
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 6, -1);
+               return check_condition_result;
+       }
+       arr[0] = 0xc8;          /* ATS | ATSS | LURS */
+       arr[1] = 0x1;           /* ITNRS */
+       if (repd) {
+               arr[3] = 0xc;
+               len = 16;
+       } else
+               len = 4;
+
+       len = (len < alloc_len) ? len : alloc_len;
+       return fill_from_dev_buffer(scp, arr, len);
+}
+
 /* <<Following mode page info copied from ST318451LW>> */
 
 static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target)
@@ -1459,20 +1942,18 @@ static int resp_sas_sha_m_spg(unsigned char * p, int pcontrol)
 
 #define SDEBUG_MAX_MSENSE_SZ 256
 
-static int resp_mode_sense(struct scsi_cmnd * scp, int target,
-                          struct sdebug_dev_info * devip)
+static int
+resp_mode_sense(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
        unsigned char dbd, llbaa;
        int pcontrol, pcode, subpcode, bd_len;
        unsigned char dev_spec;
-       int k, alloc_len, msense_6, offset, len, errsts, target_dev_id;
+       int k, alloc_len, msense_6, offset, len, target_dev_id;
+       int target = scp->device->id;
        unsigned char * ap;
        unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
        unsigned char *cmd = scp->cmnd;
 
-       errsts = check_readiness(scp, UAS_ONLY, devip);
-       if (errsts)
-               return errsts;
        dbd = !!(cmd[1] & 0x8);
        pcontrol = (cmd[2] & 0xc0) >> 6;
        pcode = cmd[2] & 0x3f;
@@ -1542,8 +2023,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
 
        if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
                /* TODO: Control Extension page */
-               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
                return check_condition_result;
        }
        switch (pcode) {
@@ -1569,8 +2049,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                break;
        case 0x19:      /* if spc==1 then sas phy, control+discover */
                if ((subpcode > 0x2) && (subpcode < 0xff)) {
-                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                                       INVALID_FIELD_IN_CDB, 0);
+                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
                        return check_condition_result;
                }
                len = 0;
@@ -1602,15 +2081,13 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
                        }
                        len += resp_iec_m_pg(ap + len, pcontrol, target);
                } else {
-                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                                       INVALID_FIELD_IN_CDB, 0);
+                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
                        return check_condition_result;
                 }
                offset += len;
                break;
        default:
-               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
                return check_condition_result;
        }
        if (msense_6)
@@ -1624,24 +2101,21 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target,
 
 #define SDEBUG_MAX_MSELECT_SZ 512
 
-static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
-                           struct sdebug_dev_info * devip)
+static int
+resp_mode_select(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
        int pf, sp, ps, md_len, bd_len, off, spf, pg_len;
-       int param_len, res, errsts, mpage;
+       int param_len, res, mpage;
        unsigned char arr[SDEBUG_MAX_MSELECT_SZ];
        unsigned char *cmd = scp->cmnd;
+       int mselect6 = (MODE_SELECT == cmd[0]);
 
-       errsts = check_readiness(scp, UAS_ONLY, devip);
-       if (errsts)
-               return errsts;
        memset(arr, 0, sizeof(arr));
        pf = cmd[1] & 0x10;
        sp = cmd[1] & 0x1;
        param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]);
        if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                               INVALID_FIELD_IN_CDB, 0);
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, mselect6 ? 4 : 7, -1);
                return check_condition_result;
        }
         res = fetch_to_dev_buffer(scp, arr, param_len);
@@ -1655,16 +2129,14 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
        md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2);
        bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]);
        if (md_len > 2) {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                               INVALID_FIELD_IN_PARAM_LIST, 0);
+               mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
                return check_condition_result;
        }
        off = bd_len + (mselect6 ? 4 : 8);
        mpage = arr[off] & 0x3f;
        ps = !!(arr[off] & 0x80);
        if (ps) {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                               INVALID_FIELD_IN_PARAM_LIST, 0);
+               mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 7);
                return check_condition_result;
        }
        spf = !!(arr[off] & 0x40);
@@ -1701,8 +2173,7 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6,
        default:
                break;
        }
-       mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                       INVALID_FIELD_IN_PARAM_LIST, 0);
+       mk_sense_invalid_fld(scp, SDEB_IN_DATA, off, 5);
        return check_condition_result;
 set_mode_changed_ua:
        set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm);
@@ -1737,19 +2208,15 @@ static int resp_ie_l_pg(unsigned char * arr)
 static int resp_log_sense(struct scsi_cmnd * scp,
                           struct sdebug_dev_info * devip)
 {
-       int ppc, sp, pcontrol, pcode, subpcode, alloc_len, errsts, len, n;
+       int ppc, sp, pcontrol, pcode, subpcode, alloc_len, len, n;
        unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
        unsigned char *cmd = scp->cmnd;
 
-       errsts = check_readiness(scp, UAS_ONLY, devip);
-       if (errsts)
-               return errsts;
        memset(arr, 0, sizeof(arr));
        ppc = cmd[1] & 0x2;
        sp = cmd[1] & 0x1;
        if (ppc || sp) {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                               INVALID_FIELD_IN_CDB, 0);
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, ppc ? 1 : 0);
                return check_condition_result;
        }
        pcontrol = (cmd[2] & 0xc0) >> 6;
@@ -1773,8 +2240,7 @@ static int resp_log_sense(struct scsi_cmnd * scp,
                        arr[3] = resp_ie_l_pg(arr + 4);
                        break;
                default:
-                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                                       INVALID_FIELD_IN_CDB, 0);
+                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
                        return check_condition_result;
                }
        } else if (0xff == subpcode) {
@@ -1806,13 +2272,11 @@ static int resp_log_sense(struct scsi_cmnd * scp,
                        arr[3] = n - 4;
                        break;
                default:
-                       mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                                       INVALID_FIELD_IN_CDB, 0);
+                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
                        return check_condition_result;
                }
        } else {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST,
-                               INVALID_FIELD_IN_CDB, 0);
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
                return check_condition_result;
        }
        len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len);
@@ -1824,11 +2288,12 @@ static int check_device_access_params(struct scsi_cmnd *scp,
                                      unsigned long long lba, unsigned int num)
 {
        if (lba + num > sdebug_capacity) {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0);
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
                return check_condition_result;
        }
        /* transfer length excessive (tie in to block limits VPD page) */
        if (num > sdebug_store_sectors) {
+               /* needs work to find which cdb byte 'num' comes from */
                mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
                return check_condition_result;
        }
@@ -1836,17 +2301,17 @@ static int check_device_access_params(struct scsi_cmnd *scp,
 }
 
 /* Returns number of bytes copied or -1 if error. */
-static int do_device_access(struct scsi_cmnd *scmd,
-                           unsigned long long lba, unsigned int num, int write)
+static int
+do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
 {
        int ret;
-       unsigned long long block, rest = 0;
+       u64 block, rest = 0;
        struct scsi_data_buffer *sdb;
        enum dma_data_direction dir;
        size_t (*func)(struct scatterlist *, unsigned int, void *, size_t,
                       off_t);
 
-       if (write) {
+       if (do_write) {
                sdb = scsi_out(scmd);
                dir = DMA_TO_DEVICE;
                func = sg_pcopy_to_buffer;
@@ -1880,6 +2345,38 @@ static int do_device_access(struct scsi_cmnd *scmd,
        return ret;
 }
 
+/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
+ * arr into fake_store(lba,num) and return true. If comparison fails then
+ * return false. */
+static bool
+comp_write_worker(u64 lba, u32 num, const u8 *arr)
+{
+       bool res;
+       u64 block, rest = 0;
+       u32 store_blks = sdebug_store_sectors;
+       u32 lb_size = scsi_debug_sector_size;
+
+       block = do_div(lba, store_blks);
+       if (block + num > store_blks)
+               rest = block + num - store_blks;
+
+       res = !memcmp(fake_storep + (block * lb_size), arr,
+                     (num - rest) * lb_size);
+       if (!res)
+               return res;
+       if (rest)
+               res = memcmp(fake_storep, arr + ((num - rest) * lb_size),
+                            rest * lb_size);
+       if (!res)
+               return res;
+       arr += num * lb_size;
+       memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size);
+       if (rest)
+               memcpy(fake_storep, arr + ((num - rest) * lb_size),
+                      rest * lb_size);
+       return res;
+}
+
 static __be16 dif_compute_csum(const void *buf, int len)
 {
        __be16 csum;
@@ -1992,55 +2489,143 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
        return 0;
 }
 
-static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
-                    unsigned int num, u32 ei_lba)
+static int
+resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
+       u8 *cmd = scp->cmnd;
+       u64 lba;
+       u32 num;
+       u32 ei_lba;
        unsigned long iflags;
        int ret;
+       bool check_prot;
 
-       ret = check_device_access_params(SCpnt, lba, num);
-       if (ret)
-               return ret;
+       switch (cmd[0]) {
+       case READ_16:
+               ei_lba = 0;
+               lba = get_unaligned_be64(cmd + 2);
+               num = get_unaligned_be32(cmd + 10);
+               check_prot = true;
+               break;
+       case READ_10:
+               ei_lba = 0;
+               lba = get_unaligned_be32(cmd + 2);
+               num = get_unaligned_be16(cmd + 7);
+               check_prot = true;
+               break;
+       case READ_6:
+               ei_lba = 0;
+               lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
+                     (u32)(cmd[1] & 0x1f) << 16;
+               num = (0 == cmd[4]) ? 256 : cmd[4];
+               check_prot = true;
+               break;
+       case READ_12:
+               ei_lba = 0;
+               lba = get_unaligned_be32(cmd + 2);
+               num = get_unaligned_be32(cmd + 6);
+               check_prot = true;
+               break;
+       case XDWRITEREAD_10:
+               ei_lba = 0;
+               lba = get_unaligned_be32(cmd + 2);
+               num = get_unaligned_be16(cmd + 7);
+               check_prot = false;
+               break;
+       default:        /* assume READ(32) */
+               lba = get_unaligned_be64(cmd + 12);
+               ei_lba = get_unaligned_be32(cmd + 20);
+               num = get_unaligned_be32(cmd + 28);
+               check_prot = false;
+               break;
+       }
+       if (check_prot) {
+               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+                   (cmd[1] & 0xe0)) {
+                       mk_sense_invalid_opcode(scp);
+                       return check_condition_result;
+               }
+               if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
+                    scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+                   (cmd[1] & 0xe0) == 0)
+                       sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
+                                   "to DIF device\n");
+       }
+       if (sdebug_any_injecting_opt) {
+               struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
+
+               if (ep->inj_short)
+                       num /= 2;
+       }
+
+       /* inline check_device_access_params() */
+       if (lba + num > sdebug_capacity) {
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+               return check_condition_result;
+       }
+       /* transfer length excessive (tie in to block limits VPD page) */
+       if (num > sdebug_store_sectors) {
+               /* needs work to find which cdb byte 'num' comes from */
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+               return check_condition_result;
+       }
 
        if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
            (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
            ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
                /* claim unrecoverable read error */
-               mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
+               mk_sense_buffer(scp, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
                /* set info field and valid bit for fixed descriptor */
-               if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) {
-                       SCpnt->sense_buffer[0] |= 0x80; /* Valid bit */
+               if (0x70 == (scp->sense_buffer[0] & 0x7f)) {
+                       scp->sense_buffer[0] |= 0x80;   /* Valid bit */
                        ret = (lba < OPT_MEDIUM_ERR_ADDR)
                              ? OPT_MEDIUM_ERR_ADDR : (int)lba;
-                       SCpnt->sense_buffer[3] = (ret >> 24) & 0xff;
-                       SCpnt->sense_buffer[4] = (ret >> 16) & 0xff;
-                       SCpnt->sense_buffer[5] = (ret >> 8) & 0xff;
-                       SCpnt->sense_buffer[6] = ret & 0xff;
+                       put_unaligned_be32(ret, scp->sense_buffer + 3);
                }
-               scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
+               scsi_set_resid(scp, scsi_bufflen(scp));
                return check_condition_result;
        }
 
        read_lock_irqsave(&atomic_rw, iflags);
 
        /* DIX + T10 DIF */
-       if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
-               int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba);
+       if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
+               int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
 
                if (prot_ret) {
                        read_unlock_irqrestore(&atomic_rw, iflags);
-                       mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret);
+                       mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
                        return illegal_condition_result;
                }
        }
 
-       ret = do_device_access(SCpnt, lba, num, 0);
+       ret = do_device_access(scp, lba, num, false);
        read_unlock_irqrestore(&atomic_rw, iflags);
        if (ret == -1)
                return DID_ERROR << 16;
 
-       scsi_in(SCpnt)->resid = scsi_bufflen(SCpnt) - ret;
+       scsi_in(scp)->resid = scsi_bufflen(scp) - ret;
+
+       if (sdebug_any_injecting_opt) {
+               struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
 
+               if (ep->inj_recovered) {
+                       mk_sense_buffer(scp, RECOVERED_ERROR,
+                                       THRESHOLD_EXCEEDED, 0);
+                       return check_condition_result;
+               } else if (ep->inj_transport) {
+                       mk_sense_buffer(scp, ABORTED_COMMAND,
+                                       TRANSPORT_PROBLEM, ACK_NAK_TO);
+                       return check_condition_result;
+               } else if (ep->inj_dif) {
+                       /* Logical block guard check failed */
+                       mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+                       return illegal_condition_result;
+               } else if (ep->inj_dix) {
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+                       return illegal_condition_result;
+               }
+       }
        return 0;
 }
 
@@ -2223,31 +2808,95 @@ static void unmap_region(sector_t lba, unsigned int len)
        }
 }
 
-static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
-                     unsigned int num, u32 ei_lba)
+static int
+resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
+       u8 *cmd = scp->cmnd;
+       u64 lba;
+       u32 num;
+       u32 ei_lba;
        unsigned long iflags;
        int ret;
+       bool check_prot;
 
-       ret = check_device_access_params(SCpnt, lba, num);
-       if (ret)
-               return ret;
+       switch (cmd[0]) {
+       case WRITE_16:
+               ei_lba = 0;
+               lba = get_unaligned_be64(cmd + 2);
+               num = get_unaligned_be32(cmd + 10);
+               check_prot = true;
+               break;
+       case WRITE_10:
+               ei_lba = 0;
+               lba = get_unaligned_be32(cmd + 2);
+               num = get_unaligned_be16(cmd + 7);
+               check_prot = true;
+               break;
+       case WRITE_6:
+               ei_lba = 0;
+               lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
+                     (u32)(cmd[1] & 0x1f) << 16;
+               num = (0 == cmd[4]) ? 256 : cmd[4];
+               check_prot = true;
+               break;
+       case WRITE_12:
+               ei_lba = 0;
+               lba = get_unaligned_be32(cmd + 2);
+               num = get_unaligned_be32(cmd + 6);
+               check_prot = true;
+               break;
+       case 0x53:      /* XDWRITEREAD(10) */
+               ei_lba = 0;
+               lba = get_unaligned_be32(cmd + 2);
+               num = get_unaligned_be16(cmd + 7);
+               check_prot = false;
+               break;
+       default:        /* assume WRITE(32) */
+               lba = get_unaligned_be64(cmd + 12);
+               ei_lba = get_unaligned_be32(cmd + 20);
+               num = get_unaligned_be32(cmd + 28);
+               check_prot = false;
+               break;
+       }
+       if (check_prot) {
+               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+                   (cmd[1] & 0xe0)) {
+                       mk_sense_invalid_opcode(scp);
+                       return check_condition_result;
+               }
+               if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
+                    scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+                   (cmd[1] & 0xe0) == 0)
+                       sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
+                                   "to DIF device\n");
+       }
+
+       /* inline check_device_access_params() */
+       if (lba + num > sdebug_capacity) {
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+               return check_condition_result;
+       }
+       /* transfer length excessive (tie in to block limits VPD page) */
+       if (num > sdebug_store_sectors) {
+               /* needs work to find which cdb byte 'num' comes from */
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+               return check_condition_result;
+       }
 
        write_lock_irqsave(&atomic_rw, iflags);
 
        /* DIX + T10 DIF */
-       if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
-               int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba);
+       if (scsi_debug_dix && scsi_prot_sg_count(scp)) {
+               int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
 
                if (prot_ret) {
                        write_unlock_irqrestore(&atomic_rw, iflags);
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10,
-                                       prot_ret);
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
                        return illegal_condition_result;
                }
        }
 
-       ret = do_device_access(SCpnt, lba, num, 1);
+       ret = do_device_access(scp, lba, num, true);
        if (scsi_debug_lbp())
                map_region(lba, num);
        write_unlock_irqrestore(&atomic_rw, iflags);
@@ -2255,30 +2904,41 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
                return (DID_ERROR << 16);
        else if ((ret < (num * scsi_debug_sector_size)) &&
                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-               sdev_printk(KERN_INFO, SCpnt->device,
+               sdev_printk(KERN_INFO, scp->device,
                            "%s: write: cdb indicated=%u, IO sent=%d bytes\n",
                            my_name, num * scsi_debug_sector_size, ret);
 
+       if (sdebug_any_injecting_opt) {
+               struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
+
+               if (ep->inj_recovered) {
+                       mk_sense_buffer(scp, RECOVERED_ERROR,
+                                       THRESHOLD_EXCEEDED, 0);
+                       return check_condition_result;
+               } else if (ep->inj_dif) {
+                       /* Logical block guard check failed */
+                       mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+                       return illegal_condition_result;
+               } else if (ep->inj_dix) {
+                       mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+                       return illegal_condition_result;
+               }
+       }
        return 0;
 }
 
-static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
-                     unsigned int num, u32 ei_lba, unsigned int unmap)
+static int
+resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num, u32 ei_lba,
+               bool unmap, bool ndob)
 {
        unsigned long iflags;
        unsigned long long i;
        int ret;
 
-       ret = check_device_access_params(scmd, lba, num);
+       ret = check_device_access_params(scp, lba, num);
        if (ret)
                return ret;
 
-       if (num > scsi_debug_write_same_length) {
-               mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
-               return check_condition_result;
-       }
-
        write_lock_irqsave(&atomic_rw, iflags);
 
        if (unmap && scsi_debug_lbp()) {
@@ -2286,17 +2946,22 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
                goto out;
        }
 
-       /* Else fetch one logical block */
-       ret = fetch_to_dev_buffer(scmd,
-                                 fake_storep + (lba * scsi_debug_sector_size),
-                                 scsi_debug_sector_size);
+       /* if ndob then zero 1 logical block, else fetch 1 logical block */
+       if (ndob) {
+               memset(fake_storep + (lba * scsi_debug_sector_size), 0,
+                      scsi_debug_sector_size);
+               ret = 0;
+       } else
+               ret = fetch_to_dev_buffer(scp, fake_storep +
+                                              (lba * scsi_debug_sector_size),
+                                         scsi_debug_sector_size);
 
        if (-1 == ret) {
                write_unlock_irqrestore(&atomic_rw, iflags);
                return (DID_ERROR << 16);
        } else if ((ret < (num * scsi_debug_sector_size)) &&
                 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
-               sdev_printk(KERN_INFO, scmd->device,
+               sdev_printk(KERN_INFO, scp->device,
                            "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
                            my_name, "write same",
                            num * scsi_debug_sector_size, ret);
@@ -2315,34 +2980,170 @@ out:
        return 0;
 }
 
-struct unmap_block_desc {
-       __be64  lba;
-       __be32  blocks;
-       __be32  __reserved;
-};
+static int
+resp_write_same_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+       u8 *cmd = scp->cmnd;
+       u32 lba;
+       u16 num;
+       u32 ei_lba = 0;
+       bool unmap = false;
+
+       if (cmd[1] & 0x8) {
+               if (scsi_debug_lbpws10 == 0) {
+                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
+                       return check_condition_result;
+               } else
+                       unmap = true;
+       }
+       lba = get_unaligned_be32(cmd + 2);
+       num = get_unaligned_be16(cmd + 7);
+       if (num > scsi_debug_write_same_length) {
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
+               return check_condition_result;
+       }
+       return resp_write_same(scp, lba, num, ei_lba, unmap, false);
+}
 
-static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
+static int
+resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
-       unsigned char *buf;
+       u8 *cmd = scp->cmnd;
+       u64 lba;
+       u32 num;
+       u32 ei_lba = 0;
+       bool unmap = false;
+       bool ndob = false;
+
+       if (cmd[1] & 0x8) {     /* UNMAP */
+               if (scsi_debug_lbpws == 0) {
+                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 3);
+                       return check_condition_result;
+               } else
+                       unmap = true;
+       }
+       if (cmd[1] & 0x1)  /* NDOB (no data-out buffer, assumes zeroes) */
+               ndob = true;
+       lba = get_unaligned_be64(cmd + 2);
+       num = get_unaligned_be32(cmd + 10);
+       if (num > scsi_debug_write_same_length) {
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
+               return check_condition_result;
+       }
+       return resp_write_same(scp, lba, num, ei_lba, unmap, ndob);
+}
+
+static int
+resp_comp_write(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+       u8 *cmd = scp->cmnd;
+       u8 *arr;
+       u8 *fake_storep_hold;
+       u64 lba;
+       u32 dnum;
+       u32 lb_size = scsi_debug_sector_size;
+       u8 num;
+       unsigned long iflags;
+       int ret;
+
+       lba = get_unaligned_be32(cmd + 2);
+       num = cmd[13];          /* 1 to a maximum of 255 logical blocks */
+       if (0 == num)
+               return 0;       /* degenerate case, not an error */
+       dnum = 2 * num;
+       arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
+       if (NULL == arr) {
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+                               INSUFF_RES_ASCQ);
+               return check_condition_result;
+       }
+       if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
+           (cmd[1] & 0xe0)) {
+               mk_sense_invalid_opcode(scp);
+               return check_condition_result;
+       }
+       if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
+            scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
+           (cmd[1] & 0xe0) == 0)
+               sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
+                           "to DIF device\n");
+
+       /* inline check_device_access_params() */
+       if (lba + num > sdebug_capacity) {
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+               return check_condition_result;
+       }
+       /* transfer length excessive (tie in to block limits VPD page) */
+       if (num > sdebug_store_sectors) {
+               /* needs work to find which cdb byte 'num' comes from */
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+               return check_condition_result;
+       }
+
+       write_lock_irqsave(&atomic_rw, iflags);
+
+       /* trick do_device_access() to fetch both compare and write buffers
+        * from data-in into arr. Safe (atomic) since write_lock held. */
+       fake_storep_hold = fake_storep;
+       fake_storep = arr;
+       ret = do_device_access(scp, 0, dnum, true);
+       fake_storep = fake_storep_hold;
+       if (ret == -1) {
+               write_unlock_irqrestore(&atomic_rw, iflags);
+               kfree(arr);
+               return DID_ERROR << 16;
+       } else if ((ret < (dnum * lb_size)) &&
+                (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+               sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
+                           "indicated=%u, IO sent=%d bytes\n", my_name,
+                           dnum * lb_size, ret);
+       if (!comp_write_worker(lba, num, arr)) {
+               write_unlock_irqrestore(&atomic_rw, iflags);
+               kfree(arr);
+               mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
+               return check_condition_result;
+       }
+       if (scsi_debug_lbp())
+               map_region(lba, num);
+       write_unlock_irqrestore(&atomic_rw, iflags);
+       return 0;
+}
+
+struct unmap_block_desc {
+       __be64  lba;
+       __be32  blocks;
+       __be32  __reserved;
+};
+
+static int
+resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+       unsigned char *buf;
        struct unmap_block_desc *desc;
        unsigned int i, payload_len, descriptors;
        int ret;
        unsigned long iflags;
 
-       ret = check_readiness(scmd, UAS_ONLY, devip);
-       if (ret)
-               return ret;
 
-       payload_len = get_unaligned_be16(&scmd->cmnd[7]);
-       BUG_ON(scsi_bufflen(scmd) != payload_len);
+       if (!scsi_debug_lbp())
+               return 0;       /* fib and say its done */
+       payload_len = get_unaligned_be16(scp->cmnd + 7);
+       BUG_ON(scsi_bufflen(scp) != payload_len);
 
        descriptors = (payload_len - 8) / 16;
+       if (descriptors > scsi_debug_unmap_max_desc) {
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 7, -1);
+               return check_condition_result;
+       }
 
-       buf = kmalloc(scsi_bufflen(scmd), GFP_ATOMIC);
-       if (!buf)
+       buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
+       if (!buf) {
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+                               INSUFF_RES_ASCQ);
                return check_condition_result;
+       }
 
-       scsi_sg_copy_to_buffer(scmd, buf, scsi_bufflen(scmd));
+       scsi_sg_copy_to_buffer(scp, buf, scsi_bufflen(scp));
 
        BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
        BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
@@ -2355,7 +3156,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
                unsigned long long lba = get_unaligned_be64(&desc[i].lba);
                unsigned int num = get_unaligned_be32(&desc[i].blocks);
 
-               ret = check_device_access_params(scmd, lba, num);
+               ret = check_device_access_params(scp, lba, num);
                if (ret)
                        goto out;
 
@@ -2373,37 +3174,44 @@ out:
 
 #define SDEBUG_GET_LBA_STATUS_LEN 32
 
-static int resp_get_lba_status(struct scsi_cmnd * scmd,
-                              struct sdebug_dev_info * devip)
+static int
+resp_get_lba_status(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
-       unsigned long long lba;
-       unsigned int alloc_len, mapped, num;
-       unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN];
+       u8 *cmd = scp->cmnd;
+       u64 lba;
+       u32 alloc_len, mapped, num;
+       u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
        int ret;
 
-       ret = check_readiness(scmd, UAS_ONLY, devip);
-       if (ret)
-               return ret;
-
-       lba = get_unaligned_be64(&scmd->cmnd[2]);
-       alloc_len = get_unaligned_be32(&scmd->cmnd[10]);
+       lba = get_unaligned_be64(cmd + 2);
+       alloc_len = get_unaligned_be32(cmd + 10);
 
        if (alloc_len < 24)
                return 0;
 
-       ret = check_device_access_params(scmd, lba, 1);
+       ret = check_device_access_params(scp, lba, 1);
        if (ret)
                return ret;
 
-       mapped = map_state(lba, &num);
+       if (scsi_debug_lbp())
+               mapped = map_state(lba, &num);
+       else {
+               mapped = 1;
+               /* following just in case virtual_gb changed */
+               sdebug_capacity = get_sdebug_capacity();
+               if (sdebug_capacity - lba <= 0xffffffff)
+                       num = sdebug_capacity - lba;
+               else
+                       num = 0xffffffff;
+       }
 
        memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
-       put_unaligned_be32(20, &arr[0]);        /* Parameter Data Length */
-       put_unaligned_be64(lba, &arr[8]);       /* LBA */
-       put_unaligned_be32(num, &arr[16]);      /* Number of blocks */
-       arr[20] = !mapped;                      /* mapped = 0, unmapped = 1 */
+       put_unaligned_be32(20, arr);            /* Parameter Data Length */
+       put_unaligned_be64(lba, arr + 8);       /* LBA */
+       put_unaligned_be32(num, arr + 16);      /* Number of blocks */
+       arr[20] = !mapped;              /* prov_stat=0: mapped; 1: dealloc */
 
-       return fill_from_dev_buffer(scmd, arr, SDEBUG_GET_LBA_STATUS_LEN);
+       return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
 }
 
 #define SDEBUG_RLUN_ARR_SZ 256
@@ -2412,8 +3220,8 @@ static int resp_report_luns(struct scsi_cmnd * scp,
                            struct sdebug_dev_info * devip)
 {
        unsigned int alloc_len;
-       int lun_cnt, i, upper, num, n;
-       u64 wlun, lun;
+       int lun_cnt, i, upper, num, n, want_wlun, shortish;
+       u64 lun;
        unsigned char *cmd = scp->cmnd;
        int select_report = (int)cmd[2];
        struct scsi_lun *one_lun;
@@ -2421,9 +3229,9 @@ static int resp_report_luns(struct scsi_cmnd * scp,
        unsigned char * max_addr;
 
        alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
-       if ((alloc_len < 4) || (select_report > 2)) {
-               mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-                               0);
+       shortish = (alloc_len < 4);
+       if (shortish || (select_report > 2)) {
+               mk_sense_invalid_fld(scp, SDEB_IN_CDB, shortish ? 6 : 2, -1);
                return check_condition_result;
        }
        /* can produce response with up to 16k luns (lun 0 to lun 16383) */
@@ -2433,14 +3241,14 @@ static int resp_report_luns(struct scsi_cmnd * scp,
                lun_cnt = 0;
        else if (scsi_debug_no_lun_0 && (lun_cnt > 0))
                --lun_cnt;
-       wlun = (select_report > 0) ? 1 : 0;
-       num = lun_cnt + wlun;
+       want_wlun = (select_report > 0) ? 1 : 0;
+       num = lun_cnt + want_wlun;
        arr[2] = ((sizeof(struct scsi_lun) * num) >> 8) & 0xff;
        arr[3] = (sizeof(struct scsi_lun) * num) & 0xff;
        n = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
                            sizeof(struct scsi_lun)), num);
        if (n < num) {
-               wlun = 0;
+               want_wlun = 0;
                lun_cnt = n;
        }
        one_lun = (struct scsi_lun *) &arr[8];
@@ -2454,7 +3262,7 @@ static int resp_report_luns(struct scsi_cmnd * scp,
                            (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
                one_lun[i].scsi_lun[1] = lun & 0xff;
        }
-       if (wlun) {
+       if (want_wlun) {
                one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff;
                one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff;
                i++;
@@ -2476,8 +3284,8 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
        /* better not to use temporary buffer. */
        buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC);
        if (!buf) {
-               mk_sense_buffer(scp, NOT_READY,
-                               LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+                               INSUFF_RES_ASCQ);
                return check_condition_result;
        }
 
@@ -2500,6 +3308,32 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
        return 0;
 }
 
+static int
+resp_xdwriteread_10(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+       u8 *cmd = scp->cmnd;
+       u64 lba;
+       u32 num;
+       int errsts;
+
+       if (!scsi_bidi_cmnd(scp)) {
+               mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+                               INSUFF_RES_ASCQ);
+               return check_condition_result;
+       }
+       errsts = resp_read_dt0(scp, devip);
+       if (errsts)
+               return errsts;
+       if (!(cmd[1] & 0x4)) {          /* DISABLE_WRITE is not set */
+               errsts = resp_write_dt0(scp, devip);
+               if (errsts)
+                       return errsts;
+       }
+       lba = get_unaligned_be32(cmd + 2);
+       num = get_unaligned_be16(cmd + 7);
+       return resp_xdwriteread(scp, lba, num, devip);
+}
+
 /* When timer or tasklet goes off this function is called. */
 static void sdebug_q_cmd_complete(unsigned long indx)
 {
@@ -2672,10 +3506,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev)
        open_devip->sdbg_host = sdbg_host;
        atomic_set(&open_devip->num_in_q, 0);
        set_bit(SDEBUG_UA_POR, open_devip->uas_bm);
-       open_devip->used = 1;
-       if (sdev->lun == SAM2_WLUN_REPORT_LUNS)
-               open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff;
-
+       open_devip->used = true;
        return open_devip;
 }
 
@@ -2701,10 +3532,6 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp)
        if (NULL == devip)
                return 1;       /* no resources, will be marked offline */
        sdp->hostdata = devip;
-       sdp->tagged_supported = 1;
-       if (sdp->host->cmd_per_lun)
-               scsi_adjust_queue_depth(sdp, DEF_TAGGED_QUEUING,
-                                       DEF_CMD_PER_LUN);
        blk_queue_max_segment_size(sdp->request_queue, -1U);
        if (scsi_debug_no_uld)
                sdp->no_uld_attach = 1;
@@ -2721,7 +3548,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp)
                       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
        if (devip) {
                /* make this slot available for re-use */
-               devip->used = 0;
+               devip->used = false;
                sdp->hostdata = NULL;
        }
 }
@@ -3166,6 +3993,7 @@ module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
 module_param_named(removable, scsi_debug_removable, bool, S_IRUGO | S_IWUSR);
 module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
 module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
+module_param_named(strict, scsi_debug_strict, bool, S_IRUGO | S_IWUSR);
 module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
 module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
 module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
@@ -3185,7 +4013,7 @@ MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
 MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
 MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
 MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny");
-MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
+MODULE_PARM_DESC(dev_size_mb, "size in MiB of ram shared by devs(def=8)");
 MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
 MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
 MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
@@ -3212,11 +4040,12 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
 MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
 MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=6[SPC-4])");
 MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
+MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
 MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
 MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
 MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
 MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
-MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
+MODULE_PARM_DESC(virtual_gb, "virtual gigabyte (GiB) size (def=0 -> use dev_size_mb)");
 MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
 MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
 
@@ -3382,6 +4211,16 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf,
        return -EINVAL;
 opts_done:
        scsi_debug_opts = opts;
+       if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
+               sdebug_any_injecting_opt = true;
        atomic_set(&sdebug_cmnd_count, 0);
        atomic_set(&sdebug_a_tsf, 0);
        return count;
@@ -3589,12 +4428,25 @@ static ssize_t virtual_gb_store(struct device_driver *ddp, const char *buf,
                                size_t count)
 {
         int n;
+       bool changed;
 
        if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+               changed = (scsi_debug_virtual_gb != n);
                scsi_debug_virtual_gb = n;
-
                sdebug_capacity = get_sdebug_capacity();
-
+               if (changed) {
+                       struct sdebug_host_info *sdhp;
+                       struct sdebug_dev_info *dp;
+
+                       list_for_each_entry(sdhp, &sdebug_host_list,
+                                           host_list) {
+                               list_for_each_entry(dp, &sdhp->dev_info_list,
+                                                   dev_list) {
+                                       set_bit(SDEBUG_UA_CAPACITY_CHANGED,
+                                               dp->uas_bm);
+                               }
+                       }
+               }
                return count;
        }
        return -EINVAL;
@@ -3740,6 +4592,23 @@ static ssize_t host_lock_store(struct device_driver *ddp, const char *buf,
 }
 static DRIVER_ATTR_RW(host_lock);
 
+static ssize_t strict_show(struct device_driver *ddp, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_strict);
+}
+static ssize_t strict_store(struct device_driver *ddp, const char *buf,
+                           size_t count)
+{
+       int n;
+
+       if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+               scsi_debug_strict = (n > 0);
+               return count;
+       }
+       return -EINVAL;
+}
+static DRIVER_ATTR_RW(strict);
+
 
 /* Note: The following array creates attribute files in the
    /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
@@ -3775,6 +4644,7 @@ static struct attribute *sdebug_drv_attrs[] = {
        &driver_attr_removable.attr,
        &driver_attr_host_lock.attr,
        &driver_attr_ndelay.attr,
+       &driver_attr_strict.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(sdebug_drv);
@@ -4087,396 +4957,9 @@ static void sdebug_remove_adapter(void)
 }
 
 static int
-scsi_debug_queuecommand(struct scsi_cmnd *SCpnt)
-{
-       unsigned char *cmd = SCpnt->cmnd;
-       int len, k;
-       unsigned int num;
-       unsigned long long lba;
-       u32 ei_lba;
-       int errsts = 0;
-       int target = SCpnt->device->id;
-       struct sdebug_dev_info *devip = NULL;
-       int inj_recovered = 0;
-       int inj_transport = 0;
-       int inj_dif = 0;
-       int inj_dix = 0;
-       int inj_short = 0;
-       int delay_override = 0;
-       int unmap = 0;
-
-       scsi_set_resid(SCpnt, 0);
-       if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) &&
-           !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
-               char b[120];
-               int n;
-
-               len = SCpnt->cmd_len;
-               if (len > 32)
-                       strcpy(b, "too long, over 32 bytes");
-               else {
-                       for (k = 0, n = 0; k < len; ++k)
-                               n += scnprintf(b + n, sizeof(b) - n, "%02x ",
-                                              (unsigned int)cmd[k]);
-               }
-               sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name,
-                           b);
-       }
-
-       if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
-           (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
-               return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
-       devip = devInfoReg(SCpnt->device);
-       if (NULL == devip)
-               return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0);
-
-       if ((scsi_debug_every_nth != 0) &&
-           (atomic_inc_return(&sdebug_cmnd_count) >=
-            abs(scsi_debug_every_nth))) {
-               atomic_set(&sdebug_cmnd_count, 0);
-               if (scsi_debug_every_nth < -1)
-                       scsi_debug_every_nth = -1;
-               if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
-                       return 0; /* ignore command causing timeout */
-               else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
-                        scsi_medium_access_command(SCpnt))
-                       return 0; /* time out reads and writes */
-               else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
-                       inj_recovered = 1; /* to reads and writes below */
-               else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
-                       inj_transport = 1; /* to reads and writes below */
-               else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts)
-                       inj_dif = 1; /* to reads and writes below */
-               else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts)
-                       inj_dix = 1; /* to reads and writes below */
-               else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & scsi_debug_opts)
-                       inj_short = 1;
-       }
-
-       if (devip->wlun) {
-               switch (*cmd) {
-               case INQUIRY:
-               case REQUEST_SENSE:
-               case TEST_UNIT_READY:
-               case REPORT_LUNS:
-                       break;  /* only allowable wlun commands */
-               default:
-                       if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                               printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
-                                      "not supported for wlun\n", *cmd);
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                       INVALID_OPCODE, 0);
-                       errsts = check_condition_result;
-                       return schedule_resp(SCpnt, devip, errsts, 0);
-               }
-       }
-
-       switch (*cmd) {
-       case INQUIRY:     /* mandatory, ignore unit attention */
-               delay_override = 1;
-               errsts = resp_inquiry(SCpnt, target, devip);
-               break;
-       case REQUEST_SENSE:     /* mandatory, ignore unit attention */
-               delay_override = 1;
-               errsts = resp_requests(SCpnt, devip);
-               break;
-       case REZERO_UNIT:       /* actually this is REWIND for SSC */
-       case START_STOP:
-               errsts = resp_start_stop(SCpnt, devip);
-               break;
-       case ALLOW_MEDIUM_REMOVAL:
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               if (errsts)
-                       break;
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       printk(KERN_INFO "scsi_debug: Medium removal %s\n",
-                              cmd[4] ? "inhibited" : "enabled");
-               break;
-       case SEND_DIAGNOSTIC:     /* mandatory */
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               break;
-       case TEST_UNIT_READY:     /* mandatory */
-               /* delay_override = 1; */
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               break;
-       case RESERVE:
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               break;
-       case RESERVE_10:
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               break;
-       case RELEASE:
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               break;
-       case RELEASE_10:
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               break;
-       case READ_CAPACITY:
-               errsts = resp_readcap(SCpnt, devip);
-               break;
-       case SERVICE_ACTION_IN:
-               if (cmd[1] == SAI_READ_CAPACITY_16)
-                       errsts = resp_readcap16(SCpnt, devip);
-               else if (cmd[1] == SAI_GET_LBA_STATUS) {
-
-                       if (scsi_debug_lbp() == 0) {
-                               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                               INVALID_COMMAND_OPCODE, 0);
-                               errsts = check_condition_result;
-                       } else
-                               errsts = resp_get_lba_status(SCpnt, devip);
-               } else {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                       INVALID_OPCODE, 0);
-                       errsts = check_condition_result;
-               }
-               break;
-       case MAINTENANCE_IN:
-               if (MI_REPORT_TARGET_PGS != cmd[1]) {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                       INVALID_OPCODE, 0);
-                       errsts = check_condition_result;
-                       break;
-               }
-               errsts = resp_report_tgtpgs(SCpnt, devip);
-               break;
-       case READ_16:
-       case READ_12:
-       case READ_10:
-               /* READ{10,12,16} and DIF Type 2 are natural enemies */
-               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
-                   cmd[1] & 0xe0) {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                       INVALID_COMMAND_OPCODE, 0);
-                       errsts = check_condition_result;
-                       break;
-               }
-
-               if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
-                    scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
-                   (cmd[1] & 0xe0) == 0)
-                       printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
-
-               /* fall through */
-       case READ_6:
-read:
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               if (errsts)
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-               get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-
-               if (inj_short)
-                       num /= 2;
-
-               errsts = resp_read(SCpnt, lba, num, ei_lba);
-               if (inj_recovered && (0 == errsts)) {
-                       mk_sense_buffer(SCpnt, RECOVERED_ERROR,
-                                       THRESHOLD_EXCEEDED, 0);
-                       errsts = check_condition_result;
-               } else if (inj_transport && (0 == errsts)) {
-                       mk_sense_buffer(SCpnt, ABORTED_COMMAND,
-                                       TRANSPORT_PROBLEM, ACK_NAK_TO);
-                       errsts = check_condition_result;
-               } else if (inj_dif && (0 == errsts)) {
-                       /* Logical block guard check failed */
-                       mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
-                       errsts = illegal_condition_result;
-               } else if (inj_dix && (0 == errsts)) {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
-                       errsts = illegal_condition_result;
-               }
-               break;
-       case REPORT_LUNS:       /* mandatory, ignore unit attention */
-               delay_override = 1;
-               errsts = resp_report_luns(SCpnt, devip);
-               break;
-       case VERIFY:            /* 10 byte SBC-2 command */
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               break;
-       case WRITE_16:
-       case WRITE_12:
-       case WRITE_10:
-               /* WRITE{10,12,16} and DIF Type 2 are natural enemies */
-               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
-                   cmd[1] & 0xe0) {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                       INVALID_COMMAND_OPCODE, 0);
-                       errsts = check_condition_result;
-                       break;
-               }
-
-               if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
-                    scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
-                   (cmd[1] & 0xe0) == 0)
-                       printk(KERN_ERR "Unprotected RD/WR to DIF device\n");
-
-               /* fall through */
-       case WRITE_6:
-write:
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               if (errsts)
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-               get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-               errsts = resp_write(SCpnt, lba, num, ei_lba);
-               if (inj_recovered && (0 == errsts)) {
-                       mk_sense_buffer(SCpnt, RECOVERED_ERROR,
-                                       THRESHOLD_EXCEEDED, 0);
-                       errsts = check_condition_result;
-               } else if (inj_dif && (0 == errsts)) {
-                       mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1);
-                       errsts = illegal_condition_result;
-               } else if (inj_dix && (0 == errsts)) {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1);
-                       errsts = illegal_condition_result;
-               }
-               break;
-       case WRITE_SAME_16:
-       case WRITE_SAME:
-               if (cmd[1] & 0x8) {
-                       if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) ||
-                           (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) {
-                               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                               INVALID_FIELD_IN_CDB, 0);
-                               errsts = check_condition_result;
-                       } else
-                               unmap = 1;
-               }
-               if (errsts)
-                       break;
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               if (errsts)
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-               get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-               errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap);
-               break;
-       case UNMAP:
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               if (errsts)
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-
-               if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                       INVALID_COMMAND_OPCODE, 0);
-                       errsts = check_condition_result;
-               } else
-                       errsts = resp_unmap(SCpnt, devip);
-               break;
-       case MODE_SENSE:
-       case MODE_SENSE_10:
-               errsts = resp_mode_sense(SCpnt, target, devip);
-               break;
-       case MODE_SELECT:
-               errsts = resp_mode_select(SCpnt, 1, devip);
-               break;
-       case MODE_SELECT_10:
-               errsts = resp_mode_select(SCpnt, 0, devip);
-               break;
-       case LOG_SENSE:
-               errsts = resp_log_sense(SCpnt, devip);
-               break;
-       case SYNCHRONIZE_CACHE:
-               delay_override = 1;
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               break;
-       case WRITE_BUFFER:
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               break;
-       case XDWRITEREAD_10:
-               if (!scsi_bidi_cmnd(SCpnt)) {
-                       mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                                       INVALID_FIELD_IN_CDB, 0);
-                       errsts = check_condition_result;
-                       break;
-               }
-
-               errsts = check_readiness(SCpnt, UAS_TUR, devip);
-               if (errsts)
-                       break;
-               if (scsi_debug_fake_rw)
-                       break;
-               get_data_transfer_info(cmd, &lba, &num, &ei_lba);
-               errsts = resp_read(SCpnt, lba, num, ei_lba);
-               if (errsts)
-                       break;
-               errsts = resp_write(SCpnt, lba, num, ei_lba);
-               if (errsts)
-                       break;
-               errsts = resp_xdwriteread(SCpnt, lba, num, devip);
-               break;
-       case VARIABLE_LENGTH_CMD:
-               if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) {
-
-                       if ((cmd[10] & 0xe0) == 0)
-                               printk(KERN_ERR
-                                      "Unprotected RD/WR to DIF device\n");
-
-                       if (cmd[9] == READ_32) {
-                               BUG_ON(SCpnt->cmd_len < 32);
-                               goto read;
-                       }
-
-                       if (cmd[9] == WRITE_32) {
-                               BUG_ON(SCpnt->cmd_len < 32);
-                               goto write;
-                       }
-               }
-
-               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                               INVALID_FIELD_IN_CDB, 0);
-               errsts = check_condition_result;
-               break;
-       case 0x85:
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       sdev_printk(KERN_INFO, SCpnt->device,
-                       "%s: ATA PASS-THROUGH(16) not supported\n", my_name);
-               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST,
-                               INVALID_OPCODE, 0);
-               errsts = check_condition_result;
-               break;
-       default:
-               if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
-                       sdev_printk(KERN_INFO, SCpnt->device,
-                                   "%s: Opcode: 0x%x not supported\n",
-                                   my_name, *cmd);
-               errsts = check_readiness(SCpnt, UAS_ONLY, devip);
-               if (errsts)
-                       break;  /* Unit attention takes precedence */
-               mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
-               errsts = check_condition_result;
-               break;
-       }
-       return schedule_resp(SCpnt, devip, errsts,
-                            (delay_override ? 0 : scsi_debug_delay));
-}
-
-static int
-sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
-{
-       if (scsi_debug_host_lock) {
-               unsigned long iflags;
-               int rc;
-
-               spin_lock_irqsave(shost->host_lock, iflags);
-               rc = scsi_debug_queuecommand(cmd);
-               spin_unlock_irqrestore(shost->host_lock, iflags);
-               return rc;
-       } else
-               return scsi_debug_queuecommand(cmd);
-}
-
-static int
-sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason)
+sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
 {
        int num_in_q = 0;
-       int bad = 0;
        unsigned long iflags;
        struct sdebug_dev_info *devip;
 
@@ -4488,43 +4971,18 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason)
        }
        num_in_q = atomic_read(&devip->num_in_q);
        spin_unlock_irqrestore(&queued_arr_lock, iflags);
-       if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) {
-               if (qdepth < 1)
-                       qdepth = 1;
-               /* allow to exceed max host queued_arr elements for testing */
-               if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
-                       qdepth = SCSI_DEBUG_CANQUEUE + 10;
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-       } else if (reason == SCSI_QDEPTH_QFULL)
-               scsi_track_queue_full(sdev, qdepth);
-       else
-               bad = 1;
-       if (bad)
-               sdev_printk(KERN_WARNING, sdev,
-                           "%s: unknown reason=0x%x\n", __func__, reason);
+
+       if (qdepth < 1)
+               qdepth = 1;
+       /* allow to exceed max host queued_arr elements for testing */
+       if (qdepth > SCSI_DEBUG_CANQUEUE + 10)
+               qdepth = SCSI_DEBUG_CANQUEUE + 10;
+       scsi_change_queue_depth(sdev, qdepth);
+
        if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
-               if (SCSI_QDEPTH_QFULL == reason)
-                       sdev_printk(KERN_INFO, sdev,
-                           "%s: -> %d, num_in_q=%d, reason: queue full\n",
-                                   __func__, qdepth, num_in_q);
-               else {
-                       const char *cp;
-
-                       switch (reason) {
-                       case SCSI_QDEPTH_DEFAULT:
-                               cp = "default (sysfs ?)";
-                               break;
-                       case SCSI_QDEPTH_RAMP_UP:
-                               cp = "ramp up";
-                               break;
-                       default:
-                               cp = "unknown";
-                               break;
-                       }
-                       sdev_printk(KERN_INFO, sdev,
-                                   "%s: qdepth=%d, num_in_q=%d, reason: %s\n",
-                                   __func__, qdepth, num_in_q, cp);
-               }
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: qdepth=%d, num_in_q=%d\n",
+                           __func__, qdepth, num_in_q);
        }
        return sdev->queue_depth;
 }
@@ -4532,14 +4990,7 @@ sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason)
 static int
 sdebug_change_qtype(struct scsi_device *sdev, int qtype)
 {
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, qtype);
-               if (qtype)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               qtype = 0;
+       qtype = scsi_change_queue_type(sdev, qtype);
        if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) {
                const char *cp;
 
@@ -4562,6 +5013,193 @@ sdebug_change_qtype(struct scsi_device *sdev, int qtype)
        return qtype;
 }
 
+static int
+check_inject(struct scsi_cmnd *scp)
+{
+       struct sdebug_scmd_extra_t *ep = scsi_cmd_priv(scp);
+
+       memset(ep, 0, sizeof(struct sdebug_scmd_extra_t));
+
+       if (atomic_inc_return(&sdebug_cmnd_count) >=
+           abs(scsi_debug_every_nth)) {
+               atomic_set(&sdebug_cmnd_count, 0);
+               if (scsi_debug_every_nth < -1)
+                       scsi_debug_every_nth = -1;
+               if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
+                       return 1; /* ignore command causing timeout */
+               else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
+                        scsi_medium_access_command(scp))
+                       return 1; /* time out reads and writes */
+               if (sdebug_any_injecting_opt) {
+                       int opts = scsi_debug_opts;
+
+                       if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
+                               ep->inj_recovered = true;
+                       else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
+                               ep->inj_transport = true;
+                       else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
+                               ep->inj_dif = true;
+                       else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
+                               ep->inj_dix = true;
+                       else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
+                               ep->inj_short = true;
+               }
+       }
+       return 0;
+}
+
+static int
+scsi_debug_queuecommand(struct scsi_cmnd *scp)
+{
+       u8 sdeb_i;
+       struct scsi_device *sdp = scp->device;
+       const struct opcode_info_t *oip;
+       const struct opcode_info_t *r_oip;
+       struct sdebug_dev_info *devip;
+       u8 *cmd = scp->cmnd;
+       int (*r_pfp)(struct scsi_cmnd *, struct sdebug_dev_info *);
+       int k, na;
+       int errsts = 0;
+       int errsts_no_connect = DID_NO_CONNECT << 16;
+       u32 flags;
+       u16 sa;
+       u8 opcode = cmd[0];
+       bool has_wlun_rl;
+       bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts);
+
+       scsi_set_resid(scp, 0);
+       if (debug && !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts)) {
+               char b[120];
+               int n, len, sb;
+
+               len = scp->cmd_len;
+               sb = (int)sizeof(b);
+               if (len > 32)
+                       strcpy(b, "too long, over 32 bytes");
+               else {
+                       for (k = 0, n = 0; k < len && n < sb; ++k)
+                               n += scnprintf(b + n, sb - n, "%02x ",
+                                              (u32)cmd[k]);
+               }
+               sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b);
+       }
+       has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS);
+       if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl)
+               return schedule_resp(scp, NULL, errsts_no_connect, 0);
+
+       sdeb_i = opcode_ind_arr[opcode];        /* fully mapped */
+       oip = &opcode_info_arr[sdeb_i];         /* safe if table consistent */
+       devip = (struct sdebug_dev_info *)sdp->hostdata;
+       if (!devip) {
+               devip = devInfoReg(sdp);
+               if (NULL == devip)
+                       return schedule_resp(scp, NULL, errsts_no_connect, 0);
+       }
+       na = oip->num_attached;
+       r_pfp = oip->pfp;
+       if (na) {       /* multiple commands with this opcode */
+               r_oip = oip;
+               if (FF_SA & r_oip->flags) {
+                       if (F_SA_LOW & oip->flags)
+                               sa = 0x1f & cmd[1];
+                       else
+                               sa = get_unaligned_be16(cmd + 8);
+                       for (k = 0; k <= na; oip = r_oip->arrp + k++) {
+                               if (opcode == oip->opcode && sa == oip->sa)
+                                       break;
+                       }
+               } else {   /* since no service action only check opcode */
+                       for (k = 0; k <= na; oip = r_oip->arrp + k++) {
+                               if (opcode == oip->opcode)
+                                       break;
+                       }
+               }
+               if (k > na) {
+                       if (F_SA_LOW & r_oip->flags)
+                               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 4);
+                       else if (F_SA_HIGH & r_oip->flags)
+                               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, 7);
+                       else
+                               mk_sense_invalid_opcode(scp);
+                       goto check_cond;
+               }
+       }       /* else (when na==0) we assume the oip is a match */
+       flags = oip->flags;
+       if (F_INV_OP & flags) {
+               mk_sense_invalid_opcode(scp);
+               goto check_cond;
+       }
+       if (has_wlun_rl && !(F_RL_WLUN_OK & flags)) {
+               if (debug)
+                       sdev_printk(KERN_INFO, sdp, "scsi_debug: Opcode: "
+                                   "0x%x not supported for wlun\n", opcode);
+               mk_sense_invalid_opcode(scp);
+               goto check_cond;
+       }
+       if (scsi_debug_strict) {        /* check cdb against mask */
+               u8 rem;
+               int j;
+
+               for (k = 1; k < oip->len_mask[0] && k < 16; ++k) {
+                       rem = ~oip->len_mask[k] & cmd[k];
+                       if (rem) {
+                               for (j = 7; j >= 0; --j, rem <<= 1) {
+                                       if (0x80 & rem)
+                                               break;
+                               }
+                               mk_sense_invalid_fld(scp, SDEB_IN_CDB, k, j);
+                               goto check_cond;
+                       }
+               }
+       }
+       if (!(F_SKIP_UA & flags) &&
+           SDEBUG_NUM_UAS != find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS)) {
+               errsts = check_readiness(scp, UAS_ONLY, devip);
+               if (errsts)
+                       goto check_cond;
+       }
+       if ((F_M_ACCESS & flags) && devip->stopped) {
+               mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
+               if (debug)
+                       sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
+                                   "%s\n", my_name, "initializing command "
+                                   "required");
+               errsts = check_condition_result;
+               goto fini;
+       }
+       if (scsi_debug_fake_rw && (F_FAKE_RW & flags))
+               goto fini;
+       if (scsi_debug_every_nth) {
+               if (check_inject(scp))
+                       return 0;       /* ignore command: make trouble */
+       }
+       if (oip->pfp)   /* if this command has a resp_* function, call it */
+               errsts = oip->pfp(scp, devip);
+       else if (r_pfp) /* if leaf function ptr NULL, try the root's */
+               errsts = r_pfp(scp, devip);
+
+fini:
+       return schedule_resp(scp, devip, errsts,
+                            ((F_DELAY_OVERR & flags) ? 0 : scsi_debug_delay));
+check_cond:
+       return schedule_resp(scp, devip, check_condition_result, 0);
+}
+
+static int
+sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
+{
+       if (scsi_debug_host_lock) {
+               unsigned long iflags;
+               int rc;
+
+               spin_lock_irqsave(shost->host_lock, iflags);
+               rc = scsi_debug_queuecommand(cmd);
+               spin_unlock_irqrestore(shost->host_lock, iflags);
+               return rc;
+       } else
+               return scsi_debug_queuecommand(cmd);
+}
+
 static struct scsi_host_template sdebug_driver_template = {
        .show_info =            scsi_debug_show_info,
        .write_info =           scsi_debug_write_info,
@@ -4587,13 +5225,16 @@ static struct scsi_host_template sdebug_driver_template = {
        .max_sectors =          -1U,
        .use_clustering =       DISABLE_CLUSTERING,
        .module =               THIS_MODULE,
+       .track_queue_depth =    1,
+       .cmd_size =             sizeof(struct sdebug_scmd_extra_t),
 };
 
 static int sdebug_driver_probe(struct device * dev)
 {
-        int error = 0;
-        struct sdebug_host_info *sdbg_host;
-        struct Scsi_Host *hpnt;
+       int error = 0;
+       int opts;
+       struct sdebug_host_info *sdbg_host;
+       struct Scsi_Host *hpnt;
        int host_prot;
 
        sdbg_host = to_sdebug_host(dev);
@@ -4603,7 +5244,7 @@ static int sdebug_driver_probe(struct device * dev)
                sdebug_driver_template.use_clustering = ENABLE_CLUSTERING;
        hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host));
        if (NULL == hpnt) {
-               printk(KERN_ERR "%s: scsi_register failed\n", __func__);
+               pr_err("%s: scsi_host_alloc failed\n", __func__);
                error = -ENODEV;
                return error;
        }
@@ -4660,6 +5301,18 @@ static int sdebug_driver_probe(struct device * dev)
        else
                scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
 
+       opts = scsi_debug_opts;
+       if (SCSI_DEBUG_OPT_RECOVERED_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_DIF_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_DIX_ERR & opts)
+               sdebug_any_injecting_opt = true;
+       else if (SCSI_DEBUG_OPT_SHORT_TRANSFER & opts)
+               sdebug_any_injecting_opt = true;
+
         error = scsi_add_host(hpnt, &sdbg_host->dev);
         if (error) {
                 printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
index 49014a143c6a9ab56ec81a56d3c7180156341d95..c1d04d4d3c6c140457c19e50865b29bd3287d54f 100644 (file)
@@ -202,6 +202,7 @@ static struct {
        {"IOMEGA", "Io20S         *F", NULL, BLIST_KEY},
        {"INSITE", "Floptical   F*8I", NULL, BLIST_KEY},
        {"INSITE", "I325VM", NULL, BLIST_KEY},
+       {"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC},
        {"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
        {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
        {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
index 9a6f8468225f372bae07f36d4779f8c19f27c6e3..e42fff6e8c109d66891bf291c07f7cb14a875b30 100644 (file)
@@ -36,6 +36,7 @@
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
+#include <scsi/sg.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
@@ -157,8 +158,9 @@ scmd_eh_abort_handler(struct work_struct *work)
                } else {
                        SCSI_LOG_ERROR_RECOVERY(3,
                                scmd_printk(KERN_INFO, scmd,
-                                           "scmd %p abort failed, rtn %d\n",
-                                           scmd, rtn));
+                                           "scmd %p abort %s\n", scmd,
+                                           (rtn == FAST_IO_FAIL) ?
+                                           "not send" : "failed"));
                }
        }
 
@@ -355,7 +357,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
 
                if (cmd_cancel || cmd_failed) {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               sdev_printk(KERN_INFO, sdev,
+                               shost_printk(KERN_INFO, shost,
                                            "%s: cmds failed: %d, cancel: %d\n",
                                            __func__, cmd_failed,
                                            cmd_cancel));
@@ -459,14 +461,6 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
        if (! scsi_command_normalize_sense(scmd, &sshdr))
                return FAILED;  /* no valid sense data */
 
-       if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done)
-               /*
-                * nasty: for mid-layer issued TURs, we need to return the
-                * actual sense data without any recovery attempt.  For eh
-                * issued ones, we need to try to recover and interpret
-                */
-               return SUCCESS;
-
        scsi_report_sense(sdev, &sshdr);
 
        if (scsi_sense_is_deferred(&sshdr))
@@ -482,6 +476,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                /* handler does not care. Drop down to default handling */
        }
 
+       if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done)
+               /*
+                * nasty: for mid-layer issued TURs, we need to return the
+                * actual sense data without any recovery attempt.  For eh
+                * issued ones, we need to try to recover and interpret
+                */
+               return SUCCESS;
+
        /*
         * Previous logic looked for FILEMARK, EOM or ILI which are
         * mainly associated with tapes and returned SUCCESS.
@@ -608,7 +610,7 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
        struct scsi_host_template *sht = sdev->host->hostt;
        struct scsi_device *tmp_sdev;
 
-       if (!sht->change_queue_depth ||
+       if (!sht->track_queue_depth ||
            sdev->queue_depth >= sdev->max_queue_depth)
                return;
 
@@ -629,12 +631,8 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
                    tmp_sdev->id != sdev->id ||
                    tmp_sdev->queue_depth == sdev->max_queue_depth)
                        continue;
-               /*
-                * call back into LLD to increase queue_depth by one
-                * with ramp up reason code.
-                */
-               sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1,
-                                       SCSI_QDEPTH_RAMP_UP);
+
+               scsi_change_queue_depth(tmp_sdev, tmp_sdev->queue_depth + 1);
                sdev->last_queue_ramp_up = jiffies;
        }
 }
@@ -644,7 +642,7 @@ static void scsi_handle_queue_full(struct scsi_device *sdev)
        struct scsi_host_template *sht = sdev->host->hostt;
        struct scsi_device *tmp_sdev;
 
-       if (!sht->change_queue_depth)
+       if (!sht->track_queue_depth)
                return;
 
        shost_for_each_device(tmp_sdev, sdev->host) {
@@ -656,8 +654,7 @@ static void scsi_handle_queue_full(struct scsi_device *sdev)
                 * the device when we got the queue full so we start
                 * from the highest possible value and work our way down.
                 */
-               sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
-                                       SCSI_QDEPTH_QFULL);
+               scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1);
        }
 }
 
@@ -869,7 +866,24 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
        return rtn;
 }
 
-static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt, struct scsi_cmnd *scmd)
+/**
+ * scsi_try_to_abort_cmd - Ask host to abort a SCSI command
+ * @scmd:      SCSI cmd used to send a target reset
+ *
+ * Return value:
+ *     SUCCESS, FAILED, or FAST_IO_FAIL
+ *
+ * Notes:
+ *    SUCCESS does not necessarily indicate that the command
+ *    has been aborted; it only indicates that the LLDDs
+ *    has cleared all references to that command.
+ *    LLDDs should return FAILED only if an abort was required
+ *    but could not be executed. LLDDs should return FAST_IO_FAIL
+ *    if the device is temporarily unavailable (eg due to a
+ *    link down on FibreChannel)
+ */
+static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt,
+                                struct scsi_cmnd *scmd)
 {
        if (!hostt->eh_abort_handler)
                return FAILED;
@@ -1156,9 +1170,9 @@ int scsi_eh_get_sense(struct list_head *work_q,
                shost = scmd->device->host;
                if (scsi_host_eh_past_deadline(shost)) {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               shost_printk(KERN_INFO, shost,
-                                           "skip %s, past eh deadline\n",
-                                            __func__));
+                               scmd_printk(KERN_INFO, scmd,
+                                           "%s: skip request sense, past eh deadline\n",
+                                            current->comm));
                        break;
                }
                if (status_byte(scmd->result) != CHECK_CONDITION)
@@ -1180,7 +1194,7 @@ int scsi_eh_get_sense(struct list_head *work_q,
                SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd,
                        "sense requested for %p result %x\n",
                        scmd, scmd->result));
-               SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense("bh", scmd));
+               SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense(scmd));
 
                rtn = scsi_decide_disposition(scmd);
 
@@ -1265,9 +1279,9 @@ static int scsi_eh_test_devices(struct list_head *cmd_list,
                                /* Push items back onto work_q */
                                list_splice_init(cmd_list, work_q);
                                SCSI_LOG_ERROR_RECOVERY(3,
-                                       shost_printk(KERN_INFO, sdev->host,
-                                                    "skip %s, past eh deadline",
-                                                    __func__));
+                                       sdev_printk(KERN_INFO, sdev,
+                                                   "%s: skip test device, past eh deadline",
+                                                   current->comm));
                                break;
                        }
                }
@@ -1318,21 +1332,20 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
                if (scsi_host_eh_past_deadline(shost)) {
                        list_splice_init(&check_list, work_q);
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               shost_printk(KERN_INFO, shost,
-                                           "skip %s, past eh deadline\n",
-                                            __func__));
+                               scmd_printk(KERN_INFO, scmd,
+                                           "%s: skip aborting cmd, past eh deadline\n",
+                                           current->comm));
                        return list_empty(work_q);
                }
                SCSI_LOG_ERROR_RECOVERY(3,
-                       shost_printk(KERN_INFO, shost,
-                                    "%s: aborting cmd: 0x%p\n",
-                                    current->comm, scmd));
+                       scmd_printk(KERN_INFO, scmd,
+                                    "%s: aborting cmd\n", current->comm));
                rtn = scsi_try_to_abort_cmd(shost->hostt, scmd);
                if (rtn == FAILED) {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               shost_printk(KERN_INFO, shost,
-                                            "%s: aborting cmd failed: 0x%p\n",
-                                            current->comm, scmd));
+                               scmd_printk(KERN_INFO, scmd,
+                                           "%s: aborting cmd failed\n",
+                                            current->comm));
                        list_splice_init(&check_list, work_q);
                        return list_empty(work_q);
                }
@@ -1390,9 +1403,9 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
        shost_for_each_device(sdev, shost) {
                if (scsi_host_eh_past_deadline(shost)) {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               shost_printk(KERN_INFO, shost,
-                                           "skip %s, past eh deadline\n",
-                                            __func__));
+                               sdev_printk(KERN_INFO, sdev,
+                                           "%s: skip START_UNIT, past eh deadline\n",
+                                           current->comm));
                        break;
                }
                stu_scmd = NULL;
@@ -1407,9 +1420,9 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
                        continue;
 
                SCSI_LOG_ERROR_RECOVERY(3,
-                       shost_printk(KERN_INFO, shost,
-                                    "%s: Sending START_UNIT to sdev: 0x%p\n",
-                                    current->comm, sdev));
+                       sdev_printk(KERN_INFO, sdev,
+                                    "%s: Sending START_UNIT\n",
+                                   current->comm));
 
                if (!scsi_eh_try_stu(stu_scmd)) {
                        if (!scsi_device_online(sdev) ||
@@ -1423,9 +1436,9 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
                        }
                } else {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               shost_printk(KERN_INFO, shost,
-                                            "%s: START_UNIT failed to sdev:"
-                                            " 0x%p\n", current->comm, sdev));
+                               sdev_printk(KERN_INFO, sdev,
+                                           "%s: START_UNIT failed\n",
+                                           current->comm));
                }
        }
 
@@ -1456,9 +1469,9 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
        shost_for_each_device(sdev, shost) {
                if (scsi_host_eh_past_deadline(shost)) {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               shost_printk(KERN_INFO, shost,
-                                           "skip %s, past eh deadline\n",
-                                            __func__));
+                               sdev_printk(KERN_INFO, sdev,
+                                           "%s: skip BDR, past eh deadline\n",
+                                            current->comm));
                        break;
                }
                bdr_scmd = NULL;
@@ -1472,9 +1485,8 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
                        continue;
 
                SCSI_LOG_ERROR_RECOVERY(3,
-                       shost_printk(KERN_INFO, shost,
-                                    "%s: Sending BDR sdev: 0x%p\n",
-                                    current->comm, sdev));
+                       sdev_printk(KERN_INFO, sdev,
+                                    "%s: Sending BDR\n", current->comm));
                rtn = scsi_try_bus_device_reset(bdr_scmd);
                if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
                        if (!scsi_device_online(sdev) ||
@@ -1490,9 +1502,8 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
                        }
                } else {
                        SCSI_LOG_ERROR_RECOVERY(3,
-                               shost_printk(KERN_INFO, shost,
-                                            "%s: BDR failed sdev: 0x%p\n",
-                                            current->comm, sdev));
+                               sdev_printk(KERN_INFO, sdev,
+                                           "%s: BDR failed\n", current->comm));
                }
        }
 
@@ -1528,8 +1539,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
                        list_splice_init(&tmp_list, work_q);
                        SCSI_LOG_ERROR_RECOVERY(3,
                                shost_printk(KERN_INFO, shost,
-                                           "skip %s, past eh deadline\n",
-                                            __func__));
+                                           "%s: Skip target reset, past eh deadline\n",
+                                            current->comm));
                        return list_empty(work_q);
                }
 
@@ -1591,8 +1602,8 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
                        list_splice_init(&check_list, work_q);
                        SCSI_LOG_ERROR_RECOVERY(3,
                                shost_printk(KERN_INFO, shost,
-                                           "skip %s, past eh deadline\n",
-                                            __func__));
+                                           "%s: skip BRST, past eh deadline\n",
+                                            current->comm));
                        return list_empty(work_q);
                }
 
@@ -2001,8 +2012,10 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
         * is no point trying to lock the door of an off-line device.
         */
        shost_for_each_device(sdev, shost) {
-               if (scsi_device_online(sdev) && sdev->locked)
+               if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) {
                        scsi_eh_lock_door(sdev);
+                       sdev->was_reset = 0;
+               }
        }
 
        /*
@@ -2191,9 +2204,9 @@ int scsi_error_handler(void *data)
                 */
                if (!shost->eh_noresume && scsi_autopm_get_host(shost) != 0) {
                        SCSI_LOG_ERROR_RECOVERY(1,
-                               printk(KERN_ERR "Error handler scsi_eh_%d "
-                                               "unable to autoresume\n",
-                                               shost->host_no));
+                               shost_printk(KERN_ERR, shost,
+                                            "scsi_eh_%d: unable to autoresume\n",
+                                            shost->host_no));
                        continue;
                }
 
@@ -2294,42 +2307,34 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd)
 {
 }
 
-/*
- * Function:   scsi_reset_provider
- *
- * Purpose:    Send requested reset to a bus or device at any phase.
- *
- * Arguments:  device  - device to send reset to
- *             flag - reset type (see scsi.h)
- *
- * Returns:    SUCCESS/FAILURE.
- *
- * Notes:      This is used by the SCSI Generic driver to provide
- *             Bus/Device reset capability.
+/**
+ * scsi_ioctl_reset: explicitly reset a host/bus/target/device
+ * @dev:       scsi_device to operate on
+ * @arg:       reset type (see sg.h)
  */
 int
-scsi_reset_provider(struct scsi_device *dev, int flag)
+scsi_ioctl_reset(struct scsi_device *dev, int __user *arg)
 {
        struct scsi_cmnd *scmd;
        struct Scsi_Host *shost = dev->host;
        struct request req;
        unsigned long flags;
-       int rtn;
+       int error = 0, rtn, val;
 
-       if (scsi_autopm_get_host(shost) < 0)
-               return FAILED;
+       if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+               return -EACCES;
 
-       if (!get_device(&dev->sdev_gendev)) {
-               rtn = FAILED;
-               goto out_put_autopm_host;
-       }
+       error = get_user(val, arg);
+       if (error)
+               return error;
 
+       if (scsi_autopm_get_host(shost) < 0)
+               return -EIO;
+
+       error = -EIO;
        scmd = scsi_get_command(dev, GFP_KERNEL);
-       if (!scmd) {
-               rtn = FAILED;
-               put_device(&dev->sdev_gendev);
+       if (!scmd)
                goto out_put_autopm_host;
-       }
 
        blk_rq_init(NULL, &req);
        scmd->request = &req;
@@ -2347,29 +2352,37 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
        shost->tmf_in_progress = 1;
        spin_unlock_irqrestore(shost->host_lock, flags);
 
-       switch (flag) {
-       case SCSI_TRY_RESET_DEVICE:
+       switch (val & ~SG_SCSI_RESET_NO_ESCALATE) {
+       case SG_SCSI_RESET_NOTHING:
+               rtn = SUCCESS;
+               break;
+       case SG_SCSI_RESET_DEVICE:
                rtn = scsi_try_bus_device_reset(scmd);
-               if (rtn == SUCCESS)
+               if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
                        break;
                /* FALLTHROUGH */
-       case SCSI_TRY_RESET_TARGET:
+       case SG_SCSI_RESET_TARGET:
                rtn = scsi_try_target_reset(scmd);
-               if (rtn == SUCCESS)
+               if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
                        break;
                /* FALLTHROUGH */
-       case SCSI_TRY_RESET_BUS:
+       case SG_SCSI_RESET_BUS:
                rtn = scsi_try_bus_reset(scmd);
-               if (rtn == SUCCESS)
+               if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
                        break;
                /* FALLTHROUGH */
-       case SCSI_TRY_RESET_HOST:
+       case SG_SCSI_RESET_HOST:
                rtn = scsi_try_host_reset(scmd);
-               break;
+               if (rtn == SUCCESS)
+                       break;
        default:
+               /* FALLTHROUGH */
                rtn = FAILED;
+               break;
        }
 
+       error = (rtn == SUCCESS) ? 0 : -EIO;
+
        spin_lock_irqsave(shost->host_lock, flags);
        shost->tmf_in_progress = 0;
        spin_unlock_irqrestore(shost->host_lock, flags);
@@ -2383,15 +2396,15 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
                             "waking up host to restart after TMF\n"));
 
        wake_up(&shost->host_wait);
-
        scsi_run_host_queues(shost);
 
-       scsi_next_command(scmd);
+       scsi_put_command(scmd);
+
 out_put_autopm_host:
        scsi_autopm_put_host(shost);
-       return rtn;
+       return error;
 }
-EXPORT_SYMBOL(scsi_reset_provider);
+EXPORT_SYMBOL(scsi_ioctl_reset);
 
 /**
  * scsi_normalize_sense - normalize main elements from either fixed or
@@ -2410,20 +2423,20 @@ EXPORT_SYMBOL(scsi_reset_provider);
  *     responded to a SCSI command with the CHECK_CONDITION status.
  *
  * Return value:
- *     1 if valid sense data information found, else 0;
+ *     true if valid sense data information found, else false;
  */
-int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
-                         struct scsi_sense_hdr *sshdr)
+bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
+                         struct scsi_sense_hdr *sshdr)
 {
        if (!sense_buffer || !sb_len)
-               return 0;
+               return false;
 
        memset(sshdr, 0, sizeof(struct scsi_sense_hdr));
 
        sshdr->response_code = (sense_buffer[0] & 0x7f);
 
        if (!scsi_sense_valid(sshdr))
-               return 0;
+               return false;
 
        if (sshdr->response_code >= 0x72) {
                /*
@@ -2453,12 +2466,12 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
                }
        }
 
-       return 1;
+       return true;
 }
 EXPORT_SYMBOL(scsi_normalize_sense);
 
-int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
-                                struct scsi_sense_hdr *sshdr)
+bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd,
+                                 struct scsi_sense_hdr *sshdr)
 {
        return scsi_normalize_sense(cmd->sense_buffer,
                        SCSI_SENSE_BUFFERSIZE, sshdr);
index 1aaaf43c6803b80d3b9b09afccf547ce12cd1d7e..c4f7b56fa6f60d880fb5ce6b57e91a2c694bb30f 100644 (file)
@@ -126,7 +126,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
                        sdev_printk(KERN_INFO, sdev,
                                    "ioctl_internal_command return code = %x\n",
                                    result);
-                       scsi_print_sense_hdr("   ", &sshdr);
+                       scsi_print_sense_hdr(sdev, NULL, &sshdr);
                        break;
                }
        }
@@ -200,19 +200,6 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
 {
        char scsi_cmd[MAX_COMMAND_SIZE];
 
-       /* No idea how this happens.... */
-       if (!sdev)
-               return -ENXIO;
-
-       /*
-        * If we are in the middle of error recovery, don't let anyone
-        * else try and use this device.  Also, if error recovery fails, it
-        * may try and take the device offline, in which case all further
-        * access to the device is prohibited.
-        */
-       if (!scsi_block_when_processing_errors(sdev))
-               return -ENODEV;
-
        /* Check for deprecated ioctls ... all the ioctls which don't
         * follow the new unique numbering scheme are deprecated */
        switch (cmd) {
@@ -273,6 +260,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
                                     START_STOP_TIMEOUT, NORMAL_RETRIES);
         case SCSI_IOCTL_GET_PCI:
                 return scsi_ioctl_get_pci(sdev, arg);
+       case SG_SCSI_RESET:
+               return scsi_ioctl_reset(sdev, arg);
        default:
                if (sdev->host->hostt->ioctl)
                        return sdev->host->hostt->ioctl(sdev, cmd, arg);
@@ -281,55 +270,20 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
 }
 EXPORT_SYMBOL(scsi_ioctl);
 
-/**
- * scsi_nonblockable_ioctl() - Handle SG_SCSI_RESET
- * @sdev: scsi device receiving ioctl
- * @cmd: Must be SC_SCSI_RESET
- * @arg: pointer to int containing SG_SCSI_RESET_{DEVICE,BUS,HOST}
- * @ndelay: file mode O_NDELAY flag
+/*
+ * We can process a reset even when a device isn't fully operable.
  */
-int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
-                           void __user *arg, int ndelay)
+int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int cmd,
+               bool ndelay)
 {
-       int val, result;
-
-       /* The first set of iocts may be executed even if we're doing
-        * error processing, as long as the device was opened
-        * non-blocking */
-       if (ndelay) {
+       if (cmd == SG_SCSI_RESET && ndelay) {
                if (scsi_host_in_recovery(sdev->host))
+                       return -EAGAIN;
+       } else {
+               if (!scsi_block_when_processing_errors(sdev))
                        return -ENODEV;
-       } else if (!scsi_block_when_processing_errors(sdev))
-               return -ENODEV;
-
-       switch (cmd) {
-       case SG_SCSI_RESET:
-               result = get_user(val, (int __user *)arg);
-               if (result)
-                       return result;
-               if (val == SG_SCSI_RESET_NOTHING)
-                       return 0;
-               switch (val) {
-               case SG_SCSI_RESET_DEVICE:
-                       val = SCSI_TRY_RESET_DEVICE;
-                       break;
-               case SG_SCSI_RESET_TARGET:
-                       val = SCSI_TRY_RESET_TARGET;
-                       break;
-               case SG_SCSI_RESET_BUS:
-                       val = SCSI_TRY_RESET_BUS;
-                       break;
-               case SG_SCSI_RESET_HOST:
-                       val = SCSI_TRY_RESET_HOST;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-                       return -EACCES;
-               return (scsi_reset_provider(sdev, val) ==
-                       SUCCESS) ? 0 : -EIO;
        }
-       return -ENODEV;
+
+       return 0;
 }
-EXPORT_SYMBOL(scsi_nonblockable_ioctl);
+EXPORT_SYMBOL_GPL(scsi_ioctl_block_when_processing_errors);
index 9eff8a3751324e06edb80d03833d79e1e7f9444b..7e3d954c9cacc1bdad0881be35a6cb1a2b0d7254 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/hardirq.h>
 #include <linux/scatterlist.h>
 #include <linux/blk-mq.h>
+#include <linux/ratelimit.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -47,7 +48,7 @@ struct scsi_host_sg_pool {
        mempool_t       *pool;
 };
 
-#define SP(x) { x, "sgpool-" __stringify(x) }
+#define SP(x) { .size = x, "sgpool-" __stringify(x) }
 #if (SCSI_MAX_SG_SEGMENTS < 32)
 #error SCSI_MAX_SG_SEGMENTS is too small (must be 32 or greater)
 #endif
@@ -542,17 +543,6 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
        put_device(&sdev->sdev_gendev);
 }
 
-void scsi_next_command(struct scsi_cmnd *cmd)
-{
-       struct scsi_device *sdev = cmd->device;
-       struct request_queue *q = sdev->request_queue;
-
-       scsi_put_command(cmd);
-       scsi_run_queue(q);
-
-       put_device(&sdev->sdev_gendev);
-}
-
 void scsi_run_host_queues(struct Scsi_Host *shost)
 {
        struct scsi_device *sdev;
@@ -598,10 +588,10 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq)
        __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free);
 }
 
-static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
-                             gfp_t gfp_mask, bool mq)
+static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, bool mq)
 {
        struct scatterlist *first_chunk = NULL;
+       gfp_t gfp_mask = mq ? GFP_NOIO : GFP_ATOMIC;
        int ret;
 
        BUG_ON(!nents);
@@ -730,8 +720,6 @@ static bool scsi_end_request(struct request *req, int error,
                        kblockd_schedule_work(&sdev->requeue_work);
                else
                        blk_mq_start_stopped_hw_queues(q, true);
-
-               put_device(&sdev->sdev_gendev);
        } else {
                unsigned long flags;
 
@@ -743,9 +731,12 @@ static bool scsi_end_request(struct request *req, int error,
                spin_unlock_irqrestore(q->queue_lock, flags);
 
                scsi_release_buffers(cmd);
-               scsi_next_command(cmd);
+
+               scsi_put_command(cmd);
+               scsi_run_queue(q);
        }
 
+       put_device(&sdev->sdev_gendev);
        return false;
 }
 
@@ -831,8 +822,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        struct request *req = cmd->request;
        int error = 0;
        struct scsi_sense_hdr sshdr;
-       int sense_valid = 0;
-       int sense_deferred = 0;
+       bool sense_valid = false;
+       int sense_deferred = 0, level = 0;
        enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
              ACTION_DELAYED_RETRY} action;
        unsigned long wait_for = (cmd->allowed + 1) * req->timeout;
@@ -912,7 +903,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                if ((sshdr.asc == 0x0) && (sshdr.ascq == 0x1d))
                        ;
                else if (!(req->cmd_flags & REQ_QUIET))
-                       scsi_print_sense("", cmd);
+                       scsi_print_sense(cmd);
                result = 0;
                /* BLOCK_PC may have set error */
                error = 0;
@@ -1039,10 +1030,24 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        case ACTION_FAIL:
                /* Give up and fail the remainder of the request */
                if (!(req->cmd_flags & REQ_QUIET)) {
-                       scsi_print_result(cmd);
-                       if (driver_byte(result) & DRIVER_SENSE)
-                               scsi_print_sense("", cmd);
-                       scsi_print_command(cmd);
+                       static DEFINE_RATELIMIT_STATE(_rs,
+                                       DEFAULT_RATELIMIT_INTERVAL,
+                                       DEFAULT_RATELIMIT_BURST);
+
+                       if (unlikely(scsi_logging_level))
+                               level = SCSI_LOG_LEVEL(SCSI_LOG_MLCOMPLETE_SHIFT,
+                                                      SCSI_LOG_MLCOMPLETE_BITS);
+
+                       /*
+                        * if logging is enabled the failure will be printed
+                        * in scsi_log_completion(), so avoid duplicate messages
+                        */
+                       if (!level && __ratelimit(&_rs)) {
+                               scsi_print_result(cmd, NULL, FAILED);
+                               if (driver_byte(result) & DRIVER_SENSE)
+                                       scsi_print_sense(cmd);
+                               scsi_print_command(cmd);
+                       }
                }
                if (!scsi_end_request(req, error, blk_rq_err_bytes(req), 0))
                        return;
@@ -1072,8 +1077,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        }
 }
 
-static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
-                            gfp_t gfp_mask)
+static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb)
 {
        int count;
 
@@ -1081,7 +1085,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
         * If sg table allocation fails, requeue request later.
         */
        if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments,
-                                       gfp_mask, req->mq_ctx != NULL)))
+                                       req->mq_ctx != NULL)))
                return BLKPREP_DEFER;
 
        /* 
@@ -1106,7 +1110,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb,
  *             BLKPREP_DEFER if the failure is retryable
  *             BLKPREP_KILL if the failure is fatal
  */
-int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+int scsi_init_io(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
        struct request *rq = cmd->request;
@@ -1115,7 +1119,7 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 
        BUG_ON(!rq->nr_phys_segments);
 
-       error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask);
+       error = scsi_init_sgtable(rq, &cmd->sdb);
        if (error)
                goto err_exit;
 
@@ -1131,8 +1135,7 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
                        rq->next_rq->special = bidi_sdb;
                }
 
-               error = scsi_init_sgtable(rq->next_rq, rq->next_rq->special,
-                                         GFP_ATOMIC);
+               error = scsi_init_sgtable(rq->next_rq, rq->next_rq->special);
                if (error)
                        goto err_exit;
        }
@@ -1144,7 +1147,7 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
                BUG_ON(prot_sdb == NULL);
                ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio);
 
-               if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask, is_mq)) {
+               if (scsi_alloc_sgtable(prot_sdb, ivecs, is_mq)) {
                        error = BLKPREP_DEFER;
                        goto err_exit;
                }
@@ -1213,7 +1216,7 @@ static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
         * submit a request without an attached bio.
         */
        if (req->bio) {
-               int ret = scsi_init_io(cmd, GFP_ATOMIC);
+               int ret = scsi_init_io(cmd);
                if (unlikely(ret))
                        return ret;
        } else {
@@ -1637,6 +1640,87 @@ static void scsi_softirq_done(struct request *rq)
        }
 }
 
+/**
+ * scsi_dispatch_command - Dispatch a command to the low-level driver.
+ * @cmd: command block we are dispatching.
+ *
+ * Return: nonzero return request was rejected and device's queue needs to be
+ * plugged.
+ */
+static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
+{
+       struct Scsi_Host *host = cmd->device->host;
+       int rtn = 0;
+
+       atomic_inc(&cmd->device->iorequest_cnt);
+
+       /* check if the device is still usable */
+       if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
+               /* in SDEV_DEL we error all commands. DID_NO_CONNECT
+                * returns an immediate error upwards, and signals
+                * that the device is no longer present */
+               cmd->result = DID_NO_CONNECT << 16;
+               goto done;
+       }
+
+       /* Check to see if the scsi lld made this device blocked. */
+       if (unlikely(scsi_device_blocked(cmd->device))) {
+               /*
+                * in blocked state, the command is just put back on
+                * the device queue.  The suspend state has already
+                * blocked the queue so future requests should not
+                * occur until the device transitions out of the
+                * suspend state.
+                */
+               SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
+                       "queuecommand : device blocked\n"));
+               return SCSI_MLQUEUE_DEVICE_BUSY;
+       }
+
+       /* Store the LUN value in cmnd, if needed. */
+       if (cmd->device->lun_in_cdb)
+               cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) |
+                              (cmd->device->lun << 5 & 0xe0);
+
+       scsi_log_send(cmd);
+
+       /*
+        * Before we queue this command, check if the command
+        * length exceeds what the host adapter can handle.
+        */
+       if (cmd->cmd_len > cmd->device->host->max_cmd_len) {
+               SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
+                              "queuecommand : command too long. "
+                              "cdb_size=%d host->max_cmd_len=%d\n",
+                              cmd->cmd_len, cmd->device->host->max_cmd_len));
+               cmd->result = (DID_ABORT << 16);
+               goto done;
+       }
+
+       if (unlikely(host->shost_state == SHOST_DEL)) {
+               cmd->result = (DID_NO_CONNECT << 16);
+               goto done;
+
+       }
+
+       trace_scsi_dispatch_cmd_start(cmd);
+       rtn = host->hostt->queuecommand(host, cmd);
+       if (rtn) {
+               trace_scsi_dispatch_cmd_error(cmd, rtn);
+               if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
+                   rtn != SCSI_MLQUEUE_TARGET_BUSY)
+                       rtn = SCSI_MLQUEUE_HOST_BUSY;
+
+               SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
+                       "queuecommand : request rejected\n"));
+       }
+
+       return rtn;
+ done:
+       cmd->scsi_done(cmd);
+       return 0;
+}
+
 /**
  * scsi_done - Invoke completion on finished SCSI command.
  * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
@@ -1725,7 +1809,7 @@ static void scsi_request_fn(struct request_queue *q)
                 * we add the dev to the starved list so it eventually gets
                 * a run when a tag is freed.
                 */
-               if (blk_queue_tagged(q) && !blk_rq_tagged(req)) {
+               if (blk_queue_tagged(q) && !(req->cmd_flags & REQ_QUEUED)) {
                        spin_lock_irq(shost->host_lock);
                        if (list_empty(&sdev->starved_entry))
                                list_add_tail(&sdev->starved_entry,
@@ -1739,6 +1823,11 @@ static void scsi_request_fn(struct request_queue *q)
 
                if (!scsi_host_queue_ready(q, shost, sdev))
                        goto host_not_ready;
+       
+               if (sdev->simple_tags)
+                       cmd->flags |= SCMD_TAGGED;
+               else
+                       cmd->flags &= ~SCMD_TAGGED;
 
                /*
                 * Finally, initialize any error handling parameters, and set up
@@ -1893,6 +1982,11 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req,
                blk_mq_start_request(req);
        }
 
+       if (sdev->simple_tags)
+               cmd->flags |= SCMD_TAGGED;
+       else
+               cmd->flags &= ~SCMD_TAGGED;
+
        scsi_init_cmd_errh(cmd);
        cmd->scsi_done = scsi_mq_done;
 
@@ -2086,7 +2180,7 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
 
        memset(&shost->tag_set, 0, sizeof(shost->tag_set));
        shost->tag_set.ops = &scsi_mq_ops;
-       shost->tag_set.nr_hw_queues = 1;
+       shost->tag_set.nr_hw_queues = shost->nr_hw_queues ? : 1;
        shost->tag_set.queue_depth = shost->can_queue;
        shost->tag_set.cmd_size = cmd_size;
        shost->tag_set.numa_node = NUMA_NO_NODE;
index 1f65139e14f8d3e9dc470c696c1e3aedabf344a8..7fe64a847143132be478030b4fdffd7dde5418ac 100644 (file)
@@ -51,6 +51,7 @@ do {                                                          \
                } while (0);                                    \
 } while (0)
 #else
+#define SCSI_LOG_LEVEL(SHIFT, BITS) 0
 #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)
 #endif /* CONFIG_SCSI_LOGGING */
 
index 12b8e1bee7f099fd04ce6686a88e2db21477086d..2dc4a83fb84c4528881026ee7bd46ae06777db21 100644 (file)
@@ -29,7 +29,6 @@ extern int scsi_init_hosts(void);
 extern void scsi_exit_hosts(void);
 
 /* scsi.c */
-extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
 #ifdef CONFIG_SCSI_LOGGING
@@ -84,7 +83,6 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd);
 extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
 extern void scsi_device_unbusy(struct scsi_device *sdev);
 extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
-extern void scsi_next_command(struct scsi_cmnd *cmd);
 extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
 extern void scsi_run_host_queues(struct Scsi_Host *shost);
 extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev);
index ba3f1e8d0d57cc905b2ceca579c666af9fb78201..983aed10ff2f8d97c9d34254768ecd3ec819ab9b 100644 (file)
@@ -286,7 +286,13 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        }
        WARN_ON_ONCE(!blk_get_queue(sdev->request_queue));
        sdev->request_queue->queuedata = sdev;
-       scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+
+       if (!shost_use_blk_mq(sdev->host) &&
+           (shost->bqt || shost->hostt->use_blk_tags)) {
+               blk_queue_init_tags(sdev->request_queue,
+                                   sdev->host->cmd_per_lun, shost->bqt);
+       }
+       scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun);
 
        scsi_sysfs_device_initialize(sdev);
 
@@ -874,8 +880,10 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
                        (inq_result[3] & 0x0f) == 1 ? " CCS" : "");
 
        if ((sdev->scsi_level >= SCSI_2) && (inq_result[7] & 2) &&
-           !(*bflags & BLIST_NOTQ))
+           !(*bflags & BLIST_NOTQ)) {
                sdev->tagged_supported = 1;
+               sdev->simple_tags = 1;
+       }
 
        /*
         * Some devices (Texel CD ROM drives) have handshaking problems
@@ -1214,9 +1222,9 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget,
                sparse_lun = 0;
 
        /*
-        * If less than SCSI_1_CSS, and no special lun scaning, stop
+        * If less than SCSI_1_CCS, and no special lun scanning, stop
         * scanning; this matches 2.4 behaviour, but could just be a bug
-        * (to continue scanning a SCSI_1_CSS device).
+        * (to continue scanning a SCSI_1_CCS device).
         *
         * This test is broken.  We might not have any device on lun0 for
         * a sparselun device, and if that's the case then how would we
@@ -1585,16 +1593,15 @@ EXPORT_SYMBOL(scsi_add_device);
 
 void scsi_rescan_device(struct device *dev)
 {
-       struct scsi_driver *drv;
-       
        if (!dev->driver)
                return;
 
-       drv = to_scsi_driver(dev->driver);
-       if (try_module_get(drv->owner)) {
+       if (try_module_get(dev->driver->owner)) {
+               struct scsi_driver *drv = to_scsi_driver(dev->driver);
+
                if (drv->rescan)
                        drv->rescan(dev);
-               module_put(drv->owner);
+               module_put(dev->driver->owner);
        }
 }
 EXPORT_SYMBOL(scsi_rescan_device);
@@ -1727,7 +1734,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
 
        if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
            ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
-           ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
+           ((lun != SCAN_WILD_CARD) && (lun >= shost->max_lun)))
                return -EINVAL;
 
        mutex_lock(&shost->scan_mutex);
index f4cb7b3e9e2350d8b12f28d366cf90ab6c552262..1cb64a8e18c91475d7f0bda12246fe7862782c03 100644 (file)
@@ -727,9 +727,7 @@ show_queue_type_field(struct device *dev, struct device_attribute *attr,
        struct scsi_device *sdev = to_scsi_device(dev);
        const char *name = "none";
 
-       if (sdev->ordered_tags)
-               name = "ordered";
-       else if (sdev->simple_tags)
+       if (sdev->simple_tags)
                name = "simple";
 
        return snprintf(buf, 20, "%s\n", name);
@@ -747,9 +745,12 @@ store_queue_type_field(struct device *dev, struct device_attribute *attr,
        if (!sdev->tagged_supported || !sht->change_queue_type)
                return -EINVAL;
 
-       if (strncmp(buf, "ordered", 7) == 0)
-               tag_type = MSG_ORDERED_TAG;
-       else if (strncmp(buf, "simple", 6) == 0)
+       /*
+        * We're never issueing order tags these days, but allow the value
+        * for backwards compatibility.
+        */
+       if (strncmp(buf, "ordered", 7) == 0 ||
+           strncmp(buf, "simple", 6) == 0)
                tag_type = MSG_SIMPLE_TAG;
        else if (strncmp(buf, "none", 4) != 0)
                return -EINVAL;
@@ -876,11 +877,10 @@ sdev_store_queue_depth(struct device *dev, struct device_attribute *attr,
 
        depth = simple_strtoul(buf, NULL, 0);
 
-       if (depth < 1)
+       if (depth < 1 || depth > sht->can_queue)
                return -EINVAL;
 
-       retval = sht->change_queue_depth(sdev, depth,
-                                        SCSI_QDEPTH_DEFAULT);
+       retval = sht->change_queue_depth(sdev, depth);
        if (retval < 0)
                return retval;
 
index 503594e5f76d91fb96ca106bf5d42332e0335025..82af28b90294fe785d8b22fa87ab38d428ac0ab6 100644 (file)
@@ -278,7 +278,7 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
                return scsi_trace_rw16(p, cdb, len);
        case UNMAP:
                return scsi_trace_unmap(p, cdb, len);
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                return scsi_trace_service_action_in(p, cdb, len);
        case VARIABLE_LENGTH_CMD:
                return scsi_trace_varlen(p, cdb, len);
index cf08071a9b6e33867fae59d47a3bc7fbd573ca7f..fa2aece76cc22094d36d605bc9075def9db9783b 100644 (file)
@@ -32,6 +32,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_spi.h>
 
@@ -1207,6 +1208,28 @@ int spi_populate_ppr_msg(unsigned char *msg, int period, int offset,
 }
 EXPORT_SYMBOL_GPL(spi_populate_ppr_msg);
 
+/**
+ * spi_populate_tag_msg - place a tag message in a buffer
+ * @msg:       pointer to the area to place the tag
+ * @cmd:       pointer to the scsi command for the tag
+ *
+ * Notes:
+ *     designed to create the correct type of tag message for the 
+ *     particular request.  Returns the size of the tag message.
+ *     May return 0 if TCQ is disabled for this device.
+ **/
+int spi_populate_tag_msg(unsigned char *msg, struct scsi_cmnd *cmd)
+{
+        if (cmd->flags & SCMD_TAGGED) {
+               *msg++ = MSG_SIMPLE_TAG;
+               *msg++ = cmd->request->tag;
+               return 2;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(spi_populate_tag_msg);
+
 #ifdef CONFIG_SCSI_CONSTANTS
 static const char * const one_byte_msgs[] = {
 /* 0x00 */ "Task Complete", NULL /* Extended Message */, "Save Pointers",
index 92d24d6dcb395399da066c6604e830b0c775a482..910f4a7a39248a56ea7a123030551c90410fa30d 100644 (file)
@@ -163,8 +163,8 @@ int scsi_partsize(unsigned char *buf, unsigned long capacity,
                    end_head * end_sector + end_sector;
 
                /* This is the actual _sector_ number at the end */
-               logical_end = get_unaligned(&largest->start_sect)
-                   + get_unaligned(&largest->nr_sects);
+               logical_end = get_unaligned_le32(&largest->start_sect)
+                   + get_unaligned_le32(&largest->nr_sects);
 
                /* This is for >1023 cylinders */
                ext_cyl = (logical_end - (end_head * end_sector + end_sector))
index cfba74cd8e8b1754e8b1412c65a560a0451ff470..fedab3c21ddf18adcb291a99c49b7b4ac051aa85 100644 (file)
@@ -116,7 +116,7 @@ static int sd_eh_action(struct scsi_cmnd *, int);
 static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
 static void scsi_disk_release(struct device *cdev);
 static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
-static void sd_print_result(struct scsi_disk *, int);
+static void sd_print_result(const struct scsi_disk *, const char *, int);
 
 static DEFINE_SPINLOCK(sd_index_lock);
 static DEFINE_IDA(sd_index_ida);
@@ -510,9 +510,9 @@ static const struct dev_pm_ops sd_pm_ops = {
 };
 
 static struct scsi_driver sd_template = {
-       .owner                  = THIS_MODULE,
        .gendrv = {
                .name           = "sd",
+               .owner          = THIS_MODULE,
                .probe          = sd_probe,
                .remove         = sd_remove,
                .shutdown       = sd_shutdown,
@@ -656,7 +656,7 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
        unsigned int logical_block_size = sdkp->device->sector_size;
        unsigned int max_blocks = 0;
 
-       q->limits.discard_zeroes_data = sdkp->lbprz;
+       q->limits.discard_zeroes_data = 0;
        q->limits.discard_alignment = sdkp->unmap_alignment *
                logical_block_size;
        q->limits.discard_granularity =
@@ -680,11 +680,13 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
        case SD_LBP_WS16:
                max_blocks = min_not_zero(sdkp->max_ws_blocks,
                                          (u32)SD_MAX_WS16_BLOCKS);
+               q->limits.discard_zeroes_data = sdkp->lbprz;
                break;
 
        case SD_LBP_WS10:
                max_blocks = min_not_zero(sdkp->max_ws_blocks,
                                          (u32)SD_MAX_WS10_BLOCKS);
+               q->limits.discard_zeroes_data = sdkp->lbprz;
                break;
 
        case SD_LBP_ZERO:
@@ -784,7 +786,7 @@ static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd)
         * amount of blocks described by the request.
         */
        blk_add_request_payload(rq, page, len);
-       ret = scsi_init_io(cmd, GFP_ATOMIC);
+       ret = scsi_init_io(cmd);
        rq->__data_len = nr_bytes;
 
 out:
@@ -878,7 +880,7 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
         * knows how much to actually write.
         */
        rq->__data_len = sdp->sector_size;
-       ret = scsi_init_io(cmd, GFP_ATOMIC);
+       ret = scsi_init_io(cmd);
        rq->__data_len = nr_bytes;
        return ret;
 }
@@ -912,7 +914,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt)
        int ret;
        unsigned char protect;
 
-       ret = scsi_init_io(SCpnt, GFP_ATOMIC);
+       ret = scsi_init_io(SCpnt);
        if (ret != BLKPREP_OK)
                goto out;
        SCpnt = rq->special;
@@ -1334,9 +1336,9 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
         * may try and take the device offline, in which case all further
         * access to the device is prohibited.
         */
-       error = scsi_nonblockable_ioctl(sdp, cmd, p,
-                                       (mode & FMODE_NDELAY) != 0);
-       if (!scsi_block_when_processing_errors(sdp) || !error)
+       error = scsi_ioctl_block_when_processing_errors(sdp, cmd,
+                       (mode & FMODE_NDELAY) != 0);
+       if (error)
                goto out;
 
        /*
@@ -1492,7 +1494,7 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
        }
 
        if (res) {
-               sd_print_result(sdkp, res);
+               sd_print_result(sdkp, "Synchronize Cache(10) failed", res);
 
                if (driver_byte(res) & DRIVER_SENSE)
                        sd_print_sense_hdr(sdkp, &sshdr);
@@ -1541,31 +1543,19 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
                           unsigned int cmd, unsigned long arg)
 {
        struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
-       int ret;
-
-       ret = scsi_verify_blk_ioctl(bdev, cmd);
-       if (ret < 0)
-               return ret;
+       int error;
 
-       /*
-        * If we are in the middle of error recovery, don't let anyone
-        * else try and use this device.  Also, if error recovery fails, it
-        * may try and take the device offline, in which case all further
-        * access to the device is prohibited.
-        */
-       if (!scsi_block_when_processing_errors(sdev))
-               return -ENODEV;
+       error = scsi_ioctl_block_when_processing_errors(sdev, cmd,
+                       (mode & FMODE_NDELAY) != 0);
+       if (error)
+               return error;
               
-       if (sdev->host->hostt->compat_ioctl) {
-               ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
-
-               return ret;
-       }
-
        /* 
         * Let the static ioctl translation table take care of it.
         */
-       return -ENOIOCTLCMD; 
+       if (!sdev->host->hostt->compat_ioctl)
+               return -ENOIOCTLCMD; 
+       return sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
 }
 #endif
 
@@ -1713,17 +1703,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                if (sense_valid)
                        sense_deferred = scsi_sense_is_deferred(&sshdr);
        }
-#ifdef CONFIG_SCSI_LOGGING
-       SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt));
-       if (sense_valid) {
-               SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
-                                                  "sd_done: sb[respc,sk,asc,"
-                                                  "ascq]=%x,%x,%x,%x\n",
-                                                  sshdr.response_code,
-                                                  sshdr.sense_key, sshdr.asc,
-                                                  sshdr.ascq));
-       }
-#endif
        sdkp->medium_access_timed_out = 0;
 
        if (driver_byte(result) != DRIVER_SENSE &&
@@ -1743,7 +1722,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                 * unknown amount of data was transferred so treat it as an
                 * error.
                 */
-               scsi_print_sense("sd", SCpnt);
                SCpnt->result = 0;
                memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
                break;
@@ -1779,6 +1757,10 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                break;
        }
  out:
+       SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
+                                          "sd_done: completed %d of %d bytes\n",
+                                          good_bytes, scsi_bufflen(SCpnt)));
+
        if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt))
                sd_dif_complete(SCpnt, good_bytes);
 
@@ -1834,12 +1816,12 @@ sd_spinup_disk(struct scsi_disk *sdkp)
                        /* no sense, TUR either succeeded or failed
                         * with a status error */
                        if(!spintime && !scsi_status_is_good(the_result)) {
-                               sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n");
-                               sd_print_result(sdkp, the_result);
+                               sd_print_result(sdkp, "Test Unit Ready failed",
+                                               the_result);
                        }
                        break;
                }
-                                       
+
                /*
                 * The device does not want the automatic start to be issued.
                 */
@@ -1955,7 +1937,6 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
                        struct scsi_sense_hdr *sshdr, int sense_valid,
                        int the_result)
 {
-       sd_print_result(sdkp, the_result);
        if (driver_byte(the_result) & DRIVER_SENSE)
                sd_print_sense_hdr(sdkp, sshdr);
        else
@@ -2001,7 +1982,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
 
        do {
                memset(cmd, 0, 16);
-               cmd[0] = SERVICE_ACTION_IN;
+               cmd[0] = SERVICE_ACTION_IN_16;
                cmd[1] = SAI_READ_CAPACITY_16;
                cmd[13] = RC16_LEN;
                memset(buffer, 0, RC16_LEN);
@@ -2036,7 +2017,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
        } while (the_result && retries);
 
        if (the_result) {
-               sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n");
+               sd_print_result(sdkp, "Read Capacity(16) failed", the_result);
                read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result);
                return -EINVAL;
        }
@@ -2118,7 +2099,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
        } while (the_result && retries);
 
        if (the_result) {
-               sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n");
+               sd_print_result(sdkp, "Read Capacity(10) failed", the_result);
                read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result);
                return -EINVAL;
        }
@@ -2643,12 +2624,12 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
 
                } else {        /* LBP VPD page tells us what to use */
 
-                       if (sdkp->lbpu && sdkp->max_unmap_blocks)
-                               sd_config_discard(sdkp, SD_LBP_UNMAP);
-                       else if (sdkp->lbpws)
+                       if (sdkp->lbpws)
                                sd_config_discard(sdkp, SD_LBP_WS16);
                        else if (sdkp->lbpws10)
                                sd_config_discard(sdkp, SD_LBP_WS10);
+                       else if (sdkp->lbpu && sdkp->max_unmap_blocks)
+                               sd_config_discard(sdkp, SD_LBP_UNMAP);
                        else
                                sd_config_discard(sdkp, SD_LBP_DISABLE);
                }
@@ -3142,8 +3123,7 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
        res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr,
                               SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM);
        if (res) {
-               sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n");
-               sd_print_result(sdkp, res);
+               sd_print_result(sdkp, "Start/Stop Unit failed", res);
                if (driver_byte(res) & DRIVER_SENSE)
                        sd_print_sense_hdr(sdkp, &sshdr);
                if (scsi_sense_valid(&sshdr) &&
@@ -3337,15 +3317,27 @@ module_exit(exit_sd);
 static void sd_print_sense_hdr(struct scsi_disk *sdkp,
                               struct scsi_sense_hdr *sshdr)
 {
-       sd_printk(KERN_INFO, sdkp, " ");
-       scsi_show_sense_hdr(sshdr);
-       sd_printk(KERN_INFO, sdkp, " ");
-       scsi_show_extd_sense(sshdr->asc, sshdr->ascq);
+       scsi_show_sense_hdr(sdkp->device,
+                           sdkp->disk ? sdkp->disk->disk_name : NULL, sshdr);
+       scsi_show_extd_sense(sdkp->device,
+                            sdkp->disk ? sdkp->disk->disk_name : NULL,
+                            sshdr->asc, sshdr->ascq);
 }
 
-static void sd_print_result(struct scsi_disk *sdkp, int result)
+static void sd_print_result(const struct scsi_disk *sdkp, const char *msg,
+                           int result)
 {
-       sd_printk(KERN_INFO, sdkp, " ");
-       scsi_show_result(result);
+       const char *hb_string = scsi_hostbyte_string(result);
+       const char *db_string = scsi_driverbyte_string(result);
+
+       if (hb_string || db_string)
+               sd_printk(KERN_INFO, sdkp,
+                         "%s: Result: hostbyte=%s driverbyte=%s\n", msg,
+                         hb_string ? hb_string : "invalid",
+                         db_string ? db_string : "invalid");
+       else
+               sd_printk(KERN_INFO, sdkp,
+                         "%s: Result: hostbyte=0x%02x driverbyte=0x%02x\n",
+                         msg, host_byte(result), driver_byte(result));
 }
 
index 467377884b63ffbc55bdeb23e592b3aabfd8a20d..63ba5ca7f9a16b21735c1283c2a17df40a7ee06c 100644 (file)
@@ -103,9 +103,9 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
 
 #define sd_printk(prefix, sdsk, fmt, a...)                             \
         (sdsk)->disk ?                                                 \
-       sdev_printk(prefix, (sdsk)->device, "[%s] " fmt,                \
-                   (sdsk)->disk->disk_name, ##a) :                     \
-       sdev_printk(prefix, (sdsk)->device, fmt, ##a)
+             sdev_prefix_printk(prefix, (sdsk)->device,                \
+                                (sdsk)->disk->disk_name, fmt, ##a) :   \
+             sdev_printk(prefix, (sdsk)->device, fmt, ##a)
 
 #define sd_first_printk(prefix, sdsk, fmt, a...)                       \
        do {                                                            \
index 80bfece1a2de74bdcf908a5a381ab5291521741a..b7e79e7646ad2a82aa0e37c43671f3c2191beb4f 100644 (file)
@@ -693,9 +693,9 @@ static struct class_interface ses_interface = {
 };
 
 static struct scsi_driver ses_template = {
-       .owner                  = THIS_MODULE,
        .gendrv = {
                .name           = "ses",
+               .owner          = THIS_MODULE,
                .probe          = ses_probe,
                .remove         = ses_remove,
        },
index 60354449d9ed1cc16f7ca43fdef340c935d2b1c8..b14f64cb97245ce8d50f21d3e83683831e71aa95 100644 (file)
@@ -219,8 +219,8 @@ static void sg_device_destroy(struct kref *kref);
 #define SZ_SG_REQ_INFO sizeof(sg_req_info_t)
 
 #define sg_printk(prefix, sdp, fmt, a...) \
-       sdev_printk(prefix, (sdp)->device, "[%s] " fmt, \
-                   (sdp)->disk->disk_name, ##a)
+       sdev_prefix_printk(prefix, (sdp)->device,               \
+                          (sdp)->disk->disk_name, fmt, ##a)
 
 static int sg_allow_access(struct file *filp, unsigned char *cmd)
 {
@@ -1071,39 +1071,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
                if (atomic_read(&sdp->detaching))
                        return -ENODEV;
                return put_user(sdp->device->host->hostt->emulated, ip);
-       case SG_SCSI_RESET:
-               if (atomic_read(&sdp->detaching))
-                       return -ENODEV;
-               if (filp->f_flags & O_NONBLOCK) {
-                       if (scsi_host_in_recovery(sdp->device->host))
-                               return -EBUSY;
-               } else if (!scsi_block_when_processing_errors(sdp->device))
-                       return -EBUSY;
-               result = get_user(val, ip);
-               if (result)
-                       return result;
-               if (SG_SCSI_RESET_NOTHING == val)
-                       return 0;
-               switch (val) {
-               case SG_SCSI_RESET_DEVICE:
-                       val = SCSI_TRY_RESET_DEVICE;
-                       break;
-               case SG_SCSI_RESET_TARGET:
-                       val = SCSI_TRY_RESET_TARGET;
-                       break;
-               case SG_SCSI_RESET_BUS:
-                       val = SCSI_TRY_RESET_BUS;
-                       break;
-               case SG_SCSI_RESET_HOST:
-                       val = SCSI_TRY_RESET_HOST;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-                       return -EACCES;
-               return (scsi_reset_provider(sdp->device, val) ==
-                       SUCCESS) ? 0 : -EIO;
        case SCSI_IOCTL_SEND_COMMAND:
                if (atomic_read(&sdp->detaching))
                        return -ENODEV;
@@ -1123,13 +1090,6 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
                        return result;
                sdp->sgdebug = (char) val;
                return 0;
-       case SCSI_IOCTL_GET_IDLUN:
-       case SCSI_IOCTL_GET_BUS_NUMBER:
-       case SCSI_IOCTL_PROBE_HOST:
-       case SG_GET_TRANSFORM:
-               if (atomic_read(&sdp->detaching))
-                       return -ENODEV;
-               return scsi_ioctl(sdp->device, cmd_in, p);
        case BLKSECTGET:
                return put_user(max_sectors_bytes(sdp->device->request_queue),
                                ip);
@@ -1145,11 +1105,25 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
                return blk_trace_startstop(sdp->device->request_queue, 0);
        case BLKTRACETEARDOWN:
                return blk_trace_remove(sdp->device->request_queue);
+       case SCSI_IOCTL_GET_IDLUN:
+       case SCSI_IOCTL_GET_BUS_NUMBER:
+       case SCSI_IOCTL_PROBE_HOST:
+       case SG_GET_TRANSFORM:
+       case SG_SCSI_RESET:
+               if (atomic_read(&sdp->detaching))
+                       return -ENODEV;
+               break;
        default:
                if (read_only)
                        return -EPERM;  /* don't know so take safe approach */
-               return scsi_ioctl(sdp->device, cmd_in, p);
+               break;
        }
+
+       result = scsi_ioctl_block_when_processing_errors(sdp->device,
+                       cmd_in, filp->f_flags & O_NDELAY);
+       if (result)
+               return result;
+       return scsi_ioctl(sdp->device, cmd_in, p);
 }
 
 #ifdef CONFIG_COMPAT
@@ -1360,7 +1334,7 @@ sg_rq_end_io(struct request *rq, int uptodate)
                if ((sdp->sgdebug > 0) &&
                    ((CHECK_CONDITION == srp->header.masked_status) ||
                     (COMMAND_TERMINATED == srp->header.masked_status)))
-                       __scsi_print_sense(__func__, sense,
+                       __scsi_print_sense(sdp->device, __func__, sense,
                                           SCSI_SENSE_BUFFERSIZE);
 
                /* Following if statement is a patch supplied by Eric Youngdale */
index 2de44cc58b1acd5cf038fd1a40ace6f34810b276..8bd54a64efd6a52aef163f0cbe4f34f5ef9ac71c 100644 (file)
@@ -88,9 +88,9 @@ static struct dev_pm_ops sr_pm_ops = {
 };
 
 static struct scsi_driver sr_template = {
-       .owner                  = THIS_MODULE,
        .gendrv = {
                .name           = "sr",
+               .owner          = THIS_MODULE,
                .probe          = sr_probe,
                .remove         = sr_remove,
                .pm             = &sr_pm_ops,
@@ -387,7 +387,7 @@ static int sr_init_command(struct scsi_cmnd *SCpnt)
        struct request *rq = SCpnt->request;
        int ret;
 
-       ret = scsi_init_io(SCpnt, GFP_ATOMIC);
+       ret = scsi_init_io(SCpnt);
        if (ret != BLKPREP_OK)
                goto out;
        SCpnt = rq->special;
@@ -549,6 +549,11 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 
        mutex_lock(&sr_mutex);
 
+       ret = scsi_ioctl_block_when_processing_errors(sdev, cmd,
+                       (mode & FMODE_NDELAY) != 0);
+       if (ret)
+               goto out;
+
        /*
         * Send SCSI addressing ioctls directly to mid level, send other
         * ioctls to cdrom/block level.
@@ -564,16 +569,6 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
        if (ret != -ENOSYS)
                goto out;
 
-       /*
-        * ENODEV means that we didn't recognise the ioctl, or that we
-        * cannot execute it in the current device state.  In either
-        * case fall through to scsi_ioctl, which will return ENDOEV again
-        * if it doesn't recognise the ioctl
-        */
-       ret = scsi_nonblockable_ioctl(sdev, cmd, argp,
-                                       (mode & FMODE_NDELAY) != 0);
-       if (ret != -ENODEV)
-               goto out;
        ret = scsi_ioctl(sdev, cmd, argp);
 
 out:
index 1d1f6f416c593daeb888283be777e4a7a3528b7b..1de33719ad8ef32c7042e2e59fd3c310973f7896 100644 (file)
@@ -57,8 +57,7 @@ typedef struct scsi_cd {
 } Scsi_CD;
 
 #define sr_printk(prefix, cd, fmt, a...) \
-       sdev_printk(prefix, (cd)->device, "[%s] " fmt, \
-                   (cd)->cdi.name, ##a)
+       sdev_prefix_printk(prefix, (cd)->device, (cd)->cdi.name, fmt, ##a)
 
 int sr_do_ioctl(Scsi_CD *, struct packet_command *);
 
index 6389fcff12ecf6896a3da469748bcfb5edc4cbe3..fb929fac22ba4453b2abc6fdb0f6167598612630 100644 (file)
@@ -246,7 +246,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
                                          "CDROM not ready.  Make sure there "
                                          "is a disc in the drive.\n");
 #ifdef DEBUG
-                       scsi_print_sense_hdr("sr", &sshdr);
+                       scsi_print_sense_hdr(cd->device, cd->cdi.name, &sshdr);
 #endif
                        err = -ENOMEDIUM;
                        break;
@@ -257,15 +257,15 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
                                /* sense: Invalid command operation code */
                                err = -EDRIVE_CANT_DO_THIS;
 #ifdef DEBUG
-                       __scsi_print_command(cgc->cmd);
-                       scsi_print_sense_hdr("sr", &sshdr);
+                       __scsi_print_command(cgc->cmd, CDROM_PACKET_SIZE);
+                       scsi_print_sense_hdr(cd->device, cd->cdi.name, &sshdr);
 #endif
                        break;
                default:
                        sr_printk(KERN_ERR, cd,
                                  "CDROM (ioctl) error, command: ");
-                       __scsi_print_command(cgc->cmd);
-                       scsi_print_sense_hdr("sr", &sshdr);
+                       __scsi_print_command(cgc->cmd, CDROM_PACKET_SIZE);
+                       scsi_print_sense_hdr(cd->device, cd->cdi.name, &sshdr);
                        err = -EIO;
                }
        }
index 4daa372ed3811888f950a6c28cff4f68d08208a6..128d3b55bdd9fcc086606605bd787bc7e7ef2a6a 100644 (file)
@@ -56,7 +56,8 @@ static const char *verstr = "20101219";
 
 /* The driver prints some debugging information on the console if DEBUG
    is defined and non-zero. */
-#define DEBUG 0
+#define DEBUG 1
+#define NO_DEBUG 0
 
 #define ST_DEB_MSG  KERN_NOTICE
 #if DEBUG
@@ -80,6 +81,7 @@ static int max_sg_segs;
 static int try_direct_io = TRY_DIRECT_IO;
 static int try_rdio = 1;
 static int try_wdio = 1;
+static int debug_flag;
 
 static struct class st_sysfs_class;
 static const struct attribute_group *st_dev_groups[];
@@ -100,6 +102,9 @@ module_param_named(max_sg_segs, max_sg_segs, int, 0);
 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (256)");
 module_param_named(try_direct_io, try_direct_io, int, 0);
 MODULE_PARM_DESC(try_direct_io, "Try direct I/O between user buffer and tape drive (1)");
+module_param_named(debug_flag, debug_flag, int, 0);
+MODULE_PARM_DESC(debug_flag, "Enable DEBUG, same as setting debugging=1");
+
 
 /* Extra parameters for testing */
 module_param_named(try_rdio, try_rdio, int, 0);
@@ -124,6 +129,9 @@ static struct st_dev_parm {
        },
        {
                "try_direct_io", &try_direct_io
+       },
+       {
+               "debug_flag", &debug_flag
        }
 };
 #endif
@@ -194,9 +202,9 @@ static int do_create_sysfs_files(void);
 static void do_remove_sysfs_files(void);
 
 static struct scsi_driver st_template = {
-       .owner                  = THIS_MODULE,
        .gendrv = {
                .name           = "st",
+               .owner          = THIS_MODULE,
                .probe          = st_probe,
                .remove         = st_remove,
        },
@@ -306,8 +314,7 @@ static inline char *tape_name(struct scsi_tape *tape)
 }
 
 #define st_printk(prefix, t, fmt, a...) \
-       sdev_printk(prefix, (t)->device, "%s: " fmt, \
-                   tape_name(t), ##a)
+       sdev_prefix_printk(prefix, (t)->device, tape_name(t), fmt, ##a)
 #ifdef DEBUG
 #define DEBC_printk(t, fmt, a...) \
        if (debugging) { st_printk(ST_DEB_MSG, t, fmt, ##a ); }
@@ -374,7 +381,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
                            SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
                            SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
                if (cmdstatp->have_sense)
-                        __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
+                       __scsi_print_sense(STp->device, name,
+                                          SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
        } ) /* end DEB */
        if (!debugging) { /* Abnormal conditions for tape */
                if (!cmdstatp->have_sense)
@@ -390,7 +398,8 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
                         SRpnt->cmd[0] != MODE_SENSE &&
                         SRpnt->cmd[0] != TEST_UNIT_READY) {
 
-                       __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
+                       __scsi_print_sense(STp->device, name,
+                                          SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
                }
        }
 
@@ -852,17 +861,16 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
 /* Lock or unlock the drive door. Don't use when st_request allocated. */
 static int do_door_lock(struct scsi_tape * STp, int do_lock)
 {
-       int retval, cmd;
+       int retval;
 
-       cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
        DEBC_printk(STp, "%socking drive door.\n", do_lock ? "L" : "Unl");
-       retval = scsi_ioctl(STp->device, cmd, NULL);
-       if (!retval) {
+
+       retval = scsi_set_medium_removal(STp->device,
+                       do_lock ? SCSI_REMOVAL_PREVENT : SCSI_REMOVAL_ALLOW);
+       if (!retval)
                STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
-       }
-       else {
+       else
                STp->door_locked = ST_LOCK_FAILS;
-       }
        return retval;
 }
 
@@ -3367,11 +3375,10 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
         * may try and take the device offline, in which case all further
         * access to the device is prohibited.
         */
-       retval = scsi_nonblockable_ioctl(STp->device, cmd_in, p,
-                                       file->f_flags & O_NDELAY);
-       if (!scsi_block_when_processing_errors(STp->device) || retval != -ENODEV)
+       retval = scsi_ioctl_block_when_processing_errors(STp->device, cmd_in,
+                       file->f_flags & O_NDELAY);
+       if (retval)
                goto out;
-       retval = 0;
 
        cmd_type = _IOC_TYPE(cmd_in);
        cmd_nr = _IOC_NR(cmd_in);
@@ -4309,6 +4316,12 @@ static int __init init_st(void)
        printk(KERN_INFO "st: Version %s, fixed bufsize %d, s/g segs %d\n",
                verstr, st_fixed_buffer_size, st_max_sg_segs);
 
+       debugging = (debug_flag > 0) ? debug_flag : NO_DEBUG;
+       if (debugging) {
+               printk(KERN_INFO "st: Debugging enabled debug_flag = %d\n",
+                       debugging);
+       }
+
        err = class_register(&st_sysfs_class);
        if (err) {
                pr_err("Unable register sysfs class for SCSI tapes\n");
index 1aa4befcfbd0120b11df14a4b0f918b00f5be72d..98a62bc15069773ba2de93dd9d4164e8655919f0 100644 (file)
@@ -543,34 +543,16 @@ stex_ss_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
        readl(hba->mmio_base + YH2I_REQ); /* flush */
 }
 
-static int
-stex_slave_alloc(struct scsi_device *sdev)
-{
-       /* Cheat: usually extracted from Inquiry data */
-       sdev->tagged_supported = 1;
-
-       scsi_activate_tcq(sdev, sdev->host->can_queue);
-
-       return 0;
-}
-
 static int
 stex_slave_config(struct scsi_device *sdev)
 {
        sdev->use_10_for_rw = 1;
        sdev->use_10_for_ms = 1;
        blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
-       sdev->tagged_supported = 1;
 
        return 0;
 }
 
-static void
-stex_slave_destroy(struct scsi_device *sdev)
-{
-       scsi_deactivate_tcq(sdev, 1);
-}
-
 static int
 stex_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
@@ -1162,9 +1144,7 @@ static int stex_abort(struct scsi_cmnd *cmd)
        int result = SUCCESS;
        unsigned long flags;
 
-       printk(KERN_INFO DRV_NAME
-               "(%s): aborting command\n", pci_name(hba->pdev));
-       scsi_print_command(cmd);
+       scmd_printk(KERN_INFO, cmd, "aborting command\n");
 
        base = hba->mmio_base;
        spin_lock_irqsave(host->host_lock, flags);
@@ -1352,9 +1332,8 @@ static int stex_reset(struct scsi_cmnd *cmd)
 
        hba = (struct st_hba *) &cmd->device->host->hostdata[0];
 
-       printk(KERN_INFO DRV_NAME
-               "(%s): resetting host\n", pci_name(hba->pdev));
-       scsi_print_command(cmd);
+       shost_printk(KERN_INFO, cmd->device->host,
+                    "resetting host\n");
 
        return stex_do_reset(hba) ? FAILED : SUCCESS;
 }
@@ -1391,12 +1370,11 @@ static struct scsi_host_template driver_template = {
        .proc_name                      = DRV_NAME,
        .bios_param                     = stex_biosparam,
        .queuecommand                   = stex_queuecommand,
-       .slave_alloc                    = stex_slave_alloc,
        .slave_configure                = stex_slave_config,
-       .slave_destroy                  = stex_slave_destroy,
        .eh_abort_handler               = stex_abort,
        .eh_host_reset_handler          = stex_reset,
        .this_id                        = -1,
+       .use_blk_tags                   = 1,
 };
 
 static struct pci_device_id stex_pci_tbl[] = {
index 733e5f75951877f6884ce78c0295bf56540114b4..e3ba251fb6e75540f229af13a1af9f7f7d28dcbd 100644 (file)
@@ -1097,7 +1097,8 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
        if (scmnd->result) {
                if (scsi_normalize_sense(scmnd->sense_buffer,
                                SCSI_SENSE_BUFFERSIZE, &sense_hdr))
-                       scsi_print_sense_hdr("storvsc", &sense_hdr);
+                       scsi_print_sense_hdr(scmnd->device, "storvsc",
+                                            &sense_hdr);
        }
 
        if (vm_srb->srb_status != SRB_STATUS_SUCCESS)
@@ -1428,8 +1429,7 @@ static void storvsc_device_destroy(struct scsi_device *sdevice)
 
 static int storvsc_device_configure(struct scsi_device *sdevice)
 {
-       scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG,
-                               STORVSC_MAX_IO_REQUESTS);
+       scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS);
 
        blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
 
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
deleted file mode 100644 (file)
index 1a2367a..0000000
+++ /dev/null
@@ -1,2933 +0,0 @@
-/* sun3_NCR5380.c -- adapted from atari_NCR5380.c for the sun3 by 
-   Sam Creasey. */ 
-/* 
- * NCR 5380 generic driver routines.  These should make it *trivial*
- *     to implement 5380 SCSI drivers under Linux with a non-trantor
- *     architecture.
- *
- *     Note that these routines also work with NR53c400 family chips.
- *
- * Copyright 1993, Drew Eckhardt
- *     Visionary Computing 
- *     (Unix and Linux consulting and custom programming)
- *     drew@colorado.edu
- *     +1 (303) 666-5836
- *
- * DISTRIBUTION RELEASE 6. 
- *
- * For more information, please consult 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-/*
- * ++roman: To port the 5380 driver to the Atari, I had to do some changes in
- * this file, too:
- *
- *  - Some of the debug statements were incorrect (undefined variables and the
- *    like). I fixed that.
- *
- *  - In information_transfer(), I think a #ifdef was wrong. Looking at the
- *    possible DMA transfer size should also happen for REAL_DMA. I added this
- *    in the #if statement.
- *
- *  - When using real DMA, information_transfer() should return in a DATAOUT
- *    phase after starting the DMA. It has nothing more to do.
- *
- *  - The interrupt service routine should run main after end of DMA, too (not
- *    only after RESELECTION interrupts). Additionally, it should _not_ test
- *    for more interrupts after running main, since a DMA process may have
- *    been started and interrupts are turned on now. The new int could happen
- *    inside the execution of NCR5380_intr(), leading to recursive
- *    calls.
- *
- * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
- *    and USLEEP, because these were messing up readability and will never be
- *    needed for Atari SCSI.
- * 
- * - I've revised the NCR5380_main() calling scheme (relax the 'main_running'
- *   stuff), and 'main' is executed in a bottom half if awoken by an
- *   interrupt.
- *
- * - The code was quite cluttered up by "#if (NDEBUG & NDEBUG_*) printk..."
- *   constructs. In my eyes, this made the source rather unreadable, so I
- *   finally replaced that by the *_PRINTK() macros.
- *
- */
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_transport_spi.h>
-
-/*
- * Further development / testing that should be done : 
- * 1.  Test linked command handling code after Eric is ready with 
- *     the high level code.
- */
-
-#if (NDEBUG & NDEBUG_LISTS)
-#define LIST(x,y) \
-  { printk("LINE:%d   Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); \
-    if ((x)==(y)) udelay(5); }
-#define REMOVE(w,x,y,z) \
-  { printk("LINE:%d   Removing: %p->%p  %p->%p \n", __LINE__, \
-          (void*)(w), (void*)(x), (void*)(y), (void*)(z)); \
-    if ((x)==(y)) udelay(5); }
-#else
-#define LIST(x,y)
-#define REMOVE(w,x,y,z)
-#endif
-
-#ifndef notyet
-#undef LINKED
-#endif
-
-/*
- * Design
- * Issues :
- *
- * The other Linux SCSI drivers were written when Linux was Intel PC-only,
- * and specifically for each board rather than each chip.  This makes their
- * adaptation to platforms like the Mac (Some of which use NCR5380's)
- * more difficult than it has to be.
- *
- * Also, many of the SCSI drivers were written before the command queuing
- * routines were implemented, meaning their implementations of queued 
- * commands were hacked on rather than designed in from the start.
- *
- * When I designed the Linux SCSI drivers I figured that 
- * while having two different SCSI boards in a system might be useful
- * for debugging things, two of the same type wouldn't be used.
- * Well, I was wrong and a number of users have mailed me about running
- * multiple high-performance SCSI boards in a server.
- *
- * Finally, when I get questions from users, I have no idea what 
- * revision of my driver they are running.
- *
- * This driver attempts to address these problems :
- * This is a generic 5380 driver.  To use it on a different platform, 
- * one simply writes appropriate system specific macros (ie, data
- * transfer - some PC's will use the I/O bus, 68K's must use 
- * memory mapped) and drops this file in their 'C' wrapper.
- *
- * As far as command queueing, two queues are maintained for 
- * each 5380 in the system - commands that haven't been issued yet,
- * and commands that are currently executing.  This means that an 
- * unlimited number of commands may be queued, letting 
- * more commands propagate from the higher driver levels giving higher 
- * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported, 
- * allowing multiple commands to propagate all the way to a SCSI-II device 
- * while a command is already executing.
- *
- * To solve the multiple-boards-in-the-same-system problem, 
- * there is a separate instance structure for each instance
- * of a 5380 in the system.  So, multiple NCR5380 drivers will
- * be able to coexist with appropriate changes to the high level
- * SCSI code.  
- *
- * A NCR5380_PUBLIC_REVISION macro is provided, with the release
- * number (updated for each public release) printed by the 
- * NCR5380_print_options command, which should be called from the 
- * wrapper detect function, so that I know what release of the driver
- * users are using.
- *
- * Issues specific to the NCR5380 : 
- *
- * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead 
- * piece of hardware that requires you to sit in a loop polling for 
- * the REQ signal as long as you are connected.  Some devices are 
- * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect 
- * while doing long seek operations.
- * 
- * The workaround for this is to keep track of devices that have
- * disconnected.  If the device hasn't disconnected, for commands that
- * should disconnect, we do something like 
- *
- * while (!REQ is asserted) { sleep for N usecs; poll for M usecs }
- * 
- * Some tweaking of N and M needs to be done.  An algorithm based 
- * on "time to data" would give the best results as long as short time
- * to datas (ie, on the same track) were considered, however these 
- * broken devices are the exception rather than the rule and I'd rather
- * spend my time optimizing for the normal case.
- *
- * Architecture :
- *
- * At the heart of the design is a coroutine, NCR5380_main,
- * which is started when not running by the interrupt handler,
- * timer, and queue command function.  It attempts to establish
- * I_T_L or I_T_L_Q nexuses by removing the commands from the 
- * issue queue and calling NCR5380_select() if a nexus 
- * is not established. 
- *
- * Once a nexus is established, the NCR5380_information_transfer()
- * phase goes through the various phases as instructed by the target.
- * if the target goes into MSG IN and sends a DISCONNECT message,
- * the command structure is placed into the per instance disconnected
- * queue, and NCR5380_main tries to find more work.  If USLEEP
- * was defined, and the target is idle for too long, the system
- * will try to sleep.
- *
- * If a command has disconnected, eventually an interrupt will trigger,
- * calling NCR5380_intr()  which will in turn call NCR5380_reselect
- * to reestablish a nexus.  This will run main if necessary.
- *
- * On command termination, the done function will be called as 
- * appropriate.
- *
- * SCSI pointers are maintained in the SCp field of SCSI command 
- * structures, being initialized after the command is connected
- * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
- * Note that in violation of the standard, an implicit SAVE POINTERS operation
- * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS.
- */
-
-/*
- * Using this file :
- * This file a skeleton Linux SCSI driver for the NCR 5380 series
- * of chips.  To use it, you write an architecture specific functions 
- * and macros and include this file in your driver.
- *
- * These macros control options : 
- * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- *     for commands that return with a CHECK CONDITION status. 
- *
- * LINKED - if defined, linked commands are supported.
- *
- * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
- *
- * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible
- *
- * These macros MUST be defined :
- * 
- * NCR5380_read(register)  - read from the specified register
- *
- * NCR5380_write(register, value) - write to the specific register 
- *
- * Either real DMA *or* pseudo DMA may be implemented
- * REAL functions : 
- * NCR5380_REAL_DMA should be defined if real DMA is to be used.
- * Note that the DMA setup functions should return the number of bytes 
- *     that they were able to program the controller for.
- *
- * Also note that generic i386/PC versions of these macros are 
- *     available as NCR5380_i386_dma_write_setup,
- *     NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual.
- *
- * NCR5380_dma_write_setup(instance, src, count) - initialize
- * NCR5380_dma_read_setup(instance, dst, count) - initialize
- * NCR5380_dma_residual(instance); - residual count
- *
- * PSEUDO functions :
- * NCR5380_pwrite(instance, src, count)
- * NCR5380_pread(instance, dst, count);
- *
- * If nothing specific to this implementation needs doing (ie, with external
- * hardware), you must also define 
- *  
- * NCR5380_queue_command
- * NCR5380_reset
- * NCR5380_abort
- * NCR5380_proc_info
- *
- * to be the global entry points into the specific driver, ie 
- * #define NCR5380_queue_command t128_queue_command.
- *
- * If this is not done, the routines will be defined as static functions
- * with the NCR5380* names and the user must provide a globally
- * accessible wrapper function.
- *
- * The generic driver is initialized by calling NCR5380_init(instance),
- * after setting the appropriate host specific fields and ID.  If the 
- * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
- * possible) function may be used.  Before the specific driver initialization
- * code finishes, NCR5380_print_options should be called.
- */
-
-static struct Scsi_Host *first_instance = NULL;
-static struct scsi_host_template *the_template = NULL;
-
-/* Macros ease life... :-) */
-#define        SETUP_HOSTDATA(in)                              \
-    struct NCR5380_hostdata *hostdata =                        \
-       (struct NCR5380_hostdata *)(in)->hostdata
-#define        HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata)
-
-#define        NEXT(cmd)               ((struct scsi_cmnd *)(cmd)->host_scribble)
-#define        SET_NEXT(cmd, next)     ((cmd)->host_scribble = (void *)(next))
-#define        NEXTADDR(cmd)           ((struct scsi_cmnd **)&((cmd)->host_scribble))
-
-#define        HOSTNO          instance->host_no
-#define        H_NO(cmd)       (cmd)->device->host->host_no
-
-#define SGADDR(buffer) (void *)(((unsigned long)sg_virt(((buffer)))))
-
-#ifdef SUPPORT_TAGS
-
-/*
- * Functions for handling tagged queuing
- * =====================================
- *
- * ++roman (01/96): Now I've implemented SCSI-2 tagged queuing. Some notes:
- *
- * Using consecutive numbers for the tags is no good idea in my eyes. There
- * could be wrong re-usings if the counter (8 bit!) wraps and some early
- * command has been preempted for a long time. My solution: a bitfield for
- * remembering used tags.
- *
- * There's also the problem that each target has a certain queue size, but we
- * cannot know it in advance :-( We just see a QUEUE_FULL status being
- * returned. So, in this case, the driver internal queue size assumption is
- * reduced to the number of active tags if QUEUE_FULL is returned by the
- * target. The command is returned to the mid-level, but with status changed
- * to BUSY, since --as I've seen-- the mid-level can't handle QUEUE_FULL
- * correctly.
- *
- * We're also not allowed running tagged commands as long as an untagged
- * command is active. And REQUEST SENSE commands after a contingent allegiance
- * condition _must_ be untagged. To keep track whether an untagged command has
- * been issued, the host->busy array is still employed, as it is without
- * support for tagged queuing.
- *
- * One could suspect that there are possible race conditions between
- * is_lun_busy(), cmd_get_tag() and cmd_free_tag(). But I think this isn't the
- * case: is_lun_busy() and cmd_get_tag() are both called from NCR5380_main(),
- * which already guaranteed to be running at most once. It is also the only
- * place where tags/LUNs are allocated. So no other allocation can slip
- * between that pair, there could only happen a reselection, which can free a
- * tag, but that doesn't hurt. Only the sequence in cmd_free_tag() becomes
- * important: the tag bit must be cleared before 'nr_allocated' is decreased.
- */
-
-/* -1 for TAG_NONE is not possible with unsigned char cmd->tag */
-#undef TAG_NONE
-#define TAG_NONE 0xff
-
-/* For the m68k, the number of bits in 'allocated' must be a multiple of 32! */
-#if (MAX_TAGS % 32) != 0
-#error "MAX_TAGS must be a multiple of 32!"
-#endif
-
-typedef struct {
-    char       allocated[MAX_TAGS/8];
-    int                nr_allocated;
-    int                queue_size;
-} TAG_ALLOC;
-
-static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
-
-
-static void __init init_tags( void )
-{
-    int target, lun;
-    TAG_ALLOC *ta;
-    
-    if (!setup_use_tagged_queuing)
-       return;
-    
-    for( target = 0; target < 8; ++target ) {
-       for( lun = 0; lun < 8; ++lun ) {
-           ta = &TagAlloc[target][lun];
-           memset( &ta->allocated, 0, MAX_TAGS/8 );
-           ta->nr_allocated = 0;
-           /* At the beginning, assume the maximum queue size we could
-            * support (MAX_TAGS). This value will be decreased if the target
-            * returns QUEUE_FULL status.
-            */
-           ta->queue_size = MAX_TAGS;
-       }
-    }
-}
-
-
-/* Check if we can issue a command to this LUN: First see if the LUN is marked
- * busy by an untagged command. If the command should use tagged queuing, also
- * check that there is a free tag and the target's queue won't overflow. This
- * function should be called with interrupts disabled to avoid race
- * conditions.
- */ 
-
-static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged)
-{
-    u8 lun = cmd->device->lun;
-    SETUP_HOSTDATA(cmd->device->host);
-
-    if (hostdata->busy[cmd->device->id] & (1 << lun))
-       return( 1 );
-    if (!should_be_tagged ||
-       !setup_use_tagged_queuing || !cmd->device->tagged_supported)
-       return( 0 );
-    if (TagAlloc[cmd->device->id][lun].nr_allocated >=
-       TagAlloc[cmd->device->id][lun].queue_size ) {
-       dprintk(NDEBUG_TAGS,  "scsi%d: target %d lun %d: no free tags\n",
-                   H_NO(cmd), cmd->device->id, lun );
-       return( 1 );
-    }
-    return( 0 );
-}
-
-
-/* Allocate a tag for a command (there are no checks anymore, check_lun_busy()
- * must be called before!), or reserve the LUN in 'busy' if the command is
- * untagged.
- */
-
-static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged)
-{
-    u8 lun = cmd->device->lun;
-    SETUP_HOSTDATA(cmd->device->host);
-
-    /* If we or the target don't support tagged queuing, allocate the LUN for
-     * an untagged command.
-     */
-    if (!should_be_tagged ||
-       !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
-       cmd->tag = TAG_NONE;
-       hostdata->busy[cmd->device->id] |= (1 << lun);
-       dprintk(NDEBUG_TAGS,  "scsi%d: target %d lun %d now allocated by untagged "
-                   "command\n", H_NO(cmd), cmd->device->id, lun );
-    }
-    else {
-       TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
-
-       cmd->tag = find_first_zero_bit( &ta->allocated, MAX_TAGS );
-       set_bit( cmd->tag, &ta->allocated );
-       ta->nr_allocated++;
-       dprintk(NDEBUG_TAGS,  "scsi%d: using tag %d for target %d lun %d "
-                   "(now %d tags in use)\n",
-                   H_NO(cmd), cmd->tag, cmd->device->id, lun,
-                   ta->nr_allocated );
-    }
-}
-
-
-/* Mark the tag of command 'cmd' as free, or in case of an untagged command,
- * unlock the LUN.
- */
-
-static void cmd_free_tag(struct scsi_cmnd *cmd)
-{
-    u8 lun = cmd->device->lun;
-    SETUP_HOSTDATA(cmd->device->host);
-
-    if (cmd->tag == TAG_NONE) {
-       hostdata->busy[cmd->device->id] &= ~(1 << lun);
-       dprintk(NDEBUG_TAGS,  "scsi%d: target %d lun %d untagged cmd finished\n",
-                   H_NO(cmd), cmd->device->id, lun );
-    }
-    else if (cmd->tag >= MAX_TAGS) {
-       printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
-               H_NO(cmd), cmd->tag );
-    }
-    else {
-       TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun];
-       clear_bit( cmd->tag, &ta->allocated );
-       ta->nr_allocated--;
-       dprintk(NDEBUG_TAGS,  "scsi%d: freed tag %d for target %d lun %d\n",
-                   H_NO(cmd), cmd->tag, cmd->device->id, lun );
-    }
-}
-
-
-static void free_all_tags( void )
-{
-    int target, lun;
-    TAG_ALLOC *ta;
-
-    if (!setup_use_tagged_queuing)
-       return;
-    
-    for( target = 0; target < 8; ++target ) {
-       for( lun = 0; lun < 8; ++lun ) {
-           ta = &TagAlloc[target][lun];
-           memset( &ta->allocated, 0, MAX_TAGS/8 );
-           ta->nr_allocated = 0;
-       }
-    }
-}
-
-#endif /* SUPPORT_TAGS */
-
-
-/*
- * Function : void initialize_SCp(struct scsi_cmnd *cmd)
- *
- * Purpose : initialize the saved data pointers for cmd to point to the 
- *     start of the buffer.
- *
- * Inputs : cmd - struct scsi_cmnd structure to have pointers reset.
- */
-
-static __inline__ void initialize_SCp(struct scsi_cmnd *cmd)
-{
-    /* 
-     * Initialize the Scsi Pointer field so that all of the commands in the 
-     * various queues are valid.
-     */
-
-    if (scsi_bufflen(cmd)) {
-       cmd->SCp.buffer = scsi_sglist(cmd);
-       cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
-       cmd->SCp.ptr = (char *) SGADDR(cmd->SCp.buffer);
-       cmd->SCp.this_residual = cmd->SCp.buffer->length;
-    } else {
-       cmd->SCp.buffer = NULL;
-       cmd->SCp.buffers_residual = 0;
-       cmd->SCp.ptr = NULL;
-       cmd->SCp.this_residual = 0;
-    }
-    
-}
-
-#include <linux/delay.h>
-
-#if NDEBUG
-static struct {
-    unsigned char mask;
-    const char * name;} 
-signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, 
-    { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD,  "CD" }, { SR_IO, "IO" }, 
-    { SR_SEL, "SEL" }, {0, NULL}}, 
-basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}},
-icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"},
-    {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, 
-    {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, 
-    {0, NULL}},
-mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, 
-    {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, 
-    "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"},
-    {MR_MONITOR_BSY, "MODE MONITOR BSY"},
-    {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, 
-    {0, NULL}};
-
-/*
- * Function : void NCR5380_print(struct Scsi_Host *instance)
- *
- * Purpose : print the SCSI bus signals for debugging purposes
- *
- * Input : instance - which NCR5380
- */
-
-static void NCR5380_print(struct Scsi_Host *instance) {
-    unsigned char status, data, basr, mr, icr, i;
-    unsigned long flags;
-
-    local_irq_save(flags);
-    data = NCR5380_read(CURRENT_SCSI_DATA_REG);
-    status = NCR5380_read(STATUS_REG);
-    mr = NCR5380_read(MODE_REG);
-    icr = NCR5380_read(INITIATOR_COMMAND_REG);
-    basr = NCR5380_read(BUS_AND_STATUS_REG);
-    local_irq_restore(flags);
-    printk("STATUS_REG: %02x ", status);
-    for (i = 0; signals[i].mask ; ++i) 
-       if (status & signals[i].mask)
-           printk(",%s", signals[i].name);
-    printk("\nBASR: %02x ", basr);
-    for (i = 0; basrs[i].mask ; ++i) 
-       if (basr & basrs[i].mask)
-           printk(",%s", basrs[i].name);
-    printk("\nICR: %02x ", icr);
-    for (i = 0; icrs[i].mask; ++i) 
-       if (icr & icrs[i].mask)
-           printk(",%s", icrs[i].name);
-    printk("\nMODE: %02x ", mr);
-    for (i = 0; mrs[i].mask; ++i) 
-       if (mr & mrs[i].mask)
-           printk(",%s", mrs[i].name);
-    printk("\n");
-}
-
-static struct {
-    unsigned char value;
-    const char *name;
-} phases[] = {
-    {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"},
-    {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"},
-    {PHASE_UNKNOWN, "UNKNOWN"}};
-
-/* 
- * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
- *
- * Purpose : print the current SCSI phase for debugging purposes
- *
- * Input : instance - which NCR5380
- */
-
-static void NCR5380_print_phase(struct Scsi_Host *instance)
-{
-    unsigned char status;
-    int i;
-
-    status = NCR5380_read(STATUS_REG);
-    if (!(status & SR_REQ)) 
-       printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
-    else {
-       for (i = 0; (phases[i].value != PHASE_UNKNOWN) && 
-           (phases[i].value != (status & PHASE_MASK)); ++i); 
-       printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
-    }
-}
-
-#endif
-
-/*
- * ++roman: New scheme of calling NCR5380_main()
- * 
- * If we're not in an interrupt, we can call our main directly, it cannot be
- * already running. Else, we queue it on a task queue, if not 'main_running'
- * tells us that a lower level is already executing it. This way,
- * 'main_running' needs not be protected in a special way.
- *
- * queue_main() is a utility function for putting our main onto the task
- * queue, if main_running is false. It should be called only from a
- * interrupt or bottom half.
- */
-
-#include <linux/gfp.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-
-static volatile int main_running = 0;
-static DECLARE_WORK(NCR5380_tqueue, NCR5380_main);
-
-static __inline__ void queue_main(void)
-{
-    if (!main_running) {
-       /* If in interrupt and NCR5380_main() not already running,
-          queue it on the 'immediate' task queue, to be processed
-          immediately after the current interrupt processing has
-          finished. */
-       schedule_work(&NCR5380_tqueue);
-    }
-    /* else: nothing to do: the running NCR5380_main() will pick up
-       any newly queued command. */
-}
-
-
-static inline void NCR5380_all_init (void)
-{
-    static int done = 0;
-    if (!done) {
-       dprintk(NDEBUG_INIT, "scsi : NCR5380_all_init()\n");
-       done = 1;
-    }
-}
-
-/*
- * Function : void NCR58380_print_options (struct Scsi_Host *instance)
- *
- * Purpose : called by probe code indicating the NCR5380 driver
- *          options that were selected.
- *
- * Inputs : instance, pointer to this instance.  Unused.
- */
-
-static void __init NCR5380_print_options (struct Scsi_Host *instance)
-{
-    printk(" generic options"
-#ifdef AUTOSENSE 
-    " AUTOSENSE"
-#endif
-#ifdef REAL_DMA
-    " REAL DMA"
-#endif
-#ifdef PARITY
-    " PARITY"
-#endif
-#ifdef SUPPORT_TAGS
-    " SCSI-2 TAGGED QUEUING"
-#endif
-    );
-    printk(" generic release=%d", NCR5380_PUBLIC_RELEASE);
-}
-
-/*
- * Function : void NCR5380_print_status (struct Scsi_Host *instance)
- *
- * Purpose : print commands in the various queues, called from
- *     NCR5380_abort and NCR5380_debug to aid debugging.
- *
- * Inputs : instance, pointer to this instance.  
- */
-
-static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd)
-{
-       int i, s;
-       unsigned char *command;
-       printk("scsi%d: destination target %d, lun %llu\n",
-               H_NO(cmd), cmd->device->id, cmd->device->lun);
-       printk(KERN_CONT "        command = ");
-       command = cmd->cmnd;
-       printk(KERN_CONT "%2d (0x%02x)", command[0], command[0]);
-       for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-               printk(KERN_CONT " %02x", command[i]);
-       printk("\n");
-}
-
-static void NCR5380_print_status(struct Scsi_Host *instance)
-{
-       struct NCR5380_hostdata *hostdata;
-       Scsi_Cmnd *ptr;
-       unsigned long flags;
-
-       NCR5380_dprint(NDEBUG_ANY, instance);
-       NCR5380_dprint_phase(NDEBUG_ANY, instance);
-
-       hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-
-       printk("\nNCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
-       local_irq_save(flags);
-       printk("NCR5380: coroutine is%s running.\n",
-               main_running ? "" : "n't");
-       if (!hostdata->connected)
-               printk("scsi%d: no currently connected command\n", HOSTNO);
-       else
-               lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected);
-       printk("scsi%d: issue_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
-               lprint_Scsi_Cmnd(ptr);
-
-       printk("scsi%d: disconnected_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-            ptr = NEXT(ptr))
-               lprint_Scsi_Cmnd(ptr);
-
-       local_irq_restore(flags);
-       printk("\n");
-}
-
-static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m)
-{
-       int i, s;
-       unsigned char *command;
-       seq_printf(m, "scsi%d: destination target %d, lun %llu\n",
-               H_NO(cmd), cmd->device->id, cmd->device->lun);
-       seq_printf(m, "        command = ");
-       command = cmd->cmnd;
-       seq_printf(m, "%2d (0x%02x)", command[0], command[0]);
-       for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-               seq_printf(m, " %02x", command[i]);
-       seq_printf(m, "\n");
-}
-
-static int NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance)
-{
-       struct NCR5380_hostdata *hostdata;
-       Scsi_Cmnd *ptr;
-       unsigned long flags;
-
-       hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-
-       seq_printf(m, "NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
-       local_irq_save(flags);
-       seq_printf(m, "NCR5380: coroutine is%s running.\n",
-               main_running ? "" : "n't");
-       if (!hostdata->connected)
-               seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO);
-       else
-               show_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, m);
-       seq_printf(m, "scsi%d: issue_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr))
-               show_Scsi_Cmnd(ptr, m);
-
-       seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO);
-       for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-            ptr = NEXT(ptr))
-               show_Scsi_Cmnd(ptr, m);
-
-       local_irq_restore(flags);
-       return 0;
-}
-
-/* 
- * Function : void NCR5380_init (struct Scsi_Host *instance)
- *
- * Purpose : initializes *instance and corresponding 5380 chip.
- *
- * Inputs : instance - instantiation of the 5380 driver.  
- *
- * Notes : I assume that the host, hostno, and id bits have been
- *     set correctly.  I don't care about the irq and other fields. 
- * 
- */
-
-static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
-{
-    int i;
-    SETUP_HOSTDATA(instance);
-
-    NCR5380_all_init();
-
-    hostdata->aborted = 0;
-    hostdata->id_mask = 1 << instance->this_id;
-    hostdata->id_higher_mask = 0;
-    for (i = hostdata->id_mask; i <= 0x80; i <<= 1)
-       if (i > hostdata->id_mask)
-           hostdata->id_higher_mask |= i;
-    for (i = 0; i < 8; ++i)
-       hostdata->busy[i] = 0;
-#ifdef SUPPORT_TAGS
-    init_tags();
-#endif
-#if defined (REAL_DMA)
-    hostdata->dma_len = 0;
-#endif
-    hostdata->targets_present = 0;
-    hostdata->connected = NULL;
-    hostdata->issue_queue = NULL;
-    hostdata->disconnected_queue = NULL;
-    hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;
-
-    if (!the_template) {
-       the_template = instance->hostt;
-       first_instance = instance;
-    }
-       
-
-#ifndef AUTOSENSE
-    if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))
-        printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"
-               "        without AUTOSENSE option, contingent allegiance conditions may\n"
-               "        be incorrectly cleared.\n", HOSTNO);
-#endif /* def AUTOSENSE */
-
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-    NCR5380_write(MODE_REG, MR_BASE);
-    NCR5380_write(TARGET_COMMAND_REG, 0);
-    NCR5380_write(SELECT_ENABLE_REG, 0);
-
-    return 0;
-}
-
-static void NCR5380_exit(struct Scsi_Host *instance)
-{
-       /* Empty, as we didn't schedule any delayed work */
-}
-
-/* 
- * Function : int NCR5380_queue_command (struct scsi_cmnd *cmd,
- *     void (*done)(struct scsi_cmnd *))
- *
- * Purpose :  enqueues a SCSI command
- *
- * Inputs : cmd - SCSI command, done - function called on completion, with
- *     a pointer to the command descriptor.
- * 
- * Returns : 0
- *
- * Side effects : 
- *      cmd is added to the per instance issue_queue, with minor 
- *     twiddling done to the host specific fields of cmd.  If the 
- *     main coroutine is not running, it is restarted.
- *
- */
-
-/* Only make static if a wrapper function is used */
-static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd,
-                                void (*done)(struct scsi_cmnd *))
-{
-    SETUP_HOSTDATA(cmd->device->host);
-    struct scsi_cmnd *tmp;
-    unsigned long flags;
-
-#if (NDEBUG & NDEBUG_NO_WRITE)
-    switch (cmd->cmnd[0]) {
-    case WRITE_6:
-    case WRITE_10:
-       printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
-              H_NO(cmd));
-       cmd->result = (DID_ERROR << 16);
-       done(cmd);
-       return 0;
-    }
-#endif /* (NDEBUG & NDEBUG_NO_WRITE) */
-
-
-#ifdef NCR5380_STATS
-# if 0
-    if (!hostdata->connected && !hostdata->issue_queue &&
-       !hostdata->disconnected_queue) {
-       hostdata->timebase = jiffies;
-    }
-# endif
-# ifdef NCR5380_STAT_LIMIT
-    if (scsi_bufflen(cmd) > NCR5380_STAT_LIMIT)
-# endif
-       switch (cmd->cmnd[0])
-       {
-           case WRITE:
-           case WRITE_6:
-           case WRITE_10:
-               hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase);
-               hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);
-               hostdata->pendingw++;
-               break;
-           case READ:
-           case READ_6:
-           case READ_10:
-               hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase);
-               hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);
-               hostdata->pendingr++;
-               break;
-       }
-#endif
-
-    /* 
-     * We use the host_scribble field as a pointer to the next command  
-     * in a queue 
-     */
-
-    SET_NEXT(cmd, NULL);
-    cmd->scsi_done = done;
-
-    cmd->result = 0;
-
-
-    /* 
-     * Insert the cmd into the issue queue. Note that REQUEST SENSE 
-     * commands are added to the head of the queue since any command will
-     * clear the contingent allegiance condition that exists and the 
-     * sense data is only guaranteed to be valid while the condition exists.
-     */
-
-    local_irq_save(flags);
-    /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
-     * Otherwise a running NCR5380_main may steal the lock.
-     * Lock before actually inserting due to fairness reasons explained in
-     * atari_scsi.c. If we insert first, then it's impossible for this driver
-     * to release the lock.
-     * Stop timer for this command while waiting for the lock, or timeouts
-     * may happen (and they really do), and it's no good if the command doesn't
-     * appear in any of the queues.
-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
-     * because also a timer int can trigger an abort or reset, which would
-     * alter queues and touch the lock.
-     */
-    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
-       LIST(cmd, hostdata->issue_queue);
-       SET_NEXT(cmd, hostdata->issue_queue);
-       hostdata->issue_queue = cmd;
-    } else {
-       for (tmp = (struct scsi_cmnd *)hostdata->issue_queue;
-            NEXT(tmp); tmp = NEXT(tmp))
-           ;
-       LIST(cmd, tmp);
-       SET_NEXT(tmp, cmd);
-    }
-
-    local_irq_restore(flags);
-
-    dprintk(NDEBUG_QUEUES, "scsi%d: command added to %s of queue\n", H_NO(cmd),
-             (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-
-    /* If queue_command() is called from an interrupt (real one or bottom
-     * half), we let queue_main() do the job of taking care about main. If it
-     * is already running, this is a no-op, else main will be queued.
-     *
-     * If we're not in an interrupt, we can call NCR5380_main()
-     * unconditionally, because it cannot be already running.
-     */
-    if (in_interrupt() || ((flags >> 8) & 7) >= 6)
-       queue_main();
-    else
-       NCR5380_main(NULL);
-    return 0;
-}
-
-static DEF_SCSI_QCMD(NCR5380_queue_command)
-
-/*
- * Function : NCR5380_main (void) 
- *
- * Purpose : NCR5380_main is a coroutine that runs as long as more work can 
- *     be done on the NCR5380 host adapters in a system.  Both 
- *     NCR5380_queue_command() and NCR5380_intr() will try to start it 
- *     in case it is not running.
- * 
- * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should 
- *  reenable them.  This prevents reentrancy and kernel stack overflow.
- */    
-    
-static void NCR5380_main (struct work_struct *bl)
-{
-    struct scsi_cmnd *tmp, *prev;
-    struct Scsi_Host *instance = first_instance;
-    struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
-    int done;
-    unsigned long flags;
-    
-    /*
-     * We run (with interrupts disabled) until we're sure that none of 
-     * the host adapters have anything that can be done, at which point 
-     * we set main_running to 0 and exit.
-     *
-     * Interrupts are enabled before doing various other internal 
-     * instructions, after we've decided that we need to run through
-     * the loop again.
-     *
-     * this should prevent any race conditions.
-     * 
-     * ++roman: Just disabling the NCR interrupt isn't sufficient here,
-     * because also a timer int can trigger an abort or reset, which can
-     * alter queues and touch the Falcon lock.
-     */
-
-    /* Tell int handlers main() is now already executing.  Note that
-       no races are possible here. If an int comes in before
-       'main_running' is set here, and queues/executes main via the
-       task queue, it doesn't do any harm, just this instance of main
-       won't find any work left to do. */
-    if (main_running)
-       return;
-    main_running = 1;
-
-    local_save_flags(flags);
-    do {
-       local_irq_disable(); /* Freeze request queues */
-       done = 1;
-       
-       if (!hostdata->connected) {
-           dprintk(NDEBUG_MAIN,  "scsi%d: not connected\n", HOSTNO );
-           /*
-            * Search through the issue_queue for a command destined
-            * for a target that's not busy.
-            */
-#if (NDEBUG & NDEBUG_LISTS)
-           for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL;
-                tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))
-               ;
-           if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/
-#endif
-           for (tmp = (struct scsi_cmnd *) hostdata->issue_queue,
-                prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) {
-
-               if (prev != tmp)
-                       dprintk(NDEBUG_LISTS, "MAIN tmp=%p   target=%d   busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun);
-               /*  When we find one, remove it from the issue queue. */
-               /* ++guenther: possible race with Falcon locking */
-               if (
-#ifdef SUPPORT_TAGS
-                   !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)
-#else
-                   !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))
-#endif
-                   ) {
-                   /* ++guenther: just to be sure, this must be atomic */
-                   local_irq_disable();
-                   if (prev) {
-                       REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-                       SET_NEXT(prev, NEXT(tmp));
-                   } else {
-                       REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));
-                       hostdata->issue_queue = NEXT(tmp);
-                   }
-                   SET_NEXT(tmp, NULL);
-                   
-                   /* reenable interrupts after finding one */
-                   local_irq_restore(flags);
-                   
-                   /* 
-                    * Attempt to establish an I_T_L nexus here. 
-                    * On success, instance->hostdata->connected is set.
-                    * On failure, we must add the command back to the
-                    *   issue queue so we can keep trying.     
-                    */
-                   dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d "
-                               "lun %llu removed from issue_queue\n",
-                               HOSTNO, tmp->device->id, tmp->device->lun);
-                   /* 
-                    * REQUEST SENSE commands are issued without tagged
-                    * queueing, even on SCSI-II devices because the 
-                    * contingent allegiance condition exists for the 
-                    * entire unit.
-                    */
-                   /* ++roman: ...and the standard also requires that
-                    * REQUEST SENSE command are untagged.
-                    */
-                   
-#ifdef SUPPORT_TAGS
-                   cmd_get_tag( tmp, tmp->cmnd[0] != REQUEST_SENSE );
-#endif
-                   if (!NCR5380_select(instance, tmp, 
-                           (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : 
-                           TAG_NEXT)) {
-                       break;
-                   } else {
-                       local_irq_disable();
-                       LIST(tmp, hostdata->issue_queue);
-                       SET_NEXT(tmp, hostdata->issue_queue);
-                       hostdata->issue_queue = tmp;
-#ifdef SUPPORT_TAGS
-                       cmd_free_tag( tmp );
-#endif
-                       local_irq_restore(flags);
-                       dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, "
-                                   "returned to issue_queue\n", HOSTNO);
-                       if (hostdata->connected)
-                           break;
-                   }
-               } /* if target/lun/target queue is not busy */
-           } /* for issue_queue */
-       } /* if (!hostdata->connected) */
-       if (hostdata->connected 
-#ifdef REAL_DMA
-           && !hostdata->dma_len
-#endif
-           ) {
-           local_irq_restore(flags);
-           dprintk(NDEBUG_MAIN, "scsi%d: main: performing information transfer\n",
-                       HOSTNO);
-           NCR5380_information_transfer(instance);
-           dprintk(NDEBUG_MAIN, "scsi%d: main: done set false\n", HOSTNO);
-           done = 0;
-       }
-    } while (!done);
-
-    /* Better allow ints _after_ 'main_running' has been cleared, else
-       an interrupt could believe we'll pick up the work it left for
-       us, but we won't see it anymore here... */
-    main_running = 0;
-    local_irq_restore(flags);
-}
-
-
-#ifdef REAL_DMA
-/*
- * Function : void NCR5380_dma_complete (struct Scsi_Host *instance)
- *
- * Purpose : Called by interrupt handler when DMA finishes or a phase
- *     mismatch occurs (which would finish the DMA transfer).  
- *
- * Inputs : instance - this instance of the NCR5380.
- *
- */
-
-static void NCR5380_dma_complete( struct Scsi_Host *instance )
-{
-    SETUP_HOSTDATA(instance);
-    int           transfered;
-    unsigned char **data;
-    volatile int  *count;
-
-    if (!hostdata->connected) {
-       printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
-              "no connected cmd\n", HOSTNO);
-       return;
-    }
-
-    dprintk(NDEBUG_DMA, "scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
-              HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
-              NCR5380_read(STATUS_REG));
-
-    if((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) {
-           printk("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n", HOSTNO);
-           printk("please e-mail sammy@sammy.net with a description of how this\n");
-           printk("error was produced.\n");
-           BUG();
-    }
-
-    /* make sure we're not stuck in a data phase */
-    if((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH |
-                                           BASR_ACK)) ==
-       (BASR_PHASE_MATCH | BASR_ACK)) {
-           printk("scsi%d: BASR %02x\n", HOSTNO, NCR5380_read(BUS_AND_STATUS_REG));
-           printk("scsi%d: bus stuck in data phase -- probably a single byte "
-                  "overrun!\n", HOSTNO);
-           printk("not prepared for this error!\n");
-           printk("please e-mail sammy@sammy.net with a description of how this\n");
-           printk("error was produced.\n");
-           BUG();
-    }
-
-
-
-    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-    NCR5380_write(MODE_REG, MR_BASE);
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-    transfered = hostdata->dma_len - NCR5380_dma_residual(instance);
-    hostdata->dma_len = 0;
-
-    data = (unsigned char **) &(hostdata->connected->SCp.ptr);
-    count = &(hostdata->connected->SCp.this_residual);
-    *data += transfered;
-    *count -= transfered;
-
-}
-#endif /* REAL_DMA */
-
-
-/*
- * Function : void NCR5380_intr (int irq)
- * 
- * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
- *     from the disconnected queue, and restarting NCR5380_main() 
- *     as required.
- *
- * Inputs : int irq, irq that caused this interrupt.
- *
- */
-
-static irqreturn_t NCR5380_intr (int irq, void *dev_id)
-{
-    struct Scsi_Host *instance = first_instance;
-    int done = 1, handled = 0;
-    unsigned char basr;
-
-    dprintk(NDEBUG_INTR, "scsi%d: NCR5380 irq triggered\n", HOSTNO);
-
-    /* Look for pending interrupts */
-    basr = NCR5380_read(BUS_AND_STATUS_REG);
-    dprintk(NDEBUG_INTR, "scsi%d: BASR=%02x\n", HOSTNO, basr);
-    /* dispatch to appropriate routine if found and done=0 */
-    if (basr & BASR_IRQ) {
-       NCR5380_dprint(NDEBUG_INTR, instance);
-       if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
-           done = 0;
-//         ENABLE_IRQ();
-           dprintk(NDEBUG_INTR, "scsi%d: SEL interrupt\n", HOSTNO);
-           NCR5380_reselect(instance);
-           (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-       }
-       else if (basr & BASR_PARITY_ERROR) {
-           dprintk(NDEBUG_INTR, "scsi%d: PARITY interrupt\n", HOSTNO);
-           (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-       }
-       else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-           dprintk(NDEBUG_INTR, "scsi%d: RESET interrupt\n", HOSTNO);
-           (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-       }
-       else {
-           /*  
-            * The rest of the interrupt conditions can occur only during a
-            * DMA transfer
-            */
-
-#if defined(REAL_DMA)
-           /*
-            * We should only get PHASE MISMATCH and EOP interrupts if we have
-            * DMA enabled, so do a sanity check based on the current setting
-            * of the MODE register.
-            */
-
-           if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) &&
-               ((basr & BASR_END_DMA_TRANSFER) || 
-                !(basr & BASR_PHASE_MATCH))) {
-                   
-               dprintk(NDEBUG_INTR, "scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
-               NCR5380_dma_complete( instance );
-               done = 0;
-//             ENABLE_IRQ();
-           } else
-#endif /* REAL_DMA */
-           {
-/* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
-               if (basr & BASR_PHASE_MATCH)
-                  dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt, "
-                          "BASR 0x%x, MR 0x%x, SR 0x%x\n",
-                          HOSTNO, basr, NCR5380_read(MODE_REG),
-                          NCR5380_read(STATUS_REG));
-               (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-#ifdef SUN3_SCSI_VME
-               dregs->csr |= CSR_DMA_ENABLE;
-#endif
-           }
-       } /* if !(SELECTION || PARITY) */
-       handled = 1;
-    } /* BASR & IRQ */
-    else {
-
-       printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
-              "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
-              NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
-       (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-#ifdef SUN3_SCSI_VME
-               dregs->csr |= CSR_DMA_ENABLE;
-#endif
-    }
-    
-    if (!done) {
-       dprintk(NDEBUG_INTR, "scsi%d: in int routine, calling main\n", HOSTNO);
-       /* Put a call to NCR5380_main() on the queue... */
-       queue_main();
-    }
-    return IRQ_RETVAL(handled);
-}
-
-#ifdef NCR5380_STATS
-static void collect_stats(struct NCR5380_hostdata *hostdata,
-                         struct scsi_cmnd *cmd)
-{
-# ifdef NCR5380_STAT_LIMIT
-    if (scsi_bufflen(cmd) > NCR5380_STAT_LIMIT)
-# endif
-       switch (cmd->cmnd[0])
-       {
-           case WRITE:
-           case WRITE_6:
-           case WRITE_10:
-               hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase);
-               /*hostdata->bytes_write[cmd->device->id] += scsi_bufflen(cmd);*/
-               hostdata->pendingw--;
-               break;
-           case READ:
-           case READ_6:
-           case READ_10:
-               hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase);
-               /*hostdata->bytes_read[cmd->device->id] += scsi_bufflen(cmd);*/
-               hostdata->pendingr--;
-               break;
-       }
-}
-#endif
-
-/* 
- * Function : int NCR5380_select(struct Scsi_Host *instance,
- *                              struct scsi_cmnd *cmd, int tag);
- *
- * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command,
- *     including ARBITRATION, SELECTION, and initial message out for 
- *     IDENTIFY and queue messages. 
- *
- * Inputs : instance - instantiation of the 5380 driver on which this 
- *     target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for 
- *     new tag, TAG_NONE for untagged queueing, otherwise set to the tag for 
- *     the command that is presently connected.
- * 
- * Returns : -1 if selection could not execute for some reason,
- *     0 if selection succeeded or failed because the target 
- *     did not respond.
- *
- * Side effects : 
- *     If bus busy, arbitration failed, etc, NCR5380_select() will exit 
- *             with registers as they should have been on entry - ie
- *             SELECT_ENABLE will be set appropriately, the NCR5380
- *             will cease to drive any SCSI bus signals.
- *
- *     If successful : I_T_L or I_T_L_Q nexus will be established, 
- *             instance->connected will be set to cmd.  
- *             SELECT interrupt will be disabled.
- *
- *     If failed (no target) : cmd->scsi_done() will be called, and the 
- *             cmd->result host byte set to DID_BAD_TARGET.
- */
-
-static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd,
-                         int tag)
-{
-    SETUP_HOSTDATA(instance);
-    unsigned char tmp[3], phase;
-    unsigned char *data;
-    int len;
-    unsigned long timeout;
-    unsigned long flags;
-
-    hostdata->restart_select = 0;
-    NCR5380_dprint(NDEBUG_ARBITRATION, instance);
-    dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO,
-              instance->this_id);
-
-    /* 
-     * Set the phase bits to 0, otherwise the NCR5380 won't drive the 
-     * data bus during SELECTION.
-     */
-
-    local_irq_save(flags);
-    if (hostdata->connected) {
-       local_irq_restore(flags);
-       return -1;
-    }
-    NCR5380_write(TARGET_COMMAND_REG, 0);
-
-
-    /* 
-     * Start arbitration.
-     */
-    
-    NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
-    NCR5380_write(MODE_REG, MR_ARBITRATE);
-
-    local_irq_restore(flags);
-
-    /* Wait for arbitration logic to complete */
-#ifdef NCR_TIMEOUT
-    {
-      unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
-
-      while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-          && time_before(jiffies, timeout) && !hostdata->connected)
-       ;
-      if (time_after_eq(jiffies, timeout))
-      {
-       printk("scsi : arbitration timeout at %d\n", __LINE__);
-       NCR5380_write(MODE_REG, MR_BASE);
-       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-       return -1;
-      }
-    }
-#else /* NCR_TIMEOUT */
-    while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
-        && !hostdata->connected);
-#endif
-
-    dprintk(NDEBUG_ARBITRATION, "scsi%d: arbitration complete\n", HOSTNO);
-
-    if (hostdata->connected) {
-       NCR5380_write(MODE_REG, MR_BASE); 
-       return -1;
-    }
-    /* 
-     * The arbitration delay is 2.2us, but this is a minimum and there is 
-     * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate
-     * the integral nature of udelay().
-     *
-     */
-
-    udelay(3);
-
-    /* Check for lost arbitration */
-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-       (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) ||
-       (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-       hostdata->connected) {
-       NCR5380_write(MODE_REG, MR_BASE); 
-       dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
-                  HOSTNO);
-       return -1;
-    }
-
-     /* after/during arbitration, BSY should be asserted.
-       IBM DPES-31080 Version S31Q works now */
-     /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL |
-                                        ICR_ASSERT_BSY ) ;
-    
-    if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
-       hostdata->connected) {
-       NCR5380_write(MODE_REG, MR_BASE);
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
-                  HOSTNO);
-       return -1;
-    }
-
-    /* 
-     * Again, bus clear + bus settle time is 1.2us, however, this is 
-     * a minimum so we'll udelay ceil(1.2)
-     */
-
-#ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY
-    /* ++roman: But some targets (see above :-) seem to need a bit more... */
-    udelay(15);
-#else
-    udelay(2);
-#endif
-    
-    if (hostdata->connected) {
-       NCR5380_write(MODE_REG, MR_BASE);
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       return -1;
-    }
-
-    dprintk(NDEBUG_ARBITRATION, "scsi%d: won arbitration\n", HOSTNO);
-
-    /* 
-     * Now that we have won arbitration, start Selection process, asserting 
-     * the host and target ID's on the SCSI bus.
-     */
-
-    NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id)));
-
-    /* 
-     * Raise ATN while SEL is true before BSY goes false from arbitration,
-     * since this is the only way to guarantee that we'll get a MESSAGE OUT
-     * phase immediately after selection.
-     */
-
-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | 
-       ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL ));
-    NCR5380_write(MODE_REG, MR_BASE);
-
-    /* 
-     * Reselect interrupts must be turned off prior to the dropping of BSY,
-     * otherwise we will trigger an interrupt.
-     */
-
-    if (hostdata->connected) {
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       return -1;
-    }
-
-    NCR5380_write(SELECT_ENABLE_REG, 0);
-
-    /*
-     * The initiator shall then wait at least two deskew delays and release 
-     * the BSY signal.
-     */
-    udelay(1);        /* wingel -- wait two bus deskew delay >2*45ns */
-
-    /* Reset BSY */
-    NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | 
-       ICR_ASSERT_ATN | ICR_ASSERT_SEL));
-
-    /* 
-     * Something weird happens when we cease to drive BSY - looks
-     * like the board/chip is letting us do another read before the 
-     * appropriate propagation delay has expired, and we're confusing
-     * a BSY signal from ourselves as the target's response to SELECTION.
-     *
-     * A small delay (the 'C++' frontend breaks the pipeline with an
-     * unnecessary jump, making it work on my 386-33/Trantor T128, the
-     * tighter 'C' code breaks and requires this) solves the problem - 
-     * the 1 us delay is arbitrary, and only used because this delay will 
-     * be the same on other platforms and since it works here, it should 
-     * work there.
-     *
-     * wingel suggests that this could be due to failing to wait
-     * one deskew delay.
-     */
-
-    udelay(1);
-
-    dprintk(NDEBUG_SELECTION, "scsi%d: selecting target %d\n", HOSTNO, cmd->device->id);
-
-    /* 
-     * The SCSI specification calls for a 250 ms timeout for the actual 
-     * selection.
-     */
-
-    timeout = jiffies + 25; 
-
-    /* 
-     * XXX very interesting - we're seeing a bounce where the BSY we 
-     * asserted is being reflected / still asserted (propagation delay?)
-     * and it's detecting as true.  Sigh.
-     */
-
-#if 0
-    /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert
-     * IO while SEL is true. But again, there are some disks out the in the
-     * world that do that nevertheless. (Somebody claimed that this announces
-     * reselection capability of the target.) So we better skip that test and
-     * only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
-     */
-
-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & 
-       (SR_BSY | SR_IO)));
-
-    if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == 
-           (SR_SEL | SR_IO)) {
-           NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-           NCR5380_reselect(instance);
-           printk (KERN_ERR "scsi%d: reselection after won arbitration?\n",
-                   HOSTNO);
-           NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-           return -1;
-    }
-#else
-    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
-#endif
-
-    /* 
-     * No less than two deskew delays after the initiator detects the 
-     * BSY signal is true, it shall release the SEL signal and may 
-     * change the DATA BUS.                                     -wingel
-     */
-
-    udelay(1);
-
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-
-    if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       if (hostdata->targets_present & (1 << cmd->device->id)) {
-           printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
-           if (hostdata->restart_select)
-               printk(KERN_NOTICE "\trestart select\n");
-           NCR5380_dprint(NDEBUG_ANY, instance);
-           NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-           return -1;
-       }
-       cmd->result = DID_BAD_TARGET << 16;
-#ifdef NCR5380_STATS
-       collect_stats(hostdata, cmd);
-#endif
-#ifdef SUPPORT_TAGS
-       cmd_free_tag( cmd );
-#endif
-       cmd->scsi_done(cmd);
-       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-       dprintk(NDEBUG_SELECTION, "scsi%d: target did not respond within 250ms\n", HOSTNO);
-       NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-       return 0;
-    } 
-
-    hostdata->targets_present |= (1 << cmd->device->id);
-
-    /*
-     * Since we followed the SCSI spec, and raised ATN while SEL 
-     * was true but before BSY was false during selection, the information
-     * transfer phase should be a MESSAGE OUT phase so that we can send the
-     * IDENTIFY message.
-     * 
-     * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG
-     * message (2 bytes) with a tag ID that we increment with every command
-     * until it wraps back to 0.
-     *
-     * XXX - it turns out that there are some broken SCSI-II devices,
-     *      which claim to support tagged queuing but fail when more than
-     *      some number of commands are issued at once.
-     */
-
-    /* Wait for start of REQ/ACK handshake */
-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
-    dprintk(NDEBUG_SELECTION, "scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
-              HOSTNO, cmd->device->id);
-    tmp[0] = IDENTIFY(1, cmd->device->lun);
-
-#ifdef SUPPORT_TAGS
-    if (cmd->tag != TAG_NONE) {
-       tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;
-       tmp[2] = cmd->tag;
-       len = 3;
-    } else 
-       len = 1;
-#else
-    len = 1;
-    cmd->tag=0;
-#endif /* SUPPORT_TAGS */
-
-    /* Send message(s) */
-    data = tmp;
-    phase = PHASE_MSGOUT;
-    NCR5380_transfer_pio(instance, &phase, &len, &data);
-    dprintk(NDEBUG_SELECTION, "scsi%d: nexus established.\n", HOSTNO);
-    /* XXX need to handle errors here */
-    hostdata->connected = cmd;
-#ifndef SUPPORT_TAGS
-    hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-#endif    
-#ifdef SUN3_SCSI_VME
-    dregs->csr |= CSR_INTR;
-#endif
-    initialize_SCp(cmd);
-
-
-    return 0;
-}
-
-/* 
- * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, 
- *      unsigned char *phase, int *count, unsigned char **data)
- *
- * Purpose : transfers data in given phase using polled I/O
- *
- * Inputs : instance - instance of driver, *phase - pointer to 
- *     what phase is expected, *count - pointer to number of 
- *     bytes to transfer, **data - pointer to data pointer.
- * 
- * Returns : -1 when different phase is entered without transferring
- *     maximum number of bytes, 0 if all bytes are transferred or exit
- *     is in same phase.
- *
- *     Also, *phase, *count, *data are modified in place.
- *
- * XXX Note : handling for bus free may be useful.
- */
-
-/*
- * Note : this code is not as quick as it could be, however it 
- * IS 100% reliable, and for the actual data transfer where speed
- * counts, we will always do a pseudo DMA or DMA transfer.
- */
-
-static int NCR5380_transfer_pio( struct Scsi_Host *instance, 
-                                unsigned char *phase, int *count,
-                                unsigned char **data)
-{
-    register unsigned char p = *phase, tmp;
-    register int c = *count;
-    register unsigned char *d = *data;
-
-    /* 
-     * The NCR5380 chip will only drive the SCSI bus when the 
-     * phase specified in the appropriate bits of the TARGET COMMAND
-     * REGISTER match the STATUS REGISTER
-     */
-
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
-
-    do {
-       /* 
-        * Wait for assertion of REQ, after which the phase bits will be 
-        * valid 
-        */
-       while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
-
-       dprintk(NDEBUG_HANDSHAKE, "scsi%d: REQ detected\n", HOSTNO);
-
-       /* Check for phase mismatch */  
-       if ((tmp & PHASE_MASK) != p) {
-           dprintk(NDEBUG_PIO, "scsi%d: phase mismatch\n", HOSTNO);
-           NCR5380_dprint_phase(NDEBUG_PIO, instance);
-           break;
-       }
-
-       /* Do actual transfer from SCSI bus to / from memory */
-       if (!(p & SR_IO)) 
-           NCR5380_write(OUTPUT_DATA_REG, *d);
-       else 
-           *d = NCR5380_read(CURRENT_SCSI_DATA_REG);
-
-       ++d;
-
-       /* 
-        * The SCSI standard suggests that in MSGOUT phase, the initiator
-        * should drop ATN on the last byte of the message phase
-        * after REQ has been asserted for the handshake but before
-        * the initiator raises ACK.
-        */
-
-       if (!(p & SR_IO)) {
-           if (!((p & SR_MSG) && c > 1)) {
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                   ICR_ASSERT_DATA);
-               NCR5380_dprint(NDEBUG_PIO, instance);
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                       ICR_ASSERT_DATA | ICR_ASSERT_ACK);
-           } else {
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
-                   ICR_ASSERT_DATA | ICR_ASSERT_ATN);
-               NCR5380_dprint(NDEBUG_PIO, instance);
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                   ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
-           }
-       } else {
-           NCR5380_dprint(NDEBUG_PIO, instance);
-           NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
-       }
-
-       while (NCR5380_read(STATUS_REG) & SR_REQ);
-
-       dprintk(NDEBUG_HANDSHAKE, "scsi%d: req false, handshake complete\n", HOSTNO);
-
-/*
- * We have several special cases to consider during REQ/ACK handshaking : 
- * 1.  We were in MSGOUT phase, and we are on the last byte of the 
- *     message.  ATN must be dropped as ACK is dropped.
- *
- * 2.  We are in a MSGIN phase, and we are on the last byte of the  
- *     message.  We must exit with ACK asserted, so that the calling
- *     code may raise ATN before dropping ACK to reject the message.
- *
- * 3.  ACK and ATN are clear and the target may proceed as normal.
- */
-       if (!(p == PHASE_MSGIN && c == 1)) {  
-           if (p == PHASE_MSGOUT && c > 1)
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-           else
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-       } 
-    } while (--c);
-
-    dprintk(NDEBUG_PIO, "scsi%d: residual %d\n", HOSTNO, c);
-
-    *count = c;
-    *data = d;
-    tmp = NCR5380_read(STATUS_REG);
-    /* The phase read from the bus is valid if either REQ is (already)
-     * asserted or if ACK hasn't been released yet. The latter is the case if
-     * we're in MSGIN and all wanted bytes have been received. */
-    if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))
-       *phase = tmp & PHASE_MASK;
-    else 
-       *phase = PHASE_UNKNOWN;
-
-    if (!c || (*phase == p))
-       return 0;
-    else 
-       return -1;
-}
-
-/*
- * Function : do_abort (Scsi_Host *host)
- * 
- * Purpose : abort the currently established nexus.  Should only be 
- *     called from a routine which can drop into a 
- * 
- * Returns : 0 on success, -1 on failure.
- */
-
-static int do_abort (struct Scsi_Host *host) 
-{
-    unsigned char tmp, *msgptr, phase;
-    int len;
-
-    /* Request message out phase */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-
-    /* 
-     * Wait for the target to indicate a valid phase by asserting 
-     * REQ.  Once this happens, we'll have either a MSGOUT phase 
-     * and can immediately send the ABORT message, or we'll have some 
-     * other phase and will have to source/sink data.
-     * 
-     * We really don't care what value was on the bus or what value
-     * the target sees, so we just handshake.
-     */
-    
-    while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
-
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
-    if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
-                     ICR_ASSERT_ACK);
-       while (NCR5380_read(STATUS_REG) & SR_REQ);
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
-    }
-   
-    tmp = ABORT;
-    msgptr = &tmp;
-    len = 1;
-    phase = PHASE_MSGOUT;
-    NCR5380_transfer_pio (host, &phase, &len, &msgptr);
-
-    /*
-     * If we got here, and the command completed successfully,
-     * we're about to go into bus free state.
-     */
-
-    return len ? -1 : 0;
-}
-
-#if defined(REAL_DMA)
-/* 
- * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, 
- *      unsigned char *phase, int *count, unsigned char **data)
- *
- * Purpose : transfers data in given phase using either real
- *     or pseudo DMA.
- *
- * Inputs : instance - instance of driver, *phase - pointer to 
- *     what phase is expected, *count - pointer to number of 
- *     bytes to transfer, **data - pointer to data pointer.
- * 
- * Returns : -1 when different phase is entered without transferring
- *     maximum number of bytes, 0 if all bytes or transferred or exit
- *     is in same phase.
- *
- *     Also, *phase, *count, *data are modified in place.
- *
- */
-
-
-static int NCR5380_transfer_dma( struct Scsi_Host *instance, 
-                                unsigned char *phase, int *count,
-                                unsigned char **data)
-{
-    SETUP_HOSTDATA(instance);
-    register int c = *count;
-    register unsigned char p = *phase;
-    unsigned long flags;
-
-    /* sanity check */
-    if(!sun3_dma_setup_done) {
-        printk("scsi%d: transfer_dma without setup!\n", HOSTNO);
-        BUG();
-    }
-    hostdata->dma_len = c;
-
-    dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n",
-              HOSTNO, (p & SR_IO) ? "reading" : "writing",
-              c, (p & SR_IO) ? "to" : "from", *data);
-
-    /* netbsd turns off ints here, why not be safe and do it too */
-    local_irq_save(flags);
-    
-    /* send start chain */
-    sun3scsi_dma_start(c, *data);
-    
-    if (p & SR_IO) {
-           NCR5380_write(TARGET_COMMAND_REG, 1);
-           NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-           NCR5380_write(INITIATOR_COMMAND_REG, 0);
-           NCR5380_write(MODE_REG, (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
-           NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);
-    } else {
-           NCR5380_write(TARGET_COMMAND_REG, 0);
-           NCR5380_read(RESET_PARITY_INTERRUPT_REG);
-           NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_DATA);
-           NCR5380_write(MODE_REG, (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR));
-           NCR5380_write(START_DMA_SEND_REG, 0);
-    }
-
-#ifdef SUN3_SCSI_VME
-    dregs->csr |= CSR_DMA_ENABLE;
-#endif
-
-    local_irq_restore(flags);
-
-    sun3_dma_active = 1;
-    return 0;
-}
-#endif /* defined(REAL_DMA) */
-
-/*
- * Function : NCR5380_information_transfer (struct Scsi_Host *instance)
- *
- * Purpose : run through the various SCSI phases and do as the target 
- *     directs us to.  Operates on the currently connected command, 
- *     instance->connected.
- *
- * Inputs : instance, instance for which we are doing commands
- *
- * Side effects : SCSI things happen, the disconnected queue will be 
- *     modified if a command disconnects, *instance->connected will
- *     change.
- *
- * XXX Note : we need to watch for bus free or a reset condition here 
- *     to recover from an unexpected bus free condition.
- */
-static void NCR5380_information_transfer (struct Scsi_Host *instance)
-{
-    SETUP_HOSTDATA(instance);
-    unsigned long flags;
-    unsigned char msgout = NOP;
-    int sink = 0;
-    int len;
-#if defined(REAL_DMA)
-    int transfersize;
-#endif
-    unsigned char *data;
-    unsigned char phase, tmp, extended_msg[10], old_phase=0xff;
-    struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected;
-
-#ifdef SUN3_SCSI_VME
-    dregs->csr |= CSR_INTR;
-#endif
-
-    while (1) {
-       tmp = NCR5380_read(STATUS_REG);
-       /* We only have a valid SCSI phase when REQ is asserted */
-       if (tmp & SR_REQ) {
-           phase = (tmp & PHASE_MASK); 
-           if (phase != old_phase) {
-               old_phase = phase;
-               NCR5380_dprint_phase(NDEBUG_INFORMATION, instance);
-           }
-
-           if(phase == PHASE_CMDOUT) {
-                   void *d;
-                   unsigned long count;
-
-               if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
-                       count = cmd->SCp.buffer->length;
-                       d = SGADDR(cmd->SCp.buffer);
-               } else {
-                       count = cmd->SCp.this_residual;
-                       d = cmd->SCp.ptr;
-               }
-#ifdef REAL_DMA
-               /* this command setup for dma yet? */
-               if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done
-                                                 != cmd))
-               {
-                       if (cmd->request->cmd_type == REQ_TYPE_FS) {
-                               sun3scsi_dma_setup(d, count,
-                                                  rq_data_dir(cmd->request));
-                               sun3_dma_setup_done = cmd;
-                       }
-               }
-#endif
-#ifdef SUN3_SCSI_VME
-               dregs->csr |= CSR_INTR;
-#endif
-           }
-
-           
-           if (sink && (phase != PHASE_MSGOUT)) {
-               NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));
-
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | 
-                   ICR_ASSERT_ACK);
-               while (NCR5380_read(STATUS_REG) & SR_REQ);
-               NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                   ICR_ASSERT_ATN);
-               sink = 0;
-               continue;
-           }
-
-           switch (phase) {
-           case PHASE_DATAOUT:
-#if (NDEBUG & NDEBUG_NO_DATAOUT)
-               printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "
-                      "aborted\n", HOSTNO);
-               sink = 1;
-               do_abort(instance);
-               cmd->result = DID_ERROR  << 16;
-               cmd->scsi_done(cmd);
-               return;
-#endif
-           case PHASE_DATAIN:
-               /* 
-                * If there is no room left in the current buffer in the
-                * scatter-gather list, move onto the next one.
-                */
-               if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
-                   ++cmd->SCp.buffer;
-                   --cmd->SCp.buffers_residual;
-                   cmd->SCp.this_residual = cmd->SCp.buffer->length;
-                   cmd->SCp.ptr = SGADDR(cmd->SCp.buffer);
-                   dprintk(NDEBUG_INFORMATION, "scsi%d: %d bytes and %d buffers left\n",
-                              HOSTNO, cmd->SCp.this_residual,
-                              cmd->SCp.buffers_residual);
-               }
-
-               /*
-                * The preferred transfer method is going to be 
-                * PSEUDO-DMA for systems that are strictly PIO,
-                * since we can let the hardware do the handshaking.
-                *
-                * For this to work, we need to know the transfersize
-                * ahead of time, since the pseudo-DMA code will sit
-                * in an unconditional loop.
-                */
-
-/* ++roman: I suggest, this should be
- *   #if def(REAL_DMA)
- * instead of leaving REAL_DMA out.
- */
-
-#if defined(REAL_DMA)
-//             if (!cmd->device->borken &&
-               if((transfersize =
-                   NCR5380_dma_xfer_len(instance,cmd,phase)) > SUN3_DMA_MINSIZE) {
-                   len = transfersize;
-                   cmd->SCp.phase = phase;
-
-                   if (NCR5380_transfer_dma(instance, &phase,
-                       &len, (unsigned char **) &cmd->SCp.ptr)) {
-                       /*
-                        * If the watchdog timer fires, all future
-                        * accesses to this device will use the
-                        * polled-IO. */ 
-                       printk(KERN_NOTICE "scsi%d: switching target %d "
-                              "lun %llu to slow handshake\n", HOSTNO,
-                              cmd->device->id, cmd->device->lun);
-                       cmd->device->borken = 1;
-                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                           ICR_ASSERT_ATN);
-                       sink = 1;
-                       do_abort(instance);
-                       cmd->result = DID_ERROR  << 16;
-                       cmd->scsi_done(cmd);
-                       /* XXX - need to source or sink data here, as appropriate */
-                   } else {
-#ifdef REAL_DMA
-                       /* ++roman: When using real DMA,
-                        * information_transfer() should return after
-                        * starting DMA since it has nothing more to
-                        * do.
-                        */
-                                   return;
-#else                  
-                       cmd->SCp.this_residual -= transfersize - len;
-#endif
-                   }
-               } else 
-#endif /* defined(REAL_DMA) */
-                 NCR5380_transfer_pio(instance, &phase, 
-                   (int *) &cmd->SCp.this_residual, (unsigned char **)
-                   &cmd->SCp.ptr);
-#ifdef REAL_DMA
-               /* if we had intended to dma that command clear it */
-               if(sun3_dma_setup_done == cmd)
-                       sun3_dma_setup_done = NULL;
-#endif
-
-               break;
-           case PHASE_MSGIN:
-               len = 1;
-               data = &tmp;
-               NCR5380_write(SELECT_ENABLE_REG, 0);    /* disable reselects */
-               NCR5380_transfer_pio(instance, &phase, &len, &data);
-               cmd->SCp.Message = tmp;
-               
-               switch (tmp) {
-               /*
-                * Linking lets us reduce the time required to get the 
-                * next command out to the device, hopefully this will
-                * mean we don't waste another revolution due to the delays
-                * required by ARBITRATION and another SELECTION.
-                *
-                * In the current implementation proposal, low level drivers
-                * merely have to start the next command, pointed to by 
-                * next_link, done() is called as with unlinked commands.
-                */
-#ifdef LINKED
-               case LINKED_CMD_COMPLETE:
-               case LINKED_FLG_CMD_COMPLETE:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   
-                   dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command "
-                              "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun);
-
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   /*
-                    * Sanity check : A linked command should only terminate
-                    * with one of these messages if there are more linked
-                    * commands available.
-                    */
-
-                   if (!cmd->next_link) {
-                        printk(KERN_NOTICE "scsi%d: target %d lun %llu "
-                               "linked command complete, no next_link\n",
-                               HOSTNO, cmd->device->id, cmd->device->lun);
-                           sink = 1;
-                           do_abort (instance);
-                           return;
-                   }
-
-                   initialize_SCp(cmd->next_link);
-                   /* The next command is still part of this process; copy it
-                    * and don't free it! */
-                   cmd->next_link->tag = cmd->tag;
-                   cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-                   dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request "
-                              "done, calling scsi_done().\n",
-                              HOSTNO, cmd->device->id, cmd->device->lun);
-#ifdef NCR5380_STATS
-                   collect_stats(hostdata, cmd);
-#endif
-                   cmd->scsi_done(cmd);
-                   cmd = hostdata->connected;
-                   break;
-#endif /* def LINKED */
-               case ABORT:
-               case COMMAND_COMPLETE: 
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   hostdata->connected = NULL;
-                   dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu "
-                             "completed\n", HOSTNO, cmd->device->id, cmd->device->lun);
-#ifdef SUPPORT_TAGS
-                   cmd_free_tag( cmd );
-                   if (status_byte(cmd->SCp.Status) == QUEUE_FULL) {
-                       /* Turn a QUEUE FULL status into BUSY, I think the
-                        * mid level cannot handle QUEUE FULL :-( (The
-                        * command is retried after BUSY). Also update our
-                        * queue size to the number of currently issued
-                        * commands now.
-                        */
-                       /* ++Andreas: the mid level code knows about
-                          QUEUE_FULL now. */
-                       TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun];
-                       dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned "
-                                  "QUEUE_FULL after %d commands\n",
-                                  HOSTNO, cmd->device->id, cmd->device->lun,
-                                  ta->nr_allocated);
-                       if (ta->queue_size > ta->nr_allocated)
-                           ta->nr_allocated = ta->queue_size;
-                   }
-#else
-                   hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
-#endif
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-
-                   /* 
-                    * I'm not sure what the correct thing to do here is : 
-                    * 
-                    * If the command that just executed is NOT a request 
-                    * sense, the obvious thing to do is to set the result
-                    * code to the values of the stored parameters.
-                    * 
-                    * If it was a REQUEST SENSE command, we need some way to
-                    * differentiate between the failure code of the original
-                    * and the failure code of the REQUEST sense - the obvious
-                    * case is success, where we fall through and leave the
-                    * result code unchanged.
-                    * 
-                    * The non-obvious place is where the REQUEST SENSE failed
-                    */
-
-                   if (cmd->cmnd[0] != REQUEST_SENSE) 
-                       cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-                   else if (status_byte(cmd->SCp.Status) != GOOD)
-                       cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
-                   
-#ifdef AUTOSENSE
-                   if ((cmd->cmnd[0] == REQUEST_SENSE) &&
-                                               hostdata->ses.cmd_len) {
-                       scsi_eh_restore_cmnd(cmd, &hostdata->ses);
-                       hostdata->ses.cmd_len = 0 ;
-                   }
-
-                   if ((cmd->cmnd[0] != REQUEST_SENSE) && 
-                       (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) {
-                       scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0);
-                       dprintk(NDEBUG_AUTOSENSE, "scsi%d: performing request sense\n",
-                                   HOSTNO);
-                       /* this is initialized from initialize_SCp 
-                       cmd->SCp.buffer = NULL;
-                       cmd->SCp.buffers_residual = 0;
-                       */
-
-                       local_irq_save(flags);
-                       LIST(cmd,hostdata->issue_queue);
-                       SET_NEXT(cmd, hostdata->issue_queue);
-                       hostdata->issue_queue = (struct scsi_cmnd *) cmd;
-                       local_irq_restore(flags);
-                       dprintk(NDEBUG_QUEUES, "scsi%d: REQUEST SENSE added to head of "
-                                 "issue queue\n", H_NO(cmd));
-                  } else
-#endif /* def AUTOSENSE */
-                  {
-#ifdef NCR5380_STATS
-                      collect_stats(hostdata, cmd);
-#endif
-                      cmd->scsi_done(cmd);
-                   }
-
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   /* 
-                    * Restore phase bits to 0 so an interrupted selection, 
-                    * arbitration can resume.
-                    */
-                   NCR5380_write(TARGET_COMMAND_REG, 0);
-                   
-                   while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
-                       barrier();
-
-                   return;
-               case MESSAGE_REJECT:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   switch (hostdata->last_message) {
-                   case HEAD_OF_QUEUE_TAG:
-                   case ORDERED_QUEUE_TAG:
-                   case SIMPLE_QUEUE_TAG:
-                       /* The target obviously doesn't support tagged
-                        * queuing, even though it announced this ability in
-                        * its INQUIRY data ?!? (maybe only this LUN?) Ok,
-                        * clear 'tagged_supported' and lock the LUN, since
-                        * the command is treated as untagged further on.
-                        */
-                       cmd->device->tagged_supported = 0;
-                       hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
-                       cmd->tag = TAG_NONE;
-                       dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected "
-                                  "QUEUE_TAG message; tagged queuing "
-                                  "disabled\n",
-                                  HOSTNO, cmd->device->id, cmd->device->lun);
-                       break;
-                   }
-                   break;
-               case DISCONNECT:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   local_irq_save(flags);
-                   cmd->device->disconnect = 1;
-                   LIST(cmd,hostdata->disconnected_queue);
-                   SET_NEXT(cmd, hostdata->disconnected_queue);
-                   hostdata->connected = NULL;
-                   hostdata->disconnected_queue = cmd;
-                   local_irq_restore(flags);
-                   dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was "
-                             "moved from connected to the "
-                             "disconnected_queue\n", HOSTNO, 
-                             cmd->device->id, cmd->device->lun);
-                   /* 
-                    * Restore phase bits to 0 so an interrupted selection, 
-                    * arbitration can resume.
-                    */
-                   NCR5380_write(TARGET_COMMAND_REG, 0);
-
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   /* Wait for bus free to avoid nasty timeouts */
-                   while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected)
-                       barrier();
-#ifdef SUN3_SCSI_VME
-                   dregs->csr |= CSR_DMA_ENABLE;
-#endif
-                   return;
-               /* 
-                * The SCSI data pointer is *IMPLICITLY* saved on a disconnect
-                * operation, in violation of the SCSI spec so we can safely 
-                * ignore SAVE/RESTORE pointers calls.
-                *
-                * Unfortunately, some disks violate the SCSI spec and 
-                * don't issue the required SAVE_POINTERS message before
-                * disconnecting, and we have to break spec to remain 
-                * compatible.
-                */
-               case SAVE_POINTERS:
-               case RESTORE_POINTERS:
-                   /* Accept message by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                   /* Enable reselect interrupts */
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   break;
-               case EXTENDED_MESSAGE:
-/* 
- * Extended messages are sent in the following format :
- * Byte        
- * 0           EXTENDED_MESSAGE == 1
- * 1           length (includes one byte for code, doesn't 
- *             include first two bytes)
- * 2           code
- * 3..length+1 arguments
- *
- * Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since spi_print_msg() wants the whole thing.  
- */
-                   extended_msg[0] = EXTENDED_MESSAGE;
-                   /* Accept first byte by clearing ACK */
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-                   dprintk(NDEBUG_EXTENDED, "scsi%d: receiving extended message\n", HOSTNO);
-
-                   len = 2;
-                   data = extended_msg + 1;
-                   phase = PHASE_MSGIN;
-                   NCR5380_transfer_pio(instance, &phase, &len, &data);
-                   dprintk(NDEBUG_EXTENDED, "scsi%d: length=%d, code=0x%02x\n", HOSTNO,
-                              (int)extended_msg[1], (int)extended_msg[2]);
-
-                   if (!len && extended_msg[1] <= 
-                       (sizeof (extended_msg) - 1)) {
-                       /* Accept third byte by clearing ACK */
-                       NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-                       len = extended_msg[1] - 1;
-                       data = extended_msg + 3;
-                       phase = PHASE_MSGIN;
-
-                       NCR5380_transfer_pio(instance, &phase, &len, &data);
-                       dprintk(NDEBUG_EXTENDED, "scsi%d: message received, residual %d\n",
-                                  HOSTNO, len);
-
-                       switch (extended_msg[2]) {
-                       case EXTENDED_SDTR:
-                       case EXTENDED_WDTR:
-                       case EXTENDED_MODIFY_DATA_POINTER:
-                       case EXTENDED_EXTENDED_IDENTIFY:
-                           tmp = 0;
-                       }
-                   } else if (len) {
-                       printk(KERN_NOTICE "scsi%d: error receiving "
-                              "extended message\n", HOSTNO);
-                       tmp = 0;
-                   } else {
-                       printk(KERN_NOTICE "scsi%d: extended message "
-                              "code %02x length %d is too long\n",
-                              HOSTNO, extended_msg[2], extended_msg[1]);
-                       tmp = 0;
-                   }
-               /* Fall through to reject message */
-
-               /* 
-                * If we get something weird that we aren't expecting, 
-                * reject it.
-                */
-               default:
-                   if (!tmp) {
-                       printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
-                       spi_print_msg(extended_msg);
-                       printk("\n");
-                   } else if (tmp != EXTENDED_MESSAGE)
-                       printk(KERN_DEBUG "scsi%d: rejecting unknown "
-                              "message %02x from target %d, lun %llu\n",
-                              HOSTNO, tmp, cmd->device->id, cmd->device->lun);
-                   else
-                       printk(KERN_DEBUG "scsi%d: rejecting unknown "
-                              "extended message "
-                              "code %02x, length %d from target %d, lun %llu\n",
-                              HOSTNO, extended_msg[1], extended_msg[0],
-                              cmd->device->id, cmd->device->lun);
-   
-
-                   msgout = MESSAGE_REJECT;
-                   NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
-                       ICR_ASSERT_ATN);
-                   break;
-               } /* switch (tmp) */
-               break;
-           case PHASE_MSGOUT:
-               len = 1;
-               data = &msgout;
-               hostdata->last_message = msgout;
-               NCR5380_transfer_pio(instance, &phase, &len, &data);
-               if (msgout == ABORT) {
-#ifdef SUPPORT_TAGS
-                   cmd_free_tag( cmd );
-#else
-                   hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
-#endif
-                   hostdata->connected = NULL;
-                   cmd->result = DID_ERROR << 16;
-#ifdef NCR5380_STATS
-                   collect_stats(hostdata, cmd);
-#endif
-                   cmd->scsi_done(cmd);
-                   NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-                   return;
-               }
-               msgout = NOP;
-               break;
-           case PHASE_CMDOUT:
-               len = cmd->cmd_len;
-               data = cmd->cmnd;
-               /* 
-                * XXX for performance reasons, on machines with a 
-                * PSEUDO-DMA architecture we should probably 
-                * use the dma transfer function.  
-                */
-               NCR5380_transfer_pio(instance, &phase, &len, 
-                   &data);
-               break;
-           case PHASE_STATIN:
-               len = 1;
-               data = &tmp;
-               NCR5380_transfer_pio(instance, &phase, &len, &data);
-               cmd->SCp.Status = tmp;
-               break;
-           default:
-               printk("scsi%d: unknown phase\n", HOSTNO);
-               NCR5380_dprint(NDEBUG_ANY, instance);
-           } /* switch(phase) */
-       } /* if (tmp * SR_REQ) */ 
-    } /* while (1) */
-}
-
-/*
- * Function : void NCR5380_reselect (struct Scsi_Host *instance)
- *
- * Purpose : does reselection, initializing the instance->connected 
- *     field to point to the struct scsi_cmnd for which the I_T_L or I_T_L_Q
- *     nexus has been reestablished,
- *     
- * Inputs : instance - this instance of the NCR5380.
- *
- */
-
-/* it might eventually prove necessary to do a dma setup on
-   reselection, but it doesn't seem to be needed now -- sam */
-
-static void NCR5380_reselect (struct Scsi_Host *instance)
-{
-    SETUP_HOSTDATA(instance);
-    unsigned char target_mask;
-    unsigned char lun;
-#ifdef SUPPORT_TAGS
-    unsigned char tag;
-#endif
-    unsigned char msg[3];
-    struct scsi_cmnd *tmp = NULL, *prev;
-/*    unsigned long flags; */
-
-    /*
-     * Disable arbitration, etc. since the host adapter obviously
-     * lost, and tell an interrupted NCR5380_select() to restart.
-     */
-
-    NCR5380_write(MODE_REG, MR_BASE);
-    hostdata->restart_select = 1;
-
-    target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
-
-    dprintk(NDEBUG_RESELECTION, "scsi%d: reselect\n", HOSTNO);
-
-    /* 
-     * At this point, we have detected that our SCSI ID is on the bus,
-     * SEL is true and BSY was false for at least one bus settle delay
-     * (400 ns).
-     *
-     * We must assert BSY ourselves, until the target drops the SEL
-     * signal.
-     */
-
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
-    
-    while (NCR5380_read(STATUS_REG) & SR_SEL);
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-    /*
-     * Wait for target to go into MSGIN.
-     */
-
-    while (!(NCR5380_read(STATUS_REG) & SR_REQ));
-
-#if 1
-    // acknowledge toggle to MSGIN
-    NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(PHASE_MSGIN));
-
-    // peek at the byte without really hitting the bus
-    msg[0] = NCR5380_read(CURRENT_SCSI_DATA_REG);
-#endif
-
-    if (!(msg[0] & 0x80)) {
-       printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
-       spi_print_msg(msg);
-       do_abort(instance);
-       return;
-    }
-    lun = (msg[0] & 0x07);
-
-    /* 
-     * Find the command corresponding to the I_T_L or I_T_L_Q  nexus we 
-     * just reestablished, and remove it from the disconnected queue.
-     */
-
-    for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL;
-        tmp; prev = tmp, tmp = NEXT(tmp) ) {
-       if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun)
-#ifdef SUPPORT_TAGS
-           && (tag == tmp->tag) 
-#endif
-           ) {
-           if (prev) {
-               REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
-               SET_NEXT(prev, NEXT(tmp));
-           } else {
-               REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp));
-               hostdata->disconnected_queue = NEXT(tmp);
-           }
-           SET_NEXT(tmp, NULL);
-           break;
-       }
-    }
-    
-    if (!tmp) {
-       printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
-#ifdef SUPPORT_TAGS
-               "tag %d "
-#endif
-               "not in disconnected_queue.\n",
-               HOSTNO, target_mask, lun
-#ifdef SUPPORT_TAGS
-               , tag
-#endif
-               );
-       /* 
-        * Since we have an established nexus that we can't do anything
-        * with, we must abort it.  
-        */
-       do_abort(instance);
-       return;
-    }
-#if 1
-    /* engage dma setup for the command we just saw */
-    {
-           void *d;
-           unsigned long count;
-
-           if (!tmp->SCp.this_residual && tmp->SCp.buffers_residual) {
-                   count = tmp->SCp.buffer->length;
-                   d = SGADDR(tmp->SCp.buffer);
-           } else {
-                   count = tmp->SCp.this_residual;
-                   d = tmp->SCp.ptr;
-           }
-#ifdef REAL_DMA
-           /* setup this command for dma if not already */
-           if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done != tmp))
-           {
-                   sun3scsi_dma_setup(d, count, rq_data_dir(tmp->request));
-                   sun3_dma_setup_done = tmp;
-           }
-#endif
-    }
-#endif
-
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
-    /* Accept message by clearing ACK */
-    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-
-#ifdef SUPPORT_TAGS
-    /* If the phase is still MSGIN, the target wants to send some more
-     * messages. In case it supports tagged queuing, this is probably a
-     * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus.
-     */
-    tag = TAG_NONE;
-    if (phase == PHASE_MSGIN && setup_use_tagged_queuing) {
-       /* Accept previous IDENTIFY message by clearing ACK */
-       NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-       len = 2;
-       data = msg+1;
-       if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
-           msg[1] == SIMPLE_QUEUE_TAG)
-           tag = msg[2];
-       dprintk(NDEBUG_TAGS, "scsi%d: target mask %02x, lun %d sent tag %d at "
-                  "reselection\n", HOSTNO, target_mask, lun, tag);
-    }
-#endif
-    
-    hostdata->connected = tmp;
-    dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n",
-              HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag);
-}
-
-
-/*
- * Function : int NCR5380_abort(struct scsi_cmnd *cmd)
- *
- * Purpose : abort a command
- *
- * Inputs : cmd - the struct scsi_cmnd to abort, code - code to set the
- *     host byte of the result field to, if zero DID_ABORTED is 
- *     used.
- *
- * Returns : 0 - success, -1 on failure.
- *
- * XXX - there is no way to abort the command that is currently 
- *      connected, you have to wait for it to complete.  If this is 
- *      a problem, we could implement longjmp() / setjmp(), setjmp()
- *      called where the loop started in NCR5380_main().
- */
-
-static int NCR5380_abort(struct scsi_cmnd *cmd)
-{
-    struct Scsi_Host *instance = cmd->device->host;
-    SETUP_HOSTDATA(instance);
-    struct scsi_cmnd *tmp, **prev;
-    unsigned long flags;
-
-    printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
-    scsi_print_command(cmd);
-
-    NCR5380_print_status (instance);
-
-    local_irq_save(flags);
-    
-    dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
-               NCR5380_read(BUS_AND_STATUS_REG),
-               NCR5380_read(STATUS_REG));
-
-#if 1
-/* 
- * Case 1 : If the command is the currently executing command, 
- * we'll set the aborted flag and return control so that 
- * information transfer routine can exit cleanly.
- */
-
-    if (hostdata->connected == cmd) {
-
-       dprintk(NDEBUG_ABORT, "scsi%d: aborting connected command\n", HOSTNO);
-/*
- * We should perform BSY checking, and make sure we haven't slipped
- * into BUS FREE.
- */
-
-/*     NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
-/* 
- * Since we can't change phases until we've completed the current 
- * handshake, we have to source or sink a byte of data if the current
- * phase is not MSGOUT.
- */
-
-/* 
- * Return control to the executing NCR drive so we can clear the
- * aborted flag and get back into our main loop.
- */ 
-
-       if (do_abort(instance) == 0) {
-         hostdata->aborted = 1;
-         hostdata->connected = NULL;
-         cmd->result = DID_ABORT << 16;
-#ifdef SUPPORT_TAGS
-         cmd_free_tag( cmd );
-#else
-         hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
-#endif
-         local_irq_restore(flags);
-         cmd->scsi_done(cmd);
-         return SUCCESS;
-       } else {
-/*       local_irq_restore(flags); */
-         printk("scsi%d: abort of connected command failed!\n", HOSTNO);
-         return FAILED;
-       } 
-   }
-#endif
-
-/* 
- * Case 2 : If the command hasn't been issued yet, we simply remove it 
- *         from the issue queue.
- */
-    for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue),
-       tmp = (struct scsi_cmnd *) hostdata->issue_queue;
-       tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp))
-       if (cmd == tmp) {
-           REMOVE(5, *prev, tmp, NEXT(tmp));
-           (*prev) = NEXT(tmp);
-           SET_NEXT(tmp, NULL);
-           tmp->result = DID_ABORT << 16;
-           local_irq_restore(flags);
-           dprintk(NDEBUG_ABORT, "scsi%d: abort removed command from issue queue.\n",
-                       HOSTNO);
-           /* Tagged queuing note: no tag to free here, hasn't been assigned
-            * yet... */
-           tmp->scsi_done(tmp);
-           return SUCCESS;
-       }
-
-/* 
- * Case 3 : If any commands are connected, we're going to fail the abort
- *         and let the high level SCSI driver retry at a later time or 
- *         issue a reset.
- *
- *         Timeouts, and therefore aborted commands, will be highly unlikely
- *          and handling them cleanly in this situation would make the common
- *         case of noresets less efficient, and would pollute our code.  So,
- *         we fail.
- */
-
-    if (hostdata->connected) {
-       local_irq_restore(flags);
-       dprintk(NDEBUG_ABORT, "scsi%d: abort failed, command connected.\n", HOSTNO);
-        return FAILED;
-    }
-
-/*
- * Case 4: If the command is currently disconnected from the bus, and 
- *     there are no connected commands, we reconnect the I_T_L or 
- *     I_T_L_Q nexus associated with it, go into message out, and send 
- *      an abort message.
- *
- * This case is especially ugly. In order to reestablish the nexus, we
- * need to call NCR5380_select().  The easiest way to implement this 
- * function was to abort if the bus was busy, and let the interrupt
- * handler triggered on the SEL for reselect take care of lost arbitrations
- * where necessary, meaning interrupts need to be enabled.
- *
- * When interrupts are enabled, the queues may change - so we 
- * can't remove it from the disconnected queue before selecting it
- * because that could cause a failure in hashing the nexus if that 
- * device reselected.
- * 
- * Since the queues may change, we can't use the pointers from when we
- * first locate it.
- *
- * So, we must first locate the command, and if NCR5380_select()
- * succeeds, then issue the abort, relocate the command and remove
- * it from the disconnected queue.
- */
-
-    for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp;
-        tmp = NEXT(tmp)) 
-        if (cmd == tmp) {
-            local_irq_restore(flags);
-           dprintk(NDEBUG_ABORT, "scsi%d: aborting disconnected command.\n", HOSTNO);
-  
-            if (NCR5380_select (instance, cmd, (int) cmd->tag)) 
-               return FAILED;
-
-           dprintk(NDEBUG_ABORT, "scsi%d: nexus reestablished.\n", HOSTNO);
-
-           do_abort (instance);
-
-           local_irq_save(flags);
-           for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue),
-               tmp = (struct scsi_cmnd *) hostdata->disconnected_queue;
-               tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
-                   if (cmd == tmp) {
-                   REMOVE(5, *prev, tmp, NEXT(tmp));
-                   *prev = NEXT(tmp);
-                   SET_NEXT(tmp, NULL);
-                   tmp->result = DID_ABORT << 16;
-                   /* We must unlock the tag/LUN immediately here, since the
-                    * target goes to BUS FREE and doesn't send us another
-                    * message (COMMAND_COMPLETE or the like)
-                    */
-#ifdef SUPPORT_TAGS
-                   cmd_free_tag( tmp );
-#else
-                   hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
-#endif
-                   local_irq_restore(flags);
-                   tmp->scsi_done(tmp);
-                   return SUCCESS;
-               }
-       }
-
-/*
- * Case 5 : If we reached this point, the command was not found in any of 
- *         the queues.
- *
- * We probably reached this point because of an unlikely race condition
- * between the command completing successfully and the abortion code,
- * so we won't panic, but we will notify the user in case something really
- * broke.
- */
-
-    local_irq_restore(flags);
-    printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); 
-
-    return FAILED;
-}
-
-
-/* 
- * Function : int NCR5380_bus_reset(struct scsi_cmnd *cmd)
- * 
- * Purpose : reset the SCSI bus.
- *
- * Returns : SUCCESS or FAILURE
- *
- */ 
-
-static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
-{
-    SETUP_HOSTDATA(cmd->device->host);
-    int           i;
-    unsigned long flags;
-#if defined(RESET_RUN_DONE)
-    struct scsi_cmnd *connected, *disconnected_queue;
-#endif
-
-
-    NCR5380_print_status (cmd->device->host);
-
-    /* get in phase */
-    NCR5380_write( TARGET_COMMAND_REG,
-                  PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
-    /* assert RST */
-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
-    udelay (40);
-    /* reset NCR registers */
-    NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
-    NCR5380_write( MODE_REG, MR_BASE );
-    NCR5380_write( TARGET_COMMAND_REG, 0 );
-    NCR5380_write( SELECT_ENABLE_REG, 0 );
-    /* ++roman: reset interrupt condition! otherwise no interrupts don't get
-     * through anymore ... */
-    (void)NCR5380_read( RESET_PARITY_INTERRUPT_REG );
-
-       /* MSch 20140115 - looking at the generic NCR5380 driver, all of this
-        * should go.
-        * Catch-22: if we don't clear all queues, the SCSI driver lock will
-        * not be released by atari_scsi_reset()!
-        */
-
-#if defined(RESET_RUN_DONE)
-       /* XXX Should now be done by midlevel code, but it's broken XXX */
-       /* XXX see below                                            XXX */
-
-    /* MSch: old-style reset: actually abort all command processing here */
-
-    /* After the reset, there are no more connected or disconnected commands
-     * and no busy units; to avoid problems with re-inserting the commands
-     * into the issue_queue (via scsi_done()), the aborted commands are
-     * remembered in local variables first.
-     */
-    local_irq_save(flags);
-    connected = (struct scsi_cmnd *)hostdata->connected;
-    hostdata->connected = NULL;
-    disconnected_queue = (struct scsi_cmnd *)hostdata->disconnected_queue;
-    hostdata->disconnected_queue = NULL;
-#ifdef SUPPORT_TAGS
-    free_all_tags();
-#endif
-    for( i = 0; i < 8; ++i )
-       hostdata->busy[i] = 0;
-#ifdef REAL_DMA
-    hostdata->dma_len = 0;
-#endif
-    local_irq_restore(flags);
-
-    /* In order to tell the mid-level code which commands were aborted, 
-     * set the command status to DID_RESET and call scsi_done() !!!
-     * This ultimately aborts processing of these commands in the mid-level.
-     */
-
-    if ((cmd = connected)) {
-       dprintk(NDEBUG_ABORT, "scsi%d: reset aborted a connected command\n", H_NO(cmd));
-       cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-       cmd->scsi_done( cmd );
-    }
-
-    for (i = 0; (cmd = disconnected_queue); ++i) {
-       disconnected_queue = NEXT(cmd);
-       SET_NEXT(cmd, NULL);
-       cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
-       cmd->scsi_done( cmd );
-    }
-    if (i > 0)
-       dprintk(NDEBUG_ABORT, "scsi: reset aborted %d disconnected command(s)\n", i);
-
-
-    /* since all commands have been explicitly terminated, we need to tell
-     * the midlevel code that the reset was SUCCESSFUL, and there is no 
-     * need to 'wake up' the commands by a request_sense
-     */
-    return SUCCESS;
-#else /* 1 */
-
-    /* MSch: new-style reset handling: let the mid-level do what it can */
-
-    /* ++guenther: MID-LEVEL IS STILL BROKEN.
-     * Mid-level is supposed to requeue all commands that were active on the
-     * various low-level queues. In fact it does this, but that's not enough
-     * because all these commands are subject to timeout. And if a timeout
-     * happens for any removed command, *_abort() is called but all queues
-     * are now empty. Abort then gives up the falcon lock, which is fatal,
-     * since the mid-level will queue more commands and must have the lock
-     * (it's all happening inside timer interrupt handler!!).
-     * Even worse, abort will return NOT_RUNNING for all those commands not
-     * on any queue, so they won't be retried ...
-     *
-     * Conclusion: either scsi.c disables timeout for all resetted commands
-     * immediately, or we lose!  As of linux-2.0.20 it doesn't.
-     */
-
-    /* After the reset, there are no more connected or disconnected commands
-     * and no busy units; so clear the low-level status here to avoid 
-     * conflicts when the mid-level code tries to wake up the affected 
-     * commands!
-     */
-
-    if (hostdata->issue_queue)
-       dprintk(NDEBUG_ABORT, "scsi%d: reset aborted issued command(s)\n", H_NO(cmd));
-    if (hostdata->connected) 
-       dprintk(NDEBUG_ABORT, "scsi%d: reset aborted a connected command\n", H_NO(cmd));
-    if (hostdata->disconnected_queue)
-       dprintk(NDEBUG_ABORT, "scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
-
-    local_irq_save(flags);
-    hostdata->issue_queue = NULL;
-    hostdata->connected = NULL;
-    hostdata->disconnected_queue = NULL;
-#ifdef SUPPORT_TAGS
-    free_all_tags();
-#endif
-    for( i = 0; i < 8; ++i )
-       hostdata->busy[i] = 0;
-#ifdef REAL_DMA
-    hostdata->dma_len = 0;
-#endif
-    local_irq_restore(flags);
-
-    /* we did no complete reset of all commands, so a wakeup is required */
-    return SUCCESS;
-#endif /* 1 */
-}
-
-/* Local Variables: */
-/* tab-width: 8     */
-/* End:             */
index 9707b7494a89644e99c2629127f7a612ccabf6ec..2a906d1d34baa87703e0541b93ba8512bf09eddf 100644 (file)
  * Generic Generic NCR5380 driver
  *
  * Copyright 1995, Russell King
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
-
-/*
- * This is from mac_scsi.h, but hey, maybe this is useful for Sun3 too! :)
- *
- * Options :
- *
- * PARITY - enable parity checking.  Not supported.
- *
- * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
- *
- * USLEEP - enable support for devices that don't disconnect.  Untested.
- */
-
-#define AUTOSENSE
-
 #include <linux/types.h>
-#include <linux/stddef.h>
-#include <linux/ctype.h>
 #include <linux/delay.h>
-
 #include <linux/module.h>
-#include <linux/signal.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
-
-#include <asm/sun3ints.h>
 #include <asm/dvma.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
 
-/* dma on! */
-#define REAL_DMA
-
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include "sun3_scsi.h"
-#include "NCR5380.h"
 
-extern int sun3_map_test(unsigned long, char *);
+/* Definitions for the core NCR5380 driver. */
 
-#define USE_WRAPPER
-/*#define RESET_BOOT */
-#define DRIVER_SETUP
+#define REAL_DMA
+/* #define SUPPORT_TAGS */
+/* minimum number of bytes to do dma on */
+#define DMA_MIN_SIZE                    129
 
-/*
- * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
- */
-#ifdef BUG
-#undef RESET_BOOT
-#undef DRIVER_SETUP
-#endif
+/* #define MAX_TAGS                     32 */
 
-/* #define SUPPORT_TAGS */
+#define NCR5380_implementation_fields   /* none */
 
-#ifdef SUN3_SCSI_VME
-#define ENABLE_IRQ()
-#else
-#define        ENABLE_IRQ()    enable_irq( IRQ_SUN3_SCSI ); 
-#endif
+#define NCR5380_read(reg)               sun3scsi_read(reg)
+#define NCR5380_write(reg, value)       sun3scsi_write(reg, value)
+
+#define NCR5380_queue_command           sun3scsi_queue_command
+#define NCR5380_bus_reset               sun3scsi_bus_reset
+#define NCR5380_abort                   sun3scsi_abort
+#define NCR5380_show_info               sun3scsi_show_info
+#define NCR5380_info                    sun3scsi_info
 
+#define NCR5380_dma_read_setup(instance, data, count) \
+        sun3scsi_dma_setup(data, count, 0)
+#define NCR5380_dma_write_setup(instance, data, count) \
+        sun3scsi_dma_setup(data, count, 1)
+#define NCR5380_dma_residual(instance) \
+        sun3scsi_dma_residual(instance)
+#define NCR5380_dma_xfer_len(instance, cmd, phase) \
+        sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO))
 
-static irqreturn_t scsi_sun3_intr(int irq, void *dummy);
-static inline unsigned char sun3scsi_read(int reg);
-static inline void sun3scsi_write(int reg, int value);
+#define NCR5380_acquire_dma_irq(instance)    (1)
+#define NCR5380_release_dma_irq(instance)
+
+#include "NCR5380.h"
+
+
+extern int sun3_map_test(unsigned long, char *);
 
 static int setup_can_queue = -1;
 module_param(setup_can_queue, int, 0);
@@ -117,9 +86,7 @@ module_param(setup_use_tagged_queuing, int, 0);
 static int setup_hostid = -1;
 module_param(setup_hostid, int, 0);
 
-static struct scsi_cmnd *sun3_dma_setup_done = NULL;
-
-#define        RESET_RUN_DONE
+/* #define RESET_BOOT */
 
 #define        AFTER_RESET_DELAY       (HZ/2)
 
@@ -129,18 +96,15 @@ static struct scsi_cmnd *sun3_dma_setup_done = NULL;
 /* dvma buffer to allocate -- 32k should hopefully be more than sufficient */
 #define SUN3_DVMA_BUFSIZE 0xe000
 
-/* minimum number of bytes to do dma on */
-#define SUN3_DMA_MINSIZE 128
-
-static volatile unsigned char *sun3_scsi_regp;
+static struct scsi_cmnd *sun3_dma_setup_done;
+static unsigned char *sun3_scsi_regp;
 static volatile struct sun3_dma_regs *dregs;
-#ifndef SUN3_SCSI_VME
-static struct sun3_udc_regs *udc_regs = NULL;
-#endif
+static struct sun3_udc_regs *udc_regs;
 static unsigned char *sun3_dma_orig_addr = NULL;
 static unsigned long sun3_dma_orig_count = 0;
 static int sun3_dma_active = 0;
 static unsigned long last_residual = 0;
+static struct Scsi_Host *default_instance;
 
 /*
  * NCR 5380 register access functions
@@ -148,12 +112,12 @@ static unsigned long last_residual = 0;
 
 static inline unsigned char sun3scsi_read(int reg)
 {
-       return( sun3_scsi_regp[reg] );
+       return in_8(sun3_scsi_regp + reg);
 }
 
 static inline void sun3scsi_write(int reg, int value)
 {
-       sun3_scsi_regp[reg] = value;
+       out_8(sun3_scsi_regp + reg, value);
 }
 
 #ifndef SUN3_SCSI_VME
@@ -180,213 +144,10 @@ static inline void sun3_udc_write(unsigned short val, unsigned char reg)
 }
 #endif
 
-/*
- * XXX: status debug
- */
-static struct Scsi_Host *default_instance;
-
-/*
- * Function : int sun3scsi_detect(struct scsi_host_template * tpnt)
- *
- * Purpose : initializes mac NCR5380 driver based on the
- *     command line / compile time port and irq definitions.
- *
- * Inputs : tpnt - template for this SCSI adapter.
- *
- * Returns : 1 if a host adapter was found, 0 if not.
- *
- */
-static int __init sun3scsi_detect(struct scsi_host_template *tpnt)
-{
-       unsigned long ioaddr, irq;
-       static int called = 0;
-       struct Scsi_Host *instance;
-#ifdef SUN3_SCSI_VME
-       int i;
-       unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI,
-                                  IOBASE_SUN3_VMESCSI + 0x4000,
-                                  0 };
-       unsigned long vecs[3] = { SUN3_VEC_VMESCSI0,
-                                 SUN3_VEC_VMESCSI1,
-                                 0 };
-#endif
-
-       /* check that this machine has an onboard 5380 */
-       switch(idprom->id_machtype) {
-#ifdef SUN3_SCSI_VME
-       case SM_SUN3|SM_3_160:
-       case SM_SUN3|SM_3_260:
-               break;
-#else
-       case SM_SUN3|SM_3_50:
-       case SM_SUN3|SM_3_60:
-               break;
-#endif
-
-       default:
-               return 0;
-       }
-
-       if(called)
-               return 0;
-
-#ifdef SUN3_SCSI_VME
-       tpnt->proc_name = "Sun3 5380 VME SCSI";
-#else
-       tpnt->proc_name = "Sun3 5380 SCSI";
-#endif
-
-       /* setup variables */
-       tpnt->can_queue =
-               (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
-       tpnt->cmd_per_lun =
-               (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
-       tpnt->sg_tablesize = 
-               (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
-
-       if (setup_hostid >= 0)
-               tpnt->this_id = setup_hostid;
-       else {
-               /* use 7 as default */
-               tpnt->this_id = 7;
-       }
-
-#ifdef SUN3_SCSI_VME
-       ioaddr = 0;
-       for (i = 0; addrs[i] != 0; i++) {
-               unsigned char x;
-
-               ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE,
-                                                    SUN3_PAGE_TYPE_VME16);
-               irq = vecs[i];
-               sun3_scsi_regp = (unsigned char *)ioaddr;
-
-               dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
-
-               if (sun3_map_test((unsigned long)dregs, &x)) {
-                       unsigned short oldcsr;
-
-                       oldcsr = dregs->csr;
-                       dregs->csr = 0;
-                       udelay(SUN3_DMA_DELAY);
-                       if (dregs->csr == 0x1400)
-                               break;
-
-                       dregs->csr = oldcsr;
-               }
-
-               iounmap((void *)ioaddr);
-               ioaddr = 0;
-       }
-
-       if (!ioaddr)
-               return 0;
-#else
-       irq = IRQ_SUN3_SCSI;
-       ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE);
-       sun3_scsi_regp = (unsigned char *)ioaddr;
-
-       dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
-
-       if((udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs)))
-          == NULL) {
-            printk("SUN3 Scsi couldn't allocate DVMA memory!\n");
-            return 0;
-       }
-#endif
-#ifdef SUPPORT_TAGS
-       if (setup_use_tagged_queuing < 0)
-               setup_use_tagged_queuing = USE_TAGGED_QUEUING;
-#endif
-
-       instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-       if(instance == NULL)
-               return 0;
-               
-       default_instance = instance;
-
-        instance->io_port = (unsigned long) ioaddr;
-       instance->irq = irq;
-
-       NCR5380_init(instance, 0);
-
-       instance->n_io_port = 32;
-
-        ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
-
-       if (request_irq(instance->irq, scsi_sun3_intr,
-                            0, "Sun3SCSI-5380", instance)) {
-#ifndef REAL_DMA
-               printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-                      instance->host_no, instance->irq);
-               instance->irq = SCSI_IRQ_NONE;
-#else
-               printk("scsi%d: IRQ%d not free, bailing out\n",
-                      instance->host_no, instance->irq);
-               return 0;
-#endif
-       }
-       
-       pr_info("scsi%d: %s at port %lX irq", instance->host_no,
-               tpnt->proc_name, instance->io_port);
-       if (instance->irq == SCSI_IRQ_NONE)
-               printk ("s disabled");
-       else
-               printk (" %d", instance->irq);
-       printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
-              instance->can_queue, instance->cmd_per_lun,
-              SUN3SCSI_PUBLIC_RELEASE);
-       printk("\nscsi%d:", instance->host_no);
-       NCR5380_print_options(instance);
-       printk("\n");
-
-       dregs->csr = 0;
-       udelay(SUN3_DMA_DELAY);
-       dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
-       udelay(SUN3_DMA_DELAY);
-       dregs->fifo_count = 0;
-#ifdef SUN3_SCSI_VME
-       dregs->fifo_count_hi = 0;
-       dregs->dma_addr_hi = 0;
-       dregs->dma_addr_lo = 0;
-       dregs->dma_count_hi = 0;
-       dregs->dma_count_lo = 0;
-
-       dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
-#endif
-
-       called = 1;
-
-#ifdef RESET_BOOT
-       sun3_scsi_reset_boot(instance);
-#endif
-
-       return 1;
-}
-
-int sun3scsi_release (struct Scsi_Host *shpnt)
-{
-       if (shpnt->irq != SCSI_IRQ_NONE)
-               free_irq(shpnt->irq, shpnt);
-
-       iounmap((void *)sun3_scsi_regp);
-
-       NCR5380_exit(shpnt);
-       return 0;
-}
-
 #ifdef RESET_BOOT
-/*
- * Our 'bus reset on boot' function
- */
-
 static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
 {
        unsigned long end;
-
-       NCR5380_local_declare();
-       NCR5380_setup(instance);
        
        /*
         * Do a SCSI reset to clean up the bus during initialization. No
@@ -422,11 +183,6 @@ static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
 }
 #endif
 
-static const char *sun3scsi_info(struct Scsi_Host *spnt)
-{
-    return "";
-}
-
 // safe bits for the CSR
 #define CSR_GOOD 0x060f
 
@@ -468,7 +224,6 @@ static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
 void sun3_sun3_debug (void)
 {
        unsigned long flags;
-       NCR5380_local_declare();
 
        if (default_instance) {
                        local_irq_save(flags);
@@ -732,25 +487,200 @@ static int sun3scsi_dma_finish(int write_flag)
 
 }
        
-#include "sun3_NCR5380.c"
+#include "atari_NCR5380.c"
 
-static struct scsi_host_template driver_template = {
+#ifdef SUN3_SCSI_VME
+#define SUN3_SCSI_NAME          "Sun3 NCR5380 VME SCSI"
+#define DRV_MODULE_NAME         "sun3_scsi_vme"
+#else
+#define SUN3_SCSI_NAME          "Sun3 NCR5380 SCSI"
+#define DRV_MODULE_NAME         "sun3_scsi"
+#endif
+
+#define PFX                     DRV_MODULE_NAME ": "
+
+static struct scsi_host_template sun3_scsi_template = {
+       .module                 = THIS_MODULE,
+       .proc_name              = DRV_MODULE_NAME,
        .show_info              = sun3scsi_show_info,
        .name                   = SUN3_SCSI_NAME,
-       .detect                 = sun3scsi_detect,
-       .release                = sun3scsi_release,
        .info                   = sun3scsi_info,
        .queuecommand           = sun3scsi_queue_command,
        .eh_abort_handler       = sun3scsi_abort,
        .eh_bus_reset_handler   = sun3scsi_bus_reset,
-       .can_queue              = CAN_QUEUE,
+       .can_queue              = 16,
        .this_id                = 7,
-       .sg_tablesize           = SG_TABLESIZE,
-       .cmd_per_lun            = CMD_PER_LUN,
+       .sg_tablesize           = SG_NONE,
+       .cmd_per_lun            = 2,
        .use_clustering         = DISABLE_CLUSTERING
 };
 
+static int __init sun3_scsi_probe(struct platform_device *pdev)
+{
+       struct Scsi_Host *instance;
+       int error;
+       struct resource *irq, *mem;
+       unsigned char *ioaddr;
+       int host_flags = 0;
+#ifdef SUN3_SCSI_VME
+       int i;
+#endif
+
+       if (setup_can_queue > 0)
+               sun3_scsi_template.can_queue = setup_can_queue;
+       if (setup_cmd_per_lun > 0)
+               sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun;
+       if (setup_sg_tablesize >= 0)
+               sun3_scsi_template.sg_tablesize = setup_sg_tablesize;
+       if (setup_hostid >= 0)
+               sun3_scsi_template.this_id = setup_hostid & 7;
+
+#ifdef SUN3_SCSI_VME
+       ioaddr = NULL;
+       for (i = 0; i < 2; i++) {
+               unsigned char x;
+
+               irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               if (!irq || !mem)
+                       break;
+
+               ioaddr = sun3_ioremap(mem->start, resource_size(mem),
+                                     SUN3_PAGE_TYPE_VME16);
+               dregs = (struct sun3_dma_regs *)(ioaddr + 8);
+
+               if (sun3_map_test((unsigned long)dregs, &x)) {
+                       unsigned short oldcsr;
+
+                       oldcsr = dregs->csr;
+                       dregs->csr = 0;
+                       udelay(SUN3_DMA_DELAY);
+                       if (dregs->csr == 0x1400)
+                               break;
+
+                       dregs->csr = oldcsr;
+               }
+
+               iounmap(ioaddr);
+               ioaddr = NULL;
+       }
+       if (!ioaddr)
+               return -ENODEV;
+#else
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!irq || !mem)
+               return -ENODEV;
+
+       ioaddr = ioremap(mem->start, resource_size(mem));
+       dregs = (struct sun3_dma_regs *)(ioaddr + 8);
+
+       udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs));
+       if (!udc_regs) {
+               pr_err(PFX "couldn't allocate DVMA memory!\n");
+               iounmap(ioaddr);
+               return -ENOMEM;
+       }
+#endif
+
+       sun3_scsi_regp = ioaddr;
+
+       instance = scsi_host_alloc(&sun3_scsi_template,
+                                  sizeof(struct NCR5380_hostdata));
+       if (!instance) {
+               error = -ENOMEM;
+               goto fail_alloc;
+       }
+       default_instance = instance;
+
+       instance->io_port = (unsigned long)ioaddr;
+       instance->irq = irq->start;
+
+#ifdef SUPPORT_TAGS
+       host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
+#endif
+
+       NCR5380_init(instance, host_flags);
+
+       error = request_irq(instance->irq, scsi_sun3_intr, 0,
+                           "NCR5380", instance);
+       if (error) {
+#ifdef REAL_DMA
+               pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n",
+                      instance->host_no, instance->irq);
+               goto fail_irq;
+#else
+               pr_warn(PFX "scsi%d: IRQ %d not free, interrupts disabled\n",
+                       instance->host_no, instance->irq);
+               instance->irq = NO_IRQ;
+#endif
+       }
+
+       dregs->csr = 0;
+       udelay(SUN3_DMA_DELAY);
+       dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
+       udelay(SUN3_DMA_DELAY);
+       dregs->fifo_count = 0;
+#ifdef SUN3_SCSI_VME
+       dregs->fifo_count_hi = 0;
+       dregs->dma_addr_hi = 0;
+       dregs->dma_addr_lo = 0;
+       dregs->dma_count_hi = 0;
+       dregs->dma_count_lo = 0;
+
+       dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
+#endif
+
+#ifdef RESET_BOOT
+       sun3_scsi_reset_boot(instance);
+#endif
+
+       error = scsi_add_host(instance, NULL);
+       if (error)
+               goto fail_host;
+
+       platform_set_drvdata(pdev, instance);
+
+       scsi_scan_host(instance);
+       return 0;
+
+fail_host:
+       if (instance->irq != NO_IRQ)
+               free_irq(instance->irq, instance);
+fail_irq:
+       NCR5380_exit(instance);
+       scsi_host_put(instance);
+fail_alloc:
+       if (udc_regs)
+               dvma_free(udc_regs);
+       iounmap(sun3_scsi_regp);
+       return error;
+}
+
+static int __exit sun3_scsi_remove(struct platform_device *pdev)
+{
+       struct Scsi_Host *instance = platform_get_drvdata(pdev);
+
+       scsi_remove_host(instance);
+       if (instance->irq != NO_IRQ)
+               free_irq(instance->irq, instance);
+       NCR5380_exit(instance);
+       scsi_host_put(instance);
+       if (udc_regs)
+               dvma_free(udc_regs);
+       iounmap(sun3_scsi_regp);
+       return 0;
+}
+
+static struct platform_driver sun3_scsi_driver = {
+       .remove = __exit_p(sun3_scsi_remove),
+       .driver = {
+               .name   = DRV_MODULE_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
 
-#include "scsi_module.c"
+module_platform_driver_probe(sun3_scsi_driver, sun3_scsi_probe);
 
+MODULE_ALIAS("platform:" DRV_MODULE_NAME);
 MODULE_LICENSE("GPL");
index e96a37cf06ac117f45246e4f60e6745384a0a119..d22745fae328d46804d85bd432c7235320708469 100644 (file)
  *     (Unix and Linux consulting and custom programming)
  *     drew@colorado.edu
  *      +1 (303) 440-4894
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 #ifndef SUN3_SCSI_H
 #define SUN3_SCSI_H
 
-#define SUN3SCSI_PUBLIC_RELEASE 1
-
-/*
- * Int: level 2 autovector
- * IO: type 1, base 0x00140000, 5 bits phys space: A<4..0>
- */
-#define IRQ_SUN3_SCSI 2
-#define IOBASE_SUN3_SCSI 0x00140000
-
-#define IOBASE_SUN3_VMESCSI 0xff200000
-
-static int sun3scsi_abort(struct scsi_cmnd *);
-static int sun3scsi_detect (struct scsi_host_template *);
-static const char *sun3scsi_info (struct Scsi_Host *);
-static int sun3scsi_bus_reset(struct scsi_cmnd *);
-static int sun3scsi_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int sun3scsi_release (struct Scsi_Host *);
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#ifndef SG_TABLESIZE
-#define SG_TABLESIZE SG_NONE
-#endif
-
-#ifndef MAX_TAGS
-#define MAX_TAGS 32
-#endif
-
-#ifndef USE_TAGGED_QUEUING
-#define        USE_TAGGED_QUEUING 1
-#endif
-
-#include <scsi/scsicam.h>
-
-#ifdef SUN3_SCSI_VME
-#define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI"
-#else
-#define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI"
-#endif
-
-#define NCR5380_implementation_fields \
-    int port, ctrl
-
-#define NCR5380_local_declare() \
-        struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
-        _instance = instance
-
-#define NCR5380_read(reg) sun3scsi_read(reg)
-#define NCR5380_write(reg, value) sun3scsi_write(reg, value)
-
-#define NCR5380_intr sun3scsi_intr
-#define NCR5380_queue_command sun3scsi_queue_command
-#define NCR5380_bus_reset sun3scsi_bus_reset
-#define NCR5380_abort sun3scsi_abort
-#define NCR5380_show_info sun3scsi_show_info
-#define NCR5380_dma_xfer_len(i, cmd, phase) \
-        sun3scsi_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
-
-#define NCR5380_dma_write_setup(instance, data, count) sun3scsi_dma_setup(data, count, 1)
-#define NCR5380_dma_read_setup(instance, data, count) sun3scsi_dma_setup(data, count, 0)
-#define NCR5380_dma_residual sun3scsi_dma_residual
-
 /* additional registers - mainly DMA control regs */
 /* these start at regbase + 8 -- directly after the NCR regs */
 struct sun3_dma_regs {
index e59e6f96b7253ddc58e51da5401bb9f9731cc309..5d00e514ff28aa59d940c69bfa6da4199bdda97a 100644 (file)
@@ -820,9 +820,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev)
        if (reqtags > SYM_CONF_MAX_TAG)
                reqtags = SYM_CONF_MAX_TAG;
        depth_to_use = reqtags ? reqtags : 1;
-       scsi_adjust_queue_depth(sdev,
-                               sdev->tagged_supported ? MSG_SIMPLE_TAG : 0,
-                               depth_to_use);
+       scsi_change_queue_depth(sdev, depth_to_use);
        lp->s.scdev_depth = depth_to_use;
        sym_tune_dev_queuing(tp, sdev->lun, reqtags);
 
index 8cc80931df14990860e1e1525d83dd3d9c0dbf57..87828acbf7c63601d618909a59028a3b4ffa6372 100644 (file)
@@ -1,4 +1,3 @@
-#define AUTOSENSE
 #define PSEUDO_DMA
 
 /*
@@ -12,8 +11,6 @@
  *     drew@colorado.edu
  *      +1 (303) 440-4894
  *
- * DISTRIBUTION RELEASE 3.
- *
  * For more information, please consult 
  *
  * Trantor Systems, Ltd.
  * 5415 Randall Place
  * Fremont, CA 94538
  * 1+ (415) 770-1400, FAX 1+ (415) 770-9910
- * 
- * and 
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 /*
- * Options : 
- * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
- *      for commands that return with a CHECK CONDITION status. 
- *
- * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
- * increase compared to polled I/O.
- *
- * PARITY - enable parity checking.  Not supported.
- * 
- * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
- *
- *
- * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  You
- *          only really want to use this if you're having a problem with
- *          dropped characters during high speed communications, and even
- *          then, you're going to be better off twiddling with transfersize.
- *
- * USLEEP - enable support for devices that don't disconnect.  Untested.
- *
  * The card is detected and initialized in one of several ways : 
  * 1.  Autoprobe (default) - since the board is memory mapped, 
  *     a BIOS signature is scanned for to locate the registers.
 #include <linux/module.h>
 #include <linux/delay.h>
 
-#include "scsi.h"
 #include <scsi/scsi_host.h>
 #include "t128.h"
 #define AUTOPROBE_IRQ
@@ -148,6 +113,7 @@ static struct signature {
 
 #define NO_SIGNATURES ARRAY_SIZE(signatures)
 
+#ifndef MODULE
 /*
  * Function : t128_setup(char *str, int *ints)
  *
@@ -158,9 +124,13 @@ static struct signature {
  *
  */
 
-void __init t128_setup(char *str, int *ints){
+static int __init t128_setup(char *str)
+{
     static int commandline_current = 0;
     int i;
+    int ints[10];
+
+    get_options(str, ARRAY_SIZE(ints), ints);
     if (ints[0] != 2) 
        printk("t128_setup : usage t128=address,irq\n");
     else 
@@ -174,8 +144,12 @@ void __init t128_setup(char *str, int *ints){
                }
            ++commandline_current;
        }
+    return 1;
 }
 
+__setup("t128=", t128_setup);
+#endif
+
 /* 
  * Function : int t128_detect(struct scsi_host_template * tpnt)
  *
@@ -189,17 +163,14 @@ void __init t128_setup(char *str, int *ints){
  *
  */
 
-int __init t128_detect(struct scsi_host_template * tpnt){
+static int __init t128_detect(struct scsi_host_template *tpnt)
+{
     static int current_override = 0, current_base = 0;
     struct Scsi_Host *instance;
     unsigned long base;
     void __iomem *p;
     int sig, count;
 
-    tpnt->proc_name = "t128";
-    tpnt->show_info = t128_show_info;
-    tpnt->write_info = t128_write_info;
-
     for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
        base = 0;
        p = NULL;
@@ -254,15 +225,19 @@ found:
        else 
            instance->irq = NCR5380_probe_irq(instance, T128_IRQS);
 
-       if (instance->irq != SCSI_IRQ_NONE) 
+       /* Compatibility with documented NCR5380 kernel parameters */
+       if (instance->irq == 255)
+               instance->irq = NO_IRQ;
+
+       if (instance->irq != NO_IRQ)
            if (request_irq(instance->irq, t128_intr, 0, "t128",
                            instance)) {
                printk("scsi%d : IRQ%d not free, interrupts disabled\n", 
                    instance->host_no, instance->irq);
-               instance->irq = SCSI_IRQ_NONE;
+               instance->irq = NO_IRQ;
            } 
 
-       if (instance->irq == SCSI_IRQ_NONE) {
+       if (instance->irq == NO_IRQ) {
            printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
            printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
        }
@@ -271,16 +246,6 @@ found:
        printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
 #endif
 
-       printk("scsi%d : at 0x%08lx", instance->host_no, instance->base);
-       if (instance->irq == SCSI_IRQ_NONE)
-           printk (" interrupts disabled");
-       else 
-           printk (" irq %d", instance->irq);
-       printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
-           CAN_QUEUE, CMD_PER_LUN, T128_PUBLIC_RELEASE);
-       NCR5380_print_options(instance);
-       printk("\n");
-
        ++current_override;
        ++count;
     }
@@ -291,7 +256,7 @@ static int t128_release(struct Scsi_Host *shost)
 {
        NCR5380_local_declare();
        NCR5380_setup(shost);
-       if (shost->irq)
+       if (shost->irq != NO_IRQ)
                free_irq(shost->irq, shost);
        NCR5380_exit(shost);
        if (shost->io_port && shost->n_io_port)
@@ -321,8 +286,8 @@ static int t128_release(struct Scsi_Host *shost)
  * and matching the H_C_S coordinates to what DOS uses.
  */
 
-int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev,
-               sector_t capacity, int * ip)
+static int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+                          sector_t capacity, int *ip)
 {
   ip[0] = 64;
   ip[1] = 32;
@@ -430,6 +395,10 @@ static struct scsi_host_template driver_template = {
        .name           = "Trantor T128/T128F/T228",
        .detect         = t128_detect,
        .release        = t128_release,
+       .proc_name      = "t128",
+       .show_info      = t128_show_info,
+       .write_info     = t128_write_info,
+       .info           = t128_info,
        .queuecommand   = t128_queue_command,
        .eh_abort_handler = t128_abort,
        .eh_bus_reset_handler    = t128_bus_reset,
index fd68cecc62afa9aee9403deebe9822d47afd6f25..2c7371454dfd40cf5d398f64c9072d5f11f9e03d 100644 (file)
@@ -8,8 +8,6 @@
  *     drew@colorado.edu
  *      +1 (303) 440-4894
  *
- * DISTRIBUTION RELEASE 3.
- *
  * For more information, please consult
  *
  * Trantor Systems, Ltd.
  * 5415 Randall Place
  * Fremont, CA 94538
  * 1+ (415) 770-1400, FAX 1+ (415) 770-9910
- *
- * and
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
  */
 
 #ifndef T128_H
 #define T128_H
 
-#define T128_PUBLIC_RELEASE 3
-
 #define TDEBUG         0
 #define TDEBUG_INIT    0x1
 #define TDEBUG_TRANSFER 0x2
 #define T_DATA_REG_OFFSET      0x1e00  /* rw 512 bytes long */
 
 #ifndef ASM
-static int t128_abort(struct scsi_cmnd *);
-static int t128_biosparam(struct scsi_device *, struct block_device *,
-                         sector_t, int*);
-static int t128_detect(struct scsi_host_template *);
-static int t128_queue_command(struct Scsi_Host *, struct scsi_cmnd *);
-static int t128_bus_reset(struct scsi_cmnd *);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 2
@@ -134,6 +112,7 @@ static int t128_bus_reset(struct scsi_cmnd *);
 #define NCR5380_queue_command t128_queue_command
 #define NCR5380_abort t128_abort
 #define NCR5380_bus_reset t128_bus_reset
+#define NCR5380_info t128_info
 #define NCR5380_show_info t128_show_info
 #define NCR5380_write_info t128_write_info
 
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
deleted file mode 100644 (file)
index 7645757..0000000
+++ /dev/null
@@ -1,2620 +0,0 @@
-/************************************************************************
- *     FILE NAME : TMSCSIM.C                                           *
- *          BY   : C.L. Huang,  ching@tekram.com.tw                    *
- *     Description: Device Driver for Tekram DC-390(T) PCI SCSI        *
- *                  Bus Master Host Adapter                            *
- * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.                  *
- ************************************************************************
- * (C) Copyright: put under GNU GPL in 10/96                           *
- *                             (see Documentation/scsi/tmscsim.txt)    *
- ************************************************************************
- * $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $                *
- *     Enhancements and bugfixes by                                    *
- *     Kurt Garloff <kurt@garloff.de>  <garloff@suse.de>               *
- ************************************************************************
- *     HISTORY:                                                        *
- *                                                                     *
- *     REV#    DATE    NAME    DESCRIPTION                             *
- *     1.00  96/04/24  CLH     First release                           *
- *     1.01  96/06/12  CLH     Fixed bug of Media Change for Removable *
- *                             Device, scan all LUN. Support Pre2.0.10 *
- *     1.02  96/06/18  CLH     Fixed bug of Command timeout ...        *
- *     1.03  96/09/25  KG      Added tmscsim_proc_info()               *
- *     1.04  96/10/11  CLH     Updating for support KV 2.0.x           *
- *     1.05  96/10/18  KG      Fixed bug in DC390_abort(null ptr deref)*
- *     1.06  96/10/25  KG      Fixed module support                    *
- *     1.07  96/11/09  KG      Fixed tmscsim_proc_info()               *
- *     1.08  96/11/18  KG      Fixed null ptr in DC390_Disconnect()    *
- *     1.09  96/11/30  KG      Added register the allocated IO space   *
- *     1.10  96/12/05  CLH     Modified tmscsim_proc_info(), and reset *
- *                             pending interrupt in DC390_detect()     *
- *     1.11  97/02/05  KG/CLH  Fixeds problem with partitions greater  *
- *                             than 1GB                                *
- *     1.12  98/02/15  MJ      Rewritten PCI probing                   *
- *     1.13  98/04/08  KG      Support for non DC390, __initfunc decls,*
- *                             changed max devs from 10 to 16          *
- *     1.14a 98/05/05  KG      Dynamic DCB allocation, add-single-dev  *
- *                             for LUNs if LUN_SCAN (BIOS) not set     *
- *                             runtime config using /proc interface    *
- *     1.14b 98/05/06  KG      eliminated cli (); sti (); spinlocks    *
- *     1.14c 98/05/07  KG      2.0.x compatibility                     *
- *     1.20a 98/05/07  KG      changed names of funcs to be consistent *
- *                             DC390_ (entry points), dc390_ (internal)*
- *                             reworked locking                        *
- *     1.20b 98/05/12  KG      bugs: version, kfree, _ctmp             *
- *                             debug output                            *
- *     1.20c 98/05/12  KG      bugs: kfree, parsing, EEpromDefaults    *
- *     1.20d 98/05/14  KG      bugs: list linkage, clear flag after    *
- *                             reset on startup, code cleanup          *
- *     1.20e 98/05/15  KG      spinlock comments, name space cleanup   *
- *                             pLastDCB now part of ACB structure      *
- *                             added stats, timeout for 2.1, TagQ bug  *
- *                             RESET and INQUIRY interface commands    *
- *     1.20f 98/05/18  KG      spinlocks fixes, max_lun fix, free DCBs *
- *                             for missing LUNs, pending int           *
- *     1.20g 98/05/19  KG      Clean up: Avoid short                   *
- *     1.20h 98/05/21  KG      Remove AdaptSCSIID, max_lun ...         *
- *     1.20i 98/05/21  KG      Aiiie: Bug with TagQMask                *
- *     1.20j 98/05/24  KG      Handle STAT_BUSY, handle pACB->pLinkDCB *
- *                             == 0 in remove_dev and DoingSRB_Done    *
- *     1.20k 98/05/25  KG      DMA_INT (experimental)                  *
- *     1.20l 98/05/27  KG      remove DMA_INT; DMA_IDLE cmds added;    *
- *     1.20m 98/06/10  KG      glitch configurable; made some global   *
- *                             vars part of ACB; use DC390_readX       *
- *     1.20n 98/06/11  KG      startup params                          *
- *     1.20o 98/06/15  KG      added TagMaxNum to boot/module params   *
- *                             Device Nr -> Idx, TagMaxNum power of 2  *
- *     1.20p 98/06/17  KG      Docu updates. Reset depends on settings *
- *                             pci_set_master added; 2.0.xx: pcibios_* *
- *                             used instead of MechNum things ...      *
- *     1.20q 98/06/23  KG      Changed defaults. Added debug code for  *
- *                             removable media and fixed it. TagMaxNum *
- *                             fixed for DC390. Locking: ACB, DRV for  *
- *                             better IRQ sharing. Spelling: Queueing  *
- *                             Parsing and glitch_cfg changes. Display *
- *                             real SyncSpeed value. Made DisConn      *
- *                             functional (!)                          *
- *     1.20r 98/06/30  KG      Debug macros, allow disabling DsCn, set *
- *                             BIT4 in CtrlR4, EN_PAGE_INT, 2.0 module *
- *                             param -1 fixed.                         *
- *     1.20s 98/08/20  KG      Debug info on abort(), try to check PCI,*
- *                             phys_to_bus instead of phys_to_virt,    *
- *                             fixed sel. process, fixed locking,      *
- *                             added MODULE_XXX infos, changed IRQ     *
- *                             request flags, disable DMA_INT          *
- *     1.20t 98/09/07  KG      TagQ report fixed; Write Erase DMA Stat;*
- *                             initfunc -> __init; better abort;       *
- *                             Timeout for XFER_DONE & BLAST_COMPLETE; *
- *                             Allow up to 33 commands being processed *
- *     2.0a  98/10/14  KG      Max Cmnds back to 17. DMA_Stat clearing *
- *                             all flags. Clear within while() loops   *
- *                             in DataIn_0/Out_0. Null ptr in dumpinfo *
- *                             for pSRB==0. Better locking during init.*
- *                             bios_param() now respects part. table.  *
- *     2.0b  98/10/24  KG      Docu fixes. Timeout Msg in DMA Blast.   *
- *                             Disallow illegal idx in INQUIRY/REMOVE  *
- *     2.0c  98/11/19  KG      Cleaned up detect/init for SMP boxes,   *
- *                             Write Erase DMA (1.20t) caused problems *
- *     2.0d  98/12/25  KG      Christmas release ;-) Message handling  *
- *                             completely reworked. Handle target ini- *
- *                             tiated SDTR correctly.                  *
- *     2.0d1 99/01/25  KG      Try to handle RESTORE_PTR               *
- *     2.0d2 99/02/08  KG      Check for failure of kmalloc, correct   *
- *                             inclusion of scsicam.h, DelayReset      *
- *     2.0d3 99/05/31  KG      DRIVER_OK -> DID_OK, DID_NO_CONNECT,    *
- *                             detect Target mode and warn.            *
- *                             pcmd->result handling cleaned up.       *
- *     2.0d4 99/06/01  KG      Cleaned selection process. Found bug    *
- *                             which prevented more than 16 tags. Now: *
- *                             24. SDTR cleanup. Cleaner multi-LUN     *
- *                             handling. Don't modify ControlRegs/FIFO *
- *                             when connected.                         *
- *     2.0d5 99/06/01  KG      Clear DevID, Fix INQUIRY after cfg chg. *
- *     2.0d6 99/06/02  KG      Added ADD special command to allow cfg. *
- *                             before detection. Reset SYNC_NEGO_DONE  *
- *                             after a bus reset.                      *
- *     2.0d7 99/06/03  KG      Fixed bugs wrt add,remove commands      *
- *     2.0d8 99/06/04  KG      Removed copying of cmnd into CmdBlock.  *
- *                             Fixed Oops in _release().               *
- *     2.0d9 99/06/06  KG      Also tag queue INQUIRY, T_U_R, ...      *
- *                             Allow arb. no. of Tagged Cmnds. Max 32  *
- *     2.0d1099/06/20  KG      TagMaxNo changes now honoured! Queueing *
- *                             clearified (renamed ..) TagMask handling*
- *                             cleaned.                                *
- *     2.0d1199/06/28  KG      cmd->result now identical to 2.0d2      *
- *     2.0d1299/07/04  KG      Changed order of processing in IRQ      *
- *     2.0d1399/07/05  KG      Don't update DCB fields if removed      *
- *     2.0d1499/07/05  KG      remove_dev: Move kfree() to the end     *
- *     2.0d1599/07/12  KG      use_new_eh_code: 0, ULONG -> UINT where *
- *                             appropriate                             *
- *     2.0d1699/07/13  KG      Reenable StartSCSI interrupt, Retry msg *
- *     2.0d1799/07/15  KG      Remove debug msg. Disable recfg. when   *
- *                             there are queued cmnds                  *
- *     2.0d1899/07/18  KG      Selection timeout: Don't requeue        *
- *     2.0d1999/07/18  KG      Abort: Only call scsi_done if dequeued  *
- *     2.0d2099/07/19  KG      Rst_Detect: DoingSRB_Done               *
- *     2.0d2199/08/15  KG      dev_id for request/free_irq, cmnd[0] for*
- *                             RETRY, SRBdone does DID_ABORT for the   *
- *                             cmd passed by DC390_reset()             *
- *     2.0d2299/08/25  KG      dev_id fixed. can_queue: 42             *
- *     2.0d2399/08/25  KG      Removed some debugging code. dev_id     *
- *                             now is set to pACB. Use u8,u16,u32.     *
- *     2.0d2499/11/14  KG      Unreg. I/O if failed IRQ alloc. Call    *
- *                             done () w/ DID_BAD_TARGET in case of    *
- *                             missing DCB. We are old EH!!            *
- *     2.0d2500/01/15  KG      2.3.3x compat from Andreas Schultz      *
- *                             set unique_id. Disable RETRY message.   *
- *     2.0d2600/01/29  KG      Go to new EH.                           *
- *     2.0d2700/01/31  KG      ... but maintain 2.0 compat.            *
- *                             and fix DCB freeing                     *
- *     2.0d2800/02/14  KG      Queue statistics fixed, dump special cmd*
- *                             Waiting_Timer for failed StartSCSI      *
- *                             New EH: Don't return cmnds to ML on RST *
- *                             Use old EH (don't have new EH fns yet)  *
- *                             Reset: Unlock, but refuse to queue      *
- *                             2.3 __setup function                    *
- *     2.0e  00/05/22  KG      Return residual for 2.3                 *
- *     2.0e1 00/05/25  KG      Compile fixes for 2.3.99                *
- *     2.0e2 00/05/27  KG      Jeff Garzik's pci_enable_device()       *
- *     2.0e3 00/09/29  KG      Some 2.4 changes. Don't try Sync Nego   *
- *                             before INQUIRY has reported ability.    *
- *                             Recognise INQUIRY as scanning command.  *
- *     2.0e4 00/10/13  KG      Allow compilation into 2.4 kernel       *
- *     2.0e5 00/11/17  KG      Store Inq.flags in DCB                  *
- *     2.0e6 00/11/22  KG      2.4 init function (Thx to O.Schumann)   *
- *                             2.4 PCI device table (Thx to A.Richter) *
- *     2.0e7 00/11/28  KG      Allow overriding of BIOS settings       *
- *     2.0f  00/12/20  KG      Handle failed INQUIRYs during scan      *
- *     2.1a  03/11/29  GL, KG  Initial fixing for 2.6. Convert to      *
- *                             use the current PCI-mapping API, update *
- *                             command-queuing.                        *
- *     2.1b  04/04/13  GL      Fix for 64-bit platforms                *
- *     2.1b1 04/01/31  GL      (applied 05.04) Remove internal         *
- *                             command-queuing.                        *
- *     2.1b2 04/02/01  CH      (applied 05.04) Fix error-handling      *
- *     2.1c  04/05/23  GL      Update to use the new pci_driver API,   *
- *                             some scsi EH updates, more cleanup.     *
- *     2.1d  04/05/27  GL      Moved setting of scan_devices to        *
- *                             slave_alloc/_configure/_destroy, as     *
- *                             suggested by CH.                        *
- ***********************************************************************/
-
-/* DEBUG options */
-//#define DC390_DEBUG0
-//#define DC390_DEBUG1
-//#define DC390_DCBDEBUG
-//#define DC390_PARSEDEBUG
-//#define DC390_REMOVABLEDEBUG
-//#define DC390_LOCKDEBUG
-
-//#define NOP do{}while(0)
-#define C_NOP
-
-/* Debug definitions */
-#ifdef DC390_DEBUG0
-# define DEBUG0(x) x
-#else
-# define DEBUG0(x) C_NOP
-#endif
-#ifdef DC390_DEBUG1
-# define DEBUG1(x) x
-#else
-# define DEBUG1(x) C_NOP
-#endif
-#ifdef DC390_DCBDEBUG
-# define DCBDEBUG(x) x
-#else
-# define DCBDEBUG(x) C_NOP
-#endif
-#ifdef DC390_PARSEDEBUG
-# define PARSEDEBUG(x) x
-#else
-# define PARSEDEBUG(x) C_NOP
-#endif
-#ifdef DC390_REMOVABLEDEBUG
-# define REMOVABLEDEBUG(x) x
-#else
-# define REMOVABLEDEBUG(x) C_NOP
-#endif
-#define DCBDEBUG1(x) C_NOP
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsicam.h>
-#include <scsi/scsi_tcq.h>
-
-
-#define DC390_BANNER "Tekram DC390/AM53C974"
-#define DC390_VERSION "2.1d 2004-05-27"
-
-#define PCI_DEVICE_ID_AMD53C974        PCI_DEVICE_ID_AMD_SCSI
-
-#include "tmscsim.h"
-
-
-static void dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-
-static void dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB );
-static void dc390_Disconnect( struct dc390_acb* pACB );
-static void dc390_Reselect( struct dc390_acb* pACB );
-static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
-static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
-static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
-static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB);
-static void dc390_ResetDevParam(struct dc390_acb* pACB);
-
-static u32     dc390_laststatus = 0;
-static u8      dc390_adapterCnt = 0;
-
-static int disable_clustering;
-module_param(disable_clustering, int, S_IRUGO);
-MODULE_PARM_DESC(disable_clustering, "If you experience problems with your devices, try setting to 1");
-
-/* Startup values, to be overriden on the commandline */
-static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
-
-module_param_array(tmscsim, int, NULL, 0);
-MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
-MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
-MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
-
-static void *dc390_phase0[]={
-       dc390_DataOut_0,
-       dc390_DataIn_0,
-       dc390_Command_0,
-       dc390_Status_0,
-       dc390_Nop_0,
-       dc390_Nop_0,
-       dc390_MsgOut_0,
-       dc390_MsgIn_0,
-       dc390_Nop_1
-       };
-
-static void *dc390_phase1[]={
-       dc390_DataOutPhase,
-       dc390_DataInPhase,
-       dc390_CommandPhase,
-       dc390_StatusPhase,
-       dc390_Nop_0,
-       dc390_Nop_0,
-       dc390_MsgOutPhase,
-       dc390_MsgInPhase,
-       dc390_Nop_1
-       };
-
-#ifdef DC390_DEBUG1
-static char* dc390_p0_str[] = {
-       "dc390_DataOut_0",
-       "dc390_DataIn_0",
-       "dc390_Command_0",
-       "dc390_Status_0",
-       "dc390_Nop_0",
-       "dc390_Nop_0",
-       "dc390_MsgOut_0",
-       "dc390_MsgIn_0",
-       "dc390_Nop_1"
-       };
-     
-static char* dc390_p1_str[] = {
-       "dc390_DataOutPhase",
-       "dc390_DataInPhase",
-       "dc390_CommandPhase",
-       "dc390_StatusPhase",
-       "dc390_Nop_0",
-       "dc390_Nop_0",
-       "dc390_MsgOutPhase",
-       "dc390_MsgInPhase",
-       "dc390_Nop_1"
-       };
-#endif   
-
-static u8  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
-static u8  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
-static u8  dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
-
-/***********************************************************************
- * Functions for the management of the internal structures 
- * (DCBs, SRBs, Queueing)
- *
- **********************************************************************/
-static void inline dc390_start_segment(struct dc390_srb* pSRB)
-{
-       struct scatterlist *psgl = pSRB->pSegmentList;
-
-       /* start new sg segment */
-       pSRB->SGBusAddr = sg_dma_address(psgl);
-       pSRB->SGToBeXferLen = sg_dma_len(psgl);
-}
-
-static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
-{
-       unsigned long xfer = pSRB->SGToBeXferLen - residue;
-
-       /* xfer more bytes transferred */
-       pSRB->SGBusAddr += xfer;
-       pSRB->TotalXferredLen += xfer;
-       pSRB->SGToBeXferLen = residue;
-
-       return xfer;
-}
-
-static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
-{
-   struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
-   while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
-     {
-       pDCB = pDCB->pNextDCB;
-       if (pDCB == pACB->pLinkDCB)
-            return NULL;
-     }
-   DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n",        \
-                     pDCB, pDCB->TargetID, pDCB->TargetLUN));
-   return pDCB;
-}
-
-/* Insert SRB oin top of free list */
-static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-    DEBUG0(printk ("DC390: Free SRB %p\n", pSRB));
-    pSRB->pNextSRB = pACB->pFreeSRB;
-    pACB->pFreeSRB = pSRB;
-}
-
-static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-    pDCB->GoingSRBCnt++;
-    DEBUG0(printk("DC390: Append SRB %p to Going\n", pSRB));
-    /* Append to the list of Going commands */
-    if( pDCB->pGoingSRB )
-       pDCB->pGoingLast->pNextSRB = pSRB;
-    else
-       pDCB->pGoingSRB = pSRB;
-
-    pDCB->pGoingLast = pSRB;
-    /* No next one in sent list */
-    pSRB->pNextSRB = NULL;
-}
-
-static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-       DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB));
-   if (pSRB == pDCB->pGoingSRB)
-       pDCB->pGoingSRB = pSRB->pNextSRB;
-   else
-     {
-       struct dc390_srb* psrb = pDCB->pGoingSRB;
-       while (psrb && psrb->pNextSRB != pSRB)
-         psrb = psrb->pNextSRB;
-       if (!psrb) 
-         { printk (KERN_ERR "DC390: Remove non-ex. SRB %p from Going!\n", pSRB); return; }
-       psrb->pNextSRB = pSRB->pNextSRB;
-       if (pSRB == pDCB->pGoingLast)
-         pDCB->pGoingLast = psrb;
-     }
-   pDCB->GoingSRBCnt--;
-}
-
-static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
-{
-       sg_init_one(sg, addr, length);
-       return sg;
-}
-
-/* Create pci mapping */
-static int dc390_pci_map (struct dc390_srb* pSRB)
-{
-       int error = 0;
-       struct scsi_cmnd *pcmd = pSRB->pcmd;
-       struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
-       dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
-
-       /* Map sense buffer */
-       if (pSRB->SRBFlag & AUTO_REQSENSE) {
-               pSRB->pSegmentList      = dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
-               pSRB->SGcount           = pci_map_sg(pdev, pSRB->pSegmentList, 1,
-                                                    DMA_FROM_DEVICE);
-               cmdp->saved_dma_handle  = sg_dma_address(pSRB->pSegmentList);
-
-               /* TODO: error handling */
-               if (pSRB->SGcount != 1)
-                       error = 1;
-               DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __func__, pcmd->sense_buffer, cmdp->saved_dma_handle));
-       /* Map SG list */
-       } else if (scsi_sg_count(pcmd)) {
-               int nseg;
-
-               nseg = scsi_dma_map(pcmd);
-
-               pSRB->pSegmentList      = scsi_sglist(pcmd);
-               pSRB->SGcount           = nseg;
-
-               /* TODO: error handling */
-               if (nseg < 0)
-                       error = 1;
-               DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
-                             __func__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
-       /* Map single segment */
-       } else
-               pSRB->SGcount = 0;
-
-       return error;
-}
-
-/* Remove pci mapping */
-static void dc390_pci_unmap (struct dc390_srb* pSRB)
-{
-       struct scsi_cmnd *pcmd = pSRB->pcmd;
-       struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
-       DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)));
-
-       if (pSRB->SRBFlag) {
-               pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
-               DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __func__, cmdp->saved_dma_handle));
-       } else {
-               scsi_dma_unmap(pcmd);
-               DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
-                             __func__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
-       }
-}
-
-static void __inline__
-dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-       if (pSRB->TagNumber != SCSI_NO_TAG) {
-               pDCB->TagMask &= ~(1 << pSRB->TagNumber);   /* free tag mask */
-               pSRB->TagNumber = SCSI_NO_TAG;
-       }
-}
-
-
-static int
-dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
-    struct scsi_cmnd *scmd = pSRB->pcmd;
-    struct scsi_device *sdev = scmd->device;
-    u8 cmd, disc_allowed, try_sync_nego;
-    char tag[2];
-
-    pSRB->ScsiPhase = SCSI_NOP0;
-
-    if (pACB->Connected)
-    {
-       // Should not happen normally
-       printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n",
-               pSRB->SRBState, pSRB->SRBFlag);
-       pSRB->SRBState = SRB_READY;
-       pACB->SelConn++;
-       return 1;
-    }
-    if (time_before (jiffies, pACB->last_reset))
-    {
-       DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
-       return 1;
-    }
-    /* KG: Moved pci mapping here */
-    dc390_pci_map(pSRB);
-    /* TODO: error handling */
-    DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
-    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
-    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
-    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
-    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
-    DC390_write8 (CtrlReg4, pDCB->CtrlR4);
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);            /* Flush FIFO */
-    DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\
-            scmd->cmnd[0], pDCB->SyncMode));
-
-    /* Don't disconnect on AUTO_REQSENSE, cause it might be an
-     * Contingent Allegiance Condition (6.6), where no tags should be used.
-     * All other have to be allowed to disconnect to prevent Incorrect 
-     * Initiator Connection (6.8.2/6.5.2) */
-    /* Changed KG, 99/06/06 */
-    if (! (pSRB->SRBFlag & AUTO_REQSENSE))
-       disc_allowed = pDCB->DevMode & EN_DISCONNECT_;
-    else
-       disc_allowed = 0;
-
-    if ((pDCB->SyncMode & SYNC_ENABLE) && pDCB->TargetLUN == 0 && sdev->sdtr &&
-       (((scmd->cmnd[0] == REQUEST_SENSE || (pSRB->SRBFlag & AUTO_REQSENSE)) &&
-         !(pDCB->SyncMode & SYNC_NEGO_DONE)) || scmd->cmnd[0] == INQUIRY))
-      try_sync_nego = 1;
-    else
-      try_sync_nego = 0;
-
-    pSRB->MsgCnt = 0;
-    cmd = SEL_W_ATN;
-    DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
-    /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
-    if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed && scsi_populate_tag_msg(scmd, tag)) {
-       DC390_write8(ScsiFifo, tag[0]);
-       pDCB->TagMask |= 1 << tag[1];
-       pSRB->TagNumber = tag[1];
-       DC390_write8(ScsiFifo, tag[1]);
-       DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for SRB %p, block tag %02x\n", pSRB, tag[1]));
-       cmd = SEL_W_ATN3;
-    } else {
-       /* No TagQ */
-//no_tag:
-       DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for SRB %p, No TagQ\n", disc_allowed ? "" : "o", pSRB));
-    }
-
-    pSRB->SRBState = SRB_START_;
-
-    if (try_sync_nego)
-      { 
-       u8 Sync_Off = pDCB->SyncOffset;
-        DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN));
-       pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE;
-       pSRB->MsgOutBuf[1] = 3;
-       pSRB->MsgOutBuf[2] = EXTENDED_SDTR;
-       pSRB->MsgOutBuf[3] = pDCB->NegoPeriod;
-       if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET;
-       pSRB->MsgOutBuf[4] = Sync_Off;
-       pSRB->MsgCnt = 5;
-       //pSRB->SRBState = SRB_MSGOUT_;
-       pSRB->SRBState |= DO_SYNC_NEGO;
-       cmd = SEL_W_ATN_STOP;
-      }
-
-    /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */
-    if (cmd != SEL_W_ATN_STOP)
-      {
-       if( pSRB->SRBFlag & AUTO_REQSENSE )
-         {
-           DC390_write8 (ScsiFifo, REQUEST_SENSE);
-           DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
-           DC390_write8 (ScsiFifo, 0);
-           DC390_write8 (ScsiFifo, 0);
-           DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
-           DC390_write8 (ScsiFifo, 0);
-           DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n"));
-         }
-       else    /* write cmnd to bus */ 
-         {
-           u8 *ptr; u8 i;
-           ptr = (u8 *)scmd->cmnd;
-           for (i = 0; i < scmd->cmd_len; i++)
-             DC390_write8 (ScsiFifo, *(ptr++));
-         }
-      }
-    DEBUG0(if (pACB->pActiveDCB)       \
-          printk (KERN_WARNING "DC390: ActiveDCB != 0\n"));
-    DEBUG0(if (pDCB->pActiveSRB)       \
-          printk (KERN_WARNING "DC390: ActiveSRB != 0\n"));
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-    if (DC390_read8 (Scsi_Status) & INTERRUPT)
-    {
-       dc390_freetag (pDCB, pSRB);
-       DEBUG0(printk ("DC390: Interrupt during Start SCSI (target %02i-%02i)\n",
-                      scmd->device->id, (u8)scmd->device->lun));
-       pSRB->SRBState = SRB_READY;
-       //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-       pACB->SelLost++;
-       return 1;
-    }
-    DC390_write8 (ScsiCmd, cmd);
-    pACB->pActiveDCB = pDCB;
-    pDCB->pActiveSRB = pSRB;
-    pACB->Connected = 1;
-    pSRB->ScsiPhase = SCSI_NOP1;
-    return 0;
-}
-
-
-static void __inline__
-dc390_InvalidCmd(struct dc390_acb* pACB)
-{
-       if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
-               DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-}
-
-
-static irqreturn_t __inline__
-DC390_Interrupt(void *dev_id)
-{
-    struct dc390_acb *pACB = dev_id;
-    struct dc390_dcb *pDCB;
-    struct dc390_srb *pSRB;
-    u8  sstatus=0;
-    u8  phase;
-    void   (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
-    u8  istate, istatus;
-
-    sstatus = DC390_read8 (Scsi_Status);
-    if( !(sstatus & INTERRUPT) )
-       return IRQ_NONE;
-
-    DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
-
-    //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
-    //dstatus = DC390_read8 (DMA_Status);
-    //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
-    spin_lock_irq(pACB->pScsiHost->host_lock);
-
-    istate = DC390_read8 (Intern_State);
-    istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
-
-    DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus));
-    dc390_laststatus &= ~0x00ffffff;
-    dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
-
-    if (sstatus & ILLEGAL_OP_ERR)
-    {
-       printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
-       dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
-    }
-       
-    else if (istatus &  INVALID_CMD)
-    {
-       printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus);
-       dc390_InvalidCmd( pACB );
-       goto unlock;
-    }
-
-    if (istatus &  SCSI_RESET)
-    {
-       dc390_ScsiRstDetect( pACB );
-       goto unlock;
-    }
-
-    if (istatus &  DISCONNECTED)
-    {
-       dc390_Disconnect( pACB );
-       goto unlock;
-    }
-
-    if (istatus &  RESELECTED)
-    {
-       dc390_Reselect( pACB );
-       goto unlock;
-    }
-
-    else if (istatus & (SELECTED | SEL_ATTENTION))
-    {
-       printk (KERN_ERR "DC390: Target mode not supported!\n");
-       goto unlock;
-    }
-
-    if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
-    {
-       pDCB = pACB->pActiveDCB;
-       if (!pDCB)
-       {
-               printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
-               goto unlock;
-       }
-       pSRB = pDCB->pActiveSRB;
-       if( pDCB->DCBFlag & ABORT_DEV_ )
-         dc390_EnableMsgOut_Abort (pACB, pSRB);
-
-       phase = pSRB->ScsiPhase;
-       DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus));
-       stateV = (void *) dc390_phase0[phase];
-       ( *stateV )( pACB, pSRB, &sstatus );
-
-       pSRB->ScsiPhase = sstatus & 7;
-       phase = (u8) sstatus & 7;
-       DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
-       stateV = (void *) dc390_phase1[phase];
-       ( *stateV )( pACB, pSRB, &sstatus );
-    }
-
- unlock:
-    spin_unlock_irq(pACB->pScsiHost->host_lock);
-    return IRQ_HANDLED;
-}
-
-static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
-{
-    irqreturn_t ret;
-    DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
-    /* Locking is done in DC390_Interrupt */
-    ret = DC390_Interrupt(dev_id);
-    DEBUG1(printk (".. IRQ returned\n"));
-    return ret;
-}
-
-static void
-dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    u8   sstatus;
-    u32  ResidCnt;
-    u8   dstate = 0;
-
-    sstatus = *psstatus;
-
-    if( !(pSRB->SRBState & SRB_XFERPAD) )
-    {
-       if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
-           pSRB->SRBStatus |= PARITY_ERROR;
-
-       if( sstatus & COUNT_2_ZERO )
-       {
-           unsigned long timeout = jiffies + HZ;
-
-           /* Function called from the ISR with the host_lock held and interrupts disabled */
-           if (pSRB->SGToBeXferLen)
-               while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
-                   spin_unlock_irq(pACB->pScsiHost->host_lock);
-                   udelay(50);
-                   spin_lock_irq(pACB->pScsiHost->host_lock);
-               }
-           if (!time_before(jiffies, timeout))
-               printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
-                       DC390_read32 (DMA_Wk_ByteCntr));
-           dc390_laststatus &= ~0xff000000;
-           dc390_laststatus |= dstate << 24;
-           pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
-           pSRB->SGIndex++;
-           if( pSRB->SGIndex < pSRB->SGcount )
-           {
-               pSRB->pSegmentList++;
-
-               dc390_start_segment(pSRB);
-           }
-           else
-               pSRB->SGToBeXferLen = 0;
-       }
-       else
-       {
-           ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
-                   (((u32) DC390_read8 (CtcReg_High) << 16) |
-                    ((u32) DC390_read8 (CtcReg_Mid) << 8) |
-                    (u32) DC390_read8 (CtcReg_Low));
-
-           dc390_advance_segment(pSRB, ResidCnt);
-       }
-    }
-    if ((*psstatus & 7) != SCSI_DATA_OUT)
-    {
-           DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
-           DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    }      
-}
-
-static void
-dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    u8   sstatus, residual, bval;
-    u32  ResidCnt, i;
-    unsigned long   xferCnt;
-
-    sstatus = *psstatus;
-
-    if( !(pSRB->SRBState & SRB_XFERPAD) )
-    {
-       if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
-           pSRB->SRBStatus |= PARITY_ERROR;
-
-       if( sstatus & COUNT_2_ZERO )
-       {
-           int dstate = 0;
-           unsigned long timeout = jiffies + HZ;
-
-           /* Function called from the ISR with the host_lock held and interrupts disabled */
-           if (pSRB->SGToBeXferLen)
-               while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
-                   spin_unlock_irq(pACB->pScsiHost->host_lock);
-                   udelay(50);
-                   spin_lock_irq(pACB->pScsiHost->host_lock);
-               }
-           if (!time_before(jiffies, timeout)) {
-               printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
-                       DC390_read32 (DMA_Wk_ByteCntr));
-               printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
-           }
-           dc390_laststatus &= ~0xff000000;
-           dc390_laststatus |= dstate << 24;
-           DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \
-               + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8)               \
-               + ((unsigned long) DC390_read8 (CtcReg_Low)));
-           DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
-
-           DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-
-           pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
-           pSRB->SGIndex++;
-           if( pSRB->SGIndex < pSRB->SGcount )
-           {
-               pSRB->pSegmentList++;
-
-               dc390_start_segment(pSRB);
-           }
-           else
-               pSRB->SGToBeXferLen = 0;
-       }
-       else    /* phase changed */
-       {
-           residual = 0;
-           bval = DC390_read8 (Current_Fifo);
-           while( bval & 0x1f )
-           {
-               DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
-               if( (bval & 0x1f) == 1 )
-               {
-                   for(i=0; i < 0x100; i++)
-                   {
-                       bval = DC390_read8 (Current_Fifo);
-                       if( !(bval & 0x1f) )
-                           goto din_1;
-                       else if( i == 0x0ff )
-                       {
-                           residual = 1;   /* ;1 residual byte */
-                           goto din_1;
-                       }
-                   }
-               }
-               else
-                   bval = DC390_read8 (Current_Fifo);
-           }
-din_1:
-           DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
-           for (i = 0xa000; i; i--)
-           {
-               bval = DC390_read8 (DMA_Status);
-               if (bval & BLAST_COMPLETE)
-                   break;
-           }
-           /* It seems a DMA Blast abort isn't that bad ... */
-           if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
-           //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-           dc390_laststatus &= ~0xff000000;
-           dc390_laststatus |= bval << 24;
-
-           DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
-           ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
-                       ((u32) DC390_read8 (CtcReg_Mid) << 8)) |
-                   (u32) DC390_read8 (CtcReg_Low);
-
-           xferCnt = dc390_advance_segment(pSRB, ResidCnt);
-
-           if (residual) {
-               size_t count = 1;
-               size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
-               unsigned long flags;
-               u8 *ptr;
-
-               bval = DC390_read8 (ScsiFifo);      /* get one residual byte */
-
-               local_irq_save(flags);
-               ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
-               if (likely(ptr)) {
-                       *(ptr + offset) = bval;
-                       scsi_kunmap_atomic_sg(ptr);
-               }
-               local_irq_restore(flags);
-               WARN_ON(!ptr);
-
-               /* 1 more byte read */
-               xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
-           }
-           DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
-                          pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
-       }
-    }
-    if ((*psstatus & 7) != SCSI_DATA_IN)
-    {
-           DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-           DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-    }
-}
-
-static void
-dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-
-    pSRB->TargetStatus = DC390_read8 (ScsiFifo);
-    //udelay (1);
-    pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */
-
-    *psstatus = SCSI_NOP0;
-    pSRB->SRBState = SRB_COMPLETED;
-    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
-}
-
-static void
-dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
-       *psstatus = SCSI_NOP0;
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void __inline__
-dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
-{
-  DC390_write8 (Sync_Period, pDCB->SyncPeriod);
-  DC390_write8 (Sync_Offset, pDCB->SyncOffset);
-  DC390_write8 (CtrlReg3, pDCB->CtrlR3);
-  DC390_write8 (CtrlReg4, pDCB->CtrlR4);
-  dc390_SetXferRate (pACB, pDCB);
-}
-
-
-#ifdef DC390_DEBUG0
-static void
-dc390_printMsg (u8 *MsgBuf, u8 len)
-{
-  int i;
-  printk (" %02x", MsgBuf[0]);
-  for (i = 1; i < len; i++)
-    printk (" %02x", MsgBuf[i]);
-  printk ("\n");
-}
-#endif
-
-#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
-
-/* reject_msg */
-static void __inline__
-dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-  pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
-  pSRB->MsgCnt = 1;
-  DC390_ENABLE_MSGOUT;
-  DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
-}
-
-/* abort command */
-static void
-dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
-{
-    pSRB->MsgOutBuf[0] = ABORT; 
-    pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
-    pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
-}
-
-static struct dc390_srb*
-dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, s8 tag)
-{
-  struct dc390_srb* pSRB = pDCB->pGoingSRB;
-
-  if (pSRB)
-    {
-       struct scsi_cmnd *scmd = scsi_find_tag(pSRB->pcmd->device, tag);
-       pSRB = (struct dc390_srb *)scmd->host_scribble;
-
-       if (pDCB->DCBFlag & ABORT_DEV_)
-       {
-         pSRB->SRBState = SRB_ABORT_SENT;
-         dc390_EnableMsgOut_Abort( pACB, pSRB );
-       }
-
-       if (!(pSRB->SRBState & SRB_DISCONNECT))
-               goto mingx0;
-
-       pDCB->pActiveSRB = pSRB;
-       pSRB->SRBState = SRB_DATA_XFER;
-    }
-  else
-    {
-    mingx0:
-      pSRB = pACB->pTmpSRB;
-      pSRB->SRBState = SRB_UNEXPECT_RESEL;
-      pDCB->pActiveSRB = pSRB;
-      pSRB->MsgOutBuf[0] = ABORT_TAG;
-      pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
-    }
-  return pSRB;
-}
-
-
-/* set async transfer mode */
-static void 
-dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-  struct dc390_dcb* pDCB = pSRB->pSRBDCB;
-  if (!(pSRB->SRBState & DO_SYNC_NEGO)) 
-    printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
-  pSRB->SRBState &= ~DO_SYNC_NEGO;
-  pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
-  pDCB->SyncPeriod = 0;
-  pDCB->SyncOffset = 0;
-  //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
-  pDCB->CtrlR3 = FAST_CLK;     /* fast clock / normal scsi */
-  pDCB->CtrlR4 &= 0x3f;
-  pDCB->CtrlR4 |= pACB->glitch_cfg;    /* glitch eater */
-  dc390_reprog (pACB, pDCB);
-}
-
-/* set sync transfer mode */
-static void
-dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-  u8 bval;
-  u16 wval, wval1;
-  struct dc390_dcb* pDCB = pSRB->pSRBDCB;
-  u8 oldsyncperiod = pDCB->SyncPeriod;
-  u8 oldsyncoffset = pDCB->SyncOffset;
-  
-  if (!(pSRB->SRBState & DO_SYNC_NEGO))
-    {
-      printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n", 
-             pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
-
-      /* reject */
-      //dc390_MsgIn_reject (pACB, pSRB);
-      //return dc390_MsgIn_set_async (pACB, pSRB);
-
-      /* Reply with corrected SDTR Message */
-      if (pSRB->MsgInBuf[4] > 15)
-       { 
-         printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
-         pSRB->MsgInBuf[4] = 15;
-       }
-      if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
-       {
-         printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
-         pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
-       }
-      memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
-      pSRB->MsgCnt = 5;
-      DC390_ENABLE_MSGOUT;
-    }
-
-  pSRB->SRBState &= ~DO_SYNC_NEGO;
-  pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
-  pDCB->SyncOffset &= 0x0f0;
-  pDCB->SyncOffset |= pSRB->MsgInBuf[4];
-  pDCB->NegoPeriod = pSRB->MsgInBuf[3];
-
-  wval = (u16) pSRB->MsgInBuf[3];
-  wval = wval << 2; wval -= 3; wval1 = wval / 25;      /* compute speed */
-  if( (wval1 * 25) != wval) wval1++;
-  bval = FAST_CLK+FAST_SCSI;   /* fast clock / fast scsi */
-
-  pDCB->CtrlR4 &= 0x3f;                /* Glitch eater: 12ns less than normal */
-  if (pACB->glitch_cfg != NS_TO_GLITCH(0))
-    pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
-  else
-    pDCB->CtrlR4 |= NS_TO_GLITCH(0);
-  if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
-
-  if (wval1 >= 8)
-    {
-      wval1--; /* Timing computation differs by 1 from FAST_SCSI */
-      bval = FAST_CLK;         /* fast clock / normal scsi */
-      pDCB->CtrlR4 |= pACB->glitch_cfg;        /* glitch eater */
-    }
-
-  pDCB->CtrlR3 = bval;
-  pDCB->SyncPeriod = (u8)wval1;
-  
-  if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
-    {
-      if (! (bval & FAST_SCSI)) wval1++;
-      printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID, 
-             40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
-    }
-  
-  dc390_reprog (pACB, pDCB);
-}
-
-
-/* handle RESTORE_PTR */
-/* This doesn't look very healthy... to-be-fixed */
-static void 
-dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
-    struct scsi_cmnd *pcmd = pSRB->pcmd;
-    struct scatterlist *psgl;
-    pSRB->TotalXferredLen = 0;
-    pSRB->SGIndex = 0;
-    if (scsi_sg_count(pcmd)) {
-       size_t saved;
-       pSRB->pSegmentList = scsi_sglist(pcmd);
-       psgl = pSRB->pSegmentList;
-       //dc390_pci_sync(pSRB);
-
-       while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr)
-       {
-           pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
-           pSRB->SGIndex++;
-           if( pSRB->SGIndex < pSRB->SGcount )
-           {
-               pSRB->pSegmentList++;
-
-               dc390_start_segment(pSRB);
-           }
-           else
-               pSRB->SGToBeXferLen = 0;
-       }
-
-       saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
-       pSRB->SGToBeXferLen -= saved;
-       pSRB->SGBusAddr += saved;
-       printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
-               pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
-
-    } else {
-        pSRB->SGcount = 0;
-        printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");
-    }
-
-  pSRB->TotalXferredLen = pSRB->Saved_Ptr;
-}
-
-
-/* According to the docs, the AM53C974 reads the message and 
- * generates a Successful Operation IRQ before asserting ACK for
- * the last byte (how does it know whether it's the last ?) */
-/* The old code handled it in another way, indicating, that on
- * every message byte an IRQ is generated and every byte has to
- * be manually ACKed. Hmmm ?  (KG, 98/11/28) */
-/* The old implementation was correct. Sigh! */
-
-/* Check if the message is complete */
-static u8 __inline__
-dc390_MsgIn_complete (u8 *msgbuf, u32 len)
-{ 
-  if (*msgbuf == EXTENDED_MESSAGE)
-  {
-       if (len < 2) return 0;
-       if (len < msgbuf[1] + 2) return 0;
-  }
-  else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
-       if (len < 2) return 0;
-  return 1;
-}
-
-
-
-/* read and eval received messages */
-static void
-dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    struct dc390_dcb*   pDCB = pACB->pActiveDCB;
-
-    /* Read the msg */
-
-    pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
-    //pSRB->SRBState = 0;
-
-    /* Msg complete ? */
-    if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
-      {
-       DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
-       /* Now eval the msg */
-       switch (pSRB->MsgInBuf[0]) 
-         {
-         case DISCONNECT: 
-           pSRB->SRBState = SRB_DISCONNECT; break;
-           
-         case SIMPLE_QUEUE_TAG:
-         case HEAD_OF_QUEUE_TAG:
-         case ORDERED_QUEUE_TAG:
-           pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
-           break;
-           
-         case MESSAGE_REJECT: 
-           DC390_write8 (ScsiCmd, RESET_ATN_CMD);
-           pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
-           if( pSRB->SRBState & DO_SYNC_NEGO)
-             dc390_MsgIn_set_async (pACB, pSRB);
-           break;
-           
-         case EXTENDED_MESSAGE:
-           /* reject every extended msg but SDTR */
-           if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
-             dc390_MsgIn_reject (pACB, pSRB);
-           else
-             {
-               if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
-                 dc390_MsgIn_set_async (pACB, pSRB);
-               else
-                 dc390_MsgIn_set_sync (pACB, pSRB);
-             }
-           
-           // nothing has to be done
-         case COMMAND_COMPLETE: break;
-           
-           // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the
-           // scsi command. Thanks, Gerard, for pointing it out.
-         case SAVE_POINTERS: 
-           pSRB->Saved_Ptr = pSRB->TotalXferredLen;
-           break;
-           // The device might want to restart transfer with a RESTORE
-         case RESTORE_POINTERS:
-           DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n"));
-           dc390_restore_ptr (pACB, pSRB);
-           break;
-
-           // reject unknown messages
-         default: dc390_MsgIn_reject (pACB, pSRB);
-         }
-       
-       /* Clear counter and MsgIn state */
-       pSRB->SRBState &= ~SRB_MSGIN;
-       pACB->MsgLen = 0;
-      }
-
-    *psstatus = SCSI_NOP0;
-    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void
-dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
-{
-    unsigned long  lval;
-    struct dc390_dcb*   pDCB = pACB->pActiveDCB;
-
-    if (pSRB == pACB->pTmpSRB)
-    {
-       if (pDCB)
-               printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
-       else
-               printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
-
-       /* Try to recover - some broken disks react badly to tagged INQUIRY */
-       if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
-               pSRB = pDCB->pGoingSRB;
-               pDCB->pActiveSRB = pSRB;
-       } else {
-               pSRB->pSRBDCB = pDCB;
-               dc390_EnableMsgOut_Abort(pACB, pSRB);
-               if (pDCB)
-                       pDCB->DCBFlag |= ABORT_DEV;
-               return;
-       }
-    }
-
-    if( pSRB->SGIndex < pSRB->SGcount )
-    {
-       DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
-       if( !pSRB->SGToBeXferLen )
-       {
-           dc390_start_segment(pSRB);
-
-           DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
-       }
-       lval = pSRB->SGToBeXferLen;
-       DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
-       DC390_write8 (CtcReg_Low, (u8) lval);
-       lval >>= 8;
-       DC390_write8 (CtcReg_Mid, (u8) lval);
-       lval >>= 8;
-       DC390_write8 (CtcReg_High, (u8) lval);
-
-       DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
-       DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
-
-       //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
-       pSRB->SRBState = SRB_DATA_XFER;
-
-       DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
-
-       DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
-       //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
-       //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
-       //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
-    }
-    else    /* xfer pad */
-    {
-       if( pSRB->SGcount )
-       {
-           pSRB->AdaptStatus = H_OVER_UNDER_RUN;
-           pSRB->SRBStatus |= OVER_RUN;
-           DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
-       }
-       DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
-       DC390_write8 (CtcReg_Low, 0);
-       DC390_write8 (CtcReg_Mid, 0);
-       DC390_write8 (CtcReg_High, 0);
-
-       pSRB->SRBState |= SRB_XFERPAD;
-       DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
-/*
-       DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
-       DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
-*/
-    }
-}
-
-
-static void
-dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
-}
-
-static void
-dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
-}
-
-static void
-dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    struct dc390_dcb*   pDCB;
-    u8  i, cnt;
-    u8     *ptr;
-
-    DC390_write8 (ScsiCmd, RESET_ATN_CMD);
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
-    {
-       cnt = (u8) pSRB->pcmd->cmd_len;
-       ptr = (u8 *) pSRB->pcmd->cmnd;
-       for(i=0; i < cnt; i++)
-           DC390_write8 (ScsiFifo, *(ptr++));
-    }
-    else
-    {
-       DC390_write8 (ScsiFifo, REQUEST_SENSE);
-       pDCB = pACB->pActiveDCB;
-       DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
-       DC390_write8 (ScsiFifo, 0);
-       DC390_write8 (ScsiFifo, 0);
-       DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
-       DC390_write8 (ScsiFifo, 0);
-       DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
-    }
-    pSRB->SRBState = SRB_COMMAND;
-    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-}
-
-static void
-dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    pSRB->SRBState = SRB_STATUS;
-    DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    u8   bval, i, cnt;
-    u8     *ptr;
-    struct dc390_dcb*    pDCB;
-
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    pDCB = pACB->pActiveDCB;
-    if( !(pSRB->SRBState & SRB_MSGOUT) )
-    {
-       cnt = pSRB->MsgCnt;
-       if( cnt )
-       {
-           ptr = (u8 *) pSRB->MsgOutBuf;
-           for(i=0; i < cnt; i++)
-               DC390_write8 (ScsiFifo, *(ptr++));
-           pSRB->MsgCnt = 0;
-           if( (pDCB->DCBFlag & ABORT_DEV_) &&
-               (pSRB->MsgOutBuf[0] == ABORT) )
-               pSRB->SRBState = SRB_ABORT_SENT;
-       }
-       else
-       {
-           bval = ABORT;       /* ??? MSG_NOP */
-           if( (pSRB->pcmd->cmnd[0] == INQUIRY ) ||
-               (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) ||
-               (pSRB->SRBFlag & AUTO_REQSENSE) )
-           {
-               if( pDCB->SyncMode & SYNC_ENABLE )
-                   goto  mop1;
-           }
-           DC390_write8 (ScsiFifo, bval);
-       }
-       DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-    }
-    else
-    {
-mop1:
-        printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
-       DC390_write8 (ScsiFifo, EXTENDED_MESSAGE);
-       DC390_write8 (ScsiFifo, 3);     /*    ;length of extended msg */
-       DC390_write8 (ScsiFifo, EXTENDED_SDTR); /*    ; sync nego */
-       DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
-       if (pDCB->SyncOffset & 0x0f)
-                   DC390_write8 (ScsiFifo, pDCB->SyncOffset);
-       else
-                   DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);              
-       pSRB->SRBState |= DO_SYNC_NEGO;
-       DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-    }
-}
-
-static void
-dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    if( !(pSRB->SRBState & SRB_MSGIN) )
-    {
-       pSRB->SRBState &= ~SRB_DISCONNECT;
-       pSRB->SRBState |= SRB_MSGIN;
-    }
-    DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-
-static void
-dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
-{
-    u8  bval, i, cnt;
-    struct dc390_dcb*   ptr;
-
-    if( !(pDCB->TargetLUN) )
-    {
-       if( !pACB->scan_devices )
-       {
-           ptr = pACB->pLinkDCB;
-           cnt = pACB->DCBCnt;
-           bval = pDCB->TargetID;
-           for(i=0; i<cnt; i++)
-           {
-               if( ptr->TargetID == bval )
-               {
-                   ptr->SyncPeriod = pDCB->SyncPeriod;
-                   ptr->SyncOffset = pDCB->SyncOffset;
-                   ptr->CtrlR3 = pDCB->CtrlR3;
-                   ptr->CtrlR4 = pDCB->CtrlR4;
-                   ptr->SyncMode = pDCB->SyncMode;
-               }
-               ptr = ptr->pNextDCB;
-           }
-       }
-    }
-    return;
-}
-
-
-static void
-dc390_Disconnect( struct dc390_acb* pACB )
-{
-    struct dc390_dcb *pDCB;
-    struct dc390_srb *pSRB, *psrb;
-    u8  i, cnt;
-
-    DEBUG0(printk(KERN_INFO "DISC,"));
-
-    if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n");
-    pACB->Connected = 0;
-    pDCB = pACB->pActiveDCB;
-    if (!pDCB)
-     {
-       DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
-              pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
-       mdelay(400);
-       DC390_read8 (INT_Status);       /* Reset Pending INT */
-       DC390_write8 (ScsiCmd, EN_SEL_RESEL);
-       return;
-     }
-    DC390_write8 (ScsiCmd, EN_SEL_RESEL);
-    pSRB = pDCB->pActiveSRB;
-    pACB->pActiveDCB = NULL;
-    pSRB->ScsiPhase = SCSI_NOP0;
-    if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
-       pSRB->SRBState = 0;
-    else if( pSRB->SRBState & SRB_ABORT_SENT )
-    {
-       pDCB->TagMask = 0;
-       pDCB->DCBFlag = 0;
-       cnt = pDCB->GoingSRBCnt;
-       pDCB->GoingSRBCnt = 0;
-       pSRB = pDCB->pGoingSRB;
-       for( i=0; i < cnt; i++)
-       {
-           psrb = pSRB->pNextSRB;
-           dc390_Free_insert (pACB, pSRB);
-           pSRB = psrb;
-       }
-       pDCB->pGoingSRB = NULL;
-    }
-    else
-    {
-       if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
-          !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
-       {       /* Selection time out */
-               pSRB->AdaptStatus = H_SEL_TIMEOUT;
-               pSRB->TargetStatus = 0;
-               goto  disc1;
-       }
-       else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
-       {
-disc1:
-           dc390_freetag (pDCB, pSRB);
-           pDCB->pActiveSRB = NULL;
-           pSRB->SRBState = SRB_FREE;
-           dc390_SRBdone( pACB, pDCB, pSRB);
-       }
-    }
-    pACB->MsgLen = 0;
-}
-
-
-static void
-dc390_Reselect( struct dc390_acb* pACB )
-{
-    struct dc390_dcb*   pDCB;
-    struct dc390_srb*   pSRB;
-    u8  id, lun;
-
-    DEBUG0(printk(KERN_INFO "RSEL,"));
-    pACB->Connected = 1;
-    pDCB = pACB->pActiveDCB;
-    if( pDCB )
-    {  /* Arbitration lost but Reselection won */
-       DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
-       pSRB = pDCB->pActiveSRB;
-       if( !( pACB->scan_devices ) )
-       {
-           struct scsi_cmnd *pcmd = pSRB->pcmd;
-           scsi_set_resid(pcmd, scsi_bufflen(pcmd));
-           SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-           dc390_Going_remove(pDCB, pSRB);
-           dc390_Free_insert(pACB, pSRB);
-           pcmd->scsi_done (pcmd);
-           DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB));
-       }
-    }
-    /* Get ID */
-    lun = DC390_read8 (ScsiFifo);
-    DEBUG0(printk ("Dev %02x,", lun));
-    if (!(lun & (1 << pACB->pScsiHost->this_id)))
-      printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
-    else
-      lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
-    id = 0; while (lun >>= 1) id++;
-    /* Get LUN */
-    lun = DC390_read8 (ScsiFifo);
-    if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
-    lun &= 7;
-    DEBUG0(printk ("(%02i-%i),", id, lun));
-    pDCB = dc390_findDCB (pACB, id, lun);
-    if (!pDCB)
-    {
-       printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
-                   id, lun);
-       return;
-    }
-    pACB->pActiveDCB = pDCB;
-    /* TagQ: We expect a message soon, so never mind the exact SRB */
-    if( pDCB->SyncMode & EN_TAG_QUEUEING )
-    {
-       pSRB = pACB->pTmpSRB;
-       pDCB->pActiveSRB = pSRB;
-    }
-    else
-    {
-       pSRB = pDCB->pActiveSRB;
-       if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
-       {
-           pSRB= pACB->pTmpSRB;
-           pSRB->SRBState = SRB_UNEXPECT_RESEL;
-           printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
-                   id, lun);
-           pDCB->pActiveSRB = pSRB;
-           dc390_EnableMsgOut_Abort ( pACB, pSRB );
-       }
-       else
-       {
-           if( pDCB->DCBFlag & ABORT_DEV_ )
-           {
-               pSRB->SRBState = SRB_ABORT_SENT;
-               printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
-                       id, lun);
-               dc390_EnableMsgOut_Abort( pACB, pSRB );
-           }
-           else
-               pSRB->SRBState = SRB_DATA_XFER;
-       }
-    }
-
-    DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
-    pSRB->ScsiPhase = SCSI_NOP0;
-    DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
-    DC390_write8 (Sync_Period, pDCB->SyncPeriod);
-    DC390_write8 (Sync_Offset, pDCB->SyncOffset);
-    DC390_write8 (CtrlReg1, pDCB->CtrlR1);
-    DC390_write8 (CtrlReg3, pDCB->CtrlR3);
-    DC390_write8 (CtrlReg4, pDCB->CtrlR4);     /* ; Glitch eater */
-    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);  /* ;to release the /ACK signal */
-}
-
-static int __inline__
-dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-       struct scsi_cmnd *pcmd;
-
-       pcmd = pSRB->pcmd;
-
-       REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
-                             pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-
-       pSRB->SRBFlag |= AUTO_REQSENSE;
-       pSRB->SavedTotXLen = pSRB->TotalXferredLen;
-       pSRB->AdaptStatus = 0;
-       pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
-       /* We are called from SRBdone, original PCI mapping has been removed
-        * already, new one is set up from StartSCSI */
-       pSRB->SGIndex = 0;
-
-       pSRB->TotalXferredLen = 0;
-       pSRB->SGToBeXferLen = 0;
-       return dc390_StartSCSI(pACB, pDCB, pSRB);
-}
-
-
-static void
-dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
-    u8 status;
-    struct scsi_cmnd *pcmd;
-
-    pcmd = pSRB->pcmd;
-    /* KG: Moved pci_unmap here */
-    dc390_pci_unmap(pSRB);
-
-    status = pSRB->TargetStatus;
-
-    DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p\n", status, pcmd->result, pSRB));
-    if(pSRB->SRBFlag & AUTO_REQSENSE)
-    {  /* Last command was a Request Sense */
-       pSRB->SRBFlag &= ~AUTO_REQSENSE;
-       pSRB->AdaptStatus = 0;
-       pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
-
-       //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
-       if (status == SAM_STAT_CHECK_CONDITION)
-           pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
-       else /* Retry */
-       {
-           if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
-           {
-               /* Don't retry on TEST_UNIT_READY */
-               pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
-               REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
-                      (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
-           } else {
-               SET_RES_DRV(pcmd->result, DRIVER_SENSE);
-               //pSRB->ScsiCmdLen       = (u8) (pSRB->Segment1[0] >> 8);
-               DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
-               pSRB->TotalXferredLen = 0;
-               SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-           }
-       }
-       goto cmd_done;
-    }
-    if( status )
-    {
-       if (status == SAM_STAT_CHECK_CONDITION)
-       {
-           if (dc390_RequestSense(pACB, pDCB, pSRB)) {
-               SET_RES_DID(pcmd->result, DID_ERROR);
-               goto cmd_done;
-           }
-           return;
-       }
-       else if (status == SAM_STAT_TASK_SET_FULL)
-       {
-           scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
-           DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
-           pSRB->TotalXferredLen = 0;
-           SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-       }
-       else if (status == SAM_STAT_BUSY &&
-                (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
-                pACB->scan_devices)
-       {
-           pSRB->AdaptStatus = 0;
-           pSRB->TargetStatus = status;
-           pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
-       }
-       else
-       {   /* Another error */
-           pSRB->TotalXferredLen = 0;
-           SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
-           goto cmd_done;
-       }
-    }
-    else
-    {  /*  Target status == 0 */
-       status = pSRB->AdaptStatus;
-       if (status == H_OVER_UNDER_RUN)
-       {
-           pSRB->TargetStatus = 0;
-           SET_RES_DID(pcmd->result,DID_OK);
-           SET_RES_MSG(pcmd->result,pSRB->EndMessage);
-       }
-       else if (status == H_SEL_TIMEOUT)
-       {
-           pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
-           /* Devices are removed below ... */
-       }
-       else if( pSRB->SRBStatus & PARITY_ERROR)
-       {
-           //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0);
-           SET_RES_DID(pcmd->result,DID_PARITY);
-           SET_RES_MSG(pcmd->result,pSRB->EndMessage);
-       }
-       else                   /* No error */
-       {
-           pSRB->AdaptStatus = 0;
-           pSRB->TargetStatus = 0;
-           SET_RES_DID(pcmd->result,DID_OK);
-       }
-    }
-
-cmd_done:
-    scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
-
-    dc390_Going_remove (pDCB, pSRB);
-    /* Add to free list */
-    dc390_Free_insert (pACB, pSRB);
-
-    DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done\n"));
-    pcmd->scsi_done (pcmd);
-
-    return;
-}
-
-
-/* Remove all SRBs from Going list and inform midlevel */
-static void
-dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
-{
-    struct dc390_dcb *pDCB, *pdcb;
-    struct dc390_srb *psrb, *psrb2;
-    int i;
-    struct scsi_cmnd *pcmd;
-
-    pDCB = pACB->pLinkDCB;
-    pdcb = pDCB;
-    if (! pdcb) return;
-    do
-    {
-       psrb = pdcb->pGoingSRB;
-       for (i = 0; i < pdcb->GoingSRBCnt; i++)
-       {
-           psrb2 = psrb->pNextSRB;
-           pcmd = psrb->pcmd;
-           dc390_Free_insert (pACB, psrb);
-           psrb  = psrb2;
-       }
-       pdcb->GoingSRBCnt = 0;
-       pdcb->pGoingSRB = NULL;
-       pdcb->TagMask = 0;
-       pdcb = pdcb->pNextDCB;
-    } while( pdcb != pDCB );
-}
-
-
-static void
-dc390_ResetSCSIBus( struct dc390_acb* pACB )
-{
-    //DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
-    //udelay (250);
-    //DC390_write8 (ScsiCmd, NOP_CMD);
-
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-    DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD);
-    pACB->Connected = 0;
-
-    return;
-}
-
-static void
-dc390_ScsiRstDetect( struct dc390_acb* pACB )
-{
-    printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
-    //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
-
-    DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-    /* Unlock before ? */
-    /* delay half a second */
-    udelay (1000);
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    pACB->last_reset = jiffies + 5*HZ/2
-                   + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-    pACB->Connected = 0;
-
-    if( pACB->ACBFlag & RESET_DEV )
-       pACB->ACBFlag |= RESET_DONE;
-    else
-    {   /* Reset was issued by sb else */
-       pACB->ACBFlag |= RESET_DETECT;
-
-       dc390_ResetDevParam( pACB );
-       dc390_DoingSRB_Done( pACB, NULL);
-       //dc390_RecoverSRB( pACB );
-       pACB->pActiveDCB = NULL;
-       pACB->ACBFlag = 0;
-    }
-    return;
-}
-
-static int DC390_queuecommand_lck(struct scsi_cmnd *cmd,
-               void (*done)(struct scsi_cmnd *))
-{
-       struct scsi_device *sdev = cmd->device;
-       struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
-       struct dc390_dcb *dcb = sdev->hostdata;
-       struct dc390_srb *srb;
-
-       if (sdev->queue_depth <= dcb->GoingSRBCnt)
-               goto device_busy;
-       if (acb->pActiveDCB)
-               goto host_busy;
-       if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV))
-               goto host_busy;
-
-       srb = acb->pFreeSRB;
-       if (unlikely(srb == NULL))
-               goto host_busy;
-
-       cmd->scsi_done = done;
-       cmd->result = 0;
-       acb->Cmds++;
-
-       acb->pFreeSRB = srb->pNextSRB;
-       srb->pNextSRB = NULL;
-
-       srb->pSRBDCB = dcb;
-       srb->pcmd = cmd;
-       cmd->host_scribble = (char *)srb;
-    
-       srb->SGIndex = 0;
-       srb->AdaptStatus = 0;
-       srb->TargetStatus = 0;
-       srb->MsgCnt = 0;
-
-       srb->SRBStatus = 0;
-       srb->SRBFlag = 0;
-       srb->SRBState = 0;
-       srb->TotalXferredLen = 0;
-       srb->SGBusAddr = 0;
-       srb->SGToBeXferLen = 0;
-       srb->ScsiPhase = 0;
-       srb->EndMessage = 0;
-       srb->TagNumber = SCSI_NO_TAG;
-
-       if (dc390_StartSCSI(acb, dcb, srb)) {
-               dc390_Free_insert(acb, srb);
-               goto host_busy;
-       }
-
-       dc390_Going_append(dcb, srb);
-
-       return 0;
-
- host_busy:
-       return SCSI_MLQUEUE_HOST_BUSY;
-
- device_busy:
-       return SCSI_MLQUEUE_DEVICE_BUSY;
-}
-
-static DEF_SCSI_QCMD(DC390_queuecommand)
-
-static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
-    struct pci_dev *pdev;
-    u16 pstat;
-
-    if (!pDCB) pDCB = pACB->pActiveDCB;
-    if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
-
-    if (pSRB) 
-    {
-       printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n",
-               pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,
-               pSRB->ScsiPhase);
-       printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus);
-    }
-    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus);
-    printk ("DC390: Register dump: SCSI block:\n");
-    printk ("DC390: XferCnt  Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n");
-    printk ("DC390:  %06x   %02x   %02x   %02x",
-           DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
-           DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
-    printk ("   %02x   %02x   %02x   %02x   %02x   %02x\n",
-           DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
-           DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
-    DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
-    if (DC390_read8(Current_Fifo) & 0x1f)
-      {
-       printk ("DC390: FIFO:");
-       while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo));
-       printk ("\n");
-      }
-    printk ("DC390: Register dump: DMA engine:\n");
-    printk ("DC390: Cmd   STrCnt    SBusA    WrkBC    WrkAC Stat SBusCtrl\n");
-    printk ("DC390:  %02x %08x %08x %08x %08x   %02x %08x\n",
-           DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
-           DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
-           DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
-    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
-    pdev = pACB->pdev;
-    pci_read_config_word(pdev, PCI_STATUS, &pstat);
-    printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
-    printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n");
-}
-
-
-static int DC390_abort(struct scsi_cmnd *cmd)
-{
-       struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
-       struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
-
-       scmd_printk(KERN_WARNING, cmd, "DC390: Abort command\n");
-
-       /* abort() is too stupid for already sent commands at the moment. 
-        * If it's called we are in trouble anyway, so let's dump some info 
-        * into the syslog at least. (KG, 98/08/20,99/06/20) */
-       dc390_dumpinfo(pACB, pDCB, NULL);
-
-       pDCB->DCBFlag |= ABORT_DEV_;
-       printk(KERN_INFO "DC390: Aborted.\n");
-
-       return FAILED;
-}
-
-
-static void dc390_ResetDevParam( struct dc390_acb* pACB )
-{
-    struct dc390_dcb *pDCB, *pdcb;
-
-    pDCB = pACB->pLinkDCB;
-    if (! pDCB) return;
-    pdcb = pDCB;
-    do
-    {
-       pDCB->SyncMode &= ~SYNC_NEGO_DONE;
-       pDCB->SyncPeriod = 0;
-       pDCB->SyncOffset = 0;
-       pDCB->TagMask = 0;
-       pDCB->CtrlR3 = FAST_CLK;
-       pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;
-       pDCB->CtrlR4 |= pACB->glitch_cfg;
-       pDCB = pDCB->pNextDCB;
-    }
-    while( pdcb != pDCB );
-    pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT);
-
-}
-
-static int DC390_bus_reset (struct scsi_cmnd *cmd)
-{
-       struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
-       u8   bval;
-
-       spin_lock_irq(cmd->device->host->host_lock);
-
-       bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
-       DC390_write8(CtrlReg1, bval);   /* disable IRQ on bus reset */
-
-       pACB->ACBFlag |= RESET_DEV;
-       dc390_ResetSCSIBus(pACB);
-
-       dc390_ResetDevParam(pACB);
-       mdelay(1);
-       pACB->last_reset = jiffies + 3*HZ/2
-               + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-
-       DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-       DC390_read8(INT_Status);                /* Reset Pending INT */
-
-       dc390_DoingSRB_Done(pACB, cmd);
-
-       pACB->pActiveDCB = NULL;
-       pACB->ACBFlag = 0;
-
-       bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
-       DC390_write8(CtrlReg1, bval);   /* re-enable interrupt */
-
-       spin_unlock_irq(cmd->device->host->host_lock);
-
-       return SUCCESS;
-}
-
-/**
- * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new
- * scsi device that we need to deal with.
- *
- * @scsi_device: The new scsi device that we need to handle.
- */
-static int dc390_slave_alloc(struct scsi_device *scsi_device)
-{
-       struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
-       struct dc390_dcb *pDCB, *pDCB2 = NULL;
-       uint id = scsi_device->id;
-       uint lun = scsi_device->lun;
-
-       pDCB = kzalloc(sizeof(struct dc390_dcb), GFP_KERNEL);
-       if (!pDCB)
-               return -ENOMEM;
-
-       if (!pACB->DCBCnt++) {
-               pACB->pLinkDCB = pDCB;
-               pACB->pDCBRunRobin = pDCB;
-       } else {
-               pACB->pLastDCB->pNextDCB = pDCB;
-       }
-   
-       pDCB->pNextDCB = pACB->pLinkDCB;
-       pACB->pLastDCB = pDCB;
-
-       pDCB->pDCBACB = pACB;
-       pDCB->TargetID = id;
-       pDCB->TargetLUN = lun;
-
-       /*
-        * Some values are for all LUNs: Copy them 
-        * In a clean way: We would have an own structure for a SCSI-ID 
-        */
-       if (lun && (pDCB2 = dc390_findDCB(pACB, id, 0))) {
-               pDCB->DevMode = pDCB2->DevMode;
-               pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE;
-               pDCB->SyncPeriod = pDCB2->SyncPeriod;
-               pDCB->SyncOffset = pDCB2->SyncOffset;
-               pDCB->NegoPeriod = pDCB2->NegoPeriod;
-      
-               pDCB->CtrlR3 = pDCB2->CtrlR3;
-               pDCB->CtrlR4 = pDCB2->CtrlR4;
-       } else {
-               u8 index = pACB->AdapterIndex;
-               PEEprom prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
-
-               pDCB->DevMode = prom->EE_MODE1;
-               pDCB->NegoPeriod =
-                       (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2;
-               pDCB->CtrlR3 = FAST_CLK;
-               pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED;
-               if (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION)
-                       pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
-       }
-
-       if (pDCB->DevMode & SYNC_NEGO_)
-               pDCB->SyncMode |= SYNC_ENABLE;
-       else {
-               pDCB->SyncMode = 0;
-               pDCB->SyncOffset &= ~0x0f;
-       }
-
-       pDCB->CtrlR1 = pACB->pScsiHost->this_id;
-       if (pDCB->DevMode & PARITY_CHK_)
-               pDCB->CtrlR1 |= PARITY_ERR_REPO;
-
-       pACB->scan_devices = 1;
-       scsi_device->hostdata = pDCB;
-       return 0;
-}
-
-/**
- * dc390_slave_destroy - Called by the scsi mid layer to tell us about a
- * device that is going away.
- *
- * @scsi_device: The scsi device that we need to remove.
- */
-static void dc390_slave_destroy(struct scsi_device *scsi_device)
-{
-       struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata;
-       struct dc390_dcb* pDCB = (struct dc390_dcb*) scsi_device->hostdata;
-       struct dc390_dcb* pPrevDCB = pACB->pLinkDCB;
-
-       pACB->scan_devices = 0;
-
-       BUG_ON(pDCB->GoingSRBCnt > 1);
-       
-       if (pDCB == pACB->pLinkDCB) {
-               if (pACB->pLastDCB == pDCB) {
-                       pDCB->pNextDCB = NULL;
-                       pACB->pLastDCB = NULL;
-               }
-               pACB->pLinkDCB = pDCB->pNextDCB;
-       } else {
-               while (pPrevDCB->pNextDCB != pDCB)
-                       pPrevDCB = pPrevDCB->pNextDCB;
-               pPrevDCB->pNextDCB = pDCB->pNextDCB;
-               if (pDCB == pACB->pLastDCB)
-                       pACB->pLastDCB = pPrevDCB;
-       }
-
-       if (pDCB == pACB->pActiveDCB)
-               pACB->pActiveDCB = NULL;
-       if (pDCB == pACB->pLinkDCB)
-               pACB->pLinkDCB = pDCB->pNextDCB;
-       if (pDCB == pACB->pDCBRunRobin)
-               pACB->pDCBRunRobin = pDCB->pNextDCB;
-       kfree(pDCB); 
-       
-       pACB->DCBCnt--;
-}
-
-static int dc390_slave_configure(struct scsi_device *sdev)
-{
-       struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
-       struct dc390_dcb *dcb = (struct dc390_dcb *)sdev->hostdata;
-
-       acb->scan_devices = 0;
-       if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) {
-               dcb->SyncMode |= EN_TAG_QUEUEING;
-               scsi_activate_tcq(sdev, acb->TagMaxNum);
-       }
-
-       return 0;
-}
-
-static struct scsi_host_template driver_template = {
-       .module                 = THIS_MODULE,
-       .proc_name              = "tmscsim", 
-       .name                   = DC390_BANNER " V" DC390_VERSION,
-       .slave_alloc            = dc390_slave_alloc,
-       .slave_configure        = dc390_slave_configure,
-       .slave_destroy          = dc390_slave_destroy,
-       .queuecommand           = DC390_queuecommand,
-       .eh_abort_handler       = DC390_abort,
-       .eh_bus_reset_handler   = DC390_bus_reset,
-       .can_queue              = 1,
-       .this_id                = 7,
-       .sg_tablesize           = SG_ALL,
-       .cmd_per_lun            = 1,
-       .use_clustering         = ENABLE_CLUSTERING,
-       .max_sectors            = 0x4000, /* 8MiB = 16 * 1024 * 512 */
-};
-
-/***********************************************************************
- * Functions for access to DC390 EEPROM
- * and some to emulate it
- *
- **********************************************************************/
-
-static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
-{
-       u8 carryFlag = 1, j = 0x80, bval;
-       int i;
-
-       for (i = 0; i < 9; i++) {
-               if (carryFlag) {
-                       pci_write_config_byte(pdev, 0x80, 0x40);
-                       bval = 0xc0;
-               } else
-                       bval = 0x80;
-
-               udelay(160);
-               pci_write_config_byte(pdev, 0x80, bval);
-               udelay(160);
-               pci_write_config_byte(pdev, 0x80, 0);
-               udelay(160);
-
-               carryFlag = (cmd & j) ? 1 : 0;
-               j >>= 1;
-       }
-}
-
-static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
-{
-       int i;
-       u16 wval = 0;
-       u8 bval;
-
-       for (i = 0; i < 16; i++) {
-               wval <<= 1;
-
-               pci_write_config_byte(pdev, 0x80, 0x80);
-               udelay(160);
-               pci_write_config_byte(pdev, 0x80, 0x40);
-               udelay(160);
-               pci_read_config_byte(pdev, 0x00, &bval);
-
-               if (bval == 0x22)
-                       wval |= 1;
-       }
-
-       return wval;
-}
-
-static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
-{
-       u8 cmd = EEPROM_READ, i;
-
-       for (i = 0; i < 0x40; i++) {
-               pci_write_config_byte(pdev, 0xc0, 0);
-               udelay(160);
-
-               dc390_eeprom_prepare_read(pdev, cmd++);
-               *ptr++ = dc390_eeprom_get_data(pdev);
-
-               pci_write_config_byte(pdev, 0x80, 0);
-               pci_write_config_byte(pdev, 0x80, 0);
-               udelay(160);
-       }
-}
-
-/* Override EEprom values with explicitly set values */
-static void dc390_eeprom_override(u8 index)
-{
-       u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
-
-       /* Adapter Settings */
-       if (tmscsim[0] != -2)
-               ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */
-       if (tmscsim[3] != -2)
-               ptr[EE_MODE2] = (u8)tmscsim[3];
-       if (tmscsim[5] != -2)
-               ptr[EE_DELAY] = tmscsim[5];             /* Reset delay */
-       if (tmscsim[4] != -2)
-               ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4];   /* Tagged Cmds */
-
-       /* Device Settings */
-       for (id = 0; id < MAX_SCSI_ID; id++) {
-               if (tmscsim[2] != -2)
-                       ptr[id << 2] = (u8)tmscsim[2];          /* EE_MODE1 */
-               if (tmscsim[1] != -2)
-                       ptr[(id << 2) + 1] = (u8)tmscsim[1];    /* EE_Speed */
-       }
-}
-
-static int tmscsim_def[] = {
-       7,
-       0 /* 10MHz */,
-       PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
-       MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
-       3 /* 16 Tags per LUN */,
-       1 /* s delay after Reset */,
-};
-
-/* Copy defaults over set values where missing */
-static void dc390_fill_with_defaults (void)
-{
-       int i;
-
-       for (i = 0; i < 6; i++) {
-               if (tmscsim[i] < 0 || tmscsim[i] > 255)
-                       tmscsim[i] = tmscsim_def[i];
-       }
-
-       /* Sanity checks */
-       if (tmscsim[0] > 7)
-               tmscsim[0] = 7;
-       if (tmscsim[1] > 7)
-               tmscsim[1] = 4;
-       if (tmscsim[4] > 5)
-               tmscsim[4] = 4;
-       if (tmscsim[5] > 180)
-               tmscsim[5] = 180;
-}
-
-static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
-{
-       u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
-       u8 EEbuf[128];
-       u16 *ptr = (u16 *)EEbuf, wval = 0;
-       int i;
-
-       dc390_read_eeprom(pdev, ptr);
-       memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
-       memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], 
-              &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
-
-       dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
-
-       for (i = 0; i < 0x40; i++, ptr++)
-               wval += *ptr;
-
-       /* no Tekram EEprom found */
-       if (wval != 0x1234) {
-               int speed;
-
-               printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
-
-               /*
-                * XXX(hch): bogus, because we might have tekram and
-                *           non-tekram hbas in a single machine.
-                */
-               dc390_fill_with_defaults();
-
-               speed = dc390_clock_speed[tmscsim[1]];
-               printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), "
-                      "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", 
-                      tmscsim[0], tmscsim[1], speed / 10, speed % 10,
-                      (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
-       }
-}
-
-static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
-{
-       struct Scsi_Host *shost = pACB->pScsiHost;
-       u8 dstate;
-
-       /* Disable SCSI bus reset interrupt */
-       DC390_write8(CtrlReg1, DIS_INT_ON_SCSI_RST | shost->this_id);
-
-       if (pACB->Gmode2 & RST_SCSI_BUS) {
-               dc390_ResetSCSIBus(pACB);
-               udelay(1000);
-               pACB->last_reset = jiffies + HZ/2 +
-                       HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-       }
-
-       pACB->ACBFlag = 0;
-
-       /* Reset Pending INT */
-       DC390_read8(INT_Status);
-       
-       /* 250ms selection timeout */
-       DC390_write8(Scsi_TimeOut, SEL_TIMEOUT);
-       
-       /* Conversion factor = 0 , 40MHz clock */
-       DC390_write8(Clk_Factor, CLK_FREQ_40MHZ);
-       
-       /* NOP cmd - clear command register */
-       DC390_write8(ScsiCmd, NOP_CMD);
-       
-       /* Enable Feature and SCSI-2 */
-       DC390_write8(CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);
-       
-       /* Fast clock */
-       DC390_write8(CtrlReg3, FAST_CLK);
-
-       /* Negation */
-       DC390_write8(CtrlReg4, pACB->glitch_cfg | /* glitch eater */
-               (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ?
-                NEGATE_REQACKDATA : 0);
-       
-       /* Clear Transfer Count High: ID */
-       DC390_write8(CtcReg_High, 0);
-       DC390_write8(DMA_Cmd, DMA_IDLE_CMD);
-       DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-       DC390_write32(DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
-       dstate = DC390_read8(DMA_Status);
-       DC390_write8(DMA_Status, dstate);
-}
-
-static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct dc390_acb *pACB;
-       struct Scsi_Host *shost;
-       unsigned long io_port;
-       int error = -ENODEV, i;
-
-       if (pci_enable_device(pdev))
-               goto out;
-
-       pci_set_master(pdev);
-
-       error = -ENOMEM;
-       if (disable_clustering)
-               driver_template.use_clustering = DISABLE_CLUSTERING;
-       shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb));
-       if (!shost)
-               goto out_disable_device;
-
-       pACB = (struct dc390_acb *)shost->hostdata;
-       memset(pACB, 0, sizeof(struct dc390_acb));
-
-       dc390_check_eeprom(pdev, dc390_adapterCnt);
-       dc390_eeprom_override(dc390_adapterCnt);
-
-       io_port = pci_resource_start(pdev, 0);
-
-       shost->this_id = dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID];
-       shost->io_port = io_port;
-       shost->n_io_port = 0x80;
-       shost->irq = pdev->irq;
-       shost->base = io_port;
-       shost->unique_id = io_port;
-
-       pACB->last_reset = jiffies;
-       pACB->pScsiHost = shost;
-       pACB->IOPortBase = (u16) io_port;
-       pACB->IRQLevel = pdev->irq;
-       
-       shost->max_id = 8;
-
-       if (shost->max_id - 1 ==
-           dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID])
-               shost->max_id--;
-
-       if (dc390_eepromBuf[dc390_adapterCnt][EE_MODE2] & LUN_CHECK)
-               shost->max_lun = 8;
-       else
-               shost->max_lun = 1;
-
-       pACB->pFreeSRB = pACB->SRB_array;
-       pACB->SRBCount = MAX_SRB_CNT;
-       pACB->AdapterIndex = dc390_adapterCnt;
-       pACB->TagMaxNum =
-               2 << dc390_eepromBuf[dc390_adapterCnt][EE_TAG_CMD_NUM];
-       pACB->Gmode2 = dc390_eepromBuf[dc390_adapterCnt][EE_MODE2];
-
-       for (i = 0; i < pACB->SRBCount-1; i++)
-               pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
-       pACB->SRB_array[pACB->SRBCount-1].pNextSRB = NULL;
-       pACB->pTmpSRB = &pACB->TmpSRB;
-
-       pACB->sel_timeout = SEL_TIMEOUT;
-       pACB->glitch_cfg = EATER_25NS;
-       pACB->pdev = pdev;
-
-       if (!request_region(io_port, shost->n_io_port, "tmscsim")) {
-               printk(KERN_ERR "DC390: register IO ports error!\n");
-               goto out_host_put;
-       }
-
-       /* Reset Pending INT */
-       DC390_read8_(INT_Status, io_port);
-
-       if (request_irq(pdev->irq, do_DC390_Interrupt, IRQF_SHARED,
-                               "tmscsim", pACB)) {
-               printk(KERN_ERR "DC390: register IRQ error!\n");
-               goto out_release_region;
-       }
-
-       dc390_init_hw(pACB, dc390_adapterCnt);
-       
-       dc390_adapterCnt++;
-
-       pci_set_drvdata(pdev, shost);
-
-       error = scsi_add_host(shost, &pdev->dev);
-       if (error)
-               goto out_free_irq;
-       scsi_scan_host(shost);
-       return 0;
-
- out_free_irq:
-       free_irq(pdev->irq, pACB);
- out_release_region:
-       release_region(io_port, shost->n_io_port);
- out_host_put:
-       scsi_host_put(shost);
- out_disable_device:
-       pci_disable_device(pdev);
- out:
-       return error;
-}
-
-/**
- * dc390_remove_one - Called to remove a single instance of the adapter.
- *
- * @dev: The PCI device to remove.
- */
-static void dc390_remove_one(struct pci_dev *dev)
-{
-       struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
-       unsigned long iflags;
-       struct dc390_acb* pACB = (struct dc390_acb*) scsi_host->hostdata;
-       u8 bval;
-
-       scsi_remove_host(scsi_host);
-
-       spin_lock_irqsave(scsi_host->host_lock, iflags);
-       pACB->ACBFlag = RESET_DEV;
-       bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
-       DC390_write8 (CtrlReg1, bval);  /* disable interrupt */
-       if (pACB->Gmode2 & RST_SCSI_BUS)
-               dc390_ResetSCSIBus(pACB);
-       spin_unlock_irqrestore(scsi_host->host_lock, iflags);
-
-       free_irq(scsi_host->irq, pACB);
-       release_region(scsi_host->io_port, scsi_host->n_io_port);
-
-       pci_disable_device(dev);
-       scsi_host_put(scsi_host);
-}
-
-static struct pci_device_id tmscsim_pci_tbl[] = {
-       { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974,
-               PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
-
-static struct pci_driver dc390_driver = {
-       .name           = "tmscsim",
-       .id_table       = tmscsim_pci_tbl,
-       .probe          = dc390_probe_one,
-       .remove         = dc390_remove_one,
-};
-
-static int __init dc390_module_init(void)
-{
-       if (!disable_clustering) {
-               printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n");
-               printk(KERN_INFO "       with \"disable_clustering=1\" and report to maintainers\n");
-       }
-
-       if (tmscsim[0] == -1 || tmscsim[0] > 15) {
-               tmscsim[0] = 7;
-               tmscsim[1] = 4;
-               tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_;
-               tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION;
-               tmscsim[4] = 2;
-               tmscsim[5] = 10;
-               printk (KERN_INFO "DC390: Using safe settings.\n");
-       }
-
-       return pci_register_driver(&dc390_driver);
-}
-
-static void __exit dc390_module_exit(void)
-{
-       pci_unregister_driver(&dc390_driver);
-}
-
-module_init(dc390_module_init);
-module_exit(dc390_module_exit);
-
-#ifndef MODULE
-static int __init dc390_setup (char *str)
-{      
-       int ints[8],i, im;
-
-       get_options(str, ARRAY_SIZE(ints), ints);
-       im = ints[0];
-
-       if (im > 6) {
-               printk (KERN_NOTICE "DC390: ignore extra params!\n");
-               im = 6;
-       }
-
-       for (i = 0; i < im; i++)
-               tmscsim[i] = ints[i+1];
-       /* dc390_checkparams (); */
-       return 1;
-}
-
-__setup("tmscsim=", dc390_setup);
-#endif
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
deleted file mode 100644 (file)
index 3d1bb4a..0000000
+++ /dev/null
@@ -1,551 +0,0 @@
-/***********************************************************************
-;*     File Name : TMSCSIM.H                                          *
-;*                 TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter  *
-;*                 Device Driver                                      *
-;***********************************************************************/
-/* $Id: tmscsim.h,v 2.15.2.3 2000/11/17 20:52:27 garloff Exp $ */
-
-#ifndef _TMSCSIM_H
-#define _TMSCSIM_H
-
-#include <linux/types.h>
-
-#define SCSI_IRQ_NONE 255
-
-#define MAX_ADAPTER_NUM        4
-#define MAX_SG_LIST_BUF        16      /* Not used */
-#define MAX_SCSI_ID            8
-#define MAX_SRB_CNT            50      /* Max number of started commands */
-
-#define SEL_TIMEOUT            153     /* 250 ms selection timeout (@ 40 MHz) */
-
-/*
-;-----------------------------------------------------------------------
-; SCSI Request Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_srb
-{
-//u8           CmdBlock[12];
-
-struct dc390_srb       *pNextSRB;
-struct dc390_dcb       *pSRBDCB;
-struct scsi_cmnd       *pcmd;
-struct scatterlist     *pSegmentList;
-
-struct scatterlist Segmentx;   /* make a one entry of S/G list table */
-
-unsigned long  SGBusAddr;      /*;a segment starting address as seen by AM53C974A
-                                 in CPU endianness. We're only getting 32-bit bus
-                                 addresses by default */
-unsigned long  SGToBeXferLen;  /*; to be xfer length */
-unsigned long  TotalXferredLen;
-unsigned long  SavedTotXLen;
-unsigned long  Saved_Ptr;
-u32            SRBState;
-
-u8             SRBStatus;
-u8             SRBFlag;        /*; b0-AutoReqSense,b6-Read,b7-write */
-                               /*; b4-settimeout,b5-Residual valid */
-u8             AdaptStatus;
-u8             TargetStatus;
-
-u8             ScsiPhase;
-s8             TagNumber;
-u8             SGIndex;
-u8             SGcount;
-
-u8             MsgCnt;
-u8             EndMessage;
-
-u8             MsgInBuf[6];
-u8             MsgOutBuf[6];
-
-//u8           IORBFlag;       /*;81h-Reset, 2-retry */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Device Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_dcb
-{
-struct dc390_dcb       *pNextDCB;
-struct dc390_acb       *pDCBACB;
-
-/* Queued SRBs */
-struct dc390_srb       *pGoingSRB;
-struct dc390_srb       *pGoingLast;
-struct dc390_srb       *pActiveSRB;
-u8             GoingSRBCnt;
-
-u32            TagMask;
-
-u8             TargetID;       /*; SCSI Target ID  (SCSI Only) */
-u8             TargetLUN;      /*; SCSI Log.  Unit (SCSI Only) */
-u8             DevMode;
-u8             DCBFlag;
-
-u8             CtrlR1;
-u8             CtrlR3;
-u8             CtrlR4;
-
-u8             SyncMode;       /*; 0:async mode */
-u8             NegoPeriod;     /*;for nego. */
-u8             SyncPeriod;     /*;for reg. */
-u8             SyncOffset;     /*;for reg. and nego.(low nibble) */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Adapter Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_acb
-{
-struct Scsi_Host *pScsiHost;
-u16            IOPortBase;
-u8             IRQLevel;
-u8             status;
-
-u8             SRBCount;
-u8             AdapterIndex;   /*; nth Adapter this driver */
-u8             DCBCnt;
-
-u8             TagMaxNum;
-u8             ACBFlag;
-u8             Gmode2;
-u8             scan_devices;
-
-struct dc390_dcb       *pLinkDCB;
-struct dc390_dcb       *pLastDCB;
-struct dc390_dcb       *pDCBRunRobin;
-
-struct dc390_dcb       *pActiveDCB;
-struct dc390_srb       *pFreeSRB;
-struct dc390_srb       *pTmpSRB;
-
-u8             msgin123[4];
-u8             Connected;
-u8             pad;
-
-#if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0)
-spinlock_t     lock;
-#endif
-u8             sel_timeout;
-u8             glitch_cfg;
-
-u8             MsgLen;
-u8             Ignore_IRQ;     /* Not used */
-
-struct pci_dev *pdev;
-
-unsigned long   last_reset;
-unsigned long  Cmds;
-u32            SelLost;
-u32            SelConn;
-u32            CmdInQ;
-u32            CmdOutOfSRB;
-
-struct dc390_srb       TmpSRB;
-struct dc390_srb       SRB_array[MAX_SRB_CNT];         /* 50 SRBs */
-};
-
-
-/*;-----------------------------------------------------------------------*/
-
-
-#define BIT31  0x80000000
-#define BIT30  0x40000000
-#define BIT29  0x20000000
-#define BIT28  0x10000000
-#define BIT27  0x08000000
-#define BIT26  0x04000000
-#define BIT25  0x02000000
-#define BIT24  0x01000000
-#define BIT23  0x00800000
-#define BIT22  0x00400000
-#define BIT21  0x00200000
-#define BIT20  0x00100000
-#define BIT19  0x00080000
-#define BIT18  0x00040000
-#define BIT17  0x00020000
-#define BIT16  0x00010000
-#define BIT15  0x00008000
-#define BIT14  0x00004000
-#define BIT13  0x00002000
-#define BIT12  0x00001000
-#define BIT11  0x00000800
-#define BIT10  0x00000400
-#define BIT9   0x00000200
-#define BIT8   0x00000100
-#define BIT7   0x00000080
-#define BIT6   0x00000040
-#define BIT5   0x00000020
-#define BIT4   0x00000010
-#define BIT3   0x00000008
-#define BIT2   0x00000004
-#define BIT1   0x00000002
-#define BIT0   0x00000001
-
-/*;---UnitCtrlFlag */
-#define UNIT_ALLOCATED BIT0
-#define UNIT_INFO_CHANGED BIT1
-#define FORMATING_MEDIA BIT2
-#define UNIT_RETRY     BIT3
-
-/*;---UnitFlags */
-#define DASD_SUPPORT   BIT0
-#define SCSI_SUPPORT   BIT1
-#define ASPI_SUPPORT   BIT2
-
-/*;----SRBState machine definition */
-#define SRB_FREE       0
-#define SRB_WAIT       BIT0
-#define SRB_READY      BIT1
-#define SRB_MSGOUT     BIT2    /*;arbitration+msg_out 1st byte*/
-#define SRB_MSGIN      BIT3
-#define SRB_MSGIN_MULTI BIT4
-#define SRB_COMMAND    BIT5
-#define SRB_START_     BIT6    /*;arbitration+msg_out+command_out*/
-#define SRB_DISCONNECT BIT7
-#define SRB_DATA_XFER  BIT8
-#define SRB_XFERPAD    BIT9
-#define SRB_STATUS     BIT10
-#define SRB_COMPLETED  BIT11
-#define SRB_ABORT_SENT BIT12
-#define DO_SYNC_NEGO   BIT13
-#define SRB_UNEXPECT_RESEL BIT14
-
-/*;---SRBstatus */
-#define SRB_OK         BIT0
-#define ABORTION       BIT1
-#define OVER_RUN       BIT2
-#define UNDER_RUN      BIT3
-#define PARITY_ERROR   BIT4
-#define SRB_ERROR      BIT5
-
-/*;---ACBFlag */
-#define RESET_DEV      BIT0
-#define RESET_DETECT   BIT1
-#define RESET_DONE     BIT2
-
-/*;---DCBFlag */
-#define ABORT_DEV_     BIT0
-
-/*;---SRBFlag */
-#define DATAOUT        BIT7
-#define DATAIN         BIT6
-#define RESIDUAL_VALID BIT5
-#define ENABLE_TIMER   BIT4
-#define RESET_DEV0     BIT2
-#define ABORT_DEV      BIT1
-#define AUTO_REQSENSE  BIT0
-
-/*;---Adapter status */
-#define H_STATUS_GOOD   0
-#define H_SEL_TIMEOUT   0x11
-#define H_OVER_UNDER_RUN 0x12
-#define H_UNEXP_BUS_FREE 0x13
-#define H_TARGET_PHASE_F 0x14
-#define H_INVALID_CCB_OP 0x16
-#define H_LINK_CCB_BAD  0x17
-#define H_BAD_TARGET_DIR 0x18
-#define H_DUPLICATE_CCB  0x19
-#define H_BAD_CCB_OR_SG  0x1A
-#define H_ABORT         0x0FF
-
-/* cmd->result */
-#define RES_TARGET             0x000000FF      /* Target State */
-#define RES_TARGET_LNX         STATUS_MASK     /* Only official ... */
-#define RES_ENDMSG             0x0000FF00      /* End Message */
-#define RES_DID                        0x00FF0000      /* DID_ codes */
-#define RES_DRV                        0xFF000000      /* DRIVER_ codes */
-
-#define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
-#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt))
-
-#define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
-#define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
-#define SET_RES_MSG(who, msg) do { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } while (0)
-#define SET_RES_DID(who, did) do { who &= ~RES_DID; who |= (int)(did) << 16; } while (0)
-#define SET_RES_DRV(who, drv) do { who &= ~RES_DRV; who |= (int)(drv) << 24; } while (0)
-
-/*;---Sync_Mode */
-#define SYNC_DISABLE   0
-#define SYNC_ENABLE    BIT0
-#define SYNC_NEGO_DONE BIT1
-#define WIDE_ENABLE    BIT2    /* Not used ;-) */
-#define WIDE_NEGO_DONE BIT3    /* Not used ;-) */
-#define EN_TAG_QUEUEING        BIT4
-#define EN_ATN_STOP    BIT5
-
-#define SYNC_NEGO_OFFSET 15
-
-/*;---SCSI bus phase*/
-#define SCSI_DATA_OUT  0
-#define SCSI_DATA_IN   1
-#define SCSI_COMMAND   2
-#define SCSI_STATUS_   3
-#define SCSI_NOP0      4
-#define SCSI_NOP1      5
-#define SCSI_MSG_OUT   6
-#define SCSI_MSG_IN    7
-
-/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ /* One is missing ! */
-#define ABORT_TAG      0x0d
-
-/*
- *     SISC query queue
- */
-typedef struct {
-       dma_addr_t              saved_dma_handle;
-} dc390_cmd_scp_t;
-
-/*
-;==========================================================
-; EEPROM byte offset
-;==========================================================
-*/
-typedef  struct  _EEprom
-{
-u8     EE_MODE1;
-u8     EE_SPEED;
-u8     xx1;
-u8     xx2;
-} EEprom, *PEEprom;
-
-#define REAL_EE_ADAPT_SCSI_ID 64
-#define REAL_EE_MODE2  65
-#define REAL_EE_DELAY  66
-#define REAL_EE_TAG_CMD_NUM    67
-
-#define EE_ADAPT_SCSI_ID 32
-#define EE_MODE2       33
-#define EE_DELAY       34
-#define EE_TAG_CMD_NUM 35
-
-#define EE_LEN         40
-
-/*; EE_MODE1 bits definition*/
-#define PARITY_CHK_    BIT0
-#define SYNC_NEGO_     BIT1
-#define EN_DISCONNECT_ BIT2
-#define SEND_START_    BIT3
-#define TAG_QUEUEING_  BIT4
-
-/*; EE_MODE2 bits definition*/
-#define MORE2_DRV      BIT0
-#define GREATER_1G     BIT1
-#define RST_SCSI_BUS   BIT2
-#define ACTIVE_NEGATION BIT3
-#define NO_SEEK        BIT4
-#define LUN_CHECK      BIT5
-
-#define ENABLE_CE      1
-#define DISABLE_CE     0
-#define EEPROM_READ    0x80
-
-/*
-;==========================================================
-;      AMD 53C974 Registers bit Definition
-;==========================================================
-*/
-/*
-;====================
-; SCSI Register
-;====================
-*/
-
-/*; Command Reg.(+0CH) (rw) */
-#define DMA_COMMAND            BIT7
-#define NOP_CMD                0
-#define CLEAR_FIFO_CMD         1
-#define RST_DEVICE_CMD         2
-#define RST_SCSI_BUS_CMD       3
-
-#define INFO_XFER_CMD          0x10
-#define INITIATOR_CMD_CMPLTE   0x11
-#define MSG_ACCEPTED_CMD       0x12
-#define XFER_PAD_BYTE          0x18
-#define SET_ATN_CMD            0x1A
-#define RESET_ATN_CMD          0x1B
-
-#define SEL_WO_ATN             0x41    /* currently not used */
-#define SEL_W_ATN              0x42
-#define SEL_W_ATN_STOP         0x43
-#define SEL_W_ATN3             0x46
-#define EN_SEL_RESEL           0x44
-#define DIS_SEL_RESEL          0x45    /* currently not used */
-#define RESEL                  0x40    /* " */
-#define RESEL_ATN3             0x47    /* " */
-
-#define DATA_XFER_CMD          INFO_XFER_CMD
-
-
-/*; SCSI Status Reg.(+10H) (r) */
-#define INTERRUPT              BIT7
-#define ILLEGAL_OP_ERR         BIT6
-#define PARITY_ERR             BIT5
-#define COUNT_2_ZERO           BIT4
-#define GROUP_CODE_VALID       BIT3
-#define SCSI_PHASE_MASK        (BIT2+BIT1+BIT0) 
-/* BIT2: MSG phase; BIT1: C/D physe; BIT0: I/O phase */
-
-/*; Interrupt Status Reg.(+14H) (r) */
-#define SCSI_RESET             BIT7
-#define INVALID_CMD            BIT6
-#define DISCONNECTED           BIT5
-#define SERVICE_REQUEST        BIT4
-#define SUCCESSFUL_OP          BIT3
-#define RESELECTED             BIT2
-#define SEL_ATTENTION          BIT1
-#define SELECTED               BIT0
-
-/*; Internal State Reg.(+18H) (r) */
-#define SYNC_OFFSET_FLAG       BIT3
-#define INTRN_STATE_MASK       (BIT2+BIT1+BIT0)
-/* 0x04: Sel. successful (w/o stop), 0x01: Sel. successful (w/ stop) */
-
-/*; Clock Factor Reg.(+24H) (w) */
-#define CLK_FREQ_40MHZ         0
-#define CLK_FREQ_35MHZ         (BIT2+BIT1+BIT0)
-#define CLK_FREQ_30MHZ         (BIT2+BIT1)
-#define CLK_FREQ_25MHZ         (BIT2+BIT0)
-#define CLK_FREQ_20MHZ         BIT2
-#define CLK_FREQ_15MHZ         (BIT1+BIT0)
-#define CLK_FREQ_10MHZ         BIT1
-
-/*; Control Reg. 1(+20H) (rw) */
-#define EXTENDED_TIMING        BIT7
-#define DIS_INT_ON_SCSI_RST    BIT6
-#define PARITY_ERR_REPO        BIT4
-#define SCSI_ID_ON_BUS         (BIT2+BIT1+BIT0) /* host adapter ID */
-
-/*; Control Reg. 2(+2CH) (rw) */
-#define EN_FEATURE             BIT6
-#define EN_SCSI2_CMD           BIT3
-
-/*; Control Reg. 3(+30H) (rw) */
-#define ID_MSG_CHECK           BIT7
-#define EN_QTAG_MSG            BIT6
-#define EN_GRP2_CMD            BIT5
-#define FAST_SCSI              BIT4    /* ;10MB/SEC */
-#define FAST_CLK               BIT3    /* ;25 - 40 MHZ */
-
-/*; Control Reg. 4(+34H) (rw) */
-#define EATER_12NS             0
-#define EATER_25NS             BIT7
-#define EATER_35NS             BIT6
-#define EATER_0NS              (BIT7+BIT6)
-#define REDUCED_POWER          BIT5
-#define CTRL4_RESERVED         BIT4    /* must be 1 acc. to AM53C974.c */
-#define NEGATE_REQACKDATA      BIT2
-#define NEGATE_REQACK          BIT3
-
-#define GLITCH_TO_NS(x) (((~x>>6 & 2) >> 1) | ((x>>6 & 1) << 1 ^ (x>>6 & 2)))
-#define NS_TO_GLITCH(y) (((~y<<7) | ~((y<<6) ^ ((y<<5 & 1<<6) | ~0x40))) & 0xc0)
-
-/*
-;====================
-; DMA Register
-;====================
-*/
-/*; DMA Command Reg.(+40H) (rw) */
-#define READ_DIRECTION         BIT7
-#define WRITE_DIRECTION        0
-#define EN_DMA_INT             BIT6
-#define EN_PAGE_INT            BIT5    /* page transfer interrupt enable */
-#define MAP_TO_MDL             BIT4
-#define DIAGNOSTIC             BIT2
-#define DMA_IDLE_CMD           0
-#define DMA_BLAST_CMD          BIT0
-#define DMA_ABORT_CMD          BIT1
-#define DMA_START_CMD          (BIT1+BIT0)
-
-/*; DMA Status Reg.(+54H) (r) */
-#define PCI_MS_ABORT           BIT6
-#define BLAST_COMPLETE         BIT5
-#define SCSI_INTERRUPT         BIT4
-#define DMA_XFER_DONE          BIT3
-#define DMA_XFER_ABORT         BIT2
-#define DMA_XFER_ERROR         BIT1
-#define POWER_DOWN             BIT0
-
-/*; DMA SCSI Bus and Ctrl.(+70H) */
-#define EN_INT_ON_PCI_ABORT    BIT25
-#define WRT_ERASE_DMA_STAT     BIT24
-#define PW_DOWN_CTRL           BIT21
-#define SCSI_BUSY              BIT20
-#define SCLK                   BIT19
-#define SCAM                   BIT18
-#define SCSI_LINES             0x0003ffff
-
-/*
-;==========================================================
-; SCSI Chip register address offset
-;==========================================================
-;Registers are rw unless declared otherwise 
-*/
-#define CtcReg_Low     0x00    /* r    curr. transfer count */
-#define CtcReg_Mid     0x04    /* r */
-#define CtcReg_High    0x38    /* r */
-#define ScsiFifo       0x08
-#define ScsiCmd        0x0C
-#define Scsi_Status    0x10    /* r */
-#define INT_Status     0x14    /* r */
-#define Sync_Period    0x18    /* w */
-#define Sync_Offset    0x1C    /* w */
-#define Clk_Factor     0x24    /* w */
-#define CtrlReg1       0x20    
-#define CtrlReg2       0x2C
-#define CtrlReg3       0x30
-#define CtrlReg4       0x34
-#define DMA_Cmd        0x40
-#define DMA_XferCnt    0x44    /* rw   starting transfer count (32 bit) */
-#define DMA_XferAddr   0x48    /* rw   starting physical address (32 bit) */
-#define DMA_Wk_ByteCntr 0x4C   /* r    working byte counter */
-#define DMA_Wk_AddrCntr 0x50   /* r    working address counter */
-#define DMA_Status     0x54    /* r */
-#define DMA_MDL_Addr   0x58    /* rw   starting MDL address */
-#define DMA_Wk_MDL_Cntr 0x5C   /* r    working MDL counter */
-#define DMA_ScsiBusCtrl 0x70   /* rw   SCSI Bus, PCI/DMA Ctrl */
-
-#define StcReg_Low     CtcReg_Low      /* w    start transfer count */
-#define StcReg_Mid     CtcReg_Mid      /* w */
-#define StcReg_High    CtcReg_High     /* w */
-#define Scsi_Dest_ID   Scsi_Status     /* w */
-#define Scsi_TimeOut   INT_Status      /* w */
-#define Intern_State   Sync_Period     /* r */
-#define Current_Fifo   Sync_Offset     /* r    Curr. FIFO / int. state */
-
-
-#define DC390_read8(address)                   \
-       (inb (pACB->IOPortBase + (address)))
-
-#define DC390_read8_(address, base)            \
-       (inb ((u16)(base) + (address)))
-
-#define DC390_read16(address)                  \
-       (inw (pACB->IOPortBase + (address)))
-
-#define DC390_read32(address)                  \
-       (inl (pACB->IOPortBase + (address)))
-
-#define DC390_write8(address,value)            \
-       outb ((value), pACB->IOPortBase + (address))
-
-#define DC390_write8_(address,value,base)      \
-       outb ((value), (u16)(base) + (address))
-
-#define DC390_write16(address,value)           \
-       outw ((value), pACB->IOPortBase + (address))
-
-#define DC390_write32(address,value)           \
-       outl ((value), pACB->IOPortBase + (address))
-
-
-#endif /* _TMSCSIM_H */
index d8dcf36aed11ec5250b8e710cd2796544fac5d23..14eb50b95a1e32ec437efe1c0a192e21feb347e6 100644 (file)
@@ -696,25 +696,25 @@ static int u14_34f_slave_configure(struct scsi_device *dev) {
    if (TLDEV(dev->type) && dev->tagged_supported)
 
       if (tag_mode == TAG_SIMPLE) {
-         scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, tqd);
+         scsi_change_queue_depth(dev, tqd);
          tag_suffix = ", simple tags";
          }
       else if (tag_mode == TAG_ORDERED) {
-         scsi_adjust_queue_depth(dev, MSG_ORDERED_TAG, tqd);
+         scsi_change_queue_depth(dev, tqd);
          tag_suffix = ", ordered tags";
          }
       else {
-         scsi_adjust_queue_depth(dev, 0, tqd);
+         scsi_change_queue_depth(dev, tqd);
          tag_suffix = ", no tags";
          }
 
    else if (TLDEV(dev->type) && linked_comm) {
-      scsi_adjust_queue_depth(dev, 0, tqd);
+      scsi_change_queue_depth(dev, tqd);
       tag_suffix = ", untagged";
       }
 
    else {
-      scsi_adjust_queue_depth(dev, 0, utqd);
+      scsi_change_queue_depth(dev, utqd);
       tag_suffix = "";
       }
 
index 8adf067ff019344eaf0c42b97007b4abac65e79e..1c3467b8256612b96bafaee3827312e21711de28 100644 (file)
@@ -102,7 +102,6 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba)
        clkfreq = devm_kzalloc(dev, sz * sizeof(*clkfreq),
                        GFP_KERNEL);
        if (!clkfreq) {
-               dev_err(dev, "%s: no memory\n", "freq-table-hz");
                ret = -ENOMEM;
                goto out;
        }
@@ -112,19 +111,19 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba)
        if (ret && (ret != -EINVAL)) {
                dev_err(dev, "%s: error reading array %d\n",
                                "freq-table-hz", ret);
-               goto free_clkfreq;
+               return ret;
        }
 
        for (i = 0; i < sz; i += 2) {
                ret = of_property_read_string_index(np,
                                "clock-names", i/2, (const char **)&name);
                if (ret)
-                       goto free_clkfreq;
+                       goto out;
 
                clki = devm_kzalloc(dev, sizeof(*clki), GFP_KERNEL);
                if (!clki) {
                        ret = -ENOMEM;
-                       goto free_clkfreq;
+                       goto out;
                }
 
                clki->min_freq = clkfreq[i];
@@ -134,8 +133,6 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba)
                                clki->min_freq, clki->max_freq, clki->name);
                list_add_tail(&clki->list, &hba->clk_list_head);
        }
-free_clkfreq:
-       kfree(clkfreq);
 out:
        return ret;
 }
@@ -162,10 +159,8 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name,
        }
 
        vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
-       if (!vreg) {
-               dev_err(dev, "No memory for %s regulator\n", name);
-               goto out;
-       }
+       if (!vreg)
+               return -ENOMEM;
 
        vreg->name = kstrdup(name, GFP_KERNEL);
 
index 497c38a4a86615178e367e40666937e2d969b41f..2e4614b9dddfafb8377462cc942071ed1665f90b 100644 (file)
@@ -744,6 +744,8 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
        if (!ufshcd_is_clkgating_allowed(hba))
                return;
        device_remove_file(hba->dev, &hba->clk_gating.delay_attr);
+       cancel_work_sync(&hba->clk_gating.ungate_work);
+       cancel_delayed_work_sync(&hba->clk_gating.gate_work);
 }
 
 /* Must be called with host lock acquired */
@@ -2246,6 +2248,22 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
        return ret;
 }
 
+ /**
+ * ufshcd_init_pwr_info - setting the POR (power on reset)
+ * values in hba power info
+ * @hba: per-adapter instance
+ */
+static void ufshcd_init_pwr_info(struct ufs_hba *hba)
+{
+       hba->pwr_info.gear_rx = UFS_PWM_G1;
+       hba->pwr_info.gear_tx = UFS_PWM_G1;
+       hba->pwr_info.lane_rx = 1;
+       hba->pwr_info.lane_tx = 1;
+       hba->pwr_info.pwr_rx = SLOWAUTO_MODE;
+       hba->pwr_info.pwr_tx = SLOWAUTO_MODE;
+       hba->pwr_info.hs_rate = 0;
+}
+
 /**
  * ufshcd_get_max_pwr_mode - reads the max power mode negotiated with device
  * @hba: per-adapter instance
@@ -2695,7 +2713,7 @@ static void ufshcd_set_queue_depth(struct scsi_device *sdev)
 
        dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n",
                        __func__, lun_qdepth);
-       scsi_activate_tcq(sdev, lun_qdepth);
+       scsi_change_queue_depth(sdev, lun_qdepth);
 }
 
 /*
@@ -2765,11 +2783,9 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
        struct ufs_hba *hba;
 
        hba = shost_priv(sdev->host);
-       sdev->tagged_supported = 1;
 
        /* Mode sense(6) is not supported by UFS, so use Mode sense(10) */
        sdev->use_10_for_ms = 1;
-       scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
 
        /* allow SCSI layer to restart the device in case of errors */
        sdev->allow_restart = 1;
@@ -2789,34 +2805,16 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
  * ufshcd_change_queue_depth - change queue depth
  * @sdev: pointer to SCSI device
  * @depth: required depth to set
- * @reason: reason for changing the depth
  *
- * Change queue depth according to the reason and make sure
- * the max. limits are not crossed.
+ * Change queue depth and make sure the max. limits are not crossed.
  */
-static int ufshcd_change_queue_depth(struct scsi_device *sdev,
-               int depth, int reason)
+static int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth)
 {
        struct ufs_hba *hba = shost_priv(sdev->host);
 
        if (depth > hba->nutrs)
                depth = hba->nutrs;
-
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-       case SCSI_QDEPTH_RAMP_UP:
-               if (!sdev->tagged_supported)
-                       depth = 1;
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               scsi_track_queue_full(sdev, depth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       return depth;
+       return scsi_change_queue_depth(sdev, depth);
 }
 
 /**
@@ -2842,10 +2840,14 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev)
        struct ufs_hba *hba;
 
        hba = shost_priv(sdev->host);
-       scsi_deactivate_tcq(sdev, hba->nutrs);
        /* Drop the reference as it won't be needed anymore */
-       if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN)
+       if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) {
+               unsigned long flags;
+
+               spin_lock_irqsave(hba->host->host_lock, flags);
                hba->sdev_ufs_device = NULL;
+               spin_unlock_irqrestore(hba->host->host_lock, flags);
+       }
 }
 
 /**
@@ -4062,6 +4064,8 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
 static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
 {
        int ret = 0;
+       struct scsi_device *sdev_rpmb;
+       struct scsi_device *sdev_boot;
 
        hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0,
                ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL);
@@ -4070,56 +4074,33 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
                hba->sdev_ufs_device = NULL;
                goto out;
        }
+       scsi_device_put(hba->sdev_ufs_device);
 
-       hba->sdev_boot = __scsi_add_device(hba->host, 0, 0,
+       sdev_boot = __scsi_add_device(hba->host, 0, 0,
                ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL);
-       if (IS_ERR(hba->sdev_boot)) {
-               ret = PTR_ERR(hba->sdev_boot);
-               hba->sdev_boot = NULL;
+       if (IS_ERR(sdev_boot)) {
+               ret = PTR_ERR(sdev_boot);
                goto remove_sdev_ufs_device;
        }
+       scsi_device_put(sdev_boot);
 
-       hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
+       sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
                ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL);
-       if (IS_ERR(hba->sdev_rpmb)) {
-               ret = PTR_ERR(hba->sdev_rpmb);
-               hba->sdev_rpmb = NULL;
+       if (IS_ERR(sdev_rpmb)) {
+               ret = PTR_ERR(sdev_rpmb);
                goto remove_sdev_boot;
        }
+       scsi_device_put(sdev_rpmb);
        goto out;
 
 remove_sdev_boot:
-       scsi_remove_device(hba->sdev_boot);
+       scsi_remove_device(sdev_boot);
 remove_sdev_ufs_device:
        scsi_remove_device(hba->sdev_ufs_device);
 out:
        return ret;
 }
 
-/**
- * ufshcd_scsi_remove_wlus - Removes the W-LUs which were added by
- *                          ufshcd_scsi_add_wlus()
- * @hba: per-adapter instance
- *
- */
-static void ufshcd_scsi_remove_wlus(struct ufs_hba *hba)
-{
-       if (hba->sdev_ufs_device) {
-               scsi_remove_device(hba->sdev_ufs_device);
-               hba->sdev_ufs_device = NULL;
-       }
-
-       if (hba->sdev_boot) {
-               scsi_remove_device(hba->sdev_boot);
-               hba->sdev_boot = NULL;
-       }
-
-       if (hba->sdev_rpmb) {
-               scsi_remove_device(hba->sdev_rpmb);
-               hba->sdev_rpmb = NULL;
-       }
-}
-
 /**
  * ufshcd_probe_hba - probe hba to detect device and initialize
  * @hba: per-adapter instance
@@ -4134,6 +4115,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
        if (ret)
                goto out;
 
+       ufshcd_init_pwr_info(hba);
+
        /* UniPro link is active now */
        ufshcd_set_link_active(hba);
 
@@ -4235,6 +4218,8 @@ static struct scsi_host_template ufshcd_driver_template = {
        .cmd_per_lun            = UFSHCD_CMD_PER_LUN,
        .can_queue              = UFSHCD_CAN_QUEUE,
        .max_host_blocked       = 1,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
@@ -4264,12 +4249,18 @@ static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
 static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
+       if (!vreg)
+               return 0;
+
        return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA);
 }
 
 static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
                                         struct ufs_vreg *vreg)
 {
+       if (!vreg)
+               return 0;
+
        return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
 }
 
@@ -4471,7 +4462,7 @@ out:
                        if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled)
                                clk_disable_unprepare(clki->clk);
                }
-       } else if (!ret && on) {
+       } else if (on) {
                spin_lock_irqsave(hba->host->host_lock, flags);
                hba->clk_gating.state = CLKS_ON;
                spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -4675,11 +4666,25 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
 {
        unsigned char cmd[6] = { START_STOP };
        struct scsi_sense_hdr sshdr;
-       struct scsi_device *sdp = hba->sdev_ufs_device;
+       struct scsi_device *sdp;
+       unsigned long flags;
        int ret;
 
-       if (!sdp || !scsi_device_online(sdp))
-               return -ENODEV;
+       spin_lock_irqsave(hba->host->host_lock, flags);
+       sdp = hba->sdev_ufs_device;
+       if (sdp) {
+               ret = scsi_device_get(sdp);
+               if (!ret && !scsi_device_online(sdp)) {
+                       ret = -ENODEV;
+                       scsi_device_put(sdp);
+               }
+       } else {
+               ret = -ENODEV;
+       }
+       spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+       if (ret)
+               return ret;
 
        /*
         * If scsi commands fail, the scsi mid-layer schedules scsi error-
@@ -4707,17 +4712,18 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
                                     START_STOP_TIMEOUT, 0, NULL, REQ_PM);
        if (ret) {
                sdev_printk(KERN_WARNING, sdp,
-                         "START_STOP failed for power mode: %d\n", pwr_mode);
-               scsi_show_result(ret);
+                           "START_STOP failed for power mode: %d, result %x\n",
+                           pwr_mode, ret);
                if (driver_byte(ret) & DRIVER_SENSE) {
-                       scsi_show_sense_hdr(&sshdr);
-                       scsi_show_extd_sense(sshdr.asc, sshdr.ascq);
+                       scsi_show_sense_hdr(sdp, NULL, &sshdr);
+                       scsi_show_extd_sense(sdp, NULL, sshdr.asc, sshdr.ascq);
                }
        }
 
        if (!ret)
                hba->curr_dev_pwr_mode = pwr_mode;
 out:
+       scsi_device_put(sdp);
        hba->host->eh_noresume = 0;
        return ret;
 }
@@ -5087,7 +5093,7 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
        int ret = 0;
 
        if (!hba || !hba->is_powered)
-               goto out;
+               return 0;
 
        if (pm_runtime_suspended(hba->dev)) {
                if (hba->rpm_lvl == hba->spm_lvl)
@@ -5231,7 +5237,6 @@ EXPORT_SYMBOL(ufshcd_shutdown);
 void ufshcd_remove(struct ufs_hba *hba)
 {
        scsi_remove_host(hba->host);
-       ufshcd_scsi_remove_wlus(hba);
        /* disable interrupts */
        ufshcd_disable_intr(hba, hba->intr_mask);
        ufshcd_hba_stop(hba);
index 58ecdff5065c27d2dc3b6c563f641675799435dc..4a574aa458557a14ecc15b0d96d69dc8fa1fc9d8 100644 (file)
@@ -392,8 +392,6 @@ struct ufs_hba {
         * "UFS device" W-LU.
         */
        struct scsi_device *sdev_ufs_device;
-       struct scsi_device *sdev_rpmb;
-       struct scsi_device *sdev_boot;
 
        enum ufs_dev_pwr_mode curr_dev_pwr_mode;
        enum uic_link_state uic_link_state;
index b83846fc785964a93b9885e690b6de2f72175b4f..22e70126425bdc8072d8fbb34829d84afe65fbcd 100644 (file)
@@ -561,6 +561,15 @@ static int virtscsi_queuecommand_single(struct Scsi_Host *sh,
        return virtscsi_queuecommand(vscsi, &vscsi->req_vqs[0], sc);
 }
 
+static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi,
+                                                 struct scsi_cmnd *sc)
+{
+       u32 tag = blk_mq_unique_tag(sc->request);
+       u16 hwq = blk_mq_unique_tag_to_hwq(tag);
+
+       return &vscsi->req_vqs[hwq];
+}
+
 static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi,
                                               struct virtio_scsi_target_state *tgt)
 {
@@ -604,7 +613,12 @@ static int virtscsi_queuecommand_multi(struct Scsi_Host *sh,
        struct virtio_scsi *vscsi = shost_priv(sh);
        struct virtio_scsi_target_state *tgt =
                                scsi_target(sc->device)->hostdata;
-       struct virtio_scsi_vq *req_vq = virtscsi_pick_vq(vscsi, tgt);
+       struct virtio_scsi_vq *req_vq;
+
+       if (shost_use_blk_mq(sh))
+               req_vq = virtscsi_pick_vq_mq(vscsi, sc);
+       else
+               req_vq = virtscsi_pick_vq(vscsi, tgt);
 
        return virtscsi_queuecommand(vscsi, req_vq, sc);
 }
@@ -668,30 +682,13 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc)
  * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth
  * @sdev:      Virtscsi target whose queue depth to change
  * @qdepth:    New queue depth
- * @reason:    Reason for the queue depth change.
  */
-static int virtscsi_change_queue_depth(struct scsi_device *sdev,
-                                      int qdepth,
-                                      int reason)
+static int virtscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
        struct Scsi_Host *shost = sdev->host;
        int max_depth = shost->cmd_per_lun;
 
-       switch (reason) {
-       case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */
-               scsi_track_queue_full(sdev, qdepth);
-               break;
-       case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */
-       case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */
-               scsi_adjust_queue_depth(sdev,
-                                       scsi_get_tag_type(sdev),
-                                       min(max_depth, qdepth));
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       return sdev->queue_depth;
+       return scsi_change_queue_depth(sdev, min(max_depth, qdepth));
 }
 
 static int virtscsi_abort(struct scsi_cmnd *sc)
@@ -758,6 +755,7 @@ static struct scsi_host_template virtscsi_host_template_single = {
        .use_clustering = ENABLE_CLUSTERING,
        .target_alloc = virtscsi_target_alloc,
        .target_destroy = virtscsi_target_destroy,
+       .track_queue_depth = 1,
 };
 
 static struct scsi_host_template virtscsi_host_template_multi = {
@@ -776,6 +774,7 @@ static struct scsi_host_template virtscsi_host_template_multi = {
        .use_clustering = ENABLE_CLUSTERING,
        .target_alloc = virtscsi_target_alloc,
        .target_destroy = virtscsi_target_destroy,
+       .track_queue_depth = 1,
 };
 
 #define virtscsi_config_get(vdev, fld) \
@@ -983,6 +982,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
        shost->max_id = num_targets;
        shost->max_channel = 0;
        shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE;
+       shost->nr_hw_queues = num_queues;
 
        if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) {
                host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION |
index 598f65efaaec0e725851301959d138deda7cfaa1..0f133c1817de3421bb74133a8a48e79d9e0c3c3d 100644 (file)
@@ -504,33 +504,11 @@ static void pvscsi_setup_all_rings(const struct pvscsi_adapter *adapter)
        }
 }
 
-static int pvscsi_change_queue_depth(struct scsi_device *sdev,
-                                    int qdepth,
-                                    int reason)
+static int pvscsi_change_queue_depth(struct scsi_device *sdev, int qdepth)
 {
-       int max_depth;
-       struct Scsi_Host *shost = sdev->host;
-
-       if (reason != SCSI_QDEPTH_DEFAULT)
-               /*
-                * We support only changing default.
-                */
-               return -EOPNOTSUPP;
-
-       max_depth = shost->can_queue;
        if (!sdev->tagged_supported)
-               max_depth = 1;
-       if (qdepth > max_depth)
-               qdepth = max_depth;
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
-
-       if (sdev->inquiry_len > 7)
-               sdev_printk(KERN_INFO, sdev,
-                           "qdepth(%d), tagged(%d), simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
-                           sdev->queue_depth, sdev->tagged_supported,
-                           sdev->simple_tags, sdev->ordered_tags,
-                           sdev->scsi_level, (sdev->inquiry[7] & 2) >> 1);
-       return sdev->queue_depth;
+               qdepth = 1;
+       return scsi_change_queue_depth(sdev, qdepth);
 }
 
 /*
@@ -723,10 +701,6 @@ static int pvscsi_queue_ring(struct pvscsi_adapter *adapter,
        memcpy(e->cdb, cmd->cmnd, e->cdbLen);
 
        e->tag = SIMPLE_QUEUE_TAG;
-       if (sdev->tagged_supported &&
-           (cmd->tag == HEAD_OF_QUEUE_TAG ||
-            cmd->tag == ORDERED_QUEUE_TAG))
-               e->tag = cmd->tag;
 
        if (cmd->sc_data_direction == DMA_FROM_DEVICE)
                e->flags = PVSCSI_FLAG_CMD_DIR_TOHOST;
index 32674236fec773ec4cbac6dcd057cfc2873c3460..f94d73611ab40908b643264483c931d2e973f0cf 100644 (file)
@@ -1653,7 +1653,6 @@ static struct scsi_host_template driver_template = {
        .can_queue              = WD7000_Q,
        .this_id                = 7,
        .sg_tablesize           = WD7000_SG,
-       .cmd_per_lun            = 1,
        .unchecked_isa_dma      = 1,
        .use_clustering         = ENABLE_CLUSTERING,
 };
diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c
new file mode 100644 (file)
index 0000000..7702664
--- /dev/null
@@ -0,0 +1,996 @@
+/*
+ * Driver for Western Digital WD7193, WD7197 and WD7296 SCSI cards
+ * Copyright 2013 Ondrej Zary
+ *
+ * Original driver by
+ * Aaron Dewell <dewell@woods.net>
+ * Gaerti <Juergen.Gaertner@mbox.si.uni-hannover.de>
+ *
+ * HW documentation available in book:
+ *
+ * SPIDER Command Protocol
+ * by Chandru M. Sippy
+ * SCSI Storage Products (MCP)
+ * Western Digital Corporation
+ * 09-15-95
+ *
+ * http://web.archive.org/web/20070717175254/http://sun1.rrzn.uni-hannover.de/gaertner.juergen/wd719x/Linux/Docu/Spider/
+ */
+
+/*
+ * Driver workflow:
+ * 1. SCSI command is transformed to SCB (Spider Control Block) by the
+ *    queuecommand function.
+ * 2. The address of the SCB is stored in a list to be able to access it, if
+ *    something goes wrong.
+ * 3. The address of the SCB is written to the Controller, which loads the SCB
+ *    via BM-DMA and processes it.
+ * 4. After it has finished, it generates an interrupt, and sets registers.
+ *
+ * flaws:
+ *  - abort/reset functions
+ *
+ * ToDo:
+ *  - tagged queueing
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <linux/eeprom_93cx6.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include "wd719x.h"
+
+/* low-level register access */
+static inline u8 wd719x_readb(struct wd719x *wd, u8 reg)
+{
+       return ioread8(wd->base + reg);
+}
+
+static inline u32 wd719x_readl(struct wd719x *wd, u8 reg)
+{
+       return ioread32(wd->base + reg);
+}
+
+static inline void wd719x_writeb(struct wd719x *wd, u8 reg, u8 val)
+{
+       iowrite8(val, wd->base + reg);
+}
+
+static inline void wd719x_writew(struct wd719x *wd, u8 reg, u16 val)
+{
+       iowrite16(val, wd->base + reg);
+}
+
+static inline void wd719x_writel(struct wd719x *wd, u8 reg, u32 val)
+{
+       iowrite32(val, wd->base + reg);
+}
+
+/* wait until the command register is ready */
+static inline int wd719x_wait_ready(struct wd719x *wd)
+{
+       int i = 0;
+
+       do {
+               if (wd719x_readb(wd, WD719X_AMR_COMMAND) == WD719X_CMD_READY)
+                       return 0;
+               udelay(1);
+       } while (i++ < WD719X_WAIT_FOR_CMD_READY);
+
+       dev_err(&wd->pdev->dev, "command register is not ready: 0x%02x\n",
+               wd719x_readb(wd, WD719X_AMR_COMMAND));
+
+       return -ETIMEDOUT;
+}
+
+/* poll interrupt status register until command finishes */
+static inline int wd719x_wait_done(struct wd719x *wd, int timeout)
+{
+       u8 status;
+
+       while (timeout > 0) {
+               status = wd719x_readb(wd, WD719X_AMR_INT_STATUS);
+               if (status)
+                       break;
+               timeout--;
+               udelay(1);
+       }
+
+       if (timeout <= 0) {
+               dev_err(&wd->pdev->dev, "direct command timed out\n");
+               return -ETIMEDOUT;
+       }
+
+       if (status != WD719X_INT_NOERRORS) {
+               dev_err(&wd->pdev->dev, "direct command failed, status 0x%02x, SUE 0x%02x\n",
+                       status, wd719x_readb(wd, WD719X_AMR_SCB_ERROR));
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int wd719x_direct_cmd(struct wd719x *wd, u8 opcode, u8 dev, u8 lun,
+                            u8 tag, dma_addr_t data, int timeout)
+{
+       int ret = 0;
+
+       /* clear interrupt status register (allow command register to clear) */
+       wd719x_writeb(wd, WD719X_AMR_INT_STATUS, WD719X_INT_NONE);
+
+       /* Wait for the Command register to become free */
+       if (wd719x_wait_ready(wd))
+               return -ETIMEDOUT;
+
+       /* make sure we get NO interrupts */
+       dev |= WD719X_DISABLE_INT;
+       wd719x_writeb(wd, WD719X_AMR_CMD_PARAM, dev);
+       wd719x_writeb(wd, WD719X_AMR_CMD_PARAM_2, lun);
+       wd719x_writeb(wd, WD719X_AMR_CMD_PARAM_3, tag);
+       if (data)
+               wd719x_writel(wd, WD719X_AMR_SCB_IN, data);
+
+       /* clear interrupt status register again */
+       wd719x_writeb(wd, WD719X_AMR_INT_STATUS, WD719X_INT_NONE);
+
+       /* Now, write the command */
+       wd719x_writeb(wd, WD719X_AMR_COMMAND, opcode);
+
+       if (timeout)    /* wait for the command to complete */
+               ret = wd719x_wait_done(wd, timeout);
+
+       /* clear interrupt status register (clean up) */
+       if (opcode != WD719X_CMD_READ_FIRMVER)
+               wd719x_writeb(wd, WD719X_AMR_INT_STATUS, WD719X_INT_NONE);
+
+       return ret;
+}
+
+static void wd719x_destroy(struct wd719x *wd)
+{
+       struct wd719x_scb *scb;
+
+       /* stop the RISC */
+       if (wd719x_direct_cmd(wd, WD719X_CMD_SLEEP, 0, 0, 0, 0,
+                             WD719X_WAIT_FOR_RISC))
+               dev_warn(&wd->pdev->dev, "RISC sleep command failed\n");
+       /* disable RISC */
+       wd719x_writeb(wd, WD719X_PCI_MODE_SELECT, 0);
+
+       /* free all SCBs */
+       list_for_each_entry(scb, &wd->active_scbs, list)
+               pci_free_consistent(wd->pdev, sizeof(struct wd719x_scb), scb,
+                                   scb->phys);
+       list_for_each_entry(scb, &wd->free_scbs, list)
+               pci_free_consistent(wd->pdev, sizeof(struct wd719x_scb), scb,
+                                   scb->phys);
+       /* free internal buffers */
+       pci_free_consistent(wd->pdev, wd->fw_size, wd->fw_virt, wd->fw_phys);
+       wd->fw_virt = NULL;
+       pci_free_consistent(wd->pdev, WD719X_HASH_TABLE_SIZE, wd->hash_virt,
+                           wd->hash_phys);
+       wd->hash_virt = NULL;
+       pci_free_consistent(wd->pdev, sizeof(struct wd719x_host_param),
+                           wd->params, wd->params_phys);
+       wd->params = NULL;
+       free_irq(wd->pdev->irq, wd);
+}
+
+/* finish a SCSI command, mark SCB (if any) as free, unmap buffers */
+static void wd719x_finish_cmd(struct scsi_cmnd *cmd, int result)
+{
+       struct wd719x *wd = shost_priv(cmd->device->host);
+       struct wd719x_scb *scb = (struct wd719x_scb *) cmd->host_scribble;
+
+       if (scb) {
+               list_move(&scb->list, &wd->free_scbs);
+               dma_unmap_single(&wd->pdev->dev, cmd->SCp.dma_handle,
+                                SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
+               scsi_dma_unmap(cmd);
+       }
+       cmd->result = result << 16;
+       cmd->scsi_done(cmd);
+}
+
+/* Build a SCB and send it to the card */
+static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
+{
+       int i, count_sg;
+       unsigned long flags;
+       struct wd719x_scb *scb;
+       struct wd719x *wd = shost_priv(sh);
+       dma_addr_t phys;
+
+       cmd->host_scribble = NULL;
+
+       /* get a free SCB - either from existing ones or allocate a new one */
+       spin_lock_irqsave(wd->sh->host_lock, flags);
+       scb = list_first_entry_or_null(&wd->free_scbs, struct wd719x_scb, list);
+       if (scb) {
+               list_del(&scb->list);
+               phys = scb->phys;
+       } else {
+               spin_unlock_irqrestore(wd->sh->host_lock, flags);
+               scb = pci_alloc_consistent(wd->pdev, sizeof(struct wd719x_scb),
+                                          &phys);
+               spin_lock_irqsave(wd->sh->host_lock, flags);
+               if (!scb) {
+                       dev_err(&wd->pdev->dev, "unable to allocate SCB\n");
+                       wd719x_finish_cmd(cmd, DID_ERROR);
+                       spin_unlock_irqrestore(wd->sh->host_lock, flags);
+                       return 0;
+               }
+       }
+       memset(scb, 0, sizeof(struct wd719x_scb));
+       list_add(&scb->list, &wd->active_scbs);
+
+       scb->phys = phys;
+       scb->cmd = cmd;
+       cmd->host_scribble = (char *) scb;
+
+       scb->CDB_tag = 0;       /* Tagged queueing not supported yet */
+       scb->devid = cmd->device->id;
+       scb->lun = cmd->device->lun;
+
+       /* copy the command */
+       memcpy(scb->CDB, cmd->cmnd, cmd->cmd_len);
+
+       /* map sense buffer */
+       scb->sense_buf_length = SCSI_SENSE_BUFFERSIZE;
+       cmd->SCp.dma_handle = dma_map_single(&wd->pdev->dev, cmd->sense_buffer,
+                       SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
+       scb->sense_buf = cpu_to_le32(cmd->SCp.dma_handle);
+
+       /* request autosense */
+       scb->SCB_options |= WD719X_SCB_FLAGS_AUTO_REQUEST_SENSE;
+
+       /* check direction */
+       if (cmd->sc_data_direction == DMA_TO_DEVICE)
+               scb->SCB_options |= WD719X_SCB_FLAGS_CHECK_DIRECTION
+                                |  WD719X_SCB_FLAGS_PCI_TO_SCSI;
+       else if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+               scb->SCB_options |= WD719X_SCB_FLAGS_CHECK_DIRECTION;
+
+       /* Scather/gather */
+       count_sg = scsi_dma_map(cmd);
+       if (count_sg < 0) {
+               wd719x_finish_cmd(cmd, DID_ERROR);
+               spin_unlock_irqrestore(wd->sh->host_lock, flags);
+               return 0;
+       }
+       BUG_ON(count_sg > WD719X_SG);
+
+       if (count_sg) {
+               struct scatterlist *sg;
+
+               scb->data_length = cpu_to_le32(count_sg *
+                                              sizeof(struct wd719x_sglist));
+               scb->data_p = cpu_to_le32(scb->phys +
+                                         offsetof(struct wd719x_scb, sg_list));
+
+               scsi_for_each_sg(cmd, sg, count_sg, i) {
+                       scb->sg_list[i].ptr = cpu_to_le32(sg_dma_address(sg));
+                       scb->sg_list[i].length = cpu_to_le32(sg_dma_len(sg));
+               }
+               scb->SCB_options |= WD719X_SCB_FLAGS_DO_SCATTER_GATHER;
+       } else { /* zero length */
+               scb->data_length = 0;
+               scb->data_p = 0;
+       }
+
+       /* check if the Command register is free */
+       if (wd719x_readb(wd, WD719X_AMR_COMMAND) != WD719X_CMD_READY) {
+               spin_unlock_irqrestore(wd->sh->host_lock, flags);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       /* write pointer to the AMR */
+       wd719x_writel(wd, WD719X_AMR_SCB_IN, scb->phys);
+       /* send SCB opcode */
+       wd719x_writeb(wd, WD719X_AMR_COMMAND, WD719X_CMD_PROCESS_SCB);
+
+       spin_unlock_irqrestore(wd->sh->host_lock, flags);
+
+       return 0;
+}
+
+static int wd719x_chip_init(struct wd719x *wd)
+{
+       int i, ret;
+       u32 risc_init[3];
+       const struct firmware *fw_wcs, *fw_risc;
+       const char fwname_wcs[] = "wd719x-wcs.bin";
+       const char fwname_risc[] = "wd719x-risc.bin";
+
+       memset(wd->hash_virt, 0, WD719X_HASH_TABLE_SIZE);
+
+       /* WCS (sequencer) firmware */
+       ret = request_firmware(&fw_wcs, fwname_wcs, &wd->pdev->dev);
+       if (ret) {
+               dev_err(&wd->pdev->dev, "Unable to load firmware %s: %d\n",
+                       fwname_wcs, ret);
+               return ret;
+       }
+       /* RISC firmware */
+       ret = request_firmware(&fw_risc, fwname_risc, &wd->pdev->dev);
+       if (ret) {
+               dev_err(&wd->pdev->dev, "Unable to load firmware %s: %d\n",
+                       fwname_risc, ret);
+               release_firmware(fw_wcs);
+               return ret;
+       }
+       wd->fw_size = ALIGN(fw_wcs->size, 4) + fw_risc->size;
+
+       if (!wd->fw_virt)
+               wd->fw_virt = pci_alloc_consistent(wd->pdev, wd->fw_size,
+                                                  &wd->fw_phys);
+       if (!wd->fw_virt) {
+               ret = -ENOMEM;
+               goto wd719x_init_end;
+       }
+
+       /* make a fresh copy of WCS and RISC code */
+       memcpy(wd->fw_virt, fw_wcs->data, fw_wcs->size);
+       memcpy(wd->fw_virt + ALIGN(fw_wcs->size, 4), fw_risc->data,
+               fw_risc->size);
+
+       /* Reset the Spider Chip and adapter itself */
+       wd719x_writeb(wd, WD719X_PCI_PORT_RESET, WD719X_PCI_RESET);
+       udelay(WD719X_WAIT_FOR_RISC);
+       /* Clear PIO mode bits set by BIOS */
+       wd719x_writeb(wd, WD719X_AMR_CMD_PARAM, 0);
+       /* ensure RISC is not running */
+       wd719x_writeb(wd, WD719X_PCI_MODE_SELECT, 0);
+       /* ensure command port is ready */
+       wd719x_writeb(wd, WD719X_AMR_COMMAND, 0);
+       if (wd719x_wait_ready(wd)) {
+               ret = -ETIMEDOUT;
+               goto wd719x_init_end;
+       }
+
+       /* Transfer the first 2K words of RISC code to kick start the uP */
+       risc_init[0] = wd->fw_phys;                             /* WCS FW */
+       risc_init[1] = wd->fw_phys + ALIGN(fw_wcs->size, 4);    /* RISC FW */
+       risc_init[2] = wd->hash_phys;                           /* hash table */
+
+       /* clear DMA status */
+       wd719x_writeb(wd, WD719X_PCI_CHANNEL2_3STATUS, 0);
+
+       /* address to read firmware from */
+       wd719x_writel(wd, WD719X_PCI_EXTERNAL_ADDR, risc_init[1]);
+       /* base address to write firmware to (on card) */
+       wd719x_writew(wd, WD719X_PCI_INTERNAL_ADDR, WD719X_PRAM_BASE_ADDR);
+       /* size: first 2K words */
+       wd719x_writew(wd, WD719X_PCI_DMA_TRANSFER_SIZE, 2048 * 2);
+       /* start DMA */
+       wd719x_writeb(wd, WD719X_PCI_CHANNEL2_3CMD, WD719X_START_CHANNEL2_3DMA);
+
+       /* wait for DMA to complete */
+       i = WD719X_WAIT_FOR_RISC;
+       while (i-- > 0) {
+               u8 status = wd719x_readb(wd, WD719X_PCI_CHANNEL2_3STATUS);
+               if (status == WD719X_START_CHANNEL2_3DONE)
+                       break;
+               if (status == WD719X_START_CHANNEL2_3ABORT) {
+                       dev_warn(&wd->pdev->dev, "RISC bootstrap failed: DMA aborted\n");
+                       ret = -EIO;
+                       goto wd719x_init_end;
+               }
+               udelay(1);
+       }
+       if (i < 1) {
+               dev_warn(&wd->pdev->dev, "RISC bootstrap failed: DMA timeout\n");
+               ret = -ETIMEDOUT;
+               goto wd719x_init_end;
+       }
+
+       /* firmware is loaded, now initialize and wake up the RISC */
+       /* write RISC initialization long words to Spider */
+       wd719x_writel(wd, WD719X_AMR_SCB_IN, risc_init[0]);
+       wd719x_writel(wd, WD719X_AMR_SCB_IN + 4, risc_init[1]);
+       wd719x_writel(wd, WD719X_AMR_SCB_IN + 8, risc_init[2]);
+
+       /* disable interrupts during initialization of RISC */
+       wd719x_writeb(wd, WD719X_AMR_CMD_PARAM, WD719X_DISABLE_INT);
+
+       /* issue INITIALIZE RISC comand */
+       wd719x_writeb(wd, WD719X_AMR_COMMAND, WD719X_CMD_INIT_RISC);
+       /* enable advanced mode (wake up RISC) */
+       wd719x_writeb(wd, WD719X_PCI_MODE_SELECT, WD719X_ENABLE_ADVANCE_MODE);
+       udelay(WD719X_WAIT_FOR_RISC);
+
+       ret = wd719x_wait_done(wd, WD719X_WAIT_FOR_RISC);
+       /* clear interrupt status register */
+       wd719x_writeb(wd, WD719X_AMR_INT_STATUS, WD719X_INT_NONE);
+       if (ret) {
+               dev_warn(&wd->pdev->dev, "Unable to initialize RISC\n");
+               goto wd719x_init_end;
+       }
+       /* RISC is up and running */
+
+       /* Read FW version from RISC */
+       ret = wd719x_direct_cmd(wd, WD719X_CMD_READ_FIRMVER, 0, 0, 0, 0,
+                               WD719X_WAIT_FOR_RISC);
+       if (ret) {
+               dev_warn(&wd->pdev->dev, "Unable to read firmware version\n");
+               goto wd719x_init_end;
+       }
+       dev_info(&wd->pdev->dev, "RISC initialized with firmware version %.2x.%.2x\n",
+                       wd719x_readb(wd, WD719X_AMR_SCB_OUT + 1),
+                       wd719x_readb(wd, WD719X_AMR_SCB_OUT));
+
+       /* RESET SCSI bus */
+       ret = wd719x_direct_cmd(wd, WD719X_CMD_BUSRESET, 0, 0, 0, 0,
+                               WD719X_WAIT_FOR_SCSI_RESET);
+       if (ret) {
+               dev_warn(&wd->pdev->dev, "SCSI bus reset failed\n");
+               goto wd719x_init_end;
+       }
+
+       /* use HostParameter structure to set Spider's Host Parameter Block */
+       ret = wd719x_direct_cmd(wd, WD719X_CMD_SET_PARAM, 0,
+                               sizeof(struct wd719x_host_param), 0,
+                               wd->params_phys, WD719X_WAIT_FOR_RISC);
+       if (ret) {
+               dev_warn(&wd->pdev->dev, "Failed to set HOST PARAMETERS\n");
+               goto wd719x_init_end;
+       }
+
+       /* initiate SCAM (does nothing if disabled in BIOS) */
+       /* bug?: we should pass a mask of static IDs which we don't have */
+       ret = wd719x_direct_cmd(wd, WD719X_CMD_INIT_SCAM, 0, 0, 0, 0,
+                               WD719X_WAIT_FOR_SCSI_RESET);
+       if (ret) {
+               dev_warn(&wd->pdev->dev, "SCAM initialization failed\n");
+               goto wd719x_init_end;
+       }
+
+       /* clear AMR_BIOS_SHARE_INT register */
+       wd719x_writeb(wd, WD719X_AMR_BIOS_SHARE_INT, 0);
+
+wd719x_init_end:
+       release_firmware(fw_wcs);
+       release_firmware(fw_risc);
+
+       return ret;
+}
+
+static int wd719x_abort(struct scsi_cmnd *cmd)
+{
+       int action, result;
+       unsigned long flags;
+       struct wd719x_scb *scb = (struct wd719x_scb *)cmd->host_scribble;
+       struct wd719x *wd = shost_priv(cmd->device->host);
+
+       dev_info(&wd->pdev->dev, "abort command, tag: %x\n", cmd->tag);
+
+       action = /*cmd->tag ? WD719X_CMD_ABORT_TAG : */WD719X_CMD_ABORT;
+
+       spin_lock_irqsave(wd->sh->host_lock, flags);
+       result = wd719x_direct_cmd(wd, action, cmd->device->id,
+                                  cmd->device->lun, cmd->tag, scb->phys, 0);
+       spin_unlock_irqrestore(wd->sh->host_lock, flags);
+       if (result)
+               return FAILED;
+
+       return SUCCESS;
+}
+
+static int wd719x_reset(struct scsi_cmnd *cmd, u8 opcode, u8 device)
+{
+       int result;
+       unsigned long flags;
+       struct wd719x *wd = shost_priv(cmd->device->host);
+
+       dev_info(&wd->pdev->dev, "%s reset requested\n",
+                (opcode == WD719X_CMD_BUSRESET) ? "bus" : "device");
+
+       spin_lock_irqsave(wd->sh->host_lock, flags);
+       result = wd719x_direct_cmd(wd, opcode, device, 0, 0, 0,
+                                  WD719X_WAIT_FOR_SCSI_RESET);
+       spin_unlock_irqrestore(wd->sh->host_lock, flags);
+       if (result)
+               return FAILED;
+
+       return SUCCESS;
+}
+
+static int wd719x_dev_reset(struct scsi_cmnd *cmd)
+{
+       return wd719x_reset(cmd, WD719X_CMD_RESET, cmd->device->id);
+}
+
+static int wd719x_bus_reset(struct scsi_cmnd *cmd)
+{
+       return wd719x_reset(cmd, WD719X_CMD_BUSRESET, 0);
+}
+
+static int wd719x_host_reset(struct scsi_cmnd *cmd)
+{
+       struct wd719x *wd = shost_priv(cmd->device->host);
+       struct wd719x_scb *scb, *tmp;
+       unsigned long flags;
+       int result;
+
+       dev_info(&wd->pdev->dev, "host reset requested\n");
+       spin_lock_irqsave(wd->sh->host_lock, flags);
+       /* Try to reinit the RISC */
+       if (wd719x_chip_init(wd) == 0)
+               result = SUCCESS;
+       else
+               result = FAILED;
+
+       /* flush all SCBs */
+       list_for_each_entry_safe(scb, tmp, &wd->active_scbs, list) {
+               struct scsi_cmnd *tmp_cmd = scb->cmd;
+               wd719x_finish_cmd(tmp_cmd, result);
+       }
+       spin_unlock_irqrestore(wd->sh->host_lock, flags);
+
+       return result;
+}
+
+static int wd719x_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+                           sector_t capacity, int geom[])
+{
+       if (capacity >= 0x200000) {
+               geom[0] = 255;  /* heads */
+               geom[1] = 63;   /* sectors */
+       } else {
+               geom[0] = 64;   /* heads */
+               geom[1] = 32;   /* sectors */
+       }
+       geom[2] = sector_div(capacity, geom[0] * geom[1]);      /* cylinders */
+
+       return 0;
+}
+
+/* process a SCB-completion interrupt */
+static inline void wd719x_interrupt_SCB(struct wd719x *wd,
+                                       union wd719x_regs regs,
+                                       struct wd719x_scb *scb)
+{
+       struct scsi_cmnd *cmd;
+       int result;
+
+       /* now have to find result from card */
+       switch (regs.bytes.SUE) {
+       case WD719X_SUE_NOERRORS:
+               result = DID_OK;
+               break;
+       case WD719X_SUE_REJECTED:
+               dev_err(&wd->pdev->dev, "command rejected\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_SCBQFULL:
+               dev_err(&wd->pdev->dev, "SCB queue is full\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_TERM:
+               dev_dbg(&wd->pdev->dev, "SCB terminated by direct command\n");
+               result = DID_ABORT;     /* or DID_RESET? */
+               break;
+       case WD719X_SUE_CHAN1ABORT:
+       case WD719X_SUE_CHAN23ABORT:
+               result = DID_ABORT;
+               dev_err(&wd->pdev->dev, "DMA abort\n");
+               break;
+       case WD719X_SUE_CHAN1PAR:
+       case WD719X_SUE_CHAN23PAR:
+               result = DID_PARITY;
+               dev_err(&wd->pdev->dev, "DMA parity error\n");
+               break;
+       case WD719X_SUE_TIMEOUT:
+               result = DID_TIME_OUT;
+               dev_dbg(&wd->pdev->dev, "selection timeout\n");
+               break;
+       case WD719X_SUE_RESET:
+               dev_dbg(&wd->pdev->dev, "bus reset occured\n");
+               result = DID_RESET;
+               break;
+       case WD719X_SUE_BUSERROR:
+               dev_dbg(&wd->pdev->dev, "SCSI bus error\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_WRONGWAY:
+               dev_err(&wd->pdev->dev, "wrong data transfer direction\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_BADPHASE:
+               dev_err(&wd->pdev->dev, "invalid SCSI phase\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_TOOLONG:
+               dev_err(&wd->pdev->dev, "record too long\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_BUSFREE:
+               dev_err(&wd->pdev->dev, "unexpected bus free\n");
+               result = DID_NO_CONNECT; /* or DID_ERROR ???*/
+               break;
+       case WD719X_SUE_ARSDONE:
+               dev_dbg(&wd->pdev->dev, "auto request sense\n");
+               if (regs.bytes.SCSI == 0)
+                       result = DID_OK;
+               else
+                       result = DID_PARITY;
+               break;
+       case WD719X_SUE_IGNORED:
+               dev_err(&wd->pdev->dev, "target id %d ignored command\n",
+                       scb->cmd->device->id);
+               result = DID_NO_CONNECT;
+               break;
+       case WD719X_SUE_WRONGTAGS:
+               dev_err(&wd->pdev->dev, "reversed tags\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_BADTAGS:
+               dev_err(&wd->pdev->dev, "tag type not supported by target\n");
+               result = DID_ERROR;
+               break;
+       case WD719X_SUE_NOSCAMID:
+               dev_err(&wd->pdev->dev, "no SCAM soft ID available\n");
+               result = DID_ERROR;
+               break;
+       default:
+               dev_warn(&wd->pdev->dev, "unknown SUE error code: 0x%x\n",
+                        regs.bytes.SUE);
+               result = DID_ERROR;
+               break;
+       }
+       cmd = scb->cmd;
+
+       wd719x_finish_cmd(cmd, result);
+}
+
+static irqreturn_t wd719x_interrupt(int irq, void *dev_id)
+{
+       struct wd719x *wd = dev_id;
+       union wd719x_regs regs;
+       unsigned long flags;
+       u32 SCB_out;
+
+       spin_lock_irqsave(wd->sh->host_lock, flags);
+       /* read SCB pointer back from card */
+       SCB_out = wd719x_readl(wd, WD719X_AMR_SCB_OUT);
+       /* read all status info at once */
+       regs.all = cpu_to_le32(wd719x_readl(wd, WD719X_AMR_OP_CODE));
+
+       switch (regs.bytes.INT) {
+       case WD719X_INT_NONE:
+               spin_unlock_irqrestore(wd->sh->host_lock, flags);
+               return IRQ_NONE;
+       case WD719X_INT_LINKNOSTATUS:
+               dev_err(&wd->pdev->dev, "linked command completed with no status\n");
+               break;
+       case WD719X_INT_BADINT:
+               dev_err(&wd->pdev->dev, "unsolicited interrupt\n");
+               break;
+       case WD719X_INT_NOERRORS:
+       case WD719X_INT_LINKNOERRORS:
+       case WD719X_INT_ERRORSLOGGED:
+       case WD719X_INT_SPIDERFAILED:
+               /* was the cmd completed a direct or SCB command? */
+               if (regs.bytes.OPC == WD719X_CMD_PROCESS_SCB) {
+                       struct wd719x_scb *scb;
+                       list_for_each_entry(scb, &wd->active_scbs, list)
+                               if (SCB_out == scb->phys)
+                                       break;
+                       if (SCB_out == scb->phys)
+                               wd719x_interrupt_SCB(wd, regs, scb);
+                       else
+                               dev_err(&wd->pdev->dev, "card returned invalid SCB pointer\n");
+               } else
+                       dev_warn(&wd->pdev->dev, "direct command 0x%x completed\n",
+                                regs.bytes.OPC);
+               break;
+       case WD719X_INT_PIOREADY:
+               dev_err(&wd->pdev->dev, "card indicates PIO data ready but we never use PIO\n");
+               /* interrupt will not be cleared until all data is read */
+               break;
+       default:
+               dev_err(&wd->pdev->dev, "unknown interrupt reason: %d\n",
+                       regs.bytes.INT);
+
+       }
+       /* clear interrupt so another can happen */
+       wd719x_writeb(wd, WD719X_AMR_INT_STATUS, WD719X_INT_NONE);
+       spin_unlock_irqrestore(wd->sh->host_lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+static void wd719x_eeprom_reg_read(struct eeprom_93cx6 *eeprom)
+{
+       struct wd719x *wd = eeprom->data;
+       u8 reg = wd719x_readb(wd, WD719X_PCI_GPIO_DATA);
+
+       eeprom->reg_data_out = reg & WD719X_EE_DO;
+}
+
+static void wd719x_eeprom_reg_write(struct eeprom_93cx6 *eeprom)
+{
+       struct wd719x *wd = eeprom->data;
+       u8 reg = 0;
+
+       if (eeprom->reg_data_in)
+               reg |= WD719X_EE_DI;
+       if (eeprom->reg_data_clock)
+               reg |= WD719X_EE_CLK;
+       if (eeprom->reg_chip_select)
+               reg |= WD719X_EE_CS;
+
+       wd719x_writeb(wd, WD719X_PCI_GPIO_DATA, reg);
+}
+
+/* read config from EEPROM so it can be downloaded by the RISC on (re-)init */
+static void wd719x_read_eeprom(struct wd719x *wd)
+{
+       struct eeprom_93cx6 eeprom;
+       u8 gpio;
+       struct wd719x_eeprom_header header;
+
+       eeprom.data = wd;
+       eeprom.register_read = wd719x_eeprom_reg_read;
+       eeprom.register_write = wd719x_eeprom_reg_write;
+       eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+       /* set all outputs to low */
+       wd719x_writeb(wd, WD719X_PCI_GPIO_DATA, 0);
+       /* configure GPIO pins */
+       gpio = wd719x_readb(wd, WD719X_PCI_GPIO_CONTROL);
+       /* GPIO outputs */
+       gpio &= (~(WD719X_EE_CLK | WD719X_EE_DI | WD719X_EE_CS));
+       /* GPIO input */
+       gpio |= WD719X_EE_DO;
+       wd719x_writeb(wd, WD719X_PCI_GPIO_CONTROL, gpio);
+
+       /* read EEPROM header */
+       eeprom_93cx6_multireadb(&eeprom, 0, (u8 *)&header, sizeof(header));
+
+       if (header.sig1 == 'W' && header.sig2 == 'D')
+               eeprom_93cx6_multireadb(&eeprom, header.cfg_offset,
+                                       (u8 *)wd->params,
+                                       sizeof(struct wd719x_host_param));
+       else { /* default EEPROM values */
+               dev_warn(&wd->pdev->dev, "EEPROM signature is invalid (0x%02x 0x%02x), using default values\n",
+                        header.sig1, header.sig2);
+               wd->params->ch_1_th     = 0x10; /* 16 DWs = 64 B */
+               wd->params->scsi_conf   = 0x4c; /* 48ma, spue, parity check */
+               wd->params->own_scsi_id = 0x07; /* ID 7, SCAM disabled */
+               wd->params->sel_timeout = 0x4d; /* 250 ms */
+               wd->params->sleep_timer = 0x01;
+               wd->params->cdb_size    = cpu_to_le16(0x5555);  /* all 6 B */
+               wd->params->scsi_pad    = 0x1b;
+               if (wd->type == WD719X_TYPE_7193) /* narrow card - disable */
+                       wd->params->wide = cpu_to_le32(0x00000000);
+               else    /* initiate & respond to WIDE messages */
+                       wd->params->wide = cpu_to_le32(0xffffffff);
+               wd->params->sync        = cpu_to_le32(0xffffffff);
+               wd->params->soft_mask   = 0x00; /* all disabled */
+               wd->params->unsol_mask  = 0x00; /* all disabled */
+       }
+       /* disable TAGGED messages */
+       wd->params->tag_en = cpu_to_le16(0x0000);
+}
+
+/* Read card type from GPIO bits 1 and 3 */
+static enum wd719x_card_type wd719x_detect_type(struct wd719x *wd)
+{
+       u8 card = wd719x_readb(wd, WD719X_PCI_GPIO_CONTROL);
+
+       card |= WD719X_GPIO_ID_BITS;
+       wd719x_writeb(wd, WD719X_PCI_GPIO_CONTROL, card);
+       card = wd719x_readb(wd, WD719X_PCI_GPIO_DATA) & WD719X_GPIO_ID_BITS;
+       switch (card) {
+       case 0x08:
+               return WD719X_TYPE_7193;
+       case 0x02:
+               return WD719X_TYPE_7197;
+       case 0x00:
+               return WD719X_TYPE_7296;
+       default:
+               dev_warn(&wd->pdev->dev, "unknown card type 0x%x\n", card);
+               return WD719X_TYPE_UNKNOWN;
+       }
+}
+
+static int wd719x_board_found(struct Scsi_Host *sh)
+{
+       struct wd719x *wd = shost_priv(sh);
+       char *card_types[] = { "Unknown card", "WD7193", "WD7197", "WD7296" };
+       int ret;
+
+       INIT_LIST_HEAD(&wd->active_scbs);
+       INIT_LIST_HEAD(&wd->free_scbs);
+
+       sh->base = pci_resource_start(wd->pdev, 0);
+
+       wd->type = wd719x_detect_type(wd);
+
+       wd->sh = sh;
+       sh->irq = wd->pdev->irq;
+       wd->fw_virt = NULL;
+
+       /* memory area for host (EEPROM) parameters */
+       wd->params = pci_alloc_consistent(wd->pdev,
+                                         sizeof(struct wd719x_host_param),
+                                         &wd->params_phys);
+       if (!wd->params) {
+               dev_warn(&wd->pdev->dev, "unable to allocate parameter buffer\n");
+               return -ENOMEM;
+       }
+
+       /* memory area for the RISC for hash table of outstanding requests */
+       wd->hash_virt = pci_alloc_consistent(wd->pdev, WD719X_HASH_TABLE_SIZE,
+                                            &wd->hash_phys);
+       if (!wd->hash_virt) {
+               dev_warn(&wd->pdev->dev, "unable to allocate hash buffer\n");
+               ret = -ENOMEM;
+               goto fail_free_params;
+       }
+
+       ret = request_irq(wd->pdev->irq, wd719x_interrupt, IRQF_SHARED,
+                         "wd719x", wd);
+       if (ret) {
+               dev_warn(&wd->pdev->dev, "unable to assign IRQ %d\n",
+                        wd->pdev->irq);
+               goto fail_free_hash;
+       }
+
+       /* read parameters from EEPROM */
+       wd719x_read_eeprom(wd);
+
+       ret = wd719x_chip_init(wd);
+       if (ret)
+               goto fail_free_irq;
+
+       sh->this_id = wd->params->own_scsi_id & WD719X_EE_SCSI_ID_MASK;
+
+       dev_info(&wd->pdev->dev, "%s at I/O 0x%lx, IRQ %u, SCSI ID %d\n",
+                card_types[wd->type], sh->base, sh->irq, sh->this_id);
+
+       return 0;
+
+fail_free_irq:
+       free_irq(wd->pdev->irq, wd);
+fail_free_hash:
+       pci_free_consistent(wd->pdev, WD719X_HASH_TABLE_SIZE, wd->hash_virt,
+                           wd->hash_phys);
+fail_free_params:
+       pci_free_consistent(wd->pdev, sizeof(struct wd719x_host_param),
+                           wd->params, wd->params_phys);
+
+       return ret;
+}
+
+static struct scsi_host_template wd719x_template = {
+       .name                           = "Western Digital 719x",
+       .queuecommand                   = wd719x_queuecommand,
+       .eh_abort_handler               = wd719x_abort,
+       .eh_device_reset_handler        = wd719x_dev_reset,
+       .eh_bus_reset_handler           = wd719x_bus_reset,
+       .eh_host_reset_handler          = wd719x_host_reset,
+       .bios_param                     = wd719x_biosparam,
+       .proc_name                      = "wd719x",
+       .can_queue                      = 255,
+       .this_id                        = 7,
+       .sg_tablesize                   = WD719X_SG,
+       .cmd_per_lun                    = WD719X_CMD_PER_LUN,
+       .use_clustering                 = ENABLE_CLUSTERING,
+};
+
+static int wd719x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *d)
+{
+       int err;
+       struct Scsi_Host *sh;
+       struct wd719x *wd;
+
+       err = pci_enable_device(pdev);
+       if (err)
+               goto fail;
+
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               dev_warn(&pdev->dev, "Unable to set 32-bit DMA mask\n");
+               goto disable_device;
+       }
+
+       err = pci_request_regions(pdev, "wd719x");
+       if (err)
+               goto disable_device;
+       pci_set_master(pdev);
+
+       err = -ENODEV;
+       if (pci_resource_len(pdev, 0) == 0)
+               goto release_region;
+
+       err = -ENOMEM;
+       sh = scsi_host_alloc(&wd719x_template, sizeof(struct wd719x));
+       if (!sh)
+               goto release_region;
+
+       wd = shost_priv(sh);
+       wd->base = pci_iomap(pdev, 0, 0);
+       if (!wd->base)
+               goto free_host;
+       wd->pdev = pdev;
+
+       err = wd719x_board_found(sh);
+       if (err)
+               goto unmap;
+
+       err = scsi_add_host(sh, &wd->pdev->dev);
+       if (err)
+               goto destroy;
+
+       scsi_scan_host(sh);
+
+       pci_set_drvdata(pdev, sh);
+       return 0;
+
+destroy:
+       wd719x_destroy(wd);
+unmap:
+       pci_iounmap(pdev, wd->base);
+free_host:
+       scsi_host_put(sh);
+release_region:
+       pci_release_regions(pdev);
+disable_device:
+       pci_disable_device(pdev);
+fail:
+       return err;
+}
+
+
+static void wd719x_pci_remove(struct pci_dev *pdev)
+{
+       struct Scsi_Host *sh = pci_get_drvdata(pdev);
+       struct wd719x *wd = shost_priv(sh);
+
+       scsi_remove_host(sh);
+       wd719x_destroy(wd);
+       pci_iounmap(pdev, wd->base);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+
+       scsi_host_put(sh);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(wd719x_pci_table) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_WD, 0x3296) },
+       {}
+};
+
+MODULE_DEVICE_TABLE(pci, wd719x_pci_table);
+
+static struct pci_driver wd719x_pci_driver = {
+       .name =         "wd719x",
+       .id_table =     wd719x_pci_table,
+       .probe =        wd719x_pci_probe,
+       .remove =       wd719x_pci_remove,
+};
+
+static int __init wd719x_init(void)
+{
+       return pci_register_driver(&wd719x_pci_driver);
+}
+
+static void __exit wd719x_exit(void)
+{
+       pci_unregister_driver(&wd719x_pci_driver);
+}
+
+module_init(wd719x_init);
+module_exit(wd719x_exit);
+
+MODULE_DESCRIPTION("Western Digital WD7193/7197/7296 SCSI driver");
+MODULE_AUTHOR("Ondrej Zary, Aaron Dewell, Juergen Gaertner");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("wd719x-wcs.bin");
+MODULE_FIRMWARE("wd719x-risc.bin");
diff --git a/drivers/scsi/wd719x.h b/drivers/scsi/wd719x.h
new file mode 100644 (file)
index 0000000..185e30e
--- /dev/null
@@ -0,0 +1,249 @@
+#ifndef _WD719X_H_
+#define _WD719X_H_
+
+#define WD719X_SG 255          /* Scatter/gather size */
+#define WD719X_CMD_PER_LUN 1   /* We should be able to do linked commands, but
+                                * this is 1 for now to be safe. */
+
+struct wd719x_sglist {
+       __le32 ptr;
+       __le32 length;
+} __packed;
+
+enum wd719x_card_type {
+       WD719X_TYPE_UNKNOWN = 0,
+       WD719X_TYPE_7193,
+       WD719X_TYPE_7197,
+       WD719X_TYPE_7296,
+};
+
+union wd719x_regs {
+       __le32 all;     /* All Status at once */
+       struct {
+               u8 OPC;         /* Opcode register */
+               u8 SCSI;        /* SCSI Errors */
+               u8 SUE;         /* Spider unique Errors */
+               u8 INT;         /* Interrupt Status */
+       } bytes;
+};
+
+/* Spider Command Block (SCB) */
+struct wd719x_scb {
+       __le32 Int_SCB; /* 00-03 Internal SCB link pointer (must be cleared) */
+       u8 SCB_opcode;  /* 04 SCB Command opcode */
+       u8 CDB_tag;     /* 05 SCSI Tag byte for CDB queues (0 if untagged) */
+       u8 lun;         /* 06 SCSI LUN */
+       u8 devid;       /* 07 SCSI Device ID */
+       u8 CDB[16];     /* 08-23 SCSI CDB (16 bytes as defined by ANSI spec. */
+       __le32 data_p;  /* 24-27 Data transfer address (or SG list address) */
+       __le32 data_length; /* 28-31 Data transfer Length (or SG list length) */
+       __le32 CDB_link;    /* 32-35 SCSI CDB Link Ptr */
+       __le32 sense_buf;   /* 36-39 Auto request sense buffer address */
+       u8 sense_buf_length;/* 40 Auto request sense transfer length */
+       u8 reserved;    /* 41 reserved */
+       u8 SCB_options; /* 42 SCB-options */
+       u8 SCB_tag_msg; /* 43 Tagged messages options */
+       /* Not filled in by host */
+       __le32 req_ptr; /* 44-47 Ptr to Host Request returned on interrupt */
+       u8 host_opcode; /* 48 Host Command Opcode (same as AMR_00) */
+       u8 scsi_stat;   /* 49 SCSI Status returned */
+       u8 ret_error;   /* 50 SPIDER Unique Error Code returned (SUE) */
+       u8 int_stat;    /* 51 Message u8 / Interrupt Status byte returned */
+       __le32 transferred; /* 52-55 Bytes Transferred */
+       u8 last_trans[3];  /* 56-58 Bytes Transferred in last session */
+       u8 length;      /* 59 SCSI Messages Length (1-8) */
+       u8 sync_offset; /* 60 Synchronous offset */
+       u8 sync_rate;   /* 61 Synchronous rate */
+       u8 flags[2];    /* 62-63 SCB specific flags (local to each thread) */
+       /* everything below is for driver use (not used by card) */
+       dma_addr_t phys;        /* bus address of the SCB */
+       struct scsi_cmnd *cmd;  /* a copy of the pointer we were passed */
+       struct list_head list;
+       struct wd719x_sglist sg_list[WD719X_SG] __aligned(8); /* SG list */
+} __packed;
+
+struct wd719x {
+       struct Scsi_Host *sh;   /* pointer to host structure */
+       struct pci_dev *pdev;
+       void __iomem *base;
+       enum wd719x_card_type type; /* type of card */
+       void *fw_virt;          /* firmware buffer CPU address */
+       dma_addr_t fw_phys;     /* firmware buffer bus address */
+       size_t fw_size;         /* firmware buffer size */
+       struct wd719x_host_param *params; /* host parameters (EEPROM) */
+       dma_addr_t params_phys; /* host parameters bus address */
+       void *hash_virt;        /* hash table CPU address */
+       dma_addr_t hash_phys;   /* hash table bus address */
+       struct list_head active_scbs;
+       struct list_head free_scbs;
+};
+
+/* timeout delays in microsecs */
+#define WD719X_WAIT_FOR_CMD_READY      500
+#define WD719X_WAIT_FOR_RISC           2000
+#define WD719X_WAIT_FOR_SCSI_RESET     3000000
+
+/* All commands except 0x00 generate an interrupt */
+#define WD719X_CMD_READY       0x00 /* Command register ready (or noop) */
+#define WD719X_CMD_INIT_RISC   0x01 /* Initialize RISC */
+/* 0x02 is reserved */
+#define WD719X_CMD_BUSRESET    0x03 /* Assert SCSI bus reset */
+#define WD719X_CMD_READ_FIRMVER        0x04 /* Read the Firmware Revision */
+#define WD719X_CMD_ECHO_BYTES  0x05 /* Echo command bytes (DW) */
+/* 0x06 is reserved */
+/* 0x07 is reserved */
+#define WD719X_CMD_GET_PARAM   0x08 /* Get programmable parameters */
+#define WD719X_CMD_SET_PARAM   0x09 /* Set programmable parameters */
+#define WD719X_CMD_SLEEP       0x0a /* Put SPIDER to sleep */
+#define WD719X_CMD_READ_INIT   0x0b /* Read initialization parameters */
+#define WD719X_CMD_RESTORE_INIT        0x0c /* Restore initialization parameters */
+/* 0x0d is reserved */
+/* 0x0e is reserved */
+/* 0x0f is reserved */
+#define WD719X_CMD_ABORT_TAG   0x10 /* Send Abort tag message to target */
+#define WD719X_CMD_ABORT       0x11 /* Send Abort message to target */
+#define WD719X_CMD_RESET       0x12 /* Send Reset message to target */
+#define WD719X_CMD_INIT_SCAM   0x13 /* Initiate SCAM */
+#define WD719X_CMD_GET_SYNC    0x14 /* Get synchronous rates */
+#define WD719X_CMD_SET_SYNC    0x15 /* Set synchronous rates */
+#define WD719X_CMD_GET_WIDTH   0x16 /* Get SCSI bus width */
+#define WD719X_CMD_SET_WIDTH   0x17 /* Set SCSI bus width */
+#define WD719X_CMD_GET_TAGS    0x18 /* Get tag flags */
+#define WD719X_CMD_SET_TAGS    0x19 /* Set tag flags */
+#define WD719X_CMD_GET_PARAM2  0x1a /* Get programmable params (format 2) */
+#define WD719X_CMD_SET_PARAM2  0x1b /* Set programmable params (format 2) */
+/* Commands with request pointers (mailbox) */
+#define WD719X_CMD_PROCESS_SCB 0x80 /* Process SCSI Control Block (SCB) */
+/* No interrupt generated on acceptance of SCB pointer */
+
+/* interrupt status defines */
+#define WD719X_INT_NONE                0x00 /* No interrupt pending */
+#define WD719X_INT_NOERRORS    0x01 /* Command completed with no errors */
+#define WD719X_INT_LINKNOERRORS        0x02 /* link cmd completed with no errors */
+#define WD719X_INT_LINKNOSTATUS        0x03 /* link cmd completed with no flag set */
+#define WD719X_INT_ERRORSLOGGED        0x04 /* cmd completed with errors logged */
+#define WD719X_INT_SPIDERFAILED        0x05 /* cmd failed without valid SCSI status */
+#define WD719X_INT_BADINT      0x80 /* unsolicited interrupt */
+#define WD719X_INT_PIOREADY    0xf0 /* data ready for PIO output */
+
+/* Spider Unique Error Codes (SUE) */
+#define WD719X_SUE_NOERRORS    0x00 /* No errors detected by SPIDER */
+#define WD719X_SUE_REJECTED    0x01 /* Command Rejected (bad opcode/param) */
+#define WD719X_SUE_SCBQFULL    0x02 /* SCB queue full */
+/* 0x03 is reserved */
+#define WD719X_SUE_TERM                0x04 /* Host terminated SCB via primative cmd */
+#define WD719X_SUE_CHAN1PAR    0x05 /* PCI Channel 1 parity error occurred */
+#define WD719X_SUE_CHAN1ABORT  0x06 /* PCI Channel 1 system abort occurred */
+#define WD719X_SUE_CHAN23PAR   0x07 /* PCI Channel 2/3 parity error occurred */
+#define WD719X_SUE_CHAN23ABORT 0x08 /* PCI Channel 2/3 system abort occurred */
+#define WD719X_SUE_TIMEOUT     0x10 /* Selection/reselection timeout */
+#define WD719X_SUE_RESET       0x11 /* SCSI bus reset occurred */
+#define WD719X_SUE_BUSERROR    0x12 /* SCSI bus error */
+#define WD719X_SUE_WRONGWAY    0x13 /* Wrong data transfer dir set by target */
+#define WD719X_SUE_BADPHASE    0x14 /* SCSI phase illegal or unexpected */
+#define WD719X_SUE_TOOLONG     0x15 /* target requested too much data */
+#define WD719X_SUE_BUSFREE     0x16 /* Unexpected SCSI bus free */
+#define WD719X_SUE_ARSDONE     0x17 /* Auto request sense executed */
+#define WD719X_SUE_IGNORED     0x18 /* SCSI message was ignored by target */
+#define WD719X_SUE_WRONGTAGS   0x19 /* Tagged SCB & tags off (or vice versa) */
+#define WD719X_SUE_BADTAGS     0x1a /* Wrong tag message type for target */
+#define WD719X_SUE_NOSCAMID    0x1b /* No SCAM soft ID available */
+
+/* code sizes */
+#define        WD719X_HASH_TABLE_SIZE  4096
+
+/* Advanced Mode Registers */
+/* Regs 0x00..0x1f are for Advanced Mode of the card (RISC is running). */
+#define WD719X_AMR_COMMAND             0x00
+#define WD719X_AMR_CMD_PARAM           0x01
+#define WD719X_AMR_CMD_PARAM_2         0x02
+#define WD719X_AMR_CMD_PARAM_3         0x03
+#define WD719X_AMR_SCB_IN              0x04
+
+#define WD719X_AMR_BIOS_SHARE_INT      0x0f
+
+#define WD719X_AMR_SCB_OUT             0x18
+#define WD719X_AMR_OP_CODE             0x1c
+#define WD719X_AMR_SCSI_STATUS         0x1d
+#define WD719X_AMR_SCB_ERROR           0x1e
+#define WD719X_AMR_INT_STATUS          0x1f
+
+#define WD719X_DISABLE_INT     0x80
+
+/* SCB flags */
+#define WD719X_SCB_FLAGS_CHECK_DIRECTION       0x01
+#define WD719X_SCB_FLAGS_PCI_TO_SCSI           0x02
+#define WD719X_SCB_FLAGS_AUTO_REQUEST_SENSE    0x10
+#define WD719X_SCB_FLAGS_DO_SCATTER_GATHER     0x20
+#define WD719X_SCB_FLAGS_NO_DISCONNECT         0x40
+
+/* PCI Registers used for reset, initial code download */
+/* Regs 0x20..0x3f are for Normal (DOS) mode (RISC is asleep). */
+#define WD719X_PCI_GPIO_CONTROL                0x3C
+#define WD719X_PCI_GPIO_DATA           0x3D
+#define WD719X_PCI_PORT_RESET          0x3E
+#define WD719X_PCI_MODE_SELECT         0x3F
+
+#define WD719X_PCI_EXTERNAL_ADDR       0x60
+#define WD719X_PCI_INTERNAL_ADDR       0x64
+#define WD719X_PCI_DMA_TRANSFER_SIZE   0x66
+#define WD719X_PCI_CHANNEL2_3CMD       0x68
+#define WD719X_PCI_CHANNEL2_3STATUS    0x69
+
+#define WD719X_GPIO_ID_BITS            0x0a
+#define WD719X_PRAM_BASE_ADDR          0x00
+
+/* codes written to or read from the card */
+#define WD719X_PCI_RESET                0x01
+#define WD719X_ENABLE_ADVANCE_MODE      0x01
+
+#define WD719X_START_CHANNEL2_3DMA      0x17
+#define WD719X_START_CHANNEL2_3DONE     0x01
+#define WD719X_START_CHANNEL2_3ABORT    0x20
+
+/* 33C296 GPIO bits for EEPROM pins */
+#define WD719X_EE_DI   (1 << 1)
+#define WD719X_EE_CS   (1 << 2)
+#define WD719X_EE_CLK  (1 << 3)
+#define WD719X_EE_DO   (1 << 4)
+
+/* EEPROM contents */
+struct wd719x_eeprom_header {
+       u8 sig1;
+       u8 sig2;
+       u8 version;
+       u8 checksum;
+       u8 cfg_offset;
+       u8 cfg_size;
+       u8 setup_offset;
+       u8 setup_size;
+} __packed;
+
+#define WD719X_EE_SIG1         0
+#define WD719X_EE_SIG2         1
+#define WD719X_EE_VERSION      2
+#define WD719X_EE_CHECKSUM     3
+#define WD719X_EE_CFG_OFFSET   4
+#define WD719X_EE_CFG_SIZE     5
+#define WD719X_EE_SETUP_OFFSET 6
+#define WD719X_EE_SETUP_SIZE   7
+
+#define WD719X_EE_SCSI_ID_MASK 0xf
+
+/* SPIDER Host Parameters Block (=EEPROM configuration block) */
+struct wd719x_host_param {
+       u8 ch_1_th;     /* FIFO threshold */
+       u8 scsi_conf;   /* SCSI configuration */
+       u8 own_scsi_id; /* controller SCSI ID */
+       u8 sel_timeout; /* selection timeout*/
+       u8 sleep_timer; /* seep timer */
+       __le16 cdb_size;/* CDB size groups */
+       __le16 tag_en;  /* Tag msg enables (ID 0-15) */
+       u8 scsi_pad;    /* SCSI pad control */
+       __le32 wide;    /* WIDE msg options (ID 0-15) */
+       __le32 sync;    /* SYNC msg options (ID 0-15) */
+       u8 soft_mask;   /* soft error mask */
+       u8 unsol_mask;  /* unsolicited error mask */
+} __packed;
+
+#endif /* _WD719X_H_ */
index bc9dcc8cc3cef3620b9685e7d30592dff01ba016..51da2341280d76fcff7f0be7f7f4916363726fa5 100644 (file)
@@ -348,15 +348,15 @@ struct knav_range_info {
        list_for_each_entry(region, &kdev->regions, list)
 
 #define first_region(kdev)                                     \
-       list_first_entry(&kdev->regions, \
-                       struct knav_region, list)
+       list_first_entry_or_null(&kdev->regions, \
+                                struct knav_region, list)
 
 #define for_each_queue_range(kdev, range)                      \
        list_for_each_entry(range, &kdev->queue_ranges, list)
 
 #define first_queue_range(kdev)                                        \
-       list_first_entry(&kdev->queue_ranges, \
-                       struct knav_range_info, list)
+       list_first_entry_or_null(&kdev->queue_ranges, \
+                                struct knav_range_info, list)
 
 #define for_each_pool(kdev, pool)                              \
        list_for_each_entry(pool, &kdev->pools, list)
index 0a2c8634c48b30a38773f00f019f53e175e86371..9b8dd67326811264e226117b04c1c33b92d92fd1 100644 (file)
@@ -785,7 +785,7 @@ void *knav_pool_create(const char *name,
                dev_err(kdev->dev, "out of descs in region(%d) for pool(%s)\n",
                        region_id, name);
                ret = -ENOMEM;
-               goto err;
+               goto err_unlock;
        }
 
        /* Region maintains a sorted (by region offset) list of pools
@@ -815,15 +815,16 @@ void *knav_pool_create(const char *name,
                dev_err(kdev->dev, "pool(%s) create failed: fragmented desc pool in region(%d)\n",
                        name, region_id);
                ret = -ENOMEM;
-               goto err;
+               goto err_unlock;
        }
 
        mutex_unlock(&knav_dev_lock);
        kdesc_fill_pool(pool);
        return pool;
 
-err:
+err_unlock:
        mutex_unlock(&knav_dev_lock);
+err:
        kfree(pool->name);
        devm_kfree(kdev->dev, pool);
        return ERR_PTR(ret);
@@ -1305,14 +1306,14 @@ static void knav_free_queue_ranges(struct knav_device *kdev)
 static void knav_queue_free_regions(struct knav_device *kdev)
 {
        struct knav_region *region;
-       struct knav_pool *pool;
+       struct knav_pool *pool, *tmp;
        unsigned size;
 
        for (;;) {
                region = first_region(kdev);
                if (!region)
                        break;
-               list_for_each_entry(pool, &region->pools, region_inst)
+               list_for_each_entry_safe(pool, tmp, &region->pools, region_inst)
                        knav_pool_destroy(pool);
 
                size = region->virt_end - region->virt_start;
@@ -1639,7 +1640,7 @@ static int knav_queue_init_queues(struct knav_device *kdev)
        size = (1 << kdev->inst_shift) * kdev->num_queues_in_use;
        kdev->instances = devm_kzalloc(kdev->dev, size, GFP_KERNEL);
        if (!kdev->instances)
-               return -1;
+               return -ENOMEM;
 
        for_each_queue_range(kdev, range) {
                if (range->ops && range->ops->init_range)
index bf5ee9c8533094592d40a0328d0d5caffeb80fda..a928a7fc6be4b03aab6d3efa2b44d2bdf03dd871 100644 (file)
@@ -1,6 +1,15 @@
 #
 # ARM Versatile SoC drivers
 #
+config SOC_INTEGRATOR_CM
+       bool "SoC bus device for the ARM Integrator platform core modules"
+       depends on ARCH_INTEGRATOR
+       select SOC_BUS
+       help
+         Include support for the SoC bus on the ARM Integrator platform
+         core modules providing some sysfs information about the ASIC
+         variant.
+
 config SOC_REALVIEW
        bool "SoC bus device for the ARM RealView platforms"
        depends on ARCH_REALVIEW
index ad547435648ebd9638061a5e665cad771da90bef..cf612fe3a659709ab969ffbdcad5e797b9561b7a 100644 (file)
@@ -1 +1,2 @@
+obj-$(CONFIG_SOC_INTEGRATOR_CM)        += soc-integrator.o
 obj-$(CONFIG_SOC_REALVIEW)     += soc-realview.o
diff --git a/drivers/soc/versatile/soc-integrator.c b/drivers/soc/versatile/soc-integrator.c
new file mode 100644 (file)
index 0000000..a5d7d39
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * Author: Linus Walleij <linus.walleij@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.
+ *
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+
+#define INTEGRATOR_HDR_ID_OFFSET       0x00
+
+static u32 integrator_coreid;
+
+static const struct of_device_id integrator_cm_match[] = {
+       { .compatible = "arm,core-module-integrator", },
+       { }
+};
+
+static const char *integrator_arch_str(u32 id)
+{
+       switch ((id >> 16) & 0xff) {
+       case 0x00:
+               return "ASB little-endian";
+       case 0x01:
+               return "AHB little-endian";
+       case 0x03:
+               return "AHB-Lite system bus, bi-endian";
+       case 0x04:
+               return "AHB";
+       case 0x08:
+               return "AHB system bus, ASB processor bus";
+       default:
+               return "Unknown";
+       }
+}
+
+static const char *integrator_fpga_str(u32 id)
+{
+       switch ((id >> 12) & 0xf) {
+       case 0x01:
+               return "XC4062";
+       case 0x02:
+               return "XC4085";
+       case 0x03:
+               return "XVC600";
+       case 0x04:
+               return "EPM7256AE (Altera PLD)";
+       default:
+               return "Unknown";
+       }
+}
+
+static ssize_t integrator_get_manf(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%02x\n", integrator_coreid >> 24);
+}
+
+static struct device_attribute integrator_manf_attr =
+       __ATTR(manufacturer,  S_IRUGO, integrator_get_manf,  NULL);
+
+static ssize_t integrator_get_arch(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%s\n", integrator_arch_str(integrator_coreid));
+}
+
+static struct device_attribute integrator_arch_attr =
+       __ATTR(arch,  S_IRUGO, integrator_get_arch,  NULL);
+
+static ssize_t integrator_get_fpga(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%s\n", integrator_fpga_str(integrator_coreid));
+}
+
+static struct device_attribute integrator_fpga_attr =
+       __ATTR(fpga,  S_IRUGO, integrator_get_fpga,  NULL);
+
+static ssize_t integrator_get_build(struct device *dev,
+                              struct device_attribute *attr,
+                              char *buf)
+{
+       return sprintf(buf, "%02x\n", (integrator_coreid >> 4) & 0xFF);
+}
+
+static struct device_attribute integrator_build_attr =
+       __ATTR(build,  S_IRUGO, integrator_get_build,  NULL);
+
+static int __init integrator_soc_init(void)
+{
+       static struct regmap *syscon_regmap;
+       struct soc_device *soc_dev;
+       struct soc_device_attribute *soc_dev_attr;
+       struct device_node *np;
+       struct device *dev;
+       u32 val;
+       int ret;
+
+       np = of_find_matching_node(NULL, integrator_cm_match);
+       if (!np)
+               return -ENODEV;
+
+       syscon_regmap = syscon_node_to_regmap(np);
+       if (IS_ERR(syscon_regmap))
+               return PTR_ERR(syscon_regmap);
+
+       ret = regmap_read(syscon_regmap, INTEGRATOR_HDR_ID_OFFSET,
+                         &val);
+       if (ret)
+               return -ENODEV;
+       integrator_coreid = val;
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               return -ENOMEM;
+
+       soc_dev_attr->soc_id = "Integrator";
+       soc_dev_attr->machine = "Integrator";
+       soc_dev_attr->family = "Versatile";
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev)) {
+               kfree(soc_dev_attr);
+               return -ENODEV;
+       }
+       dev = soc_device_to_device(soc_dev);
+
+       device_create_file(dev, &integrator_manf_attr);
+       device_create_file(dev, &integrator_arch_attr);
+       device_create_file(dev, &integrator_fpga_attr);
+       device_create_file(dev, &integrator_build_attr);
+
+       dev_info(dev, "Detected ARM core module:\n");
+       dev_info(dev, "    Manufacturer: %02x\n", (val >> 24));
+       dev_info(dev, "    Architecture: %s\n", integrator_arch_str(val));
+       dev_info(dev, "    FPGA: %s\n", integrator_fpga_str(val));
+       dev_info(dev, "    Build: %02x\n", (val >> 4) & 0xFF);
+       dev_info(dev, "    Rev: %c\n", ('A' + (val & 0x03)));
+
+       return 0;
+}
+device_initcall(integrator_soc_init);
index cea8ea3491d2c38fb1b5196b783fd5bd08c01a0c..1a07bf540fecc384ef44112e0798c1afd798e9dd 100644 (file)
@@ -26,6 +26,7 @@ static const struct of_device_id realview_soc_of_match[] = {
        { .compatible = "arm,realview-pb11mp-soc", },
        { .compatible = "arm,realview-pba8-soc", },
        { .compatible = "arm,realview-pbx-soc", },
+       { }
 };
 
 static u32 realview_coreid;
index 72921588525008a0f4eaf615980eb884b8614108..d0d5542efc06db7a74b46a6a7230a4ce65ba53d5 100644 (file)
@@ -376,9 +376,6 @@ static void pump_transfers(unsigned long data)
        chip = dws->cur_chip;
        spi = message->spi;
 
-       if (unlikely(!chip->clk_div))
-               chip->clk_div = dws->max_freq / chip->speed_hz;
-
        if (message->state == ERROR_STATE) {
                message->status = -EIO;
                goto early_exit;
@@ -419,7 +416,7 @@ static void pump_transfers(unsigned long data)
        if (transfer->speed_hz) {
                speed = chip->speed_hz;
 
-               if (transfer->speed_hz != speed) {
+               if ((transfer->speed_hz != speed) || (!chip->clk_div)) {
                        speed = transfer->speed_hz;
 
                        /* clk_div doesn't support odd number */
@@ -581,7 +578,6 @@ static int dw_spi_setup(struct spi_device *spi)
                dev_err(&spi->dev, "No max speed HZ parameter\n");
                return -EINVAL;
        }
-       chip->speed_hz = spi->max_speed_hz;
 
        chip->tmode = 0; /* Tx & Rx */
        /* Default SPI mode is SCPOL = 0, SCPH = 0 */
@@ -669,6 +665,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
        master->cleanup = dw_spi_cleanup;
        master->transfer_one_message = dw_spi_transfer_one_message;
        master->max_speed_hz = dws->max_freq;
+       master->dev.of_node = dev->of_node;
 
        /* Basic HW init */
        spi_hw_init(dws);
index 448216025ce852ed10a95c1d2f689f512d6499bf..831ceb4a91f623e3932f3a684c6226fb35baf50c 100644 (file)
@@ -46,7 +46,7 @@
 
 #define SPI_TCR                        0x08
 
-#define SPI_CTAR(x)            (0x0c + (x * 4))
+#define SPI_CTAR(x)            (0x0c + (((x) & 0x3) * 4))
 #define SPI_CTAR_FMSZ(x)       (((x) & 0x0000000f) << 27)
 #define SPI_CTAR_CPOL(x)       ((x) << 26)
 #define SPI_CTAR_CPHA(x)       ((x) << 25)
@@ -70,7 +70,7 @@
 
 #define SPI_PUSHR              0x34
 #define SPI_PUSHR_CONT         (1 << 31)
-#define SPI_PUSHR_CTAS(x)      (((x) & 0x00000007) << 28)
+#define SPI_PUSHR_CTAS(x)      (((x) & 0x00000003) << 28)
 #define SPI_PUSHR_EOQ          (1 << 27)
 #define SPI_PUSHR_CTCNT        (1 << 26)
 #define SPI_PUSHR_PCS(x)       (((1 << x) & 0x0000003f) << 16)
index 835cdda6f4f586d1eb31fccf6904f4203a82ddcd..c76b7d7879dfe6539f80a174ceec9538db4f032c 100644 (file)
@@ -454,7 +454,7 @@ static int orion_spi_probe(struct platform_device *pdev)
        spi->master = master;
 
        of_id = of_match_device(orion_spi_of_match_table, &pdev->dev);
-       devdata = of_id->data;
+       devdata = (of_id) ? of_id->data : &orion_spi_dev_data;
        spi->devdata = devdata;
 
        spi->clk = devm_clk_get(&pdev->dev, NULL);
index f35f723816eacb94a0921247dfbe5dbe74611e23..fc2dd8441608fe31ad482800312fe26722c384e1 100644 (file)
@@ -1106,7 +1106,7 @@ err_rxdesc:
                     pl022->sgt_tx.nents, DMA_TO_DEVICE);
 err_tx_sgmap:
        dma_unmap_sg(rxchan->device->dev, pl022->sgt_rx.sgl,
-                    pl022->sgt_tx.nents, DMA_FROM_DEVICE);
+                    pl022->sgt_rx.nents, DMA_FROM_DEVICE);
 err_rx_sgmap:
        sg_free_table(&pl022->sgt_tx);
 err_alloc_tx_sg:
index d8a105f76837682b61670567aebe9741732f0f58..9e9e0f971e6c1ff651afae9861afbaf311eebe6c 100644 (file)
@@ -1274,7 +1274,9 @@ static int pxa2xx_spi_suspend(struct device *dev)
        if (status != 0)
                return status;
        write_SSCR0(0, drv_data->ioaddr);
-       clk_disable_unprepare(ssp->clk);
+
+       if (!pm_runtime_suspended(dev))
+               clk_disable_unprepare(ssp->clk);
 
        return 0;
 }
@@ -1288,7 +1290,8 @@ static int pxa2xx_spi_resume(struct device *dev)
        pxa2xx_spi_dma_resume(drv_data);
 
        /* Enable the SSP clock */
-       clk_prepare_enable(ssp->clk);
+       if (!pm_runtime_suspended(dev))
+               clk_prepare_enable(ssp->clk);
 
        /* Restore LPSS private register bits */
        lpss_ssp_setup(drv_data);
index f96ea8a38d640f988a797ecd448b2c9c64e9a8ed..87bc16f491f0ce8e3d78733d434a67189632e756 100644 (file)
 #define RXBUSY                                         (1 << 0)
 #define TXBUSY                                         (1 << 1)
 
+/* sclk_out: spi master internal logic in rk3x can support 50Mhz */
+#define MAX_SCLK_OUT           50000000
+
 enum rockchip_ssi_type {
        SSI_MOTO_SPI = 0,
        SSI_TI_SSP,
@@ -325,6 +328,8 @@ static int rockchip_spi_unprepare_message(struct spi_master *master,
 
        spin_unlock_irqrestore(&rs->lock, flags);
 
+       spi_enable_chip(rs, 0);
+
        return 0;
 }
 
@@ -381,6 +386,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi *rs)
        if (rs->tx)
                wait_for_idle(rs);
 
+       spi_enable_chip(rs, 0);
+
        return 0;
 }
 
@@ -392,8 +399,10 @@ static void rockchip_spi_dma_rxcb(void *data)
        spin_lock_irqsave(&rs->lock, flags);
 
        rs->state &= ~RXBUSY;
-       if (!(rs->state & TXBUSY))
+       if (!(rs->state & TXBUSY)) {
+               spi_enable_chip(rs, 0);
                spi_finalize_current_transfer(rs->master);
+       }
 
        spin_unlock_irqrestore(&rs->lock, flags);
 }
@@ -409,8 +418,10 @@ static void rockchip_spi_dma_txcb(void *data)
        spin_lock_irqsave(&rs->lock, flags);
 
        rs->state &= ~TXBUSY;
-       if (!(rs->state & RXBUSY))
+       if (!(rs->state & RXBUSY)) {
+               spi_enable_chip(rs, 0);
                spi_finalize_current_transfer(rs->master);
+       }
 
        spin_unlock_irqrestore(&rs->lock, flags);
 }
@@ -496,12 +507,19 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
                        dmacr |= RF_DMA_EN;
        }
 
+       if (WARN_ON(rs->speed > MAX_SCLK_OUT))
+               rs->speed = MAX_SCLK_OUT;
+
+       /* the minimum divsor is 2 */
+       if (rs->max_freq < 2 * rs->speed) {
+               clk_set_rate(rs->spiclk, 2 * rs->speed);
+               rs->max_freq = clk_get_rate(rs->spiclk);
+       }
+
        /* div doesn't support odd number */
        div = max_t(u32, rs->max_freq / rs->speed, 1);
        div = (div + 1) & 0xfffe;
 
-       spi_enable_chip(rs, 0);
-
        writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
 
        writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
@@ -515,8 +533,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
        spi_set_clk(rs, div);
 
        dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div);
-
-       spi_enable_chip(rs, 1);
 }
 
 static int rockchip_spi_transfer_one(
@@ -524,7 +540,7 @@ static int rockchip_spi_transfer_one(
                struct spi_device *spi,
                struct spi_transfer *xfer)
 {
-       int ret = 0;
+       int ret = 1;
        struct rockchip_spi *rs = spi_master_get_devdata(master);
 
        WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) &&
@@ -556,17 +572,27 @@ static int rockchip_spi_transfer_one(
                rs->tmode = CR0_XFM_RO;
 
        /* we need prepare dma before spi was enabled */
-       if (master->can_dma && master->can_dma(master, spi, xfer)) {
+       if (master->can_dma && master->can_dma(master, spi, xfer))
                rs->use_dma = 1;
-               rockchip_spi_prepare_dma(rs);
-       } else {
+       else
                rs->use_dma = 0;
-       }
 
        rockchip_spi_config(rs);
 
-       if (!rs->use_dma)
+       if (rs->use_dma) {
+               if (rs->tmode == CR0_XFM_RO) {
+                       /* rx: dma must be prepared first */
+                       rockchip_spi_prepare_dma(rs);
+                       spi_enable_chip(rs, 1);
+               } else {
+                       /* tx or tr: spi must be enabled first */
+                       spi_enable_chip(rs, 1);
+                       rockchip_spi_prepare_dma(rs);
+               }
+       } else {
+               spi_enable_chip(rs, 1);
                ret = rockchip_spi_pio_transfer(rs);
+       }
 
        return ret;
 }
index 39e2c0a55a2865acc6c50354cf90fa27263bc922..f63de781c72959c7c29b8fb2bb215f4e33b28f87 100644 (file)
@@ -562,9 +562,9 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 
        sspi->word_width = DIV_ROUND_UP(bits_per_word, 8);
        txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                          sspi->word_width;
+                                          (sspi->word_width >> 1);
        rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
-                                          sspi->word_width;
+                                          (sspi->word_width >> 1);
 
        if (!(spi->mode & SPI_CS_HIGH))
                regval |= SIRFSOC_SPI_CS_IDLE_STAT;
index ebcb33df2eb22facb58cebc10277c3ab12925a42..50f20f243981e68b0d007ff714476d0a29a42a80 100644 (file)
@@ -615,13 +615,13 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                                sg_free_table(sgt);
                                return -ENOMEM;
                        }
-                       sg_buf = page_address(vm_page) +
-                               ((size_t)buf & ~PAGE_MASK);
+                       sg_set_page(&sgt->sgl[i], vm_page,
+                                   min, offset_in_page(buf));
                } else {
                        sg_buf = buf;
+                       sg_set_buf(&sgt->sgl[i], sg_buf, min);
                }
 
-               sg_set_buf(&sgt->sgl[i], sg_buf, min);
 
                buf += min;
                len -= min;
index e3bc23bb588340f6856efe33e2d26fc4f6156ea4..e50039fb14749f0f700505c3be183f1ad52e693a 100644 (file)
@@ -82,10 +82,11 @@ struct spidev_data {
        struct spi_device       *spi;
        struct list_head        device_entry;
 
-       /* buffer is NULL unless this device is open (users > 0) */
+       /* TX/RX buffers are NULL unless this device is open (users > 0) */
        struct mutex            buf_lock;
        unsigned                users;
-       u8                      *buffer;
+       u8                      *tx_buffer;
+       u8                      *rx_buffer;
 };
 
 static LIST_HEAD(device_list);
@@ -135,7 +136,7 @@ static inline ssize_t
 spidev_sync_write(struct spidev_data *spidev, size_t len)
 {
        struct spi_transfer     t = {
-                       .tx_buf         = spidev->buffer,
+                       .tx_buf         = spidev->tx_buffer,
                        .len            = len,
                };
        struct spi_message      m;
@@ -149,7 +150,7 @@ static inline ssize_t
 spidev_sync_read(struct spidev_data *spidev, size_t len)
 {
        struct spi_transfer     t = {
-                       .rx_buf         = spidev->buffer,
+                       .rx_buf         = spidev->rx_buffer,
                        .len            = len,
                };
        struct spi_message      m;
@@ -179,7 +180,7 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
        if (status > 0) {
                unsigned long   missing;
 
-               missing = copy_to_user(buf, spidev->buffer, status);
+               missing = copy_to_user(buf, spidev->rx_buffer, status);
                if (missing == status)
                        status = -EFAULT;
                else
@@ -206,7 +207,7 @@ spidev_write(struct file *filp, const char __user *buf,
        spidev = filp->private_data;
 
        mutex_lock(&spidev->buf_lock);
-       missing = copy_from_user(spidev->buffer, buf, count);
+       missing = copy_from_user(spidev->tx_buffer, buf, count);
        if (missing == 0)
                status = spidev_sync_write(spidev, count);
        else
@@ -224,7 +225,7 @@ static int spidev_message(struct spidev_data *spidev,
        struct spi_transfer     *k_tmp;
        struct spi_ioc_transfer *u_tmp;
        unsigned                n, total;
-       u8                      *buf;
+       u8                      *tx_buf, *rx_buf;
        int                     status = -EFAULT;
 
        spi_message_init(&msg);
@@ -236,7 +237,8 @@ static int spidev_message(struct spidev_data *spidev,
         * We walk the array of user-provided transfers, using each one
         * to initialize a kernel version of the same transfer.
         */
-       buf = spidev->buffer;
+       tx_buf = spidev->tx_buffer;
+       rx_buf = spidev->rx_buffer;
        total = 0;
        for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers;
                        n;
@@ -250,20 +252,21 @@ static int spidev_message(struct spidev_data *spidev,
                }
 
                if (u_tmp->rx_buf) {
-                       k_tmp->rx_buf = buf;
+                       k_tmp->rx_buf = rx_buf;
                        if (!access_ok(VERIFY_WRITE, (u8 __user *)
                                                (uintptr_t) u_tmp->rx_buf,
                                                u_tmp->len))
                                goto done;
                }
                if (u_tmp->tx_buf) {
-                       k_tmp->tx_buf = buf;
-                       if (copy_from_user(buf, (const u8 __user *)
+                       k_tmp->tx_buf = tx_buf;
+                       if (copy_from_user(tx_buf, (const u8 __user *)
                                                (uintptr_t) u_tmp->tx_buf,
                                        u_tmp->len))
                                goto done;
                }
-               buf += k_tmp->len;
+               tx_buf += k_tmp->len;
+               rx_buf += k_tmp->len;
 
                k_tmp->cs_change = !!u_tmp->cs_change;
                k_tmp->tx_nbits = u_tmp->tx_nbits;
@@ -290,17 +293,17 @@ static int spidev_message(struct spidev_data *spidev,
                goto done;
 
        /* copy any rx data out of bounce buffer */
-       buf = spidev->buffer;
+       rx_buf = spidev->rx_buffer;
        for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {
                if (u_tmp->rx_buf) {
                        if (__copy_to_user((u8 __user *)
-                                       (uintptr_t) u_tmp->rx_buf, buf,
+                                       (uintptr_t) u_tmp->rx_buf, rx_buf,
                                        u_tmp->len)) {
                                status = -EFAULT;
                                goto done;
                        }
                }
-               buf += u_tmp->len;
+               rx_buf += u_tmp->len;
        }
        status = total;
 
@@ -508,22 +511,41 @@ static int spidev_open(struct inode *inode, struct file *filp)
                        break;
                }
        }
-       if (status == 0) {
-               if (!spidev->buffer) {
-                       spidev->buffer = kmalloc(bufsiz, GFP_KERNEL);
-                       if (!spidev->buffer) {
+
+       if (status) {
+               pr_debug("spidev: nothing for minor %d\n", iminor(inode));
+               goto err_find_dev;
+       }
+
+       if (!spidev->tx_buffer) {
+               spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL);
+               if (!spidev->tx_buffer) {
                                dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
                                status = -ENOMEM;
+                       goto err_find_dev;
                        }
                }
-               if (status == 0) {
-                       spidev->users++;
-                       filp->private_data = spidev;
-                       nonseekable_open(inode, filp);
+
+       if (!spidev->rx_buffer) {
+               spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL);
+               if (!spidev->rx_buffer) {
+                       dev_dbg(&spidev->spi->dev, "open/ENOMEM\n");
+                       status = -ENOMEM;
+                       goto err_alloc_rx_buf;
                }
-       } else
-               pr_debug("spidev: nothing for minor %d\n", iminor(inode));
+       }
+
+       spidev->users++;
+       filp->private_data = spidev;
+       nonseekable_open(inode, filp);
+
+       mutex_unlock(&device_list_lock);
+       return 0;
 
+err_alloc_rx_buf:
+       kfree(spidev->tx_buffer);
+       spidev->tx_buffer = NULL;
+err_find_dev:
        mutex_unlock(&device_list_lock);
        return status;
 }
@@ -542,8 +564,11 @@ static int spidev_release(struct inode *inode, struct file *filp)
        if (!spidev->users) {
                int             dofree;
 
-               kfree(spidev->buffer);
-               spidev->buffer = NULL;
+               kfree(spidev->tx_buffer);
+               spidev->tx_buffer = NULL;
+
+               kfree(spidev->rx_buffer);
+               spidev->rx_buffer = NULL;
 
                /* ... after we unbound from the underlying device? */
                spin_lock_irq(&spidev->spi_lock);
index 28b93d39a94eb6b76b72d1db051b2f52b48175e7..a673ffa34aa32a3dc6a6363450f5cfbb93599d98 100644 (file)
@@ -420,7 +420,7 @@ static ssize_t logger_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct logger_log *log = file_get_log(iocb->ki_filp);
        struct logger_entry header;
        struct timespec now;
-       size_t len, count;
+       size_t len, count, w_off;
 
        count = min_t(size_t, iocb->ki_nbytes, LOGGER_ENTRY_MAX_PAYLOAD);
 
@@ -452,11 +452,14 @@ static ssize_t logger_write_iter(struct kiocb *iocb, struct iov_iter *from)
        memcpy(log->buffer + log->w_off, &header, len);
        memcpy(log->buffer, (char *)&header + len, sizeof(header) - len);
 
-       len = min(count, log->size - log->w_off);
+       /* Work with a copy until we are ready to commit the whole entry */
+       w_off =  logger_offset(log, log->w_off + sizeof(struct logger_entry));
 
-       if (copy_from_iter(log->buffer + log->w_off, len, from) != len) {
+       len = min(count, log->size - w_off);
+
+       if (copy_from_iter(log->buffer + w_off, len, from) != len) {
                /*
-                * Note that by not updating w_off, this abandons the
+                * Note that by not updating log->w_off, this abandons the
                 * portion of the new entry that *was* successfully
                 * copied, just above.  This is intentional to avoid
                 * message corruption from missing fragments.
@@ -470,7 +473,7 @@ static ssize_t logger_write_iter(struct kiocb *iocb, struct iov_iter *from)
                return -EFAULT;
        }
 
-       log->w_off = logger_offset(log, log->w_off + count);
+       log->w_off = logger_offset(log, w_off + count);
        mutex_unlock(&log->mutex);
 
        /* wake up any blocked readers */
index a8bc2b567789c8188c1ad372301e0072fb1a0bbf..152f4c12ea43d204a7cbd38375673ff3674993bb 100644 (file)
@@ -426,6 +426,7 @@ config COMEDI_AIO_IIRO_16
 
 config COMEDI_II_PCI20KC
        tristate "Intelligent Instruments PCI-20001C carrier support"
+       depends on HAS_IOMEM
        ---help---
          Enable support for Intelligent Instruments PCI-20001C carrier
          PCI-20001, PCI-20006 and PCI-20341
@@ -667,7 +668,6 @@ config COMEDI_ADDI_APCI_2200
 config COMEDI_ADDI_APCI_3120
        tristate "ADDI-DATA APCI_3120/3001 support"
        depends on HAS_DMA
-       depends on VIRT_TO_BUS
        ---help---
          Enable support for ADDI-DATA APCI_3120/3001 cards
 
index 495969f46e76656dbcaf3523b102c43ca0df495f..9c32f027600936bcb25765b395f9d4f9406d932b 100644 (file)
@@ -1462,10 +1462,7 @@ static int __comedi_get_user_chanlist(struct comedi_device *dev,
        unsigned int *chanlist;
        int ret;
 
-       /* user_chanlist could be NULL for do_cmdtest ioctls */
-       if (!user_chanlist)
-               return 0;
-
+       cmd->chanlist = NULL;
        chanlist = memdup_user(user_chanlist,
                               cmd->chanlist_len * sizeof(unsigned int));
        if (IS_ERR(chanlist))
@@ -1609,13 +1606,18 @@ static int do_cmdtest_ioctl(struct comedi_device *dev,
 
        s = &dev->subdevices[cmd.subdev];
 
-       /* load channel/gain list */
-       ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &cmd);
-       if (ret)
-               return ret;
+       /* user_chanlist can be NULL for COMEDI_CMDTEST ioctl */
+       if (user_chanlist) {
+               /* load channel/gain list */
+               ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &cmd);
+               if (ret)
+                       return ret;
+       }
 
        ret = s->do_cmdtest(dev, s, &cmd);
 
+       kfree(cmd.chanlist);    /* free kernel copy of user chanlist */
+
        /* restore chanlist pointer before copying back */
        cmd.chanlist = (unsigned int __force *)user_chanlist;
 
@@ -1642,7 +1644,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev,
 
 */
 
-static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
+static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg,
                         void *file)
 {
        int ret = 0;
@@ -1679,7 +1681,7 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
        This function isn't protected by the semaphore, since
        we already own the lock.
 */
-static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg,
+static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg,
                           void *file)
 {
        struct comedi_subdevice *s;
@@ -1714,7 +1716,7 @@ static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg,
                nothing
 
 */
-static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
+static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg,
                           void *file)
 {
        struct comedi_subdevice *s;
@@ -1751,7 +1753,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
                nothing
 
 */
-static int do_poll_ioctl(struct comedi_device *dev, unsigned int arg,
+static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg,
                         void *file)
 {
        struct comedi_subdevice *s;
index 32a19264a170ce7290cc44c42ea77a5e15a6d5dd..2a29b9baec0de55471da2cf2e8d9201cdc335a86 100644 (file)
@@ -1559,14 +1559,16 @@ static int mxs_lradc_probe(struct platform_device *pdev)
        /* Grab all IRQ sources */
        for (i = 0; i < of_cfg->irq_count; i++) {
                lradc->irq[i] = platform_get_irq(pdev, i);
-               if (lradc->irq[i] < 0)
-                       return lradc->irq[i];
+               if (lradc->irq[i] < 0) {
+                       ret = lradc->irq[i];
+                       goto err_clk;
+               }
 
                ret = devm_request_irq(dev, lradc->irq[i],
                                        mxs_lradc_handle_irq, 0,
                                        of_cfg->irq_name[i], iio);
                if (ret)
-                       return ret;
+                       goto err_clk;
        }
 
        lradc->vref_mv = of_cfg->vref_mv;
@@ -1588,7 +1590,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
                                &mxs_lradc_trigger_handler,
                                &mxs_lradc_buffer_ops);
        if (ret)
-               return ret;
+               goto err_clk;
 
        ret = mxs_lradc_trigger_init(iio);
        if (ret)
@@ -1643,6 +1645,8 @@ err_dev:
        mxs_lradc_trigger_remove(iio);
 err_trig:
        iio_triggered_buffer_cleanup(iio);
+err_clk:
+       clk_disable_unprepare(lradc->clk);
        return ret;
 }
 
index d0c89d0457de086f30c97a8cad845dc8e578ac77..b6bd609c3655f9e0f78e778a6acc018ed1cfc4c0 100644 (file)
@@ -115,6 +115,7 @@ static const struct iio_chan_spec ad5933_channels[] = {
                .channel = 0,
                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
                .address = AD5933_REG_TEMP_DATA,
+               .scan_index = -1,
                .scan_type = {
                        .sign = 's',
                        .realbits = 14,
@@ -124,9 +125,7 @@ static const struct iio_chan_spec ad5933_channels[] = {
                .type = IIO_VOLTAGE,
                .indexed = 1,
                .channel = 0,
-               .extend_name = "real_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-               BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "real",
                .address = AD5933_REG_REAL_DATA,
                .scan_index = 0,
                .scan_type = {
@@ -138,9 +137,7 @@ static const struct iio_chan_spec ad5933_channels[] = {
                .type = IIO_VOLTAGE,
                .indexed = 1,
                .channel = 0,
-               .extend_name = "imag_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-               BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "imag",
                .address = AD5933_REG_IMAG_DATA,
                .scan_index = 1,
                .scan_type = {
@@ -749,14 +746,14 @@ static int ad5933_probe(struct i2c_client *client,
        indio_dev->name = id->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->channels = ad5933_channels;
-       indio_dev->num_channels = 1; /* only register temp0_input */
+       indio_dev->num_channels = ARRAY_SIZE(ad5933_channels);
 
        ret = ad5933_register_ring_funcs_and_init(indio_dev);
        if (ret)
                goto error_disable_reg;
 
-       /* skip temp0_input, register in0_(real|imag)_raw */
-       ret = iio_buffer_register(indio_dev, &ad5933_channels[1], 2);
+       ret = iio_buffer_register(indio_dev, ad5933_channels,
+               ARRAY_SIZE(ad5933_channels));
        if (ret)
                goto error_unreg_ring;
 
index 6014625920b04a42e22a32120f078ae346a76a0d..e969107ddb47e18727223a67b9ad5844ba65619e 100644 (file)
@@ -537,7 +537,8 @@ static const struct i2c_device_id isl29028_id[] = {
 MODULE_DEVICE_TABLE(i2c, isl29028_id);
 
 static const struct of_device_id isl29028_of_match[] = {
-       { .compatible = "isil,isl29028", },
+       { .compatible = "isl,isl29028", },
+       { .compatible = "isil,isl29028", },/* deprecated, don't use */
        { },
 };
 MODULE_DEVICE_TABLE(of, isl29028_of_match);
index 07318203a836e86155760c7ec16c595094b37489..e8c98cf570701d4c32a51269c844862aea3c5f70 100644 (file)
@@ -119,7 +119,6 @@ struct ade7758_state {
        u8                      *tx;
        u8                      *rx;
        struct mutex            buf_lock;
-       const struct iio_chan_spec *ade7758_ring_channels;
        struct spi_transfer     ring_xfer[4];
        struct spi_message      ring_msg;
        /*
index abc60067cd720272b345ca53d57e07a182b7ce87..fb373b89dcc2c5f090f0b98b3173e4ffb0d3634f 100644 (file)
@@ -634,9 +634,6 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_VOLTAGE,
                .indexed = 1,
                .channel = 0,
-               .extend_name = "raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = AD7758_WT(AD7758_PHASE_A, AD7758_VOLTAGE),
                .scan_index = 0,
                .scan_type = {
@@ -648,9 +645,6 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_CURRENT,
                .indexed = 1,
                .channel = 0,
-               .extend_name = "raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = AD7758_WT(AD7758_PHASE_A, AD7758_CURRENT),
                .scan_index = 1,
                .scan_type = {
@@ -662,9 +656,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 0,
-               .extend_name = "apparent_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "apparent",
                .address = AD7758_WT(AD7758_PHASE_A, AD7758_APP_PWR),
                .scan_index = 2,
                .scan_type = {
@@ -676,9 +668,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 0,
-               .extend_name = "active_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "active",
                .address = AD7758_WT(AD7758_PHASE_A, AD7758_ACT_PWR),
                .scan_index = 3,
                .scan_type = {
@@ -690,9 +680,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 0,
-               .extend_name = "reactive_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "reactive",
                .address = AD7758_WT(AD7758_PHASE_A, AD7758_REACT_PWR),
                .scan_index = 4,
                .scan_type = {
@@ -704,9 +692,6 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_VOLTAGE,
                .indexed = 1,
                .channel = 1,
-               .extend_name = "raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = AD7758_WT(AD7758_PHASE_B, AD7758_VOLTAGE),
                .scan_index = 5,
                .scan_type = {
@@ -718,9 +703,6 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_CURRENT,
                .indexed = 1,
                .channel = 1,
-               .extend_name = "raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = AD7758_WT(AD7758_PHASE_B, AD7758_CURRENT),
                .scan_index = 6,
                .scan_type = {
@@ -732,9 +714,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 1,
-               .extend_name = "apparent_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "apparent",
                .address = AD7758_WT(AD7758_PHASE_B, AD7758_APP_PWR),
                .scan_index = 7,
                .scan_type = {
@@ -746,9 +726,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 1,
-               .extend_name = "active_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "active",
                .address = AD7758_WT(AD7758_PHASE_B, AD7758_ACT_PWR),
                .scan_index = 8,
                .scan_type = {
@@ -760,9 +738,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 1,
-               .extend_name = "reactive_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "reactive",
                .address = AD7758_WT(AD7758_PHASE_B, AD7758_REACT_PWR),
                .scan_index = 9,
                .scan_type = {
@@ -774,9 +750,6 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_VOLTAGE,
                .indexed = 1,
                .channel = 2,
-               .extend_name = "raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = AD7758_WT(AD7758_PHASE_C, AD7758_VOLTAGE),
                .scan_index = 10,
                .scan_type = {
@@ -788,9 +761,6 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_CURRENT,
                .indexed = 1,
                .channel = 2,
-               .extend_name = "raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .address = AD7758_WT(AD7758_PHASE_C, AD7758_CURRENT),
                .scan_index = 11,
                .scan_type = {
@@ -802,9 +772,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 2,
-               .extend_name = "apparent_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "apparent",
                .address = AD7758_WT(AD7758_PHASE_C, AD7758_APP_PWR),
                .scan_index = 12,
                .scan_type = {
@@ -816,9 +784,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 2,
-               .extend_name = "active_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "active",
                .address = AD7758_WT(AD7758_PHASE_C, AD7758_ACT_PWR),
                .scan_index = 13,
                .scan_type = {
@@ -830,9 +796,7 @@ static const struct iio_chan_spec ade7758_channels[] = {
                .type = IIO_POWER,
                .indexed = 1,
                .channel = 2,
-               .extend_name = "reactive_raw",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .extend_name = "reactive",
                .address = AD7758_WT(AD7758_PHASE_C, AD7758_REACT_PWR),
                .scan_index = 14,
                .scan_type = {
@@ -873,13 +837,14 @@ static int ade7758_probe(struct spi_device *spi)
                goto error_free_rx;
        }
        st->us = spi;
-       st->ade7758_ring_channels = &ade7758_channels[0];
        mutex_init(&st->buf_lock);
 
        indio_dev->name = spi->dev.driver->name;
        indio_dev->dev.parent = &spi->dev;
        indio_dev->info = &ade7758_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = ade7758_channels;
+       indio_dev->num_channels = ARRAY_SIZE(ade7758_channels);
 
        ret = ade7758_configure_ring(indio_dev);
        if (ret)
index c0accf8cce93f1fdbd3ad3a3d4213220ddb87b17..6e90064907427596e8a5ee0d00c12ea046635874 100644 (file)
@@ -85,17 +85,16 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
  **/
 static int ade7758_ring_preenable(struct iio_dev *indio_dev)
 {
-       struct ade7758_state *st = iio_priv(indio_dev);
        unsigned channel;
 
-       if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
+       if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
                return -EINVAL;
 
        channel = find_first_bit(indio_dev->active_scan_mask,
                                 indio_dev->masklength);
 
        ade7758_write_waveform_type(&indio_dev->dev,
-               st->ade7758_ring_channels[channel].address);
+               indio_dev->channels[channel].address);
 
        return 0;
 }
index 9935e66935af191e25d1ee4fee4ff70564228f20..eddef9cd2e1662087a4595cc48382b88c121832f 100644 (file)
@@ -275,11 +275,11 @@ u8 rtw_sitesurvey_cmd(struct adapter  *padapter, struct ndis_802_11_ssid *ssid,
        if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
                rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
 
-       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (ph2c == NULL)
                return _FAIL;
 
-       psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_KERNEL);
+       psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
        if (psurveyPara == NULL) {
                kfree(ph2c);
                return _FAIL;
@@ -405,7 +405,7 @@ u8 rtw_joinbss_cmd(struct adapter  *padapter, struct wlan_network *pnetwork)
        else
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.Ssid));
 
-       pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (pcmd == NULL) {
                res = _FAIL;
                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
@@ -755,13 +755,13 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
        u8      res = _SUCCESS;
 
 
-       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (ph2c == NULL) {
                res = _FAIL;
                goto exit;
        }
 
-       pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
+       pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
        if (pdrvextra_cmd_parm == NULL) {
                kfree(ph2c);
                res = _FAIL;
@@ -967,13 +967,13 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
        u8      res = _SUCCESS;
 
        if (enqueue) {
-               ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+               ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
                if (ph2c == NULL) {
                        res = _FAIL;
                        goto exit;
                }
 
-               pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
+               pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
                if (pdrvextra_cmd_parm == NULL) {
                        kfree(ph2c);
                        res = _FAIL;
@@ -1010,13 +1010,13 @@ u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
 
        u8      res = _SUCCESS;
 
-       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (ph2c == NULL) {
                res = _FAIL;
                goto exit;
        }
 
-       pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
+       pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
        if (pdrvextra_cmd_parm == NULL) {
                kfree(ph2c);
                res = _FAIL;
@@ -1088,13 +1088,13 @@ u8 rtw_ps_cmd(struct adapter *padapter)
 
        u8      res = _SUCCESS;
 
-       ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (ppscmd == NULL) {
                res = _FAIL;
                goto exit;
        }
 
-       pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_KERNEL);
+       pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
        if (pdrvextra_cmd_parm == NULL) {
                kfree(ppscmd);
                res = _FAIL;
index 5ba5099ec20d1af8fd4415b8dbeab8d3dd1fdcc8..70b1bc3e0e63333abaa5ee2a2f63e4778f3124c2 100644 (file)
@@ -4241,12 +4241,12 @@ void report_survey_event(struct adapter *padapter,
        pcmdpriv = &padapter->cmdpriv;
 
 
-       pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (pcmd_obj == NULL)
                return;
 
        cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
-       pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+       pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (pevtcmd == NULL) {
                kfree(pcmd_obj);
                return;
@@ -4339,12 +4339,12 @@ void report_join_res(struct adapter *padapter, int res)
        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 
-       pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+       pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
        if (pcmd_obj == NULL)
                return;
 
        cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
-       pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+       pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
        if (pevtcmd == NULL) {
                kfree(pcmd_obj);
                return;
@@ -4854,11 +4854,11 @@ void survey_timer_hdl(void *function_context)
                        pmlmeext->scan_abort = false;/* reset */
                }
 
-               ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+               ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
                if (ph2c == NULL)
                        goto exit_survey_timer_hdl;
 
-               psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_KERNEL);
+               psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
                if (psurveyPara == NULL) {
                        kfree(ph2c);
                        goto exit_survey_timer_hdl;
index 33ccbbbd8ed6903fb8dd5ff61c26b9c89ca0e94c..d300369977fae5e51834ffd7f06962ea97db6195 100644 (file)
@@ -935,7 +935,7 @@ int rtw_check_bcn_info(struct adapter  *Adapter, u8 *pframe, u32 packet_len)
                return true;
        }
 
-       bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_KERNEL);
+       bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
 
        subtype = GetFrameSubType(pframe) >> 4;
 
index 407a318b09dbe2837dc64573792e6f886cc88d62..2f87150a21b7e2c1b3f09dd5df10d3085c8fda83 100644 (file)
@@ -47,6 +47,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
        {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
        {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
+       {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
        {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
        {}      /* Terminating entry */
 };
index e5121a2a64b45994ec169c97a64c0d875ebabb98..a86f36e49dd1bb8ac3b10aaeba876f1e7ed2a657 100644 (file)
@@ -107,12 +107,12 @@ enum rt_customer_id
 };
 
 struct eeprom_priv {
+       u8              mac_addr[6];    /* PermanentAddress */
        u8              bautoload_fail_flag;
        u8              bloadfile_fail_flag;
        u8              bloadmac_fail_flag;
        /* u8           bempty; */
        /* u8           sys_config; */
-       u8              mac_addr[6];    /* PermanentAddress */
        /* u8           config0; */
        u16             channel_plan;
        /* u8           country_string[3]; */
index dc2d84ac5a0e0077355b97d8b7a13b74083d9e79..81d44c477a5bf11431e37659adf62acf94a8b5bf 100644 (file)
@@ -31,6 +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
+       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
+
 source "drivers/target/loopback/Kconfig"
 source "drivers/target/tcm_fc/Kconfig"
 source "drivers/target/iscsi/Kconfig"
index 85b012d2f89bb2bce6b69a446adbd3b878ae76be..bbb4a7d638efeb4309120b4275cd0415befd9a05 100644 (file)
@@ -22,6 +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
 
 # Fabric modules
 obj-$(CONFIG_LOOPBACK_TARGET)  += loopback/
index 260c3e1e312c66310917238cada772696e457b6a..73e58d22e325d8780d17470a9a9851a732669f89 100644 (file)
@@ -3491,7 +3491,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
                                len = sprintf(buf, "TargetAddress="
                                        "%s:%hu,%hu",
                                        inaddr_any ? conn->local_ip : np->np_ip,
-                                       inaddr_any ? conn->local_port : np->np_port,
+                                       np->np_port,
                                        tpg->tpgt);
                                len += 1;
 
@@ -3709,7 +3709,6 @@ static inline void iscsit_thread_check_cpumask(
        struct task_struct *p,
        int mode)
 {
-       char buf[128];
        /*
         * mode == 1 signals iscsi_target_tx_thread() usage.
         * mode == 0 signals iscsi_target_rx_thread() usage.
@@ -3728,8 +3727,6 @@ static inline void iscsit_thread_check_cpumask(
         * both TX and RX kthreads are scheduled to run on the
         * same CPU.
         */
-       memset(buf, 0, 128);
-       cpumask_scnprintf(buf, 128, conn->conn_cpumask);
        set_cpus_allowed_ptr(p, conn->conn_cpumask);
 }
 
@@ -4326,8 +4323,7 @@ int iscsit_close_connection(
        if (conn->conn_tx_hash.tfm)
                crypto_free_hash(conn->conn_tx_hash.tfm);
 
-       if (conn->conn_cpumask)
-               free_cpumask_var(conn->conn_cpumask);
+       free_cpumask_var(conn->conn_cpumask);
 
        kfree(conn->conn_ops);
        conn->conn_ops = NULL;
index ae03f3e5de1e47f8ce9bb43ae134361d8e9e325a..9059c1e0b26e559dc0c1f69b3b97625d7cb806e4 100644 (file)
@@ -669,12 +669,10 @@ static ssize_t lio_target_nacl_show_info(
        } else {
                sess = se_sess->fabric_sess_ptr;
 
-               if (sess->sess_ops->InitiatorName)
-                       rb += sprintf(page+rb, "InitiatorName: %s\n",
-                               sess->sess_ops->InitiatorName);
-               if (sess->sess_ops->InitiatorAlias)
-                       rb += sprintf(page+rb, "InitiatorAlias: %s\n",
-                               sess->sess_ops->InitiatorAlias);
+               rb += sprintf(page+rb, "InitiatorName: %s\n",
+                       sess->sess_ops->InitiatorName);
+               rb += sprintf(page+rb, "InitiatorAlias: %s\n",
+                       sess->sess_ops->InitiatorAlias);
 
                rb += sprintf(page+rb, "LIO Session ID: %u   "
                        "ISID: 0x%02x %02x %02x %02x %02x %02x  "
index 0d1e6ee3e99246d5b613641237df8ea01a1dcfd2..a0ae5fc0ad75b5079fc7932f6dacbb19b2c68a64 100644 (file)
@@ -345,7 +345,6 @@ static int iscsit_dataout_check_datasn(
        struct iscsi_cmd *cmd,
        unsigned char *buf)
 {
-       int dump = 0, recovery = 0;
        u32 data_sn = 0;
        struct iscsi_conn *conn = cmd->conn;
        struct iscsi_data *hdr = (struct iscsi_data *) buf;
@@ -370,13 +369,11 @@ static int iscsit_dataout_check_datasn(
                pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
                        " higher than expected 0x%08x.\n", cmd->init_task_tag,
                                be32_to_cpu(hdr->datasn), data_sn);
-               recovery = 1;
                goto recover;
        } else if (be32_to_cpu(hdr->datasn) < data_sn) {
                pr_err("Command ITT: 0x%08x, received DataSN: 0x%08x"
                        " lower than expected 0x%08x, discarding payload.\n",
                        cmd->init_task_tag, be32_to_cpu(hdr->datasn), data_sn);
-               dump = 1;
                goto dump;
        }
 
@@ -392,8 +389,7 @@ dump:
        if (iscsit_dump_data_payload(conn, payload_length, 1) < 0)
                return DATAOUT_CANNOT_RECOVER;
 
-       return (recovery || dump) ? DATAOUT_WITHIN_COMMAND_RECOVERY :
-                               DATAOUT_NORMAL;
+       return DATAOUT_WITHIN_COMMAND_RECOVERY;
 }
 
 static int iscsit_dataout_pre_datapduinorder_yes(
index 5e71ac609418137784f99078a1837afa216e8642..480f2e0ecc1170884c5f56ca38644fab1465a0de 100644 (file)
@@ -978,8 +978,7 @@ int iscsit_setup_np(
        return 0;
 fail:
        np->np_socket = NULL;
-       if (sock)
-               sock_release(sock);
+       sock_release(sock);
        return ret;
 }
 
@@ -1190,8 +1189,7 @@ old_sess_out:
        if (!IS_ERR(conn->conn_tx_hash.tfm))
                crypto_free_hash(conn->conn_tx_hash.tfm);
 
-       if (conn->conn_cpumask)
-               free_cpumask_var(conn->conn_cpumask);
+       free_cpumask_var(conn->conn_cpumask);
 
        kfree(conn->conn_ops);
 
@@ -1268,8 +1266,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                        iscsit_put_transport(conn->conn_transport);
                        kfree(conn);
                        conn = NULL;
-                       if (ret == -ENODEV)
-                               goto out;
                        /* Get another socket */
                        return 1;
                }
index 73355f4fca745a71d0fa3cb66956148c64e41f11..ce87ce9bdb9c59fd0d5d5eaf886acb7fc4c2b799 100644 (file)
@@ -1481,8 +1481,9 @@ void iscsit_collect_login_stats(
                if (conn->param_list)
                        intrname = iscsi_find_param_from_key(INITIATORNAME,
                                                             conn->param_list);
-               strcpy(ls->last_intr_fail_name,
-                      (intrname ? intrname->value : "Unknown"));
+               strlcpy(ls->last_intr_fail_name,
+                      (intrname ? intrname->value : "Unknown"),
+                      sizeof(ls->last_intr_fail_name));
 
                ls->last_intr_fail_ip_family = conn->login_family;
 
index 340de9d92b15bf28a5c13dff1760d23576957e1e..4d1b7224a7f2559d200ec11aaced60a8d67c4a6c 100644 (file)
@@ -110,65 +110,6 @@ static struct device_driver tcm_loop_driverfs = {
  */
 struct device *tcm_loop_primary;
 
-/*
- * Copied from drivers/scsi/libfc/fc_fcp.c:fc_change_queue_depth() and
- * drivers/scsi/libiscsi.c:iscsi_change_queue_depth()
- */
-static int tcm_loop_change_queue_depth(
-       struct scsi_device *sdev,
-       int depth,
-       int reason)
-{
-       switch (reason) {
-       case SCSI_QDEPTH_DEFAULT:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       case SCSI_QDEPTH_QFULL:
-               scsi_track_queue_full(sdev, depth);
-               break;
-       case SCSI_QDEPTH_RAMP_UP:
-               scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-       return sdev->queue_depth;
-}
-
-static int tcm_loop_change_queue_type(struct scsi_device *sdev, int tag)
-{
-       if (sdev->tagged_supported) {
-               scsi_set_tag_type(sdev, tag);
-
-               if (tag)
-                       scsi_activate_tcq(sdev, sdev->queue_depth);
-               else
-                       scsi_deactivate_tcq(sdev, sdev->queue_depth);
-       } else
-               tag = 0;
-
-       return tag;
-}
-
-/*
- * Locate the SAM Task Attr from struct scsi_cmnd *
- */
-static int tcm_loop_sam_attr(struct scsi_cmnd *sc)
-{
-       if (sc->device->tagged_supported) {
-               switch (sc->tag) {
-               case HEAD_OF_QUEUE_TAG:
-                       return MSG_HEAD_TAG;
-               case ORDERED_QUEUE_TAG:
-                       return MSG_ORDERED_TAG;
-               default:
-                       break;
-               }
-       }
-
-       return MSG_SIMPLE_TAG;
-}
-
 static void tcm_loop_submission_work(struct work_struct *work)
 {
        struct tcm_loop_cmd *tl_cmd =
@@ -227,7 +168,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
 
        rc = target_submit_cmd_map_sgls(se_cmd, tl_nexus->se_sess, sc->cmnd,
                        &tl_cmd->tl_sense_buf[0], tl_cmd->sc->device->lun,
-                       transfer_length, tcm_loop_sam_attr(sc),
+                       transfer_length, MSG_SIMPLE_TAG,
                        sc->sc_data_direction, 0,
                        scsi_sglist(sc), scsi_sg_count(sc),
                        sgl_bidi, sgl_bidi_count,
@@ -266,7 +207,7 @@ static int tcm_loop_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *sc)
        }
 
        tl_cmd->sc = sc;
-       tl_cmd->sc_cmd_tag = sc->tag;
+       tl_cmd->sc_cmd_tag = sc->request->tag;
        INIT_WORK(&tl_cmd->work, tcm_loop_submission_work);
        queue_work(tcm_loop_workqueue, &tl_cmd->work);
        return 0;
@@ -370,7 +311,7 @@ static int tcm_loop_abort_task(struct scsi_cmnd *sc)
         */
        tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
        ret = tcm_loop_issue_tmr(tl_tpg, tl_nexus, sc->device->lun,
-                                sc->tag, TMR_ABORT_TASK);
+                                sc->request->tag, TMR_ABORT_TASK);
        return (ret == TMR_FUNCTION_COMPLETE) ? SUCCESS : FAILED;
 }
 
@@ -438,27 +379,13 @@ static int tcm_loop_slave_alloc(struct scsi_device *sd)
        return 0;
 }
 
-static int tcm_loop_slave_configure(struct scsi_device *sd)
-{
-       if (sd->tagged_supported) {
-               scsi_activate_tcq(sd, sd->queue_depth);
-               scsi_adjust_queue_depth(sd, MSG_SIMPLE_TAG,
-                                       sd->host->cmd_per_lun);
-       } else {
-               scsi_adjust_queue_depth(sd, 0,
-                                       sd->host->cmd_per_lun);
-       }
-
-       return 0;
-}
-
 static struct scsi_host_template tcm_loop_driver_template = {
        .show_info              = tcm_loop_show_info,
        .proc_name              = "tcm_loopback",
        .name                   = "TCM_Loopback",
        .queuecommand           = tcm_loop_queuecommand,
-       .change_queue_depth     = tcm_loop_change_queue_depth,
-       .change_queue_type      = tcm_loop_change_queue_type,
+       .change_queue_depth     = scsi_change_queue_depth,
+       .change_queue_type      = scsi_change_queue_type,
        .eh_abort_handler = tcm_loop_abort_task,
        .eh_device_reset_handler = tcm_loop_device_reset,
        .eh_target_reset_handler = tcm_loop_target_reset,
@@ -469,8 +396,9 @@ static struct scsi_host_template tcm_loop_driver_template = {
        .max_sectors            = 0xFFFF,
        .use_clustering         = DISABLE_CLUSTERING,
        .slave_alloc            = tcm_loop_slave_alloc,
-       .slave_configure        = tcm_loop_slave_configure,
        .module                 = THIS_MODULE,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
 };
 
 static int tcm_loop_driver_probe(struct device *dev)
@@ -960,8 +888,7 @@ static int tcm_loop_port_link(
                                struct tcm_loop_tpg, tl_se_tpg);
        struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
 
-       atomic_inc(&tl_tpg->tl_tpg_port_count);
-       smp_mb__after_atomic();
+       atomic_inc_mb(&tl_tpg->tl_tpg_port_count);
        /*
         * Add Linux/SCSI struct scsi_device by HCTL
         */
@@ -995,8 +922,7 @@ static void tcm_loop_port_unlink(
        scsi_remove_device(sd);
        scsi_device_put(sd);
 
-       atomic_dec(&tl_tpg->tl_tpg_port_count);
-       smp_mb__after_atomic();
+       atomic_dec_mb(&tl_tpg->tl_tpg_port_count);
 
        pr_debug("TCM_Loop_ConfigFS: Port Unlink Successful\n");
 }
index fbc5ebb5f7613c4f7a70c5c0adfbadf27bd4cf30..75cbde1f7c5b6e34ea7060011c2aca817e4e55f2 100644 (file)
@@ -392,8 +392,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
                                if (tg_pt_id != tg_pt_gp->tg_pt_gp_id)
                                        continue;
 
-                               atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
-                               smp_mb__after_atomic();
+                               atomic_inc_mb(&tg_pt_gp->tg_pt_gp_ref_cnt);
 
                                spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
@@ -403,8 +402,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd)
                                        found = true;
 
                                spin_lock(&dev->t10_alua.tg_pt_gps_lock);
-                               atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
-                               smp_mb__after_atomic();
+                               atomic_dec_mb(&tg_pt_gp->tg_pt_gp_ref_cnt);
                                break;
                        }
                        spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
@@ -578,7 +576,7 @@ static inline int core_alua_state_standby(
        case SEND_DIAGNOSTIC:
        case READ_CAPACITY:
                return 0;
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                switch (cdb[1] & 0x1f) {
                case SAI_READ_CAPACITY_16:
                        return 0;
@@ -998,8 +996,7 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
                 * every I_T nexus other than the I_T nexus on which the SET
                 * TARGET PORT GROUPS command
                 */
-               atomic_inc(&mem->tg_pt_gp_mem_ref_cnt);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&mem->tg_pt_gp_mem_ref_cnt);
                spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
 
                spin_lock_bh(&port->sep_alua_lock);
@@ -1028,8 +1025,7 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
                spin_unlock_bh(&port->sep_alua_lock);
 
                spin_lock(&tg_pt_gp->tg_pt_gp_lock);
-               atomic_dec(&mem->tg_pt_gp_mem_ref_cnt);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&mem->tg_pt_gp_mem_ref_cnt);
        }
        spin_unlock(&tg_pt_gp->tg_pt_gp_lock);
        /*
@@ -1063,7 +1059,6 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work)
                core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state));
        spin_lock(&dev->t10_alua.tg_pt_gps_lock);
        atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
-       smp_mb__after_atomic();
        spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
        if (tg_pt_gp->tg_pt_gp_transition_complete)
@@ -1125,7 +1120,6 @@ static int core_alua_do_transition_tg_pt(
         */
        spin_lock(&dev->t10_alua.tg_pt_gps_lock);
        atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
-       smp_mb__after_atomic();
        spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
        if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs) {
@@ -1168,7 +1162,6 @@ int core_alua_do_port_transition(
        spin_lock(&local_lu_gp_mem->lu_gp_mem_lock);
        lu_gp = local_lu_gp_mem->lu_gp;
        atomic_inc(&lu_gp->lu_gp_ref_cnt);
-       smp_mb__after_atomic();
        spin_unlock(&local_lu_gp_mem->lu_gp_mem_lock);
        /*
         * For storage objects that are members of the 'default_lu_gp',
@@ -1184,8 +1177,7 @@ int core_alua_do_port_transition(
                l_tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl;
                rc = core_alua_do_transition_tg_pt(l_tg_pt_gp,
                                                   new_state, explicit);
-               atomic_dec(&lu_gp->lu_gp_ref_cnt);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&lu_gp->lu_gp_ref_cnt);
                return rc;
        }
        /*
@@ -1198,8 +1190,7 @@ int core_alua_do_port_transition(
                                lu_gp_mem_list) {
 
                dev = lu_gp_mem->lu_gp_mem_dev;
-               atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&lu_gp_mem->lu_gp_mem_ref_cnt);
                spin_unlock(&lu_gp->lu_gp_lock);
 
                spin_lock(&dev->t10_alua.tg_pt_gps_lock);
@@ -1227,8 +1218,7 @@ int core_alua_do_port_transition(
                                tg_pt_gp->tg_pt_gp_alua_port = NULL;
                                tg_pt_gp->tg_pt_gp_alua_nacl = NULL;
                        }
-                       atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
-                       smp_mb__after_atomic();
+                       atomic_inc_mb(&tg_pt_gp->tg_pt_gp_ref_cnt);
                        spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
                        /*
                         * core_alua_do_transition_tg_pt() will always return
@@ -1238,16 +1228,14 @@ int core_alua_do_port_transition(
                                        new_state, explicit);
 
                        spin_lock(&dev->t10_alua.tg_pt_gps_lock);
-                       atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
-                       smp_mb__after_atomic();
+                       atomic_dec_mb(&tg_pt_gp->tg_pt_gp_ref_cnt);
                        if (rc)
                                break;
                }
                spin_unlock(&dev->t10_alua.tg_pt_gps_lock);
 
                spin_lock(&lu_gp->lu_gp_lock);
-               atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&lu_gp_mem->lu_gp_mem_ref_cnt);
        }
        spin_unlock(&lu_gp->lu_gp_lock);
 
@@ -1260,8 +1248,7 @@ int core_alua_do_port_transition(
                         core_alua_dump_state(new_state));
        }
 
-       atomic_dec(&lu_gp->lu_gp_ref_cnt);
-       smp_mb__after_atomic();
+       atomic_dec_mb(&lu_gp->lu_gp_ref_cnt);
        return rc;
 }
 
index 756def38c77af934a3e16ef3ae9219e67ceb06cc..79f9296a08ae7195d859c5ba200b2b990f78c0de 100644 (file)
@@ -665,6 +665,9 @@ SE_DEV_ATTR(is_nonrot, S_IRUGO | S_IWUSR);
 DEF_DEV_ATTRIB(emulate_rest_reord);
 SE_DEV_ATTR(emulate_rest_reord, S_IRUGO | S_IWUSR);
 
+DEF_DEV_ATTRIB(force_pr_aptpl);
+SE_DEV_ATTR(force_pr_aptpl, S_IRUGO | S_IWUSR);
+
 DEF_DEV_ATTRIB_RO(hw_block_size);
 SE_DEV_ATTR_RO(hw_block_size);
 
@@ -719,6 +722,7 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
        &target_core_dev_attrib_hw_pi_prot_type.attr,
        &target_core_dev_attrib_pi_prot_format.attr,
        &target_core_dev_attrib_enforce_pr_isids.attr,
+       &target_core_dev_attrib_force_pr_aptpl.attr,
        &target_core_dev_attrib_is_nonrot.attr,
        &target_core_dev_attrib_emulate_rest_reord.attr,
        &target_core_dev_attrib_hw_block_size.attr,
@@ -1263,7 +1267,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
 {
        unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL;
        unsigned char *t_fabric = NULL, *t_port = NULL;
-       char *orig, *ptr, *arg_p, *opts;
+       char *orig, *ptr, *opts;
        substring_t args[MAX_OPT_ARGS];
        unsigned long long tmp_ll;
        u64 sa_res_key = 0;
@@ -1295,14 +1299,14 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                token = match_token(ptr, tokens, args);
                switch (token) {
                case Opt_initiator_fabric:
-                       i_fabric = match_strdup(&args[0]);
+                       i_fabric = match_strdup(args);
                        if (!i_fabric) {
                                ret = -ENOMEM;
                                goto out;
                        }
                        break;
                case Opt_initiator_node:
-                       i_port = match_strdup(&args[0]);
+                       i_port = match_strdup(args);
                        if (!i_port) {
                                ret = -ENOMEM;
                                goto out;
@@ -1316,7 +1320,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                        }
                        break;
                case Opt_initiator_sid:
-                       isid = match_strdup(&args[0]);
+                       isid = match_strdup(args);
                        if (!isid) {
                                ret = -ENOMEM;
                                goto out;
@@ -1330,15 +1334,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                        }
                        break;
                case Opt_sa_res_key:
-                       arg_p = match_strdup(&args[0]);
-                       if (!arg_p) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       ret = kstrtoull(arg_p, 0, &tmp_ll);
+                       ret = kstrtoull(args->from, 0, &tmp_ll);
                        if (ret < 0) {
-                               pr_err("kstrtoull() failed for"
-                                       " sa_res_key=\n");
+                               pr_err("kstrtoull() failed for sa_res_key=\n");
                                goto out;
                        }
                        sa_res_key = (u64)tmp_ll;
@@ -1370,14 +1368,14 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                 * PR APTPL Metadata for Target Port
                 */
                case Opt_target_fabric:
-                       t_fabric = match_strdup(&args[0]);
+                       t_fabric = match_strdup(args);
                        if (!t_fabric) {
                                ret = -ENOMEM;
                                goto out;
                        }
                        break;
                case Opt_target_node:
-                       t_port = match_strdup(&args[0]);
+                       t_port = match_strdup(args);
                        if (!t_port) {
                                ret = -ENOMEM;
                                goto out;
index 98da90167159b198dfc65a8ebdc912b350e4c6f0..c45f9e907e44c168de68060b83737e302533f785 100644 (file)
@@ -224,8 +224,7 @@ struct se_dev_entry *core_get_se_deve_from_rtpi(
                if (port->sep_rtpi != rtpi)
                        continue;
 
-               atomic_inc(&deve->pr_ref_count);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&deve->pr_ref_count);
                spin_unlock_irq(&nacl->device_list_lock);
 
                return deve;
@@ -1019,6 +1018,23 @@ int se_dev_set_enforce_pr_isids(struct se_device *dev, int flag)
        return 0;
 }
 
+int se_dev_set_force_pr_aptpl(struct se_device *dev, int flag)
+{
+       if ((flag != 0) && (flag != 1)) {
+               printk(KERN_ERR "Illegal value %d\n", flag);
+               return -EINVAL;
+       }
+       if (dev->export_count) {
+               pr_err("dev[%p]: Unable to set force_pr_aptpl while"
+                      " export_count is %d\n", dev, dev->export_count);
+               return -EINVAL;
+       }
+
+       dev->dev_attrib.force_pr_aptpl = flag;
+       pr_debug("dev[%p]: SE Device force_pr_aptpl: %d\n", dev, flag);
+       return 0;
+}
+
 int se_dev_set_is_nonrot(struct se_device *dev, int flag)
 {
        if ((flag != 0) && (flag != 1)) {
@@ -1250,24 +1266,16 @@ struct se_lun *core_dev_add_lun(
  *
  *
  */
-int core_dev_del_lun(
+void core_dev_del_lun(
        struct se_portal_group *tpg,
-       u32 unpacked_lun)
+       struct se_lun *lun)
 {
-       struct se_lun *lun;
-
-       lun = core_tpg_pre_dellun(tpg, unpacked_lun);
-       if (IS_ERR(lun))
-               return PTR_ERR(lun);
-
-       core_tpg_post_dellun(tpg, lun);
-
-       pr_debug("%s_TPG[%u]_LUN[%u] - Deactivated %s Logical Unit from"
+       pr_debug("%s_TPG[%u]_LUN[%u] - Deactivating %s Logical Unit from"
                " device object\n", tpg->se_tpg_tfo->get_fabric_name(),
-               tpg->se_tpg_tfo->tpg_get_tag(tpg), unpacked_lun,
+               tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun,
                tpg->se_tpg_tfo->get_fabric_name());
 
-       return 0;
+       core_tpg_remove_lun(tpg, lun);
 }
 
 struct se_lun *core_get_lun_from_tpg(struct se_portal_group *tpg, u32 unpacked_lun)
@@ -1396,8 +1404,7 @@ int core_dev_add_initiator_node_lun_acl(
 
        spin_lock(&lun->lun_acl_lock);
        list_add_tail(&lacl->lacl_list, &lun->lun_acl_list);
-       atomic_inc(&lun->lun_acl_count);
-       smp_mb__after_atomic();
+       atomic_inc_mb(&lun->lun_acl_count);
        spin_unlock(&lun->lun_acl_lock);
 
        pr_debug("%s_TPG[%hu]_LUN[%u->%u] - Added %s ACL for "
@@ -1409,7 +1416,8 @@ int core_dev_add_initiator_node_lun_acl(
         * Check to see if there are any existing persistent reservation APTPL
         * pre-registrations that need to be enabled for this LUN ACL..
         */
-       core_scsi3_check_aptpl_registration(lun->lun_se_dev, tpg, lun, lacl);
+       core_scsi3_check_aptpl_registration(lun->lun_se_dev, tpg, lun, nacl,
+                                           lacl->mapped_lun);
        return 0;
 }
 
@@ -1430,8 +1438,7 @@ int core_dev_del_initiator_node_lun_acl(
 
        spin_lock(&lun->lun_acl_lock);
        list_del(&lacl->lacl_list);
-       atomic_dec(&lun->lun_acl_count);
-       smp_mb__after_atomic();
+       atomic_dec_mb(&lun->lun_acl_count);
        spin_unlock(&lun->lun_acl_lock);
 
        core_disable_device_list_for_node(lun, NULL, lacl->mapped_lun,
@@ -1554,6 +1561,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
        dev->dev_attrib.emulate_3pc = DA_EMULATE_3PC;
        dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE0_PROT;
        dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
+       dev->dev_attrib.force_pr_aptpl = DA_FORCE_PR_APTPL;
        dev->dev_attrib.is_nonrot = DA_IS_NONROT;
        dev->dev_attrib.emulate_rest_reord = DA_EMULATE_REST_REORD;
        dev->dev_attrib.max_unmap_lba_count = DA_MAX_UNMAP_LBA_COUNT;
index 7de9f0475d0552e2b10f58ffa227083336659a2c..0c3f90130b7d398c8670509834d3fe3a59f0de98 100644 (file)
@@ -320,7 +320,7 @@ static struct config_group *target_fabric_make_mappedlun(
                        struct se_node_acl, acl_group);
        struct se_portal_group *se_tpg = se_nacl->se_tpg;
        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
-       struct se_lun_acl *lacl;
+       struct se_lun_acl *lacl = NULL;
        struct config_item *acl_ci;
        struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
        char *buf;
@@ -406,6 +406,7 @@ static struct config_group *target_fabric_make_mappedlun(
 out:
        if (lacl_cg)
                kfree(lacl_cg->default_groups);
+       kfree(lacl);
        kfree(buf);
        return ERR_PTR(ret);
 }
@@ -821,7 +822,7 @@ static int target_fabric_port_unlink(
                tf->tf_ops.fabric_pre_unlink(se_tpg, lun);
        }
 
-       core_dev_del_lun(se_tpg, lun->unpacked_lun);
+       core_dev_del_lun(se_tpg, lun);
        return 0;
 }
 
@@ -910,16 +911,12 @@ static struct config_group *target_fabric_make_lun(
                                GFP_KERNEL);
        if (!port_stat_grp->default_groups) {
                pr_err("Unable to allocate port_stat_grp->default_groups\n");
-               errno = -ENOMEM;
-               goto out;
+               kfree(lun_cg->default_groups);
+               return ERR_PTR(-ENOMEM);
        }
        target_stat_setup_port_default_groups(lun);
 
        return &lun->lun_group;
-out:
-       if (lun_cg)
-               kfree(lun_cg->default_groups);
-       return ERR_PTR(errno);
 }
 
 static void target_fabric_drop_lun(
index 0d1cf8b4f49f64a182287f1c74e05a841fce6a30..35bfe77160d86828b6511034787862f74788addc 100644 (file)
@@ -394,9 +394,9 @@ char *iscsi_parse_pr_out_transport_id(
         * If the caller wants the TransportID Length, we set that value for the
         * entire iSCSI Tarnsport ID now.
         */
-        if (out_tid_len != NULL) {
-               add_len = ((buf[2] >> 8) & 0xff);
-               add_len |= (buf[3] & 0xff);
+       if (out_tid_len) {
+               /* The shift works thanks to integer promotion rules */
+               add_len = (buf[2] << 8) | buf[3];
 
                tid_len = strlen(&buf[4]);
                tid_len += 4; /* Add four bytes for iSCSI Transport ID header */
index 7d6cddaec5250cf28239c49b22eeb269a30e69d0..72c83d98662bb7117d3911ab931940990a79f82d 100644 (file)
@@ -415,7 +415,7 @@ fd_execute_sync_cache(struct se_cmd *cmd)
        } else {
                start = cmd->t_task_lba * dev->dev_attrib.block_size;
                if (cmd->data_length)
-                       end = start + cmd->data_length;
+                       end = start + cmd->data_length - 1;
                else
                        end = LLONG_MAX;
        }
@@ -680,7 +680,12 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                        struct fd_dev *fd_dev = FD_DEV(dev);
                        loff_t start = cmd->t_task_lba *
                                dev->dev_attrib.block_size;
-                       loff_t end = start + cmd->data_length;
+                       loff_t end;
+
+                       if (cmd->data_length)
+                               end = start + cmd->data_length - 1;
+                       else
+                               end = LLONG_MAX;
 
                        vfs_fsync_range(fd_dev->fd_file, start, end, 1);
                }
@@ -762,7 +767,9 @@ static ssize_t fd_set_configfs_dev_params(struct se_device *dev,
                        fd_dev->fbd_flags |= FBDF_HAS_SIZE;
                        break;
                case Opt_fd_buffered_io:
-                       match_int(args, &arg);
+                       ret = match_int(args, &arg);
+                       if (ret)
+                               goto out;
                        if (arg != 1) {
                                pr_err("bogus fd_buffered_io=%d value\n", arg);
                                ret = -EINVAL;
index de9cab708f4590ee98034898992e68c1f0459077..e31f42f369fff45d6bfd9c260e7483787b646472 100644 (file)
@@ -38,6 +38,7 @@ int   se_dev_set_emulate_3pc(struct se_device *, int);
 int    se_dev_set_pi_prot_type(struct se_device *, int);
 int    se_dev_set_pi_prot_format(struct se_device *, int);
 int    se_dev_set_enforce_pr_isids(struct se_device *, int);
+int    se_dev_set_force_pr_aptpl(struct se_device *, int);
 int    se_dev_set_is_nonrot(struct se_device *, int);
 int    se_dev_set_emulate_rest_reord(struct se_device *dev, int);
 int    se_dev_set_queue_depth(struct se_device *, u32);
@@ -46,7 +47,7 @@ int   se_dev_set_fabric_max_sectors(struct se_device *, u32);
 int    se_dev_set_optimal_sectors(struct se_device *, u32);
 int    se_dev_set_block_size(struct se_device *, u32);
 struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_device *, u32);
-int    core_dev_del_lun(struct se_portal_group *, u32);
+void   core_dev_del_lun(struct se_portal_group *, struct se_lun *);
 struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32);
 struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *,
                struct se_node_acl *, u32, int *);
@@ -82,8 +83,7 @@ void  core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
 struct se_lun *core_tpg_alloc_lun(struct se_portal_group *, u32);
 int    core_tpg_add_lun(struct se_portal_group *, struct se_lun *,
                u32, struct se_device *);
-struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);
-int    core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
+void core_tpg_remove_lun(struct se_portal_group *, struct se_lun *);
 
 /* target_core_transport.c */
 extern struct kmem_cache *se_tmr_req_cache;
index df357862286e10758492b8ad88dfa65e79c1582f..4c261c33cf55e62394db8b22cf312fdbb352d8f7 100644 (file)
@@ -459,7 +459,7 @@ static int core_scsi3_pr_seq_non_holder(
        case ACCESS_CONTROL_OUT:
        case INQUIRY:
        case LOG_SENSE:
-       case READ_MEDIA_SERIAL_NUMBER:
+       case SERVICE_ACTION_IN_12:
        case REPORT_LUNS:
        case REQUEST_SENSE:
        case PERSISTENT_RESERVE_IN:
@@ -674,8 +674,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
         */
        spin_lock(&dev->se_port_lock);
        list_for_each_entry_safe(port, port_tmp, &dev->dev_sep_list, sep_list) {
-               atomic_inc(&port->sep_tg_pt_ref_cnt);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&port->sep_tg_pt_ref_cnt);
                spin_unlock(&dev->se_port_lock);
 
                spin_lock_bh(&port->sep_alua_lock);
@@ -709,8 +708,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
                        if (strcmp(nacl->initiatorname, nacl_tmp->initiatorname))
                                continue;
 
-                       atomic_inc(&deve_tmp->pr_ref_count);
-                       smp_mb__after_atomic();
+                       atomic_inc_mb(&deve_tmp->pr_ref_count);
                        spin_unlock_bh(&port->sep_alua_lock);
                        /*
                         * Grab a configfs group dependency that is released
@@ -722,10 +720,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
                        if (ret < 0) {
                                pr_err("core_scsi3_lunacl_depend"
                                                "_item() failed\n");
-                               atomic_dec(&port->sep_tg_pt_ref_cnt);
-                               smp_mb__after_atomic();
-                               atomic_dec(&deve_tmp->pr_ref_count);
-                               smp_mb__after_atomic();
+                               atomic_dec_mb(&port->sep_tg_pt_ref_cnt);
+                               atomic_dec_mb(&deve_tmp->pr_ref_count);
                                goto out;
                        }
                        /*
@@ -739,10 +735,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
                                                nacl_tmp, deve_tmp, NULL,
                                                sa_res_key, all_tg_pt, aptpl);
                        if (!pr_reg_atp) {
-                               atomic_dec(&port->sep_tg_pt_ref_cnt);
-                               smp_mb__after_atomic();
-                               atomic_dec(&deve_tmp->pr_ref_count);
-                               smp_mb__after_atomic();
+                               atomic_dec_mb(&port->sep_tg_pt_ref_cnt);
+                               atomic_dec_mb(&deve_tmp->pr_ref_count);
                                core_scsi3_lunacl_undepend_item(deve_tmp);
                                goto out;
                        }
@@ -754,8 +748,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
                spin_unlock_bh(&port->sep_alua_lock);
 
                spin_lock(&dev->se_port_lock);
-               atomic_dec(&port->sep_tg_pt_ref_cnt);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&port->sep_tg_pt_ref_cnt);
        }
        spin_unlock(&dev->se_port_lock);
 
@@ -902,6 +895,7 @@ static int __core_scsi3_check_aptpl_registration(
        spin_lock(&pr_tmpl->aptpl_reg_lock);
        list_for_each_entry_safe(pr_reg, pr_reg_tmp, &pr_tmpl->aptpl_reg_list,
                                pr_reg_aptpl_list) {
+
                if (!strcmp(pr_reg->pr_iport, i_port) &&
                     (pr_reg->pr_res_mapped_lun == deve->mapped_lun) &&
                    !(strcmp(pr_reg->pr_tport, t_port)) &&
@@ -944,10 +938,10 @@ int core_scsi3_check_aptpl_registration(
        struct se_device *dev,
        struct se_portal_group *tpg,
        struct se_lun *lun,
-       struct se_lun_acl *lun_acl)
+       struct se_node_acl *nacl,
+       u32 mapped_lun)
 {
-       struct se_node_acl *nacl = lun_acl->se_lun_nacl;
-       struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun];
+       struct se_dev_entry *deve = nacl->device_list[mapped_lun];
 
        if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
                return 0;
@@ -1109,8 +1103,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
                                if (dev->dev_attrib.enforce_pr_isids)
                                        continue;
                        }
-                       atomic_inc(&pr_reg->pr_res_holders);
-                       smp_mb__after_atomic();
+                       atomic_inc_mb(&pr_reg->pr_res_holders);
                        spin_unlock(&pr_tmpl->registration_lock);
                        return pr_reg;
                }
@@ -1124,8 +1117,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
                if (strcmp(isid, pr_reg->pr_reg_isid))
                        continue;
 
-               atomic_inc(&pr_reg->pr_res_holders);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&pr_reg->pr_res_holders);
                spin_unlock(&pr_tmpl->registration_lock);
                return pr_reg;
        }
@@ -1154,8 +1146,7 @@ static struct t10_pr_registration *core_scsi3_locate_pr_reg(
 
 static void core_scsi3_put_pr_reg(struct t10_pr_registration *pr_reg)
 {
-       atomic_dec(&pr_reg->pr_res_holders);
-       smp_mb__after_atomic();
+       atomic_dec_mb(&pr_reg->pr_res_holders);
 }
 
 static int core_scsi3_check_implicit_release(
@@ -1348,8 +1339,7 @@ static void core_scsi3_tpg_undepend_item(struct se_portal_group *tpg)
        configfs_undepend_item(tpg->se_tpg_tfo->tf_subsys,
                        &tpg->tpg_group.cg_item);
 
-       atomic_dec(&tpg->tpg_pr_ref_count);
-       smp_mb__after_atomic();
+       atomic_dec_mb(&tpg->tpg_pr_ref_count);
 }
 
 static int core_scsi3_nodeacl_depend_item(struct se_node_acl *nacl)
@@ -1368,16 +1358,14 @@ static void core_scsi3_nodeacl_undepend_item(struct se_node_acl *nacl)
        struct se_portal_group *tpg = nacl->se_tpg;
 
        if (nacl->dynamic_node_acl) {
-               atomic_dec(&nacl->acl_pr_ref_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&nacl->acl_pr_ref_count);
                return;
        }
 
        configfs_undepend_item(tpg->se_tpg_tfo->tf_subsys,
                        &nacl->acl_group.cg_item);
 
-       atomic_dec(&nacl->acl_pr_ref_count);
-       smp_mb__after_atomic();
+       atomic_dec_mb(&nacl->acl_pr_ref_count);
 }
 
 static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
@@ -1407,8 +1395,7 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
         * For nacl->dynamic_node_acl=1
         */
        if (!lun_acl) {
-               atomic_dec(&se_deve->pr_ref_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&se_deve->pr_ref_count);
                return;
        }
        nacl = lun_acl->se_lun_nacl;
@@ -1417,8 +1404,7 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
        configfs_undepend_item(tpg->se_tpg_tfo->tf_subsys,
                        &lun_acl->se_lun_group.cg_item);
 
-       atomic_dec(&se_deve->pr_ref_count);
-       smp_mb__after_atomic();
+       atomic_dec_mb(&se_deve->pr_ref_count);
 }
 
 static sense_reason_t
@@ -1551,15 +1537,13 @@ core_scsi3_decode_spec_i_port(
                        if (!i_str)
                                continue;
 
-                       atomic_inc(&tmp_tpg->tpg_pr_ref_count);
-                       smp_mb__after_atomic();
+                       atomic_inc_mb(&tmp_tpg->tpg_pr_ref_count);
                        spin_unlock(&dev->se_port_lock);
 
                        if (core_scsi3_tpg_depend_item(tmp_tpg)) {
                                pr_err(" core_scsi3_tpg_depend_item()"
                                        " for tmp_tpg\n");
-                               atomic_dec(&tmp_tpg->tpg_pr_ref_count);
-                               smp_mb__after_atomic();
+                               atomic_dec_mb(&tmp_tpg->tpg_pr_ref_count);
                                ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                                goto out_unmap;
                        }
@@ -1571,10 +1555,8 @@ core_scsi3_decode_spec_i_port(
                        spin_lock_irq(&tmp_tpg->acl_node_lock);
                        dest_node_acl = __core_tpg_get_initiator_node_acl(
                                                tmp_tpg, i_str);
-                       if (dest_node_acl) {
-                               atomic_inc(&dest_node_acl->acl_pr_ref_count);
-                               smp_mb__after_atomic();
-                       }
+                       if (dest_node_acl)
+                               atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
                        spin_unlock_irq(&tmp_tpg->acl_node_lock);
 
                        if (!dest_node_acl) {
@@ -1586,8 +1568,7 @@ core_scsi3_decode_spec_i_port(
                        if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
                                pr_err("configfs_depend_item() failed"
                                        " for dest_node_acl->acl_group\n");
-                               atomic_dec(&dest_node_acl->acl_pr_ref_count);
-                               smp_mb__after_atomic();
+                               atomic_dec_mb(&dest_node_acl->acl_pr_ref_count);
                                core_scsi3_tpg_undepend_item(tmp_tpg);
                                ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                                goto out_unmap;
@@ -1646,8 +1627,7 @@ core_scsi3_decode_spec_i_port(
                if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
                        pr_err("core_scsi3_lunacl_depend_item()"
                                        " failed\n");
-                       atomic_dec(&dest_se_deve->pr_ref_count);
-                       smp_mb__after_atomic();
+                       atomic_dec_mb(&dest_se_deve->pr_ref_count);
                        core_scsi3_nodeacl_undepend_item(dest_node_acl);
                        core_scsi3_tpg_undepend_item(dest_tpg);
                        ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -2758,7 +2738,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
        struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
        u32 pr_res_mapped_lun = 0;
-       int all_reg = 0, calling_it_nexus = 0, released_regs = 0;
+       int all_reg = 0, calling_it_nexus = 0;
+       bool sa_res_key_unmatched = sa_res_key != 0;
        int prh_type = 0, prh_scope = 0;
 
        if (!se_sess)
@@ -2833,6 +2814,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                        if (!all_reg) {
                                if (pr_reg->pr_res_key != sa_res_key)
                                        continue;
+                               sa_res_key_unmatched = false;
 
                                calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0;
                                pr_reg_nacl = pr_reg->pr_reg_nacl;
@@ -2840,7 +2822,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                                __core_scsi3_free_registration(dev, pr_reg,
                                        (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
                                                NULL, calling_it_nexus);
-                               released_regs++;
                        } else {
                                /*
                                 * Case for any existing all registrants type
@@ -2858,6 +2839,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                                if ((sa_res_key) &&
                                     (pr_reg->pr_res_key != sa_res_key))
                                        continue;
+                               sa_res_key_unmatched = false;
 
                                calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0;
                                if (calling_it_nexus)
@@ -2868,7 +2850,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                                __core_scsi3_free_registration(dev, pr_reg,
                                        (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
                                                NULL, 0);
-                               released_regs++;
                        }
                        if (!calling_it_nexus)
                                core_scsi3_ua_allocate(pr_reg_nacl,
@@ -2883,7 +2864,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                 * registered reservation key, then the device server shall
                 * complete the command with RESERVATION CONFLICT status.
                 */
-               if (!released_regs) {
+               if (sa_res_key_unmatched) {
                        spin_unlock(&dev->dev_reservation_lock);
                        core_scsi3_put_pr_reg(pr_reg_n);
                        return TCM_RESERVATION_CONFLICT;
@@ -3167,15 +3148,13 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
                if (!dest_tf_ops)
                        continue;
 
-               atomic_inc(&dest_se_tpg->tpg_pr_ref_count);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&dest_se_tpg->tpg_pr_ref_count);
                spin_unlock(&dev->se_port_lock);
 
                if (core_scsi3_tpg_depend_item(dest_se_tpg)) {
                        pr_err("core_scsi3_tpg_depend_item() failed"
                                " for dest_se_tpg\n");
-                       atomic_dec(&dest_se_tpg->tpg_pr_ref_count);
-                       smp_mb__after_atomic();
+                       atomic_dec_mb(&dest_se_tpg->tpg_pr_ref_count);
                        ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                        goto out_put_pr_reg;
                }
@@ -3271,10 +3250,8 @@ after_iport_check:
        spin_lock_irq(&dest_se_tpg->acl_node_lock);
        dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg,
                                initiator_str);
-       if (dest_node_acl) {
-               atomic_inc(&dest_node_acl->acl_pr_ref_count);
-               smp_mb__after_atomic();
-       }
+       if (dest_node_acl)
+               atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
        spin_unlock_irq(&dest_se_tpg->acl_node_lock);
 
        if (!dest_node_acl) {
@@ -3288,8 +3265,7 @@ after_iport_check:
        if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
                pr_err("core_scsi3_nodeacl_depend_item() for"
                        " dest_node_acl\n");
-               atomic_dec(&dest_node_acl->acl_pr_ref_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&dest_node_acl->acl_pr_ref_count);
                dest_node_acl = NULL;
                ret = TCM_INVALID_PARAMETER_LIST;
                goto out;
@@ -3313,8 +3289,7 @@ after_iport_check:
 
        if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
                pr_err("core_scsi3_lunacl_depend_item() failed\n");
-               atomic_dec(&dest_se_deve->pr_ref_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&dest_se_deve->pr_ref_count);
                dest_se_deve = NULL;
                ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                goto out;
@@ -3497,6 +3472,7 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb)
 sense_reason_t
 target_scsi3_emulate_pr_out(struct se_cmd *cmd)
 {
+       struct se_device *dev = cmd->se_dev;
        unsigned char *cdb = &cmd->t_task_cdb[0];
        unsigned char *buf;
        u64 res_key, sa_res_key;
@@ -3561,6 +3537,13 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd)
                aptpl = (buf[17] & 0x01);
                unreg = (buf[17] & 0x02);
        }
+       /*
+        * If the backend device has been configured to force APTPL metadata
+        * write-out, go ahead and propigate aptpl=1 down now.
+        */
+       if (dev->dev_attrib.force_pr_aptpl)
+               aptpl = 1;
+
        transport_kunmap_data_sg(cmd);
        buf = NULL;
 
@@ -3803,7 +3786,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
        if (!buf)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-       buf[0] = ((add_len << 8) & 0xff);
+       buf[0] = ((add_len >> 8) & 0xff);
        buf[1] = (add_len & 0xff);
        buf[2] |= 0x10; /* CRH: Compatible Reservation Hanlding bit. */
        buf[2] |= 0x08; /* SIP_C: Specify Initiator Ports Capable bit */
@@ -3879,8 +3862,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
                se_tpg = pr_reg->pr_reg_nacl->se_tpg;
                add_desc_len = 0;
 
-               atomic_inc(&pr_reg->pr_res_holders);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&pr_reg->pr_res_holders);
                spin_unlock(&pr_tmpl->registration_lock);
                /*
                 * Determine expected length of $FABRIC_MOD specific
@@ -3893,8 +3875,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
                        pr_warn("SPC-3 PRIN READ_FULL_STATUS ran"
                                " out of buffer: %d\n", cmd->data_length);
                        spin_lock(&pr_tmpl->registration_lock);
-                       atomic_dec(&pr_reg->pr_res_holders);
-                       smp_mb__after_atomic();
+                       atomic_dec_mb(&pr_reg->pr_res_holders);
                        break;
                }
                /*
@@ -3955,8 +3936,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
                                se_nacl, pr_reg, &format_code, &buf[off+4]);
 
                spin_lock(&pr_tmpl->registration_lock);
-               atomic_dec(&pr_reg->pr_res_holders);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&pr_reg->pr_res_holders);
                /*
                 * Set the ADDITIONAL DESCRIPTOR LENGTH
                 */
index 2ee2936fa0bd065d8755e96e85fa0a63250e9cc4..749fd7bb7510d0d7d9dcfcbc223c1169b0b3b5ae 100644 (file)
@@ -60,7 +60,7 @@ extern int core_scsi3_alloc_aptpl_registration(
                        unsigned char *, u16, u32, int, int, u8);
 extern int core_scsi3_check_aptpl_registration(struct se_device *,
                        struct se_portal_group *, struct se_lun *,
-                       struct se_lun_acl *);
+                       struct se_node_acl *, u32);
 extern void core_scsi3_free_pr_reg_from_nacl(struct se_device *,
                                             struct se_node_acl *);
 extern void core_scsi3_free_all_registrations(struct se_device *);
index 70d9f6dabba067b66c8b66fafa79242339315294..7c8291f0bbbce5f519bce28b1c6db8d4269a62bd 100644 (file)
@@ -749,14 +749,18 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_device *dev,
                                ret = -EINVAL;
                                goto out;
                        }
-                       match_int(args, &arg);
+                       ret = match_int(args, &arg);
+                       if (ret)
+                               goto out;
                        pdv->pdv_host_id = arg;
                        pr_debug("PSCSI[%d]: Referencing SCSI Host ID:"
                                " %d\n", phv->phv_host_id, pdv->pdv_host_id);
                        pdv->pdv_flags |= PDF_HAS_VIRT_HOST_ID;
                        break;
                case Opt_scsi_channel_id:
-                       match_int(args, &arg);
+                       ret = match_int(args, &arg);
+                       if (ret)
+                               goto out;
                        pdv->pdv_channel_id = arg;
                        pr_debug("PSCSI[%d]: Referencing SCSI Channel"
                                " ID: %d\n",  phv->phv_host_id,
@@ -764,7 +768,9 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_device *dev,
                        pdv->pdv_flags |= PDF_HAS_CHANNEL_ID;
                        break;
                case Opt_scsi_target_id:
-                       match_int(args, &arg);
+                       ret = match_int(args, &arg);
+                       if (ret)
+                               goto out;
                        pdv->pdv_target_id = arg;
                        pr_debug("PSCSI[%d]: Referencing SCSI Target"
                                " ID: %d\n", phv->phv_host_id,
@@ -772,7 +778,9 @@ static ssize_t pscsi_set_configfs_dev_params(struct se_device *dev,
                        pdv->pdv_flags |= PDF_HAS_TARGET_ID;
                        break;
                case Opt_scsi_lun_id:
-                       match_int(args, &arg);
+                       ret = match_int(args, &arg);
+                       if (ret)
+                               goto out;
                        pdv->pdv_lun_id = arg;
                        pr_debug("PSCSI[%d]: Referencing SCSI LUN ID:"
                                " %d\n", phv->phv_host_id, pdv->pdv_lun_id);
index bd78d9235ac645678aeaacc3a564c1c4c13c5742..8d171ff77e75d48f4ba443f5f896c44f6453f292 100644 (file)
@@ -852,7 +852,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
                size = READ_CAP_LEN;
                cmd->execute_cmd = sbc_emulate_readcapacity;
                break;
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                switch (cmd->t_task_cdb[1] & 0x1f) {
                case SAI_READ_CAPACITY_16:
                        cmd->execute_cmd = sbc_emulate_readcapacity_16;
@@ -948,7 +948,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
        }
 
        /* reject any command that we don't have a handler for */
-       if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd)
+       if (!cmd->execute_cmd)
                return TCM_UNSUPPORTED_SCSI_OPCODE;
 
        if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
index f7cd95e8111a7e496cf198c9f6a7ec18f854942b..fa5e157db47be242f855a9c1a209ea9e08e60c3d 100644 (file)
@@ -64,21 +64,17 @@ int core_tmr_alloc_req(
 }
 EXPORT_SYMBOL(core_tmr_alloc_req);
 
-void core_tmr_release_req(
-       struct se_tmr_req *tmr)
+void core_tmr_release_req(struct se_tmr_req *tmr)
 {
        struct se_device *dev = tmr->tmr_dev;
        unsigned long flags;
 
-       if (!dev) {
-               kfree(tmr);
-               return;
+       if (dev) {
+               spin_lock_irqsave(&dev->se_tmr_lock, flags);
+               list_del(&tmr->tmr_list);
+               spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
        }
 
-       spin_lock_irqsave(&dev->se_tmr_lock, flags);
-       list_del(&tmr->tmr_list);
-       spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
-
        kfree(tmr);
 }
 
@@ -90,9 +86,8 @@ static void core_tmr_handle_tas_abort(
        bool remove = true;
        /*
         * TASK ABORTED status (TAS) bit support
-       */
-       if ((tmr_nacl &&
-            (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) {
+        */
+       if ((tmr_nacl && (tmr_nacl != cmd->se_sess->se_node_acl)) && tas) {
                remove = false;
                transport_send_task_abort(cmd);
        }
@@ -120,13 +115,12 @@ void core_tmr_abort_task(
        struct se_tmr_req *tmr,
        struct se_session *se_sess)
 {
-       struct se_cmd *se_cmd, *tmp_cmd;
+       struct se_cmd *se_cmd;
        unsigned long flags;
        int ref_tag;
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
-       list_for_each_entry_safe(se_cmd, tmp_cmd,
-                       &se_sess->sess_cmd_list, se_cmd_list) {
+       list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) {
 
                if (dev != se_cmd->se_dev)
                        continue;
index be783f717f1923013f44caa03482e064d51510c6..0696de9553d3d7dea5b8e0f1f874f5f5b91ab821 100644 (file)
@@ -40,6 +40,7 @@
 #include <target/target_core_fabric.h>
 
 #include "target_core_internal.h"
+#include "target_core_pr.h"
 
 extern struct se_device *g_lun0_dev;
 
@@ -166,6 +167,13 @@ void core_tpg_add_node_to_devs(
 
                core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun,
                                lun_access, acl, tpg);
+               /*
+                * Check to see if there are any existing persistent reservation
+                * APTPL pre-registrations that need to be enabled for this dynamic
+                * LUN ACL now..
+                */
+               core_scsi3_check_aptpl_registration(dev, tpg, lun, acl,
+                                                   lun->unpacked_lun);
                spin_lock(&tpg->tpg_lun_lock);
        }
        spin_unlock(&tpg->tpg_lun_lock);
@@ -335,7 +343,7 @@ void core_tpg_clear_object_luns(struct se_portal_group *tpg)
                        continue;
 
                spin_unlock(&tpg->tpg_lun_lock);
-               core_dev_del_lun(tpg, lun->unpacked_lun);
+               core_dev_del_lun(tpg, lun);
                spin_lock(&tpg->tpg_lun_lock);
        }
        spin_unlock(&tpg->tpg_lun_lock);
@@ -663,13 +671,6 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
        return 0;
 }
 
-static void core_tpg_release_virtual_lun0(struct se_portal_group *se_tpg)
-{
-       struct se_lun *lun = &se_tpg->tpg_virt_lun0;
-
-       core_tpg_post_dellun(se_tpg, lun);
-}
-
 int core_tpg_register(
        struct target_core_fabric_ops *tfo,
        struct se_wwn *se_wwn,
@@ -773,7 +774,7 @@ int core_tpg_deregister(struct se_portal_group *se_tpg)
        spin_unlock_irq(&se_tpg->acl_node_lock);
 
        if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL)
-               core_tpg_release_virtual_lun0(se_tpg);
+               core_tpg_remove_lun(se_tpg, &se_tpg->tpg_virt_lun0);
 
        se_tpg->se_tpg_fabric_ptr = NULL;
        array_free(se_tpg->tpg_lun_list, TRANSPORT_MAX_LUNS_PER_TPG);
@@ -838,37 +839,7 @@ int core_tpg_add_lun(
        return 0;
 }
 
-struct se_lun *core_tpg_pre_dellun(
-       struct se_portal_group *tpg,
-       u32 unpacked_lun)
-{
-       struct se_lun *lun;
-
-       if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
-               pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG"
-                       "-1: %u for Target Portal Group: %u\n",
-                       tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
-                       TRANSPORT_MAX_LUNS_PER_TPG-1,
-                       tpg->se_tpg_tfo->tpg_get_tag(tpg));
-               return ERR_PTR(-EOVERFLOW);
-       }
-
-       spin_lock(&tpg->tpg_lun_lock);
-       lun = tpg->tpg_lun_list[unpacked_lun];
-       if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
-               pr_err("%s Logical Unit Number: %u is not active on"
-                       " Target Portal Group: %u, ignoring request.\n",
-                       tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
-                       tpg->se_tpg_tfo->tpg_get_tag(tpg));
-               spin_unlock(&tpg->tpg_lun_lock);
-               return ERR_PTR(-ENODEV);
-       }
-       spin_unlock(&tpg->tpg_lun_lock);
-
-       return lun;
-}
-
-int core_tpg_post_dellun(
+void core_tpg_remove_lun(
        struct se_portal_group *tpg,
        struct se_lun *lun)
 {
@@ -882,6 +853,4 @@ int core_tpg_post_dellun(
        spin_unlock(&tpg->tpg_lun_lock);
 
        percpu_ref_exit(&lun->lun_ref);
-
-       return 0;
 }
index 7fa62fc93e0b52d70ac49c67f5455a139935f55c..be877bf6f7304a88fabb3506d65ac75542471b01 100644 (file)
@@ -232,6 +232,10 @@ void transport_subsystem_check_init(void)
        if (ret != 0)
                pr_err("Unable to load target_core_pscsi\n");
 
+       ret = request_module("target_core_user");
+       if (ret != 0)
+               pr_err("Unable to load target_core_user\n");
+
        sub_api_initialized = 1;
 }
 
@@ -752,8 +756,7 @@ void target_qf_do_work(struct work_struct *work)
 
        list_for_each_entry_safe(cmd, cmd_tmp, &qf_cmd_list, se_qf_node) {
                list_del(&cmd->se_qf_node);
-               atomic_dec(&dev->dev_qf_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&dev->dev_qf_count);
 
                pr_debug("Processing %s cmd: %p QUEUE_FULL in work queue"
                        " context: %s\n", cmd->se_tfo->get_fabric_name(), cmd,
@@ -1166,7 +1169,6 @@ transport_check_alloc_task_attr(struct se_cmd *cmd)
         * Dormant to Active status.
         */
        cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id);
-       smp_mb__after_atomic();
        pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n",
                        cmd->se_ordered_id, cmd->sam_task_attr,
                        dev->transport->name);
@@ -1722,8 +1724,7 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
                         cmd->t_task_cdb[0], cmd->se_ordered_id);
                return false;
        case MSG_ORDERED_TAG:
-               atomic_inc(&dev->dev_ordered_sync);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&dev->dev_ordered_sync);
 
                pr_debug("Added ORDERED for CDB: 0x%02x to ordered list, "
                         " se_ordered_id: %u\n",
@@ -1740,8 +1741,7 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
                /*
                 * For SIMPLE and UNTAGGED Task Attribute commands
                 */
-               atomic_inc(&dev->simple_cmds);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&dev->simple_cmds);
                break;
        }
 
@@ -1845,8 +1845,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
                return;
 
        if (cmd->sam_task_attr == MSG_SIMPLE_TAG) {
-               atomic_dec(&dev->simple_cmds);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&dev->simple_cmds);
                dev->dev_cur_ordered_id++;
                pr_debug("Incremented dev->dev_cur_ordered_id: %u for"
                        " SIMPLE: %u\n", dev->dev_cur_ordered_id,
@@ -1857,8 +1856,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
                        " HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id,
                        cmd->se_ordered_id);
        } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) {
-               atomic_dec(&dev->dev_ordered_sync);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&dev->dev_ordered_sync);
 
                dev->dev_cur_ordered_id++;
                pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:"
@@ -1877,8 +1875,7 @@ static void transport_complete_qf(struct se_cmd *cmd)
        if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
                trace_target_cmd_complete(cmd);
                ret = cmd->se_tfo->queue_status(cmd);
-               if (ret)
-                       goto out;
+               goto out;
        }
 
        switch (cmd->data_direction) {
@@ -1916,8 +1913,7 @@ static void transport_handle_queue_full(
 {
        spin_lock_irq(&dev->qf_cmd_lock);
        list_add_tail(&cmd->se_qf_node, &cmd->se_dev->qf_cmd_list);
-       atomic_inc(&dev->dev_qf_count);
-       smp_mb__after_atomic();
+       atomic_inc_mb(&dev->dev_qf_count);
        spin_unlock_irq(&cmd->se_dev->qf_cmd_lock);
 
        schedule_work(&cmd->se_dev->qf_work_queue);
@@ -2296,7 +2292,7 @@ transport_generic_new_cmd(struct se_cmd *cmd)
         * and let it call back once the write buffers are ready.
         */
        target_add_to_state_list(cmd);
-       if (cmd->data_direction != DMA_TO_DEVICE) {
+       if (cmd->data_direction != DMA_TO_DEVICE || cmd->data_length == 0) {
                target_execute_cmd(cmd);
                return 0;
        }
@@ -2896,7 +2892,6 @@ void transport_send_task_abort(struct se_cmd *cmd)
                if (cmd->se_tfo->write_pending_status(cmd) != 0) {
                        cmd->transport_state |= CMD_T_ABORTED;
                        cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
-                       smp_mb__after_atomic();
                        return;
                }
        }
index 101858e245b36c3ad7da937ec3637e7ec32650d6..1738b164698877d984d83239250b717aba83b2d7 100644 (file)
@@ -161,8 +161,7 @@ int core_scsi3_ua_allocate(
                spin_unlock(&deve->ua_lock);
                spin_unlock_irq(&nacl->device_list_lock);
 
-               atomic_inc(&deve->ua_count);
-               smp_mb__after_atomic();
+               atomic_inc_mb(&deve->ua_count);
                return 0;
        }
        list_add_tail(&ua->ua_nacl_list, &deve->ua_list);
@@ -174,8 +173,7 @@ int core_scsi3_ua_allocate(
                nacl->se_tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
                asc, ascq);
 
-       atomic_inc(&deve->ua_count);
-       smp_mb__after_atomic();
+       atomic_inc_mb(&deve->ua_count);
        return 0;
 }
 
@@ -189,8 +187,7 @@ void core_scsi3_ua_release_all(
                list_del(&ua->ua_nacl_list);
                kmem_cache_free(se_ua_cache, ua);
 
-               atomic_dec(&deve->ua_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&deve->ua_count);
        }
        spin_unlock(&deve->ua_lock);
 }
@@ -250,8 +247,7 @@ void core_scsi3_ua_for_check_condition(
                list_del(&ua->ua_nacl_list);
                kmem_cache_free(se_ua_cache, ua);
 
-               atomic_dec(&deve->ua_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&deve->ua_count);
        }
        spin_unlock(&deve->ua_lock);
        spin_unlock_irq(&nacl->device_list_lock);
@@ -309,8 +305,7 @@ int core_scsi3_ua_clear_for_request_sense(
                list_del(&ua->ua_nacl_list);
                kmem_cache_free(se_ua_cache, ua);
 
-               atomic_dec(&deve->ua_count);
-               smp_mb__after_atomic();
+               atomic_dec_mb(&deve->ua_count);
        }
        spin_unlock(&deve->ua_lock);
        spin_unlock_irq(&nacl->device_list_lock);
index be912b36daae63cc4ca46ab51a75383be8b8cb39..a6b56b364e7af5b7895df6f8b955c3d3d053f296 100644 (file)
@@ -1,4 +1,5 @@
 #ifndef TARGET_CORE_UA_H
+#define TARGET_CORE_UA_H
 
 /*
  * From spc4r17, Table D.1: ASC and ASCQ Assignement
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
new file mode 100644 (file)
index 0000000..9a1b314
--- /dev/null
@@ -0,0 +1,1167 @@
+/*
+ * Copyright (C) 2013 Shaohua Li <shli@kernel.org>
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/idr.h>
+#include <linux/timer.h>
+#include <linux/parser.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <linux/uio_driver.h>
+#include <net/genetlink.h>
+#include <target/target_core_base.h>
+#include <target/target_core_fabric.h>
+#include <target/target_core_backend.h>
+#include <linux/target_core_user.h>
+
+/*
+ * Define a shared-memory interface for LIO to pass SCSI commands and
+ * data to userspace for processing. This is to allow backends that
+ * are too complex for in-kernel support to be possible.
+ *
+ * It uses the UIO framework to do a lot of the device-creation and
+ * introspection work for us.
+ *
+ * See the .h file for how the ring is laid out. Note that while the
+ * command ring is defined, the particulars of the data area are
+ * not. Offset values in the command entry point to other locations
+ * internal to the mmap()ed area. There is separate space outside the
+ * command ring for data buffers. This leaves maximum flexibility for
+ * moving buffer allocations, or even page flipping or other
+ * allocation techniques, without altering the command ring layout.
+ *
+ * SECURITY:
+ * The user process must be assumed to be malicious. There's no way to
+ * prevent it breaking the command ring protocol if it wants, but in
+ * order to prevent other issues we must only ever read *data* from
+ * the shared memory area, not offsets or sizes. This applies to
+ * command ring entries as well as the mailbox. Extra code needed for
+ * this may have a 'UAM' comment.
+ */
+
+
+#define TCMU_TIME_OUT (30 * MSEC_PER_SEC)
+
+#define CMDR_SIZE (16 * 4096)
+#define DATA_SIZE (257 * 4096)
+
+#define TCMU_RING_SIZE (CMDR_SIZE + DATA_SIZE)
+
+static struct device *tcmu_root_device;
+
+struct tcmu_hba {
+       u32 host_id;
+};
+
+/* User wants all cmds or just some */
+enum passthru_level {
+       TCMU_PASS_ALL = 0,
+       TCMU_PASS_IO,
+       TCMU_PASS_INVALID,
+};
+
+#define TCMU_CONFIG_LEN 256
+
+struct tcmu_dev {
+       struct se_device se_dev;
+
+       char *name;
+       struct se_hba *hba;
+
+#define TCMU_DEV_BIT_OPEN 0
+#define TCMU_DEV_BIT_BROKEN 1
+       unsigned long flags;
+       enum passthru_level pass_level;
+
+       struct uio_info uio_info;
+
+       struct tcmu_mailbox *mb_addr;
+       size_t dev_size;
+       u32 cmdr_size;
+       u32 cmdr_last_cleaned;
+       /* Offset of data ring from start of mb */
+       size_t data_off;
+       size_t data_size;
+       /* Ring head + tail values. */
+       /* Must add data_off and mb_addr to get the address */
+       size_t data_head;
+       size_t data_tail;
+
+       wait_queue_head_t wait_cmdr;
+       /* TODO should this be a mutex? */
+       spinlock_t cmdr_lock;
+
+       struct idr commands;
+       spinlock_t commands_lock;
+
+       struct timer_list timeout;
+
+       char dev_config[TCMU_CONFIG_LEN];
+};
+
+#define TCMU_DEV(_se_dev) container_of(_se_dev, struct tcmu_dev, se_dev)
+
+#define CMDR_OFF sizeof(struct tcmu_mailbox)
+
+struct tcmu_cmd {
+       struct se_cmd *se_cmd;
+       struct tcmu_dev *tcmu_dev;
+
+       uint16_t cmd_id;
+
+       /* Can't use se_cmd->data_length when cleaning up expired cmds, because if
+          cmd has been completed then accessing se_cmd is off limits */
+       size_t data_length;
+
+       unsigned long deadline;
+
+#define TCMU_CMD_BIT_EXPIRED 0
+       unsigned long flags;
+};
+
+static struct kmem_cache *tcmu_cmd_cache;
+
+/* multicast group */
+enum tcmu_multicast_groups {
+       TCMU_MCGRP_CONFIG,
+};
+
+static const struct genl_multicast_group tcmu_mcgrps[] = {
+       [TCMU_MCGRP_CONFIG] = { .name = "config", },
+};
+
+/* Our generic netlink family */
+static struct genl_family tcmu_genl_family = {
+       .id = GENL_ID_GENERATE,
+       .hdrsize = 0,
+       .name = "TCM-USER",
+       .version = 1,
+       .maxattr = TCMU_ATTR_MAX,
+       .mcgrps = tcmu_mcgrps,
+       .n_mcgrps = ARRAY_SIZE(tcmu_mcgrps),
+};
+
+static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
+{
+       struct se_device *se_dev = se_cmd->se_dev;
+       struct tcmu_dev *udev = TCMU_DEV(se_dev);
+       struct tcmu_cmd *tcmu_cmd;
+       int cmd_id;
+
+       tcmu_cmd = kmem_cache_zalloc(tcmu_cmd_cache, GFP_KERNEL);
+       if (!tcmu_cmd)
+               return NULL;
+
+       tcmu_cmd->se_cmd = se_cmd;
+       tcmu_cmd->tcmu_dev = udev;
+       tcmu_cmd->data_length = se_cmd->data_length;
+
+       tcmu_cmd->deadline = jiffies + msecs_to_jiffies(TCMU_TIME_OUT);
+
+       idr_preload(GFP_KERNEL);
+       spin_lock_irq(&udev->commands_lock);
+       cmd_id = idr_alloc(&udev->commands, tcmu_cmd, 0,
+               USHRT_MAX, GFP_NOWAIT);
+       spin_unlock_irq(&udev->commands_lock);
+       idr_preload_end();
+
+       if (cmd_id < 0) {
+               kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
+               return NULL;
+       }
+       tcmu_cmd->cmd_id = cmd_id;
+
+       return tcmu_cmd;
+}
+
+static inline void tcmu_flush_dcache_range(void *vaddr, size_t size)
+{
+       unsigned long offset = (unsigned long) vaddr & ~PAGE_MASK;
+
+       size = round_up(size+offset, PAGE_SIZE);
+       vaddr -= offset;
+
+       while (size) {
+               flush_dcache_page(virt_to_page(vaddr));
+               size -= PAGE_SIZE;
+       }
+}
+
+/*
+ * Some ring helper functions. We don't assume size is a power of 2 so
+ * we can't use circ_buf.h.
+ */
+static inline size_t spc_used(size_t head, size_t tail, size_t size)
+{
+       int diff = head - tail;
+
+       if (diff >= 0)
+               return diff;
+       else
+               return size + diff;
+}
+
+static inline size_t spc_free(size_t head, size_t tail, size_t size)
+{
+       /* Keep 1 byte unused or we can't tell full from empty */
+       return (size - spc_used(head, tail, size) - 1);
+}
+
+static inline size_t head_to_end(size_t head, size_t size)
+{
+       return size - head;
+}
+
+#define UPDATE_HEAD(head, used, size) smp_store_release(&head, ((head % size) + used) % size)
+
+/*
+ * We can't queue a command until we have space available on the cmd ring *and* space
+ * space avail on the data ring.
+ *
+ * Called with ring lock held.
+ */
+static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t data_needed)
+{
+       struct tcmu_mailbox *mb = udev->mb_addr;
+       size_t space;
+       u32 cmd_head;
+       size_t cmd_needed;
+
+       tcmu_flush_dcache_range(mb, sizeof(*mb));
+
+       cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
+
+       /*
+        * If cmd end-of-ring space is too small then we need space for a NOP plus
+        * original cmd - cmds are internally contiguous.
+        */
+       if (head_to_end(cmd_head, udev->cmdr_size) >= cmd_size)
+               cmd_needed = cmd_size;
+       else
+               cmd_needed = cmd_size + head_to_end(cmd_head, udev->cmdr_size);
+
+       space = spc_free(cmd_head, udev->cmdr_last_cleaned, udev->cmdr_size);
+       if (space < cmd_needed) {
+               pr_debug("no cmd space: %u %u %u\n", cmd_head,
+                      udev->cmdr_last_cleaned, udev->cmdr_size);
+               return false;
+       }
+
+       space = spc_free(udev->data_head, udev->data_tail, udev->data_size);
+       if (space < data_needed) {
+               pr_debug("no data space: %zu %zu %zu\n", udev->data_head,
+                      udev->data_tail, udev->data_size);
+               return false;
+       }
+
+       return true;
+}
+
+static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
+{
+       struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
+       struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
+       size_t base_command_size, command_size;
+       struct tcmu_mailbox *mb;
+       struct tcmu_cmd_entry *entry;
+       int i;
+       struct scatterlist *sg;
+       struct iovec *iov;
+       int iov_cnt = 0;
+       uint32_t cmd_head;
+       uint64_t cdb_off;
+
+       if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags))
+               return -EINVAL;
+
+       /*
+        * Must be a certain minimum size for response sense info, but
+        * also may be larger if the iov array is large.
+        *
+        * iovs = sgl_nents+1, for end-of-ring case, plus another 1
+        * b/c size == offsetof one-past-element.
+       */
+       base_command_size = max(offsetof(struct tcmu_cmd_entry,
+                                        req.iov[se_cmd->t_data_nents + 2]),
+                               sizeof(struct tcmu_cmd_entry));
+       command_size = base_command_size
+               + round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE);
+
+       WARN_ON(command_size & (TCMU_OP_ALIGN_SIZE-1));
+
+       spin_lock_irq(&udev->cmdr_lock);
+
+       mb = udev->mb_addr;
+       cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
+       if ((command_size > (udev->cmdr_size / 2))
+           || tcmu_cmd->data_length > (udev->data_size - 1))
+               pr_warn("TCMU: Request of size %zu/%zu may be too big for %u/%zu "
+                       "cmd/data ring buffers\n", command_size, tcmu_cmd->data_length,
+                       udev->cmdr_size, udev->data_size);
+
+       while (!is_ring_space_avail(udev, command_size, tcmu_cmd->data_length)) {
+               int ret;
+               DEFINE_WAIT(__wait);
+
+               prepare_to_wait(&udev->wait_cmdr, &__wait, TASK_INTERRUPTIBLE);
+
+               pr_debug("sleeping for ring space\n");
+               spin_unlock_irq(&udev->cmdr_lock);
+               ret = schedule_timeout(msecs_to_jiffies(TCMU_TIME_OUT));
+               finish_wait(&udev->wait_cmdr, &__wait);
+               if (!ret) {
+                       pr_warn("tcmu: command timed out\n");
+                       return -ETIMEDOUT;
+               }
+
+               spin_lock_irq(&udev->cmdr_lock);
+
+               /* We dropped cmdr_lock, cmd_head is stale */
+               cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
+       }
+
+       /* Insert a PAD if end-of-ring space is too small */
+       if (head_to_end(cmd_head, udev->cmdr_size) < command_size) {
+               size_t pad_size = head_to_end(cmd_head, udev->cmdr_size);
+
+               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);
+
+               UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size);
+
+               cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
+               WARN_ON(cmd_head != 0);
+       }
+
+       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;
+
+       /*
+        * Fix up iovecs, and handle if allocation in data ring wrapped.
+        */
+       iov = &entry->req.iov[0];
+       for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, i) {
+               size_t copy_bytes = min((size_t)sg->length,
+                                    head_to_end(udev->data_head, udev->data_size));
+               void *from = kmap_atomic(sg_page(sg)) + sg->offset;
+               void *to = (void *) mb + udev->data_off + udev->data_head;
+
+               if (tcmu_cmd->se_cmd->data_direction == DMA_TO_DEVICE) {
+                       memcpy(to, from, copy_bytes);
+                       tcmu_flush_dcache_range(to, copy_bytes);
+               }
+
+               /* Even iov_base is relative to mb_addr */
+               iov->iov_len = copy_bytes;
+               iov->iov_base = (void *) udev->data_off + udev->data_head;
+               iov_cnt++;
+               iov++;
+
+               UPDATE_HEAD(udev->data_head, copy_bytes, udev->data_size);
+
+               /* Uh oh, we wrapped the buffer. Must split sg across 2 iovs. */
+               if (sg->length != copy_bytes) {
+                       from += copy_bytes;
+                       copy_bytes = sg->length - copy_bytes;
+
+                       iov->iov_len = copy_bytes;
+                       iov->iov_base = (void *) udev->data_off + udev->data_head;
+
+                       if (se_cmd->data_direction == DMA_TO_DEVICE) {
+                               to = (void *) mb + udev->data_off + udev->data_head;
+                               memcpy(to, from, copy_bytes);
+                               tcmu_flush_dcache_range(to, copy_bytes);
+                       }
+
+                       iov_cnt++;
+                       iov++;
+
+                       UPDATE_HEAD(udev->data_head, copy_bytes, udev->data_size);
+               }
+
+               kunmap_atomic(from);
+       }
+       entry->req.iov_cnt = iov_cnt;
+
+       /* All offsets relative to mb_addr, not start of entry! */
+       cdb_off = CMDR_OFF + cmd_head + base_command_size;
+       memcpy((void *) mb + cdb_off, se_cmd->t_task_cdb, scsi_command_size(se_cmd->t_task_cdb));
+       entry->req.cdb_off = cdb_off;
+       tcmu_flush_dcache_range(entry, sizeof(*entry));
+
+       UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
+       tcmu_flush_dcache_range(mb, sizeof(*mb));
+
+       spin_unlock_irq(&udev->cmdr_lock);
+
+       /* TODO: only if FLUSH and FUA? */
+       uio_event_notify(&udev->uio_info);
+
+       mod_timer(&udev->timeout,
+               round_jiffies_up(jiffies + msecs_to_jiffies(TCMU_TIME_OUT)));
+
+       return 0;
+}
+
+static int tcmu_queue_cmd(struct se_cmd *se_cmd)
+{
+       struct se_device *se_dev = se_cmd->se_dev;
+       struct tcmu_dev *udev = TCMU_DEV(se_dev);
+       struct tcmu_cmd *tcmu_cmd;
+       int ret;
+
+       tcmu_cmd = tcmu_alloc_cmd(se_cmd);
+       if (!tcmu_cmd)
+               return -ENOMEM;
+
+       ret = tcmu_queue_cmd_ring(tcmu_cmd);
+       if (ret < 0) {
+               pr_err("TCMU: Could not queue command\n");
+               spin_lock_irq(&udev->commands_lock);
+               idr_remove(&udev->commands, tcmu_cmd->cmd_id);
+               spin_unlock_irq(&udev->commands_lock);
+
+               kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
+       }
+
+       return ret;
+}
+
+static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *entry)
+{
+       struct se_cmd *se_cmd = cmd->se_cmd;
+       struct tcmu_dev *udev = cmd->tcmu_dev;
+
+       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+               /* cmd has been completed already from timeout, just reclaim data
+                  ring space */
+               UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
+               return;
+       }
+
+       if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) {
+               memcpy(se_cmd->sense_buffer, entry->rsp.sense_buffer,
+                              se_cmd->scsi_sense_length);
+
+               UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
+       }
+       else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
+               struct scatterlist *sg;
+               int i;
+
+               /* It'd be easier to look at entry's iovec again, but UAM */
+               for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, i) {
+                       size_t copy_bytes;
+                       void *to;
+                       void *from;
+
+                       copy_bytes = min((size_t)sg->length,
+                                        head_to_end(udev->data_tail, udev->data_size));
+
+                       to = kmap_atomic(sg_page(sg)) + sg->offset;
+                       WARN_ON(sg->length + sg->offset > PAGE_SIZE);
+                       from = (void *) udev->mb_addr + udev->data_off + udev->data_tail;
+                       tcmu_flush_dcache_range(from, copy_bytes);
+                       memcpy(to, from, copy_bytes);
+
+                       UPDATE_HEAD(udev->data_tail, copy_bytes, udev->data_size);
+
+                       /* Uh oh, wrapped the data buffer for this sg's data */
+                       if (sg->length != copy_bytes) {
+                               from = (void *) udev->mb_addr + udev->data_off + udev->data_tail;
+                               WARN_ON(udev->data_tail);
+                               to += copy_bytes;
+                               copy_bytes = sg->length - copy_bytes;
+                               tcmu_flush_dcache_range(from, copy_bytes);
+                               memcpy(to, from, copy_bytes);
+
+                               UPDATE_HEAD(udev->data_tail, copy_bytes, udev->data_size);
+                       }
+
+                       kunmap_atomic(to);
+               }
+
+       } else if (se_cmd->data_direction == DMA_TO_DEVICE) {
+               UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
+       } else {
+               pr_warn("TCMU: data direction was %d!\n", se_cmd->data_direction);
+       }
+
+       target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status);
+       cmd->se_cmd = NULL;
+
+       kmem_cache_free(tcmu_cmd_cache, cmd);
+}
+
+static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
+{
+       struct tcmu_mailbox *mb;
+       LIST_HEAD(cpl_cmds);
+       unsigned long flags;
+       int handled = 0;
+
+       if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) {
+               pr_err("ring broken, not handling completions\n");
+               return 0;
+       }
+
+       spin_lock_irqsave(&udev->cmdr_lock, flags);
+
+       mb = udev->mb_addr;
+       tcmu_flush_dcache_range(mb, sizeof(*mb));
+
+       while (udev->cmdr_last_cleaned != ACCESS_ONCE(mb->cmd_tail)) {
+
+               struct tcmu_cmd_entry *entry = (void *) mb + CMDR_OFF + udev->cmdr_last_cleaned;
+               struct tcmu_cmd *cmd;
+
+               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);
+                       continue;
+               }
+               WARN_ON(tcmu_hdr_get_op(&entry->hdr) != TCMU_OP_CMD);
+
+               spin_lock(&udev->commands_lock);
+               cmd = idr_find(&udev->commands, entry->cmd_id);
+               if (cmd)
+                       idr_remove(&udev->commands, cmd->cmd_id);
+               spin_unlock(&udev->commands_lock);
+
+               if (!cmd) {
+                       pr_err("cmd_id not found, ring is broken\n");
+                       set_bit(TCMU_DEV_BIT_BROKEN, &udev->flags);
+                       break;
+               }
+
+               tcmu_handle_completion(cmd, entry);
+
+               UPDATE_HEAD(udev->cmdr_last_cleaned, tcmu_hdr_get_len(&entry->hdr), udev->cmdr_size);
+
+               handled++;
+       }
+
+       if (mb->cmd_tail == mb->cmd_head)
+               del_timer(&udev->timeout); /* no more pending cmds */
+
+       spin_unlock_irqrestore(&udev->cmdr_lock, flags);
+
+       wake_up(&udev->wait_cmdr);
+
+       return handled;
+}
+
+static int tcmu_check_expired_cmd(int id, void *p, void *data)
+{
+       struct tcmu_cmd *cmd = p;
+
+       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
+               return 0;
+
+       if (!time_after(cmd->deadline, jiffies))
+               return 0;
+
+       set_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
+       target_complete_cmd(cmd->se_cmd, SAM_STAT_CHECK_CONDITION);
+       cmd->se_cmd = NULL;
+
+       kmem_cache_free(tcmu_cmd_cache, cmd);
+
+       return 0;
+}
+
+static void tcmu_device_timedout(unsigned long data)
+{
+       struct tcmu_dev *udev = (struct tcmu_dev *)data;
+       unsigned long flags;
+       int handled;
+
+       handled = tcmu_handle_completions(udev);
+
+       pr_warn("%d completions handled from timeout\n", handled);
+
+       spin_lock_irqsave(&udev->commands_lock, flags);
+       idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
+       spin_unlock_irqrestore(&udev->commands_lock, flags);
+
+       /*
+        * We don't need to wakeup threads on wait_cmdr since they have their
+        * own timeout.
+        */
+}
+
+static int tcmu_attach_hba(struct se_hba *hba, u32 host_id)
+{
+       struct tcmu_hba *tcmu_hba;
+
+       tcmu_hba = kzalloc(sizeof(struct tcmu_hba), GFP_KERNEL);
+       if (!tcmu_hba)
+               return -ENOMEM;
+
+       tcmu_hba->host_id = host_id;
+       hba->hba_ptr = tcmu_hba;
+
+       return 0;
+}
+
+static void tcmu_detach_hba(struct se_hba *hba)
+{
+       kfree(hba->hba_ptr);
+       hba->hba_ptr = NULL;
+}
+
+static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
+{
+       struct tcmu_dev *udev;
+
+       udev = kzalloc(sizeof(struct tcmu_dev), GFP_KERNEL);
+       if (!udev)
+               return NULL;
+
+       udev->name = kstrdup(name, GFP_KERNEL);
+       if (!udev->name) {
+               kfree(udev);
+               return NULL;
+       }
+
+       udev->hba = hba;
+
+       init_waitqueue_head(&udev->wait_cmdr);
+       spin_lock_init(&udev->cmdr_lock);
+
+       idr_init(&udev->commands);
+       spin_lock_init(&udev->commands_lock);
+
+       setup_timer(&udev->timeout, tcmu_device_timedout,
+               (unsigned long)udev);
+
+       udev->pass_level = TCMU_PASS_ALL;
+
+       return &udev->se_dev;
+}
+
+static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on)
+{
+       struct tcmu_dev *tcmu_dev = container_of(info, struct tcmu_dev, uio_info);
+
+       tcmu_handle_completions(tcmu_dev);
+
+       return 0;
+}
+
+/*
+ * mmap code from uio.c. Copied here because we want to hook mmap()
+ * and this stuff must come along.
+ */
+static int tcmu_find_mem_index(struct vm_area_struct *vma)
+{
+       struct tcmu_dev *udev = vma->vm_private_data;
+       struct uio_info *info = &udev->uio_info;
+
+       if (vma->vm_pgoff < MAX_UIO_MAPS) {
+               if (info->mem[vma->vm_pgoff].size == 0)
+                       return -1;
+               return (int)vma->vm_pgoff;
+       }
+       return -1;
+}
+
+static int tcmu_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct tcmu_dev *udev = vma->vm_private_data;
+       struct uio_info *info = &udev->uio_info;
+       struct page *page;
+       unsigned long offset;
+       void *addr;
+
+       int mi = tcmu_find_mem_index(vma);
+       if (mi < 0)
+               return VM_FAULT_SIGBUS;
+
+       /*
+        * We need to subtract mi because userspace uses offset = N*PAGE_SIZE
+        * to use mem[N].
+        */
+       offset = (vmf->pgoff - mi) << PAGE_SHIFT;
+
+       addr = (void *)(unsigned long)info->mem[mi].addr + offset;
+       if (info->mem[mi].memtype == UIO_MEM_LOGICAL)
+               page = virt_to_page(addr);
+       else
+               page = vmalloc_to_page(addr);
+       get_page(page);
+       vmf->page = page;
+       return 0;
+}
+
+static const struct vm_operations_struct tcmu_vm_ops = {
+       .fault = tcmu_vma_fault,
+};
+
+static int tcmu_mmap(struct uio_info *info, struct vm_area_struct *vma)
+{
+       struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info);
+
+       vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+       vma->vm_ops = &tcmu_vm_ops;
+
+       vma->vm_private_data = udev;
+
+       /* Ensure the mmap is exactly the right size */
+       if (vma_pages(vma) != (TCMU_RING_SIZE >> PAGE_SHIFT))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int tcmu_open(struct uio_info *info, struct inode *inode)
+{
+       struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info);
+
+       /* O_EXCL not supported for char devs, so fake it? */
+       if (test_and_set_bit(TCMU_DEV_BIT_OPEN, &udev->flags))
+               return -EBUSY;
+
+       pr_debug("open\n");
+
+       return 0;
+}
+
+static int tcmu_release(struct uio_info *info, struct inode *inode)
+{
+       struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info);
+
+       clear_bit(TCMU_DEV_BIT_OPEN, &udev->flags);
+
+       pr_debug("close\n");
+
+       return 0;
+}
+
+static int tcmu_netlink_event(enum tcmu_genl_cmd cmd, const char *name, int minor)
+{
+       struct sk_buff *skb;
+       void *msg_header;
+       int ret = -ENOMEM;
+
+       skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+       if (!skb)
+               return ret;
+
+       msg_header = genlmsg_put(skb, 0, 0, &tcmu_genl_family, 0, cmd);
+       if (!msg_header)
+               goto free_skb;
+
+       ret = nla_put_string(skb, TCMU_ATTR_DEVICE, name);
+       if (ret < 0)
+               goto free_skb;
+
+       ret = nla_put_u32(skb, TCMU_ATTR_MINOR, minor);
+       if (ret < 0)
+               goto free_skb;
+
+       ret = genlmsg_end(skb, msg_header);
+       if (ret < 0)
+               goto free_skb;
+
+       ret = genlmsg_multicast(&tcmu_genl_family, skb, 0,
+                               TCMU_MCGRP_CONFIG, GFP_KERNEL);
+
+       /* We don't care if no one is listening */
+       if (ret == -ESRCH)
+               ret = 0;
+
+       return ret;
+free_skb:
+       nlmsg_free(skb);
+       return ret;
+}
+
+static int tcmu_configure_device(struct se_device *dev)
+{
+       struct tcmu_dev *udev = TCMU_DEV(dev);
+       struct tcmu_hba *hba = udev->hba->hba_ptr;
+       struct uio_info *info;
+       struct tcmu_mailbox *mb;
+       size_t size;
+       size_t used;
+       int ret = 0;
+       char *str;
+
+       info = &udev->uio_info;
+
+       size = snprintf(NULL, 0, "tcm-user/%u/%s/%s", hba->host_id, udev->name,
+                       udev->dev_config);
+       size += 1; /* for \0 */
+       str = kmalloc(size, GFP_KERNEL);
+       if (!str)
+               return -ENOMEM;
+
+       used = snprintf(str, size, "tcm-user/%u/%s", hba->host_id, udev->name);
+
+       if (udev->dev_config[0])
+               snprintf(str + used, size - used, "/%s", udev->dev_config);
+
+       info->name = str;
+
+       udev->mb_addr = vzalloc(TCMU_RING_SIZE);
+       if (!udev->mb_addr) {
+               ret = -ENOMEM;
+               goto err_vzalloc;
+       }
+
+       /* mailbox fits in first part of CMDR space */
+       udev->cmdr_size = CMDR_SIZE - CMDR_OFF;
+       udev->data_off = CMDR_SIZE;
+       udev->data_size = TCMU_RING_SIZE - CMDR_SIZE;
+
+       mb = udev->mb_addr;
+       mb->version = 1;
+       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->mem[0].name = "tcm-user command & data buffer";
+       info->mem[0].addr = (phys_addr_t) udev->mb_addr;
+       info->mem[0].size = TCMU_RING_SIZE;
+       info->mem[0].memtype = UIO_MEM_VIRTUAL;
+
+       info->irqcontrol = tcmu_irqcontrol;
+       info->irq = UIO_IRQ_CUSTOM;
+
+       info->mmap = tcmu_mmap;
+       info->open = tcmu_open;
+       info->release = tcmu_release;
+
+       ret = uio_register_device(tcmu_root_device, info);
+       if (ret)
+               goto err_register;
+
+       /* Other attributes can be configured in userspace */
+       dev->dev_attrib.hw_block_size = 512;
+       dev->dev_attrib.hw_max_sectors = 128;
+       dev->dev_attrib.hw_queue_depth = 128;
+
+       ret = tcmu_netlink_event(TCMU_CMD_ADDED_DEVICE, udev->uio_info.name,
+                                udev->uio_info.uio_dev->minor);
+       if (ret)
+               goto err_netlink;
+
+       return 0;
+
+err_netlink:
+       uio_unregister_device(&udev->uio_info);
+err_register:
+       vfree(udev->mb_addr);
+err_vzalloc:
+       kfree(info->name);
+
+       return ret;
+}
+
+static int tcmu_check_pending_cmd(int id, void *p, void *data)
+{
+       struct tcmu_cmd *cmd = p;
+
+       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
+               return 0;
+       return -EINVAL;
+}
+
+static void tcmu_free_device(struct se_device *dev)
+{
+       struct tcmu_dev *udev = TCMU_DEV(dev);
+       int i;
+
+       del_timer_sync(&udev->timeout);
+
+       vfree(udev->mb_addr);
+
+       /* Upper layer should drain all requests before calling this */
+       spin_lock_irq(&udev->commands_lock);
+       i = idr_for_each(&udev->commands, tcmu_check_pending_cmd, NULL);
+       idr_destroy(&udev->commands);
+       spin_unlock_irq(&udev->commands_lock);
+       WARN_ON(i);
+
+       /* Device was configured */
+       if (udev->uio_info.uio_dev) {
+               tcmu_netlink_event(TCMU_CMD_REMOVED_DEVICE, udev->uio_info.name,
+                                  udev->uio_info.uio_dev->minor);
+
+               uio_unregister_device(&udev->uio_info);
+               kfree(udev->uio_info.name);
+               kfree(udev->name);
+       }
+
+       kfree(udev);
+}
+
+enum {
+       Opt_dev_config, Opt_dev_size, Opt_err, Opt_pass_level,
+};
+
+static match_table_t tokens = {
+       {Opt_dev_config, "dev_config=%s"},
+       {Opt_dev_size, "dev_size=%u"},
+       {Opt_pass_level, "pass_level=%u"},
+       {Opt_err, NULL}
+};
+
+static ssize_t tcmu_set_configfs_dev_params(struct se_device *dev,
+               const char *page, ssize_t count)
+{
+       struct tcmu_dev *udev = TCMU_DEV(dev);
+       char *orig, *ptr, *opts, *arg_p;
+       substring_t args[MAX_OPT_ARGS];
+       int ret = 0, token;
+       int arg;
+
+       opts = kstrdup(page, GFP_KERNEL);
+       if (!opts)
+               return -ENOMEM;
+
+       orig = opts;
+
+       while ((ptr = strsep(&opts, ",\n")) != NULL) {
+               if (!*ptr)
+                       continue;
+
+               token = match_token(ptr, tokens, args);
+               switch (token) {
+               case Opt_dev_config:
+                       if (match_strlcpy(udev->dev_config, &args[0],
+                                         TCMU_CONFIG_LEN) == 0) {
+                               ret = -EINVAL;
+                               break;
+                       }
+                       pr_debug("TCMU: Referencing Path: %s\n", udev->dev_config);
+                       break;
+               case Opt_dev_size:
+                       arg_p = match_strdup(&args[0]);
+                       if (!arg_p) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       ret = kstrtoul(arg_p, 0, (unsigned long *) &udev->dev_size);
+                       kfree(arg_p);
+                       if (ret < 0)
+                               pr_err("kstrtoul() failed for dev_size=\n");
+                       break;
+               case Opt_pass_level:
+                       match_int(args, &arg);
+                       if (arg >= TCMU_PASS_INVALID) {
+                               pr_warn("TCMU: Invalid pass_level: %d\n", arg);
+                               break;
+                       }
+
+                       pr_debug("TCMU: Setting pass_level to %d\n", arg);
+                       udev->pass_level = arg;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       kfree(orig);
+       return (!ret) ? count : ret;
+}
+
+static ssize_t tcmu_show_configfs_dev_params(struct se_device *dev, char *b)
+{
+       struct tcmu_dev *udev = TCMU_DEV(dev);
+       ssize_t bl = 0;
+
+       bl = sprintf(b + bl, "Config: %s ",
+                    udev->dev_config[0] ? udev->dev_config : "NULL");
+       bl += sprintf(b + bl, "Size: %zu PassLevel: %u\n",
+                     udev->dev_size, udev->pass_level);
+
+       return bl;
+}
+
+static sector_t tcmu_get_blocks(struct se_device *dev)
+{
+       struct tcmu_dev *udev = TCMU_DEV(dev);
+
+       return div_u64(udev->dev_size - dev->dev_attrib.block_size,
+                      dev->dev_attrib.block_size);
+}
+
+static sense_reason_t
+tcmu_execute_rw(struct se_cmd *se_cmd, struct scatterlist *sgl, u32 sgl_nents,
+               enum dma_data_direction data_direction)
+{
+       int ret;
+
+       ret = tcmu_queue_cmd(se_cmd);
+
+       if (ret != 0)
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       else
+               return TCM_NO_SENSE;
+}
+
+static sense_reason_t
+tcmu_pass_op(struct se_cmd *se_cmd)
+{
+       int ret = tcmu_queue_cmd(se_cmd);
+
+       if (ret != 0)
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       else
+               return TCM_NO_SENSE;
+}
+
+static struct sbc_ops tcmu_sbc_ops = {
+       .execute_rw = tcmu_execute_rw,
+       .execute_sync_cache     = tcmu_pass_op,
+       .execute_write_same     = tcmu_pass_op,
+       .execute_write_same_unmap = tcmu_pass_op,
+       .execute_unmap          = tcmu_pass_op,
+};
+
+static sense_reason_t
+tcmu_parse_cdb(struct se_cmd *cmd)
+{
+       unsigned char *cdb = cmd->t_task_cdb;
+       struct tcmu_dev *udev = TCMU_DEV(cmd->se_dev);
+       sense_reason_t ret;
+
+       switch (udev->pass_level) {
+       case TCMU_PASS_ALL:
+               /* We're just like pscsi, then */
+               /*
+                * For REPORT LUNS we always need to emulate the response, for everything
+                * else, pass it up.
+                */
+               switch (cdb[0]) {
+               case REPORT_LUNS:
+                       cmd->execute_cmd = spc_emulate_report_luns;
+                       break;
+               case READ_6:
+               case READ_10:
+               case READ_12:
+               case READ_16:
+               case WRITE_6:
+               case WRITE_10:
+               case WRITE_12:
+               case WRITE_16:
+               case WRITE_VERIFY:
+                       cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+                       /* FALLTHROUGH */
+               default:
+                       cmd->execute_cmd = tcmu_pass_op;
+               }
+               ret = TCM_NO_SENSE;
+               break;
+       case TCMU_PASS_IO:
+               ret = sbc_parse_cdb(cmd, &tcmu_sbc_ops);
+               break;
+       default:
+               pr_err("Unknown tcm-user pass level %d\n", udev->pass_level);
+               ret = TCM_CHECK_CONDITION_ABORT_CMD;
+       }
+
+       return ret;
+}
+
+static struct se_subsystem_api tcmu_template = {
+       .name                   = "user",
+       .inquiry_prod           = "USER",
+       .inquiry_rev            = TCMU_VERSION,
+       .owner                  = THIS_MODULE,
+       .transport_type         = TRANSPORT_PLUGIN_VHBA_PDEV,
+       .attach_hba             = tcmu_attach_hba,
+       .detach_hba             = tcmu_detach_hba,
+       .alloc_device           = tcmu_alloc_device,
+       .configure_device       = tcmu_configure_device,
+       .free_device            = tcmu_free_device,
+       .parse_cdb              = tcmu_parse_cdb,
+       .set_configfs_dev_params = tcmu_set_configfs_dev_params,
+       .show_configfs_dev_params = tcmu_show_configfs_dev_params,
+       .get_device_type        = sbc_get_device_type,
+       .get_blocks             = tcmu_get_blocks,
+};
+
+static int __init tcmu_module_init(void)
+{
+       int ret;
+
+       BUILD_BUG_ON((sizeof(struct tcmu_cmd_entry) % TCMU_OP_ALIGN_SIZE) != 0);
+
+       tcmu_cmd_cache = kmem_cache_create("tcmu_cmd_cache",
+                               sizeof(struct tcmu_cmd),
+                               __alignof__(struct tcmu_cmd),
+                               0, NULL);
+       if (!tcmu_cmd_cache)
+               return -ENOMEM;
+
+       tcmu_root_device = root_device_register("tcm_user");
+       if (IS_ERR(tcmu_root_device)) {
+               ret = PTR_ERR(tcmu_root_device);
+               goto out_free_cache;
+       }
+
+       ret = genl_register_family(&tcmu_genl_family);
+       if (ret < 0) {
+               goto out_unreg_device;
+       }
+
+       ret = transport_subsystem_register(&tcmu_template);
+       if (ret)
+               goto out_unreg_genl;
+
+       return 0;
+
+out_unreg_genl:
+       genl_unregister_family(&tcmu_genl_family);
+out_unreg_device:
+       root_device_unregister(tcmu_root_device);
+out_free_cache:
+       kmem_cache_destroy(tcmu_cmd_cache);
+
+       return ret;
+}
+
+static void __exit tcmu_module_exit(void)
+{
+       transport_subsystem_release(&tcmu_template);
+       genl_unregister_family(&tcmu_genl_family);
+       root_device_unregister(tcmu_root_device);
+       kmem_cache_destroy(tcmu_cmd_cache);
+}
+
+MODULE_DESCRIPTION("TCM USER subsystem plugin");
+MODULE_AUTHOR("Shaohua Li <shli@kernel.org>");
+MODULE_AUTHOR("Andy Grover <agrover@redhat.com>");
+MODULE_LICENSE("GPL");
+
+module_init(tcmu_module_init);
+module_exit(tcmu_module_exit);
index 21ce50880c79d1480166b08b52b4bb81cc85d4d6..ccee7e332a4d4900af26527d4e6d4141a679206d 100644 (file)
@@ -98,7 +98,7 @@ static void ft_tport_delete(struct ft_tport *tport)
        ft_sess_delete_all(tport);
        lport = tport->lport;
        BUG_ON(tport != lport->prov[FC_TYPE_FCP]);
-       rcu_assign_pointer(lport->prov[FC_TYPE_FCP], NULL);
+       RCU_INIT_POINTER(lport->prov[FC_TYPE_FCP], NULL);
 
        tpg = tport->tpg;
        if (tpg) {
index ef5587fe2c69d05fdf1934eb93a80788e4b87cf5..f554d25b439971f126b55c6ec3ed38271ab502aa 100644 (file)
@@ -84,6 +84,16 @@ config THERMAL_GOV_STEP_WISE
          Enable this to manage platform thermals using a simple linear
          governor.
 
+config THERMAL_GOV_BANG_BANG
+       bool "Bang Bang thermal governor"
+       default n
+       help
+         Enable this to manage platform thermals using bang bang governor.
+
+         Say 'Y' here if you want to use two point temperature regulation
+         used for fans without throttling.  Some fan drivers depend on this
+         governor to be enabled (e.g. acerhdf).
+
 config THERMAL_GOV_USER_SPACE
        bool "User_space thermal governor"
        help
@@ -207,21 +217,6 @@ config X86_PKG_TEMP_THERMAL
          two trip points which can be set by user to get notifications via thermal
          notification methods.
 
-config ACPI_INT3403_THERMAL
-       tristate "ACPI INT3403 thermal driver"
-       depends on X86 && ACPI
-       help
-         Newer laptops and tablets that use ACPI may have thermal sensors
-         outside the core CPU/SOC for thermal safety reasons. These
-         temperature sensors are also exposed for the OS to use via the so
-         called INT3403 ACPI object. This driver will, on devices that have
-         such sensors, expose the temperature information from these sensors
-         to userspace via the normal thermal framework. This means that a wide
-         range of applications and GUI widgets can show this information to
-         the user or use this information for making decisions. For example,
-         the Intel Thermal Daemon can use this information to allow the user
-         to select his laptop to run without turning on the fans.
-
 config INTEL_SOC_DTS_THERMAL
        tristate "Intel SoCs DTS thermal driver"
        depends on X86 && IOSF_MBI
@@ -234,6 +229,30 @@ config INTEL_SOC_DTS_THERMAL
          notification methods.The other trip is a critical trip point, which
          was set by the driver based on the TJ MAX temperature.
 
+config INT340X_THERMAL
+       tristate "ACPI INT340X thermal drivers"
+       depends on X86 && ACPI
+       select THERMAL_GOV_USER_SPACE
+       select ACPI_THERMAL_REL
+       select ACPI_FAN
+       help
+         Newer laptops and tablets that use ACPI may have thermal sensors and
+         other devices with thermal control capabilities outside the core
+         CPU/SOC, for thermal safety reasons.
+         They are exposed for the OS to use via the INT3400 ACPI device object
+         as the master, and INT3401~INT340B ACPI device objects as the slaves.
+         Enable this to expose the temperature information and cooling ability
+         from these objects to userspace via the normal thermal framework.
+         This means that a wide range of applications and GUI widgets can show
+         the information to the user or use this information for making
+         decisions. For example, the Intel Thermal Daemon can use this
+         information to allow the user to select his laptop to run without
+         turning on the fans.
+
+config ACPI_THERMAL_REL
+       tristate
+       depends on ACPI
+
 menu "Texas Instruments thermal drivers"
 source "drivers/thermal/ti-soc-thermal/Kconfig"
 endmenu
index 31e232f84b6ba80fa082d0cfd8ca33a8640a05a8..39c4fe87da2f838b63af97518826fdba863f36d0 100644 (file)
@@ -11,6 +11,7 @@ thermal_sys-$(CONFIG_THERMAL_OF)              += of-thermal.o
 
 # governors
 thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
+thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG)    += gov_bang_bang.o
 thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE)    += step_wise.o
 thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE)   += user_space.o
 
@@ -31,5 +32,5 @@ obj-$(CONFIG_INTEL_POWERCLAMP)        += intel_powerclamp.o
 obj-$(CONFIG_X86_PKG_TEMP_THERMAL)     += x86_pkg_temp_thermal.o
 obj-$(CONFIG_INTEL_SOC_DTS_THERMAL)    += intel_soc_dts_thermal.o
 obj-$(CONFIG_TI_SOC_THERMAL)   += ti-soc-thermal/
-obj-$(CONFIG_ACPI_INT3403_THERMAL)     += int3403_thermal.o
+obj-$(CONFIG_INT340X_THERMAL)  += int340x_thermal/
 obj-$(CONFIG_ST_THERMAL)       += st/
index 1ab0018271c5c622c0b7556fb92a3a1d9ad38e5b..ad09e51ffae4d097109241d9a19b97c97858109b 100644 (file)
@@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
        unsigned int cpufreq_state;
        unsigned int cpufreq_val;
        struct cpumask allowed_cpus;
+       struct list_head node;
 };
 static DEFINE_IDR(cpufreq_idr);
 static DEFINE_MUTEX(cooling_cpufreq_lock);
 
 static unsigned int cpufreq_dev_count;
 
-/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
-#define NOTIFY_INVALID NULL
-static struct cpufreq_cooling_device *notify_device;
+static LIST_HEAD(cpufreq_dev_list);
 
 /**
  * get_idr - function to get a unique id.
@@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
 
        cpufreq_device->cpufreq_state = cooling_state;
        cpufreq_device->cpufreq_val = clip_freq;
-       notify_device = cpufreq_device;
 
        for_each_cpu(cpuid, mask) {
                if (is_cpufreq_valid(cpuid))
                        cpufreq_update_policy(cpuid);
        }
 
-       notify_device = NOTIFY_INVALID;
-
        return 0;
 }
 
@@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
 {
        struct cpufreq_policy *policy = data;
        unsigned long max_freq = 0;
+       struct cpufreq_cooling_device *cpufreq_dev;
 
-       if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
+       if (event != CPUFREQ_ADJUST)
                return 0;
 
-       if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
-               max_freq = notify_device->cpufreq_val;
-       else
-               return 0;
+       mutex_lock(&cooling_cpufreq_lock);
+       list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
+               if (!cpumask_test_cpu(policy->cpu,
+                                       &cpufreq_dev->allowed_cpus))
+                       continue;
+
+               if (!cpufreq_dev->cpufreq_val)
+                       cpufreq_dev->cpufreq_val = get_cpu_frequency(
+                                       cpumask_any(&cpufreq_dev->allowed_cpus),
+                                       cpufreq_dev->cpufreq_state);
 
-       /* Never exceed user_policy.max */
-       if (max_freq > policy->user_policy.max)
-               max_freq = policy->user_policy.max;
+               max_freq = cpufreq_dev->cpufreq_val;
 
-       if (policy->max != max_freq)
-               cpufreq_verify_within_limits(policy, 0, max_freq);
+               if (policy->max != max_freq)
+                       cpufreq_verify_within_limits(policy, 0, max_freq);
+       }
+       mutex_unlock(&cooling_cpufreq_lock);
 
        return 0;
 }
@@ -486,6 +489,7 @@ __cpufreq_cooling_register(struct device_node *np,
                cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
                                          CPUFREQ_POLICY_NOTIFIER);
        cpufreq_dev_count++;
+       list_add(&cpufreq_dev->node, &cpufreq_dev_list);
 
        mutex_unlock(&cooling_cpufreq_lock);
 
@@ -549,6 +553,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
        cpufreq_dev = cdev->devdata;
        mutex_lock(&cooling_cpufreq_lock);
+       list_del(&cpufreq_dev->node);
        cpufreq_dev_count--;
 
        /* Unregister the notifier for the last cpufreq cooling device */
index 944ba2f340c83cfed436c569c949d58dc6a60dfe..6e0a3fbfae867f9ebab079a2d485677222a3e349 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/thermal.h>
+#include <trace/events/thermal.h>
 
 #include "thermal_core.h"
 
@@ -34,6 +35,7 @@ static int get_trip_level(struct thermal_zone_device *tz)
 {
        int count = 0;
        unsigned long trip_temp;
+       enum thermal_trip_type trip_type;
 
        if (tz->trips == 0 || !tz->ops->get_trip_temp)
                return 0;
@@ -43,6 +45,16 @@ static int get_trip_level(struct thermal_zone_device *tz)
                if (tz->temperature < trip_temp)
                        break;
        }
+
+       /*
+        * count > 0 only if temperature is greater than first trip
+        * point, in which case, trip_point = count - 1
+        */
+       if (count > 0) {
+               tz->ops->get_trip_type(tz, count - 1, &trip_type);
+               trace_thermal_zone_trip(tz, count - 1, trip_type);
+       }
+
        return count;
 }
 
diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
new file mode 100644 (file)
index 0000000..c5dd76b
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *  gov_bang_bang.c - A simple thermal throttling governor using hysteresis
+ *
+ *  Copyright (C) 2014 Peter Feuerer <peter@piie.net>
+ *
+ *  Based on step_wise.c with following Copyrights:
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/thermal.h>
+
+#include "thermal_core.h"
+
+static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+{
+       long trip_temp;
+       unsigned long trip_hyst;
+       struct thermal_instance *instance;
+
+       tz->ops->get_trip_temp(tz, trip, &trip_temp);
+       tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
+
+       dev_dbg(&tz->device, "Trip%d[temp=%ld]:temp=%d:hyst=%ld\n",
+                               trip, trip_temp, tz->temperature,
+                               trip_hyst);
+
+       mutex_lock(&tz->lock);
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if (instance->trip != trip)
+                       continue;
+
+               /* in case fan is in initial state, switch the fan off */
+               if (instance->target == THERMAL_NO_TARGET)
+                       instance->target = 0;
+
+               /* in case fan is neither on nor off set the fan to active */
+               if (instance->target != 0 && instance->target != 1) {
+                       pr_warn("Thermal instance %s controlled by bang-bang has unexpected state: %ld\n",
+                                       instance->name, instance->target);
+                       instance->target = 1;
+               }
+
+               /*
+                * enable fan when temperature exceeds trip_temp and disable
+                * the fan in case it falls below trip_temp minus hysteresis
+                */
+               if (instance->target == 0 && tz->temperature >= trip_temp)
+                       instance->target = 1;
+               else if (instance->target == 1 &&
+                               tz->temperature < trip_temp - trip_hyst)
+                       instance->target = 0;
+
+               dev_dbg(&instance->cdev->device, "target=%d\n",
+                                       (int)instance->target);
+
+               instance->cdev->updated = false; /* cdev needs update */
+       }
+
+       mutex_unlock(&tz->lock);
+}
+
+/**
+ * bang_bang_control - controls devices associated with the given zone
+ * @tz - thermal_zone_device
+ * @trip - the trip point
+ *
+ * Regulation Logic: a two point regulation, deliver cooling state depending
+ * on the previous state shown in this diagram:
+ *
+ *                Fan:   OFF    ON
+ *
+ *                              |
+ *                              |
+ *          trip_temp:    +---->+
+ *                        |     |        ^
+ *                        |     |        |
+ *                        |     |   Temperature
+ * (trip_temp - hyst):    +<----+
+ *                        |
+ *                        |
+ *                        |
+ *
+ *   * If the fan is not running and temperature exceeds trip_temp, the fan
+ *     gets turned on.
+ *   * In case the fan is running, temperature must fall below
+ *     (trip_temp - hyst) so that the fan gets turned off again.
+ *
+ */
+static int bang_bang_control(struct thermal_zone_device *tz, int trip)
+{
+       struct thermal_instance *instance;
+
+       thermal_zone_trip_update(tz, trip);
+
+       mutex_lock(&tz->lock);
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node)
+               thermal_cdev_update(instance->cdev);
+
+       mutex_unlock(&tz->lock);
+
+       return 0;
+}
+
+static struct thermal_governor thermal_gov_bang_bang = {
+       .name           = "bang_bang",
+       .throttle       = bang_bang_control,
+};
+
+int thermal_gov_bang_bang_register(void)
+{
+       return thermal_register_governor(&thermal_gov_bang_bang);
+}
+
+void thermal_gov_bang_bang_unregister(void)
+{
+       thermal_unregister_governor(&thermal_gov_bang_bang);
+}
index 2c516f2eebed7e63537760c6eb12980207198cc3..5a1f1070b702282bb1f4ded1535dbfd3abdb6963 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
 #define MISC0                          0x0150
 #define MISC0_REFTOP_SELBIASOFF                (1 << 3)
+#define MISC1                          0x0160
+#define MISC1_IRQ_TEMPHIGH             (1 << 29)
+/* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
+#define MISC1_IRQ_TEMPLOW              (1 << 28)
+#define MISC1_IRQ_TEMPPANIC            (1 << 27)
 
 #define TEMPSENSE0                     0x0180
 #define TEMPSENSE0_ALARM_VALUE_SHIFT   20
 
 #define TEMPSENSE1                     0x0190
 #define TEMPSENSE1_MEASURE_FREQ                0xffff
+/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
+#define TEMPSENSE2                     0x0290
+#define TEMPSENSE2_LOW_VALUE_SHIFT     0
+#define TEMPSENSE2_LOW_VALUE_MASK      0xfff
+#define TEMPSENSE2_PANIC_VALUE_SHIFT   16
+#define TEMPSENSE2_PANIC_VALUE_MASK    0xfff0000
 
 #define OCOTP_ANA1                     0x04e0
 
@@ -66,6 +78,21 @@ enum imx_thermal_trip {
 #define FACTOR1                                15976
 #define FACTOR2                                4297157
 
+#define TEMPMON_IMX6Q                  1
+#define TEMPMON_IMX6SX                 2
+
+struct thermal_soc_data {
+       u32 version;
+};
+
+static struct thermal_soc_data thermal_imx6q_data = {
+       .version = TEMPMON_IMX6Q,
+};
+
+static struct thermal_soc_data thermal_imx6sx_data = {
+       .version = TEMPMON_IMX6SX,
+};
+
 struct imx_thermal_data {
        struct thermal_zone_device *tz;
        struct thermal_cooling_device *cdev;
@@ -79,8 +106,21 @@ struct imx_thermal_data {
        bool irq_enabled;
        int irq;
        struct clk *thermal_clk;
+       const struct thermal_soc_data *socdata;
 };
 
+static void imx_set_panic_temp(struct imx_thermal_data *data,
+                              signed long panic_temp)
+{
+       struct regmap *map = data->tempmon;
+       int critical_value;
+
+       critical_value = (data->c2 - panic_temp) / data->c1;
+       regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK);
+       regmap_write(map, TEMPSENSE2 + REG_SET, critical_value <<
+                       TEMPSENSE2_PANIC_VALUE_SHIFT);
+}
+
 static void imx_set_alarm_temp(struct imx_thermal_data *data,
                               signed long alarm_temp)
 {
@@ -142,13 +182,17 @@ static int imx_get_temp(struct thermal_zone_device *tz, unsigned long *temp)
        /* See imx_get_sensor_data() for formula derivation */
        *temp = data->c2 - n_meas * data->c1;
 
-       /* Update alarm value to next higher trip point */
-       if (data->alarm_temp == data->temp_passive && *temp >= data->temp_passive)
-               imx_set_alarm_temp(data, data->temp_critical);
-       if (data->alarm_temp == data->temp_critical && *temp < data->temp_passive) {
-               imx_set_alarm_temp(data, data->temp_passive);
-               dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
-                       data->alarm_temp / 1000);
+       /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
+       if (data->socdata->version == TEMPMON_IMX6Q) {
+               if (data->alarm_temp == data->temp_passive &&
+                       *temp >= data->temp_passive)
+                       imx_set_alarm_temp(data, data->temp_critical);
+               if (data->alarm_temp == data->temp_critical &&
+                       *temp < data->temp_passive) {
+                       imx_set_alarm_temp(data, data->temp_passive);
+                       dev_dbg(&tz->device, "thermal alarm off: T < %lu\n",
+                               data->alarm_temp / 1000);
+               }
        }
 
        if (*temp != data->last_temp) {
@@ -398,14 +442,27 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
+static const struct of_device_id of_imx_thermal_match[] = {
+       { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
+       { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
+       { /* end */ }
+};
+MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
+
 static int imx_thermal_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id =
+               of_match_device(of_imx_thermal_match, &pdev->dev);
        struct imx_thermal_data *data;
        struct cpumask clip_cpus;
        struct regmap *map;
        int measure_freq;
        int ret;
 
+       if (!cpufreq_get_current_driver()) {
+               dev_dbg(&pdev->dev, "no cpufreq driver!");
+               return -EPROBE_DEFER;
+       }
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -418,6 +475,20 @@ static int imx_thermal_probe(struct platform_device *pdev)
        }
        data->tempmon = map;
 
+       data->socdata = of_id->data;
+
+       /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
+       if (data->socdata->version == TEMPMON_IMX6SX) {
+               regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH |
+                       MISC1_IRQ_TEMPLOW | MISC1_IRQ_TEMPPANIC);
+               /*
+                * reset value of LOW ALARM is incorrect, set it to lowest
+                * value to avoid false trigger of low alarm.
+                */
+               regmap_write(map, TEMPSENSE2 + REG_SET,
+                       TEMPSENSE2_LOW_VALUE_MASK);
+       }
+
        data->irq = platform_get_irq(pdev, 0);
        if (data->irq < 0)
                return data->irq;
@@ -454,6 +525,30 @@ static int imx_thermal_probe(struct platform_device *pdev)
                return ret;
        }
 
+       data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(data->thermal_clk)) {
+               ret = PTR_ERR(data->thermal_clk);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&pdev->dev,
+                               "failed to get thermal clk: %d\n", ret);
+               cpufreq_cooling_unregister(data->cdev);
+               return ret;
+       }
+
+       /*
+        * Thermal sensor needs clk on to get correct value, normally
+        * we should enable its clk before taking measurement and disable
+        * clk after measurement is done, but if alarm function is enabled,
+        * hardware will auto measure the temperature periodically, so we
+        * need to keep the clk always on for alarm function.
+        */
+       ret = clk_prepare_enable(data->thermal_clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
+               cpufreq_cooling_unregister(data->cdev);
+               return ret;
+       }
+
        data->tz = thermal_zone_device_register("imx_thermal_zone",
                                                IMX_TRIP_NUM,
                                                BIT(IMX_TRIP_PASSIVE), data,
@@ -464,31 +559,20 @@ static int imx_thermal_probe(struct platform_device *pdev)
                ret = PTR_ERR(data->tz);
                dev_err(&pdev->dev,
                        "failed to register thermal zone device %d\n", ret);
+               clk_disable_unprepare(data->thermal_clk);
                cpufreq_cooling_unregister(data->cdev);
                return ret;
        }
 
-       data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(data->thermal_clk)) {
-               dev_warn(&pdev->dev, "failed to get thermal clk!\n");
-       } else {
-               /*
-                * Thermal sensor needs clk on to get correct value, normally
-                * we should enable its clk before taking measurement and disable
-                * clk after measurement is done, but if alarm function is enabled,
-                * hardware will auto measure the temperature periodically, so we
-                * need to keep the clk always on for alarm function.
-                */
-               ret = clk_prepare_enable(data->thermal_clk);
-               if (ret)
-                       dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
-       }
-
        /* Enable measurements at ~ 10 Hz */
        regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
        measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
        regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
        imx_set_alarm_temp(data, data->temp_passive);
+
+       if (data->socdata->version == TEMPMON_IMX6SX)
+               imx_set_panic_temp(data, data->temp_critical);
+
        regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
 
@@ -550,12 +634,6 @@ static int imx_thermal_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
                         imx_thermal_suspend, imx_thermal_resume);
 
-static const struct of_device_id of_imx_thermal_match[] = {
-       { .compatible = "fsl,imx6q-tempmon", },
-       { /* end */ }
-};
-MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
-
 static struct platform_driver imx_thermal = {
        .driver = {
                .name   = "imx_thermal",
diff --git a/drivers/thermal/int3403_thermal.c b/drivers/thermal/int3403_thermal.c
deleted file mode 100644 (file)
index 17554ee..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * ACPI INT3403 thermal driver
- * Copyright (c) 2013, 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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/acpi.h>
-#include <linux/thermal.h>
-
-#define INT3403_TYPE_SENSOR            0x03
-#define INT3403_PERF_CHANGED_EVENT     0x80
-#define INT3403_THERMAL_EVENT          0x90
-
-#define DECI_KELVIN_TO_MILLI_CELSIUS(t, off) (((t) - (off)) * 100)
-#define KELVIN_OFFSET  2732
-#define MILLI_CELSIUS_TO_DECI_KELVIN(t, off) (((t) / 100) + (off))
-
-#define ACPI_INT3403_CLASS             "int3403"
-#define ACPI_INT3403_FILE_STATE                "state"
-
-struct int3403_sensor {
-       struct thermal_zone_device *tzone;
-       unsigned long *thresholds;
-       unsigned long   crit_temp;
-       int             crit_trip_id;
-       unsigned long   psv_temp;
-       int             psv_trip_id;
-};
-
-static int sys_get_curr_temp(struct thermal_zone_device *tzone,
-                               unsigned long *temp)
-{
-       struct acpi_device *device = tzone->devdata;
-       unsigned long long tmp;
-       acpi_status status;
-
-       status = acpi_evaluate_integer(device->handle, "_TMP", NULL, &tmp);
-       if (ACPI_FAILURE(status))
-               return -EIO;
-
-       *temp = DECI_KELVIN_TO_MILLI_CELSIUS(tmp, KELVIN_OFFSET);
-
-       return 0;
-}
-
-static int sys_get_trip_hyst(struct thermal_zone_device *tzone,
-               int trip, unsigned long *temp)
-{
-       struct acpi_device *device = tzone->devdata;
-       unsigned long long hyst;
-       acpi_status status;
-
-       status = acpi_evaluate_integer(device->handle, "GTSH", NULL, &hyst);
-       if (ACPI_FAILURE(status))
-               return -EIO;
-
-       /*
-        * Thermal hysteresis represents a temperature difference.
-        * Kelvin and Celsius have same degree size. So the
-        * conversion here between tenths of degree Kelvin unit
-        * and Milli-Celsius unit is just to multiply 100.
-        */
-       *temp = hyst * 100;
-
-       return 0;
-}
-
-static int sys_get_trip_temp(struct thermal_zone_device *tzone,
-               int trip, unsigned long *temp)
-{
-       struct acpi_device *device = tzone->devdata;
-       struct int3403_sensor *obj = acpi_driver_data(device);
-
-       if (trip == obj->crit_trip_id)
-               *temp = obj->crit_temp;
-       else if (trip == obj->psv_trip_id)
-               *temp = obj->psv_temp;
-       else {
-               /*
-                * get_trip_temp is a mandatory callback but
-                * PATx method doesn't return any value, so return
-                * cached value, which was last set from user space.
-                */
-               *temp = obj->thresholds[trip];
-       }
-
-       return 0;
-}
-
-static int sys_get_trip_type(struct thermal_zone_device *thermal,
-               int trip, enum thermal_trip_type *type)
-{
-       struct acpi_device *device = thermal->devdata;
-       struct int3403_sensor *obj = acpi_driver_data(device);
-
-       /* Mandatory callback, may not mean much here */
-       if (trip == obj->crit_trip_id)
-               *type = THERMAL_TRIP_CRITICAL;
-       else
-               *type = THERMAL_TRIP_PASSIVE;
-
-       return 0;
-}
-
-int sys_set_trip_temp(struct thermal_zone_device *tzone, int trip,
-                                                       unsigned long temp)
-{
-       struct acpi_device *device = tzone->devdata;
-       acpi_status status;
-       char name[10];
-       int ret = 0;
-       struct int3403_sensor *obj = acpi_driver_data(device);
-
-       snprintf(name, sizeof(name), "PAT%d", trip);
-       if (acpi_has_method(device->handle, name)) {
-               status = acpi_execute_simple_method(device->handle, name,
-                               MILLI_CELSIUS_TO_DECI_KELVIN(temp,
-                                                       KELVIN_OFFSET));
-               if (ACPI_FAILURE(status))
-                       ret = -EIO;
-               else
-                       obj->thresholds[trip] = temp;
-       } else {
-               ret = -EIO;
-               dev_err(&device->dev, "sys_set_trip_temp: method not found\n");
-       }
-
-       return ret;
-}
-
-static struct thermal_zone_device_ops tzone_ops = {
-       .get_temp = sys_get_curr_temp,
-       .get_trip_temp = sys_get_trip_temp,
-       .get_trip_type = sys_get_trip_type,
-       .set_trip_temp = sys_set_trip_temp,
-       .get_trip_hyst =  sys_get_trip_hyst,
-};
-
-static void acpi_thermal_notify(struct acpi_device *device, u32 event)
-{
-       struct int3403_sensor *obj;
-
-       if (!device)
-               return;
-
-       obj = acpi_driver_data(device);
-       if (!obj)
-               return;
-
-       switch (event) {
-       case INT3403_PERF_CHANGED_EVENT:
-               break;
-       case INT3403_THERMAL_EVENT:
-               thermal_zone_device_update(obj->tzone);
-               break;
-       default:
-               dev_err(&device->dev, "Unsupported event [0x%x]\n", event);
-               break;
-       }
-}
-
-static int sys_get_trip_crt(struct acpi_device *device, unsigned long *temp)
-{
-       unsigned long long crt;
-       acpi_status status;
-
-       status = acpi_evaluate_integer(device->handle, "_CRT", NULL, &crt);
-       if (ACPI_FAILURE(status))
-               return -EIO;
-
-       *temp = DECI_KELVIN_TO_MILLI_CELSIUS(crt, KELVIN_OFFSET);
-
-       return 0;
-}
-
-static int sys_get_trip_psv(struct acpi_device *device, unsigned long *temp)
-{
-       unsigned long long psv;
-       acpi_status status;
-
-       status = acpi_evaluate_integer(device->handle, "_PSV", NULL, &psv);
-       if (ACPI_FAILURE(status))
-               return -EIO;
-
-       *temp = DECI_KELVIN_TO_MILLI_CELSIUS(psv, KELVIN_OFFSET);
-
-       return 0;
-}
-
-static int acpi_int3403_add(struct acpi_device *device)
-{
-       int result = 0;
-       unsigned long long ptyp;
-       acpi_status status;
-       struct int3403_sensor *obj;
-       unsigned long long trip_cnt;
-       int trip_mask = 0;
-
-       if (!device)
-               return -EINVAL;
-
-       status = acpi_evaluate_integer(device->handle, "PTYP", NULL, &ptyp);
-       if (ACPI_FAILURE(status))
-               return -EINVAL;
-
-       if (ptyp != INT3403_TYPE_SENSOR)
-               return -EINVAL;
-
-       obj = devm_kzalloc(&device->dev, sizeof(*obj), GFP_KERNEL);
-       if (!obj)
-               return -ENOMEM;
-
-       device->driver_data = obj;
-
-       status = acpi_evaluate_integer(device->handle, "PATC", NULL,
-                                               &trip_cnt);
-       if (ACPI_FAILURE(status))
-               trip_cnt = 0;
-
-       if (trip_cnt) {
-               /* We have to cache, thresholds can't be readback */
-               obj->thresholds = devm_kzalloc(&device->dev,
-                                       sizeof(*obj->thresholds) * trip_cnt,
-                                       GFP_KERNEL);
-               if (!obj->thresholds)
-                       return -ENOMEM;
-               trip_mask = BIT(trip_cnt) - 1;
-       }
-
-       obj->psv_trip_id = -1;
-       if (!sys_get_trip_psv(device, &obj->psv_temp))
-               obj->psv_trip_id = trip_cnt++;
-
-       obj->crit_trip_id = -1;
-       if (!sys_get_trip_crt(device, &obj->crit_temp))
-               obj->crit_trip_id = trip_cnt++;
-
-       obj->tzone = thermal_zone_device_register(acpi_device_bid(device),
-                               trip_cnt, trip_mask, device, &tzone_ops,
-                               NULL, 0, 0);
-       if (IS_ERR(obj->tzone)) {
-               result = PTR_ERR(obj->tzone);
-               return result;
-       }
-
-       strcpy(acpi_device_name(device), "INT3403");
-       strcpy(acpi_device_class(device), ACPI_INT3403_CLASS);
-
-       return 0;
-}
-
-static int acpi_int3403_remove(struct acpi_device *device)
-{
-       struct int3403_sensor *obj;
-
-       obj = acpi_driver_data(device);
-       thermal_zone_device_unregister(obj->tzone);
-
-       return 0;
-}
-
-ACPI_MODULE_NAME("int3403");
-static const struct acpi_device_id int3403_device_ids[] = {
-       {"INT3403", 0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, int3403_device_ids);
-
-static struct acpi_driver acpi_int3403_driver = {
-       .name = "INT3403",
-       .class = ACPI_INT3403_CLASS,
-       .ids = int3403_device_ids,
-       .ops = {
-               .add = acpi_int3403_add,
-               .remove = acpi_int3403_remove,
-               .notify = acpi_thermal_notify,
-               },
-};
-
-module_acpi_driver(acpi_int3403_driver);
-
-MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("ACPI INT3403 thermal driver");
diff --git a/drivers/thermal/int340x_thermal/Makefile b/drivers/thermal/int340x_thermal/Makefile
new file mode 100644 (file)
index 0000000..ffe40bf
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_INT340X_THERMAL)  += int3400_thermal.o
+obj-$(CONFIG_INT340X_THERMAL)  += int3402_thermal.o
+obj-$(CONFIG_INT340X_THERMAL)  += int3403_thermal.o
+obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o
diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
new file mode 100644 (file)
index 0000000..0d8db80
--- /dev/null
@@ -0,0 +1,400 @@
+/* acpi_thermal_rel.c driver for exporting ACPI thermal relationship
+ *
+ * Copyright (c) 2014 Intel Corp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ */
+
+/*
+ * Two functionalities included:
+ * 1. Export _TRT, _ART, via misc device interface to the userspace.
+ * 2. Provide parsing result to kernel drivers
+ *
+ */
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include "acpi_thermal_rel.h"
+
+static acpi_handle acpi_thermal_rel_handle;
+static DEFINE_SPINLOCK(acpi_thermal_rel_chrdev_lock);
+static int acpi_thermal_rel_chrdev_count;      /* #times opened */
+static int acpi_thermal_rel_chrdev_exclu;      /* already open exclusive? */
+
+static int acpi_thermal_rel_open(struct inode *inode, struct file *file)
+{
+       spin_lock(&acpi_thermal_rel_chrdev_lock);
+       if (acpi_thermal_rel_chrdev_exclu ||
+           (acpi_thermal_rel_chrdev_count && (file->f_flags & O_EXCL))) {
+               spin_unlock(&acpi_thermal_rel_chrdev_lock);
+               return -EBUSY;
+       }
+
+       if (file->f_flags & O_EXCL)
+               acpi_thermal_rel_chrdev_exclu = 1;
+       acpi_thermal_rel_chrdev_count++;
+
+       spin_unlock(&acpi_thermal_rel_chrdev_lock);
+
+       return nonseekable_open(inode, file);
+}
+
+static int acpi_thermal_rel_release(struct inode *inode, struct file *file)
+{
+       spin_lock(&acpi_thermal_rel_chrdev_lock);
+       acpi_thermal_rel_chrdev_count--;
+       acpi_thermal_rel_chrdev_exclu = 0;
+       spin_unlock(&acpi_thermal_rel_chrdev_lock);
+
+       return 0;
+}
+
+/**
+ * acpi_parse_trt - Thermal Relationship Table _TRT for passive cooling
+ *
+ * @handle: ACPI handle of the device contains _TRT
+ * @art_count: the number of valid entries resulted from parsing _TRT
+ * @artp: pointer to pointer of array of art entries in parsing result
+ * @create_dev: whether to create platform devices for target and source
+ *
+ */
+int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trtp,
+               bool create_dev)
+{
+       acpi_status status;
+       int result = 0;
+       int i;
+       int nr_bad_entries = 0;
+       struct trt *trts;
+       struct acpi_device *adev;
+       union acpi_object *p;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_buffer element = { 0, NULL };
+       struct acpi_buffer trt_format = { sizeof("RRNNNNNN"), "RRNNNNNN" };
+
+       if (!acpi_has_method(handle, "_TRT"))
+               return 0;
+
+       status = acpi_evaluate_object(handle, "_TRT", NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       p = buffer.pointer;
+       if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
+               pr_err("Invalid _TRT data\n");
+               result = -EFAULT;
+               goto end;
+       }
+
+       *trt_count = p->package.count;
+       trts = kzalloc(*trt_count * sizeof(struct trt), GFP_KERNEL);
+       if (!trts) {
+               result = -ENOMEM;
+               goto end;
+       }
+
+       for (i = 0; i < *trt_count; i++) {
+               struct trt *trt = &trts[i - nr_bad_entries];
+
+               element.length = sizeof(struct trt);
+               element.pointer = trt;
+
+               status = acpi_extract_package(&(p->package.elements[i]),
+                                             &trt_format, &element);
+               if (ACPI_FAILURE(status)) {
+                       nr_bad_entries++;
+                       pr_warn("_TRT package %d is invalid, ignored\n", i);
+                       continue;
+               }
+               if (!create_dev)
+                       continue;
+
+               result = acpi_bus_get_device(trt->source, &adev);
+               if (!result)
+                       acpi_create_platform_device(adev);
+               else
+                       pr_warn("Failed to get source ACPI device\n");
+
+               result = acpi_bus_get_device(trt->target, &adev);
+               if (!result)
+                       acpi_create_platform_device(adev);
+               else
+                       pr_warn("Failed to get target ACPI device\n");
+       }
+
+       *trtp = trts;
+       /* don't count bad entries */
+       *trt_count -= nr_bad_entries;
+end:
+       kfree(buffer.pointer);
+       return result;
+}
+EXPORT_SYMBOL(acpi_parse_trt);
+
+/**
+ * acpi_parse_art - Parse Active Relationship Table _ART
+ *
+ * @handle: ACPI handle of the device contains _ART
+ * @art_count: the number of valid entries resulted from parsing _ART
+ * @artp: pointer to pointer of array of art entries in parsing result
+ * @create_dev: whether to create platform devices for target and source
+ *
+ */
+int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp,
+               bool create_dev)
+{
+       acpi_status status;
+       int result = 0;
+       int i;
+       int nr_bad_entries = 0;
+       struct art *arts;
+       struct acpi_device *adev;
+       union acpi_object *p;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_buffer element = { 0, NULL };
+       struct acpi_buffer art_format = {
+               sizeof("RRNNNNNNNNNNN"), "RRNNNNNNNNNNN" };
+
+       if (!acpi_has_method(handle, "_ART"))
+               return 0;
+
+       status = acpi_evaluate_object(handle, "_ART", NULL, &buffer);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       p = buffer.pointer;
+       if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
+               pr_err("Invalid _ART data\n");
+               result = -EFAULT;
+               goto end;
+       }
+
+       /* ignore p->package.elements[0], as this is _ART Revision field */
+       *art_count = p->package.count - 1;
+       arts = kzalloc(*art_count * sizeof(struct art), GFP_KERNEL);
+       if (!arts) {
+               result = -ENOMEM;
+               goto end;
+       }
+
+       for (i = 0; i < *art_count; i++) {
+               struct art *art = &arts[i - nr_bad_entries];
+
+               element.length = sizeof(struct art);
+               element.pointer = art;
+
+               status = acpi_extract_package(&(p->package.elements[i + 1]),
+                                             &art_format, &element);
+               if (ACPI_FAILURE(status)) {
+                       pr_warn("_ART package %d is invalid, ignored", i);
+                       nr_bad_entries++;
+                       continue;
+               }
+               if (!create_dev)
+                       continue;
+
+               if (art->source) {
+                       result = acpi_bus_get_device(art->source, &adev);
+                       if (!result)
+                               acpi_create_platform_device(adev);
+                       else
+                               pr_warn("Failed to get source ACPI device\n");
+               }
+               if (art->target) {
+                       result = acpi_bus_get_device(art->target, &adev);
+                       if (!result)
+                               acpi_create_platform_device(adev);
+                       else
+                               pr_warn("Failed to get source ACPI device\n");
+               }
+       }
+
+       *artp = arts;
+       /* don't count bad entries */
+       *art_count -= nr_bad_entries;
+end:
+       kfree(buffer.pointer);
+       return result;
+}
+EXPORT_SYMBOL(acpi_parse_art);
+
+
+/* get device name from acpi handle */
+static void get_single_name(acpi_handle handle, char *name)
+{
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};
+
+       if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)))
+               pr_warn("Failed get name from handle\n");
+       else {
+               memcpy(name, buffer.pointer, ACPI_NAME_SIZE);
+               kfree(buffer.pointer);
+       }
+}
+
+static int fill_art(char __user *ubuf)
+{
+       int i;
+       int ret;
+       int count;
+       int art_len;
+       struct art *arts = NULL;
+       union art_object *art_user;
+
+       ret = acpi_parse_art(acpi_thermal_rel_handle, &count, &arts, false);
+       if (ret)
+               goto free_art;
+       art_len = count * sizeof(union art_object);
+       art_user = kzalloc(art_len, GFP_KERNEL);
+       if (!art_user) {
+               ret = -ENOMEM;
+               goto free_art;
+       }
+       /* now fill in user art data */
+       for (i = 0; i < count; i++) {
+               /* userspace art needs device name instead of acpi reference */
+               get_single_name(arts[i].source, art_user[i].source_device);
+               get_single_name(arts[i].target, art_user[i].target_device);
+               /* copy the rest int data in addition to source and target */
+               memcpy(&art_user[i].weight, &arts[i].weight,
+                       sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2));
+       }
+
+       if (copy_to_user(ubuf, art_user, art_len))
+               ret = -EFAULT;
+       kfree(art_user);
+free_art:
+       kfree(arts);
+       return ret;
+}
+
+static int fill_trt(char __user *ubuf)
+{
+       int i;
+       int ret;
+       int count;
+       int trt_len;
+       struct trt *trts = NULL;
+       union trt_object *trt_user;
+
+       ret = acpi_parse_trt(acpi_thermal_rel_handle, &count, &trts, false);
+       if (ret)
+               goto free_trt;
+       trt_len = count * sizeof(union trt_object);
+       trt_user = kzalloc(trt_len, GFP_KERNEL);
+       if (!trt_user) {
+               ret = -ENOMEM;
+               goto free_trt;
+       }
+       /* now fill in user trt data */
+       for (i = 0; i < count; i++) {
+               /* userspace trt needs device name instead of acpi reference */
+               get_single_name(trts[i].source, trt_user[i].source_device);
+               get_single_name(trts[i].target, trt_user[i].target_device);
+               trt_user[i].sample_period = trts[i].sample_period;
+               trt_user[i].influence = trts[i].influence;
+       }
+
+       if (copy_to_user(ubuf, trt_user, trt_len))
+               ret = -EFAULT;
+       kfree(trt_user);
+free_trt:
+       kfree(trts);
+       return ret;
+}
+
+static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
+                                  unsigned long __arg)
+{
+       int ret = 0;
+       unsigned long length = 0;
+       unsigned long count = 0;
+       char __user *arg = (void __user *)__arg;
+       struct trt *trts;
+       struct art *arts;
+
+       switch (cmd) {
+       case ACPI_THERMAL_GET_TRT_COUNT:
+               ret = acpi_parse_trt(acpi_thermal_rel_handle, (int *)&count,
+                               &trts, false);
+               kfree(trts);
+               if (!ret)
+                       return put_user(count, (unsigned long __user *)__arg);
+               return ret;
+       case ACPI_THERMAL_GET_TRT_LEN:
+               ret = acpi_parse_trt(acpi_thermal_rel_handle, (int *)&count,
+                               &trts, false);
+               kfree(trts);
+               length = count * sizeof(union trt_object);
+               if (!ret)
+                       return put_user(length, (unsigned long __user *)__arg);
+               return ret;
+       case ACPI_THERMAL_GET_TRT:
+               return fill_trt(arg);
+       case ACPI_THERMAL_GET_ART_COUNT:
+               ret = acpi_parse_art(acpi_thermal_rel_handle, (int *)&count,
+                               &arts, false);
+               kfree(arts);
+               if (!ret)
+                       return put_user(count, (unsigned long __user *)__arg);
+               return ret;
+       case ACPI_THERMAL_GET_ART_LEN:
+               ret = acpi_parse_art(acpi_thermal_rel_handle, (int *)&count,
+                               &arts, false);
+               kfree(arts);
+               length = count * sizeof(union art_object);
+               if (!ret)
+                       return put_user(length, (unsigned long __user *)__arg);
+               return ret;
+
+       case ACPI_THERMAL_GET_ART:
+               return fill_art(arg);
+
+       default:
+               return -ENOTTY;
+       }
+}
+
+static const struct file_operations acpi_thermal_rel_fops = {
+       .owner          = THIS_MODULE,
+       .open           = acpi_thermal_rel_open,
+       .release        = acpi_thermal_rel_release,
+       .unlocked_ioctl = acpi_thermal_rel_ioctl,
+       .llseek         = no_llseek,
+};
+
+static struct miscdevice acpi_thermal_rel_misc_device = {
+       .minor  = MISC_DYNAMIC_MINOR,
+       "acpi_thermal_rel",
+       &acpi_thermal_rel_fops
+};
+
+int acpi_thermal_rel_misc_device_add(acpi_handle handle)
+{
+       acpi_thermal_rel_handle = handle;
+
+       return misc_register(&acpi_thermal_rel_misc_device);
+}
+EXPORT_SYMBOL(acpi_thermal_rel_misc_device_add);
+
+int acpi_thermal_rel_misc_device_remove(acpi_handle handle)
+{
+       misc_deregister(&acpi_thermal_rel_misc_device);
+
+       return 0;
+}
+EXPORT_SYMBOL(acpi_thermal_rel_misc_device_remove);
+
+MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
+MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com");
+MODULE_DESCRIPTION("Intel acpi thermal rel misc dev driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.h b/drivers/thermal/int340x_thermal/acpi_thermal_rel.h
new file mode 100644 (file)
index 0000000..f00700b
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef __ACPI_ACPI_THERMAL_H
+#define __ACPI_ACPI_THERMAL_H
+
+#include <asm/ioctl.h>
+
+#define ACPI_THERMAL_MAGIC 's'
+
+#define ACPI_THERMAL_GET_TRT_LEN _IOR(ACPI_THERMAL_MAGIC, 1, unsigned long)
+#define ACPI_THERMAL_GET_ART_LEN _IOR(ACPI_THERMAL_MAGIC, 2, unsigned long)
+#define ACPI_THERMAL_GET_TRT_COUNT _IOR(ACPI_THERMAL_MAGIC, 3, unsigned long)
+#define ACPI_THERMAL_GET_ART_COUNT _IOR(ACPI_THERMAL_MAGIC, 4, unsigned long)
+
+#define ACPI_THERMAL_GET_TRT   _IOR(ACPI_THERMAL_MAGIC, 5, unsigned long)
+#define ACPI_THERMAL_GET_ART   _IOR(ACPI_THERMAL_MAGIC, 6, unsigned long)
+
+struct art {
+       acpi_handle source;
+       acpi_handle target;
+       u64 weight;
+       u64 ac0_max;
+       u64 ac1_max;
+       u64 ac2_max;
+       u64 ac3_max;
+       u64 ac4_max;
+       u64 ac5_max;
+       u64 ac6_max;
+       u64 ac7_max;
+       u64 ac8_max;
+       u64 ac9_max;
+} __packed;
+
+struct trt {
+       acpi_handle source;
+       acpi_handle target;
+       u64 influence;
+       u64 sample_period;
+       u64 reverved1;
+       u64 reverved2;
+       u64 reverved3;
+       u64 reverved4;
+} __packed;
+
+#define ACPI_NR_ART_ELEMENTS 13
+/* for usrspace */
+union art_object {
+       struct {
+               char source_device[8]; /* ACPI single name */
+               char target_device[8]; /* ACPI single name */
+               u64 weight;
+               u64 ac0_max_level;
+               u64 ac1_max_level;
+               u64 ac2_max_level;
+               u64 ac3_max_level;
+               u64 ac4_max_level;
+               u64 ac5_max_level;
+               u64 ac6_max_level;
+               u64 ac7_max_level;
+               u64 ac8_max_level;
+               u64 ac9_max_level;
+       };
+       u64 __data[ACPI_NR_ART_ELEMENTS];
+};
+
+union trt_object {
+       struct {
+               char source_device[8]; /* ACPI single name */
+               char target_device[8]; /* ACPI single name */
+               u64 influence;
+               u64 sample_period;
+               u64 reserved[4];
+       };
+       u64 __data[8];
+};
+
+#ifdef __KERNEL__
+int acpi_thermal_rel_misc_device_add(acpi_handle handle);
+int acpi_thermal_rel_misc_device_remove(acpi_handle handle);
+int acpi_parse_art(acpi_handle handle, int *art_count, struct art **arts,
+               bool create_dev);
+int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trts,
+               bool create_dev);
+#endif
+
+#endif /* __ACPI_ACPI_THERMAL_H */
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
new file mode 100644 (file)
index 0000000..edc1cce
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * INT3400 thermal driver
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Zhang Rui <rui.zhang@intel.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/module.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/thermal.h>
+#include "acpi_thermal_rel.h"
+
+enum int3400_thermal_uuid {
+       INT3400_THERMAL_PASSIVE_1,
+       INT3400_THERMAL_PASSIVE_2,
+       INT3400_THERMAL_ACTIVE,
+       INT3400_THERMAL_CRITICAL,
+       INT3400_THERMAL_COOLING_MODE,
+       INT3400_THERMAL_MAXIMUM_UUID,
+};
+
+static u8 *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
+       "42A441D6-AE6A-462b-A84B-4A8CE79027D3",
+       "9E04115A-AE87-4D1C-9500-0F3E340BFE75",
+       "3A95C389-E4B8-4629-A526-C52C88626BAE",
+       "97C68AE7-15FA-499c-B8C9-5DA81D606E0A",
+       "16CAF1B7-DD38-40ed-B1C1-1B8A1913D531",
+};
+
+struct int3400_thermal_priv {
+       struct acpi_device *adev;
+       struct thermal_zone_device *thermal;
+       int mode;
+       int art_count;
+       struct art *arts;
+       int trt_count;
+       struct trt *trts;
+       u8 uuid_bitmap;
+       int rel_misc_dev_res;
+};
+
+static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
+{
+       struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL};
+       union acpi_object *obja, *objb;
+       int i, j;
+       int result = 0;
+       acpi_status status;
+
+       status = acpi_evaluate_object(priv->adev->handle, "IDSP", NULL, &buf);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       obja = (union acpi_object *)buf.pointer;
+       if (obja->type != ACPI_TYPE_PACKAGE) {
+               result = -EINVAL;
+               goto end;
+       }
+
+       for (i = 0; i < obja->package.count; i++) {
+               objb = &obja->package.elements[i];
+               if (objb->type != ACPI_TYPE_BUFFER) {
+                       result = -EINVAL;
+                       goto end;
+               }
+
+               /* UUID must be 16 bytes */
+               if (objb->buffer.length != 16) {
+                       result = -EINVAL;
+                       goto end;
+               }
+
+               for (j = 0; j < INT3400_THERMAL_MAXIMUM_UUID; j++) {
+                       u8 uuid[16];
+
+                       acpi_str_to_uuid(int3400_thermal_uuids[j], uuid);
+                       if (!strncmp(uuid, objb->buffer.pointer, 16)) {
+                               priv->uuid_bitmap |= (1 << j);
+                               break;
+                       }
+               }
+       }
+
+end:
+       kfree(buf.pointer);
+       return result;
+}
+
+static int int3400_thermal_run_osc(acpi_handle handle,
+                               enum int3400_thermal_uuid uuid, bool enable)
+{
+       u32 ret, buf[2];
+       acpi_status status;
+       int result = 0;
+       struct acpi_osc_context context = {
+               .uuid_str = int3400_thermal_uuids[uuid],
+               .rev = 1,
+               .cap.length = 8,
+       };
+
+       buf[OSC_QUERY_DWORD] = 0;
+       buf[OSC_SUPPORT_DWORD] = enable;
+
+       context.cap.pointer = buf;
+
+       status = acpi_run_osc(handle, &context);
+       if (ACPI_SUCCESS(status)) {
+               ret = *((u32 *)(context.ret.pointer + 4));
+               if (ret != enable)
+                       result = -EPERM;
+       } else
+               result = -EPERM;
+
+       kfree(context.ret.pointer);
+       return result;
+}
+
+static int int3400_thermal_get_temp(struct thermal_zone_device *thermal,
+                       unsigned long *temp)
+{
+       *temp = 20 * 1000; /* faked temp sensor with 20C */
+       return 0;
+}
+
+static int int3400_thermal_get_mode(struct thermal_zone_device *thermal,
+                               enum thermal_device_mode *mode)
+{
+       struct int3400_thermal_priv *priv = thermal->devdata;
+
+       if (!priv)
+               return -EINVAL;
+
+       *mode = priv->mode;
+
+       return 0;
+}
+
+static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
+                               enum thermal_device_mode mode)
+{
+       struct int3400_thermal_priv *priv = thermal->devdata;
+       bool enable;
+       int result = 0;
+
+       if (!priv)
+               return -EINVAL;
+
+       if (mode == THERMAL_DEVICE_ENABLED)
+               enable = true;
+       else if (mode == THERMAL_DEVICE_DISABLED)
+               enable = false;
+       else
+               return -EINVAL;
+
+       if (enable != priv->mode) {
+               priv->mode = enable;
+               /* currently, only PASSIVE COOLING is supported */
+               result = int3400_thermal_run_osc(priv->adev->handle,
+                                       INT3400_THERMAL_PASSIVE_1, enable);
+       }
+       return result;
+}
+
+static struct thermal_zone_device_ops int3400_thermal_ops = {
+       .get_temp = int3400_thermal_get_temp,
+};
+
+static struct thermal_zone_params int3400_thermal_params = {
+       .governor_name = "user_space",
+       .no_hwmon = true,
+};
+
+static int int3400_thermal_probe(struct platform_device *pdev)
+{
+       struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+       struct int3400_thermal_priv *priv;
+       int result;
+
+       if (!adev)
+               return -ENODEV;
+
+       priv = kzalloc(sizeof(struct int3400_thermal_priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->adev = adev;
+
+       result = int3400_thermal_get_uuids(priv);
+       if (result)
+               goto free_priv;
+
+       result = acpi_parse_art(priv->adev->handle, &priv->art_count,
+                               &priv->arts, true);
+       if (result)
+               goto free_priv;
+
+
+       result = acpi_parse_trt(priv->adev->handle, &priv->trt_count,
+                               &priv->trts, true);
+       if (result)
+               goto free_art;
+
+       platform_set_drvdata(pdev, priv);
+
+       if (priv->uuid_bitmap & 1 << INT3400_THERMAL_PASSIVE_1) {
+               int3400_thermal_ops.get_mode = int3400_thermal_get_mode;
+               int3400_thermal_ops.set_mode = int3400_thermal_set_mode;
+       }
+       priv->thermal = thermal_zone_device_register("INT3400 Thermal", 0, 0,
+                                               priv, &int3400_thermal_ops,
+                                               &int3400_thermal_params, 0, 0);
+       if (IS_ERR(priv->thermal)) {
+               result = PTR_ERR(priv->thermal);
+               goto free_trt;
+       }
+
+       priv->rel_misc_dev_res = acpi_thermal_rel_misc_device_add(
+                                                       priv->adev->handle);
+
+       return 0;
+free_trt:
+       kfree(priv->trts);
+free_art:
+       kfree(priv->arts);
+free_priv:
+       kfree(priv);
+       return result;
+}
+
+static int int3400_thermal_remove(struct platform_device *pdev)
+{
+       struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
+
+       if (!priv->rel_misc_dev_res)
+               acpi_thermal_rel_misc_device_remove(priv->adev->handle);
+
+       thermal_zone_device_unregister(priv->thermal);
+       kfree(priv->trts);
+       kfree(priv->arts);
+       kfree(priv);
+       return 0;
+}
+
+static const struct acpi_device_id int3400_thermal_match[] = {
+       {"INT3400", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(acpi, int3400_thermal_match);
+
+static struct platform_driver int3400_thermal_driver = {
+       .probe = int3400_thermal_probe,
+       .remove = int3400_thermal_remove,
+       .driver = {
+                  .name = "int3400 thermal",
+                  .owner = THIS_MODULE,
+                  .acpi_match_table = ACPI_PTR(int3400_thermal_match),
+                  },
+};
+
+module_platform_driver(int3400_thermal_driver);
+
+MODULE_DESCRIPTION("INT3400 Thermal driver");
+MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/int340x_thermal/int3402_thermal.c b/drivers/thermal/int340x_thermal/int3402_thermal.c
new file mode 100644 (file)
index 0000000..a5d08c1
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * INT3402 thermal driver for memory temperature reporting
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Aaron Lu <aaron.lu@intel.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/module.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+#include <linux/thermal.h>
+
+#define ACPI_ACTIVE_COOLING_MAX_NR 10
+
+struct active_trip {
+       unsigned long temp;
+       int id;
+       bool valid;
+};
+
+struct int3402_thermal_data {
+       unsigned long *aux_trips;
+       int aux_trip_nr;
+       unsigned long psv_temp;
+       int psv_trip_id;
+       unsigned long crt_temp;
+       int crt_trip_id;
+       unsigned long hot_temp;
+       int hot_trip_id;
+       struct active_trip act_trips[ACPI_ACTIVE_COOLING_MAX_NR];
+       acpi_handle *handle;
+};
+
+static int int3402_thermal_get_zone_temp(struct thermal_zone_device *zone,
+                                        unsigned long *temp)
+{
+       struct int3402_thermal_data *d = zone->devdata;
+       unsigned long long tmp;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(d->handle, "_TMP", NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       /* _TMP returns the temperature in tenths of degrees Kelvin */
+       *temp = DECI_KELVIN_TO_MILLICELSIUS(tmp);
+
+       return 0;
+}
+
+static int int3402_thermal_get_trip_temp(struct thermal_zone_device *zone,
+                                        int trip, unsigned long *temp)
+{
+       struct int3402_thermal_data *d = zone->devdata;
+       int i;
+
+       if (trip < d->aux_trip_nr)
+               *temp = d->aux_trips[trip];
+       else if (trip == d->crt_trip_id)
+               *temp = d->crt_temp;
+       else if (trip == d->psv_trip_id)
+               *temp = d->psv_temp;
+       else if (trip == d->hot_trip_id)
+               *temp = d->hot_temp;
+       else {
+               for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) {
+                       if (d->act_trips[i].valid &&
+                           d->act_trips[i].id == trip) {
+                               *temp = d->act_trips[i].temp;
+                               break;
+                       }
+               }
+               if (i == ACPI_ACTIVE_COOLING_MAX_NR)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static int int3402_thermal_get_trip_type(struct thermal_zone_device *zone,
+                                        int trip, enum thermal_trip_type *type)
+{
+       struct int3402_thermal_data *d = zone->devdata;
+       int i;
+
+       if (trip < d->aux_trip_nr)
+               *type = THERMAL_TRIP_PASSIVE;
+       else if (trip == d->crt_trip_id)
+               *type = THERMAL_TRIP_CRITICAL;
+       else if (trip == d->hot_trip_id)
+               *type = THERMAL_TRIP_HOT;
+       else if (trip == d->psv_trip_id)
+               *type = THERMAL_TRIP_PASSIVE;
+       else {
+               for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) {
+                       if (d->act_trips[i].valid &&
+                           d->act_trips[i].id == trip) {
+                               *type = THERMAL_TRIP_ACTIVE;
+                               break;
+                       }
+               }
+               if (i == ACPI_ACTIVE_COOLING_MAX_NR)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+static int int3402_thermal_set_trip_temp(struct thermal_zone_device *zone, int trip,
+                                 unsigned long temp)
+{
+       struct int3402_thermal_data *d = zone->devdata;
+       acpi_status status;
+       char name[10];
+
+       snprintf(name, sizeof(name), "PAT%d", trip);
+       status = acpi_execute_simple_method(d->handle, name,
+                       MILLICELSIUS_TO_DECI_KELVIN(temp));
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       d->aux_trips[trip] = temp;
+       return 0;
+}
+
+static struct thermal_zone_device_ops int3402_thermal_zone_ops = {
+       .get_temp       = int3402_thermal_get_zone_temp,
+       .get_trip_temp  = int3402_thermal_get_trip_temp,
+       .get_trip_type  = int3402_thermal_get_trip_type,
+       .set_trip_temp  = int3402_thermal_set_trip_temp,
+};
+
+static struct thermal_zone_params int3402_thermal_params = {
+       .governor_name = "user_space",
+       .no_hwmon = true,
+};
+
+static int int3402_thermal_get_temp(acpi_handle handle, char *name,
+                                   unsigned long *temp)
+{
+       unsigned long long r;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(handle, name, NULL, &r);
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       *temp = DECI_KELVIN_TO_MILLICELSIUS(r);
+       return 0;
+}
+
+static int int3402_thermal_probe(struct platform_device *pdev)
+{
+       struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+       struct int3402_thermal_data *d;
+       struct thermal_zone_device *zone;
+       acpi_status status;
+       unsigned long long trip_cnt;
+       int trip_mask = 0, i;
+
+       if (!acpi_has_method(adev->handle, "_TMP"))
+               return -ENODEV;
+
+       d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
+       if (!d)
+               return -ENOMEM;
+
+       status = acpi_evaluate_integer(adev->handle, "PATC", NULL, &trip_cnt);
+       if (ACPI_FAILURE(status))
+               trip_cnt = 0;
+       else {
+               d->aux_trips = devm_kzalloc(&pdev->dev,
+                               sizeof(*d->aux_trips) * trip_cnt, GFP_KERNEL);
+               if (!d->aux_trips)
+                       return -ENOMEM;
+               trip_mask = trip_cnt - 1;
+               d->handle = adev->handle;
+               d->aux_trip_nr = trip_cnt;
+       }
+
+       d->crt_trip_id = -1;
+       if (!int3402_thermal_get_temp(adev->handle, "_CRT", &d->crt_temp))
+               d->crt_trip_id = trip_cnt++;
+       d->hot_trip_id = -1;
+       if (!int3402_thermal_get_temp(adev->handle, "_HOT", &d->hot_temp))
+               d->hot_trip_id = trip_cnt++;
+       d->psv_trip_id = -1;
+       if (!int3402_thermal_get_temp(adev->handle, "_PSV", &d->psv_temp))
+               d->psv_trip_id = trip_cnt++;
+       for (i = 0; i < ACPI_ACTIVE_COOLING_MAX_NR; i++) {
+               char name[5] = { '_', 'A', 'C', '0' + i, '\0' };
+               if (int3402_thermal_get_temp(adev->handle, name,
+                                            &d->act_trips[i].temp))
+                       break;
+               d->act_trips[i].id = trip_cnt++;
+               d->act_trips[i].valid = true;
+       }
+
+       zone = thermal_zone_device_register(acpi_device_bid(adev), trip_cnt,
+                                           trip_mask, d,
+                                           &int3402_thermal_zone_ops,
+                                           &int3402_thermal_params,
+                                           0, 0);
+       if (IS_ERR(zone))
+               return PTR_ERR(zone);
+       platform_set_drvdata(pdev, zone);
+
+       return 0;
+}
+
+static int int3402_thermal_remove(struct platform_device *pdev)
+{
+       struct thermal_zone_device *zone = platform_get_drvdata(pdev);
+
+       thermal_zone_device_unregister(zone);
+       return 0;
+}
+
+static const struct acpi_device_id int3402_thermal_match[] = {
+       {"INT3402", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(acpi, int3402_thermal_match);
+
+static struct platform_driver int3402_thermal_driver = {
+       .probe = int3402_thermal_probe,
+       .remove = int3402_thermal_remove,
+       .driver = {
+                  .name = "int3402 thermal",
+                  .owner = THIS_MODULE,
+                  .acpi_match_table = int3402_thermal_match,
+                  },
+};
+
+module_platform_driver(int3402_thermal_driver);
+
+MODULE_DESCRIPTION("INT3402 Thermal driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/int340x_thermal/int3403_thermal.c
new file mode 100644 (file)
index 0000000..6e9fb62
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * ACPI INT3403 thermal driver
+ * Copyright (c) 2013, 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/acpi.h>
+#include <linux/thermal.h>
+#include <linux/platform_device.h>
+
+#define INT3403_TYPE_SENSOR            0x03
+#define INT3403_TYPE_CHARGER           0x0B
+#define INT3403_TYPE_BATTERY           0x0C
+#define INT3403_PERF_CHANGED_EVENT     0x80
+#define INT3403_THERMAL_EVENT          0x90
+
+#define DECI_KELVIN_TO_MILLI_CELSIUS(t, off) (((t) - (off)) * 100)
+#define KELVIN_OFFSET  2732
+#define MILLI_CELSIUS_TO_DECI_KELVIN(t, off) (((t) / 100) + (off))
+
+struct int3403_sensor {
+       struct thermal_zone_device *tzone;
+       unsigned long *thresholds;
+       unsigned long   crit_temp;
+       int             crit_trip_id;
+       unsigned long   psv_temp;
+       int             psv_trip_id;
+
+};
+
+struct int3403_performance_state {
+       u64 performance;
+       u64 power;
+       u64 latency;
+       u64 linear;
+       u64 control;
+       u64 raw_performace;
+       char *raw_unit;
+       int reserved;
+};
+
+struct int3403_cdev {
+       struct thermal_cooling_device *cdev;
+       unsigned long max_state;
+};
+
+struct int3403_priv {
+       struct platform_device *pdev;
+       struct acpi_device *adev;
+       unsigned long long type;
+       void *priv;
+};
+
+static int sys_get_curr_temp(struct thermal_zone_device *tzone,
+                               unsigned long *temp)
+{
+       struct int3403_priv *priv = tzone->devdata;
+       struct acpi_device *device = priv->adev;
+       unsigned long long tmp;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(device->handle, "_TMP", NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       *temp = DECI_KELVIN_TO_MILLI_CELSIUS(tmp, KELVIN_OFFSET);
+
+       return 0;
+}
+
+static int sys_get_trip_hyst(struct thermal_zone_device *tzone,
+               int trip, unsigned long *temp)
+{
+       struct int3403_priv *priv = tzone->devdata;
+       struct acpi_device *device = priv->adev;
+       unsigned long long hyst;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(device->handle, "GTSH", NULL, &hyst);
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       /*
+        * Thermal hysteresis represents a temperature difference.
+        * Kelvin and Celsius have same degree size. So the
+        * conversion here between tenths of degree Kelvin unit
+        * and Milli-Celsius unit is just to multiply 100.
+        */
+       *temp = hyst * 100;
+
+       return 0;
+}
+
+static int sys_get_trip_temp(struct thermal_zone_device *tzone,
+               int trip, unsigned long *temp)
+{
+       struct int3403_priv *priv = tzone->devdata;
+       struct int3403_sensor *obj = priv->priv;
+
+       if (priv->type != INT3403_TYPE_SENSOR || !obj)
+               return -EINVAL;
+
+       if (trip == obj->crit_trip_id)
+               *temp = obj->crit_temp;
+       else if (trip == obj->psv_trip_id)
+               *temp = obj->psv_temp;
+       else {
+               /*
+                * get_trip_temp is a mandatory callback but
+                * PATx method doesn't return any value, so return
+                * cached value, which was last set from user space
+                */
+               *temp = obj->thresholds[trip];
+       }
+
+       return 0;
+}
+
+static int sys_get_trip_type(struct thermal_zone_device *thermal,
+               int trip, enum thermal_trip_type *type)
+{
+       struct int3403_priv *priv = thermal->devdata;
+       struct int3403_sensor *obj = priv->priv;
+
+       /* Mandatory callback, may not mean much here */
+       if (trip == obj->crit_trip_id)
+               *type = THERMAL_TRIP_CRITICAL;
+       else
+               *type = THERMAL_TRIP_PASSIVE;
+
+       return 0;
+}
+
+int sys_set_trip_temp(struct thermal_zone_device *tzone, int trip,
+                                                       unsigned long temp)
+{
+       struct int3403_priv *priv = tzone->devdata;
+       struct acpi_device *device = priv->adev;
+       struct int3403_sensor *obj = priv->priv;
+       acpi_status status;
+       char name[10];
+       int ret = 0;
+
+       snprintf(name, sizeof(name), "PAT%d", trip);
+       if (acpi_has_method(device->handle, name)) {
+               status = acpi_execute_simple_method(device->handle, name,
+                               MILLI_CELSIUS_TO_DECI_KELVIN(temp,
+                                                       KELVIN_OFFSET));
+               if (ACPI_FAILURE(status))
+                       ret = -EIO;
+               else
+                       obj->thresholds[trip] = temp;
+       } else {
+               ret = -EIO;
+               dev_err(&device->dev, "sys_set_trip_temp: method not found\n");
+       }
+
+       return ret;
+}
+
+static struct thermal_zone_device_ops tzone_ops = {
+       .get_temp = sys_get_curr_temp,
+       .get_trip_temp = sys_get_trip_temp,
+       .get_trip_type = sys_get_trip_type,
+       .set_trip_temp = sys_set_trip_temp,
+       .get_trip_hyst =  sys_get_trip_hyst,
+};
+
+static struct thermal_zone_params int3403_thermal_params = {
+       .governor_name = "user_space",
+       .no_hwmon = true,
+};
+
+static void int3403_notify(acpi_handle handle,
+               u32 event, void *data)
+{
+       struct int3403_priv *priv = data;
+       struct int3403_sensor *obj;
+
+       if (!priv)
+               return;
+
+       obj = priv->priv;
+       if (priv->type != INT3403_TYPE_SENSOR || !obj)
+               return;
+
+       switch (event) {
+       case INT3403_PERF_CHANGED_EVENT:
+               break;
+       case INT3403_THERMAL_EVENT:
+               thermal_zone_device_update(obj->tzone);
+               break;
+       default:
+               dev_err(&priv->pdev->dev, "Unsupported event [0x%x]\n", event);
+               break;
+       }
+}
+
+static int sys_get_trip_crt(struct acpi_device *device, unsigned long *temp)
+{
+       unsigned long long crt;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(device->handle, "_CRT", NULL, &crt);
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       *temp = DECI_KELVIN_TO_MILLI_CELSIUS(crt, KELVIN_OFFSET);
+
+       return 0;
+}
+
+static int sys_get_trip_psv(struct acpi_device *device, unsigned long *temp)
+{
+       unsigned long long psv;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(device->handle, "_PSV", NULL, &psv);
+       if (ACPI_FAILURE(status))
+               return -EIO;
+
+       *temp = DECI_KELVIN_TO_MILLI_CELSIUS(psv, KELVIN_OFFSET);
+
+       return 0;
+}
+
+static int int3403_sensor_add(struct int3403_priv *priv)
+{
+       int result = 0;
+       acpi_status status;
+       struct int3403_sensor *obj;
+       unsigned long long trip_cnt;
+       int trip_mask = 0;
+
+       obj = devm_kzalloc(&priv->pdev->dev, sizeof(*obj), GFP_KERNEL);
+       if (!obj)
+               return -ENOMEM;
+
+       priv->priv = obj;
+
+       status = acpi_evaluate_integer(priv->adev->handle, "PATC", NULL,
+                                               &trip_cnt);
+       if (ACPI_FAILURE(status))
+               trip_cnt = 0;
+
+       if (trip_cnt) {
+               /* We have to cache, thresholds can't be readback */
+               obj->thresholds = devm_kzalloc(&priv->pdev->dev,
+                                       sizeof(*obj->thresholds) * trip_cnt,
+                                       GFP_KERNEL);
+               if (!obj->thresholds) {
+                       result = -ENOMEM;
+                       goto err_free_obj;
+               }
+               trip_mask = BIT(trip_cnt) - 1;
+       }
+
+       obj->psv_trip_id = -1;
+       if (!sys_get_trip_psv(priv->adev, &obj->psv_temp))
+               obj->psv_trip_id = trip_cnt++;
+
+       obj->crit_trip_id = -1;
+       if (!sys_get_trip_crt(priv->adev, &obj->crit_temp))
+               obj->crit_trip_id = trip_cnt++;
+
+       obj->tzone = thermal_zone_device_register(acpi_device_bid(priv->adev),
+                               trip_cnt, trip_mask, priv, &tzone_ops,
+                               &int3403_thermal_params, 0, 0);
+       if (IS_ERR(obj->tzone)) {
+               result = PTR_ERR(obj->tzone);
+               obj->tzone = NULL;
+               goto err_free_obj;
+       }
+
+       result = acpi_install_notify_handler(priv->adev->handle,
+                       ACPI_DEVICE_NOTIFY, int3403_notify,
+                       (void *)priv);
+       if (result)
+               goto err_free_obj;
+
+       return 0;
+
+ err_free_obj:
+       if (obj->tzone)
+               thermal_zone_device_unregister(obj->tzone);
+       return result;
+}
+
+static int int3403_sensor_remove(struct int3403_priv *priv)
+{
+       struct int3403_sensor *obj = priv->priv;
+
+       thermal_zone_device_unregister(obj->tzone);
+       return 0;
+}
+
+/* INT3403 Cooling devices */
+static int int3403_get_max_state(struct thermal_cooling_device *cdev,
+                                unsigned long *state)
+{
+       struct int3403_priv *priv = cdev->devdata;
+       struct int3403_cdev *obj = priv->priv;
+
+       *state = obj->max_state;
+       return 0;
+}
+
+static int int3403_get_cur_state(struct thermal_cooling_device *cdev,
+                                unsigned long *state)
+{
+       struct int3403_priv *priv = cdev->devdata;
+       unsigned long long level;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(priv->adev->handle, "PPPC", NULL, &level);
+       if (ACPI_SUCCESS(status)) {
+               *state = level;
+               return 0;
+       } else
+               return -EINVAL;
+}
+
+static int
+int3403_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+{
+       struct int3403_priv *priv = cdev->devdata;
+       acpi_status status;
+
+       status = acpi_execute_simple_method(priv->adev->handle, "SPPC", state);
+       if (ACPI_SUCCESS(status))
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static const struct thermal_cooling_device_ops int3403_cooling_ops = {
+       .get_max_state = int3403_get_max_state,
+       .get_cur_state = int3403_get_cur_state,
+       .set_cur_state = int3403_set_cur_state,
+};
+
+static int int3403_cdev_add(struct int3403_priv *priv)
+{
+       int result = 0;
+       acpi_status status;
+       struct int3403_cdev *obj;
+       struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *p;
+
+       obj = devm_kzalloc(&priv->pdev->dev, sizeof(*obj), GFP_KERNEL);
+       if (!obj)
+               return -ENOMEM;
+
+       status = acpi_evaluate_object(priv->adev->handle, "PPSS", NULL, &buf);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       p = buf.pointer;
+       if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
+               printk(KERN_WARNING "Invalid PPSS data\n");
+               return -EFAULT;
+       }
+
+       obj->max_state = p->package.count - 1;
+       obj->cdev =
+               thermal_cooling_device_register(acpi_device_bid(priv->adev),
+                               priv, &int3403_cooling_ops);
+       if (IS_ERR(obj->cdev))
+               result = PTR_ERR(obj->cdev);
+
+       priv->priv = obj;
+
+       /* TODO: add ACPI notification support */
+
+       return result;
+}
+
+static int int3403_cdev_remove(struct int3403_priv *priv)
+{
+       struct int3403_cdev *obj = priv->priv;
+
+       thermal_cooling_device_unregister(obj->cdev);
+       return 0;
+}
+
+static int int3403_add(struct platform_device *pdev)
+{
+       struct int3403_priv *priv;
+       int result = 0;
+       acpi_status status;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(struct int3403_priv),
+                           GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->pdev = pdev;
+       priv->adev = ACPI_COMPANION(&(pdev->dev));
+       if (!priv->adev) {
+               result = -EINVAL;
+               goto err;
+       }
+
+       status = acpi_evaluate_integer(priv->adev->handle, "PTYP",
+                                      NULL, &priv->type);
+       if (ACPI_FAILURE(status)) {
+               result = -EINVAL;
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, priv);
+       switch (priv->type) {
+       case INT3403_TYPE_SENSOR:
+               result = int3403_sensor_add(priv);
+               break;
+       case INT3403_TYPE_CHARGER:
+       case INT3403_TYPE_BATTERY:
+               result = int3403_cdev_add(priv);
+               break;
+       default:
+               result = -EINVAL;
+       }
+
+       if (result)
+               goto err;
+       return result;
+
+err:
+       return result;
+}
+
+static int int3403_remove(struct platform_device *pdev)
+{
+       struct int3403_priv *priv = platform_get_drvdata(pdev);
+
+       switch (priv->type) {
+       case INT3403_TYPE_SENSOR:
+               int3403_sensor_remove(priv);
+               break;
+       case INT3403_TYPE_CHARGER:
+       case INT3403_TYPE_BATTERY:
+               int3403_cdev_remove(priv);
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static const struct acpi_device_id int3403_device_ids[] = {
+       {"INT3403", 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, int3403_device_ids);
+
+static struct platform_driver int3403_driver = {
+       .probe = int3403_add,
+       .remove = int3403_remove,
+       .driver = {
+               .name = "int3403 thermal",
+               .owner  = THIS_MODULE,
+               .acpi_match_table = int3403_device_ids,
+       },
+};
+
+module_platform_driver(int3403_driver);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ACPI INT3403 thermal driver");
index 4b2b999b7611cb04390dfa1c6c3b5ac208d26069..62143ba3100182462861040ef3c28ce43ec45d00 100644 (file)
@@ -387,20 +387,27 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
                                int (*get_trend)(void *, long *))
 {
        struct device_node *np, *child, *sensor_np;
+       struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
 
        np = of_find_node_by_name(NULL, "thermal-zones");
        if (!np)
                return ERR_PTR(-ENODEV);
 
-       if (!dev || !dev->of_node)
+       if (!dev || !dev->of_node) {
+               of_node_put(np);
                return ERR_PTR(-EINVAL);
+       }
 
-       sensor_np = dev->of_node;
+       sensor_np = of_node_get(dev->of_node);
 
        for_each_child_of_node(np, child) {
                struct of_phandle_args sensor_specs;
                int ret, id;
 
+               /* Check whether child is enabled or not */
+               if (!of_device_is_available(child))
+                       continue;
+
                /* For now, thermal framework supports only 1 sensor per zone */
                ret = of_parse_phandle_with_args(child, "thermal-sensors",
                                                 "#thermal-sensor-cells",
@@ -418,16 +425,21 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
                }
 
                if (sensor_specs.np == sensor_np && id == sensor_id) {
-                       of_node_put(np);
-                       return thermal_zone_of_add_sensor(child, sensor_np,
-                                                         data,
-                                                         get_temp,
-                                                         get_trend);
+                       tzd = thermal_zone_of_add_sensor(child, sensor_np,
+                                                        data,
+                                                        get_temp,
+                                                        get_trend);
+                       of_node_put(sensor_specs.np);
+                       of_node_put(child);
+                       goto exit;
                }
+               of_node_put(sensor_specs.np);
        }
+exit:
+       of_node_put(sensor_np);
        of_node_put(np);
 
-       return ERR_PTR(-ENODEV);
+       return tzd;
 }
 EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register);
 
@@ -619,6 +631,7 @@ static int thermal_of_populate_trip(struct device_node *np,
 
        /* Required for cooling map matching */
        trip->np = np;
+       of_node_get(np);
 
        return 0;
 }
@@ -726,9 +739,14 @@ finish:
        return tz;
 
 free_tbps:
+       for (i = 0; i < tz->num_tbps; i++)
+               of_node_put(tz->tbps[i].cooling_device);
        kfree(tz->tbps);
 free_trips:
+       for (i = 0; i < tz->ntrips; i++)
+               of_node_put(tz->trips[i].np);
        kfree(tz->trips);
+       of_node_put(gchild);
 free_tz:
        kfree(tz);
        of_node_put(child);
@@ -738,7 +756,13 @@ free_tz:
 
 static inline void of_thermal_free_zone(struct __thermal_zone *tz)
 {
+       int i;
+
+       for (i = 0; i < tz->num_tbps; i++)
+               of_node_put(tz->tbps[i].cooling_device);
        kfree(tz->tbps);
+       for (i = 0; i < tz->ntrips; i++)
+               of_node_put(tz->trips[i].np);
        kfree(tz->trips);
        kfree(tz);
 }
@@ -771,6 +795,10 @@ int __init of_parse_thermal_zones(void)
                struct thermal_zone_device *zone;
                struct thermal_zone_params *tzp;
 
+               /* Check whether child is enabled or not */
+               if (!of_device_is_available(child))
+                       continue;
+
                tz = thermal_of_build_thermal_zone(child);
                if (IS_ERR(tz)) {
                        pr_err("failed to build thermal zone %s: %ld\n",
@@ -806,10 +834,13 @@ int __init of_parse_thermal_zones(void)
                        /* attempting to build remaining zones still */
                }
        }
+       of_node_put(np);
 
        return 0;
 
 exit_free:
+       of_node_put(child);
+       of_node_put(np);
        of_thermal_free_zone(tz);
 
        /* no memory available, so free what we have built */
@@ -838,6 +869,10 @@ void of_thermal_destroy_zones(void)
        for_each_child_of_node(np, child) {
                struct thermal_zone_device *zone;
 
+               /* Check whether child is enabled or not */
+               if (!of_device_is_available(child))
+                       continue;
+
                zone = thermal_zone_get_zone_by_name(child->name);
                if (IS_ERR(zone))
                        continue;
@@ -847,4 +882,5 @@ void of_thermal_destroy_zones(void)
                kfree(zone->ops);
                of_thermal_free_zone(zone->devdata);
        }
+       of_node_put(np);
 }
index 3f5ad25ddca811cf5a9c61509af9ac8c89550b28..b6be572704a4c7ff97055f1cb273ff3016399469 100644 (file)
@@ -417,13 +417,10 @@ void exynos_unregister_thermal(struct thermal_sensor_conf *sensor_conf)
 
        th_zone = sensor_conf->pzone_data;
 
-       if (th_zone->therm_dev)
-               thermal_zone_device_unregister(th_zone->therm_dev);
+       thermal_zone_device_unregister(th_zone->therm_dev);
 
-       for (i = 0; i < th_zone->cool_dev_size; i++) {
-               if (th_zone->cool_dev[i])
-                       cpufreq_cooling_unregister(th_zone->cool_dev[i]);
-       }
+       for (i = 0; i < th_zone->cool_dev_size; ++i)
+               cpufreq_cooling_unregister(th_zone->cool_dev[i]);
 
        dev_info(sensor_conf->dev,
                "Exynos: Kernel Thermal management unregistered\n");
index 3eb2ed9ea3a4db3a9c7811e06a38669cf9b8588e..158f5aa8dc5d105289e0d1b4b792fc6b28f53a83 100644 (file)
@@ -27,7 +27,7 @@
 #define SENSOR_NAME_LEN        16
 #define MAX_TRIP_COUNT 8
 #define MAX_COOLING_DEVICE 4
-#define MAX_THRESHOLD_LEVS 5
+#define MAX_TRIMINFO_CTRL_REG  2
 
 #define ACTIVE_INTERVAL 500
 #define IDLE_INTERVAL 10000
index acbff14da3a492b776c1e48c2c90461c82779f77..49c09243fd3829628bf8a53af3407c958d66cb11 100644 (file)
@@ -77,16 +77,6 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
        struct exynos_tmu_platform_data *pdata = data->pdata;
        int temp_code;
 
-       if (pdata->cal_mode == HW_MODE)
-               return temp;
-
-       if (data->soc == SOC_ARCH_EXYNOS4210)
-               /* temp should range between 25 and 125 */
-               if (temp < 25 || temp > 125) {
-                       temp_code = -EINVAL;
-                       goto out;
-               }
-
        switch (pdata->cal_type) {
        case TYPE_TWO_POINT_TRIMMING:
                temp_code = (temp - pdata->first_point_trim) *
@@ -101,7 +91,7 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
                temp_code = temp + pdata->default_temp_offset;
                break;
        }
-out:
+
        return temp_code;
 }
 
@@ -114,16 +104,6 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
        struct exynos_tmu_platform_data *pdata = data->pdata;
        int temp;
 
-       if (pdata->cal_mode == HW_MODE)
-               return temp_code;
-
-       if (data->soc == SOC_ARCH_EXYNOS4210)
-               /* temp_code should range between 75 and 175 */
-               if (temp_code < 75 || temp_code > 175) {
-                       temp = -ENODATA;
-                       goto out;
-               }
-
        switch (pdata->cal_type) {
        case TYPE_TWO_POINT_TRIMMING:
                temp = (temp_code - data->temp_error1) *
@@ -138,18 +118,35 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
                temp = temp_code - pdata->default_temp_offset;
                break;
        }
-out:
+
        return temp;
 }
 
+static void exynos_tmu_clear_irqs(struct exynos_tmu_data *data)
+{
+       const struct exynos_tmu_registers *reg = data->pdata->registers;
+       unsigned int val_irq;
+
+       val_irq = readl(data->base + reg->tmu_intstat);
+       /*
+        * Clear the interrupts.  Please note that the documentation for
+        * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
+        * states that INTCLEAR register has a different placing of bits
+        * responsible for FALL IRQs than INTSTAT register.  Exynos5420
+        * and Exynos5440 documentation is correct (Exynos4210 doesn't
+        * support FALL IRQs at all).
+        */
+       writel(val_irq, data->base + reg->tmu_intclear);
+}
+
 static int exynos_tmu_initialize(struct platform_device *pdev)
 {
        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
        struct exynos_tmu_platform_data *pdata = data->pdata;
        const struct exynos_tmu_registers *reg = pdata->registers;
-       unsigned int status, trim_info = 0, con;
+       unsigned int status, trim_info = 0, con, ctrl;
        unsigned int rising_threshold = 0, falling_threshold = 0;
-       int ret = 0, threshold_code, i, trigger_levs = 0;
+       int ret = 0, threshold_code, i;
 
        mutex_lock(&data->lock);
        clk_enable(data->clk);
@@ -164,11 +161,17 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
                }
        }
 
-       if (TMU_SUPPORTS(pdata, TRIM_RELOAD))
-               __raw_writel(1, data->base + reg->triminfo_ctrl);
-
-       if (pdata->cal_mode == HW_MODE)
-               goto skip_calib_data;
+       if (TMU_SUPPORTS(pdata, TRIM_RELOAD)) {
+               for (i = 0; i < reg->triminfo_ctrl_count; i++) {
+                       if (pdata->triminfo_reload[i]) {
+                               ctrl = readl(data->base +
+                                               reg->triminfo_ctrl[i]);
+                               ctrl |= pdata->triminfo_reload[i];
+                               writel(ctrl, data->base +
+                                               reg->triminfo_ctrl[i]);
+                       }
+               }
+       }
 
        /* Save trimming info in order to perform calibration */
        if (data->soc == SOC_ARCH_EXYNOS5440) {
@@ -197,7 +200,7 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
                        trim_info = readl(data->base + reg->triminfo_data);
        }
        data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
-       data->temp_error2 = ((trim_info >> reg->triminfo_85_shift) &
+       data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
                                EXYNOS_TMU_TEMP_MASK);
 
        if (!data->temp_error1 ||
@@ -207,67 +210,33 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
 
        if (!data->temp_error2)
                data->temp_error2 =
-                       (pdata->efuse_value >> reg->triminfo_85_shift) &
+                       (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
                        EXYNOS_TMU_TEMP_MASK;
 
-skip_calib_data:
-       if (pdata->max_trigger_level > MAX_THRESHOLD_LEVS) {
-               dev_err(&pdev->dev, "Invalid max trigger level\n");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       for (i = 0; i < pdata->max_trigger_level; i++) {
-               if (!pdata->trigger_levels[i])
-                       continue;
-
-               if ((pdata->trigger_type[i] == HW_TRIP) &&
-               (!pdata->trigger_levels[pdata->max_trigger_level - 1])) {
-                       dev_err(&pdev->dev, "Invalid hw trigger level\n");
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               /* Count trigger levels except the HW trip*/
-               if (!(pdata->trigger_type[i] == HW_TRIP))
-                       trigger_levs++;
-       }
-
        rising_threshold = readl(data->base + reg->threshold_th0);
 
        if (data->soc == SOC_ARCH_EXYNOS4210) {
                /* Write temperature code for threshold */
                threshold_code = temp_to_code(data, pdata->threshold);
-               if (threshold_code < 0) {
-                       ret = threshold_code;
-                       goto out;
-               }
                writeb(threshold_code,
                        data->base + reg->threshold_temp);
-               for (i = 0; i < trigger_levs; i++)
+               for (i = 0; i < pdata->non_hw_trigger_levels; i++)
                        writeb(pdata->trigger_levels[i], data->base +
                        reg->threshold_th0 + i * sizeof(reg->threshold_th0));
 
-               writel(reg->intclr_rise_mask, data->base + reg->tmu_intclear);
+               exynos_tmu_clear_irqs(data);
        } else {
                /* Write temperature code for rising and falling threshold */
-               for (i = 0;
-               i < trigger_levs && i < EXYNOS_MAX_TRIGGER_PER_REG; i++) {
+               for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
                        threshold_code = temp_to_code(data,
                                                pdata->trigger_levels[i]);
-                       if (threshold_code < 0) {
-                               ret = threshold_code;
-                               goto out;
-                       }
                        rising_threshold &= ~(0xff << 8 * i);
                        rising_threshold |= threshold_code << 8 * i;
                        if (pdata->threshold_falling) {
                                threshold_code = temp_to_code(data,
                                                pdata->trigger_levels[i] -
                                                pdata->threshold_falling);
-                               if (threshold_code > 0)
-                                       falling_threshold |=
-                                               threshold_code << 8 * i;
+                               falling_threshold |= threshold_code << 8 * i;
                        }
                }
 
@@ -276,9 +245,7 @@ skip_calib_data:
                writel(falling_threshold,
                                data->base + reg->threshold_th1);
 
-               writel((reg->intclr_rise_mask << reg->intclr_rise_shift) |
-                       (reg->intclr_fall_mask << reg->intclr_fall_shift),
-                               data->base + reg->tmu_intclear);
+               exynos_tmu_clear_irqs(data);
 
                /* if last threshold limit is also present */
                i = pdata->max_trigger_level - 1;
@@ -286,10 +253,6 @@ skip_calib_data:
                                (pdata->trigger_type[i] == HW_TRIP)) {
                        threshold_code = temp_to_code(data,
                                                pdata->trigger_levels[i]);
-                       if (threshold_code < 0) {
-                               ret = threshold_code;
-                               goto out;
-                       }
                        if (i == EXYNOS_MAX_TRIGGER_PER_REG - 1) {
                                /* 1-4 level to be assigned in th0 reg */
                                rising_threshold &= ~(0xff << 8 * i);
@@ -325,7 +288,7 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
        struct exynos_tmu_data *data = platform_get_drvdata(pdev);
        struct exynos_tmu_platform_data *pdata = data->pdata;
        const struct exynos_tmu_registers *reg = pdata->registers;
-       unsigned int con, interrupt_en, cal_val;
+       unsigned int con, interrupt_en;
 
        mutex_lock(&data->lock);
        clk_enable(data->clk);
@@ -335,15 +298,11 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
        if (pdata->test_mux)
                con |= (pdata->test_mux << reg->test_mux_addr_shift);
 
-       if (pdata->reference_voltage) {
-               con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
-               con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
-       }
+       con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
+       con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
 
-       if (pdata->gain) {
-               con &= ~(reg->buf_slope_sel_mask << reg->buf_slope_sel_shift);
-               con |= (pdata->gain << reg->buf_slope_sel_shift);
-       }
+       con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
+       con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
 
        if (pdata->noise_cancel_mode) {
                con &= ~(reg->therm_trip_mode_mask <<
@@ -351,29 +310,8 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
                con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
        }
 
-       if (pdata->cal_mode == HW_MODE) {
-               con &= ~(reg->calib_mode_mask << reg->calib_mode_shift);
-               cal_val = 0;
-               switch (pdata->cal_type) {
-               case TYPE_TWO_POINT_TRIMMING:
-                       cal_val = 3;
-                       break;
-               case TYPE_ONE_POINT_TRIMMING_85:
-                       cal_val = 2;
-                       break;
-               case TYPE_ONE_POINT_TRIMMING_25:
-                       cal_val = 1;
-                       break;
-               case TYPE_NONE:
-                       break;
-               default:
-                       dev_err(&pdev->dev, "Invalid calibration type, using none\n");
-               }
-               con |= cal_val << reg->calib_mode_shift;
-       }
-
        if (on) {
-               con |= (1 << reg->core_en_shift);
+               con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
                interrupt_en =
                        pdata->trigger_enable[3] << reg->inten_rise3_shift |
                        pdata->trigger_enable[2] << reg->inten_rise2_shift |
@@ -383,7 +321,7 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
                        interrupt_en |=
                                interrupt_en << reg->inten_fall0_shift;
        } else {
-               con &= ~(1 << reg->core_en_shift);
+               con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
                interrupt_en = 0; /* Disable all interrupts */
        }
        writel(interrupt_en, data->base + reg->tmu_inten);
@@ -404,8 +342,16 @@ static int exynos_tmu_read(struct exynos_tmu_data *data)
        clk_enable(data->clk);
 
        temp_code = readb(data->base + reg->tmu_cur_temp);
-       temp = code_to_temp(data, temp_code);
 
+       if (data->soc == SOC_ARCH_EXYNOS4210)
+               /* temp_code should range between 75 and 175 */
+               if (temp_code < 75 || temp_code > 175) {
+                       temp = -ENODATA;
+                       goto out;
+               }
+
+       temp = code_to_temp(data, temp_code);
+out:
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
 
@@ -465,7 +411,7 @@ static void exynos_tmu_work(struct work_struct *work)
                        struct exynos_tmu_data, irq_work);
        struct exynos_tmu_platform_data *pdata = data->pdata;
        const struct exynos_tmu_registers *reg = pdata->registers;
-       unsigned int val_irq, val_type;
+       unsigned int val_type;
 
        if (!IS_ERR(data->clk_sec))
                clk_enable(data->clk_sec);
@@ -483,9 +429,7 @@ static void exynos_tmu_work(struct work_struct *work)
        clk_enable(data->clk);
 
        /* TODO: take action based on particular interrupt */
-       val_irq = readl(data->base + reg->tmu_intstat);
-       /* clear the interrupts */
-       writel(val_irq, data->base + reg->tmu_intclear);
+       exynos_tmu_clear_irqs(data);
 
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
index 1b4a6444ea617574ae817b157f76d47329ddb2a7..c58c7663a3feaefec4f777d47220288976c95be5 100644 (file)
@@ -34,11 +34,6 @@ enum calibration_type {
        TYPE_NONE,
 };
 
-enum calibration_mode {
-       SW_MODE,
-       HW_MODE,
-};
-
 enum soc_type {
        SOC_ARCH_EXYNOS3250 = 1,
        SOC_ARCH_EXYNOS4210,
@@ -82,46 +77,19 @@ enum soc_type {
  * bitfields. The register validity, offsets and bitfield values may vary
  * slightly across different exynos SOC's.
  * @triminfo_data: register containing 2 pont trimming data
- * @triminfo_25_shift: shift bit of the 25 C trim value in triminfo_data reg.
- * @triminfo_85_shift: shift bit of the 85 C trim value in triminfo_data reg.
  * @triminfo_ctrl: trim info controller register.
- * @triminfo_reload_shift: shift of triminfo reload enable bit in triminfo_ctrl
-       reg.
+ * @triminfo_ctrl_count: the number of trim info controller register.
  * @tmu_ctrl: TMU main controller register.
  * @test_mux_addr_shift: shift bits of test mux address.
- * @buf_vref_sel_shift: shift bits of reference voltage in tmu_ctrl register.
- * @buf_vref_sel_mask: mask bits of reference voltage in tmu_ctrl register.
  * @therm_trip_mode_shift: shift bits of tripping mode in tmu_ctrl register.
  * @therm_trip_mode_mask: mask bits of tripping mode in tmu_ctrl register.
  * @therm_trip_en_shift: shift bits of tripping enable in tmu_ctrl register.
- * @buf_slope_sel_shift: shift bits of amplifier gain value in tmu_ctrl
-       register.
- * @buf_slope_sel_mask: mask bits of amplifier gain value in tmu_ctrl register.
- * @calib_mode_shift: shift bits of calibration mode value in tmu_ctrl
-       register.
- * @calib_mode_mask: mask bits of calibration mode value in tmu_ctrl
-       register.
- * @therm_trip_tq_en_shift: shift bits of thermal trip enable by TQ pin in
-       tmu_ctrl register.
- * @core_en_shift: shift bits of TMU core enable bit in tmu_ctrl register.
  * @tmu_status: register drescribing the TMU status.
  * @tmu_cur_temp: register containing the current temperature of the TMU.
- * @tmu_cur_temp_shift: shift bits of current temp value in tmu_cur_temp
-       register.
  * @threshold_temp: register containing the base threshold level.
  * @threshold_th0: Register containing first set of rising levels.
- * @threshold_th0_l0_shift: shift bits of level0 threshold temperature.
- * @threshold_th0_l1_shift: shift bits of level1 threshold temperature.
- * @threshold_th0_l2_shift: shift bits of level2 threshold temperature.
- * @threshold_th0_l3_shift: shift bits of level3 threshold temperature.
  * @threshold_th1: Register containing second set of rising levels.
- * @threshold_th1_l0_shift: shift bits of level0 threshold temperature.
- * @threshold_th1_l1_shift: shift bits of level1 threshold temperature.
- * @threshold_th1_l2_shift: shift bits of level2 threshold temperature.
- * @threshold_th1_l3_shift: shift bits of level3 threshold temperature.
  * @threshold_th2: Register containing third set of rising levels.
- * @threshold_th2_l0_shift: shift bits of level0 threshold temperature.
- * @threshold_th3: Register containing fourth set of rising levels.
  * @threshold_th3_l0_shift: shift bits of level0 threshold temperature.
  * @tmu_inten: register containing the different threshold interrupt
        enable bits.
@@ -130,68 +98,35 @@ enum soc_type {
  * @inten_rise2_shift: shift bits of rising 2 interrupt bits.
  * @inten_rise3_shift: shift bits of rising 3 interrupt bits.
  * @inten_fall0_shift: shift bits of falling 0 interrupt bits.
- * @inten_fall1_shift: shift bits of falling 1 interrupt bits.
- * @inten_fall2_shift: shift bits of falling 2 interrupt bits.
- * @inten_fall3_shift: shift bits of falling 3 interrupt bits.
  * @tmu_intstat: Register containing the interrupt status values.
  * @tmu_intclear: Register for clearing the raised interrupt status.
- * @intclr_fall_shift: shift bits for interrupt clear fall 0
- * @intclr_rise_shift: shift bits of all rising interrupt bits.
- * @intclr_rise_mask: mask bits of all rising interrupt bits.
- * @intclr_fall_mask: mask bits of all rising interrupt bits.
  * @emul_con: TMU emulation controller register.
  * @emul_temp_shift: shift bits of emulation temperature.
  * @emul_time_shift: shift bits of emulation time.
- * @emul_time_mask: mask bits of emulation time.
  * @tmu_irqstatus: register to find which TMU generated interrupts.
  * @tmu_pmin: register to get/set the Pmin value.
  */
 struct exynos_tmu_registers {
        u32     triminfo_data;
-       u32     triminfo_25_shift;
-       u32     triminfo_85_shift;
 
-       u32     triminfo_ctrl;
-       u32     triminfo_ctrl1;
-       u32     triminfo_reload_shift;
+       u32     triminfo_ctrl[MAX_TRIMINFO_CTRL_REG];
+       u32     triminfo_ctrl_count;
 
        u32     tmu_ctrl;
        u32     test_mux_addr_shift;
-       u32     buf_vref_sel_shift;
-       u32     buf_vref_sel_mask;
        u32     therm_trip_mode_shift;
        u32     therm_trip_mode_mask;
        u32     therm_trip_en_shift;
-       u32     buf_slope_sel_shift;
-       u32     buf_slope_sel_mask;
-       u32     calib_mode_shift;
-       u32     calib_mode_mask;
-       u32     therm_trip_tq_en_shift;
-       u32     core_en_shift;
 
        u32     tmu_status;
 
        u32     tmu_cur_temp;
-       u32     tmu_cur_temp_shift;
 
        u32     threshold_temp;
 
        u32     threshold_th0;
-       u32     threshold_th0_l0_shift;
-       u32     threshold_th0_l1_shift;
-       u32     threshold_th0_l2_shift;
-       u32     threshold_th0_l3_shift;
-
        u32     threshold_th1;
-       u32     threshold_th1_l0_shift;
-       u32     threshold_th1_l1_shift;
-       u32     threshold_th1_l2_shift;
-       u32     threshold_th1_l3_shift;
-
        u32     threshold_th2;
-       u32     threshold_th2_l0_shift;
-
-       u32     threshold_th3;
        u32     threshold_th3_l0_shift;
 
        u32     tmu_inten;
@@ -200,22 +135,14 @@ struct exynos_tmu_registers {
        u32     inten_rise2_shift;
        u32     inten_rise3_shift;
        u32     inten_fall0_shift;
-       u32     inten_fall1_shift;
-       u32     inten_fall2_shift;
-       u32     inten_fall3_shift;
 
        u32     tmu_intstat;
 
        u32     tmu_intclear;
-       u32     intclr_fall_shift;
-       u32     intclr_rise_shift;
-       u32     intclr_fall_mask;
-       u32     intclr_rise_mask;
 
        u32     emul_con;
        u32     emul_temp_shift;
        u32     emul_time_shift;
-       u32     emul_time_mask;
 
        u32     tmu_irqstatus;
        u32     tmu_pmin;
@@ -250,11 +177,12 @@ struct exynos_tmu_registers {
  *     1 = enable trigger_level[] interrupt,
  *     0 = disable trigger_level[] interrupt
  * @max_trigger_level: max trigger level supported by the TMU
+ * @non_hw_trigger_levels: number of defined non-hardware trigger levels
  * @gain: gain of amplifier in the positive-TC generator block
- *     0 <= gain <= 15
+ *     0 < gain <= 15
  * @reference_voltage: reference voltage of amplifier
  *     in the positive-TC generator block
- *     0 <= reference_voltage <= 31
+ *     0 < reference_voltage <= 31
  * @noise_cancel_mode: noise cancellation mode
  *     000, 100, 101, 110 and 111 can be different modes
  * @type: determines the type of SOC
@@ -265,8 +193,8 @@ struct exynos_tmu_registers {
  * @second_point_trim: temp value of the second point trimming
  * @default_temp_offset: default temperature offset in case of no trimming
  * @test_mux; information if SoC supports test MUX
+ * @triminfo_reload: reload value to read TRIMINFO register
  * @cal_type: calibration type for temperature
- * @cal_mode: calibration mode for temperature
  * @freq_clip_table: Table representing frequency reduction percentage.
  * @freq_tab_count: Count of the above table as frequency reduction may
  *     applicable to only some of the trigger levels.
@@ -284,6 +212,7 @@ struct exynos_tmu_platform_data {
        enum trigger_type trigger_type[MAX_TRIP_COUNT];
        bool trigger_enable[MAX_TRIP_COUNT];
        u8 max_trigger_level;
+       u8 non_hw_trigger_levels;
        u8 gain;
        u8 reference_voltage;
        u8 noise_cancel_mode;
@@ -295,9 +224,9 @@ struct exynos_tmu_platform_data {
        u8 second_point_trim;
        u8 default_temp_offset;
        u8 test_mux;
+       u8 triminfo_reload[MAX_TRIMINFO_CTRL_REG];
 
        enum calibration_type cal_type;
-       enum calibration_mode cal_mode;
        enum soc_type type;
        struct freq_clip_table freq_tab[4];
        unsigned int freq_tab_count;
index aa8e0dee2055d73c74719a912ef0595a1739ab9a..1724f6cdaef8f85603da7cbf99c225b0053dc055 100644 (file)
 #if defined(CONFIG_CPU_EXYNOS4210)
 static const struct exynos_tmu_registers exynos4210_tmu_registers = {
        .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
-       .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
-       .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
-       .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
-       .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
-       .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
-       .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
-       .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
        .tmu_status = EXYNOS_TMU_REG_STATUS,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
        .threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
@@ -46,7 +39,6 @@ static const struct exynos_tmu_registers exynos4210_tmu_registers = {
        .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
        .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
        .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
-       .intclr_rise_mask = EXYNOS4210_TMU_TRIG_LEVEL_MASK,
 };
 
 struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
@@ -64,6 +56,7 @@ struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
                .trigger_type[1] = THROTTLE_ACTIVE,
                .trigger_type[2] = SW_TRIP,
                .max_trigger_level = 4,
+               .non_hw_trigger_levels = 3,
                .gain = 15,
                .reference_voltage = 7,
                .cal_type = TYPE_ONE_POINT_TRIMMING,
@@ -93,18 +86,14 @@ struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
 #if defined(CONFIG_SOC_EXYNOS3250)
 static const struct exynos_tmu_registers exynos3250_tmu_registers = {
        .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
-       .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
-       .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
+       .triminfo_ctrl[0] = EXYNOS_TMU_TRIMINFO_CON1,
+       .triminfo_ctrl[1] = EXYNOS_TMU_TRIMINFO_CON2,
+       .triminfo_ctrl_count = 2,
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
        .test_mux_addr_shift = EXYNOS4412_MUX_ADDR_SHIFT,
-       .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
-       .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
        .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
        .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
        .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
-       .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
-       .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
-       .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
        .tmu_status = EXYNOS_TMU_REG_STATUS,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
        .threshold_th0 = EXYNOS_THD_TEMP_RISE,
@@ -116,14 +105,9 @@ static const struct exynos_tmu_registers exynos3250_tmu_registers = {
        .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
        .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
        .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
-       .intclr_fall_shift = EXYNOS_TMU_CLEAR_FALL_INT_SHIFT,
-       .intclr_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
-       .intclr_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
-       .intclr_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
        .emul_con = EXYNOS_EMUL_CON,
        .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
        .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
-       .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
 };
 
 #define EXYNOS3250_TMU_DATA \
@@ -141,6 +125,7 @@ static const struct exynos_tmu_registers exynos3250_tmu_registers = {
        .trigger_type[2] = SW_TRIP, \
        .trigger_type[3] = HW_TRIP, \
        .max_trigger_level = 4, \
+       .non_hw_trigger_levels = 3, \
        .gain = 8, \
        .reference_voltage = 16, \
        .noise_cancel_mode = 4, \
@@ -160,8 +145,10 @@ static const struct exynos_tmu_registers exynos3250_tmu_registers = {
                .temp_level = 95, \
        }, \
        .freq_tab_count = 2, \
+       .triminfo_reload[0] = EXYNOS_TRIMINFO_RELOAD_ENABLE, \
+       .triminfo_reload[1] = EXYNOS_TRIMINFO_RELOAD_ENABLE, \
        .registers = &exynos3250_tmu_registers, \
-       .features = (TMU_SUPPORT_EMULATION | \
+       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
                        TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
                        TMU_SUPPORT_EMUL_TIME)
 #endif
@@ -182,20 +169,13 @@ struct exynos_tmu_init_data const exynos3250_default_tmu_data = {
 #if defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
 static const struct exynos_tmu_registers exynos4412_tmu_registers = {
        .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
-       .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
-       .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
-       .triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
-       .triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
+       .triminfo_ctrl[0] = EXYNOS_TMU_TRIMINFO_CON2,
+       .triminfo_ctrl_count = 1,
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
        .test_mux_addr_shift = EXYNOS4412_MUX_ADDR_SHIFT,
-       .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
-       .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
        .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
        .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
        .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
-       .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
-       .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
-       .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
        .tmu_status = EXYNOS_TMU_REG_STATUS,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
        .threshold_th0 = EXYNOS_THD_TEMP_RISE,
@@ -208,14 +188,9 @@ static const struct exynos_tmu_registers exynos4412_tmu_registers = {
        .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
        .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
        .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
-       .intclr_fall_shift = EXYNOS_TMU_CLEAR_FALL_INT_SHIFT,
-       .intclr_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
-       .intclr_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
-       .intclr_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
        .emul_con = EXYNOS_EMUL_CON,
        .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
        .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
-       .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
 };
 
 #define EXYNOS4412_TMU_DATA \
@@ -233,6 +208,7 @@ static const struct exynos_tmu_registers exynos4412_tmu_registers = {
        .trigger_type[2] = SW_TRIP, \
        .trigger_type[3] = HW_TRIP, \
        .max_trigger_level = 4, \
+       .non_hw_trigger_levels = 3, \
        .gain = 8, \
        .reference_voltage = 16, \
        .noise_cancel_mode = 4, \
@@ -252,6 +228,7 @@ static const struct exynos_tmu_registers exynos4412_tmu_registers = {
                .temp_level = 95, \
        }, \
        .freq_tab_count = 2, \
+       .triminfo_reload[0] = EXYNOS_TRIMINFO_RELOAD_ENABLE, \
        .registers = &exynos4412_tmu_registers, \
        .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
                        TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
@@ -286,18 +263,10 @@ struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
 #if defined(CONFIG_SOC_EXYNOS5260)
 static const struct exynos_tmu_registers exynos5260_tmu_registers = {
        .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
-       .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
-       .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
-       .tmu_ctrl = EXYNOS_TMU_REG_CONTROL1,
-       .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
-       .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
        .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
        .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
        .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
-       .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
-       .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
-       .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
        .tmu_status = EXYNOS_TMU_REG_STATUS,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
        .threshold_th0 = EXYNOS_THD_TEMP_RISE,
@@ -310,14 +279,9 @@ static const struct exynos_tmu_registers exynos5260_tmu_registers = {
        .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
        .tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT,
        .tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR,
-       .intclr_fall_shift = EXYNOS5420_TMU_CLEAR_FALL_INT_SHIFT,
-       .intclr_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
-       .intclr_rise_mask = EXYNOS5260_TMU_RISE_INT_MASK,
-       .intclr_fall_mask = EXYNOS5260_TMU_FALL_INT_MASK,
        .emul_con = EXYNOS5260_EMUL_CON,
        .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
        .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
-       .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
 };
 
 #define __EXYNOS5260_TMU_DATA  \
@@ -335,6 +299,7 @@ static const struct exynos_tmu_registers exynos5260_tmu_registers = {
        .trigger_type[2] = SW_TRIP, \
        .trigger_type[3] = HW_TRIP, \
        .max_trigger_level = 4, \
+       .non_hw_trigger_levels = 3, \
        .gain = 8, \
        .reference_voltage = 16, \
        .noise_cancel_mode = 4, \
@@ -359,9 +324,8 @@ static const struct exynos_tmu_registers exynos5260_tmu_registers = {
 #define EXYNOS5260_TMU_DATA \
        __EXYNOS5260_TMU_DATA \
        .type = SOC_ARCH_EXYNOS5260, \
-       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
-                       TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
-                       TMU_SUPPORT_EMUL_TIME)
+       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
+                       TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME)
 
 struct exynos_tmu_init_data const exynos5260_default_tmu_data = {
        .tmu_data = {
@@ -378,17 +342,10 @@ struct exynos_tmu_init_data const exynos5260_default_tmu_data = {
 #if defined(CONFIG_SOC_EXYNOS5420)
 static const struct exynos_tmu_registers exynos5420_tmu_registers = {
        .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
-       .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
-       .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
        .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
-       .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
-       .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
        .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
        .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
        .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
-       .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
-       .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
-       .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
        .tmu_status = EXYNOS_TMU_REG_STATUS,
        .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
        .threshold_th0 = EXYNOS_THD_TEMP_RISE,
@@ -402,14 +359,9 @@ static const struct exynos_tmu_registers exynos5420_tmu_registers = {
        .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
        .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
        .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
-       .intclr_fall_shift = EXYNOS5420_TMU_CLEAR_FALL_INT_SHIFT,
-       .intclr_rise_shift = EXYNOS_TMU_RISE_INT_SHIFT,
-       .intclr_rise_mask = EXYNOS_TMU_RISE_INT_MASK,
-       .intclr_fall_mask = EXYNOS_TMU_FALL_INT_MASK,
        .emul_con = EXYNOS_EMUL_CON,
        .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
        .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
-       .emul_time_mask = EXYNOS_EMUL_TIME_MASK,
 };
 
 #define __EXYNOS5420_TMU_DATA  \
@@ -427,6 +379,7 @@ static const struct exynos_tmu_registers exynos5420_tmu_registers = {
        .trigger_type[2] = SW_TRIP, \
        .trigger_type[3] = HW_TRIP, \
        .max_trigger_level = 4, \
+       .non_hw_trigger_levels = 3, \
        .gain = 8, \
        .reference_voltage = 16, \
        .noise_cancel_mode = 4, \
@@ -451,16 +404,15 @@ static const struct exynos_tmu_registers exynos5420_tmu_registers = {
 #define EXYNOS5420_TMU_DATA \
        __EXYNOS5420_TMU_DATA \
        .type = SOC_ARCH_EXYNOS5250, \
-       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
-                       TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
-                       TMU_SUPPORT_EMUL_TIME)
+       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
+                       TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME)
 
 #define EXYNOS5420_TMU_DATA_SHARED \
        __EXYNOS5420_TMU_DATA \
        .type = SOC_ARCH_EXYNOS5420_TRIMINFO, \
-       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
-                       TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
-                       TMU_SUPPORT_EMUL_TIME | TMU_SUPPORT_ADDRESS_MULTIPLE)
+       .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
+                       TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME | \
+                       TMU_SUPPORT_ADDRESS_MULTIPLE)
 
 struct exynos_tmu_init_data const exynos5420_default_tmu_data = {
        .tmu_data = {
@@ -477,19 +429,10 @@ struct exynos_tmu_init_data const exynos5420_default_tmu_data = {
 #if defined(CONFIG_SOC_EXYNOS5440)
 static const struct exynos_tmu_registers exynos5440_tmu_registers = {
        .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
-       .triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
-       .triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
        .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
-       .buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
-       .buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
        .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
        .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
        .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
-       .buf_slope_sel_shift = EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT,
-       .buf_slope_sel_mask = EXYNOS_TMU_BUF_SLOPE_SEL_MASK,
-       .calib_mode_shift = EXYNOS_TMU_CALIB_MODE_SHIFT,
-       .calib_mode_mask = EXYNOS_TMU_CALIB_MODE_MASK,
-       .core_en_shift = EXYNOS_TMU_CORE_EN_SHIFT,
        .tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
        .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
        .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
@@ -504,10 +447,6 @@ static const struct exynos_tmu_registers exynos5440_tmu_registers = {
        .inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
        .tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
        .tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
-       .intclr_fall_shift = EXYNOS5440_TMU_CLEAR_FALL_INT_SHIFT,
-       .intclr_rise_shift = EXYNOS5440_TMU_RISE_INT_SHIFT,
-       .intclr_rise_mask = EXYNOS5440_TMU_RISE_INT_MASK,
-       .intclr_fall_mask = EXYNOS5440_TMU_FALL_INT_MASK,
        .tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
        .emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
        .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
@@ -521,11 +460,11 @@ static const struct exynos_tmu_registers exynos5440_tmu_registers = {
        .trigger_type[0] = SW_TRIP, \
        .trigger_type[4] = HW_TRIP, \
        .max_trigger_level = 5, \
+       .non_hw_trigger_levels = 1, \
        .gain = 5, \
        .reference_voltage = 16, \
        .noise_cancel_mode = 4, \
        .cal_type = TYPE_ONE_POINT_TRIMMING, \
-       .cal_mode = 0, \
        .efuse_value = 0x5b2d, \
        .min_efuse_value = 16, \
        .max_efuse_value = 76, \
index f0979e598491cc80f3bd0c3782090b06b172e223..63de598c9c2c3f9b8804110f086ed384991f547a 100644 (file)
 #define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT 8
 #define EXYNOS_TMU_CORE_EN_SHIFT       0
 
+/* Exynos3250 specific registers */
+#define EXYNOS_TMU_TRIMINFO_CON1       0x10
+
 /* Exynos4210 specific registers */
 #define EXYNOS4210_TMU_REG_THRESHOLD_TEMP      0x44
 #define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
-#define EXYNOS4210_TMU_REG_TRIG_LEVEL1 0x54
-#define EXYNOS4210_TMU_REG_TRIG_LEVEL2 0x58
-#define EXYNOS4210_TMU_REG_TRIG_LEVEL3 0x5C
-#define EXYNOS4210_TMU_REG_PAST_TEMP0  0x60
-#define EXYNOS4210_TMU_REG_PAST_TEMP1  0x64
-#define EXYNOS4210_TMU_REG_PAST_TEMP2  0x68
-#define EXYNOS4210_TMU_REG_PAST_TEMP3  0x6C
-
-#define EXYNOS4210_TMU_TRIG_LEVEL0_MASK        0x1
-#define EXYNOS4210_TMU_TRIG_LEVEL1_MASK        0x10
-#define EXYNOS4210_TMU_TRIG_LEVEL2_MASK        0x100
-#define EXYNOS4210_TMU_TRIG_LEVEL3_MASK        0x1000
-#define EXYNOS4210_TMU_TRIG_LEVEL_MASK 0x1111
-#define EXYNOS4210_TMU_INTCLEAR_VAL    0x1111
-
-/* Exynos5250 and Exynos4412 specific registers */
-#define EXYNOS_TMU_TRIMINFO_CON        0x14
+
+/* Exynos5250, Exynos4412, Exynos3250 specific registers */
+#define EXYNOS_TMU_TRIMINFO_CON2       0x14
 #define EXYNOS_THD_TEMP_RISE           0x50
 #define EXYNOS_THD_TEMP_FALL           0x54
 #define EXYNOS_EMUL_CON                0x80
 
-#define EXYNOS_TRIMINFO_RELOAD_SHIFT   1
+#define EXYNOS_TRIMINFO_RELOAD_ENABLE  1
 #define EXYNOS_TRIMINFO_25_SHIFT       0
 #define EXYNOS_TRIMINFO_85_SHIFT       8
-#define EXYNOS_TMU_RISE_INT_MASK       0x111
-#define EXYNOS_TMU_RISE_INT_SHIFT      0
-#define EXYNOS_TMU_FALL_INT_MASK       0x111
-#define EXYNOS_TMU_CLEAR_RISE_INT      0x111
-#define EXYNOS_TMU_CLEAR_FALL_INT      (0x111 << 12)
-#define EXYNOS_TMU_CLEAR_FALL_INT_SHIFT        12
-#define EXYNOS5420_TMU_CLEAR_FALL_INT_SHIFT    16
-#define EXYNOS5440_TMU_CLEAR_FALL_INT_SHIFT    4
 #define EXYNOS_TMU_TRIP_MODE_SHIFT     13
 #define EXYNOS_TMU_TRIP_MODE_MASK      0x7
 #define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12
-#define EXYNOS_TMU_CALIB_MODE_SHIFT    4
-#define EXYNOS_TMU_CALIB_MODE_MASK     0x3
 
 #define EXYNOS_TMU_INTEN_RISE0_SHIFT   0
 #define EXYNOS_TMU_INTEN_RISE1_SHIFT   4
 #define EXYNOS_TMU_INTEN_RISE2_SHIFT   8
 #define EXYNOS_TMU_INTEN_RISE3_SHIFT   12
 #define EXYNOS_TMU_INTEN_FALL0_SHIFT   16
-#define EXYNOS_TMU_INTEN_FALL1_SHIFT   20
-#define EXYNOS_TMU_INTEN_FALL2_SHIFT   24
-#define EXYNOS_TMU_INTEN_FALL3_SHIFT   28
 
 #define EXYNOS_EMUL_TIME       0x57F0
 #define EXYNOS_EMUL_TIME_MASK  0xffff
 #define EXYNOS_MAX_TRIGGER_PER_REG     4
 
 /* Exynos5260 specific */
-#define EXYNOS_TMU_REG_CONTROL1                        0x24
 #define EXYNOS5260_TMU_REG_INTEN               0xC0
 #define EXYNOS5260_TMU_REG_INTSTAT             0xC4
 #define EXYNOS5260_TMU_REG_INTCLEAR            0xC8
-#define EXYNOS5260_TMU_CLEAR_RISE_INT          0x1111
-#define EXYNOS5260_TMU_CLEAR_FALL_INT          (0x1111 << 16)
-#define EXYNOS5260_TMU_RISE_INT_MASK           0x1111
-#define EXYNOS5260_TMU_FALL_INT_MASK           0x1111
 #define EXYNOS5260_EMUL_CON                    0x100
 
 /* Exynos4412 specific */
 #define EXYNOS5440_TMU_S0_7_TH0                        0x110
 #define EXYNOS5440_TMU_S0_7_TH1                        0x130
 #define EXYNOS5440_TMU_S0_7_TH2                        0x150
-#define EXYNOS5440_TMU_S0_7_EVTEN              0x1F0
 #define EXYNOS5440_TMU_S0_7_IRQEN              0x210
 #define EXYNOS5440_TMU_S0_7_IRQ                        0x230
 /* exynos5440 common registers */
 #define EXYNOS5440_TMU_IRQ_STATUS              0x000
 #define EXYNOS5440_TMU_PMIN                    0x004
-#define EXYNOS5440_TMU_TEMP                    0x008
 
-#define EXYNOS5440_TMU_RISE_INT_MASK           0xf
-#define EXYNOS5440_TMU_RISE_INT_SHIFT          0
-#define EXYNOS5440_TMU_FALL_INT_MASK           0xf
 #define EXYNOS5440_TMU_INTEN_RISE0_SHIFT       0
 #define EXYNOS5440_TMU_INTEN_RISE1_SHIFT       1
 #define EXYNOS5440_TMU_INTEN_RISE2_SHIFT       2
 #define EXYNOS5440_TMU_INTEN_RISE3_SHIFT       3
 #define EXYNOS5440_TMU_INTEN_FALL0_SHIFT       4
-#define EXYNOS5440_TMU_INTEN_FALL1_SHIFT       5
-#define EXYNOS5440_TMU_INTEN_FALL2_SHIFT       6
-#define EXYNOS5440_TMU_INTEN_FALL3_SHIFT       7
-#define EXYNOS5440_TMU_TH_RISE0_SHIFT          0
-#define EXYNOS5440_TMU_TH_RISE1_SHIFT          8
-#define EXYNOS5440_TMU_TH_RISE2_SHIFT          16
-#define EXYNOS5440_TMU_TH_RISE3_SHIFT          24
 #define EXYNOS5440_TMU_TH_RISE4_SHIFT          24
 #define EXYNOS5440_EFUSE_SWAP_OFFSET           8
 
index 90163b384660247b343d9fc551dfe067128d6219..d1ec5804c0bb94cebeb22d5038b4861393047ba0 100644 (file)
@@ -275,6 +275,7 @@ int st_thermal_unregister(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(st_thermal_unregister);
 
+#ifdef CONFIG_PM_SLEEP
 static int st_thermal_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -305,6 +306,8 @@ static int st_thermal_resume(struct device *dev)
 
        return 0;
 }
+#endif
+
 SIMPLE_DEV_PM_OPS(st_thermal_pm_ops, st_thermal_suspend, st_thermal_resume);
 EXPORT_SYMBOL_GPL(st_thermal_pm_ops);
 
index f251521baaa24b21c23c50b2a4bb18e4abc810c9..fdd1f523a1eda4e94110e12dac531c218837dc08 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/thermal.h>
+#include <trace/events/thermal.h>
 
 #include "thermal_core.h"
 
@@ -76,7 +77,7 @@ static unsigned long get_target_state(struct thermal_instance *instance,
                        next_target = instance->upper;
                break;
        case THERMAL_TREND_DROPPING:
-               if (cur_state == instance->lower) {
+               if (cur_state <= instance->lower) {
                        if (!throttle)
                                next_target = THERMAL_NO_TARGET;
                } else {
@@ -129,8 +130,10 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
 
        trend = get_tz_trend(tz, trip);
 
-       if (tz->temperature >= trip_temp)
+       if (tz->temperature >= trip_temp) {
                throttle = true;
+               trace_thermal_zone_trip(tz, trip, trip_type);
+       }
 
        dev_dbg(&tz->device, "Trip%d[type=%d,temp=%ld]:trend=%d,throttle=%d\n",
                                trip, trip_type, trip_temp, trend, throttle);
index 1e23f4f8d2c2099cc2f634010e4ff8ff2c2db11c..43b90709585ff294713e299cca1b6cdac406c098 100644 (file)
@@ -38,6 +38,9 @@
 #include <net/netlink.h>
 #include <net/genetlink.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/thermal.h>
+
 #include "thermal_core.h"
 #include "thermal_hwmon.h"
 
@@ -368,6 +371,8 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
        if (tz->temperature < trip_temp)
                return;
 
+       trace_thermal_zone_trip(tz, trip, trip_type);
+
        if (tz->ops->notify)
                tz->ops->notify(tz, trip, trip_type);
 
@@ -463,6 +468,7 @@ static void update_temperature(struct thermal_zone_device *tz)
        tz->temperature = temp;
        mutex_unlock(&tz->lock);
 
+       trace_thermal_temperature(tz);
        dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
                                tz->last_temperature, tz->temperature);
 }
@@ -1287,6 +1293,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
        mutex_unlock(&cdev->lock);
        cdev->ops->set_cur_state(cdev, target);
        cdev->updated = true;
+       trace_cdev_update(cdev, target);
        dev_dbg(&cdev->device, "set to state %lu\n", target);
 }
 EXPORT_SYMBOL(thermal_cdev_update);
@@ -1568,8 +1575,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
 
        thermal_zone_device_update(tz);
 
-       if (!result)
-               return tz;
+       return tz;
 
 unregister:
        release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
@@ -1790,6 +1796,10 @@ static int __init thermal_register_governors(void)
        if (result)
                return result;
 
+       result = thermal_gov_bang_bang_register();
+       if (result)
+               return result;
+
        return thermal_gov_user_space_register();
 }
 
@@ -1797,6 +1807,7 @@ static void thermal_unregister_governors(void)
 {
        thermal_gov_step_wise_unregister();
        thermal_gov_fair_share_unregister();
+       thermal_gov_bang_bang_unregister();
        thermal_gov_user_space_unregister();
 }
 
index 3db339fb636f375f9be670bd6f827776ed8d017d..d15d243de27a7f9386e37302084a8574566c13aa 100644 (file)
@@ -69,6 +69,14 @@ static inline int thermal_gov_fair_share_register(void) { return 0; }
 static inline void thermal_gov_fair_share_unregister(void) {}
 #endif /* CONFIG_THERMAL_GOV_FAIR_SHARE */
 
+#ifdef CONFIG_THERMAL_GOV_BANG_BANG
+int thermal_gov_bang_bang_register(void);
+void thermal_gov_bang_bang_unregister(void);
+#else
+static inline int thermal_gov_bang_bang_register(void) { return 0; }
+static inline void thermal_gov_bang_bang_unregister(void) {}
+#endif /* CONFIG_THERMAL_GOV_BANG_BANG */
+
 #ifdef CONFIG_THERMAL_GOV_USER_SPACE
 int thermal_gov_user_space_register(void);
 void thermal_gov_user_space_unregister(void);
index 89c4cee253e34419006b670089cc54b0257dde52..26f097f60b104630ae49304abc6cb95d92fa1e22 100644 (file)
@@ -2123,7 +2123,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 {
        struct n_tty_data *ldata = tty->disc_data;
        unsigned char __user *b = buf;
-       DECLARE_WAITQUEUE(wait, current);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
        int c;
        int minimum, time;
        ssize_t retval = 0;
@@ -2186,10 +2186,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
                        nr--;
                        break;
                }
-               /* This statement must be first before checking for input
-                  so that any interrupt will set the state back to
-                  TASK_RUNNING. */
-               set_current_state(TASK_INTERRUPTIBLE);
 
                if (((minimum - (b - buf)) < ldata->minimum_to_wake) &&
                    ((minimum - (b - buf)) >= 1))
@@ -2220,13 +2216,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
                                n_tty_set_room(tty);
                                up_read(&tty->termios_rwsem);
 
-                               timeout = schedule_timeout(timeout);
+                               timeout = wait_woken(&wait, TASK_INTERRUPTIBLE,
+                                                    timeout);
 
                                down_read(&tty->termios_rwsem);
                                continue;
                        }
                }
-               __set_current_state(TASK_RUNNING);
 
                /* Deal with packet mode. */
                if (packet && b == buf) {
@@ -2273,7 +2269,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 
        mutex_unlock(&ldata->atomic_read_lock);
 
-       __set_current_state(TASK_RUNNING);
        if (b - buf)
                retval = b - buf;
 
@@ -2306,7 +2301,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
                           const unsigned char *buf, size_t nr)
 {
        const unsigned char *b = buf;
-       DECLARE_WAITQUEUE(wait, current);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
        int c;
        ssize_t retval = 0;
 
@@ -2324,7 +2319,6 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
 
        add_wait_queue(&tty->write_wait, &wait);
        while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
                if (signal_pending(current)) {
                        retval = -ERESTARTSYS;
                        break;
@@ -2378,12 +2372,11 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
                }
                up_read(&tty->termios_rwsem);
 
-               schedule();
+               wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
 
                down_read(&tty->termios_rwsem);
        }
 break_out:
-       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&tty->write_wait, &wait);
        if (b - buf != nr && tty->fasync)
                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
@@ -2413,12 +2406,17 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
 
        poll_wait(file, &tty->read_wait, wait);
        poll_wait(file, &tty->write_wait, wait);
+       if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
+               mask |= POLLHUP;
        if (input_available_p(tty, 1))
                mask |= POLLIN | POLLRDNORM;
+       else if (mask & POLLHUP) {
+               tty_flush_to_ldisc(tty);
+               if (input_available_p(tty, 1))
+                       mask |= POLLIN | POLLRDNORM;
+       }
        if (tty->packet && tty->link->ctrl_status)
                mask |= POLLPRI | POLLIN | POLLRDNORM;
-       if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
-               mask |= POLLHUP;
        if (tty_hung_up_p(file))
                mask |= POLLHUP;
        if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
index 8f37d57165ecf49866b839c301fe1759c34551a9..de7aae523b3728c10abc6c4000bd9b5f44786083 100644 (file)
@@ -81,7 +81,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
                /* Set to highest baudrate supported */
                if (baud >= 1152000)
                        baud = 921600;
-               quot = DIV_ROUND_CLOSEST(port->uartclk, 256 * baud);
+               quot = (port->uartclk / (256 * baud)) + 1;
        }
 
        /*
index 649b784081c7a815b82fff2dbd51b33619e9d742..98f8bcaf3e7e3c3d3d8780bb05e1301f255e11f8 100644 (file)
@@ -249,14 +249,14 @@ config SERIAL_SAMSUNG
 
 config SERIAL_SAMSUNG_UARTS_4
        bool
-       depends on PLAT_SAMSUNG
+       depends on SERIAL_SAMSUNG
        default y if !(CPU_S3C2410 || CPU_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
        help
          Internal node for the common case of 4 Samsung compatible UARTs
 
 config SERIAL_SAMSUNG_UARTS
        int
-       depends on PLAT_SAMSUNG
+       depends on SERIAL_SAMSUNG
        default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
        default 3
        help
index 8bc2563335ae34ba2ae45bf55117c808d0b219c5..bf355050eab695f50c6220589faf69a0b9e3b6b6 100644 (file)
@@ -158,7 +158,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
        if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
                return -EBUSY;
 
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (info == NULL)
                return -ENOMEM;
 
@@ -240,32 +240,6 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int of_serial_suspend(struct device *dev)
-{
-       struct of_serial_info *info = dev_get_drvdata(dev);
-
-       serial8250_suspend_port(info->line);
-       if (info->clk)
-               clk_disable_unprepare(info->clk);
-
-       return 0;
-}
-
-static int of_serial_resume(struct device *dev)
-{
-       struct of_serial_info *info = dev_get_drvdata(dev);
-
-       if (info->clk)
-               clk_prepare_enable(info->clk);
-
-       serial8250_resume_port(info->line);
-
-       return 0;
-}
-#endif
-static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume);
-
 /*
  * A few common types, add more as needed.
  */
@@ -297,7 +271,6 @@ static struct platform_driver of_platform_serial_driver = {
                .name = "of_serial",
                .owner = THIS_MODULE,
                .of_match_table = of_platform_serial_table,
-               .pm = &of_serial_pm_ops,
        },
        .probe = of_platform_serial_probe,
        .remove = of_platform_serial_remove,
index df3a8c74358e45644765da1593d19ffd44d6664a..eaeb9a02c7feace54a99df7acc6bf9544b6bc512 100644 (file)
@@ -363,7 +363,7 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
                 * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
                 * Die! Die! Die!
                 */
-               if (baud == 38400)
+               if (try == 0 && baud == 38400)
                        baud = altbaud;
 
                /*
index 16a2c0237dd60a06513e2ad1f616e13a7bd71c0b..0508a1d8e4cd73a7b679f9cc70d2e19f0716b69a 100644 (file)
@@ -1709,6 +1709,8 @@ int tty_release(struct inode *inode, struct file *filp)
        int     pty_master, tty_closing, o_tty_closing, do_sleep;
        int     idx;
        char    buf[64];
+       long    timeout = 0;
+       int     once = 1;
 
        if (tty_paranoia_check(tty, inode, __func__))
                return 0;
@@ -1789,11 +1791,18 @@ int tty_release(struct inode *inode, struct file *filp)
                if (!do_sleep)
                        break;
 
-               printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
-                               __func__, tty_name(tty, buf));
+               if (once) {
+                       once = 0;
+                       printk(KERN_WARNING "%s: %s: read/write wait queue active!\n",
+                              __func__, tty_name(tty, buf));
+               }
                tty_unlock_pair(tty, o_tty);
                mutex_unlock(&tty_mutex);
-               schedule();
+               schedule_timeout_killable(timeout);
+               if (timeout < 120 * HZ)
+                       timeout = 2 * timeout + 1;
+               else
+                       timeout = MAX_SCHEDULE_TIMEOUT;
        }
 
        /*
index 610b720d3b91789b6f55c618b08535d53edc99c3..59b25e039968596372764e9c5ddd6b92f1a8e045 100644 (file)
@@ -539,6 +539,12 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
 
        /* Save original vc_unipagdir_loc in case we allocate a new one */
        p = *vc->vc_uni_pagedir_loc;
+
+       if (!p) {
+               err = -EINVAL;
+
+               goto out_unlock;
+       }
        
        if (p->refcount > 1) {
                int j, k;
@@ -623,6 +629,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
                set_inverse_transl(vc, p, i); /* Update inverse translations */
        set_inverse_trans_unicode(vc, p);
 
+out_unlock:
        console_unlock();
        return err;
 }
index a673e5b6a2e0b7500cdf6f101b5467f4a8e58da2..60fa6278fbceffd460890de52e50c9c31ade080c 100644 (file)
 
 #define UIO_MAX_DEVICES                (1U << MINORBITS)
 
-struct uio_device {
-       struct module           *owner;
-       struct device           *dev;
-       int                     minor;
-       atomic_t                event;
-       struct fasync_struct    *async_queue;
-       wait_queue_head_t       wait;
-       struct uio_info         *info;
-       struct kobject          *map_dir;
-       struct kobject          *portio_dir;
-};
-
 static int uio_major;
 static struct cdev *uio_cdev;
 static DEFINE_IDR(uio_idr);
index 3df5005c554d2bbd655544fa046cbfb346b4c0a9..9bdc6bd73432cd1c39f371f589dd5bbab3a797bc 100644 (file)
@@ -742,7 +742,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
        ci_role_destroy(ci);
        ci_hdrc_enter_lpm(ci, true);
        usb_phy_shutdown(ci->transceiver);
-       kfree(ci->hw_bank.regmap);
 
        return 0;
 }
index e934e19f49f57e3e463c31c65caa76cca3fee905..077d58ac3dcba6db7b4ed554cac493e74a6de71a 100644 (file)
@@ -60,6 +60,9 @@ static struct acm *acm_table[ACM_TTY_MINORS];
 
 static DEFINE_MUTEX(acm_table_lock);
 
+static void acm_tty_set_termios(struct tty_struct *tty,
+                               struct ktermios *termios_old);
+
 /*
  * acm_table accessors
  */
@@ -145,8 +148,15 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value,
 /* devices aren't required to support these requests.
  * the cdc acm descriptor tells whether they do...
  */
-#define acm_set_control(acm, control) \
-       acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0)
+static inline int acm_set_control(struct acm *acm, int control)
+{
+       if (acm->quirks & QUIRK_CONTROL_LINE_STATE)
+               return -EOPNOTSUPP;
+
+       return acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE,
+                       control, NULL, 0);
+}
+
 #define acm_set_line(acm, line) \
        acm_ctrl_msg(acm, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line))
 #define acm_send_break(acm, ms) \
@@ -554,6 +564,8 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
                goto error_submit_urb;
        }
 
+       acm_tty_set_termios(tty, NULL);
+
        /*
         * Unthrottle device in case the TTY was closed while throttled.
         */
@@ -980,11 +992,12 @@ static void acm_tty_set_termios(struct tty_struct *tty,
        /* FIXME: Needs to clear unsupported bits in the termios */
        acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
 
-       if (!newline.dwDTERate) {
+       if (C_BAUD(tty) == B0) {
                newline.dwDTERate = acm->line.dwDTERate;
                newctrl &= ~ACM_CTRL_DTR;
-       } else
+       } else if (termios_old && (termios_old->c_cflag & CBAUD) == B0) {
                newctrl |=  ACM_CTRL_DTR;
+       }
 
        if (newctrl != acm->ctrlout)
                acm_set_control(acm, acm->ctrlout = newctrl);
@@ -1314,6 +1327,7 @@ made_compressed_probe:
        tty_port_init(&acm->port);
        acm->port.ops = &acm_port_ops;
        init_usb_anchor(&acm->delayed);
+       acm->quirks = quirks;
 
        buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
        if (!buf) {
@@ -1681,6 +1695,9 @@ static const struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
+       { USB_DEVICE(0x20df, 0x0001), /* Simtec Electronics Entropy Key */
+       .driver_info = QUIRK_CONTROL_LINE_STATE, },
+       { USB_DEVICE(0x2184, 0x001c) }, /* GW Instek AFG-2225 */
        { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
        },
        /* Motorola H24 HSPA module: */
index fc75651afe1c9cda8983aa82dfa8b81cfa3fb5bf..d3251ebd09e2e0bc46effe8b77503c524d12a7d4 100644 (file)
@@ -121,6 +121,7 @@ struct acm {
        unsigned int throttle_req:1;                    /* throttle requested */
        u8 bInterval;
        struct usb_anchor delayed;                      /* writes queued for a device about to be woken */
+       unsigned long quirks;
 };
 
 #define CDC_DATA_INTERFACE_TYPE        0x0a
@@ -132,3 +133,4 @@ struct acm {
 #define NOT_A_MODEM                    BIT(3)
 #define NO_DATA_INTERFACE              BIT(4)
 #define IGNORE_DEVICE                  BIT(5)
+#define QUIRK_CONTROL_LINE_STATE       BIT(6)
index b84fb141e122f7f0d60d9e4ba09642c7c9e15492..a6efb4184f2b4cf0a021b457b8e1d4fcccb30d56 100644 (file)
@@ -2060,6 +2060,8 @@ int usb_alloc_streams(struct usb_interface *interface,
                return -EINVAL;
        if (dev->speed != USB_SPEED_SUPER)
                return -EINVAL;
+       if (dev->state < USB_STATE_CONFIGURED)
+               return -ENODEV;
 
        for (i = 0; i < num_eps; i++) {
                /* Streams only apply to bulk endpoints. */
index 11e80ac313244289e3a7425fb16acc6b0c0e562e..b649fef2e35d4af1e9e8a206e73c0ed799049a1b 100644 (file)
@@ -4468,9 +4468,6 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        if (retval)
                goto fail;
 
-       if (hcd->usb_phy && !hdev->parent)
-               usb_phy_notify_connect(hcd->usb_phy, udev->speed);
-
        /*
         * Some superspeed devices have finished the link training process
         * and attached to a superspeed hub port, but the device descriptor
@@ -4627,8 +4624,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
 
        /* Disconnect any existing devices under this port */
        if (udev) {
-               if (hcd->usb_phy && !hdev->parent &&
-                               !(portstatus & USB_PORT_STAT_CONNECTION))
+               if (hcd->usb_phy && !hdev->parent)
                        usb_phy_notify_disconnect(hcd->usb_phy, udev->speed);
                usb_disconnect(&port_dev->child);
        }
@@ -4783,6 +4779,10 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
                                port_dev->child = NULL;
                                spin_unlock_irq(&device_state_lock);
                                mutex_unlock(&usb_port_peer_mutex);
+                       } else {
+                               if (hcd->usb_phy && !hdev->parent)
+                                       usb_phy_notify_connect(hcd->usb_phy,
+                                                       udev->speed);
                        }
                }
 
index 5ae883dc21f50f1b4e47fb68fa3255fea1940aa1..96fafed92b76b0972401a13b4eb67a5b1dfdddb1 100644 (file)
@@ -44,6 +44,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Creative SB Audigy 2 NX */
        { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Microsoft Wireless Laser Mouse 6000 Receiver */
+       { USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Microsoft LifeCam-VX700 v2.0 */
        { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -97,6 +100,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x04f3, 0x0089), .driver_info =
                        USB_QUIRK_DEVICE_QUALIFIER },
 
+       { USB_DEVICE(0x04f3, 0x009b), .driver_info =
+                       USB_QUIRK_DEVICE_QUALIFIER },
+
+       { USB_DEVICE(0x04f3, 0x016f), .driver_info =
+                       USB_QUIRK_DEVICE_QUALIFIER },
+
        /* Roland SC-8820 */
        { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
 
index bf015ab3b44c80ae76631b3d63268a0701ef5707..55c90c53f2d6b6c3534df4e734ad3e8fea03277e 100644 (file)
@@ -619,7 +619,7 @@ struct dwc2_hsotg {
                        unsigned port_suspend_change:1;
                        unsigned port_over_current_change:1;
                        unsigned port_l1_change:1;
-                       unsigned reserved:26;
+                       unsigned reserved:25;
                } b;
        } flags;
 
index 7b5856fadd93f350ddaaeb2dda9e63be534987e6..8b5c079c7b7dde3fb1eb0e9739e117a835c23176 100644 (file)
@@ -2327,7 +2327,7 @@ irq_retry:
 
                u32 usb_status = readl(hsotg->regs + GOTGCTL);
 
-               dev_info(hsotg->dev, "%s: USBRst\n", __func__);
+               dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
                dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
                        readl(hsotg->regs + GNPTXSTS));
 
@@ -2561,8 +2561,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
                        hs_ep->fifo_size = val;
                        break;
                }
-               if (i == 8)
-                       return -ENOMEM;
+               if (i == 8) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
        }
 
        /* for non control endpoints, set PID to D0 */
@@ -2579,6 +2581,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
        /* enable the endpoint interrupt */
        s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
 
+error:
        spin_unlock_irqrestore(&hsotg->lock, flags);
        return ret;
 }
@@ -2934,9 +2937,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 
        spin_lock_irqsave(&hsotg->lock, flags);
 
-       if (!driver)
-               hsotg->driver = NULL;
-
+       hsotg->driver = NULL;
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -3567,6 +3568,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
                s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
 
        /* disable power and clock */
+       s3c_hsotg_phy_disable(hsotg);
 
        ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
                                    hsotg->supplies);
@@ -3575,8 +3577,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
                goto err_ep_mem;
        }
 
-       s3c_hsotg_phy_disable(hsotg);
-
        ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
        if (ret)
                goto err_ep_mem;
index 2f537d588225fd11bcab9c5b827ad488a1d93f22..a0aa9f3da441381736fcad46eca794b482653340 100644 (file)
@@ -597,7 +597,7 @@ static int dwc3_omap_prepare(struct device *dev)
 {
        struct dwc3_omap        *omap = dev_get_drvdata(dev);
 
-       dwc3_omap_write_irqmisc_set(omap, 0x00);
+       dwc3_omap_disable_irqs(omap);
 
        return 0;
 }
@@ -605,19 +605,8 @@ static int dwc3_omap_prepare(struct device *dev)
 static void dwc3_omap_complete(struct device *dev)
 {
        struct dwc3_omap        *omap = dev_get_drvdata(dev);
-       u32                     reg;
 
-       reg = (USBOTGSS_IRQMISC_OEVT |
-                       USBOTGSS_IRQMISC_DRVVBUS_RISE |
-                       USBOTGSS_IRQMISC_CHRGVBUS_RISE |
-                       USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
-                       USBOTGSS_IRQMISC_IDPULLUP_RISE |
-                       USBOTGSS_IRQMISC_DRVVBUS_FALL |
-                       USBOTGSS_IRQMISC_CHRGVBUS_FALL |
-                       USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
-                       USBOTGSS_IRQMISC_IDPULLUP_FALL);
-
-       dwc3_omap_write_irqmisc_set(omap, reg);
+       dwc3_omap_enable_irqs(omap);
 }
 
 static int dwc3_omap_suspend(struct device *dev)
index 436fb08c40b8785f16e224241039e7c63899fde9..a36cf66302fbe56e06f6ed20451b8c008479b0d2 100644 (file)
@@ -30,6 +30,7 @@
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3        0xabcd
 #define PCI_DEVICE_ID_INTEL_BYT                0x0f37
 #define PCI_DEVICE_ID_INTEL_MRFLD      0x119e
+#define PCI_DEVICE_ID_INTEL_BSW                0x22B7
 
 struct dwc3_pci {
        struct device           *dev;
@@ -181,6 +182,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
                                PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
        },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
        {  }    /* Terminating Entry */
index b35938777ddeaa03954bb567fb1fb0cf096b5982..df38e7ef49761ce87f3532c37c556a1399ab8199 100644 (file)
@@ -256,7 +256,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
 
        /* stall is always issued on EP0 */
        dep = dwc->eps[0];
-       __dwc3_gadget_ep_set_halt(dep, 1);
+       __dwc3_gadget_ep_set_halt(dep, 1, false);
        dep->flags = DWC3_EP_ENABLED;
        dwc->delayed_status = false;
 
@@ -271,7 +271,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
        dwc3_ep0_out_start(dwc);
 }
 
-int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
+int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
 {
        struct dwc3_ep                  *dep = to_dwc3_ep(ep);
        struct dwc3                     *dwc = dep->dwc;
@@ -281,6 +281,20 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
        return 0;
 }
 
+int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
+{
+       struct dwc3_ep                  *dep = to_dwc3_ep(ep);
+       struct dwc3                     *dwc = dep->dwc;
+       unsigned long                   flags;
+       int                             ret;
+
+       spin_lock_irqsave(&dwc->lock, flags);
+       ret = __dwc3_gadget_ep0_set_halt(ep, value);
+       spin_unlock_irqrestore(&dwc->lock, flags);
+
+       return ret;
+}
+
 void dwc3_ep0_out_start(struct dwc3 *dwc)
 {
        int                             ret;
@@ -466,7 +480,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                                return -EINVAL;
                        if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
                                break;
-                       ret = __dwc3_gadget_ep_set_halt(dep, set);
+                       ret = __dwc3_gadget_ep_set_halt(dep, set, true);
                        if (ret)
                                return -EINVAL;
                        break;
@@ -775,11 +789,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 
        dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
 
-       r = next_request(&ep0->request_list);
-       ur = &r->request;
-
        trb = dwc->ep0_trb;
 
+       r = next_request(&ep0->request_list);
+       if (!r)
+               return;
+
        status = DWC3_TRB_SIZE_TRBSTS(trb->size);
        if (status == DWC3_TRBSTS_SETUP_PENDING) {
                dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
@@ -790,6 +805,8 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
                return;
        }
 
+       ur = &r->request;
+
        length = trb->size & DWC3_TRB_SIZE_MASK;
 
        if (dwc->ep0_bounced) {
@@ -811,12 +828,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 
                dwc3_ep0_stall_and_restart(dwc);
        } else {
-               /*
-                * handle the case where we have to send a zero packet. This
-                * seems to be case when req.length > maxpacket. Could it be?
-                */
-               if (r)
-                       dwc3_gadget_giveback(ep0, r, 0);
+               dwc3_gadget_giveback(ep0, r, 0);
+
+               if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
+                               ur->length && ur->zero) {
+                       int ret;
+
+                       dwc->ep0_next_event = DWC3_EP0_COMPLETE;
+
+                       ret = dwc3_ep0_start_trans(dwc, epnum,
+                                       dwc->ctrl_req_addr, 0,
+                                       DWC3_TRBCTL_CONTROL_DATA);
+                       WARN_ON(ret < 0);
+               }
        }
 }
 
index 3818b26bfc05abf744f50bcc6266d49b0e83dfb3..546ea5431b8cd225165b38ca0e5ff2b53906738c 100644 (file)
@@ -525,12 +525,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
                if (!usb_endpoint_xfer_isoc(desc))
                        return 0;
 
-               memset(&trb_link, 0, sizeof(trb_link));
-
                /* Link TRB for ISOC. The HWO bit is never reset */
                trb_st_hw = &dep->trb_pool[0];
 
                trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1];
+               memset(trb_link, 0, sizeof(*trb_link));
 
                trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
                trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
@@ -581,7 +580,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
        /* make sure HW endpoint isn't stalled */
        if (dep->flags & DWC3_EP_STALL)
-               __dwc3_gadget_ep_set_halt(dep, 0);
+               __dwc3_gadget_ep_set_halt(dep, 0, false);
 
        reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
        reg &= ~DWC3_DALEPENA_EP(dep->number);
@@ -1202,15 +1201,28 @@ out0:
        return ret;
 }
 
-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value)
+int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
 {
        struct dwc3_gadget_ep_cmd_params        params;
        struct dwc3                             *dwc = dep->dwc;
        int                                     ret;
 
+       if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+               dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
+               return -EINVAL;
+       }
+
        memset(&params, 0x00, sizeof(params));
 
        if (value) {
+               if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) ||
+                               (!list_empty(&dep->req_queued) ||
+                                !list_empty(&dep->request_list)))) {
+                       dev_dbg(dwc->dev, "%s: pending request, cannot halt\n",
+                                       dep->name);
+                       return -EAGAIN;
+               }
+
                ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
                        DWC3_DEPCMD_SETSTALL, &params);
                if (ret)
@@ -1241,15 +1253,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
        int                             ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
-
-       if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-               dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = __dwc3_gadget_ep_set_halt(dep, value);
-out:
+       ret = __dwc3_gadget_ep_set_halt(dep, value, false);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return ret;
@@ -1260,15 +1264,18 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
        struct dwc3_ep                  *dep = to_dwc3_ep(ep);
        struct dwc3                     *dwc = dep->dwc;
        unsigned long                   flags;
+       int                             ret;
 
        spin_lock_irqsave(&dwc->lock, flags);
        dep->flags |= DWC3_EP_WEDGE;
-       spin_unlock_irqrestore(&dwc->lock, flags);
 
        if (dep->number == 0 || dep->number == 1)
-               return dwc3_gadget_ep0_set_halt(ep, 1);
+               ret = __dwc3_gadget_ep0_set_halt(ep, 1);
        else
-               return dwc3_gadget_ep_set_halt(ep, 1);
+               ret = __dwc3_gadget_ep_set_halt(dep, 1, false);
+       spin_unlock_irqrestore(&dwc->lock, flags);
+
+       return ret;
 }
 
 /* -------------------------------------------------------------------------- */
index 178ad89822065877c72a53b21fc6684c5e456933..18ae3eaa8b6fe476d83d89374141399cbbe1302f 100644 (file)
@@ -82,10 +82,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
                const struct dwc3_event_depevt *event);
 void dwc3_ep0_out_start(struct dwc3 *dwc);
+int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
 int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
 int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
                gfp_t gfp_flags);
-int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value);
+int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
 
 /**
  * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
index 78aff1da089a7b1d07090d3dbf0ea49404c767db..60b0f41eafc40b014861000d02d6972a8e4b2683 100644 (file)
@@ -73,15 +73,23 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
        TP_PROTO(struct usb_ctrlrequest *ctrl),
        TP_ARGS(ctrl),
        TP_STRUCT__entry(
-               __field(struct usb_ctrlrequest *, ctrl)
+               __field(__u8, bRequestType)
+               __field(__u8, bRequest)
+               __field(__le16, wValue)
+               __field(__le16, wIndex)
+               __field(__le16, wLength)
        ),
        TP_fast_assign(
-               __entry->ctrl = ctrl;
+               __entry->bRequestType = ctrl->bRequestType;
+               __entry->bRequest = ctrl->bRequest;
+               __entry->wValue = ctrl->wValue;
+               __entry->wIndex = ctrl->wIndex;
+               __entry->wLength = ctrl->wLength;
        ),
        TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
-               __entry->ctrl->bRequestType, __entry->ctrl->bRequest,
-               le16_to_cpu(__entry->ctrl->wValue), le16_to_cpu(__entry->ctrl->wIndex),
-               le16_to_cpu(__entry->ctrl->wLength)
+               __entry->bRequestType, __entry->bRequest,
+               le16_to_cpu(__entry->wValue), le16_to_cpu(__entry->wIndex),
+               le16_to_cpu(__entry->wLength)
        )
 );
 
@@ -94,15 +102,22 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
        TP_PROTO(struct dwc3_request *req),
        TP_ARGS(req),
        TP_STRUCT__entry(
+               __dynamic_array(char, name, DWC3_MSG_MAX)
                __field(struct dwc3_request *, req)
+               __field(unsigned, actual)
+               __field(unsigned, length)
+               __field(int, status)
        ),
        TP_fast_assign(
+               snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name);
                __entry->req = req;
+               __entry->actual = req->request.actual;
+               __entry->length = req->request.length;
+               __entry->status = req->request.status;
        ),
        TP_printk("%s: req %p length %u/%u ==> %d",
-               __entry->req->dep->name, __entry->req,
-               __entry->req->request.actual, __entry->req->request.length,
-               __entry->req->request.status
+               __get_str(name), __entry->req, __entry->actual, __entry->length,
+               __entry->status
        )
 );
 
@@ -158,17 +173,17 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
                struct dwc3_gadget_ep_cmd_params *params),
        TP_ARGS(dep, cmd, params),
        TP_STRUCT__entry(
-               __field(struct dwc3_ep *, dep)
+               __dynamic_array(char, name, DWC3_MSG_MAX)
                __field(unsigned int, cmd)
                __field(struct dwc3_gadget_ep_cmd_params *, params)
        ),
        TP_fast_assign(
-               __entry->dep = dep;
+               snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
                __entry->cmd = cmd;
                __entry->params = params;
        ),
        TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x\n",
-               __entry->dep->name, dwc3_gadget_ep_cmd_string(__entry->cmd),
+               __get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
                __entry->cmd, __entry->params->param0,
                __entry->params->param1, __entry->params->param2
        )
@@ -184,16 +199,24 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
        TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
        TP_ARGS(dep, trb),
        TP_STRUCT__entry(
-               __field(struct dwc3_ep *, dep)
+               __dynamic_array(char, name, DWC3_MSG_MAX)
                __field(struct dwc3_trb *, trb)
+               __field(u32, bpl)
+               __field(u32, bph)
+               __field(u32, size)
+               __field(u32, ctrl)
        ),
        TP_fast_assign(
-               __entry->dep = dep;
+               snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
                __entry->trb = trb;
+               __entry->bpl = trb->bpl;
+               __entry->bph = trb->bph;
+               __entry->size = trb->size;
+               __entry->ctrl = trb->ctrl;
        ),
        TP_printk("%s: trb %p bph %08x bpl %08x size %08x ctrl %08x\n",
-               __entry->dep->name, __entry->trb, __entry->trb->bph,
-               __entry->trb->bpl, __entry->trb->size, __entry->trb->ctrl
+               __get_str(name), __entry->trb, __entry->bph, __entry->bpl,
+               __entry->size, __entry->ctrl
        )
 );
 
index a8c18df171c34cbcad3e0af3f807c32d5f9546cd..f6a51fddd5b5bbd570d780bd71cc52137f478e66 100644 (file)
@@ -560,7 +560,7 @@ static int bos_desc(struct usb_composite_dev *cdev)
        usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
        usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
        usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
-       usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
+       usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
 
        /*
         * The Superspeed USB Capability descriptor shall be implemented by all
index 6da4685490ef7668dfdbc8be950cfbd63dd2d3cb..aad8165e98ef84d314f74826e97d1bd0641a5b95 100644 (file)
@@ -433,12 +433,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                        dev_vdbg(&cdev->gadget->dev,
                                 "reset acm control interface %d\n", intf);
                        usb_ep_disable(acm->notify);
-               } else {
-                       dev_vdbg(&cdev->gadget->dev,
-                                "init acm ctrl interface %d\n", intf);
+               }
+
+               if (!acm->notify->desc)
                        if (config_ep_by_speed(cdev->gadget, f, acm->notify))
                                return -EINVAL;
-               }
+
                usb_ep_enable(acm->notify);
                acm->notify->driver_data = acm;
 
index 4d8b236ea60865c9fb85c013b416ea0a7f9476b6..c9e90de5bdd9192c459dd3dea7a9aafa3c086c6b 100644 (file)
@@ -325,7 +325,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       usb_free_all_descriptors(f);
        if (eem->port.out_ep)
                eem->port.out_ep->driver_data = NULL;
        if (eem->port.in_ep)
index 7c6771d027a222f33dc472a71ff400995749e0b7..63314ede7ba60e8efdf9a83ead4f6f19324cbc0a 100644 (file)
@@ -647,15 +647,26 @@ static void ffs_user_copy_worker(struct work_struct *work)
        if (io_data->read && ret > 0) {
                int i;
                size_t pos = 0;
+
+               /*
+                * Since req->length may be bigger than io_data->len (after
+                * being rounded up to maxpacketsize), we may end up with more
+                * data then user space has space for.
+                */
+               ret = min_t(int, ret, io_data->len);
+
                use_mm(io_data->mm);
                for (i = 0; i < io_data->nr_segs; i++) {
+                       size_t len = min_t(size_t, ret - pos,
+                                       io_data->iovec[i].iov_len);
+                       if (!len)
+                               break;
                        if (unlikely(copy_to_user(io_data->iovec[i].iov_base,
-                                                &io_data->buf[pos],
-                                                io_data->iovec[i].iov_len))) {
+                                                &io_data->buf[pos], len))) {
                                ret = -EFAULT;
                                break;
                        }
-                       pos += io_data->iovec[i].iov_len;
+                       pos += len;
                }
                unuse_mm(io_data->mm);
        }
@@ -687,7 +698,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
        struct ffs_epfile *epfile = file->private_data;
        struct ffs_ep *ep;
        char *data = NULL;
-       ssize_t ret, data_len;
+       ssize_t ret, data_len = -EINVAL;
        int halt;
 
        /* Are we still active? */
@@ -787,13 +798,30 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
                /* Fire the request */
                struct usb_request *req;
 
+               /*
+                * Sanity Check: even though data_len can't be used
+                * uninitialized at the time I write this comment, some
+                * compilers complain about this situation.
+                * In order to keep the code clean from warnings, data_len is
+                * being initialized to -EINVAL during its declaration, which
+                * means we can't rely on compiler anymore to warn no future
+                * changes won't result in data_len being used uninitialized.
+                * For such reason, we're adding this redundant sanity check
+                * here.
+                */
+               if (unlikely(data_len == -EINVAL)) {
+                       WARN(1, "%s: data_len == -EINVAL\n", __func__);
+                       ret = -EINVAL;
+                       goto error_lock;
+               }
+
                if (io_data->aio) {
                        req = usb_ep_alloc_request(ep->ep, GFP_KERNEL);
                        if (unlikely(!req))
                                goto error_lock;
 
                        req->buf      = data;
-                       req->length   = io_data->len;
+                       req->length   = data_len;
 
                        io_data->buf = data;
                        io_data->ep = ep->ep;
@@ -815,7 +843,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
 
                        req = ep->req;
                        req->buf      = data;
-                       req->length   = io_data->len;
+                       req->length   = data_len;
 
                        req->context  = &done;
                        req->complete = ffs_epfile_io_complete;
@@ -2663,8 +2691,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
        func->conf = c;
        func->gadget = c->cdev->gadget;
 
-       ffs_data_get(func->ffs);
-
        /*
         * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
         * configurations are bound in sequence with list_for_each_entry,
index a95290a1289f8946829fbab180c7c76f807c791f..59ab62c92b66667e77b4ba35cd59f754584e0fd2 100644 (file)
@@ -621,12 +621,14 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
        dev = MKDEV(major, hidg->minor);
        status = cdev_add(&hidg->cdev, dev, 1);
        if (status)
-               goto fail;
+               goto fail_free_descs;
 
        device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor);
 
        return 0;
 
+fail_free_descs:
+       usb_free_all_descriptors(f);
 fail:
        ERROR(f->config->cdev, "hidg_bind FAILED\n");
        if (hidg->req != NULL) {
@@ -635,7 +637,6 @@ fail:
                        usb_ep_free_request(hidg->in_ep, hidg->req);
        }
 
-       usb_free_all_descriptors(f);
        return status;
 }
 
index bf04389137e67cbd0790856e08136e968eccd180..298b46112b1a354eaa2965edc548b10b628ac577 100644 (file)
@@ -253,22 +253,13 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
 
        case 0:                         /* normal completion? */
                if (ep == loop->out_ep) {
-                       /* loop this OUT packet back IN to the host */
                        req->zero = (req->actual < req->length);
                        req->length = req->actual;
-                       status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
-                       if (status == 0)
-                               return;
-
-                       /* "should never get here" */
-                       ERROR(cdev, "can't loop %s to %s: %d\n",
-                               ep->name, loop->in_ep->name,
-                               status);
                }
 
                /* queue the buffer for some later OUT packet */
                req->length = buflen;
-               status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC);
+               status = usb_ep_queue(ep, req, GFP_ATOMIC);
                if (status == 0)
                        return;
 
@@ -308,60 +299,66 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
        return alloc_ep_req(ep, len, buflen);
 }
 
-static int
-enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
+static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop,
+               struct usb_ep *ep)
 {
-       int                                     result = 0;
-       struct usb_ep                           *ep;
        struct usb_request                      *req;
        unsigned                                i;
+       int                                     result;
 
-       /* one endpoint writes data back IN to the host */
-       ep = loop->in_ep;
+       /*
+        * one endpoint writes data back IN to the host while another endpoint
+        * just reads OUT packets
+        */
        result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
        if (result)
-               return result;
+               goto fail0;
        result = usb_ep_enable(ep);
        if (result < 0)
-               return result;
-       ep->driver_data = loop;
-
-       /* one endpoint just reads OUT packets */
-       ep = loop->out_ep;
-       result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
-       if (result)
                goto fail0;
-
-       result = usb_ep_enable(ep);
-       if (result < 0) {
-fail0:
-               ep = loop->in_ep;
-               usb_ep_disable(ep);
-               ep->driver_data = NULL;
-               return result;
-       }
        ep->driver_data = loop;
 
-       /* allocate a bunch of read buffers and queue them all at once.
+       /*
+        * allocate a bunch of read buffers and queue them all at once.
         * we buffer at most 'qlen' transfers; fewer if any need more
         * than 'buflen' bytes each.
         */
        for (i = 0; i < qlen && result == 0; i++) {
                req = lb_alloc_ep_req(ep, 0);
-               if (req) {
-                       req->complete = loopback_complete;
-                       result = usb_ep_queue(ep, req, GFP_ATOMIC);
-                       if (result)
-                               ERROR(cdev, "%s queue req --> %d\n",
-                                               ep->name, result);
-               } else {
-                       usb_ep_disable(ep);
-                       ep->driver_data = NULL;
-                       result = -ENOMEM;
-                       goto fail0;
+               if (!req)
+                       goto fail1;
+
+               req->complete = loopback_complete;
+               result = usb_ep_queue(ep, req, GFP_ATOMIC);
+               if (result) {
+                       ERROR(cdev, "%s queue req --> %d\n",
+                                       ep->name, result);
+                       goto fail1;
                }
        }
 
+       return 0;
+
+fail1:
+       usb_ep_disable(ep);
+
+fail0:
+       return result;
+}
+
+static int
+enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
+{
+       int                                     result = 0;
+
+       result = enable_endpoint(cdev, loop, loop->in_ep);
+       if (result)
+               return result;
+
+       result = enable_endpoint(cdev, loop, loop->out_ep);
+       if (result)
+               return result;
+
        DBG(cdev, "%s enabled\n", loop->function.name);
        return result;
 }
index 146f48cc65d7fb9c000565448121337f914c694c..16361b0a8b469644120907f5a135d3f7d5156b11 100644 (file)
@@ -1461,7 +1461,6 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       usb_free_all_descriptors(f);
        if (ncm->notify_req) {
                kfree(ncm->notify_req->buf);
                usb_ep_free_request(ncm->notify, ncm->notify_req);
index 5f40080c92ccfbe8466319cd848c04c6d1b6038d..a1b79c53499c2f4e852b1599347df3a400337745 100644 (file)
@@ -35,6 +35,7 @@ struct f_obex {
        struct gserial                  port;
        u8                              ctrl_id;
        u8                              data_id;
+       u8                              cur_alt;
        u8                              port_num;
        u8                              can_activate;
 };
@@ -235,6 +236,8 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
        } else
                goto fail;
 
+       obex->cur_alt = alt;
+
        return 0;
 
 fail:
@@ -245,10 +248,7 @@ static int obex_get_alt(struct usb_function *f, unsigned intf)
 {
        struct f_obex           *obex = func_to_obex(f);
 
-       if (intf == obex->ctrl_id)
-               return 0;
-
-       return obex->port.in->driver_data ? 1 : 0;
+       return obex->cur_alt;
 }
 
 static void obex_disable(struct usb_function *f)
@@ -397,7 +397,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       usb_free_all_descriptors(f);
        /* we might as well release our claims on endpoints */
        if (obex->port.out)
                obex->port.out->driver_data = NULL;
index b9cfc1571d71281c0607abf0420fb518796626fe..1ec8b7ffdccd40aadf3b70abfed20fd85935a649 100644 (file)
@@ -570,8 +570,8 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f)
 err_req:
        for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
                usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
-err:
        usb_free_all_descriptors(f);
+err:
        if (fp->out_ep)
                fp->out_ep->driver_data = NULL;
        if (fp->in_ep)
index ddb09dc6d1f2382f556ce378dada0b13df1f8462..f13fc6a585652f4559d446a5dd009bf151a4d1b8 100644 (file)
@@ -802,8 +802,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
 
        if (rndis->manufacturer && rndis->vendorID &&
                        rndis_set_param_vendor(rndis->config, rndis->vendorID,
-                                              rndis->manufacturer))
-               goto fail;
+                                              rndis->manufacturer)) {
+               status = -EINVAL;
+               goto fail_free_descs;
+       }
 
        /* NOTE:  all that is done without knowing or caring about
         * the network link ... which is unavailable to this code
@@ -817,10 +819,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
                        rndis->notify->name);
        return 0;
 
+fail_free_descs:
+       usb_free_all_descriptors(f);
 fail:
        kfree(f->os_desc_table);
        f->os_desc_n = 0;
-       usb_free_all_descriptors(f);
 
        if (rndis->notify_req) {
                kfree(rndis->notify_req->buf);
index 1ea8baf33333be75990c6c1b7d2d6208192f7375..e3dfa675ff06db9ca627e6d211f30263f298eb8f 100644 (file)
@@ -380,7 +380,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       usb_free_all_descriptors(f);
        /* we might as well release our claims on endpoints */
        if (geth->port.out_ep)
                geth->port.out_ep->driver_data = NULL;
index a5a27a504d67099e09670cd7ca9e48355c1c4f70..33e16658e5cfeb50d01c44c7a63a2379634e82b7 100644 (file)
@@ -512,6 +512,11 @@ static int snd_uac2_remove(struct platform_device *pdev)
        return 0;
 }
 
+static void snd_uac2_release(struct device *dev)
+{
+       dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
+}
+
 static int alsa_uac2_init(struct audio_dev *agdev)
 {
        struct snd_uac2_chip *uac2 = &agdev->uac2;
@@ -523,6 +528,7 @@ static int alsa_uac2_init(struct audio_dev *agdev)
 
        uac2->pdev.id = 0;
        uac2->pdev.name = uac2_name;
+       uac2->pdev.dev.release = snd_uac2_release;
 
        /* Register snd_uac2 driver */
        err = platform_driver_register(&uac2->pdrv);
@@ -772,6 +778,7 @@ struct usb_endpoint_descriptor fs_epout_desc = {
 
        .bEndpointAddress = USB_DIR_OUT,
        .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+       .wMaxPacketSize = cpu_to_le16(1023),
        .bInterval = 1,
 };
 
@@ -780,6 +787,7 @@ struct usb_endpoint_descriptor hs_epout_desc = {
        .bDescriptorType = USB_DT_ENDPOINT,
 
        .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+       .wMaxPacketSize = cpu_to_le16(1024),
        .bInterval = 4,
 };
 
@@ -847,6 +855,7 @@ struct usb_endpoint_descriptor fs_epin_desc = {
 
        .bEndpointAddress = USB_DIR_IN,
        .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+       .wMaxPacketSize = cpu_to_le16(1023),
        .bInterval = 1,
 };
 
@@ -855,6 +864,7 @@ struct usb_endpoint_descriptor hs_epin_desc = {
        .bDescriptorType = USB_DT_ENDPOINT,
 
        .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+       .wMaxPacketSize = cpu_to_le16(1024),
        .bInterval = 4,
 };
 
@@ -947,6 +957,9 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
        struct snd_uac2_chip *uac2 = prm->uac2;
        int i;
 
+       if (!prm->ep_enabled)
+               return;
+
        prm->ep_enabled = false;
 
        for (i = 0; i < USB_XFERS; i++) {
@@ -1071,7 +1084,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
        if (!prm->rbuf) {
                prm->max_psize = 0;
-               goto err;
+               goto err_free_descs;
        }
 
        prm = &agdev->uac2.p_prm;
@@ -1079,17 +1092,19 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
        if (!prm->rbuf) {
                prm->max_psize = 0;
-               goto err;
+               goto err_free_descs;
        }
 
        ret = alsa_uac2_init(agdev);
        if (ret)
-               goto err;
+               goto err_free_descs;
        return 0;
+
+err_free_descs:
+       usb_free_all_descriptors(fn);
 err:
        kfree(agdev->uac2.p_prm.rbuf);
        kfree(agdev->uac2.c_prm.rbuf);
-       usb_free_all_descriptors(fn);
        if (agdev->in_ep)
                agdev->in_ep->driver_data = NULL;
        if (agdev->out_ep)
index e126439e4b6509807c05f9bc133224b2ad66e460..945b3bd2ca98a4847c30ce7e462a691f944051b2 100644 (file)
@@ -279,27 +279,41 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
        else if (interface != uvc->streaming_intf)
                return -EINVAL;
        else
-               return uvc->state == UVC_STATE_STREAMING ? 1 : 0;
+               return uvc->video.ep->driver_data ? 1 : 0;
 }
 
 static int
 uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 {
        struct uvc_device *uvc = to_uvc(f);
+       struct usb_composite_dev *cdev = f->config->cdev;
        struct v4l2_event v4l2_event;
        struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
        int ret;
 
-       INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
+       INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
 
        if (interface == uvc->control_intf) {
                if (alt)
                        return -EINVAL;
 
+               if (uvc->control_ep->driver_data) {
+                       INFO(cdev, "reset UVC Control\n");
+                       usb_ep_disable(uvc->control_ep);
+                       uvc->control_ep->driver_data = NULL;
+               }
+
+               if (!uvc->control_ep->desc)
+                       if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep))
+                               return -EINVAL;
+
+               usb_ep_enable(uvc->control_ep);
+               uvc->control_ep->driver_data = uvc;
+
                if (uvc->state == UVC_STATE_DISCONNECTED) {
                        memset(&v4l2_event, 0, sizeof(v4l2_event));
                        v4l2_event.type = UVC_EVENT_CONNECT;
-                       uvc_event->speed = f->config->cdev->gadget->speed;
+                       uvc_event->speed = cdev->gadget->speed;
                        v4l2_event_queue(uvc->vdev, &v4l2_event);
 
                        uvc->state = UVC_STATE_CONNECTED;
@@ -321,8 +335,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                if (uvc->state != UVC_STATE_STREAMING)
                        return 0;
 
-               if (uvc->video.ep)
+               if (uvc->video.ep) {
                        usb_ep_disable(uvc->video.ep);
+                       uvc->video.ep->driver_data = NULL;
+               }
 
                memset(&v4l2_event, 0, sizeof(v4l2_event));
                v4l2_event.type = UVC_EVENT_STREAMOFF;
@@ -335,14 +351,22 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                if (uvc->state != UVC_STATE_CONNECTED)
                        return 0;
 
-               if (uvc->video.ep) {
-                       ret = config_ep_by_speed(f->config->cdev->gadget,
-                                       &(uvc->func), uvc->video.ep);
-                       if (ret)
-                               return ret;
-                       usb_ep_enable(uvc->video.ep);
+               if (!uvc->video.ep)
+                       return -EINVAL;
+
+               if (uvc->video.ep->driver_data) {
+                       INFO(cdev, "reset UVC\n");
+                       usb_ep_disable(uvc->video.ep);
+                       uvc->video.ep->driver_data = NULL;
                }
 
+               ret = config_ep_by_speed(f->config->cdev->gadget,
+                               &(uvc->func), uvc->video.ep);
+               if (ret)
+                       return ret;
+               usb_ep_enable(uvc->video.ep);
+               uvc->video.ep->driver_data = uvc;
+
                memset(&v4l2_event, 0, sizeof(v4l2_event));
                v4l2_event.type = UVC_EVENT_STREAMON;
                v4l2_event_queue(uvc->vdev, &v4l2_event);
@@ -366,6 +390,16 @@ uvc_function_disable(struct usb_function *f)
        v4l2_event_queue(uvc->vdev, &v4l2_event);
 
        uvc->state = UVC_STATE_DISCONNECTED;
+
+       if (uvc->video.ep->driver_data) {
+               usb_ep_disable(uvc->video.ep);
+               uvc->video.ep->driver_data = NULL;
+       }
+
+       if (uvc->control_ep->driver_data) {
+               usb_ep_disable(uvc->control_ep);
+               uvc->control_ep->driver_data = NULL;
+       }
 }
 
 /* --------------------------------------------------------------------------
index c3e1f27dbbefd2da1763766ab4cdbabc09ce4fb3..9cb86bc1a9a5444b4ed7895489c2b0c5860bac37 100644 (file)
@@ -352,7 +352,8 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
 
        if (!enable) {
                for (i = 0; i < UVC_NUM_REQUESTS; ++i)
-                       usb_ep_dequeue(video->ep, video->req[i]);
+                       if (video->req[i])
+                               usb_ep_dequeue(video->ep, video->req[i]);
 
                uvc_video_free_requests(video);
                uvcg_queue_enable(&video->queue, 0);
index 6cdb7a534f2384d7782f0ba751e6a037dbf44b28..024f58475a94a953a2c1171a5efdb5b8eb201fbd 100644 (file)
@@ -912,7 +912,7 @@ static int get_cmd_dir(const unsigned char *cdb)
        case INQUIRY:
        case MODE_SENSE:
        case MODE_SENSE_10:
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
        case MAINTENANCE_IN:
        case PERSISTENT_RESERVE_IN:
        case SECURITY_PROTOCOL_IN:
index 3ea287b0e448a1e50b01ee2be78ba18bdf5d7e23..217365d35a2523e693d689ecb90e2dc4ae599ff4 100644 (file)
@@ -357,6 +357,7 @@ config USB_EG20T
 
 config USB_GADGET_XILINX
        tristate "Xilinx USB Driver"
+       depends on HAS_DMA
        depends on OF || COMPILE_TEST
        help
          USB peripheral controller driver for Xilinx USB2 device.
index f107bb60a5ab3bc342adf61ae771707653ac23b2..f2054659f25b8e6701bd634f902de1e6a76c6fe1 100644 (file)
@@ -507,6 +507,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
 {
        struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
 
+       if (!udc->driver) {
+               dev_err(dev, "soft-connect without a gadget driver\n");
+               return -EOPNOTSUPP;
+       }
+
        if (sysfs_streq(buf, "connect")) {
                usb_gadget_udc_start(udc->gadget, udc->driver);
                usb_gadget_connect(udc->gadget);
index a8a30b1d416761cf004bb760d14125f1a1ffa5b9..a3ca1375dd522bea2998ab4e44f5ab662217be69 100644 (file)
@@ -234,7 +234,7 @@ config USB_EHCI_SH
 
 config USB_EHCI_EXYNOS
        tristate "EHCI support for Samsung S5P/EXYNOS SoC Series"
-       depends on PLAT_S5P || ARCH_EXYNOS
+       depends on ARCH_S5PV210 || ARCH_EXYNOS
        help
        Enable support for the Samsung Exynos SOC's on-chip EHCI controller.
 
@@ -550,7 +550,7 @@ config USB_OHCI_SH
 
 config USB_OHCI_EXYNOS
        tristate "OHCI support for Samsung S5P/EXYNOS SoC Series"
-       depends on PLAT_S5P || ARCH_EXYNOS
+       depends on ARCH_S5PV210 || ARCH_EXYNOS
        help
         Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
 
index d0d8fadf706610ca6483cd1cea19583f6fffbf1f..1db0626c8bf415289fd7e8f0875e15e4aeff404e 100644 (file)
@@ -607,7 +607,7 @@ found:
        wa->wa_descr = wa_descr = (struct usb_wa_descriptor *) hdr;
        if (le16_to_cpu(wa_descr->bcdWAVersion) > 0x0100)
                dev_warn(dev, "Wire Adapter v%d.%d newer than groked v1.0\n",
-                        le16_to_cpu(wa_descr->bcdWAVersion) & 0xff00 >> 8,
+                        (le16_to_cpu(wa_descr->bcdWAVersion) & 0xff00) >> 8,
                         le16_to_cpu(wa_descr->bcdWAVersion) & 0x00ff);
        result = 0;
 error:
index 696160d48ae8521651f4f313ee9998288c245ab4..388cfd83b6b667a8e40dffc6c61d9257839f2f81 100644 (file)
@@ -22,7 +22,6 @@
 
 
 #include <linux/slab.h>
-#include <linux/device.h>
 #include <asm/unaligned.h>
 
 #include "xhci.h"
@@ -1149,9 +1148,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                 * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME
                 * is enabled, so also enable remote wake here.
                 */
-               if (hcd->self.root_hub->do_remote_wakeup
-                               && device_may_wakeup(hcd->self.controller)) {
-
+               if (hcd->self.root_hub->do_remote_wakeup) {
                        if (t1 & PORT_CONNECT) {
                                t2 |= PORT_WKOC_E | PORT_WKDISC_E;
                                t2 &= ~PORT_WKCONN_E;
index 280dde93abe528ba61e98fa4790c1fada555794f..142b601f95636fdff622bca8c4fb1a9aef87093b 100644 (file)
@@ -127,20 +127,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
                xhci->quirks |= XHCI_AVOID_BEI;
        }
-       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-           (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
-            pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
-               /* Workaround for occasional spurious wakeups from S5 (or
-                * any other sleep) on Haswell machines with LPT and LPT-LP
-                * with the new Intel BIOS
-                */
-               /* Limit the quirk to only known vendors, as this triggers
-                * yet another BIOS bug on some other machines
-                * https://bugzilla.kernel.org/show_bug.cgi?id=66171
-                */
-               if (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)
-                       xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
-       }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
@@ -162,6 +148,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                        pdev->device == 0x3432)
                xhci->quirks |= XHCI_BROKEN_STREAMS;
 
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+                       pdev->device == 0x1042)
+               xhci->quirks |= XHCI_BROKEN_STREAMS;
+
        if (xhci->quirks & XHCI_RESET_ON_RESUME)
                xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                "QUIRK: Resetting on resume");
@@ -291,7 +281,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
        if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
                pdev->no_d3cold = true;
 
-       return xhci_suspend(xhci);
+       return xhci_suspend(xhci, do_wakeup);
 }
 
 static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
index 3d78b0cd674b4cd07485dfe493b3cd67d0253fdf..646300cbe5f75d34fabf3fd4d13d1100c52e97c0 100644 (file)
@@ -204,7 +204,15 @@ static int xhci_plat_suspend(struct device *dev)
        struct usb_hcd  *hcd = dev_get_drvdata(dev);
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-       return xhci_suspend(xhci);
+       /*
+        * xhci_suspend() needs `do_wakeup` to know whether host is allowed
+        * to do wakeup during suspend. Since xhci_plat_suspend is currently
+        * only designed for system suspend, device_may_wakeup() is enough
+        * to dertermine whether host is allowed to do wakeup. Need to
+        * reconsider this when xhci_plat_suspend enlarges its scope, e.g.,
+        * also applies to runtime suspend.
+        */
+       return xhci_suspend(xhci, device_may_wakeup(dev));
 }
 
 static int xhci_plat_resume(struct device *dev)
index bc6fcbc16f61ec820ba93d5fb6700cfcbd0ae2a2..06433aec81d71511f0583a1099d42d9977f8da3b 100644 (file)
@@ -1067,9 +1067,8 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
                                false);
                xhci_ring_cmd_db(xhci);
        } else {
-               /* Clear our internal halted state and restart the ring(s) */
+               /* Clear our internal halted state */
                xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED;
-               ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
        }
 }
 
@@ -1823,22 +1822,13 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
                ep->stopped_td = td;
                return 0;
        } else {
-               if (trb_comp_code == COMP_STALL) {
-                       /* The transfer is completed from the driver's
-                        * perspective, but we need to issue a set dequeue
-                        * command for this stalled endpoint to move the dequeue
-                        * pointer past the TD.  We can't do that here because
-                        * the halt condition must be cleared first.  Let the
-                        * USB class driver clear the stall later.
-                        */
-                       ep->stopped_td = td;
-                       ep->stopped_stream = ep_ring->stream_id;
-               } else if (xhci_requires_manual_halt_cleanup(xhci,
-                                       ep_ctx, trb_comp_code)) {
-                       /* Other types of errors halt the endpoint, but the
-                        * class driver doesn't call usb_reset_endpoint() unless
-                        * the error is -EPIPE.  Clear the halted status in the
-                        * xHCI hardware manually.
+               if (trb_comp_code == COMP_STALL ||
+                   xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+                                                     trb_comp_code)) {
+                       /* Issue a reset endpoint command to clear the host side
+                        * halt, followed by a set dequeue command to move the
+                        * dequeue pointer past the TD.
+                        * The class driver clears the device side halt later.
                         */
                        xhci_cleanup_halted_endpoint(xhci,
                                        slot_id, ep_index, ep_ring->stream_id,
@@ -1958,9 +1948,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                else
                        td->urb->actual_length = 0;
 
-               xhci_cleanup_halted_endpoint(xhci,
-                       slot_id, ep_index, 0, td, event_trb);
-               return finish_td(xhci, td, event_trb, event, ep, status, true);
+               return finish_td(xhci, td, event_trb, event, ep, status, false);
        }
        /*
         * Did we transfer any data, despite the errors that might have
@@ -2519,17 +2507,8 @@ cleanup:
                if (ret) {
                        urb = td->urb;
                        urb_priv = urb->hcpriv;
-                       /* Leave the TD around for the reset endpoint function
-                        * to use(but only if it's not a control endpoint,
-                        * since we already queued the Set TR dequeue pointer
-                        * command for stalled control endpoints).
-                        */
-                       if (usb_endpoint_xfer_control(&urb->ep->desc) ||
-                               (trb_comp_code != COMP_STALL &&
-                                       trb_comp_code != COMP_BABBLE))
-                               xhci_urb_free_priv(xhci, urb_priv);
-                       else
-                               kfree(urb_priv);
+
+                       xhci_urb_free_priv(xhci, urb_priv);
 
                        usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
                        if ((urb->actual_length != urb->transfer_buffer_length &&
index 2a5d45b4cb15ef30d82294de6c5d8e015449a383..033b46c470bdff8120b1e903ee3debbb9b998218 100644 (file)
@@ -35,6 +35,8 @@
 #define DRIVER_AUTHOR "Sarah Sharp"
 #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
 
+#define        PORT_WAKE_BITS  (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
+
 /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
 static int link_quirk;
 module_param(link_quirk, int, S_IRUGO | S_IWUSR);
@@ -851,13 +853,47 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
        xhci_set_cmd_ring_deq(xhci);
 }
 
+static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
+{
+       int port_index;
+       __le32 __iomem **port_array;
+       unsigned long flags;
+       u32 t1, t2;
+
+       spin_lock_irqsave(&xhci->lock, flags);
+
+       /* disble usb3 ports Wake bits*/
+       port_index = xhci->num_usb3_ports;
+       port_array = xhci->usb3_ports;
+       while (port_index--) {
+               t1 = readl(port_array[port_index]);
+               t1 = xhci_port_state_to_neutral(t1);
+               t2 = t1 & ~PORT_WAKE_BITS;
+               if (t1 != t2)
+                       writel(t2, port_array[port_index]);
+       }
+
+       /* disble usb2 ports Wake bits*/
+       port_index = xhci->num_usb2_ports;
+       port_array = xhci->usb2_ports;
+       while (port_index--) {
+               t1 = readl(port_array[port_index]);
+               t1 = xhci_port_state_to_neutral(t1);
+               t2 = t1 & ~PORT_WAKE_BITS;
+               if (t1 != t2)
+                       writel(t2, port_array[port_index]);
+       }
+
+       spin_unlock_irqrestore(&xhci->lock, flags);
+}
+
 /*
  * Stop HC (not bus-specific)
  *
  * This is called when the machine transition into S3/S4 mode.
  *
  */
-int xhci_suspend(struct xhci_hcd *xhci)
+int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
 {
        int                     rc = 0;
        unsigned int            delay = XHCI_MAX_HALT_USEC;
@@ -868,6 +904,10 @@ int xhci_suspend(struct xhci_hcd *xhci)
                        xhci->shared_hcd->state != HC_STATE_SUSPENDED)
                return -EINVAL;
 
+       /* Clear root port wake on bits if wakeup not allowed. */
+       if (!do_wakeup)
+               xhci_disable_port_wake_on_bits(xhci);
+
        /* Don't poll the roothubs on bus suspend. */
        xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
        clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
@@ -2912,68 +2952,33 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
        }
 }
 
-/* Deal with stalled endpoints.  The core should have sent the control message
- * to clear the halt condition.  However, we need to make the xHCI hardware
- * reset its sequence number, since a device will expect a sequence number of
- * zero after the halt condition is cleared.
+/* Called when clearing halted device. The core should have sent the control
+ * message to clear the device halt condition. The host side of the halt should
+ * already be cleared with a reset endpoint command issued when the STALL tx
+ * event was received.
+ *
  * Context: in_interrupt
  */
+
 void xhci_endpoint_reset(struct usb_hcd *hcd,
                struct usb_host_endpoint *ep)
 {
        struct xhci_hcd *xhci;
-       struct usb_device *udev;
-       unsigned int ep_index;
-       unsigned long flags;
-       int ret;
-       struct xhci_virt_ep *virt_ep;
-       struct xhci_command *command;
 
        xhci = hcd_to_xhci(hcd);
-       udev = (struct usb_device *) ep->hcpriv;
-       /* Called with a root hub endpoint (or an endpoint that wasn't added
-        * with xhci_add_endpoint()
-        */
-       if (!ep->hcpriv)
-               return;
-       ep_index = xhci_get_endpoint_index(&ep->desc);
-       virt_ep = &xhci->devs[udev->slot_id]->eps[ep_index];
-       if (!virt_ep->stopped_td) {
-               xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
-                       "Endpoint 0x%x not halted, refusing to reset.",
-                       ep->desc.bEndpointAddress);
-               return;
-       }
-       if (usb_endpoint_xfer_control(&ep->desc)) {
-               xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
-                               "Control endpoint stall already handled.");
-               return;
-       }
 
-       command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
-       if (!command)
-               return;
-
-       xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
-                       "Queueing reset endpoint command");
-       spin_lock_irqsave(&xhci->lock, flags);
-       ret = xhci_queue_reset_ep(xhci, command, udev->slot_id, ep_index);
        /*
-        * Can't change the ring dequeue pointer until it's transitioned to the
-        * stopped state, which is only upon a successful reset endpoint
-        * command.  Better hope that last command worked!
+        * We might need to implement the config ep cmd in xhci 4.8.1 note:
+        * The Reset Endpoint Command may only be issued to endpoints in the
+        * Halted state. If software wishes reset the Data Toggle or Sequence
+        * Number of an endpoint that isn't in the Halted state, then software
+        * may issue a Configure Endpoint Command with the Drop and Add bits set
+        * for the target endpoint. that is in the Stopped state.
         */
-       if (!ret) {
-               xhci_cleanup_stalled_ring(xhci, udev, ep_index);
-               kfree(virt_ep->stopped_td);
-               xhci_ring_cmd_db(xhci);
-       }
-       virt_ep->stopped_td = NULL;
-       virt_ep->stopped_stream = 0;
-       spin_unlock_irqrestore(&xhci->lock, flags);
 
-       if (ret)
-               xhci_warn(xhci, "FIXME allocate a new ring segment\n");
+       /* For now just print debug to follow the situation */
+       xhci_dbg(xhci, "Endpoint 0x%x ep reset callback called\n",
+                ep->desc.bEndpointAddress);
 }
 
 static int xhci_check_streams_endpoint(struct xhci_hcd *xhci,
index df76d642e7190bd04854a10024c06714dd7e48d0..d745715a1e2f53648b1e1c2b1288f9c963bb42be 100644 (file)
@@ -1746,7 +1746,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
 void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *));
 
 #ifdef CONFIG_PM
-int xhci_suspend(struct xhci_hcd *xhci);
+int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
 int xhci_resume(struct xhci_hcd *xhci, bool hibernated);
 #else
 #define        xhci_suspend    NULL
index acdfb3e68a90a69dd842dcb32414612e69c47de0..5a9b977fbc19727c1ba95fc12325944aad6df786 100644 (file)
@@ -209,7 +209,8 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
                }
        }
 
-       if (!list_empty(&controller->early_tx_list)) {
+       if (!list_empty(&controller->early_tx_list) &&
+           !hrtimer_is_queued(&controller->early_tx)) {
                ret = HRTIMER_RESTART;
                hrtimer_forward_now(&controller->early_tx,
                                ktime_set(0, 20 * NSEC_PER_USEC));
index 154bcf1b5dfae0b0033314a5841c3529263cf763..48bc09e7b83b2855a9384b0d646322cb565be6fb 100644 (file)
@@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev)
        struct dsps_glue *glue = dev_get_drvdata(dev);
        const struct dsps_musb_wrapper *wrp = glue->wrp;
        struct musb *musb = platform_get_drvdata(glue->musb);
-       void __iomem *mbase = musb->ctrl_base;
+       void __iomem *mbase;
 
        del_timer_sync(&glue->timer);
+
+       if (!musb)
+               /* This can happen if the musb device is in -EPROBE_DEFER */
+               return 0;
+
+       mbase = musb->ctrl_base;
        glue->context.control = dsps_readl(mbase, wrp->control);
        glue->context.epintr = dsps_readl(mbase, wrp->epintr_set);
        glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set);
@@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev)
        struct dsps_glue *glue = dev_get_drvdata(dev);
        const struct dsps_musb_wrapper *wrp = glue->wrp;
        struct musb *musb = platform_get_drvdata(glue->musb);
-       void __iomem *mbase = musb->ctrl_base;
+       void __iomem *mbase;
+
+       if (!musb)
+               return 0;
 
+       mbase = musb->ctrl_base;
        dsps_writel(mbase, wrp->control, glue->context.control);
        dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
        dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
@@ -896,7 +906,9 @@ static int dsps_resume(struct device *dev)
        dsps_writel(mbase, wrp->mode, glue->context.mode);
        dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
        dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
-       setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
+       if (musb->xceiv->state == OTG_STATE_B_IDLE &&
+           musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
+               mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
 
        return 0;
 }
index eca1747ca8c76621508947513f9f5b179fb95fe3..6c4eb3cf5efd599653641e5d96d20b05610a6ed5 100644 (file)
@@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
        { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
        { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+       { USB_DEVICE(0x10C4, 0x8875) }, /* CEL MeshConnect USB Stick */
        { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
        { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
        { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
@@ -155,6 +156,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
        { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
        { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
+       { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
        { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
        { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */
        { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
index dc72b924c399e955e8cd94f68c8337f1b7e3facd..1ebb351b9e9a59c9dbd90ffda56cae1769de764e 100644 (file)
@@ -140,6 +140,7 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
  * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report.
  */
 static const struct usb_device_id id_table_combined[] = {
+       { USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
@@ -469,6 +470,39 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_4701_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9300_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9301_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9302_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9303_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9304_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9305_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9306_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9307_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9308_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9309_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930A_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930B_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930C_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930D_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930E_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_930F_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9310_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9311_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9312_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9313_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9314_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9315_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9316_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9317_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9318_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_9319_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931A_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931B_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931C_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931D_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931E_PID) },
+       { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_931F_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
@@ -661,6 +695,8 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
        { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) },
+       { USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
        { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
index 5937b2d242f28c14064d56b073dbbda5fb737093..e52409c9be999f817cbdb627f4be8ec6f127cbe6 100644 (file)
 
 /*** third-party PIDs (using FTDI_VID) ***/
 
+/*
+ * Certain versions of the official Windows FTDI driver reprogrammed
+ * counterfeit FTDI devices to PID 0. Support these devices anyway.
+ */
+#define FTDI_BRICK_PID         0x0000
+
 #define FTDI_LUMEL_PD12_PID    0x6002
 
 /*
  * Xsens Technologies BV products (http://www.xsens.com).
  */
 #define XSENS_VID              0x2639
-#define XSENS_CONVERTER_PID    0xD00D  /* Xsens USB-serial converter */
+#define XSENS_AWINDA_STATION_PID 0x0101
+#define XSENS_AWINDA_DONGLE_PID 0x0102
 #define XSENS_MTW_PID          0x0200  /* Xsens MTw */
+#define XSENS_CONVERTER_PID    0xD00D  /* Xsens USB-serial converter */
+
+/* Xsens devices using FTDI VID */
 #define XSENS_CONVERTER_0_PID  0xD388  /* Xsens USB converter */
 #define XSENS_CONVERTER_1_PID  0xD389  /* Xsens Wireless Receiver */
 #define XSENS_CONVERTER_2_PID  0xD38A
 #define BAYER_CONTOUR_CABLE_PID        0x6001
 
 /*
- * The following are the values for the Matrix Orbital FTDI Range
- * Anything in this range will use an FT232RL.
+ * Matrix Orbital Intelligent USB displays.
+ * http://www.matrixorbital.com
  */
 #define MTXORB_VID                     0x1B3D
 #define MTXORB_FTDI_RANGE_0100_PID     0x0100
 #define MTXORB_FTDI_RANGE_01FD_PID     0x01FD
 #define MTXORB_FTDI_RANGE_01FE_PID     0x01FE
 #define MTXORB_FTDI_RANGE_01FF_PID     0x01FF
-
-
+#define MTXORB_FTDI_RANGE_4701_PID     0x4701
+#define MTXORB_FTDI_RANGE_9300_PID     0x9300
+#define MTXORB_FTDI_RANGE_9301_PID     0x9301
+#define MTXORB_FTDI_RANGE_9302_PID     0x9302
+#define MTXORB_FTDI_RANGE_9303_PID     0x9303
+#define MTXORB_FTDI_RANGE_9304_PID     0x9304
+#define MTXORB_FTDI_RANGE_9305_PID     0x9305
+#define MTXORB_FTDI_RANGE_9306_PID     0x9306
+#define MTXORB_FTDI_RANGE_9307_PID     0x9307
+#define MTXORB_FTDI_RANGE_9308_PID     0x9308
+#define MTXORB_FTDI_RANGE_9309_PID     0x9309
+#define MTXORB_FTDI_RANGE_930A_PID     0x930A
+#define MTXORB_FTDI_RANGE_930B_PID     0x930B
+#define MTXORB_FTDI_RANGE_930C_PID     0x930C
+#define MTXORB_FTDI_RANGE_930D_PID     0x930D
+#define MTXORB_FTDI_RANGE_930E_PID     0x930E
+#define MTXORB_FTDI_RANGE_930F_PID     0x930F
+#define MTXORB_FTDI_RANGE_9310_PID     0x9310
+#define MTXORB_FTDI_RANGE_9311_PID     0x9311
+#define MTXORB_FTDI_RANGE_9312_PID     0x9312
+#define MTXORB_FTDI_RANGE_9313_PID     0x9313
+#define MTXORB_FTDI_RANGE_9314_PID     0x9314
+#define MTXORB_FTDI_RANGE_9315_PID     0x9315
+#define MTXORB_FTDI_RANGE_9316_PID     0x9316
+#define MTXORB_FTDI_RANGE_9317_PID     0x9317
+#define MTXORB_FTDI_RANGE_9318_PID     0x9318
+#define MTXORB_FTDI_RANGE_9319_PID     0x9319
+#define MTXORB_FTDI_RANGE_931A_PID     0x931A
+#define MTXORB_FTDI_RANGE_931B_PID     0x931B
+#define MTXORB_FTDI_RANGE_931C_PID     0x931C
+#define MTXORB_FTDI_RANGE_931D_PID     0x931D
+#define MTXORB_FTDI_RANGE_931E_PID     0x931E
+#define MTXORB_FTDI_RANGE_931F_PID     0x931F
 
 /*
  * The Mobility Lab (TML)
index 93cb7cebda62760bcaae46f3710e7477ff59a507..077c714f1285171ee3b9e4c418e0df42f60cd42c 100644 (file)
@@ -311,24 +311,30 @@ static void       usa26_indat_callback(struct urb *urb)
                if ((data[0] & 0x80) == 0) {
                        /* no errors on individual bytes, only
                           possible overrun err */
-                       if (data[0] & RXERROR_OVERRUN)
-                               err = TTY_OVERRUN;
-                       else
-                               err = 0;
+                       if (data[0] & RXERROR_OVERRUN) {
+                               tty_insert_flip_char(&port->port, 0,
+                                                               TTY_OVERRUN);
+                       }
                        for (i = 1; i < urb->actual_length ; ++i)
-                               tty_insert_flip_char(&port->port, data[i], err);
+                               tty_insert_flip_char(&port->port, data[i],
+                                                               TTY_NORMAL);
                } else {
                        /* some bytes had errors, every byte has status */
                        dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
                        for (i = 0; i + 1 < urb->actual_length; i += 2) {
-                               int stat = data[i], flag = 0;
-                               if (stat & RXERROR_OVERRUN)
-                                       flag |= TTY_OVERRUN;
-                               if (stat & RXERROR_FRAMING)
-                                       flag |= TTY_FRAME;
-                               if (stat & RXERROR_PARITY)
-                                       flag |= TTY_PARITY;
+                               int stat = data[i];
+                               int flag = TTY_NORMAL;
+
+                               if (stat & RXERROR_OVERRUN) {
+                                       tty_insert_flip_char(&port->port, 0,
+                                                               TTY_OVERRUN);
+                               }
                                /* XXX should handle break (0x10) */
+                               if (stat & RXERROR_PARITY)
+                                       flag = TTY_PARITY;
+                               else if (stat & RXERROR_FRAMING)
+                                       flag = TTY_FRAME;
+
                                tty_insert_flip_char(&port->port, data[i+1],
                                                flag);
                        }
@@ -649,14 +655,19 @@ static void       usa49_indat_callback(struct urb *urb)
                } else {
                        /* some bytes had errors, every byte has status */
                        for (i = 0; i + 1 < urb->actual_length; i += 2) {
-                               int stat = data[i], flag = 0;
-                               if (stat & RXERROR_OVERRUN)
-                                       flag |= TTY_OVERRUN;
-                               if (stat & RXERROR_FRAMING)
-                                       flag |= TTY_FRAME;
-                               if (stat & RXERROR_PARITY)
-                                       flag |= TTY_PARITY;
+                               int stat = data[i];
+                               int flag = TTY_NORMAL;
+
+                               if (stat & RXERROR_OVERRUN) {
+                                       tty_insert_flip_char(&port->port, 0,
+                                                               TTY_OVERRUN);
+                               }
                                /* XXX should handle break (0x10) */
+                               if (stat & RXERROR_PARITY)
+                                       flag = TTY_PARITY;
+                               else if (stat & RXERROR_FRAMING)
+                                       flag = TTY_FRAME;
+
                                tty_insert_flip_char(&port->port, data[i+1],
                                                flag);
                        }
@@ -713,15 +724,19 @@ static void usa49wg_indat_callback(struct urb *urb)
                         */
                        for (x = 0; x + 1 < len &&
                                    i + 1 < urb->actual_length; x += 2) {
-                               int stat = data[i], flag = 0;
+                               int stat = data[i];
+                               int flag = TTY_NORMAL;
 
-                               if (stat & RXERROR_OVERRUN)
-                                       flag |= TTY_OVERRUN;
-                               if (stat & RXERROR_FRAMING)
-                                       flag |= TTY_FRAME;
-                               if (stat & RXERROR_PARITY)
-                                       flag |= TTY_PARITY;
+                               if (stat & RXERROR_OVERRUN) {
+                                       tty_insert_flip_char(&port->port, 0,
+                                                               TTY_OVERRUN);
+                               }
                                /* XXX should handle break (0x10) */
+                               if (stat & RXERROR_PARITY)
+                                       flag = TTY_PARITY;
+                               else if (stat & RXERROR_FRAMING)
+                                       flag = TTY_FRAME;
+
                                tty_insert_flip_char(&port->port, data[i+1],
                                                     flag);
                                i += 2;
@@ -773,25 +788,31 @@ static void usa90_indat_callback(struct urb *urb)
                        if ((data[0] & 0x80) == 0) {
                                /* no errors on individual bytes, only
                                   possible overrun err*/
-                               if (data[0] & RXERROR_OVERRUN)
-                                       err = TTY_OVERRUN;
-                               else
-                                       err = 0;
+                               if (data[0] & RXERROR_OVERRUN) {
+                                       tty_insert_flip_char(&port->port, 0,
+                                                               TTY_OVERRUN);
+                               }
                                for (i = 1; i < urb->actual_length ; ++i)
                                        tty_insert_flip_char(&port->port,
-                                                       data[i], err);
+                                                       data[i], TTY_NORMAL);
                        }  else {
                        /* some bytes had errors, every byte has status */
                                dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__);
                                for (i = 0; i + 1 < urb->actual_length; i += 2) {
-                                       int stat = data[i], flag = 0;
-                                       if (stat & RXERROR_OVERRUN)
-                                               flag |= TTY_OVERRUN;
-                                       if (stat & RXERROR_FRAMING)
-                                               flag |= TTY_FRAME;
-                                       if (stat & RXERROR_PARITY)
-                                               flag |= TTY_PARITY;
+                                       int stat = data[i];
+                                       int flag = TTY_NORMAL;
+
+                                       if (stat & RXERROR_OVERRUN) {
+                                               tty_insert_flip_char(
+                                                               &port->port, 0,
+                                                               TTY_OVERRUN);
+                                       }
                                        /* XXX should handle break (0x10) */
+                                       if (stat & RXERROR_PARITY)
+                                               flag = TTY_PARITY;
+                                       else if (stat & RXERROR_FRAMING)
+                                               flag = TTY_FRAME;
+
                                        tty_insert_flip_char(&port->port,
                                                        data[i+1], flag);
                                }
index 078f9ed419c84fbf1cbbdd41741ba20051a03187..02c420af251e27bb2cb3c4475343b8a869ae1ef5 100644 (file)
@@ -335,7 +335,8 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
                        port->interrupt_out_urb->transfer_buffer_length = length;
 
                        priv->cur_pos = priv->cur_pos + length;
-                       result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO);
+                       result = usb_submit_urb(port->interrupt_out_urb,
+                                       GFP_ATOMIC);
                        dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);
                        todo = priv->filled - priv->cur_pos;
 
@@ -350,7 +351,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
                if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
                        priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
                        result = usb_submit_urb(port->interrupt_in_urb,
-                                                               GFP_NOIO);
+                                       GFP_ATOMIC);
                        dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result);
                }
        }
@@ -414,8 +415,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
        int result;
        int dtr = 0;
        int rts = 0;
-       unsigned char *transfer_buffer;
-       int transfer_buffer_length = 8;
 
        /* FIXME: locking ? */
        priv = usb_get_serial_port_data(port);
@@ -425,11 +424,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
                return -EINVAL;
        }
 
-       /* allocate memory for transfer buffer */
-       transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
-       if (!transfer_buffer)
-               return -ENOMEM;
-
        if (set & TIOCM_RTS)
                rts = 1;
        if (set & TIOCM_DTR)
@@ -469,7 +463,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
                        KOBIL_TIMEOUT);
        }
        dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result);
-       kfree(transfer_buffer);
        return (result < 0) ? result : 0;
 }
 
@@ -530,8 +523,6 @@ static int kobil_ioctl(struct tty_struct *tty,
 {
        struct usb_serial_port *port = tty->driver_data;
        struct kobil_private *priv = usb_get_serial_port_data(port);
-       unsigned char *transfer_buffer;
-       int transfer_buffer_length = 8;
        int result;
 
        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
@@ -541,10 +532,6 @@ static int kobil_ioctl(struct tty_struct *tty,
 
        switch (cmd) {
        case TCFLSH:
-               transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
-               if (!transfer_buffer)
-                       return -ENOBUFS;
-
                result = usb_control_msg(port->serial->dev,
                          usb_sndctrlpipe(port->serial->dev, 0),
                          SUSBCRequest_Misc,
@@ -559,7 +546,6 @@ static int kobil_ioctl(struct tty_struct *tty,
                dev_dbg(&port->dev,
                        "%s - Send reset_all_queues (FLUSH) URB returns: %i\n",
                        __func__, result);
-               kfree(transfer_buffer);
                return (result < 0) ? -EIO: 0;
        default:
                return -ENOIOCTLCMD;
index 4856fb7e637e70ffcc5f4da4cdb6536588b3aa95..4b7bfb394a32aba025e8e07ad3384759ea1723d8 100644 (file)
@@ -215,7 +215,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 
        /* The connected devices do not have a bulk write endpoint,
         * to transmit data to de barcode device the control endpoint is used */
-       dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+       dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
        if (!dr) {
                count = -ENOMEM;
                goto error_no_dr;
index d1a3f6044c8a52d1dd6e9b899070d5e52a7c72db..7a4c21b4f67613f7bf64839b4cf4faf09804355e 100644 (file)
@@ -269,6 +269,7 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_DE910_DUAL               0x1010
 #define TELIT_PRODUCT_UE910_V2                 0x1012
 #define TELIT_PRODUCT_LE920                    0x1200
+#define TELIT_PRODUCT_LE910                    0x1201
 
 /* ZTE PRODUCTS */
 #define ZTE_VENDOR_ID                          0x19d2
@@ -362,6 +363,7 @@ static void option_instat_callback(struct urb *urb);
 
 /* Haier products */
 #define HAIER_VENDOR_ID                                0x201e
+#define HAIER_PRODUCT_CE81B                    0x10f8
 #define HAIER_PRODUCT_CE100                    0x2009
 
 /* Cinterion (formerly Siemens) products */
@@ -589,6 +591,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {
        .reserved = BIT(3) | BIT(4),
 };
 
+static const struct option_blacklist_info telit_le910_blacklist = {
+       .sendsetup = BIT(0),
+       .reserved = BIT(1) | BIT(2),
+};
+
 static const struct option_blacklist_info telit_le920_blacklist = {
        .sendsetup = BIT(0),
        .reserved = BIT(1) | BIT(5),
@@ -1138,6 +1145,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
+               .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
                .driver_info = (kernel_ulong_t)&telit_le920_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
@@ -1621,6 +1630,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
        { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HAIER_VENDOR_ID, HAIER_PRODUCT_CE81B, 0xff, 0xff, 0xff) },
        /* Pirelli  */
        { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
        { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
index a7fe664b6b7d164e628c5b466e548efe7e10e7ec..70a098de429fc39934ef8808d3e6c5011f063352 100644 (file)
@@ -490,10 +490,9 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
                        if (*tty_flag == TTY_NORMAL)
                                *tty_flag = TTY_FRAME;
                }
-               if (lsr & UART_LSR_OE){
+               if (lsr & UART_LSR_OE) {
                        port->icount.overrun++;
-                       if (*tty_flag == TTY_NORMAL)
-                               *tty_flag = TTY_OVERRUN;
+                       tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
                }
        }
 
@@ -511,12 +510,8 @@ static void ssu100_process_read_urb(struct urb *urb)
        if ((len >= 4) &&
            (packet[0] == 0x1b) && (packet[1] == 0x1b) &&
            ((packet[2] == 0x00) || (packet[2] == 0x01))) {
-               if (packet[2] == 0x00) {
+               if (packet[2] == 0x00)
                        ssu100_update_lsr(port, packet[3], &flag);
-                       if (flag == TTY_OVERRUN)
-                               tty_insert_flip_char(&port->port, 0,
-                                               TTY_OVERRUN);
-               }
                if (packet[2] == 0x01)
                        ssu100_update_msr(port, packet[3]);
 
index e08f64780e30fb3af660b7066cc14b1f6181417a..66a684a299384bef5089a0fad2770d2af48ba14d 100644 (file)
@@ -164,10 +164,10 @@ void usb_stor_show_sense(const struct us_data *us,
                         unsigned char asc,
                         unsigned char ascq)
 {
-       const char *what, *keystr;
+       const char *what, *keystr, *fmt;
 
        keystr = scsi_sense_key_string(key);
-       what = scsi_extd_sense_format(asc, ascq);
+       what = scsi_extd_sense_format(asc, ascq, &fmt);
 
        if (keystr == NULL)
                keystr = "(Unknown Key)";
@@ -175,8 +175,10 @@ void usb_stor_show_sense(const struct us_data *us,
                what = "(unknown ASC/ASCQ)";
 
        usb_stor_dbg(us, "%s: ", keystr);
-       US_DEBUGPX(what, ascq);
-       US_DEBUGPX("\n");
+       if (fmt)
+               US_DEBUGPX("%s (%s%x)\n", what, fmt, ascq);
+       else
+               US_DEBUGPX("%s\n", what);
 }
 
 int usb_stor_dbg(const struct us_data *us, const char *fmt, ...)
index 4bc2fc98636ed27f65ec8425c6a3e583e580174e..73f125e0cb587015eb282dfef0f5eaadea273ed5 100644 (file)
@@ -52,7 +52,7 @@ int usb_stor_euscsi_init(struct us_data *us)
        us->iobuf[0] = 0x1;
        result = usb_stor_control_msg(us, us->send_ctrl_pipe,
                        0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
-                       0x01, 0x0, us->iobuf, 0x1, USB_CTRL_SET_TIMEOUT);
+                       0x01, 0x0, us->iobuf, 0x1, 5 * HZ);
        usb_stor_dbg(us, "-- result is %d\n", result);
 
        return 0;
@@ -100,7 +100,7 @@ int usb_stor_huawei_e220_init(struct us_data *us)
        result = usb_stor_control_msg(us, us->send_ctrl_pipe,
                                      USB_REQ_SET_FEATURE,
                                      USB_TYPE_STANDARD | USB_RECIP_DEVICE,
-                                     0x01, 0x0, NULL, 0x0, 1000);
+                                     0x01, 0x0, NULL, 0x0, 1 * HZ);
        usb_stor_dbg(us, "Huawei mode set result is %d\n", result);
        return 0;
 }
index 8591d89a38e666b3043932c7da08a8fc4d27e350..27e4a580d2ed2fddb97e543ce5aafbd4f6280032 100644 (file)
@@ -626,6 +626,7 @@ static int config_autodelink_after_power_on(struct us_data *us)
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int config_autodelink_before_power_down(struct us_data *us)
 {
        struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
@@ -716,6 +717,7 @@ static void fw5895_init(struct us_data *us)
                }
        }
 }
+#endif
 
 #ifdef CONFIG_REALTEK_AUTOPM
 static void fw5895_set_mmc_wp(struct us_data *us)
index 22c7d4360fa222722369b6861da34bafdd4b5b96..b1d815eb6d0bb34d8edeff31581eafd1ad983a0c 100644 (file)
@@ -1118,6 +1118,31 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
                 */
                if (result == USB_STOR_XFER_LONG)
                        fake_sense = 1;
+
+               /*
+                * Sometimes a device will mistakenly skip the data phase
+                * and go directly to the status phase without sending a
+                * zero-length packet.  If we get a 13-byte response here,
+                * check whether it really is a CSW.
+                */
+               if (result == USB_STOR_XFER_SHORT &&
+                               srb->sc_data_direction == DMA_FROM_DEVICE &&
+                               transfer_length - scsi_get_resid(srb) ==
+                                       US_BULK_CS_WRAP_LEN) {
+                       struct scatterlist *sg = NULL;
+                       unsigned int offset = 0;
+
+                       if (usb_stor_access_xfer_buf((unsigned char *) bcs,
+                                       US_BULK_CS_WRAP_LEN, srb, &sg,
+                                       &offset, FROM_XFER_BUF) ==
+                                               US_BULK_CS_WRAP_LEN &&
+                                       bcs->Signature ==
+                                               cpu_to_le32(US_BULK_CS_SIGN)) {
+                               usb_stor_dbg(us, "Device skipped data phase\n");
+                               scsi_set_resid(srb, transfer_length);
+                               goto skipped_data_phase;
+                       }
+               }
        }
 
        /* See flow chart on pg 15 of the Bulk Only Transport spec for
@@ -1153,6 +1178,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
+ skipped_data_phase:
        /* check bulk status */
        residue = le32_to_cpu(bcs->Residue);
        usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
index 89b24349269efb66e72bd94b1dd080c81d6138b8..4047edfb64e1d25314b2ecea18a37972d75e7874 100644 (file)
@@ -181,7 +181,7 @@ static int uas_get_tag(struct scsi_cmnd *cmnd)
 {
        int tag;
 
-       if (blk_rq_tagged(cmnd->request))
+       if (cmnd->flags & SCMD_TAGGED)
                tag = cmnd->request->tag + 2;
        else
                tag = 1;
@@ -799,8 +799,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
        if (devinfo->flags & US_FL_NO_REPORT_OPCODES)
                sdev->no_report_opcodes = 1;
 
-       scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
-       scsi_activate_tcq(sdev, devinfo->qdepth - 2);
+       scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
        return 0;
 }
 
@@ -817,7 +816,6 @@ static struct scsi_host_template uas_host_template = {
        .sg_tablesize = SG_NONE,
        .cmd_per_lun = 1,       /* until we override it */
        .skip_settle_delay = 1,
-       .ordered_tag = 1,
 
        /*
         * The uas drivers expects tags not to be bigger than the maximum
@@ -825,6 +823,7 @@ static struct scsi_host_template uas_host_template = {
         * allocator.
         */
        .disable_blk_mq = true,
+       .use_blk_tags = 1,
 };
 
 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
index 8511b54a65d9665e51f1a0cc808b4535b611ba97..18a283d6de1c8bd18663b57bbf7499510c49fa2d 100644 (file)
@@ -54,6 +54,20 @@ UNUSUAL_DEV(0x0bc2, 0x3312, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_ATA_1X),
 
+/* Reported-by: Hans de Goede <hdegoede@redhat.com> */
+UNUSUAL_DEV(0x0bc2, 0x3320, 0x0000, 0x9999,
+               "Seagate",
+               "Expansion Desk",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_ATA_1X),
+
+/* Reported-by: Bogdan Mihalcea <bogdan.mihalcea@infim.ro> */
+UNUSUAL_DEV(0x0bc2, 0xa003, 0x0000, 0x9999,
+               "Seagate",
+               "Backup Plus",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_ATA_1X),
+
 /* https://bbs.archlinux.org/viewtopic.php?id=183190 */
 UNUSUAL_DEV(0x0bc2, 0xab20, 0x0000, 0x9999,
                "Seagate",
@@ -61,6 +75,13 @@ UNUSUAL_DEV(0x0bc2, 0xab20, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_NO_ATA_1X),
 
+/* https://bbs.archlinux.org/viewtopic.php?id=183190 */
+UNUSUAL_DEV(0x0bc2, 0xab21, 0x0000, 0x9999,
+               "Seagate",
+               "Backup+ BK",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_ATA_1X),
+
 /* Reported-by: Claudio Bizzarri <claudio.bizzarri@gmail.com> */
 UNUSUAL_DEV(0x152d, 0x0567, 0x0000, 0x9999,
                "JMicron",
@@ -75,3 +96,17 @@ UNUSUAL_DEV(0x174c, 0x5106, 0x0000, 0x9999,
                "ASM1051",
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_IGNORE_UAS),
+
+/* Reported-by: Hans de Goede <hdegoede@redhat.com> */
+UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999,
+               "VIA",
+               "VL711",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_ATA_1X),
+
+/* Reported-by: Hans de Goede <hdegoede@redhat.com> */
+UNUSUAL_DEV(0x4971, 0x1012, 0x0000, 0x9999,
+               "Hitachi",
+               "External HDD",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_IGNORE_UAS),
index 69906cacd04fdc8b3d5236dc030e8bcf749c541f..a17f11850669b461130610692d558dd7e499258b 100644 (file)
@@ -1312,6 +1312,7 @@ static int
 vhost_scsi_set_endpoint(struct vhost_scsi *vs,
                        struct vhost_scsi_target *t)
 {
+       struct se_portal_group *se_tpg;
        struct tcm_vhost_tport *tv_tport;
        struct tcm_vhost_tpg *tpg;
        struct tcm_vhost_tpg **vs_tpg;
@@ -1359,6 +1360,21 @@ vhost_scsi_set_endpoint(struct vhost_scsi *vs,
                                ret = -EEXIST;
                                goto out;
                        }
+                       /*
+                        * In order to ensure individual vhost-scsi configfs
+                        * groups cannot be removed while in use by vhost ioctl,
+                        * go ahead and take an explicit se_tpg->tpg_group.cg_item
+                        * dependency now.
+                        */
+                       se_tpg = &tpg->se_tpg;
+                       ret = configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
+                                                  &se_tpg->tpg_group.cg_item);
+                       if (ret) {
+                               pr_warn("configfs_depend_item() failed: %d\n", ret);
+                               kfree(vs_tpg);
+                               mutex_unlock(&tpg->tv_tpg_mutex);
+                               goto out;
+                       }
                        tpg->tv_tpg_vhost_count++;
                        tpg->vhost_scsi = vs;
                        vs_tpg[tpg->tport_tpgt] = tpg;
@@ -1401,6 +1417,7 @@ static int
 vhost_scsi_clear_endpoint(struct vhost_scsi *vs,
                          struct vhost_scsi_target *t)
 {
+       struct se_portal_group *se_tpg;
        struct tcm_vhost_tport *tv_tport;
        struct tcm_vhost_tpg *tpg;
        struct vhost_virtqueue *vq;
@@ -1449,6 +1466,13 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs,
                vs->vs_tpg[target] = NULL;
                match = true;
                mutex_unlock(&tpg->tv_tpg_mutex);
+               /*
+                * Release se_tpg->tpg_group.cg_item configfs dependency now
+                * to allow vhost-scsi WWPN se_tpg->tpg_group shutdown to occur.
+                */
+               se_tpg = &tpg->se_tpg;
+               configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
+                                      &se_tpg->tpg_group.cg_item);
        }
        if (match) {
                for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
index 8d03924749b847fa43577860101b7f42569e39ef..efb09046a8cf7b3d8e56a4cf267fdff98f2ff194 100644 (file)
@@ -168,7 +168,6 @@ if BACKLIGHT_CLASS_DEVICE
 config BACKLIGHT_ATMEL_LCDC
        bool "Atmel LCDC Contrast-as-Backlight control"
        depends on FB_ATMEL
-       default y if MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK || MACH_AT91SAM9263EK
        help
          This provides a backlight control internal to the Atmel LCDC
          driver.  If the LCD "contrast control" on your board is wired
index 57b1d44acbfe3d0782e0960a70eefadcdf864b36..eb976ee3a02f30d6fd751c813318c18fbf026627 100644 (file)
@@ -448,8 +448,10 @@ static int __init fb_console_setup(char *this_opt)
                return 1;
 
        while ((options = strsep(&this_opt, ",")) != NULL) {
-               if (!strncmp(options, "font:", 5))
+               if (!strncmp(options, "font:", 5)) {
                        strlcpy(fontname, options + 5, sizeof(fontname));
+                       continue;
+               }
                
                if (!strncmp(options, "scrollback:", 11)) {
                        options += 11;
@@ -457,13 +459,9 @@ static int __init fb_console_setup(char *this_opt)
                                fbcon_softback_size = simple_strtoul(options, &options, 0);
                                if (*options == 'k' || *options == 'K') {
                                        fbcon_softback_size *= 1024;
-                                       options++;
                                }
-                               if (*options != ',')
-                                       return 1;
-                               options++;
-                       } else
-                               return 1;
+                       }
+                       continue;
                }
                
                if (!strncmp(options, "map:", 4)) {
@@ -478,8 +476,7 @@ static int __init fb_console_setup(char *this_opt)
 
                                fbcon_map_override();
                        }
-
-                       return 1;
+                       continue;
                }
 
                if (!strncmp(options, "vc:", 3)) {
@@ -491,7 +488,8 @@ static int __init fb_console_setup(char *this_opt)
                        if (*options++ == '-')
                                last_fb_vc = simple_strtoul(options, &options, 10) - 1;
                        fbcon_is_default = 0; 
-               }       
+                       continue;
+               }
 
                if (!strncmp(options, "rotate:", 7)) {
                        options += 7;
@@ -499,6 +497,7 @@ static int __init fb_console_setup(char *this_opt)
                                initial_rotation = simple_strtoul(options, &options, 0);
                        if (initial_rotation > 3)
                                initial_rotation = 0;
+                       continue;
                }
        }
        return 1;
index 6e6aa704fe84a1e95bf041ece16dc6f41ec3cf03..517f565b65d760863a05577f60984300532f2f6d 100644 (file)
@@ -56,7 +56,7 @@ static int cursor_size_lastfrom;
 static int cursor_size_lastto;
 static u32 vgacon_xres;
 static u32 vgacon_yres;
-static struct vgastate state;
+static struct vgastate vgastate;
 
 #define BLANK 0x0020
 
@@ -400,7 +400,7 @@ static const char *vgacon_startup(void)
 
        vga_video_num_lines = screen_info.orig_video_lines;
        vga_video_num_columns = screen_info.orig_video_cols;
-       state.vgabase = NULL;
+       vgastate.vgabase = NULL;
 
        if (screen_info.orig_video_mode == 7) {
                /* Monochrome display */
@@ -851,12 +851,12 @@ static void vga_set_palette(struct vc_data *vc, unsigned char *table)
 {
        int i, j;
 
-       vga_w(state.vgabase, VGA_PEL_MSK, 0xff);
+       vga_w(vgastate.vgabase, VGA_PEL_MSK, 0xff);
        for (i = j = 0; i < 16; i++) {
-               vga_w(state.vgabase, VGA_PEL_IW, table[i]);
-               vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
-               vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
-               vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
+               vga_w(vgastate.vgabase, VGA_PEL_IW, table[i]);
+               vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
+               vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
+               vga_w(vgastate.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2);
        }
 }
 
@@ -1008,7 +1008,7 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
        switch (blank) {
        case 0:         /* Unblank */
                if (vga_vesa_blanked) {
-                       vga_vesa_unblank(&state);
+                       vga_vesa_unblank(&vgastate);
                        vga_vesa_blanked = 0;
                }
                if (vga_palette_blanked) {
@@ -1022,7 +1022,7 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
        case 1:         /* Normal blanking */
        case -1:        /* Obsolete */
                if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) {
-                       vga_pal_blank(&state);
+                       vga_pal_blank(&vgastate);
                        vga_palette_blanked = 1;
                        return 0;
                }
@@ -1034,7 +1034,7 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch)
                return 1;
        default:                /* VESA blanking */
                if (vga_video_type == VIDEO_TYPE_VGAC) {
-                       vga_vesa_blank(&state, blank - 1);
+                       vga_vesa_blank(&vgastate, blank - 1);
                        vga_vesa_blanked = blank;
                }
                return 0;
@@ -1280,7 +1280,7 @@ static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigne
            (charcount != 256 && charcount != 512))
                return -EINVAL;
 
-       rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
+       rc = vgacon_do_font_op(&vgastate, font->data, 1, charcount == 512);
        if (rc)
                return rc;
 
@@ -1299,7 +1299,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
        font->charcount = vga_512_chars ? 512 : 256;
        if (!font->data)
                return 0;
-       return vgacon_do_font_op(&state, font->data, 0, vga_512_chars);
+       return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars);
 }
 
 #else
index c7bf606a87064491525563ae16a3a36c8092431b..c78bfd1d1b34ac66f1a35c04dd78d2fdf25a604f 100644 (file)
@@ -999,23 +999,6 @@ config FB_ATMEL
        help
          This enables support for the AT91/AT32 LCD Controller.
 
-config FB_INTSRAM
-       bool "Frame Buffer in internal SRAM"
-       depends on FB_ATMEL && ARCH_AT91SAM9261
-       help
-         Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
-         to let frame buffer in external SDRAM.
-
-config FB_ATMEL_STN
-       bool "Use a STN display with AT91/AT32 LCD Controller"
-       depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK)
-       default n
-       help
-         Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD
-         Controller. Say N if you want to connect a TFT.
-
-         If unsure, say N.
-
 config FB_NVIDIA
        tristate "nVidia Framebuffer Support"
        depends on FB && PCI
index 3bf403150a2d6fbfcf9814df777e1ab51853c72b..9ec81d46fc5785d45a31e159b498513f62139188 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/regulator/consumer.h>
 #include <video/videomode.h>
 
-#include <mach/cpu.h>
 #include <asm/gpio.h>
 
 #include <video/atmel_lcdc.h>
index 5ee3b5505f7fb3d53aff30d0e79a146011df9609..91921665b98b6c3932f7bd6829972e0093569955 100644 (file)
@@ -301,6 +301,8 @@ static const struct of_device_id tvc_of_match[] = {
        {},
 };
 
+MODULE_DEVICE_TABLE(of, tvc_of_match);
+
 static struct platform_driver tvc_connector_driver = {
        .probe  = tvc_probe,
        .remove = __exit_p(tvc_remove),
@@ -308,6 +310,7 @@ static struct platform_driver tvc_connector_driver = {
                .name   = "connector-analog-tv",
                .owner  = THIS_MODULE,
                .of_match_table = tvc_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 74de2bc50c4feca760cb9b0928a24eb288108610..2dfb6e5ff0cc135b32055a2fb5e9a8d6abad29c4 100644 (file)
@@ -391,6 +391,7 @@ static struct platform_driver dvi_connector_driver = {
                .name   = "connector-dvi",
                .owner  = THIS_MODULE,
                .of_match_table = dvic_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 131c6e26089802f4d01feadff8213d4d6dfb1aa4..7b25967a91ebc6235c170e7925ddb229ed8b34df 100644 (file)
@@ -437,6 +437,7 @@ static struct platform_driver hdmi_connector_driver = {
                .name   = "connector-hdmi",
                .owner  = THIS_MODULE,
                .of_match_table = hdmic_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index b4e9a42a79e61cc58d9dc0abd50811e0db694d48..47ee7cdee1c5881a727f97d1863de1f26d6efcc8 100644 (file)
@@ -298,6 +298,7 @@ static struct platform_driver tfp410_driver = {
                .name   = "tfp410",
                .owner  = THIS_MODULE,
                .of_match_table = tfp410_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index c891d8f84cb2706b3fe64777bd2629889fcccb5a..c4abd56dd84697e306e649ff0365fb4504714812 100644 (file)
@@ -461,6 +461,7 @@ static struct platform_driver tpd_driver = {
                .name   = "tpd12s015",
                .owner  = THIS_MODULE,
                .of_match_table = tpd_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 3636b61dc9b4296d0255f89daee0cde1e0860f0c..a9c3dcf0f6b59cefaafcdd3e724062b9e8e6485a 100644 (file)
@@ -327,6 +327,7 @@ static struct platform_driver panel_dpi_driver = {
                .name = "panel-dpi",
                .owner = THIS_MODULE,
                .of_match_table = panel_dpi_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index d6f14e8717e89e87d978131f3b05d8696536a02a..899cb1ab523df05ca6205ddcfe96172bd7559abc 100644 (file)
@@ -1378,6 +1378,7 @@ static struct platform_driver dsicm_driver = {
                .name = "panel-dsi-cm",
                .owner = THIS_MODULE,
                .of_match_table = dsicm_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index cc5b5124e0b4b05409c8ef11a4676bc08992b126..27d4fcfa1824313a7e3799f37b8c7a0deb6c89e7 100644 (file)
@@ -394,6 +394,7 @@ static struct spi_driver lb035q02_spi_driver = {
                .name   = "panel_lgphilips_lb035q02",
                .owner  = THIS_MODULE,
                .of_match_table = lb035q02_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 3595f111aa350c89896b01d1cccfcc89af9740be..ccf3f4f3c70355580ee62dabaf62b6c09e7d4f5c 100644 (file)
@@ -424,6 +424,7 @@ static struct spi_driver nec_8048_driver = {
                .owner  = THIS_MODULE,
                .pm     = NEC_8048_PM_OPS,
                .of_match_table = nec_8048_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe  = nec_8048_probe,
        .remove = nec_8048_remove,
index f1f72ce50a1705b3f6113140b3900226ea834e10..234142cc37641ad10f668118df65f60b2deb04b1 100644 (file)
@@ -410,6 +410,7 @@ static struct platform_driver sharp_ls_driver = {
                .name = "panel-sharp-ls037v7dw01",
                .owner = THIS_MODULE,
                .of_match_table = sharp_ls_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 617f8d2f51273bc48fc474fca9013f5aa7764a5d..337ccc5c0f5eca846b62ba43b053d0f40f1cf335 100644 (file)
@@ -904,6 +904,7 @@ static struct spi_driver acx565akm_driver = {
                .name   = "acx565akm",
                .owner  = THIS_MODULE,
                .of_match_table = acx565akm_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe  = acx565akm_probe,
        .remove = acx565akm_remove,
index 728808bcceebc6545161cfa7925b60a0106d0fe7..fbba0b8ca8718abcb08f7bc8b03e4947e93dc9ba 100644 (file)
@@ -500,6 +500,7 @@ static struct spi_driver td028ttec1_spi_driver = {
                .name   = "panel-tpo-td028ttec1",
                .owner  = THIS_MODULE,
                .of_match_table = td028ttec1_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index de78ab0caaa851ca19fcd589a251f89e4804915d..5aba76bca25a03bfab66dcfe24c485fcf07982fd 100644 (file)
@@ -673,6 +673,7 @@ static struct spi_driver tpo_td043_spi_driver = {
                .owner  = THIS_MODULE,
                .pm     = &tpo_td043_spi_pm,
                .of_match_table = tpo_td043_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe  = tpo_td043_probe,
        .remove = tpo_td043_remove,
index 0a0b084ce65d626ca7619f81065b914d4286bb89..663ccc3bf4e5cebb63ef05250a1e5d9d8edeaa07 100644 (file)
@@ -1132,6 +1132,8 @@ static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
        if (!mp->enabled)
                goto out;
 
+       wait_pending_extra_info_updates();
+
        if (!mgr_manual_update(mgr))
                dispc_mgr_disable_sync(mgr->id);
 
index be053aa80880d0bb1cfcc8f3fb6d908e9f7be80d..0e9a74bb9fc2d8c1cbd2de9ca73b20f94e5f2199 100644 (file)
@@ -3290,8 +3290,11 @@ static void dispc_dump_regs(struct seq_file *s)
                DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS);
                DUMPREG(i, DISPC_OVL_ROW_INC);
                DUMPREG(i, DISPC_OVL_PIXEL_INC);
+
                if (dss_has_feature(FEAT_PRELOAD))
                        DUMPREG(i, DISPC_OVL_PRELOAD);
+               if (dss_has_feature(FEAT_MFLAG))
+                       DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
 
                if (i == OMAP_DSS_GFX) {
                        DUMPREG(i, DISPC_OVL_WINDOW_SKIP);
@@ -3312,10 +3315,6 @@ static void dispc_dump_regs(struct seq_file *s)
                }
                if (dss_has_feature(FEAT_ATTR2))
                        DUMPREG(i, DISPC_OVL_ATTRIBUTES2);
-               if (dss_has_feature(FEAT_PRELOAD))
-                       DUMPREG(i, DISPC_OVL_PRELOAD);
-               if (dss_has_feature(FEAT_MFLAG))
-                       DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD);
        }
 
 #undef DISPC_REG
@@ -3843,6 +3842,7 @@ static struct platform_driver omap_dispchw_driver = {
                .owner  = THIS_MODULE,
                .pm     = &dispc_pm_ops,
                .of_match_table = dispc_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 78edb449c763bf3efc448c3d95c4bd459c3c9002..3043d6e0a5f93c465f7da73b96b308632a4c6c5f 100644 (file)
                                        DISPC_FIR_COEF_V2_OFFSET(n, i))
 #define DISPC_OVL_PRELOAD(n)           (DISPC_OVL_BASE(n) + \
                                        DISPC_PRELOAD_OFFSET(n))
-#define DISPC_OVL_MFLAG_THRESHOLD(n)   (DISPC_OVL_BASE(n) + \
-                                       DISPC_MFLAG_THRESHOLD_OFFSET(n))
+#define DISPC_OVL_MFLAG_THRESHOLD(n)   DISPC_MFLAG_THRESHOLD_OFFSET(n)
 
 /* DISPC up/downsampling FIR filter coefficient structure */
 struct dispc_coef {
index 9368972d696210fbc7ff8d3f91b787b275fd6be2..4a3363dae74aa7479722732102ab4e22ca28fbce 100644 (file)
@@ -720,6 +720,7 @@ static struct platform_driver omap_dpi_driver = {
        .driver         = {
                .name   = "omapdss_dpi",
                .owner  = THIS_MODULE,
+               .suppress_bind_attrs = true,
        },
 };
 
index b6f6ae1d4664e9c8045f5556af19fa6479d0b0d9..0793bc67a275864ece56a4a8605553c5535704ea 100644 (file)
@@ -1603,7 +1603,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
        } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
                f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
 
-               l = FLD_MOD(l, f, 4, 1);        /* PLL_SELFREQDCO */
+               l = FLD_MOD(l, f, 3, 1);        /* PLL_SELFREQDCO */
        }
 
        l = FLD_MOD(l, 1, 13, 13);              /* DSI_PLL_REFEN */
@@ -5754,6 +5754,7 @@ static struct platform_driver omap_dsihw_driver = {
                .owner  = THIS_MODULE,
                .pm     = &dsi_pm_ops,
                .of_match_table = dsi_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 6daeb7ed44c685cd09d2831664c37b2f4071d29f..14bcd6c43f726d6c9e6c88baa2880f80bf8c97b5 100644 (file)
@@ -966,6 +966,7 @@ static struct platform_driver omap_dsshw_driver = {
                .owner  = THIS_MODULE,
                .pm     = &dss_pm_ops,
                .of_match_table = dss_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 6a8550cf43e51b4dc148075dceece5aeab181f94..9a8713ca090c01561548a4e96d37cfd6fb5fb1db 100644 (file)
@@ -781,6 +781,7 @@ static struct platform_driver omapdss_hdmihw_driver = {
                .owner  = THIS_MODULE,
                .pm     = &hdmi_pm_ops,
                .of_match_table = hdmi_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 32d02ec34d2322cdde42481a45ef7801c5d3a90d..169b764bb9d48f6cb188d075a740e0cd4da4dbb3 100644 (file)
@@ -806,6 +806,7 @@ static struct platform_driver omapdss_hdmihw_driver = {
                .owner  = THIS_MODULE,
                .pm     = &hdmi_pm_ops,
                .of_match_table = hdmi_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 54df12a8d744a1b12dc11de98dbf227294ef128c..6d92bb32fe5192e90333b8a38b0db4fa95f341e9 100644 (file)
@@ -124,16 +124,15 @@ static int hdmi_pll_config(struct hdmi_pll_data *pll)
        r = FLD_MOD(r, 0x0, 14, 14);    /* PHY_CLKINEN de-assert during locking */
        r = FLD_MOD(r, fmt->refsel, 22, 21);    /* REFSEL */
 
-       if (fmt->dcofreq) {
-               /* divider programming for frequency beyond 1000Mhz */
-               REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
+       if (fmt->dcofreq)
                r = FLD_MOD(r, 0x4, 3, 1);      /* 1000MHz and 2000MHz */
-       } else {
+       else
                r = FLD_MOD(r, 0x2, 3, 1);      /* 500MHz and 1000MHz */
-       }
 
        hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
 
+       REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
+
        r = hdmi_read_reg(pll->base, PLLCTRL_CFG4);
        r = FLD_MOD(r, fmt->regm2, 24, 18);
        r = FLD_MOD(r, fmt->regmf, 17, 0);
@@ -144,8 +143,8 @@ static int hdmi_pll_config(struct hdmi_pll_data *pll)
 
        /* wait for bit change */
        if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
-                       0, 0, 1) != 1) {
-               DSSERR("PLL GO bit not set\n");
+                       0, 0, 0) != 0) {
+               DSSERR("PLL GO bit not clearing\n");
                return -ETIMEDOUT;
        }
 
index c8a81a2b879cd9ea37e4cae59cf1a88e432e4b3f..878273f58839bb84cd72c24be915a21e9d22e2ff 100644 (file)
@@ -1044,6 +1044,7 @@ static struct platform_driver omap_rfbihw_driver = {
                .name   = "omapdss_rfbi",
                .owner  = THIS_MODULE,
                .pm     = &rfbi_pm_ops,
+               .suppress_bind_attrs = true,
        },
 };
 
index 911dcc9173a6b1e7f0b8e8ae508d8d0ec4bd652b..4c9c46d4ea60dbe2752c11f1933af4788ff41559 100644 (file)
@@ -377,6 +377,7 @@ static struct platform_driver omap_sdi_driver = {
        .driver         = {
                .name   = "omapdss_sdi",
                .owner  = THIS_MODULE,
+               .suppress_bind_attrs = true,
        },
 };
 
index 21d81113962bb81df71783be6f21ac4b7ef9e7b1..d077d8a75ddc8aeecd03d416ee1c080efed09145 100644 (file)
@@ -966,6 +966,7 @@ static struct platform_driver omap_venchw_driver = {
                .owner  = THIS_MODULE,
                .pm     = &venc_pm_ops,
                .of_match_table = venc_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 
index 15872433e0c6a9ae00a209efe181dc3a1bea3a8c..ce8a705707562a4fb2bb91db8a6aec0ea2167f4e 100644 (file)
@@ -1833,14 +1833,13 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
        if (fbdev == NULL)
                return;
 
-       for (i = 0; i < fbdev->num_fbs; i++) {
-               struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
-               int j;
+       for (i = 0; i < fbdev->num_overlays; i++) {
+               struct omap_overlay *ovl = fbdev->overlays[i];
 
-               for (j = 0; j < ofbi->num_overlays; j++) {
-                       struct omap_overlay *ovl = ofbi->overlays[j];
-                       ovl->disable(ovl);
-               }
+               ovl->disable(ovl);
+
+               if (ovl->manager)
+                       ovl->unset_manager(ovl);
        }
 
        for (i = 0; i < fbdev->num_fbs; i++)
@@ -2619,7 +2618,7 @@ err0:
        return r;
 }
 
-static int __exit omapfb_remove(struct platform_device *pdev)
+static int omapfb_remove(struct platform_device *pdev)
 {
        struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
 
@@ -2636,7 +2635,7 @@ static int __exit omapfb_remove(struct platform_device *pdev)
 
 static struct platform_driver omapfb_driver = {
        .probe          = omapfb_probe,
-       .remove         = __exit_p(omapfb_remove),
+       .remove         = omapfb_remove,
        .driver         = {
                .name   = "omapfb",
                .owner  = THIS_MODULE,
@@ -2651,6 +2650,7 @@ module_param_named(mirror, def_mirror, bool, 0);
 
 module_platform_driver(omapfb_driver);
 
+MODULE_ALIAS("platform:omapfb");
 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
 MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
 MODULE_LICENSE("GPL v2");
index 9900e8ec73939fef918abff3bda6829e6b25b4d3..03321d6a268465a7f9c19754ea84f299dda9c95d 100644 (file)
@@ -72,11 +72,18 @@ 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[] = {
+       { .compatible = "ti,omap3-1w" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids);
+
 static struct platform_driver omap_hdq_driver = {
        .probe =        omap_hdq_probe,
        .remove =       omap_hdq_remove,
        .driver =       {
                .name = "omap_hdq",
+               .of_match_table = omap_hdq_dt_ids,
        },
 };
 
index e3d5bf0a50218e0f3c8db39973a90e2cdeabefeb..08f41add146134db9c6975f277b998dee77c70f3 100644 (file)
@@ -87,6 +87,15 @@ config DA9055_WATCHDOG
          This driver can also be built as a module.  If so, the module
          will be called da9055_wdt.
 
+config DA9063_WATCHDOG
+       tristate "Dialog DA9063 Watchdog"
+       depends on MFD_DA9063
+       select WATCHDOG_CORE
+       help
+         Support for the watchdog in the DA9063 PMIC.
+
+         This driver can be built as a module. The module name is da9063_wdt.
+
 config GPIO_WATCHDOG
        tristate "Watchdog device controlled through GPIO-line"
        depends on OF_GPIO
@@ -123,6 +132,7 @@ config WM8350_WATCHDOG
 
 config XILINX_WATCHDOG
        tristate "Xilinx Watchdog timer"
+       depends on HAS_IOMEM
        select WATCHDOG_CORE
        help
          Watchdog driver for the xps_timebase_wdt ip core.
@@ -144,19 +154,27 @@ config ARM_SP805_WATCHDOG
 
 config AT91RM9200_WATCHDOG
        tristate "AT91RM9200 watchdog"
-       depends on ARCH_AT91RM9200
+       depends on SOC_AT91RM9200
        help
          Watchdog timer embedded into AT91RM9200 chips. This will reboot your
          system when the timeout is reached.
 
 config AT91SAM9X_WATCHDOG
        tristate "AT91SAM9X / AT91CAP9 watchdog"
-       depends on ARCH_AT91 && !ARCH_AT91RM9200
+       depends on ARCH_AT91
        select WATCHDOG_CORE
        help
          Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will
          reboot your system when the timeout is reached.
 
+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
+         timer in the Xilinx Zynq.
+
 config 21285_WATCHDOG
        tristate "DC21285 watchdog"
        depends on FOOTBRIDGE
@@ -319,6 +337,17 @@ config ORION_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called orion_wdt.
 
+config RN5T618_WATCHDOG
+       tristate "Ricoh RN5T618 watchdog"
+       depends on MFD_RN5T618
+       select WATCHDOG_CORE
+       help
+         If you say yes here you get support for watchdog on the Ricoh
+         RN5T618 PMIC.
+
+         This driver can also be built as a module.  If so, the module
+         will be called rn5t618_wdt.
+
 config SUNXI_WATCHDOG
        tristate "Allwinner SoCs watchdog support"
        depends on ARCH_SUNXI
@@ -444,7 +473,7 @@ config SIRFSOC_WATCHDOG
 
 config TEGRA_WATCHDOG
        tristate "Tegra watchdog"
-       depends on ARCH_TEGRA || COMPILE_TEST
+       depends on (ARCH_TEGRA || COMPILE_TEST) && HAS_IOMEM
        select WATCHDOG_CORE
        help
          Say Y here to include support for the watchdog timer
@@ -453,6 +482,29 @@ config TEGRA_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called tegra_wdt.
 
+config QCOM_WDT
+       tristate "QCOM watchdog"
+       depends on HAS_IOMEM
+       depends on ARCH_QCOM
+       select WATCHDOG_CORE
+       help
+         Say Y here to include Watchdog timer support for the watchdog found
+         on QCOM chipsets.  Currently supported targets are the MSM8960,
+         APQ8064, and IPQ8064.
+
+         To compile this driver as a module, choose M here: the
+         module will be called qcom_wdt.
+
+config MESON_WATCHDOG
+       tristate "Amlogic Meson SoCs watchdog support"
+       depends on ARCH_MESON
+       select WATCHDOG_CORE
+       help
+         Say Y here to include support for the watchdog timer
+         in Amlogic Meson SoCs.
+         To compile this driver as a module, choose M here: the
+         module will be called meson_wdt.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
index de1701470c14fd12f2bfcc08b74fd56cedbe3a6a..c569ec8f8a76b9d78ad4a8ef8d61313cb1ae7ce9 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
 obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
 obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
+obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o
 obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 obj-$(CONFIG_TWL4030_WATCHDOG) += twl4030_wdt.o
 obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
@@ -47,6 +48,7 @@ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o
 obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
 obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
 obj-$(CONFIG_SUNXI_WATCHDOG) += sunxi_wdt.o
+obj-$(CONFIG_RN5T618_WATCHDOG) += rn5t618_wdt.o
 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
 obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
@@ -57,8 +59,10 @@ obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o
 obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
 obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o
 obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o
+obj-$(CONFIG_QCOM_WDT) += qcom-wdt.o
 obj-$(CONFIG_BCM_KONA_WDT) += bcm_kona_wdt.o
 obj-$(CONFIG_TEGRA_WATCHDOG) += tegra_wdt.o
+obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
@@ -173,6 +177,7 @@ obj-$(CONFIG_XEN_WDT) += xen_wdt.o
 # Architecture Independent
 obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o
 obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o
+obj-$(CONFIG_DA9063_WATCHDOG) += da9063_wdt.o
 obj-$(CONFIG_GPIO_WATCHDOG)    += gpio_wdt.o
 obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
index 08a785398eacfd3b54d47f5eb12770632ee339e5..e96b09b135c8faed6b544e522cd58ed446aedeae 100644 (file)
@@ -30,8 +30,6 @@
  * occur, and the final time the board will reset.
  */
 
-u32 booke_wdt_enabled;
-u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
 
 #ifdef CONFIG_PPC_FSL_BOOK3E
 #define WDTP(x)                ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
@@ -41,27 +39,10 @@ u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
 #define WDTP_MASK      (TCR_WP_MASK)
 #endif
 
-/* Checks wdt=x and wdt_period=xx command-line option */
-notrace int __init early_parse_wdt(char *p)
-{
-       if (p && strncmp(p, "0", 1) != 0)
-               booke_wdt_enabled = 1;
-
-       return 0;
-}
-early_param("wdt", early_parse_wdt);
-
-int __init early_parse_wdt_period(char *p)
-{
-       unsigned long ret;
-       if (p) {
-               if (!kstrtol(p, 0, &ret))
-                       booke_wdt_period = ret;
-       }
-
-       return 0;
-}
-early_param("wdt_period", early_parse_wdt_period);
+static bool booke_wdt_enabled;
+module_param(booke_wdt_enabled, bool, 0);
+static int  booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
+module_param(booke_wdt_period, int, 0);
 
 #ifdef CONFIG_PPC_FSL_BOOK3E
 
@@ -259,5 +240,6 @@ static int __init booke_wdt_init(void)
 module_init(booke_wdt_init);
 module_exit(booke_wdt_exit);
 
+MODULE_ALIAS("booke_wdt");
 MODULE_DESCRIPTION("PowerPC Book-E watchdog driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c
new file mode 100644 (file)
index 0000000..5927c0a
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * Cadence WDT driver - Used by Xilinx Zynq
+ *
+ * Copyright (C) 2010 - 2014 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/watchdog.h>
+
+#define CDNS_WDT_DEFAULT_TIMEOUT       10
+/* Supports 1 - 516 sec */
+#define CDNS_WDT_MIN_TIMEOUT   1
+#define CDNS_WDT_MAX_TIMEOUT   516
+
+/* Restart key */
+#define CDNS_WDT_RESTART_KEY 0x00001999
+
+/* Counter register access key */
+#define CDNS_WDT_REGISTER_ACCESS_KEY 0x00920000
+
+/* Counter value divisor */
+#define CDNS_WDT_COUNTER_VALUE_DIVISOR 0x1000
+
+/* Clock prescaler value and selection */
+#define CDNS_WDT_PRESCALE_64   64
+#define CDNS_WDT_PRESCALE_512  512
+#define CDNS_WDT_PRESCALE_4096 4096
+#define CDNS_WDT_PRESCALE_SELECT_64    1
+#define CDNS_WDT_PRESCALE_SELECT_512   2
+#define CDNS_WDT_PRESCALE_SELECT_4096  3
+
+/* Input clock frequency */
+#define CDNS_WDT_CLK_10MHZ     10000000
+#define CDNS_WDT_CLK_75MHZ     75000000
+
+/* Counter maximum value */
+#define CDNS_WDT_COUNTER_MAX 0xFFF
+
+static int wdt_timeout = CDNS_WDT_DEFAULT_TIMEOUT;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_timeout, int, 0);
+MODULE_PARM_DESC(wdt_timeout,
+                "Watchdog time in seconds. (default="
+                __MODULE_STRING(CDNS_WDT_DEFAULT_TIMEOUT) ")");
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+                "Watchdog cannot be stopped once started (default="
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+/**
+ * struct cdns_wdt - Watchdog device structure
+ * @regs: baseaddress of device
+ * @rst: reset flag
+ * @clk: struct clk * of a clock source
+ * @prescaler: for saving prescaler value
+ * @ctrl_clksel: counter clock prescaler selection
+ * @io_lock: spinlock for IO register access
+ * @cdns_wdt_device: watchdog device structure
+ * @cdns_wdt_notifier: notifier structure
+ *
+ * Structure containing parameters specific to cadence watchdog.
+ */
+struct cdns_wdt {
+       void __iomem            *regs;
+       bool                    rst;
+       struct clk              *clk;
+       u32                     prescaler;
+       u32                     ctrl_clksel;
+       spinlock_t              io_lock;
+       struct watchdog_device  cdns_wdt_device;
+       struct notifier_block   cdns_wdt_notifier;
+};
+
+/* Write access to Registers */
+static inline void cdns_wdt_writereg(struct cdns_wdt *wdt, u32 offset, u32 val)
+{
+       writel_relaxed(val, wdt->regs + offset);
+}
+
+/*************************Register Map**************************************/
+
+/* Register Offsets for the WDT */
+#define CDNS_WDT_ZMR_OFFSET    0x0     /* Zero Mode Register */
+#define CDNS_WDT_CCR_OFFSET    0x4     /* Counter Control Register */
+#define CDNS_WDT_RESTART_OFFSET        0x8     /* Restart Register */
+#define CDNS_WDT_SR_OFFSET     0xC     /* Status Register */
+
+/*
+ * Zero Mode Register - This register controls how the time out is indicated
+ * and also contains the access code to allow writes to the register (0xABC).
+ */
+#define CDNS_WDT_ZMR_WDEN_MASK 0x00000001 /* Enable the WDT */
+#define CDNS_WDT_ZMR_RSTEN_MASK        0x00000002 /* Enable the reset output */
+#define CDNS_WDT_ZMR_IRQEN_MASK        0x00000004 /* Enable IRQ output */
+#define CDNS_WDT_ZMR_RSTLEN_16 0x00000030 /* Reset pulse of 16 pclk cycles */
+#define CDNS_WDT_ZMR_ZKEY_VAL  0x00ABC000 /* Access key, 0xABC << 12 */
+/*
+ * Counter Control register - This register controls how fast the timer runs
+ * and the reset value and also contains the access code to allow writes to
+ * the register.
+ */
+#define CDNS_WDT_CCR_CRV_MASK  0x00003FFC /* Counter reset value */
+
+/**
+ * cdns_wdt_stop - Stop the watchdog.
+ *
+ * @wdd: watchdog device
+ *
+ * Read the contents of the ZMR register, clear the WDEN bit
+ * in the register and set the access key for successful write.
+ *
+ * Return: always 0
+ */
+static int cdns_wdt_stop(struct watchdog_device *wdd)
+{
+       struct cdns_wdt *wdt = watchdog_get_drvdata(wdd);
+
+       spin_lock(&wdt->io_lock);
+       cdns_wdt_writereg(wdt, CDNS_WDT_ZMR_OFFSET,
+                         CDNS_WDT_ZMR_ZKEY_VAL & (~CDNS_WDT_ZMR_WDEN_MASK));
+       spin_unlock(&wdt->io_lock);
+
+       return 0;
+}
+
+/**
+ * cdns_wdt_reload - Reload the watchdog timer (i.e. pat the watchdog).
+ *
+ * @wdd: watchdog device
+ *
+ * Write the restart key value (0x00001999) to the restart register.
+ *
+ * Return: always 0
+ */
+static int cdns_wdt_reload(struct watchdog_device *wdd)
+{
+       struct cdns_wdt *wdt = watchdog_get_drvdata(wdd);
+
+       spin_lock(&wdt->io_lock);
+       cdns_wdt_writereg(wdt, CDNS_WDT_RESTART_OFFSET,
+                         CDNS_WDT_RESTART_KEY);
+       spin_unlock(&wdt->io_lock);
+
+       return 0;
+}
+
+/**
+ * cdns_wdt_start - Enable and start the watchdog.
+ *
+ * @wdd: watchdog device
+ *
+ * The counter value is calculated according to the formula:
+ *             calculated count = (timeout * clock) / prescaler + 1.
+ * The calculated count is divided by 0x1000 to obtain the field value
+ * to write to counter control register.
+ * Clears the contents of prescaler and counter reset value. Sets the
+ * prescaler to 4096 and the calculated count and access key
+ * to write to CCR Register.
+ * Sets the WDT (WDEN bit) and either the Reset signal(RSTEN bit)
+ * or Interrupt signal(IRQEN) with a specified cycles and the access
+ * key to write to ZMR Register.
+ *
+ * Return: always 0
+ */
+static int cdns_wdt_start(struct watchdog_device *wdd)
+{
+       struct cdns_wdt *wdt = watchdog_get_drvdata(wdd);
+       unsigned int data = 0;
+       unsigned short count;
+       unsigned long clock_f = clk_get_rate(wdt->clk);
+
+       /*
+        * Counter value divisor to obtain the value of
+        * counter reset to be written to control register.
+        */
+       count = (wdd->timeout * (clock_f / wdt->prescaler)) /
+                CDNS_WDT_COUNTER_VALUE_DIVISOR + 1;
+
+       if (count > CDNS_WDT_COUNTER_MAX)
+               count = CDNS_WDT_COUNTER_MAX;
+
+       spin_lock(&wdt->io_lock);
+       cdns_wdt_writereg(wdt, CDNS_WDT_ZMR_OFFSET,
+                         CDNS_WDT_ZMR_ZKEY_VAL);
+
+       count = (count << 2) & CDNS_WDT_CCR_CRV_MASK;
+
+       /* Write counter access key first to be able write to register */
+       data = count | CDNS_WDT_REGISTER_ACCESS_KEY | wdt->ctrl_clksel;
+       cdns_wdt_writereg(wdt, CDNS_WDT_CCR_OFFSET, data);
+       data = CDNS_WDT_ZMR_WDEN_MASK | CDNS_WDT_ZMR_RSTLEN_16 |
+              CDNS_WDT_ZMR_ZKEY_VAL;
+
+       /* Reset on timeout if specified in device tree. */
+       if (wdt->rst) {
+               data |= CDNS_WDT_ZMR_RSTEN_MASK;
+               data &= ~CDNS_WDT_ZMR_IRQEN_MASK;
+       } else {
+               data &= ~CDNS_WDT_ZMR_RSTEN_MASK;
+               data |= CDNS_WDT_ZMR_IRQEN_MASK;
+       }
+       cdns_wdt_writereg(wdt, CDNS_WDT_ZMR_OFFSET, data);
+       cdns_wdt_writereg(wdt, CDNS_WDT_RESTART_OFFSET,
+                         CDNS_WDT_RESTART_KEY);
+       spin_unlock(&wdt->io_lock);
+
+       return 0;
+}
+
+/**
+ * cdns_wdt_settimeout - Set a new timeout value for the watchdog device.
+ *
+ * @wdd: watchdog device
+ * @new_time: new timeout value that needs to be set
+ * Return: 0 on success
+ *
+ * Update the watchdog_device timeout with new value which is used when
+ * cdns_wdt_start is called.
+ */
+static int cdns_wdt_settimeout(struct watchdog_device *wdd,
+                              unsigned int new_time)
+{
+       wdd->timeout = new_time;
+
+       return cdns_wdt_start(wdd);
+}
+
+/**
+ * cdns_wdt_irq_handler - Notifies of watchdog timeout.
+ *
+ * @irq: interrupt number
+ * @dev_id: pointer to a platform device structure
+ * Return: IRQ_HANDLED
+ *
+ * The handler is invoked when the watchdog times out and a
+ * reset on timeout has not been enabled.
+ */
+static irqreturn_t cdns_wdt_irq_handler(int irq, void *dev_id)
+{
+       struct platform_device *pdev = dev_id;
+
+       dev_info(&pdev->dev,
+                "Watchdog timed out. Internal reset not enabled\n");
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * Info structure used to indicate the features supported by the device
+ * to the upper layers. This is defined in watchdog.h header file.
+ */
+static struct watchdog_info cdns_wdt_info = {
+       .identity       = "cdns_wdt watchdog",
+       .options        = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+                         WDIOF_MAGICCLOSE,
+};
+
+/* Watchdog Core Ops */
+static struct watchdog_ops cdns_wdt_ops = {
+       .owner = THIS_MODULE,
+       .start = cdns_wdt_start,
+       .stop = cdns_wdt_stop,
+       .ping = cdns_wdt_reload,
+       .set_timeout = cdns_wdt_settimeout,
+};
+
+/**
+ * cdns_wdt_notify_sys - Notifier for reboot or shutdown.
+ *
+ * @this: handle to notifier block
+ * @code: turn off indicator
+ * @unused: unused
+ * Return: NOTIFY_DONE
+ *
+ * This notifier is invoked whenever the system reboot or shutdown occur
+ * because we need to disable the WDT before system goes down as WDT might
+ * reset on the next boot.
+ */
+static int cdns_wdt_notify_sys(struct notifier_block *this, unsigned long code,
+                              void *unused)
+{
+       struct cdns_wdt *wdt = container_of(this, struct cdns_wdt,
+                                           cdns_wdt_notifier);
+       if (code == SYS_DOWN || code == SYS_HALT)
+               cdns_wdt_stop(&wdt->cdns_wdt_device);
+
+       return NOTIFY_DONE;
+}
+
+/************************Platform Operations*****************************/
+/**
+ * cdns_wdt_probe - Probe call for the device.
+ *
+ * @pdev: handle to the platform device structure.
+ * Return: 0 on success, negative error otherwise.
+ *
+ * It does all the memory allocation and registration for the device.
+ */
+static int cdns_wdt_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       int ret, irq;
+       unsigned long clock_f;
+       struct cdns_wdt *wdt;
+       struct watchdog_device *cdns_wdt_device;
+
+       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+       if (!wdt)
+               return -ENOMEM;
+
+       cdns_wdt_device = &wdt->cdns_wdt_device;
+       cdns_wdt_device->info = &cdns_wdt_info;
+       cdns_wdt_device->ops = &cdns_wdt_ops;
+       cdns_wdt_device->timeout = CDNS_WDT_DEFAULT_TIMEOUT;
+       cdns_wdt_device->min_timeout = CDNS_WDT_MIN_TIMEOUT;
+       cdns_wdt_device->max_timeout = CDNS_WDT_MAX_TIMEOUT;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       wdt->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(wdt->regs))
+               return PTR_ERR(wdt->regs);
+
+       /* Register the interrupt */
+       wdt->rst = of_property_read_bool(pdev->dev.of_node, "reset-on-timeout");
+       irq = platform_get_irq(pdev, 0);
+       if (!wdt->rst && irq >= 0) {
+               ret = devm_request_irq(&pdev->dev, irq, cdns_wdt_irq_handler, 0,
+                                      pdev->name, pdev);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "cannot register interrupt handler err=%d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       /* Initialize the members of cdns_wdt structure */
+       cdns_wdt_device->parent = &pdev->dev;
+
+       ret = watchdog_init_timeout(cdns_wdt_device, wdt_timeout, &pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to set timeout value\n");
+               return ret;
+       }
+
+       watchdog_set_nowayout(cdns_wdt_device, nowayout);
+       watchdog_set_drvdata(cdns_wdt_device, wdt);
+
+       wdt->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(wdt->clk)) {
+               dev_err(&pdev->dev, "input clock not found\n");
+               ret = PTR_ERR(wdt->clk);
+               return ret;
+       }
+
+       ret = clk_prepare_enable(wdt->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to enable clock\n");
+               return ret;
+       }
+
+       clock_f = clk_get_rate(wdt->clk);
+       if (clock_f <= CDNS_WDT_CLK_75MHZ) {
+               wdt->prescaler = CDNS_WDT_PRESCALE_512;
+               wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_512;
+       } else {
+               wdt->prescaler = CDNS_WDT_PRESCALE_4096;
+               wdt->ctrl_clksel = CDNS_WDT_PRESCALE_SELECT_4096;
+       }
+
+       spin_lock_init(&wdt->io_lock);
+
+       wdt->cdns_wdt_notifier.notifier_call = &cdns_wdt_notify_sys;
+       ret = register_reboot_notifier(&wdt->cdns_wdt_notifier);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "cannot register reboot notifier err=%d)\n",
+                       ret);
+               goto err_clk_disable;
+       }
+
+       ret = watchdog_register_device(cdns_wdt_device);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to register wdt device\n");
+               goto err_clk_disable;
+       }
+       platform_set_drvdata(pdev, wdt);
+
+       dev_dbg(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds%s\n",
+                wdt->regs, cdns_wdt_device->timeout,
+                nowayout ? ", nowayout" : "");
+
+       return 0;
+
+err_clk_disable:
+       clk_disable_unprepare(wdt->clk);
+
+       return ret;
+}
+
+/**
+ * cdns_wdt_remove - Probe call for the device.
+ *
+ * @pdev: handle to the platform device structure.
+ * Return: 0 on success, otherwise negative error.
+ *
+ * Unregister the device after releasing the resources.
+ */
+static int cdns_wdt_remove(struct platform_device *pdev)
+{
+       struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+
+       cdns_wdt_stop(&wdt->cdns_wdt_device);
+       watchdog_unregister_device(&wdt->cdns_wdt_device);
+       unregister_reboot_notifier(&wdt->cdns_wdt_notifier);
+       clk_disable_unprepare(wdt->clk);
+
+       return 0;
+}
+
+/**
+ * cdns_wdt_shutdown - Stop the device.
+ *
+ * @pdev: handle to the platform structure.
+ *
+ */
+static void cdns_wdt_shutdown(struct platform_device *pdev)
+{
+       struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+
+       cdns_wdt_stop(&wdt->cdns_wdt_device);
+       clk_disable_unprepare(wdt->clk);
+}
+
+/**
+ * cdns_wdt_suspend - Stop the device.
+ *
+ * @dev: handle to the device structure.
+ * Return: 0 always.
+ */
+static int __maybe_unused cdns_wdt_suspend(struct device *dev)
+{
+       struct platform_device *pdev = container_of(dev,
+                       struct platform_device, dev);
+       struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+
+       cdns_wdt_stop(&wdt->cdns_wdt_device);
+       clk_disable_unprepare(wdt->clk);
+
+       return 0;
+}
+
+/**
+ * cdns_wdt_resume - Resume the device.
+ *
+ * @dev: handle to the device structure.
+ * Return: 0 on success, errno otherwise.
+ */
+static int __maybe_unused cdns_wdt_resume(struct device *dev)
+{
+       int ret;
+       struct platform_device *pdev = container_of(dev,
+                       struct platform_device, dev);
+       struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+
+       ret = clk_prepare_enable(wdt->clk);
+       if (ret) {
+               dev_err(dev, "unable to enable clock\n");
+               return ret;
+       }
+       cdns_wdt_start(&wdt->cdns_wdt_device);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(cdns_wdt_pm_ops, cdns_wdt_suspend, cdns_wdt_resume);
+
+static struct of_device_id cdns_wdt_of_match[] = {
+       { .compatible = "cdns,wdt-r1p2", },
+       { /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, cdns_wdt_of_match);
+
+/* Driver Structure */
+static struct platform_driver cdns_wdt_driver = {
+       .probe          = cdns_wdt_probe,
+       .remove         = cdns_wdt_remove,
+       .shutdown       = cdns_wdt_shutdown,
+       .driver         = {
+               .name   = "cdns-wdt",
+               .owner  = THIS_MODULE,
+               .of_match_table = cdns_wdt_of_match,
+               .pm     = &cdns_wdt_pm_ops,
+       },
+};
+
+module_platform_driver(cdns_wdt_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Watchdog driver for Cadence WDT");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
new file mode 100644 (file)
index 0000000..2cd6b2c
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Watchdog driver for DA9063 PMICs.
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: Mariusz Wojtasik <mariusz.wojtasik@diasemi.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/kernel.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mfd/da9063/registers.h>
+#include <linux/mfd/da9063/core.h>
+#include <linux/regmap.h>
+
+/*
+ * Watchdog selector to timeout in seconds.
+ *   0: WDT disabled;
+ *   others: timeout = 2048 ms * 2^(TWDSCALE-1).
+ */
+static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
+#define DA9063_TWDSCALE_DISABLE                0
+#define DA9063_TWDSCALE_MIN            1
+#define DA9063_TWDSCALE_MAX            (ARRAY_SIZE(wdt_timeout) - 1)
+#define DA9063_WDT_MIN_TIMEOUT         wdt_timeout[DA9063_TWDSCALE_MIN]
+#define DA9063_WDT_MAX_TIMEOUT         wdt_timeout[DA9063_TWDSCALE_MAX]
+#define DA9063_WDG_TIMEOUT             wdt_timeout[3]
+
+struct da9063_watchdog {
+       struct da9063 *da9063;
+       struct watchdog_device wdtdev;
+};
+
+static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
+{
+       unsigned int i;
+
+       for (i = DA9063_TWDSCALE_MIN; i <= DA9063_TWDSCALE_MAX; i++) {
+               if (wdt_timeout[i] >= secs)
+                       return i;
+       }
+
+       return DA9063_TWDSCALE_MAX;
+}
+
+static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int regval)
+{
+       return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
+                                 DA9063_TWDSCALE_MASK, regval);
+}
+
+static int da9063_wdt_start(struct watchdog_device *wdd)
+{
+       struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
+       unsigned int selector;
+       int ret;
+
+       selector = da9063_wdt_timeout_to_sel(wdt->wdtdev.timeout);
+       ret = _da9063_wdt_set_timeout(wdt->da9063, selector);
+       if (ret)
+               dev_err(wdt->da9063->dev, "Watchdog failed to start (err = %d)\n",
+                       ret);
+
+       return ret;
+}
+
+static int da9063_wdt_stop(struct watchdog_device *wdd)
+{
+       struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
+       int ret;
+
+       ret = regmap_update_bits(wdt->da9063->regmap, DA9063_REG_CONTROL_D,
+                                DA9063_TWDSCALE_MASK, DA9063_TWDSCALE_DISABLE);
+       if (ret)
+               dev_alert(wdt->da9063->dev, "Watchdog failed to stop (err = %d)\n",
+                         ret);
+
+       return ret;
+}
+
+static int da9063_wdt_ping(struct watchdog_device *wdd)
+{
+       struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
+       int ret;
+
+       ret = regmap_write(wdt->da9063->regmap, DA9063_REG_CONTROL_F,
+                          DA9063_WATCHDOG);
+       if (ret)
+               dev_alert(wdt->da9063->dev, "Failed to ping the watchdog (err = %d)\n",
+                         ret);
+
+       return ret;
+}
+
+static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
+                                 unsigned int timeout)
+{
+       struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd);
+       unsigned int selector;
+       int ret;
+
+       selector = da9063_wdt_timeout_to_sel(timeout);
+       ret = _da9063_wdt_set_timeout(wdt->da9063, selector);
+       if (ret)
+               dev_err(wdt->da9063->dev, "Failed to set watchdog timeout (err = %d)\n",
+                       ret);
+       else
+               wdd->timeout = wdt_timeout[selector];
+
+       return ret;
+}
+
+static const struct watchdog_info da9063_watchdog_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+       .identity = "DA9063 Watchdog",
+};
+
+static const struct watchdog_ops da9063_watchdog_ops = {
+       .owner = THIS_MODULE,
+       .start = da9063_wdt_start,
+       .stop = da9063_wdt_stop,
+       .ping = da9063_wdt_ping,
+       .set_timeout = da9063_wdt_set_timeout,
+};
+
+static int da9063_wdt_probe(struct platform_device *pdev)
+{
+       int ret;
+       struct da9063 *da9063;
+       struct da9063_watchdog *wdt;
+
+       if (!pdev->dev.parent)
+               return -EINVAL;
+
+       da9063 = dev_get_drvdata(pdev->dev.parent);
+       if (!da9063)
+               return -EINVAL;
+
+       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+       if (!wdt)
+               return -ENOMEM;
+
+       wdt->da9063 = da9063;
+
+       wdt->wdtdev.info = &da9063_watchdog_info;
+       wdt->wdtdev.ops = &da9063_watchdog_ops;
+       wdt->wdtdev.min_timeout = DA9063_WDT_MIN_TIMEOUT;
+       wdt->wdtdev.max_timeout = DA9063_WDT_MAX_TIMEOUT;
+       wdt->wdtdev.timeout = DA9063_WDG_TIMEOUT;
+
+       wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
+
+       watchdog_set_drvdata(&wdt->wdtdev, wdt);
+       dev_set_drvdata(&pdev->dev, wdt);
+
+       ret = watchdog_register_device(&wdt->wdtdev);
+
+       return ret;
+}
+
+static int da9063_wdt_remove(struct platform_device *pdev)
+{
+       struct da9063_watchdog *wdt = dev_get_drvdata(&pdev->dev);
+
+       watchdog_unregister_device(&wdt->wdtdev);
+
+       return 0;
+}
+
+static struct platform_driver da9063_wdt_driver = {
+       .probe = da9063_wdt_probe,
+       .remove = da9063_wdt_remove,
+       .driver = {
+               .name = DA9063_DRVNAME_WATCHDOG,
+       },
+};
+module_platform_driver(da9063_wdt_driver);
+
+MODULE_AUTHOR("Mariusz Wojtasik <mariusz.wojtasik@diasemi.com>");
+MODULE_DESCRIPTION("Watchdog driver for Dialog DA9063");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DA9063_DRVNAME_WATCHDOG);
index 9f210299de2491cd9c9ed654268e0bda991a6c5e..9e577a64ec9e566fa52ea977f5d5ca49d17a0f03 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/bitops.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/notifier.h>
 #include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
+#include <linux/reboot.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/uaccess.h>
@@ -40,6 +43,7 @@
 #define WDOG_CONTROL_REG_OFFSET                    0x00
 #define WDOG_CONTROL_REG_WDT_EN_MASK       0x01
 #define WDOG_TIMEOUT_RANGE_REG_OFFSET      0x04
+#define WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT    4
 #define WDOG_CURRENT_COUNT_REG_OFFSET      0x08
 #define WDOG_COUNTER_RESTART_REG_OFFSET     0x0c
 #define WDOG_COUNTER_RESTART_KICK_VALUE            0x76
@@ -62,6 +66,7 @@ static struct {
        unsigned long           next_heartbeat;
        struct timer_list       timer;
        int                     expect_close;
+       struct notifier_block   restart_handler;
 } dw_wdt;
 
 static inline int dw_wdt_is_enabled(void)
@@ -106,7 +111,8 @@ static int dw_wdt_set_top(unsigned top_s)
                }
 
        /* Set the new value in the watchdog. */
-       writel(top_val, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+       writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT,
+               dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
 
        dw_wdt_set_next_heartbeat();
 
@@ -119,6 +125,26 @@ static void dw_wdt_keepalive(void)
               WDOG_COUNTER_RESTART_REG_OFFSET);
 }
 
+static int dw_wdt_restart_handle(struct notifier_block *this,
+                               unsigned long mode, void *cmd)
+{
+       u32 val;
+
+       writel(0, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+       val = readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
+       if (val & WDOG_CONTROL_REG_WDT_EN_MASK)
+               writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
+                       WDOG_COUNTER_RESTART_REG_OFFSET);
+       else
+               writel(WDOG_CONTROL_REG_WDT_EN_MASK,
+                      dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
+
+       /* wait for reset to assert... */
+       mdelay(500);
+
+       return NOTIFY_DONE;
+}
+
 static void dw_wdt_ping(unsigned long data)
 {
        if (time_before(jiffies, dw_wdt.next_heartbeat) ||
@@ -314,6 +340,12 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
        if (ret)
                goto out_disable_clk;
 
+       dw_wdt.restart_handler.notifier_call = dw_wdt_restart_handle;
+       dw_wdt.restart_handler.priority = 128;
+       ret = register_restart_handler(&dw_wdt.restart_handler);
+       if (ret)
+               pr_warn("cannot register restart handler\n");
+
        dw_wdt_set_next_heartbeat();
        setup_timer(&dw_wdt.timer, dw_wdt_ping, 0);
        mod_timer(&dw_wdt.timer, jiffies + WDT_TIMEOUT);
@@ -328,6 +360,8 @@ out_disable_clk:
 
 static int dw_wdt_drv_remove(struct platform_device *pdev)
 {
+       unregister_restart_handler(&dw_wdt.restart_handler);
+
        misc_deregister(&dw_wdt_miscdev);
 
        clk_disable_unprepare(dw_wdt.clk);
index 68c3d379ffa8c599333af45abc1b0841fd10059e..7e12f88bb4a688748d52bc0d423182c2434d34a1 100644 (file)
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/notifier.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/reboot.h>
 #include <linux/regmap.h>
 #include <linux/timer.h>
 #include <linux/watchdog.h>
@@ -59,6 +62,7 @@ struct imx2_wdt_device {
        struct regmap *regmap;
        struct timer_list timer;        /* Pings the watchdog when closed */
        struct watchdog_device wdog;
+       struct notifier_block restart_handler;
 };
 
 static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -77,6 +81,31 @@ static const struct watchdog_info imx2_wdt_info = {
        .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
 };
 
+static int imx2_restart_handler(struct notifier_block *this, unsigned long mode,
+                               void *cmd)
+{
+       unsigned int wcr_enable = IMX2_WDT_WCR_WDE;
+       struct imx2_wdt_device *wdev = container_of(this,
+                                                   struct imx2_wdt_device,
+                                                   restart_handler);
+       /* Assert SRS signal */
+       regmap_write(wdev->regmap, 0, wcr_enable);
+       /*
+        * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
+        * written twice), we add another two writes to ensure there must be at
+        * least two writes happen in the same one 32kHz clock period.  We save
+        * the target check here, since the writes shouldn't be a huge burden
+        * for other platforms.
+        */
+       regmap_write(wdev->regmap, 0, wcr_enable);
+       regmap_write(wdev->regmap, 0, wcr_enable);
+
+       /* wait for reset to assert... */
+       mdelay(500);
+
+       return NOTIFY_DONE;
+}
+
 static inline void imx2_wdt_setup(struct watchdog_device *wdog)
 {
        struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
@@ -191,12 +220,10 @@ static struct regmap_config imx2_wdt_regmap_config = {
 
 static int __init imx2_wdt_probe(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node;
        struct imx2_wdt_device *wdev;
        struct watchdog_device *wdog;
        struct resource *res;
        void __iomem *base;
-       bool big_endian;
        int ret;
        u32 val;
 
@@ -204,10 +231,6 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
        if (!wdev)
                return -ENOMEM;
 
-       big_endian = of_property_read_bool(np, "big-endian");
-       if (big_endian)
-               imx2_wdt_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
@@ -257,6 +280,12 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
                return ret;
        }
 
+       wdev->restart_handler.notifier_call = imx2_restart_handler;
+       wdev->restart_handler.priority = 128;
+       ret = register_restart_handler(&wdev->restart_handler);
+       if (ret)
+               dev_err(&pdev->dev, "cannot register restart handler\n");
+
        dev_info(&pdev->dev, "timeout %d sec (nowayout=%d)\n",
                 wdog->timeout, nowayout);
 
@@ -268,6 +297,8 @@ static int __exit imx2_wdt_remove(struct platform_device *pdev)
        struct watchdog_device *wdog = platform_get_drvdata(pdev);
        struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
 
+       unregister_restart_handler(&wdev->restart_handler);
+
        watchdog_unregister_device(wdog);
 
        if (imx2_wdt_is_running(wdev)) {
diff --git a/drivers/watchdog/meson_wdt.c b/drivers/watchdog/meson_wdt.c
new file mode 100644 (file)
index 0000000..ef6a298
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ *      Meson Watchdog Driver
+ *
+ *      Copyright (c) 2014 Carlo Caione
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#define DRV_NAME               "meson_wdt"
+
+#define MESON_WDT_TC           0x00
+#define MESON_WDT_TC_EN                BIT(22)
+#define MESON_WDT_TC_TM_MASK   0x3fffff
+#define MESON_WDT_DC_RESET     (3 << 24)
+
+#define MESON_WDT_RESET                0x04
+
+#define MESON_WDT_TIMEOUT      30
+#define MESON_WDT_MIN_TIMEOUT  1
+#define MESON_WDT_MAX_TIMEOUT  (MESON_WDT_TC_TM_MASK / 100000)
+
+#define MESON_SEC_TO_TC(s)     ((s) * 100000)
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+static unsigned int timeout = MESON_WDT_TIMEOUT;
+
+struct meson_wdt_dev {
+       struct watchdog_device wdt_dev;
+       void __iomem *wdt_base;
+       struct notifier_block restart_handler;
+};
+
+static int meson_restart_handle(struct notifier_block *this, unsigned long mode,
+                               void *cmd)
+{
+       u32 tc_reboot = MESON_WDT_DC_RESET | MESON_WDT_TC_EN;
+       struct meson_wdt_dev *meson_wdt = container_of(this,
+                                                      struct meson_wdt_dev,
+                                                      restart_handler);
+
+       while (1) {
+               writel(tc_reboot, meson_wdt->wdt_base + MESON_WDT_TC);
+               mdelay(5);
+       }
+
+       return NOTIFY_DONE;
+}
+
+static int meson_wdt_ping(struct watchdog_device *wdt_dev)
+{
+       struct meson_wdt_dev *meson_wdt = watchdog_get_drvdata(wdt_dev);
+
+       writel(0, meson_wdt->wdt_base + MESON_WDT_RESET);
+
+       return 0;
+}
+
+static void meson_wdt_change_timeout(struct watchdog_device *wdt_dev,
+                                    unsigned int timeout)
+{
+       struct meson_wdt_dev *meson_wdt = watchdog_get_drvdata(wdt_dev);
+       u32 reg;
+
+       reg = readl(meson_wdt->wdt_base + MESON_WDT_TC);
+       reg &= ~MESON_WDT_TC_TM_MASK;
+       reg |= MESON_SEC_TO_TC(timeout);
+       writel(reg, meson_wdt->wdt_base + MESON_WDT_TC);
+}
+
+static int meson_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                unsigned int timeout)
+{
+       wdt_dev->timeout = timeout;
+
+       meson_wdt_change_timeout(wdt_dev, timeout);
+       meson_wdt_ping(wdt_dev);
+
+       return 0;
+}
+
+static int meson_wdt_stop(struct watchdog_device *wdt_dev)
+{
+       struct meson_wdt_dev *meson_wdt = watchdog_get_drvdata(wdt_dev);
+       u32 reg;
+
+       reg = readl(meson_wdt->wdt_base + MESON_WDT_TC);
+       reg &= ~MESON_WDT_TC_EN;
+       writel(reg, meson_wdt->wdt_base + MESON_WDT_TC);
+
+       return 0;
+}
+
+static int meson_wdt_start(struct watchdog_device *wdt_dev)
+{
+       struct meson_wdt_dev *meson_wdt = watchdog_get_drvdata(wdt_dev);
+       u32 reg;
+
+       meson_wdt_change_timeout(wdt_dev, meson_wdt->wdt_dev.timeout);
+       meson_wdt_ping(wdt_dev);
+
+       reg = readl(meson_wdt->wdt_base + MESON_WDT_TC);
+       reg |= MESON_WDT_TC_EN;
+       writel(reg, meson_wdt->wdt_base + MESON_WDT_TC);
+
+       return 0;
+}
+
+static const struct watchdog_info meson_wdt_info = {
+       .identity       = DRV_NAME,
+       .options        = WDIOF_SETTIMEOUT |
+                         WDIOF_KEEPALIVEPING |
+                         WDIOF_MAGICCLOSE,
+};
+
+static const struct watchdog_ops meson_wdt_ops = {
+       .owner          = THIS_MODULE,
+       .start          = meson_wdt_start,
+       .stop           = meson_wdt_stop,
+       .ping           = meson_wdt_ping,
+       .set_timeout    = meson_wdt_set_timeout,
+};
+
+static int meson_wdt_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct meson_wdt_dev *meson_wdt;
+       int err;
+
+       meson_wdt = devm_kzalloc(&pdev->dev, sizeof(*meson_wdt), GFP_KERNEL);
+       if (!meson_wdt)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       meson_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(meson_wdt->wdt_base))
+               return PTR_ERR(meson_wdt->wdt_base);
+
+       meson_wdt->wdt_dev.parent = &pdev->dev;
+       meson_wdt->wdt_dev.info = &meson_wdt_info;
+       meson_wdt->wdt_dev.ops = &meson_wdt_ops;
+       meson_wdt->wdt_dev.timeout = MESON_WDT_TIMEOUT;
+       meson_wdt->wdt_dev.max_timeout = MESON_WDT_MAX_TIMEOUT;
+       meson_wdt->wdt_dev.min_timeout = MESON_WDT_MIN_TIMEOUT;
+
+       watchdog_set_drvdata(&meson_wdt->wdt_dev, meson_wdt);
+
+       watchdog_init_timeout(&meson_wdt->wdt_dev, timeout, &pdev->dev);
+       watchdog_set_nowayout(&meson_wdt->wdt_dev, nowayout);
+
+       meson_wdt_stop(&meson_wdt->wdt_dev);
+
+       err = watchdog_register_device(&meson_wdt->wdt_dev);
+       if (err)
+               return err;
+
+       platform_set_drvdata(pdev, meson_wdt);
+
+       meson_wdt->restart_handler.notifier_call = meson_restart_handle;
+       meson_wdt->restart_handler.priority = 128;
+       err = register_restart_handler(&meson_wdt->restart_handler);
+       if (err)
+               dev_err(&pdev->dev,
+                       "cannot register restart handler (err=%d)\n", err);
+
+       dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)",
+                meson_wdt->wdt_dev.timeout, nowayout);
+
+       return 0;
+}
+
+static int meson_wdt_remove(struct platform_device *pdev)
+{
+       struct meson_wdt_dev *meson_wdt = platform_get_drvdata(pdev);
+
+       unregister_restart_handler(&meson_wdt->restart_handler);
+
+       watchdog_unregister_device(&meson_wdt->wdt_dev);
+
+       return 0;
+}
+
+static void meson_wdt_shutdown(struct platform_device *pdev)
+{
+       struct meson_wdt_dev *meson_wdt = platform_get_drvdata(pdev);
+
+       meson_wdt_stop(&meson_wdt->wdt_dev);
+}
+
+static const struct of_device_id meson_wdt_dt_ids[] = {
+       { .compatible = "amlogic,meson6-wdt" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, meson_wdt_dt_ids);
+
+static struct platform_driver meson_wdt_driver = {
+       .probe          = meson_wdt_probe,
+       .remove         = meson_wdt_remove,
+       .shutdown       = meson_wdt_shutdown,
+       .driver         = {
+               .owner          = THIS_MODULE,
+               .name           = DRV_NAME,
+               .of_match_table = meson_wdt_dt_ids,
+       },
+};
+
+module_platform_driver(meson_wdt_driver);
+
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds");
+
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+                "Watchdog cannot be stopped once started (default="
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_DESCRIPTION("Meson Watchdog Timer Driver");
index 1e6e28df5d7b8030973c7a0c50d83466fb5b3b2e..b2e1b4cbbdc1a18d419ce0e5eb56b92e14445872 100644 (file)
@@ -236,7 +236,6 @@ static struct platform_driver xwdt_driver = {
        .probe       = xwdt_probe,
        .remove      = xwdt_remove,
        .driver = {
-               .owner = THIS_MODULE,
                .name  = WATCHDOG_NAME,
                .of_match_table = xwdt_of_match,
        },
index 00d0741228fc04fc80fd9b002d00f7c2587a0f86..8cb1ff3bcd901a64c4238c3658ceb6e7a45bbc62 100644 (file)
@@ -114,6 +114,46 @@ static int armada370_wdt_clock_init(struct platform_device *pdev,
        return 0;
 }
 
+static int armada375_wdt_clock_init(struct platform_device *pdev,
+                                   struct orion_watchdog *dev)
+{
+       int ret;
+
+       dev->clk = of_clk_get_by_name(pdev->dev.of_node, "fixed");
+       if (!IS_ERR(dev->clk)) {
+               ret = clk_prepare_enable(dev->clk);
+               if (ret) {
+                       clk_put(dev->clk);
+                       return ret;
+               }
+
+               atomic_io_modify(dev->reg + TIMER_CTRL,
+                               WDT_AXP_FIXED_ENABLE_BIT,
+                               WDT_AXP_FIXED_ENABLE_BIT);
+               dev->clk_rate = clk_get_rate(dev->clk);
+
+               return 0;
+       }
+
+       /* Mandatory fallback for proper devicetree backward compatibility */
+       dev->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dev->clk))
+               return PTR_ERR(dev->clk);
+
+       ret = clk_prepare_enable(dev->clk);
+       if (ret) {
+               clk_put(dev->clk);
+               return ret;
+       }
+
+       atomic_io_modify(dev->reg + TIMER_CTRL,
+                       WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT),
+                       WDT_A370_RATIO_MASK(WDT_A370_RATIO_SHIFT));
+       dev->clk_rate = clk_get_rate(dev->clk) / WDT_A370_RATIO;
+
+       return 0;
+}
+
 static int armadaxp_wdt_clock_init(struct platform_device *pdev,
                                   struct orion_watchdog *dev)
 {
@@ -394,7 +434,7 @@ static const struct orion_watchdog_data armada375_data = {
        .rstout_mask_bit = BIT(10),
        .wdt_enable_bit = BIT(8),
        .wdt_counter_offset = 0x34,
-       .clock_init = armada370_wdt_clock_init,
+       .clock_init = armada375_wdt_clock_init,
        .enabled = armada375_enabled,
        .start = armada375_start,
        .stop = armada375_stop,
diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c
new file mode 100644 (file)
index 0000000..aa85618
--- /dev/null
@@ -0,0 +1,224 @@
+/* Copyright (c) 2014, 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/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/watchdog.h>
+
+#define WDT_RST                0x0
+#define WDT_EN         0x8
+#define WDT_BITE_TIME  0x24
+
+struct qcom_wdt {
+       struct watchdog_device  wdd;
+       struct clk              *clk;
+       unsigned long           rate;
+       struct notifier_block   restart_nb;
+       void __iomem            *base;
+};
+
+static inline
+struct qcom_wdt *to_qcom_wdt(struct watchdog_device *wdd)
+{
+       return container_of(wdd, struct qcom_wdt, wdd);
+}
+
+static int qcom_wdt_start(struct watchdog_device *wdd)
+{
+       struct qcom_wdt *wdt = to_qcom_wdt(wdd);
+
+       writel(0, wdt->base + WDT_EN);
+       writel(1, wdt->base + WDT_RST);
+       writel(wdd->timeout * wdt->rate, wdt->base + WDT_BITE_TIME);
+       writel(1, wdt->base + WDT_EN);
+       return 0;
+}
+
+static int qcom_wdt_stop(struct watchdog_device *wdd)
+{
+       struct qcom_wdt *wdt = to_qcom_wdt(wdd);
+
+       writel(0, wdt->base + WDT_EN);
+       return 0;
+}
+
+static int qcom_wdt_ping(struct watchdog_device *wdd)
+{
+       struct qcom_wdt *wdt = to_qcom_wdt(wdd);
+
+       writel(1, wdt->base + WDT_RST);
+       return 0;
+}
+
+static int qcom_wdt_set_timeout(struct watchdog_device *wdd,
+                               unsigned int timeout)
+{
+       wdd->timeout = timeout;
+       return qcom_wdt_start(wdd);
+}
+
+static const struct watchdog_ops qcom_wdt_ops = {
+       .start          = qcom_wdt_start,
+       .stop           = qcom_wdt_stop,
+       .ping           = qcom_wdt_ping,
+       .set_timeout    = qcom_wdt_set_timeout,
+       .owner          = THIS_MODULE,
+};
+
+static const struct watchdog_info qcom_wdt_info = {
+       .options        = WDIOF_KEEPALIVEPING
+                       | WDIOF_MAGICCLOSE
+                       | WDIOF_SETTIMEOUT,
+       .identity       = KBUILD_MODNAME,
+};
+
+static int qcom_wdt_restart(struct notifier_block *nb, unsigned long action,
+                           void *data)
+{
+       struct qcom_wdt *wdt = container_of(nb, struct qcom_wdt, restart_nb);
+       u32 timeout;
+
+       /*
+        * Trigger watchdog bite:
+        *    Setup BITE_TIME to be 128ms, and enable WDT.
+        */
+       timeout = 128 * wdt->rate / 1000;
+
+       writel(0, wdt->base + WDT_EN);
+       writel(1, wdt->base + WDT_RST);
+       writel(timeout, wdt->base + WDT_BITE_TIME);
+       writel(1, wdt->base + WDT_EN);
+
+       /*
+        * Actually make sure the above sequence hits hardware before sleeping.
+        */
+       wmb();
+
+       msleep(150);
+       return NOTIFY_DONE;
+}
+
+static int qcom_wdt_probe(struct platform_device *pdev)
+{
+       struct qcom_wdt *wdt;
+       struct resource *res;
+       int ret;
+
+       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+       if (!wdt)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       wdt->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(wdt->base))
+               return PTR_ERR(wdt->base);
+
+       wdt->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(wdt->clk)) {
+               dev_err(&pdev->dev, "failed to get input clock\n");
+               return PTR_ERR(wdt->clk);
+       }
+
+       ret = clk_prepare_enable(wdt->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to setup clock\n");
+               return ret;
+       }
+
+       /*
+        * We use the clock rate to calculate the max timeout, so ensure it's
+        * not zero to avoid a divide-by-zero exception.
+        *
+        * WATCHDOG_CORE assumes units of seconds, if the WDT is clocked such
+        * that it would bite before a second elapses it's usefulness is
+        * limited.  Bail if this is the case.
+        */
+       wdt->rate = clk_get_rate(wdt->clk);
+       if (wdt->rate == 0 ||
+           wdt->rate > 0x10000000U) {
+               dev_err(&pdev->dev, "invalid clock rate\n");
+               ret = -EINVAL;
+               goto err_clk_unprepare;
+       }
+
+       wdt->wdd.dev = &pdev->dev;
+       wdt->wdd.info = &qcom_wdt_info;
+       wdt->wdd.ops = &qcom_wdt_ops;
+       wdt->wdd.min_timeout = 1;
+       wdt->wdd.max_timeout = 0x10000000U / wdt->rate;
+
+       /*
+        * If 'timeout-sec' unspecified in devicetree, assume a 30 second
+        * default, unless the max timeout is less than 30 seconds, then use
+        * the max instead.
+        */
+       wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U);
+       watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
+
+       ret = watchdog_register_device(&wdt->wdd);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register watchdog\n");
+               goto err_clk_unprepare;
+       }
+
+       /*
+        * WDT restart notifier has priority 0 (use as a last resort)
+        */
+       wdt->restart_nb.notifier_call = qcom_wdt_restart;
+       ret = register_restart_handler(&wdt->restart_nb);
+       if (ret)
+               dev_err(&pdev->dev, "failed to setup restart handler\n");
+
+       platform_set_drvdata(pdev, wdt);
+       return 0;
+
+err_clk_unprepare:
+       clk_disable_unprepare(wdt->clk);
+       return ret;
+}
+
+static int qcom_wdt_remove(struct platform_device *pdev)
+{
+       struct qcom_wdt *wdt = platform_get_drvdata(pdev);
+
+       unregister_restart_handler(&wdt->restart_nb);
+       watchdog_unregister_device(&wdt->wdd);
+       clk_disable_unprepare(wdt->clk);
+       return 0;
+}
+
+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", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qcom_wdt_of_table);
+
+static struct platform_driver qcom_watchdog_driver = {
+       .probe  = qcom_wdt_probe,
+       .remove = qcom_wdt_remove,
+       .driver = {
+               .name           = KBUILD_MODNAME,
+               .of_match_table = qcom_wdt_of_table,
+       },
+};
+module_platform_driver(qcom_watchdog_driver);
+
+MODULE_DESCRIPTION("QCOM KPSS Watchdog Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/watchdog/rn5t618_wdt.c b/drivers/watchdog/rn5t618_wdt.c
new file mode 100644 (file)
index 0000000..d1c1227
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Watchdog driver for Ricoh RN5T618 PMIC
+ *
+ * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.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.
+ *
+ * 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/device.h>
+#include <linux/mfd/rn5t618.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+
+#define DRIVER_NAME "rn5t618-wdt"
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+static unsigned int timeout;
+
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout, "Initial watchdog timeout in seconds");
+
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+struct rn5t618_wdt {
+       struct watchdog_device wdt_dev;
+       struct rn5t618 *rn5t618;
+};
+
+/*
+ * This array encodes the values of WDOGTIM field for the supported
+ * watchdog expiration times. If the watchdog is not accessed before
+ * the timer expiration, the PMU generates an interrupt and if the CPU
+ * doesn't clear it within one second the system is restarted.
+ */
+static const struct {
+       u8 reg_val;
+       unsigned int time;
+} rn5t618_wdt_map[] = {
+       { 0, 1 },
+       { 1, 8 },
+       { 2, 32 },
+       { 3, 128 },
+};
+
+static int rn5t618_wdt_set_timeout(struct watchdog_device *wdt_dev,
+                                  unsigned int t)
+{
+       struct rn5t618_wdt *wdt = watchdog_get_drvdata(wdt_dev);
+       int ret, i;
+
+       for (i = 0; i < ARRAY_SIZE(rn5t618_wdt_map); i++) {
+               if (rn5t618_wdt_map[i].time + 1 >= t)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(rn5t618_wdt_map))
+               return -EINVAL;
+
+       ret = regmap_update_bits(wdt->rn5t618->regmap, RN5T618_WATCHDOG,
+                                RN5T618_WATCHDOG_WDOGTIM_M,
+                                rn5t618_wdt_map[i].reg_val);
+       if (!ret)
+               wdt_dev->timeout = rn5t618_wdt_map[i].time;
+
+       return ret;
+}
+
+static int rn5t618_wdt_start(struct watchdog_device *wdt_dev)
+{
+       struct rn5t618_wdt *wdt = watchdog_get_drvdata(wdt_dev);
+       int ret;
+
+       ret = rn5t618_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+       if (ret)
+               return ret;
+
+       /* enable repower-on */
+       ret = regmap_update_bits(wdt->rn5t618->regmap, RN5T618_REPCNT,
+                                RN5T618_REPCNT_REPWRON,
+                                RN5T618_REPCNT_REPWRON);
+       if (ret)
+               return ret;
+
+       /* enable watchdog */
+       ret = regmap_update_bits(wdt->rn5t618->regmap, RN5T618_WATCHDOG,
+                                RN5T618_WATCHDOG_WDOGEN,
+                                RN5T618_WATCHDOG_WDOGEN);
+       if (ret)
+               return ret;
+
+       /* enable watchdog interrupt */
+       return regmap_update_bits(wdt->rn5t618->regmap, RN5T618_PWRIREN,
+                                 RN5T618_PWRIRQ_IR_WDOG,
+                                 RN5T618_PWRIRQ_IR_WDOG);
+}
+
+static int rn5t618_wdt_stop(struct watchdog_device *wdt_dev)
+{
+       struct rn5t618_wdt *wdt = watchdog_get_drvdata(wdt_dev);
+
+       return regmap_update_bits(wdt->rn5t618->regmap, RN5T618_WATCHDOG,
+                                 RN5T618_WATCHDOG_WDOGEN, 0);
+}
+
+static int rn5t618_wdt_ping(struct watchdog_device *wdt_dev)
+{
+       struct rn5t618_wdt *wdt = watchdog_get_drvdata(wdt_dev);
+       unsigned int val;
+       int ret;
+
+       /* The counter is restarted after a R/W access to watchdog register */
+       ret = regmap_read(wdt->rn5t618->regmap, RN5T618_WATCHDOG, &val);
+       if (ret)
+               return ret;
+
+       ret = regmap_write(wdt->rn5t618->regmap, RN5T618_WATCHDOG, val);
+       if (ret)
+               return ret;
+
+       /* Clear pending watchdog interrupt */
+       return regmap_update_bits(wdt->rn5t618->regmap, RN5T618_PWRIRQ,
+                                 RN5T618_PWRIRQ_IR_WDOG, 0);
+}
+
+static struct watchdog_info rn5t618_wdt_info = {
+       .options        = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
+                         WDIOF_KEEPALIVEPING,
+       .identity       = DRIVER_NAME,
+};
+
+static struct watchdog_ops rn5t618_wdt_ops = {
+       .owner          = THIS_MODULE,
+       .start          = rn5t618_wdt_start,
+       .stop           = rn5t618_wdt_stop,
+       .ping           = rn5t618_wdt_ping,
+       .set_timeout    = rn5t618_wdt_set_timeout,
+};
+
+static int rn5t618_wdt_probe(struct platform_device *pdev)
+{
+       struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
+       struct rn5t618_wdt *wdt;
+       int min_timeout, max_timeout;
+
+       wdt = devm_kzalloc(&pdev->dev, sizeof(struct rn5t618_wdt), GFP_KERNEL);
+       if (!wdt)
+               return -ENOMEM;
+
+       min_timeout = rn5t618_wdt_map[0].time;
+       max_timeout = rn5t618_wdt_map[ARRAY_SIZE(rn5t618_wdt_map) - 1].time;
+
+       wdt->rn5t618 = rn5t618;
+       wdt->wdt_dev.info = &rn5t618_wdt_info;
+       wdt->wdt_dev.ops = &rn5t618_wdt_ops;
+       wdt->wdt_dev.min_timeout = min_timeout;
+       wdt->wdt_dev.max_timeout = max_timeout;
+       wdt->wdt_dev.timeout = max_timeout;
+       wdt->wdt_dev.parent = &pdev->dev;
+
+       watchdog_set_drvdata(&wdt->wdt_dev, wdt);
+       watchdog_init_timeout(&wdt->wdt_dev, timeout, &pdev->dev);
+       watchdog_set_nowayout(&wdt->wdt_dev, nowayout);
+
+       platform_set_drvdata(pdev, wdt);
+
+       return watchdog_register_device(&wdt->wdt_dev);
+}
+
+static int rn5t618_wdt_remove(struct platform_device *pdev)
+{
+       struct rn5t618_wdt *wdt = platform_get_drvdata(pdev);
+
+       watchdog_unregister_device(&wdt->wdt_dev);
+
+       return 0;
+}
+
+static struct platform_driver rn5t618_wdt_driver = {
+       .probe = rn5t618_wdt_probe,
+       .remove = rn5t618_wdt_remove,
+       .driver = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+module_platform_driver(rn5t618_wdt_driver);
+
+MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
+MODULE_DESCRIPTION("RN5T618 watchdog driver");
+MODULE_LICENSE("GPL v2");
index 7c6ccd071baf502711cf0491daa3fa215cb4b9cb..1626dc66e7636837a340a6faaf762df74c25df54 100644 (file)
@@ -41,6 +41,8 @@
 #include <linux/of.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
+#include <linux/reboot.h>
+#include <linux/delay.h>
 
 #define S3C2410_WTCON          0x00
 #define S3C2410_WTDAT          0x04
@@ -128,6 +130,7 @@ struct s3c2410_wdt {
        unsigned long           wtdat_save;
        struct watchdog_device  wdt_device;
        struct notifier_block   freq_transition;
+       struct notifier_block   restart_handler;
        struct s3c2410_wdt_variant *drv_data;
        struct regmap *pmureg;
 };
@@ -155,6 +158,15 @@ static const struct s3c2410_wdt_variant drv_data_exynos5420 = {
        .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT,
 };
 
+static const struct s3c2410_wdt_variant drv_data_exynos7 = {
+       .disable_reg = EXYNOS5_WDT_DISABLE_REG_OFFSET,
+       .mask_reset_reg = EXYNOS5_WDT_MASK_RESET_REG_OFFSET,
+       .mask_bit = 23,
+       .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
+       .rst_stat_bit = 23,     /* A57 WDTRESET */
+       .quirks = QUIRK_HAS_PMU_CONFIG | QUIRK_HAS_RST_STAT,
+};
+
 static const struct of_device_id s3c2410_wdt_match[] = {
        { .compatible = "samsung,s3c2410-wdt",
          .data = &drv_data_s3c2410 },
@@ -162,6 +174,8 @@ static const struct of_device_id s3c2410_wdt_match[] = {
          .data = &drv_data_exynos5250 },
        { .compatible = "samsung,exynos5420-wdt",
          .data = &drv_data_exynos5420 },
+       { .compatible = "samsung,exynos7-wdt",
+         .data = &drv_data_exynos7 },
        {},
 };
 MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
@@ -438,6 +452,31 @@ static inline void s3c2410wdt_cpufreq_deregister(struct s3c2410_wdt *wdt)
 }
 #endif
 
+static int s3c2410wdt_restart(struct notifier_block *this,
+                             unsigned long mode, void *cmd)
+{
+       struct s3c2410_wdt *wdt = container_of(this, struct s3c2410_wdt,
+                                              restart_handler);
+       void __iomem *wdt_base = wdt->reg_base;
+
+       /* disable watchdog, to be safe  */
+       writel(0, wdt_base + S3C2410_WTCON);
+
+       /* put initial values into count and data */
+       writel(0x80, wdt_base + S3C2410_WTCNT);
+       writel(0x80, wdt_base + S3C2410_WTDAT);
+
+       /* set the watchdog to go and reset... */
+       writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV16 |
+               S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x20),
+               wdt_base + S3C2410_WTCON);
+
+       /* wait for reset to assert... */
+       mdelay(500);
+
+       return NOTIFY_DONE;
+}
+
 static inline unsigned int s3c2410wdt_get_bootstatus(struct s3c2410_wdt *wdt)
 {
        unsigned int rst_stat;
@@ -592,6 +631,12 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, wdt);
 
+       wdt->restart_handler.notifier_call = s3c2410wdt_restart;
+       wdt->restart_handler.priority = 128;
+       ret = register_restart_handler(&wdt->restart_handler);
+       if (ret)
+               pr_err("cannot register restart handler, %d\n", ret);
+
        /* print out a statement of readiness */
 
        wtcon = readl(wdt->reg_base + S3C2410_WTCON);
@@ -621,6 +666,8 @@ static int s3c2410wdt_remove(struct platform_device *dev)
        int ret;
        struct s3c2410_wdt *wdt = platform_get_drvdata(dev);
 
+       unregister_restart_handler(&wdt->restart_handler);
+
        ret = s3c2410wdt_mask_and_disable_reset(wdt, true);
        if (ret < 0)
                return ret;
index 3804d5e9baea694f8e0c10c3240f7610a5d55db5..a62b1b6decf472ac2b35cf7e663da7e704f9e005 100644 (file)
@@ -94,9 +94,33 @@ static int stmp3xxx_wdt_remove(struct platform_device *pdev)
        return 0;
 }
 
+static int __maybe_unused stmp3xxx_wdt_suspend(struct device *dev)
+{
+       struct watchdog_device *wdd = &stmp3xxx_wdd;
+
+       if (watchdog_active(wdd))
+               return wdt_stop(wdd);
+
+       return 0;
+}
+
+static int __maybe_unused stmp3xxx_wdt_resume(struct device *dev)
+{
+       struct watchdog_device *wdd = &stmp3xxx_wdd;
+
+       if (watchdog_active(wdd))
+               return wdt_start(wdd);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(stmp3xxx_wdt_pm_ops,
+                        stmp3xxx_wdt_suspend, stmp3xxx_wdt_resume);
+
 static struct platform_driver stmp3xxx_wdt_driver = {
        .driver = {
                .name = "stmp3xxx_rtc_wdt",
+               .pm = &stmp3xxx_wdt_pm_ops,
        },
        .probe = stmp3xxx_wdt_probe,
        .remove = stmp3xxx_wdt_remove,
index 480bb557f353cbdfc1923769b5ee0441750e8ca8..b62301e74e5f004b30809d49ac14c972d0e0e89c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/moduleparam.h>
 #include <linux/notifier.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/types.h>
 
 #define WDT_MAX_TIMEOUT         16
 #define WDT_MIN_TIMEOUT         1
-#define WDT_MODE_TIMEOUT(n)     ((n) << 3)
-#define WDT_TIMEOUT_MASK        WDT_MODE_TIMEOUT(0x0F)
+#define WDT_TIMEOUT_MASK        0x0F
 
-#define WDT_CTRL                0x00
 #define WDT_CTRL_RELOAD         ((1 << 0) | (0x0a57 << 1))
 
-#define WDT_MODE                0x04
 #define WDT_MODE_EN             (1 << 0)
-#define WDT_MODE_RST_EN         (1 << 1)
 
 #define DRV_NAME               "sunxi-wdt"
 #define DRV_VERSION            "1.0"
 static bool nowayout = WATCHDOG_NOWAYOUT;
 static unsigned int timeout = WDT_MAX_TIMEOUT;
 
+/*
+ * This structure stores the register offsets for different variants
+ * of Allwinner's watchdog hardware.
+ */
+struct sunxi_wdt_reg {
+       u8 wdt_ctrl;
+       u8 wdt_cfg;
+       u8 wdt_mode;
+       u8 wdt_timeout_shift;
+       u8 wdt_reset_mask;
+       u8 wdt_reset_val;
+};
+
 struct sunxi_wdt_dev {
        struct watchdog_device wdt_dev;
        void __iomem *wdt_base;
+       const struct sunxi_wdt_reg *wdt_regs;
        struct notifier_block restart_handler;
 };
 
 /*
  * wdt_timeout_map maps the watchdog timer interval value in seconds to
- * the value of the register WDT_MODE bit 3:6
+ * the value of the register WDT_MODE at bits .wdt_timeout_shift ~ +3
  *
  * [timeout seconds] = register value
  *
@@ -82,19 +93,32 @@ static int sunxi_restart_handle(struct notifier_block *this, unsigned long mode,
                                                       struct sunxi_wdt_dev,
                                                       restart_handler);
        void __iomem *wdt_base = sunxi_wdt->wdt_base;
+       const struct sunxi_wdt_reg *regs = sunxi_wdt->wdt_regs;
+       u32 val;
+
+       /* Set system reset function */
+       val = readl(wdt_base + regs->wdt_cfg);
+       val &= ~(regs->wdt_reset_mask);
+       val |= regs->wdt_reset_val;
+       writel(val, wdt_base + regs->wdt_cfg);
 
-       /* Enable timer and set reset bit in the watchdog */
-       writel(WDT_MODE_EN | WDT_MODE_RST_EN, wdt_base + WDT_MODE);
+       /* Set lowest timeout and enable watchdog */
+       val = readl(wdt_base + regs->wdt_mode);
+       val &= ~(WDT_TIMEOUT_MASK << regs->wdt_timeout_shift);
+       val |= WDT_MODE_EN;
+       writel(val, wdt_base + regs->wdt_mode);
 
        /*
         * Restart the watchdog. The default (and lowest) interval
         * value for the watchdog is 0.5s.
         */
-       writel(WDT_CTRL_RELOAD, wdt_base + WDT_CTRL);
+       writel(WDT_CTRL_RELOAD, wdt_base + regs->wdt_ctrl);
 
        while (1) {
                mdelay(5);
-               writel(WDT_MODE_EN | WDT_MODE_RST_EN, wdt_base + WDT_MODE);
+               val = readl(wdt_base + regs->wdt_mode);
+               val |= WDT_MODE_EN;
+               writel(val, wdt_base + regs->wdt_mode);
        }
        return NOTIFY_DONE;
 }
@@ -103,8 +127,9 @@ static int sunxi_wdt_ping(struct watchdog_device *wdt_dev)
 {
        struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev);
        void __iomem *wdt_base = sunxi_wdt->wdt_base;
+       const struct sunxi_wdt_reg *regs = sunxi_wdt->wdt_regs;
 
-       iowrite32(WDT_CTRL_RELOAD, wdt_base + WDT_CTRL);
+       writel(WDT_CTRL_RELOAD, wdt_base + regs->wdt_ctrl);
 
        return 0;
 }
@@ -114,6 +139,7 @@ static int sunxi_wdt_set_timeout(struct watchdog_device *wdt_dev,
 {
        struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev);
        void __iomem *wdt_base = sunxi_wdt->wdt_base;
+       const struct sunxi_wdt_reg *regs = sunxi_wdt->wdt_regs;
        u32 reg;
 
        if (wdt_timeout_map[timeout] == 0)
@@ -121,10 +147,10 @@ static int sunxi_wdt_set_timeout(struct watchdog_device *wdt_dev,
 
        sunxi_wdt->wdt_dev.timeout = timeout;
 
-       reg = ioread32(wdt_base + WDT_MODE);
-       reg &= ~WDT_TIMEOUT_MASK;
-       reg |= WDT_MODE_TIMEOUT(wdt_timeout_map[timeout]);
-       iowrite32(reg, wdt_base + WDT_MODE);
+       reg = readl(wdt_base + regs->wdt_mode);
+       reg &= ~(WDT_TIMEOUT_MASK << regs->wdt_timeout_shift);
+       reg |= wdt_timeout_map[timeout] << regs->wdt_timeout_shift;
+       writel(reg, wdt_base + regs->wdt_mode);
 
        sunxi_wdt_ping(wdt_dev);
 
@@ -135,8 +161,9 @@ static int sunxi_wdt_stop(struct watchdog_device *wdt_dev)
 {
        struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev);
        void __iomem *wdt_base = sunxi_wdt->wdt_base;
+       const struct sunxi_wdt_reg *regs = sunxi_wdt->wdt_regs;
 
-       iowrite32(0, wdt_base + WDT_MODE);
+       writel(0, wdt_base + regs->wdt_mode);
 
        return 0;
 }
@@ -146,6 +173,7 @@ static int sunxi_wdt_start(struct watchdog_device *wdt_dev)
        u32 reg;
        struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev);
        void __iomem *wdt_base = sunxi_wdt->wdt_base;
+       const struct sunxi_wdt_reg *regs = sunxi_wdt->wdt_regs;
        int ret;
 
        ret = sunxi_wdt_set_timeout(&sunxi_wdt->wdt_dev,
@@ -153,9 +181,16 @@ static int sunxi_wdt_start(struct watchdog_device *wdt_dev)
        if (ret < 0)
                return ret;
 
-       reg = ioread32(wdt_base + WDT_MODE);
-       reg |= (WDT_MODE_RST_EN | WDT_MODE_EN);
-       iowrite32(reg, wdt_base + WDT_MODE);
+       /* Set system reset function */
+       reg = readl(wdt_base + regs->wdt_cfg);
+       reg &= ~(regs->wdt_reset_mask);
+       reg |= ~(regs->wdt_reset_val);
+       writel(reg, wdt_base + regs->wdt_cfg);
+
+       /* Enable watchdog */
+       reg = readl(wdt_base + regs->wdt_mode);
+       reg |= WDT_MODE_EN;
+       writel(reg, wdt_base + regs->wdt_mode);
 
        return 0;
 }
@@ -175,9 +210,35 @@ static const struct watchdog_ops sunxi_wdt_ops = {
        .set_timeout    = sunxi_wdt_set_timeout,
 };
 
+static const struct sunxi_wdt_reg sun4i_wdt_reg = {
+       .wdt_ctrl = 0x00,
+       .wdt_cfg = 0x04,
+       .wdt_mode = 0x04,
+       .wdt_timeout_shift = 3,
+       .wdt_reset_mask = 0x02,
+       .wdt_reset_val = 0x02,
+};
+
+static const struct sunxi_wdt_reg sun6i_wdt_reg = {
+       .wdt_ctrl = 0x10,
+       .wdt_cfg = 0x14,
+       .wdt_mode = 0x18,
+       .wdt_timeout_shift = 4,
+       .wdt_reset_mask = 0x03,
+       .wdt_reset_val = 0x01,
+};
+
+static const struct of_device_id sunxi_wdt_dt_ids[] = {
+       { .compatible = "allwinner,sun4i-a10-wdt", .data = &sun4i_wdt_reg },
+       { .compatible = "allwinner,sun6i-a31-wdt", .data = &sun6i_wdt_reg },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
+
 static int sunxi_wdt_probe(struct platform_device *pdev)
 {
        struct sunxi_wdt_dev *sunxi_wdt;
+       const struct of_device_id *device;
        struct resource *res;
        int err;
 
@@ -187,6 +248,12 @@ static int sunxi_wdt_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, sunxi_wdt);
 
+       device = of_match_device(sunxi_wdt_dt_ids, &pdev->dev);
+       if (!device)
+               return -ENODEV;
+
+       sunxi_wdt->wdt_regs = device->data;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        sunxi_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(sunxi_wdt->wdt_base))
@@ -242,12 +309,6 @@ static void sunxi_wdt_shutdown(struct platform_device *pdev)
        sunxi_wdt_stop(&sunxi_wdt->wdt_dev);
 }
 
-static const struct of_device_id sunxi_wdt_dt_ids[] = {
-       { .compatible = "allwinner,sun4i-a10-wdt" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids);
-
 static struct platform_driver sunxi_wdt_driver = {
        .probe          = sunxi_wdt_probe,
        .remove         = sunxi_wdt_remove,
index afa9d6ef353ab3ab8e13f44acfa5a448953961a8..dee9c6cbe6df57f28104e9917be60a3d935f9277 100644 (file)
@@ -428,11 +428,7 @@ static int ts72xx_wdt_probe(struct platform_device *pdev)
 
 static int ts72xx_wdt_remove(struct platform_device *pdev)
 {
-       int error;
-
-       error = misc_deregister(&ts72xx_wdt_miscdev);
-
-       return error;
+       return misc_deregister(&ts72xx_wdt_miscdev);
 }
 
 static struct platform_driver ts72xx_wdt_driver = {
index 1e0a317d3dcdda5b6041ae8481006f1d1479934b..3860d02729dcc4909798d778fa28f3c71c6eec8f 100644 (file)
@@ -167,6 +167,9 @@ static struct page *balloon_next_page(struct page *page)
 
 static enum bp_state update_schedule(enum bp_state state)
 {
+       if (state == BP_ECANCELED)
+               return BP_ECANCELED;
+
        if (state == BP_DONE) {
                balloon_stats.schedule_delay = 1;
                balloon_stats.retry_count = 1;
index 1f850c97482f23e8b51a67e2d36a37f39fd21546..f745db2701719fad20d88cf2db2a935513a73465 100644 (file)
@@ -294,6 +294,7 @@ static const struct efi efi_xen __initconst = {
        .acpi                     = EFI_INVALID_TABLE_ADDR,
        .acpi20                   = EFI_INVALID_TABLE_ADDR,
        .smbios                   = EFI_INVALID_TABLE_ADDR,
+       .smbios3                  = EFI_INVALID_TABLE_ADDR,
        .sal_systab               = EFI_INVALID_TABLE_ADDR,
        .boot_info                = EFI_INVALID_TABLE_ADDR,
        .hcdp                     = EFI_INVALID_TABLE_ADDR,
index dd9c249ea3118f1e16d05289ff4af766c49d886f..95ee4302ffb860c0fd4f5c948ccf63c3ca9856ef 100644 (file)
@@ -41,24 +41,29 @@ static int xen_add_device(struct device *dev)
 #endif
 
        if (pci_seg_supported) {
-               struct physdev_pci_device_add add = {
-                       .seg = pci_domain_nr(pci_dev->bus),
-                       .bus = pci_dev->bus->number,
-                       .devfn = pci_dev->devfn
+               struct {
+                       struct physdev_pci_device_add add;
+                       uint32_t pxm;
+               } add_ext = {
+                       .add.seg = pci_domain_nr(pci_dev->bus),
+                       .add.bus = pci_dev->bus->number,
+                       .add.devfn = pci_dev->devfn
                };
+               struct physdev_pci_device_add *add = &add_ext.add;
+
 #ifdef CONFIG_ACPI
                acpi_handle handle;
 #endif
 
 #ifdef CONFIG_PCI_IOV
                if (pci_dev->is_virtfn) {
-                       add.flags = XEN_PCI_DEV_VIRTFN;
-                       add.physfn.bus = physfn->bus->number;
-                       add.physfn.devfn = physfn->devfn;
+                       add->flags = XEN_PCI_DEV_VIRTFN;
+                       add->physfn.bus = physfn->bus->number;
+                       add->physfn.devfn = physfn->devfn;
                } else
 #endif
                if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
-                       add.flags = XEN_PCI_DEV_EXTFN;
+                       add->flags = XEN_PCI_DEV_EXTFN;
 
 #ifdef CONFIG_ACPI
                handle = ACPI_HANDLE(&pci_dev->dev);
@@ -77,8 +82,8 @@ static int xen_add_device(struct device *dev)
                                status = acpi_evaluate_integer(handle, "_PXM",
                                                               NULL, &pxm);
                                if (ACPI_SUCCESS(status)) {
-                                       add.optarr[0] = pxm;
-                                       add.flags |= XEN_PCI_DEV_PXM;
+                                       add->optarr[0] = pxm;
+                                       add->flags |= XEN_PCI_DEV_PXM;
                                        break;
                                }
                                status = acpi_get_parent(handle, &handle);
@@ -86,7 +91,7 @@ static int xen_add_device(struct device *dev)
                }
 #endif /* CONFIG_ACPI */
 
-               r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, &add);
+               r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, add);
                if (r != -ENOSYS)
                        return r;
                pci_seg_supported = false;
index 3e32146472a52c535e48cbfdae294c62985e8862..50610a6acf3d313aec4c106fb6ae3837bdd31ca5 100644 (file)
@@ -274,10 +274,6 @@ static void scsiback_print_status(char *sense_buffer, int errors,
               tpg->tport->tport_name, pending_req->v2p->lun,
               pending_req->cmnd[0], status_byte(errors), msg_byte(errors),
               host_byte(errors), driver_byte(errors));
-
-       if (CHECK_CONDITION & status_byte(errors))
-               __scsi_print_sense("xen-pvscsi", sense_buffer,
-                                  SCSI_SENSE_BUFFERSIZE);
 }
 
 static void scsiback_fast_flush_area(struct vscsibk_pend *req)
index db5dc159871612caaa6bf6a068977d989328e218..664991afe0c05b616dd6f9c8909d9d517316086e 100644 (file)
@@ -67,6 +67,7 @@ source "fs/quota/Kconfig"
 
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
+source "fs/overlayfs/Kconfig"
 
 menu "Caches"
 
index 90c88529892bfc9723a9aec9ed6540daeb372f76..da0bbb456d3fcf6fee384b9287566cb64c5ae04a 100644 (file)
@@ -104,6 +104,7 @@ obj-$(CONFIG_QNX6FS_FS)             += qnx6/
 obj-$(CONFIG_AUTOFS4_FS)       += autofs4/
 obj-$(CONFIG_ADFS_FS)          += adfs/
 obj-$(CONFIG_FUSE_FS)          += fuse/
+obj-$(CONFIG_OVERLAY_FS)       += overlayfs/
 obj-$(CONFIG_UDF_FS)           += udf/
 obj-$(CONFIG_SUN_OPENPROMFS)   += openpromfs/
 obj-$(CONFIG_OMFS_FS)          += omfs/
index 84a751005f5b8ad0f0f5cd6e3c5ec67df5f7440c..14b93159ef83a140483bb31a4a6c70286d209ed8 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -165,6 +165,15 @@ static struct vfsmount *aio_mnt;
 static const struct file_operations aio_ring_fops;
 static const struct address_space_operations aio_ctx_aops;
 
+/* Backing dev info for aio fs.
+ * -no dirty page accounting or writeback happens
+ */
+static struct backing_dev_info aio_fs_backing_dev_info = {
+       .name           = "aiofs",
+       .state          = 0,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_MAP_COPY,
+};
+
 static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
 {
        struct qstr this = QSTR_INIT("[aio]", 5);
@@ -176,6 +185,7 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
 
        inode->i_mapping->a_ops = &aio_ctx_aops;
        inode->i_mapping->private_data = ctx;
+       inode->i_mapping->backing_dev_info = &aio_fs_backing_dev_info;
        inode->i_size = PAGE_SIZE * nr_pages;
 
        path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this);
@@ -220,6 +230,9 @@ static int __init aio_setup(void)
        if (IS_ERR(aio_mnt))
                panic("Failed to create aio fs mount.");
 
+       if (bdi_init(&aio_fs_backing_dev_info))
+               panic("Failed to init aio fs backing dev info.");
+
        kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
        kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
@@ -281,11 +294,6 @@ static const struct file_operations aio_ring_fops = {
        .mmap = aio_ring_mmap,
 };
 
-static int aio_set_page_dirty(struct page *page)
-{
-       return 0;
-}
-
 #if IS_ENABLED(CONFIG_MIGRATION)
 static int aio_migratepage(struct address_space *mapping, struct page *new,
                        struct page *old, enum migrate_mode mode)
@@ -357,7 +365,7 @@ out:
 #endif
 
 static const struct address_space_operations aio_ctx_aops = {
-       .set_page_dirty = aio_set_page_dirty,
+       .set_page_dirty = __set_page_dirty_no_writeback,
 #if IS_ENABLED(CONFIG_MIGRATION)
        .migratepage    = aio_migratepage,
 #endif
@@ -412,7 +420,6 @@ static int aio_setup_ring(struct kioctx *ctx)
                pr_debug("pid(%d) page[%d]->count=%d\n",
                         current->pid, i, page_count(page));
                SetPageUptodate(page);
-               SetPageDirty(page);
                unlock_page(page);
 
                ctx->ring_pages[i] = page;
index cc9d4114cda085e1f0edac3b1d80341c8db75b58..1d9c9f3754f860b2f9ca19a61d1e89d3eaa9c47c 100644 (file)
@@ -1585,7 +1585,7 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
 }
 EXPORT_SYMBOL_GPL(blkdev_write_iter);
 
-static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
+ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
        struct file *file = iocb->ki_filp;
        struct inode *bd_inode = file->f_mapping->host;
@@ -1599,6 +1599,7 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
        iov_iter_truncate(to, size);
        return generic_file_read_iter(iocb, to);
 }
+EXPORT_SYMBOL_GPL(blkdev_read_iter);
 
 /*
  * Try to release a page associated with block device when the system
index d3220d31d3cbf0e653898d15816f5895045c06d5..dcd9be32ac579451597dcf61e97b54631a69aa68 100644 (file)
@@ -1011,8 +1011,6 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
                bytes = min(bytes, working_bytes);
                kaddr = kmap_atomic(page_out);
                memcpy(kaddr + *pg_offset, buf + buf_offset, bytes);
-               if (*pg_index == (vcnt - 1) && *pg_offset == 0)
-                       memset(kaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
                kunmap_atomic(kaddr);
                flush_dcache_page(page_out);
 
@@ -1054,3 +1052,34 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
 
        return 1;
 }
+
+/*
+ * When uncompressing data, we need to make sure and zero any parts of
+ * the biovec that were not filled in by the decompression code.  pg_index
+ * and pg_offset indicate the last page and the last offset of that page
+ * that have been filled in.  This will zero everything remaining in the
+ * biovec.
+ */
+void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt,
+                                  unsigned long pg_index,
+                                  unsigned long pg_offset)
+{
+       while (pg_index < vcnt) {
+               struct page *page = bvec[pg_index].bv_page;
+               unsigned long off = bvec[pg_index].bv_offset;
+               unsigned long len = bvec[pg_index].bv_len;
+
+               if (pg_offset < off)
+                       pg_offset = off;
+               if (pg_offset < off + len) {
+                       unsigned long bytes = off + len - pg_offset;
+                       char *kaddr;
+
+                       kaddr = kmap_atomic(page);
+                       memset(kaddr + pg_offset, 0, bytes);
+                       kunmap_atomic(kaddr);
+               }
+               pg_index++;
+               pg_offset = 0;
+       }
+}
index 0c803b4fbf93dc8062e644952abb7f36ff0e8504..d181f70caae01471ca80e181818a833b41f057de 100644 (file)
@@ -45,7 +45,9 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
                                  unsigned long nr_pages);
 int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
                                 int mirror_num, unsigned long bio_flags);
-
+void btrfs_clear_biovec_end(struct bio_vec *bvec, int vcnt,
+                                  unsigned long pg_index,
+                                  unsigned long pg_offset);
 struct btrfs_compress_op {
        struct list_head *(*alloc_workspace)(void);
 
index 19bc6162fb8e899cc51bd3d777fcbddf91589aa6..150822ee0a0b9f9668f071885c4f018b1c9f6bf3 100644 (file)
@@ -80,13 +80,6 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
 {
        int i;
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-       /* lockdep really cares that we take all of these spinlocks
-        * in the right order.  If any of the locks in the path are not
-        * currently blocking, it is going to complain.  So, make really
-        * really sure by forcing the path to blocking before we clear
-        * the path blocking.
-        */
        if (held) {
                btrfs_set_lock_blocking_rw(held, held_rw);
                if (held_rw == BTRFS_WRITE_LOCK)
@@ -95,7 +88,6 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
                        held_rw = BTRFS_READ_LOCK_BLOCKING;
        }
        btrfs_set_path_blocking(p);
-#endif
 
        for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
                if (p->nodes[i] && p->locks[i]) {
@@ -107,10 +99,8 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
                }
        }
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
        if (held)
                btrfs_clear_lock_blocking_rw(held, held_rw);
-#endif
 }
 
 /* this also releases the path */
@@ -2893,7 +2883,7 @@ cow_done:
                                        }
                                        p->locks[level] = BTRFS_WRITE_LOCK;
                                } else {
-                                       err = btrfs_try_tree_read_lock(b);
+                                       err = btrfs_tree_read_lock_atomic(b);
                                        if (!err) {
                                                btrfs_set_path_blocking(p);
                                                btrfs_tree_read_lock(b);
@@ -3025,7 +3015,7 @@ again:
                        }
 
                        level = btrfs_header_level(b);
-                       err = btrfs_try_tree_read_lock(b);
+                       err = btrfs_tree_read_lock_atomic(b);
                        if (!err) {
                                btrfs_set_path_blocking(p);
                                btrfs_tree_read_lock(b);
index d557264ee974deab61c33736d93af24ffb2a93d2..fe69edda11fbad5201dffc3d4848af5b49fab1c6 100644 (file)
@@ -3276,7 +3276,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, unsigned long count);
 int btrfs_async_run_delayed_refs(struct btrfs_root *root,
                                 unsigned long count, int wait);
-int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len);
+int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len);
 int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root, u64 bytenr,
                             u64 offset, int metadata, u64 *refs, u64 *flags);
index 1ad0f47ac850bce13c5bc369416eff171604768c..1bf9f897065dc886ce4463b3d63f5e507c2b953c 100644 (file)
@@ -3817,19 +3817,19 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
        struct btrfs_super_block *sb = fs_info->super_copy;
        int ret = 0;
 
-       if (sb->root_level > BTRFS_MAX_LEVEL) {
-               printk(KERN_ERR "BTRFS: tree_root level too big: %d > %d\n",
-                               sb->root_level, BTRFS_MAX_LEVEL);
+       if (btrfs_super_root_level(sb) >= BTRFS_MAX_LEVEL) {
+               printk(KERN_ERR "BTRFS: tree_root level too big: %d >= %d\n",
+                               btrfs_super_root_level(sb), BTRFS_MAX_LEVEL);
                ret = -EINVAL;
        }
-       if (sb->chunk_root_level > BTRFS_MAX_LEVEL) {
-               printk(KERN_ERR "BTRFS: chunk_root level too big: %d > %d\n",
-                               sb->chunk_root_level, BTRFS_MAX_LEVEL);
+       if (btrfs_super_chunk_root_level(sb) >= BTRFS_MAX_LEVEL) {
+               printk(KERN_ERR "BTRFS: chunk_root level too big: %d >= %d\n",
+                               btrfs_super_chunk_root_level(sb), BTRFS_MAX_LEVEL);
                ret = -EINVAL;
        }
-       if (sb->log_root_level > BTRFS_MAX_LEVEL) {
-               printk(KERN_ERR "BTRFS: log_root level too big: %d > %d\n",
-                               sb->log_root_level, BTRFS_MAX_LEVEL);
+       if (btrfs_super_log_root_level(sb) >= BTRFS_MAX_LEVEL) {
+               printk(KERN_ERR "BTRFS: log_root level too big: %d >= %d\n",
+                               btrfs_super_log_root_level(sb), BTRFS_MAX_LEVEL);
                ret = -EINVAL;
        }
 
@@ -3837,15 +3837,15 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
         * The common minimum, we don't know if we can trust the nodesize/sectorsize
         * items yet, they'll be verified later. Issue just a warning.
         */
-       if (!IS_ALIGNED(sb->root, 4096))
+       if (!IS_ALIGNED(btrfs_super_root(sb), 4096))
                printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
                                sb->root);
-       if (!IS_ALIGNED(sb->chunk_root, 4096))
+       if (!IS_ALIGNED(btrfs_super_chunk_root(sb), 4096))
                printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
                                sb->chunk_root);
-       if (!IS_ALIGNED(sb->log_root, 4096))
+       if (!IS_ALIGNED(btrfs_super_log_root(sb), 4096))
                printk(KERN_WARNING "BTRFS: tree_root block unaligned: %llu\n",
-                               sb->log_root);
+                               btrfs_super_log_root(sb));
 
        if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_UUID_SIZE) != 0) {
                printk(KERN_ERR "BTRFS: dev_item UUID does not match fsid: %pU != %pU\n",
@@ -3857,13 +3857,13 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
         * Hint to catch really bogus numbers, bitflips or so, more exact checks are
         * done later
         */
-       if (sb->num_devices > (1UL << 31))
+       if (btrfs_super_num_devices(sb) > (1UL << 31))
                printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n",
-                               sb->num_devices);
+                               btrfs_super_num_devices(sb));
 
-       if (sb->bytenr != BTRFS_SUPER_INFO_OFFSET) {
+       if (btrfs_super_bytenr(sb) != BTRFS_SUPER_INFO_OFFSET) {
                printk(KERN_ERR "BTRFS: super offset mismatch %llu != %u\n",
-                               sb->bytenr, BTRFS_SUPER_INFO_OFFSET);
+                               btrfs_super_bytenr(sb), BTRFS_SUPER_INFO_OFFSET);
                ret = -EINVAL;
        }
 
@@ -3871,14 +3871,15 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
         * The generation is a global counter, we'll trust it more than the others
         * but it's still possible that it's the one that's wrong.
         */
-       if (sb->generation < sb->chunk_root_generation)
+       if (btrfs_super_generation(sb) < btrfs_super_chunk_root_generation(sb))
                printk(KERN_WARNING
                        "BTRFS: suspicious: generation < chunk_root_generation: %llu < %llu\n",
-                       sb->generation, sb->chunk_root_generation);
-       if (sb->generation < sb->cache_generation && sb->cache_generation != (u64)-1)
+                       btrfs_super_generation(sb), btrfs_super_chunk_root_generation(sb));
+       if (btrfs_super_generation(sb) < btrfs_super_cache_generation(sb)
+           && btrfs_super_cache_generation(sb) != (u64)-1)
                printk(KERN_WARNING
                        "BTRFS: suspicious: generation < cache_generation: %llu < %llu\n",
-                       sb->generation, sb->cache_generation);
+                       btrfs_super_generation(sb), btrfs_super_cache_generation(sb));
 
        return ret;
 }
index d565895710126f813fd8a6c88c520ffe0fcffd3c..47c1ba14108254a6eb47f44472cd63a337d76c95 100644 (file)
@@ -710,8 +710,8 @@ void btrfs_clear_space_info_full(struct btrfs_fs_info *info)
        rcu_read_unlock();
 }
 
-/* simple helper to search for an existing extent at a given offset */
-int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len)
+/* simple helper to search for an existing data extent at a given offset */
+int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len)
 {
        int ret;
        struct btrfs_key key;
@@ -726,12 +726,6 @@ int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len)
        key.type = BTRFS_EXTENT_ITEM_KEY;
        ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, path,
                                0, 0);
-       if (ret > 0) {
-               btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
-               if (key.objectid == start &&
-                   key.type == BTRFS_METADATA_ITEM_KEY)
-                       ret = 0;
-       }
        btrfs_free_path(path);
        return ret;
 }
@@ -786,7 +780,6 @@ search_again:
        else
                key.type = BTRFS_EXTENT_ITEM_KEY;
 
-again:
        ret = btrfs_search_slot(trans, root->fs_info->extent_root,
                                &key, path, 0, 0);
        if (ret < 0)
@@ -802,13 +795,6 @@ again:
                            key.offset == root->nodesize)
                                ret = 0;
                }
-               if (ret) {
-                       key.objectid = bytenr;
-                       key.type = BTRFS_EXTENT_ITEM_KEY;
-                       key.offset = root->nodesize;
-                       btrfs_release_path(path);
-                       goto again;
-               }
        }
 
        if (ret == 0) {
index 783a94355efd0be2acd75d1a84b3860ec7a28740..84a2d1868271b86b1f6a771bf5cf734a8e45c3dc 100644 (file)
@@ -413,7 +413,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
        ret = 0;
 fail:
        while (ret < 0 && !list_empty(&tmplist)) {
-               sums = list_entry(&tmplist, struct btrfs_ordered_sum, list);
+               sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list);
                list_del(&sums->list);
                kfree(sums);
        }
index 8d2b76e29d3b1ae46c04af4bd3ffa2e78926e460..4399f0c3a4ce1c6a08cfa81f2720f27a7138eea7 100644 (file)
@@ -765,23 +765,6 @@ out:
        return ret;
 }
 
-/*  copy of check_sticky in fs/namei.c()
-* It's inline, so penalty for filesystems that don't use sticky bit is
-* minimal.
-*/
-static inline int btrfs_check_sticky(struct inode *dir, struct inode *inode)
-{
-       kuid_t fsuid = current_fsuid();
-
-       if (!(dir->i_mode & S_ISVTX))
-               return 0;
-       if (uid_eq(inode->i_uid, fsuid))
-               return 0;
-       if (uid_eq(dir->i_uid, fsuid))
-               return 0;
-       return !capable(CAP_FOWNER);
-}
-
 /*  copy of may_delete in fs/namei.c()
  *     Check whether we can remove a link victim from directory dir, check
  *  whether the type of victim is right.
@@ -817,8 +800,7 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
                return error;
        if (IS_APPEND(dir))
                return -EPERM;
-       if (btrfs_check_sticky(dir, victim->d_inode)||
-               IS_APPEND(victim->d_inode)||
+       if (check_sticky(dir, victim->d_inode) || IS_APPEND(victim->d_inode) ||
            IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
                return -EPERM;
        if (isdir) {
index 5665d2149249d1d83a260c74f21889e1d394a6c3..f8229ef1b46df098a3b04260c4f943db3e924d49 100644 (file)
@@ -127,6 +127,26 @@ again:
        atomic_inc(&eb->spinning_readers);
 }
 
+/*
+ * take a spinning read lock.
+ * returns 1 if we get the read lock and 0 if we don't
+ * this won't wait for blocking writers
+ */
+int btrfs_tree_read_lock_atomic(struct extent_buffer *eb)
+{
+       if (atomic_read(&eb->blocking_writers))
+               return 0;
+
+       read_lock(&eb->lock);
+       if (atomic_read(&eb->blocking_writers)) {
+               read_unlock(&eb->lock);
+               return 0;
+       }
+       atomic_inc(&eb->read_locks);
+       atomic_inc(&eb->spinning_readers);
+       return 1;
+}
+
 /*
  * returns 1 if we get the read lock and 0 if we don't
  * this won't wait for blocking writers
@@ -158,9 +178,7 @@ int btrfs_try_tree_write_lock(struct extent_buffer *eb)
            atomic_read(&eb->blocking_readers))
                return 0;
 
-       if (!write_trylock(&eb->lock))
-               return 0;
-
+       write_lock(&eb->lock);
        if (atomic_read(&eb->blocking_writers) ||
            atomic_read(&eb->blocking_readers)) {
                write_unlock(&eb->lock);
index b81e0e9a48941891681eef385d10d071f6cbe51b..c44a9d5f5362b0dcb1c525eca16b57aead8a58ae 100644 (file)
@@ -35,6 +35,8 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw);
 void btrfs_assert_tree_locked(struct extent_buffer *eb);
 int btrfs_try_tree_read_lock(struct extent_buffer *eb);
 int btrfs_try_tree_write_lock(struct extent_buffer *eb);
+int btrfs_tree_read_lock_atomic(struct extent_buffer *eb);
+
 
 static inline void btrfs_tree_unlock_rw(struct extent_buffer *eb, int rw)
 {
index 78285f30909edd09f19cc6eb48985d47eed3c565..617553cdb7d3b36b1b8ca6a87b28526c5a060b4d 100644 (file)
@@ -373,6 +373,8 @@ cont:
        }
 done:
        kunmap(pages_in[page_in_index]);
+       if (!ret)
+               btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset);
        return ret;
 }
 
@@ -410,10 +412,23 @@ static int lzo_decompress(struct list_head *ws, unsigned char *data_in,
                goto out;
        }
 
+       /*
+        * the caller is already checking against PAGE_SIZE, but lets
+        * move this check closer to the memcpy/memset
+        */
+       destlen = min_t(unsigned long, destlen, PAGE_SIZE);
        bytes = min_t(unsigned long, destlen, out_len - start_byte);
 
        kaddr = kmap_atomic(dest_page);
        memcpy(kaddr, workspace->buf + start_byte, bytes);
+
+       /*
+        * btrfs_getblock is doing a zero on the tail of the page too,
+        * but this will cover anything missing from the decompressed
+        * data.
+        */
+       if (bytes < destlen)
+               memset(kaddr+bytes, 0, destlen-bytes);
        kunmap_atomic(kaddr);
 out:
        return ret;
index a2b97ef10317081aebaa09aedeaddf4dec71a492..54bd91ece35b6c7a1f5b2cdce9e7be8c80d99e6f 100644 (file)
@@ -2151,6 +2151,7 @@ static void __exit exit_btrfs_fs(void)
        extent_map_exit();
        extent_io_exit();
        btrfs_interface_exit();
+       btrfs_end_io_wq_exit();
        unregister_filesystem(&btrfs_fs_type);
        btrfs_exit_sysfs();
        btrfs_cleanup_fs_uuids();
index 1475979e5718ab8727ad47f8c52898257c76b0ed..286213cec86132188a9db6e687769902f06613a9 100644 (file)
@@ -672,7 +672,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                         * is this extent already allocated in the extent
                         * allocation tree?  If so, just add a reference
                         */
-                       ret = btrfs_lookup_extent(root, ins.objectid,
+                       ret = btrfs_lookup_data_extent(root, ins.objectid,
                                                ins.offset);
                        if (ret == 0) {
                                ret = btrfs_inc_extent_ref(trans, root,
index 759fa4e2de8fec28d3f6448456e1e12cec1add17..fb22fd8d8fb8fad73cb4d2b63d4d525da3eea876 100644 (file)
@@ -299,6 +299,8 @@ done:
        zlib_inflateEnd(&workspace->strm);
        if (data_in)
                kunmap(pages_in[page_in_index]);
+       if (!ret)
+               btrfs_clear_biovec_end(bvec, vcnt, page_out_index, pg_offset);
        return ret;
 }
 
@@ -310,10 +312,14 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in,
        struct workspace *workspace = list_entry(ws, struct workspace, list);
        int ret = 0;
        int wbits = MAX_WBITS;
-       unsigned long bytes_left = destlen;
+       unsigned long bytes_left;
        unsigned long total_out = 0;
+       unsigned long pg_offset = 0;
        char *kaddr;
 
+       destlen = min_t(unsigned long, destlen, PAGE_SIZE);
+       bytes_left = destlen;
+
        workspace->strm.next_in = data_in;
        workspace->strm.avail_in = srclen;
        workspace->strm.total_in = 0;
@@ -341,7 +347,6 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in,
                unsigned long buf_start;
                unsigned long buf_offset;
                unsigned long bytes;
-               unsigned long pg_offset = 0;
 
                ret = zlib_inflate(&workspace->strm, Z_NO_FLUSH);
                if (ret != Z_OK && ret != Z_STREAM_END)
@@ -384,6 +389,17 @@ next:
                ret = 0;
 
        zlib_inflateEnd(&workspace->strm);
+
+       /*
+        * this should only happen if zlib returned fewer bytes than we
+        * expected.  btrfs_get_block is responsible for zeroing from the
+        * end of the inline extent (destlen) to the end of the page
+        */
+       if (pg_offset < destlen) {
+               kaddr = kmap_atomic(dest_page);
+               memset(kaddr + pg_offset, 0, destlen - pg_offset);
+               kunmap_atomic(kaddr);
+       }
        return ret;
 }
 
index 9614adc7e7544f3e253260e2d43064a6ad6bd96e..20805db2c98774a8cbe3242d37c63f370149f1a9 100644 (file)
@@ -128,21 +128,15 @@ __clear_page_buffers(struct page *page)
        page_cache_release(page);
 }
 
-
-static int quiet_error(struct buffer_head *bh)
-{
-       if (!test_bit(BH_Quiet, &bh->b_state) && printk_ratelimit())
-               return 0;
-       return 1;
-}
-
-
-static void buffer_io_error(struct buffer_head *bh)
+static void buffer_io_error(struct buffer_head *bh, char *msg)
 {
        char b[BDEVNAME_SIZE];
-       printk(KERN_ERR "Buffer I/O error on device %s, logical block %Lu\n",
+
+       if (!test_bit(BH_Quiet, &bh->b_state))
+               printk_ratelimited(KERN_ERR
+                       "Buffer I/O error on dev %s, logical block %llu%s\n",
                        bdevname(bh->b_bdev, b),
-                       (unsigned long long)bh->b_blocknr);
+                       (unsigned long long)bh->b_blocknr, msg);
 }
 
 /*
@@ -177,17 +171,10 @@ EXPORT_SYMBOL(end_buffer_read_sync);
 
 void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
 {
-       char b[BDEVNAME_SIZE];
-
        if (uptodate) {
                set_buffer_uptodate(bh);
        } else {
-               if (!quiet_error(bh)) {
-                       buffer_io_error(bh);
-                       printk(KERN_WARNING "lost page write due to "
-                                       "I/O error on %s\n",
-                                      bdevname(bh->b_bdev, b));
-               }
+               buffer_io_error(bh, ", lost sync page write");
                set_buffer_write_io_error(bh);
                clear_buffer_uptodate(bh);
        }
@@ -304,8 +291,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
                set_buffer_uptodate(bh);
        } else {
                clear_buffer_uptodate(bh);
-               if (!quiet_error(bh))
-                       buffer_io_error(bh);
+               buffer_io_error(bh, ", async page read");
                SetPageError(page);
        }
 
@@ -353,7 +339,6 @@ still_busy:
  */
 void end_buffer_async_write(struct buffer_head *bh, int uptodate)
 {
-       char b[BDEVNAME_SIZE];
        unsigned long flags;
        struct buffer_head *first;
        struct buffer_head *tmp;
@@ -365,12 +350,7 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate)
        if (uptodate) {
                set_buffer_uptodate(bh);
        } else {
-               if (!quiet_error(bh)) {
-                       buffer_io_error(bh);
-                       printk(KERN_WARNING "lost page write due to "
-                                       "I/O error on %s\n",
-                              bdevname(bh->b_bdev, b));
-               }
+               buffer_io_error(bh, ", lost async page write");
                set_bit(AS_EIO, &page->mapping->flags);
                set_buffer_write_io_error(bh);
                clear_buffer_uptodate(bh);
@@ -993,7 +973,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
  */
 static int
 grow_dev_page(struct block_device *bdev, sector_t block,
-               pgoff_t index, int size, int sizebits)
+             pgoff_t index, int size, int sizebits, gfp_t gfp)
 {
        struct inode *inode = bdev->bd_inode;
        struct page *page;
@@ -1002,8 +982,8 @@ grow_dev_page(struct block_device *bdev, sector_t block,
        int ret = 0;            /* Will call free_more_memory() */
        gfp_t gfp_mask;
 
-       gfp_mask = mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS;
-       gfp_mask |= __GFP_MOVABLE;
+       gfp_mask = (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS) | gfp;
+
        /*
         * XXX: __getblk_slow() can not really deal with failure and
         * will endlessly loop on improvised global reclaim.  Prefer
@@ -1060,7 +1040,7 @@ failed:
  * that page was dirty, the buffers are set dirty also.
  */
 static int
-grow_buffers(struct block_device *bdev, sector_t block, int size)
+grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
 {
        pgoff_t index;
        int sizebits;
@@ -1087,11 +1067,12 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
        }
 
        /* Create a page with the proper size buffers.. */
-       return grow_dev_page(bdev, block, index, size, sizebits);
+       return grow_dev_page(bdev, block, index, size, sizebits, gfp);
 }
 
-static struct buffer_head *
-__getblk_slow(struct block_device *bdev, sector_t block, int size)
+struct buffer_head *
+__getblk_slow(struct block_device *bdev, sector_t block,
+            unsigned size, gfp_t gfp)
 {
        /* Size must be multiple of hard sectorsize */
        if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
@@ -1113,13 +1094,14 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
                if (bh)
                        return bh;
 
-               ret = grow_buffers(bdev, block, size);
+               ret = grow_buffers(bdev, block, size, gfp);
                if (ret < 0)
                        return NULL;
                if (ret == 0)
                        free_more_memory();
        }
 }
+EXPORT_SYMBOL(__getblk_slow);
 
 /*
  * The relationship between dirty buffers and dirty pages:
@@ -1373,24 +1355,25 @@ __find_get_block(struct block_device *bdev, sector_t block, unsigned size)
 EXPORT_SYMBOL(__find_get_block);
 
 /*
- * __getblk will locate (and, if necessary, create) the buffer_head
+ * __getblk_gfp() will locate (and, if necessary, create) the buffer_head
  * which corresponds to the passed block_device, block and size. The
  * returned buffer has its reference count incremented.
  *
- * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
- * attempt is failing.  FIXME, perhaps?
+ * __getblk_gfp() will lock up the machine if grow_dev_page's
+ * try_to_free_buffers() attempt is failing.  FIXME, perhaps?
  */
 struct buffer_head *
-__getblk(struct block_device *bdev, sector_t block, unsigned size)
+__getblk_gfp(struct block_device *bdev, sector_t block,
+            unsigned size, gfp_t gfp)
 {
        struct buffer_head *bh = __find_get_block(bdev, block, size);
 
        might_sleep();
        if (bh == NULL)
-               bh = __getblk_slow(bdev, block, size);
+               bh = __getblk_slow(bdev, block, size, gfp);
        return bh;
 }
-EXPORT_SYMBOL(__getblk);
+EXPORT_SYMBOL(__getblk_gfp);
 
 /*
  * Do async read-ahead on a buffer..
@@ -1406,24 +1389,28 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
 EXPORT_SYMBOL(__breadahead);
 
 /**
- *  __bread() - reads a specified block and returns the bh
+ *  __bread_gfp() - reads a specified block and returns the bh
  *  @bdev: the block_device to read from
  *  @block: number of block
  *  @size: size (in bytes) to read
- * 
+ *  @gfp: page allocation flag
+ *
  *  Reads a specified block, and returns buffer head that contains it.
+ *  The page cache can be allocated from non-movable area
+ *  not to prevent page migration if you set gfp to zero.
  *  It returns NULL if the block was unreadable.
  */
 struct buffer_head *
-__bread(struct block_device *bdev, sector_t block, unsigned size)
+__bread_gfp(struct block_device *bdev, sector_t block,
+                  unsigned size, gfp_t gfp)
 {
-       struct buffer_head *bh = __getblk(bdev, block, size);
+       struct buffer_head *bh = __getblk_gfp(bdev, block, size, gfp);
 
        if (likely(bh) && !buffer_uptodate(bh))
                bh = __bread_slow(bh);
        return bh;
 }
-EXPORT_SYMBOL(__bread);
+EXPORT_SYMBOL(__bread_gfp);
 
 /*
  * invalidate_bh_lrus() is called rarely - but not only at unmount.
@@ -2082,6 +2069,7 @@ int generic_write_end(struct file *file, struct address_space *mapping,
                        struct page *page, void *fsdata)
 {
        struct inode *inode = mapping->host;
+       loff_t old_size = inode->i_size;
        int i_size_changed = 0;
 
        copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
@@ -2101,6 +2089,8 @@ int generic_write_end(struct file *file, struct address_space *mapping,
        unlock_page(page);
        page_cache_release(page);
 
+       if (old_size < pos)
+               pagecache_isize_extended(inode, old_size, pos);
        /*
         * Don't mark the inode dirty under page lock. First, it unnecessarily
         * makes the holding time of page lock longer. Second, it forces lock
index 659f2ea9e6f74741ecbe2a7e4c322f079352fb08..cefca661464b91a4edae048a8567e900d8560df6 100644 (file)
@@ -2638,7 +2638,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
 
        for (i = 0; i < CEPH_CAP_BITS; i++)
                if ((dirty & (1 << i)) &&
-                   flush_tid == ci->i_cap_flush_tid[i])
+                   (u16)flush_tid == ci->i_cap_flush_tid[i])
                        cleaned |= 1 << i;
 
        dout("handle_cap_flush_ack inode %p mds%d seq %d on %s cleaned %s,"
index d5a23fd0da903848682c659085a6c560e48d8a8c..5bc72b07fde22bcbb00451c7522333e2aa273323 100644 (file)
@@ -778,6 +778,7 @@ restart:
                        struct dentry *parent = lock_parent(dentry);
                        if (likely(!dentry->d_lockref.count)) {
                                __dentry_kill(dentry);
+                               dput(parent);
                                goto restart;
                        }
                        if (parent)
@@ -2673,11 +2674,13 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
                        if (!IS_ROOT(new)) {
                                spin_unlock(&inode->i_lock);
                                dput(new);
+                               iput(inode);
                                return ERR_PTR(-EIO);
                        }
                        if (d_ancestor(new, dentry)) {
                                spin_unlock(&inode->i_lock);
                                dput(new);
+                               iput(inode);
                                return ERR_PTR(-EIO);
                        }
                        write_seqlock(&rename_lock);
index 1b119d3bf924d16eea7f91f52449b122ecb5dcb1..c4cd1fd86cc2ffd4a09beddd3aca3f25d1fdb06f 100644 (file)
@@ -566,6 +566,13 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
        s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
        s->s_blocksize = path.dentry->d_sb->s_blocksize;
        s->s_magic = ECRYPTFS_SUPER_MAGIC;
+       s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
+
+       rc = -EINVAL;
+       if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+               pr_err("eCryptfs: maximum fs stacking depth exceeded\n");
+               goto out_free;
+       }
 
        inode = ecryptfs_get_inode(path.dentry->d_inode, s);
        rc = PTR_ERR(inode);
index 389ba8312d5d182ea0682bd719366a305f1e2d1b..b47c7b8dc275429e87b1b35fe0a36af2e820cdf3 100644 (file)
@@ -4,7 +4,7 @@
 # Copyright (C) 2008 Panasas Inc.  All rights reserved.
 #
 # Authors:
-#   Boaz Harrosh <bharrosh@panasas.com>
+#   Boaz Harrosh <ooo@electrozaur.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
index 3bbd46956d77e2d61b6a6e9ad61b90759e5e706e..7d88ef5662135e740383af1d1ba99c4789ffb121 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index 49f51ab4caac7689d48049790eae2e0b22d4c082..d7defd557601e6049ecb69fec954ea3b9d8e4ef0 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index fffe86fd7a4260cc3bce3b6910f930ee7f32f5d6..ad9cac670a470d163001c7aa2227db46afc607d3 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index 71bf8e4fb5d427c660e9913a57054dec59f99dfc..1a376b42d30582c81a9f4d0b3f4dc85b74968cb0 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index 3f9cafd739312bd1392b21bc6ed3dc6bb9b666a1..f1d3d4eb8c4ff1fe24d17ba9431abffada04bacc 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index 4731fd991efee11b2c05e7c45306134e07b3fe82..28907460e8fadaafb4975d9ea0c4903b497e28cb 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index cfc0205d62c4af1f3bc35465d71fffa4d89cd1c9..7bd8ac8dfb280ca4c2339f6297385d579b23b93d 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * This file is part of exofs.
  *
@@ -29,7 +29,7 @@
 
 #include "ore_raid.h"
 
-MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_AUTHOR("Boaz Harrosh <ooo@electrozaur.com>");
 MODULE_DESCRIPTION("Objects Raid Engine ore.ko");
 MODULE_LICENSE("GPL");
 
index 84529b8a331b1402e3a4662a1f4ce90c4dc185b6..27cbdb6976495f5f830ca473e9b844fb1a2bd29d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * This file is part of the objects raid engine (ore).
  *
index cf6375d82129b3378e30a844f7d13c05bf19ca09..a6e746775570810b4c1a0fa2c7810ee6400eb05e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) from 2011
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * This file is part of the objects raid engine (ore).
  *
index ed73ed8ebbeea878073c6e6f6043df9e11bda1c4..95965503afcbe5d0ce8abbd3792e8be50e0a9123 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index 4dd687c3e74740f57b9ea4180859ed34f57da8cc..832e2624b80bab95bd1440c5c8295ab13ec7859a 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2005, 2006
  * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Copyrights for code taken from ext2:
  *     Copyright (C) 1992, 1993, 1994, 1995
index 1b4f2f95fc3797880ed7a7c6eab82b086ca11e4e..5e6a2c0a1f0b3eb78ed88d124a56b24453f9e790 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2012
  * Sachin Bhamare <sbhamare@panasas.com>
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * This file is part of exofs.
  *
index 7015db0bafd1b0c3179e6a9eb8de8c1e06465751..eb742d0e67ff75f159b67d3d0cac6e28b1932cf9 100644 (file)
@@ -1354,13 +1354,6 @@ set_qf_format:
                                        "not specified.");
                        return 0;
                }
-       } else {
-               if (sbi->s_jquota_fmt) {
-                       ext3_msg(sb, KERN_ERR, "error: journaled quota format "
-                                       "specified with no journaling "
-                                       "enabled.");
-                       return 0;
-               }
        }
 #endif
        return 1;
index 581ef40fbe90b8b45f3d3474d48b8c80f6639ba8..83a6f497c4e0e6803345d4b69bde90504ffd02ce 100644 (file)
@@ -176,7 +176,7 @@ static unsigned int num_clusters_in_group(struct super_block *sb,
 }
 
 /* Initializes an uninitialized block bitmap */
-static void ext4_init_block_bitmap(struct super_block *sb,
+static int ext4_init_block_bitmap(struct super_block *sb,
                                   struct buffer_head *bh,
                                   ext4_group_t block_group,
                                   struct ext4_group_desc *gdp)
@@ -192,7 +192,6 @@ static void ext4_init_block_bitmap(struct super_block *sb,
        /* If checksum is bad mark all blocks used to prevent allocation
         * essentially implementing a per-group read-only flag. */
        if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
-               ext4_error(sb, "Checksum bad for group %u", block_group);
                grp = ext4_get_group_info(sb, block_group);
                if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
                        percpu_counter_sub(&sbi->s_freeclusters_counter,
@@ -205,7 +204,7 @@ static void ext4_init_block_bitmap(struct super_block *sb,
                                           count);
                }
                set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
-               return;
+               return -EIO;
        }
        memset(bh->b_data, 0, sb->s_blocksize);
 
@@ -243,6 +242,7 @@ static void ext4_init_block_bitmap(struct super_block *sb,
                             sb->s_blocksize * 8, bh->b_data);
        ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
+       return 0;
 }
 
 /* Return the number of free blocks in a block group.  It is used when
@@ -438,11 +438,15 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
        }
        ext4_lock_group(sb, block_group);
        if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
-               ext4_init_block_bitmap(sb, bh, block_group, desc);
+               int err;
+
+               err = ext4_init_block_bitmap(sb, bh, block_group, desc);
                set_bitmap_uptodate(bh);
                set_buffer_uptodate(bh);
                ext4_unlock_group(sb, block_group);
                unlock_buffer(bh);
+               if (err)
+                       ext4_error(sb, "Checksum bad for grp %u", block_group);
                return bh;
        }
        ext4_unlock_group(sb, block_group);
@@ -636,8 +640,7 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
         * Account for the allocated meta blocks.  We will never
         * fail EDQUOT for metdata, but we do account for it.
         */
-       if (!(*errp) &&
-           ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) {
+       if (!(*errp) && (flags & EXT4_MB_DELALLOC_RESERVED)) {
                spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
                spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
                dquot_alloc_block_nofail(inode,
index 3285aa5a706af3f97c6a182a12304c7478177d9d..b610779a958c32fbfa64696e554b62c1398cecd2 100644 (file)
@@ -24,8 +24,7 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
        __u32 provided, calculated;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return 1;
 
        provided = le16_to_cpu(gdp->bg_inode_bitmap_csum_lo);
@@ -46,8 +45,7 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
        __u32 csum;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return;
 
        csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
@@ -65,8 +63,7 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return 1;
 
        provided = le16_to_cpu(gdp->bg_block_bitmap_csum_lo);
@@ -91,8 +88,7 @@ void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
        __u32 csum;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return;
 
        csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)bh->b_data, sz);
index 0bb3f9ea08329a46d27f75160a6b42718fed6042..c24143ea9c08e4e38823a42cecfb102e6d8db710 100644 (file)
@@ -151,13 +151,11 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
                                        &file->f_ra, file,
                                        index, 1);
                        file->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
-                       bh = ext4_bread(NULL, inode, map.m_lblk, 0, &err);
+                       bh = ext4_bread(NULL, inode, map.m_lblk, 0);
+                       if (IS_ERR(bh))
+                               return PTR_ERR(bh);
                }
 
-               /*
-                * We ignore I/O errors on directories so users have a chance
-                * of recovering data when there's a bad sector
-                */
                if (!bh) {
                        if (!dir_has_error) {
                                EXT4_ERROR_FILE(file, 0,
index b0c225cdb52cd20ba5927149c338d9749e951f57..c55a1faaed583778d482b0fb6368bd72b454fc19 100644 (file)
@@ -572,15 +572,15 @@ enum {
 
 /*
  * The bit position of these flags must not overlap with any of the
- * EXT4_GET_BLOCKS_*.  They are used by ext4_ext_find_extent(),
+ * EXT4_GET_BLOCKS_*.  They are used by ext4_find_extent(),
  * read_extent_tree_block(), ext4_split_extent_at(),
  * ext4_ext_insert_extent(), and ext4_ext_create_new_leaf().
  * EXT4_EX_NOCACHE is used to indicate that the we shouldn't be
  * caching the extents when reading from the extent tree while a
  * truncate or punch hole operation is in progress.
  */
-#define EXT4_EX_NOCACHE                                0x0400
-#define EXT4_EX_FORCE_CACHE                    0x0800
+#define EXT4_EX_NOCACHE                                0x40000000
+#define EXT4_EX_FORCE_CACHE                    0x20000000
 
 /*
  * Flags used by ext4_free_blocks
@@ -890,6 +890,7 @@ struct ext4_inode_info {
        struct ext4_es_tree i_es_tree;
        rwlock_t i_es_lock;
        struct list_head i_es_lru;
+       unsigned int i_es_all_nr;       /* protected by i_es_lock */
        unsigned int i_es_lru_nr;       /* protected by i_es_lock */
        unsigned long i_touch_when;     /* jiffies of last accessing */
 
@@ -1174,6 +1175,9 @@ struct ext4_super_block {
 #define EXT4_MF_MNTDIR_SAMPLED 0x0001
 #define EXT4_MF_FS_ABORTED     0x0002  /* Fatal error detected */
 
+/* Number of quota types we support */
+#define EXT4_MAXQUOTAS 2
+
 /*
  * fourth extended-fs super-block data in memory
  */
@@ -1237,7 +1241,7 @@ struct ext4_sb_info {
        u32 s_min_batch_time;
        struct block_device *journal_bdev;
 #ifdef CONFIG_QUOTA
-       char *s_qf_names[MAXQUOTAS];            /* Names of quota files with journalled quota */
+       char *s_qf_names[EXT4_MAXQUOTAS];       /* Names of quota files with journalled quota */
        int s_jquota_fmt;                       /* Format of quota to use */
 #endif
        unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
@@ -1330,8 +1334,7 @@ struct ext4_sb_info {
        /* Reclaim extents from extent status tree */
        struct shrinker s_es_shrinker;
        struct list_head s_es_lru;
-       unsigned long s_es_last_sorted;
-       struct percpu_counter s_extent_cache_cnt;
+       struct ext4_es_stats s_es_stats;
        struct mb_cache *s_mb_cache;
        spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp;
 
@@ -1399,7 +1402,6 @@ enum {
        EXT4_STATE_EXT_MIGRATE,         /* Inode is migrating */
        EXT4_STATE_DIO_UNWRITTEN,       /* need convert on dio done*/
        EXT4_STATE_NEWENTRY,            /* File just added to dir */
-       EXT4_STATE_DELALLOC_RESERVED,   /* blks already reserved for delalloc */
        EXT4_STATE_DIOREAD_LOCK,        /* Disable support for dio read
                                           nolocking */
        EXT4_STATE_MAY_INLINE_DATA,     /* may have in-inode data */
@@ -2086,10 +2088,8 @@ extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
 extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
 
 /* inode.c */
-struct buffer_head *ext4_getblk(handle_t *, struct inode *,
-                                               ext4_lblk_t, int, int *);
-struct buffer_head *ext4_bread(handle_t *, struct inode *,
-                                               ext4_lblk_t, int, int *);
+struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
+struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
 int ext4_get_block_write(struct inode *inode, sector_t iblock,
                         struct buffer_head *bh_result, int create);
 int ext4_get_block(struct inode *inode, sector_t iblock,
@@ -2109,6 +2109,7 @@ int do_journal_get_write_access(handle_t *handle,
 #define CONVERT_INLINE_DATA     2
 
 extern struct inode *ext4_iget(struct super_block *, unsigned long);
+extern struct inode *ext4_iget_normal(struct super_block *, unsigned long);
 extern int  ext4_write_inode(struct inode *, struct writeback_control *);
 extern int  ext4_setattr(struct dentry *, struct iattr *);
 extern int  ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
@@ -2332,10 +2333,18 @@ extern int ext4_register_li_request(struct super_block *sb,
 static inline int ext4_has_group_desc_csum(struct super_block *sb)
 {
        return EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                         EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
-                                         EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+                                         EXT4_FEATURE_RO_COMPAT_GDT_CSUM) ||
+              (EXT4_SB(sb)->s_chksum_driver != NULL);
 }
 
+static inline int ext4_has_metadata_csum(struct super_block *sb)
+{
+       WARN_ON_ONCE(EXT4_HAS_RO_COMPAT_FEATURE(sb,
+                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+                    !EXT4_SB(sb)->s_chksum_driver);
+
+       return (EXT4_SB(sb)->s_chksum_driver != NULL);
+}
 static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
 {
        return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
@@ -2731,21 +2740,26 @@ extern int ext4_can_extents_be_merged(struct inode *inode,
                                      struct ext4_extent *ex1,
                                      struct ext4_extent *ex2);
 extern int ext4_ext_insert_extent(handle_t *, struct inode *,
-                                 struct ext4_ext_path *,
+                                 struct ext4_ext_path **,
                                  struct ext4_extent *, int);
-extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
-                                                 struct ext4_ext_path *,
-                                                 int flags);
+extern struct ext4_ext_path *ext4_find_extent(struct inode *, ext4_lblk_t,
+                                             struct ext4_ext_path **,
+                                             int flags);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
 extern int ext4_ext_check_inode(struct inode *inode);
 extern int ext4_find_delalloc_range(struct inode *inode,
                                    ext4_lblk_t lblk_start,
                                    ext4_lblk_t lblk_end);
 extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk);
+extern ext4_lblk_t ext4_ext_next_allocated_block(struct ext4_ext_path *path);
 extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                        __u64 start, __u64 len);
 extern int ext4_ext_precache(struct inode *inode);
 extern int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len);
+extern int ext4_swap_extents(handle_t *handle, struct inode *inode1,
+                               struct inode *inode2, ext4_lblk_t lblk1,
+                            ext4_lblk_t lblk2,  ext4_lblk_t count,
+                            int mark_unwritten,int *err);
 
 /* move_extent.c */
 extern void ext4_double_down_write_data_sem(struct inode *first,
@@ -2755,8 +2769,6 @@ extern void ext4_double_up_write_data_sem(struct inode *orig_inode,
 extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
                             __u64 start_orig, __u64 start_donor,
                             __u64 len, __u64 *moved_len);
-extern int mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
-                           struct ext4_extent **extent);
 
 /* page-io.c */
 extern int __init ext4_init_pageio(void);
index a867f5ca99919d05e2e6709f80f08566a33c435d..3c938154709478ba39f5eb18d8d2b53678932ee8 100644 (file)
@@ -123,6 +123,7 @@ find_ext4_extent_tail(struct ext4_extent_header *eh)
 struct ext4_ext_path {
        ext4_fsblk_t                    p_block;
        __u16                           p_depth;
+       __u16                           p_maxdepth;
        struct ext4_extent              *p_ext;
        struct ext4_extent_idx          *p_idx;
        struct ext4_extent_header       *p_hdr;
index 0074e0d23d6ef77eb41f4c79357cac0b70696176..3445035c7e015e9460f2cd3f74b698bf823cabb6 100644 (file)
@@ -256,8 +256,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
        set_buffer_prio(bh);
        if (ext4_handle_valid(handle)) {
                err = jbd2_journal_dirty_metadata(handle, bh);
-               /* Errors can only happen if there is a bug */
-               if (WARN_ON_ONCE(err)) {
+               /* Errors can only happen due to aborted journal or a nasty bug */
+               if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) {
                        ext4_journal_abort_handle(where, line, __func__, bh,
                                                  handle, err);
                        if (inode == NULL) {
index 17c00ff202f22042c30b563f7bc4a39492542215..9c5b49fb281e16f1717b989d31dd55ade6c03f8d 100644 (file)
 #define EXT4_QUOTA_INIT_BLOCKS(sb) 0
 #define EXT4_QUOTA_DEL_BLOCKS(sb) 0
 #endif
-#define EXT4_MAXQUOTAS_TRANS_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_TRANS_BLOCKS(sb))
-#define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb))
-#define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb))
+#define EXT4_MAXQUOTAS_TRANS_BLOCKS(sb) (EXT4_MAXQUOTAS*EXT4_QUOTA_TRANS_BLOCKS(sb))
+#define EXT4_MAXQUOTAS_INIT_BLOCKS(sb) (EXT4_MAXQUOTAS*EXT4_QUOTA_INIT_BLOCKS(sb))
+#define EXT4_MAXQUOTAS_DEL_BLOCKS(sb) (EXT4_MAXQUOTAS*EXT4_QUOTA_DEL_BLOCKS(sb))
 
 static inline int ext4_jbd2_credits_xattr(struct inode *inode)
 {
index 74292a71b384e2fd480357a8115c5e4936fa6f20..0b16fb4c06d3e176e367bced078d014542a97b2a 100644 (file)
@@ -73,8 +73,7 @@ static int ext4_extent_block_csum_verify(struct inode *inode,
 {
        struct ext4_extent_tail *et;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return 1;
 
        et = find_ext4_extent_tail(eh);
@@ -88,8 +87,7 @@ static void ext4_extent_block_csum_set(struct inode *inode,
 {
        struct ext4_extent_tail *et;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return;
 
        et = find_ext4_extent_tail(eh);
@@ -98,14 +96,14 @@ static void ext4_extent_block_csum_set(struct inode *inode,
 
 static int ext4_split_extent(handle_t *handle,
                                struct inode *inode,
-                               struct ext4_ext_path *path,
+                               struct ext4_ext_path **ppath,
                                struct ext4_map_blocks *map,
                                int split_flag,
                                int flags);
 
 static int ext4_split_extent_at(handle_t *handle,
                             struct inode *inode,
-                            struct ext4_ext_path *path,
+                            struct ext4_ext_path **ppath,
                             ext4_lblk_t split,
                             int split_flag,
                             int flags);
@@ -291,6 +289,20 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check)
        return size;
 }
 
+static inline int
+ext4_force_split_extent_at(handle_t *handle, struct inode *inode,
+                          struct ext4_ext_path **ppath, ext4_lblk_t lblk,
+                          int nofail)
+{
+       struct ext4_ext_path *path = *ppath;
+       int unwritten = ext4_ext_is_unwritten(path[path->p_depth].p_ext);
+
+       return ext4_split_extent_at(handle, inode, ppath, lblk, unwritten ?
+                       EXT4_EXT_MARK_UNWRIT1|EXT4_EXT_MARK_UNWRIT2 : 0,
+                       EXT4_EX_NOCACHE | EXT4_GET_BLOCKS_PRE_IO |
+                       (nofail ? EXT4_GET_BLOCKS_METADATA_NOFAIL:0));
+}
+
 /*
  * Calculate the number of metadata blocks needed
  * to allocate @blocks
@@ -695,9 +707,11 @@ static void ext4_ext_show_move(struct inode *inode, struct ext4_ext_path *path,
 
 void ext4_ext_drop_refs(struct ext4_ext_path *path)
 {
-       int depth = path->p_depth;
-       int i;
+       int depth, i;
 
+       if (!path)
+               return;
+       depth = path->p_depth;
        for (i = 0; i <= depth; i++, path++)
                if (path->p_bh) {
                        brelse(path->p_bh);
@@ -841,24 +855,32 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode)
 }
 
 struct ext4_ext_path *
-ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
-                    struct ext4_ext_path *path, int flags)
+ext4_find_extent(struct inode *inode, ext4_lblk_t block,
+                struct ext4_ext_path **orig_path, int flags)
 {
        struct ext4_extent_header *eh;
        struct buffer_head *bh;
-       short int depth, i, ppos = 0, alloc = 0;
+       struct ext4_ext_path *path = orig_path ? *orig_path : NULL;
+       short int depth, i, ppos = 0;
        int ret;
 
        eh = ext_inode_hdr(inode);
        depth = ext_depth(inode);
 
-       /* account possible depth increase */
+       if (path) {
+               ext4_ext_drop_refs(path);
+               if (depth > path[0].p_maxdepth) {
+                       kfree(path);
+                       *orig_path = path = NULL;
+               }
+       }
        if (!path) {
+               /* account possible depth increase */
                path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
                                GFP_NOFS);
-               if (!path)
+               if (unlikely(!path))
                        return ERR_PTR(-ENOMEM);
-               alloc = 1;
+               path[0].p_maxdepth = depth + 1;
        }
        path[0].p_hdr = eh;
        path[0].p_bh = NULL;
@@ -876,7 +898,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 
                bh = read_extent_tree_block(inode, path[ppos].p_block, --i,
                                            flags);
-               if (IS_ERR(bh)) {
+               if (unlikely(IS_ERR(bh))) {
                        ret = PTR_ERR(bh);
                        goto err;
                }
@@ -910,8 +932,9 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
 
 err:
        ext4_ext_drop_refs(path);
-       if (alloc)
-               kfree(path);
+       kfree(path);
+       if (orig_path)
+               *orig_path = NULL;
        return ERR_PTR(ret);
 }
 
@@ -1238,16 +1261,24 @@ cleanup:
  *   just created block
  */
 static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
-                                unsigned int flags,
-                                struct ext4_extent *newext)
+                                unsigned int flags)
 {
        struct ext4_extent_header *neh;
        struct buffer_head *bh;
-       ext4_fsblk_t newblock;
+       ext4_fsblk_t newblock, goal = 0;
+       struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
        int err = 0;
 
-       newblock = ext4_ext_new_meta_block(handle, inode, NULL,
-               newext, &err, flags);
+       /* Try to prepend new index to old one */
+       if (ext_depth(inode))
+               goal = ext4_idx_pblock(EXT_FIRST_INDEX(ext_inode_hdr(inode)));
+       if (goal > le32_to_cpu(es->s_first_data_block)) {
+               flags |= EXT4_MB_HINT_TRY_GOAL;
+               goal--;
+       } else
+               goal = ext4_inode_to_goal_block(inode);
+       newblock = ext4_new_meta_blocks(handle, inode, goal, flags,
+                                       NULL, &err);
        if (newblock == 0)
                return err;
 
@@ -1314,9 +1345,10 @@ out:
 static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode,
                                    unsigned int mb_flags,
                                    unsigned int gb_flags,
-                                   struct ext4_ext_path *path,
+                                   struct ext4_ext_path **ppath,
                                    struct ext4_extent *newext)
 {
+       struct ext4_ext_path *path = *ppath;
        struct ext4_ext_path *curp;
        int depth, i, err = 0;
 
@@ -1340,23 +1372,21 @@ repeat:
                        goto out;
 
                /* refill path */
-               ext4_ext_drop_refs(path);
-               path = ext4_ext_find_extent(inode,
+               path = ext4_find_extent(inode,
                                    (ext4_lblk_t)le32_to_cpu(newext->ee_block),
-                                   path, gb_flags);
+                                   ppath, gb_flags);
                if (IS_ERR(path))
                        err = PTR_ERR(path);
        } else {
                /* tree is full, time to grow in depth */
-               err = ext4_ext_grow_indepth(handle, inode, mb_flags, newext);
+               err = ext4_ext_grow_indepth(handle, inode, mb_flags);
                if (err)
                        goto out;
 
                /* refill path */
-               ext4_ext_drop_refs(path);
-               path = ext4_ext_find_extent(inode,
+               path = ext4_find_extent(inode,
                                   (ext4_lblk_t)le32_to_cpu(newext->ee_block),
-                                   path, gb_flags);
+                                   ppath, gb_flags);
                if (IS_ERR(path)) {
                        err = PTR_ERR(path);
                        goto out;
@@ -1559,7 +1589,7 @@ found_extent:
  * allocated block. Thus, index entries have to be consistent
  * with leaves.
  */
-static ext4_lblk_t
+ext4_lblk_t
 ext4_ext_next_allocated_block(struct ext4_ext_path *path)
 {
        int depth;
@@ -1802,6 +1832,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
                sizeof(struct ext4_extent_idx);
        s += sizeof(struct ext4_extent_header);
 
+       path[1].p_maxdepth = path[0].p_maxdepth;
        memcpy(path[0].p_hdr, path[1].p_hdr, s);
        path[0].p_depth = 0;
        path[0].p_ext = EXT_FIRST_EXTENT(path[0].p_hdr) +
@@ -1896,9 +1927,10 @@ out:
  * creating new leaf in the no-space case.
  */
 int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
-                               struct ext4_ext_path *path,
+                               struct ext4_ext_path **ppath,
                                struct ext4_extent *newext, int gb_flags)
 {
+       struct ext4_ext_path *path = *ppath;
        struct ext4_extent_header *eh;
        struct ext4_extent *ex, *fex;
        struct ext4_extent *nearex; /* nearest extent */
@@ -1907,6 +1939,8 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
        ext4_lblk_t next;
        int mb_flags = 0, unwritten;
 
+       if (gb_flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               mb_flags |= EXT4_MB_DELALLOC_RESERVED;
        if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
                EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
                return -EIO;
@@ -1925,7 +1959,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
                /*
                 * Try to see whether we should rather test the extent on
                 * right from ex, or from the left of ex. This is because
-                * ext4_ext_find_extent() can return either extent on the
+                * ext4_find_extent() can return either extent on the
                 * left, or on the right from the searched position. This
                 * will make merging more effective.
                 */
@@ -2008,7 +2042,7 @@ prepend:
        if (next != EXT_MAX_BLOCKS) {
                ext_debug("next leaf block - %u\n", next);
                BUG_ON(npath != NULL);
-               npath = ext4_ext_find_extent(inode, next, NULL, 0);
+               npath = ext4_find_extent(inode, next, NULL, 0);
                if (IS_ERR(npath))
                        return PTR_ERR(npath);
                BUG_ON(npath->p_depth != path->p_depth);
@@ -2028,9 +2062,9 @@ prepend:
         * We're gonna add a new leaf in the tree.
         */
        if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL)
-               mb_flags = EXT4_MB_USE_RESERVED;
+               mb_flags |= EXT4_MB_USE_RESERVED;
        err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
-                                      path, newext);
+                                      ppath, newext);
        if (err)
                goto cleanup;
        depth = ext_depth(inode);
@@ -2108,10 +2142,8 @@ merge:
        err = ext4_ext_dirty(handle, inode, path + path->p_depth);
 
 cleanup:
-       if (npath) {
-               ext4_ext_drop_refs(npath);
-               kfree(npath);
-       }
+       ext4_ext_drop_refs(npath);
+       kfree(npath);
        return err;
 }
 
@@ -2133,13 +2165,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
                /* find extent for this block */
                down_read(&EXT4_I(inode)->i_data_sem);
 
-               if (path && ext_depth(inode) != depth) {
-                       /* depth was changed. we have to realloc path */
-                       kfree(path);
-                       path = NULL;
-               }
-
-               path = ext4_ext_find_extent(inode, block, path, 0);
+               path = ext4_find_extent(inode, block, &path, 0);
                if (IS_ERR(path)) {
                        up_read(&EXT4_I(inode)->i_data_sem);
                        err = PTR_ERR(path);
@@ -2156,7 +2182,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
                }
                ex = path[depth].p_ext;
                next = ext4_ext_next_allocated_block(path);
-               ext4_ext_drop_refs(path);
 
                flags = 0;
                exists = 0;
@@ -2266,11 +2291,8 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
                block = es.es_lblk + es.es_len;
        }
 
-       if (path) {
-               ext4_ext_drop_refs(path);
-               kfree(path);
-       }
-
+       ext4_ext_drop_refs(path);
+       kfree(path);
        return err;
 }
 
@@ -2826,7 +2848,7 @@ again:
                ext4_lblk_t ee_block;
 
                /* find extent for this block */
-               path = ext4_ext_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
+               path = ext4_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
                if (IS_ERR(path)) {
                        ext4_journal_stop(handle);
                        return PTR_ERR(path);
@@ -2854,24 +2876,14 @@ again:
                 */
                if (end >= ee_block &&
                    end < ee_block + ext4_ext_get_actual_len(ex) - 1) {
-                       int split_flag = 0;
-
-                       if (ext4_ext_is_unwritten(ex))
-                               split_flag = EXT4_EXT_MARK_UNWRIT1 |
-                                            EXT4_EXT_MARK_UNWRIT2;
-
                        /*
                         * Split the extent in two so that 'end' is the last
                         * block in the first new extent. Also we should not
                         * fail removing space due to ENOSPC so try to use
                         * reserved block if that happens.
                         */
-                       err = ext4_split_extent_at(handle, inode, path,
-                                       end + 1, split_flag,
-                                       EXT4_EX_NOCACHE |
-                                       EXT4_GET_BLOCKS_PRE_IO |
-                                       EXT4_GET_BLOCKS_METADATA_NOFAIL);
-
+                       err = ext4_force_split_extent_at(handle, inode, &path,
+                                                        end + 1, 1);
                        if (err < 0)
                                goto out;
                }
@@ -2893,7 +2905,7 @@ again:
                        ext4_journal_stop(handle);
                        return -ENOMEM;
                }
-               path[0].p_depth = depth;
+               path[0].p_maxdepth = path[0].p_depth = depth;
                path[0].p_hdr = ext_inode_hdr(inode);
                i = 0;
 
@@ -3013,10 +3025,9 @@ again:
 out:
        ext4_ext_drop_refs(path);
        kfree(path);
-       if (err == -EAGAIN) {
-               path = NULL;
+       path = NULL;
+       if (err == -EAGAIN)
                goto again;
-       }
        ext4_journal_stop(handle);
 
        return err;
@@ -3130,11 +3141,12 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
  */
 static int ext4_split_extent_at(handle_t *handle,
                             struct inode *inode,
-                            struct ext4_ext_path *path,
+                            struct ext4_ext_path **ppath,
                             ext4_lblk_t split,
                             int split_flag,
                             int flags)
 {
+       struct ext4_ext_path *path = *ppath;
        ext4_fsblk_t newblock;
        ext4_lblk_t ee_block;
        struct ext4_extent *ex, newex, orig_ex, zero_ex;
@@ -3205,7 +3217,7 @@ static int ext4_split_extent_at(handle_t *handle,
        if (split_flag & EXT4_EXT_MARK_UNWRIT2)
                ext4_ext_mark_unwritten(ex2);
 
-       err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
+       err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags);
        if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
                if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
                        if (split_flag & EXT4_EXT_DATA_VALID1) {
@@ -3271,11 +3283,12 @@ fix_extent_len:
  */
 static int ext4_split_extent(handle_t *handle,
                              struct inode *inode,
-                             struct ext4_ext_path *path,
+                             struct ext4_ext_path **ppath,
                              struct ext4_map_blocks *map,
                              int split_flag,
                              int flags)
 {
+       struct ext4_ext_path *path = *ppath;
        ext4_lblk_t ee_block;
        struct ext4_extent *ex;
        unsigned int ee_len, depth;
@@ -3298,7 +3311,7 @@ static int ext4_split_extent(handle_t *handle,
                                       EXT4_EXT_MARK_UNWRIT2;
                if (split_flag & EXT4_EXT_DATA_VALID2)
                        split_flag1 |= EXT4_EXT_DATA_VALID1;
-               err = ext4_split_extent_at(handle, inode, path,
+               err = ext4_split_extent_at(handle, inode, ppath,
                                map->m_lblk + map->m_len, split_flag1, flags1);
                if (err)
                        goto out;
@@ -3309,8 +3322,7 @@ static int ext4_split_extent(handle_t *handle,
         * Update path is required because previous ext4_split_extent_at() may
         * result in split of original leaf or extent zeroout.
         */
-       ext4_ext_drop_refs(path);
-       path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
+       path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
        if (IS_ERR(path))
                return PTR_ERR(path);
        depth = ext_depth(inode);
@@ -3330,7 +3342,7 @@ static int ext4_split_extent(handle_t *handle,
                        split_flag1 |= split_flag & (EXT4_EXT_MAY_ZEROOUT |
                                                     EXT4_EXT_MARK_UNWRIT2);
                }
-               err = ext4_split_extent_at(handle, inode, path,
+               err = ext4_split_extent_at(handle, inode, ppath,
                                map->m_lblk, split_flag1, flags);
                if (err)
                        goto out;
@@ -3364,9 +3376,10 @@ out:
 static int ext4_ext_convert_to_initialized(handle_t *handle,
                                           struct inode *inode,
                                           struct ext4_map_blocks *map,
-                                          struct ext4_ext_path *path,
+                                          struct ext4_ext_path **ppath,
                                           int flags)
 {
+       struct ext4_ext_path *path = *ppath;
        struct ext4_sb_info *sbi;
        struct ext4_extent_header *eh;
        struct ext4_map_blocks split_map;
@@ -3590,11 +3603,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                }
        }
 
-       allocated = ext4_split_extent(handle, inode, path,
-                                     &split_map, split_flag, flags);
-       if (allocated < 0)
-               err = allocated;
-
+       err = ext4_split_extent(handle, inode, ppath, &split_map, split_flag,
+                               flags);
+       if (err > 0)
+               err = 0;
 out:
        /* If we have gotten a failure, don't zero out status tree */
        if (!err)
@@ -3629,9 +3641,10 @@ out:
 static int ext4_split_convert_extents(handle_t *handle,
                                        struct inode *inode,
                                        struct ext4_map_blocks *map,
-                                       struct ext4_ext_path *path,
+                                       struct ext4_ext_path **ppath,
                                        int flags)
 {
+       struct ext4_ext_path *path = *ppath;
        ext4_lblk_t eof_block;
        ext4_lblk_t ee_block;
        struct ext4_extent *ex;
@@ -3665,74 +3678,15 @@ static int ext4_split_convert_extents(handle_t *handle,
                split_flag |= (EXT4_EXT_MARK_UNWRIT2 | EXT4_EXT_DATA_VALID2);
        }
        flags |= EXT4_GET_BLOCKS_PRE_IO;
-       return ext4_split_extent(handle, inode, path, map, split_flag, flags);
+       return ext4_split_extent(handle, inode, ppath, map, split_flag, flags);
 }
 
-static int ext4_convert_initialized_extents(handle_t *handle,
-                                           struct inode *inode,
-                                           struct ext4_map_blocks *map,
-                                           struct ext4_ext_path *path)
-{
-       struct ext4_extent *ex;
-       ext4_lblk_t ee_block;
-       unsigned int ee_len;
-       int depth;
-       int err = 0;
-
-       depth = ext_depth(inode);
-       ex = path[depth].p_ext;
-       ee_block = le32_to_cpu(ex->ee_block);
-       ee_len = ext4_ext_get_actual_len(ex);
-
-       ext_debug("%s: inode %lu, logical"
-               "block %llu, max_blocks %u\n", __func__, inode->i_ino,
-                 (unsigned long long)ee_block, ee_len);
-
-       if (ee_block != map->m_lblk || ee_len > map->m_len) {
-               err = ext4_split_convert_extents(handle, inode, map, path,
-                               EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
-               if (err < 0)
-                       goto out;
-               ext4_ext_drop_refs(path);
-               path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
-               if (IS_ERR(path)) {
-                       err = PTR_ERR(path);
-                       goto out;
-               }
-               depth = ext_depth(inode);
-               ex = path[depth].p_ext;
-               if (!ex) {
-                       EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
-                                        (unsigned long) map->m_lblk);
-                       err = -EIO;
-                       goto out;
-               }
-       }
-
-       err = ext4_ext_get_access(handle, inode, path + depth);
-       if (err)
-               goto out;
-       /* first mark the extent as unwritten */
-       ext4_ext_mark_unwritten(ex);
-
-       /* note: ext4_ext_correct_indexes() isn't needed here because
-        * borders are not changed
-        */
-       ext4_ext_try_to_merge(handle, inode, path, ex);
-
-       /* Mark modified extent as dirty */
-       err = ext4_ext_dirty(handle, inode, path + path->p_depth);
-out:
-       ext4_ext_show_leaf(inode, path);
-       return err;
-}
-
-
 static int ext4_convert_unwritten_extents_endio(handle_t *handle,
                                                struct inode *inode,
                                                struct ext4_map_blocks *map,
-                                               struct ext4_ext_path *path)
+                                               struct ext4_ext_path **ppath)
 {
+       struct ext4_ext_path *path = *ppath;
        struct ext4_extent *ex;
        ext4_lblk_t ee_block;
        unsigned int ee_len;
@@ -3761,16 +3715,13 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
                             inode->i_ino, (unsigned long long)ee_block, ee_len,
                             (unsigned long long)map->m_lblk, map->m_len);
 #endif
-               err = ext4_split_convert_extents(handle, inode, map, path,
+               err = ext4_split_convert_extents(handle, inode, map, ppath,
                                                 EXT4_GET_BLOCKS_CONVERT);
                if (err < 0)
-                       goto out;
-               ext4_ext_drop_refs(path);
-               path = ext4_ext_find_extent(inode, map->m_lblk, path, 0);
-               if (IS_ERR(path)) {
-                       err = PTR_ERR(path);
-                       goto out;
-               }
+                       return err;
+               path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
+               if (IS_ERR(path))
+                       return PTR_ERR(path);
                depth = ext_depth(inode);
                ex = path[depth].p_ext;
        }
@@ -3963,12 +3914,16 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
 }
 
 static int
-ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
-                       struct ext4_map_blocks *map,
-                       struct ext4_ext_path *path, int flags,
-                       unsigned int allocated, ext4_fsblk_t newblock)
+convert_initialized_extent(handle_t *handle, struct inode *inode,
+                          struct ext4_map_blocks *map,
+                          struct ext4_ext_path **ppath, int flags,
+                          unsigned int allocated, ext4_fsblk_t newblock)
 {
-       int ret = 0;
+       struct ext4_ext_path *path = *ppath;
+       struct ext4_extent *ex;
+       ext4_lblk_t ee_block;
+       unsigned int ee_len;
+       int depth;
        int err = 0;
 
        /*
@@ -3978,28 +3933,67 @@ ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
        if (map->m_len > EXT_UNWRITTEN_MAX_LEN)
                map->m_len = EXT_UNWRITTEN_MAX_LEN / 2;
 
-       ret = ext4_convert_initialized_extents(handle, inode, map,
-                                               path);
-       if (ret >= 0) {
-               ext4_update_inode_fsync_trans(handle, inode, 1);
-               err = check_eofblocks_fl(handle, inode, map->m_lblk,
-                                        path, map->m_len);
-       } else
-               err = ret;
+       depth = ext_depth(inode);
+       ex = path[depth].p_ext;
+       ee_block = le32_to_cpu(ex->ee_block);
+       ee_len = ext4_ext_get_actual_len(ex);
+
+       ext_debug("%s: inode %lu, logical"
+               "block %llu, max_blocks %u\n", __func__, inode->i_ino,
+                 (unsigned long long)ee_block, ee_len);
+
+       if (ee_block != map->m_lblk || ee_len > map->m_len) {
+               err = ext4_split_convert_extents(handle, inode, map, ppath,
+                               EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
+               if (err < 0)
+                       return err;
+               path = ext4_find_extent(inode, map->m_lblk, ppath, 0);
+               if (IS_ERR(path))
+                       return PTR_ERR(path);
+               depth = ext_depth(inode);
+               ex = path[depth].p_ext;
+               if (!ex) {
+                       EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
+                                        (unsigned long) map->m_lblk);
+                       return -EIO;
+               }
+       }
+
+       err = ext4_ext_get_access(handle, inode, path + depth);
+       if (err)
+               return err;
+       /* first mark the extent as unwritten */
+       ext4_ext_mark_unwritten(ex);
+
+       /* note: ext4_ext_correct_indexes() isn't needed here because
+        * borders are not changed
+        */
+       ext4_ext_try_to_merge(handle, inode, path, ex);
+
+       /* Mark modified extent as dirty */
+       err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+       if (err)
+               return err;
+       ext4_ext_show_leaf(inode, path);
+
+       ext4_update_inode_fsync_trans(handle, inode, 1);
+       err = check_eofblocks_fl(handle, inode, map->m_lblk, path, map->m_len);
+       if (err)
+               return err;
        map->m_flags |= EXT4_MAP_UNWRITTEN;
        if (allocated > map->m_len)
                allocated = map->m_len;
        map->m_len = allocated;
-
-       return err ? err : allocated;
+       return allocated;
 }
 
 static int
 ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
                        struct ext4_map_blocks *map,
-                       struct ext4_ext_path *path, int flags,
+                       struct ext4_ext_path **ppath, int flags,
                        unsigned int allocated, ext4_fsblk_t newblock)
 {
+       struct ext4_ext_path *path = *ppath;
        int ret = 0;
        int err = 0;
        ext4_io_end_t *io = ext4_inode_aio(inode);
@@ -4021,8 +4015,8 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
 
        /* get_block() before submit the IO, split the extent */
        if (flags & EXT4_GET_BLOCKS_PRE_IO) {
-               ret = ext4_split_convert_extents(handle, inode, map,
-                                        path, flags | EXT4_GET_BLOCKS_CONVERT);
+               ret = ext4_split_convert_extents(handle, inode, map, ppath,
+                                        flags | EXT4_GET_BLOCKS_CONVERT);
                if (ret <= 0)
                        goto out;
                /*
@@ -4040,7 +4034,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
        /* IO end_io complete, convert the filled extent to written */
        if (flags & EXT4_GET_BLOCKS_CONVERT) {
                ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
-                                                       path);
+                                                          ppath);
                if (ret >= 0) {
                        ext4_update_inode_fsync_trans(handle, inode, 1);
                        err = check_eofblocks_fl(handle, inode, map->m_lblk,
@@ -4078,7 +4072,7 @@ ext4_ext_handle_unwritten_extents(handle_t *handle, struct inode *inode,
        }
 
        /* buffered write, writepage time, convert*/
-       ret = ext4_ext_convert_to_initialized(handle, inode, map, path, flags);
+       ret = ext4_ext_convert_to_initialized(handle, inode, map, ppath, flags);
        if (ret >= 0)
                ext4_update_inode_fsync_trans(handle, inode, 1);
 out:
@@ -4279,7 +4273,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
        trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags);
 
        /* find extent for this block */
-       path = ext4_ext_find_extent(inode, map->m_lblk, NULL, 0);
+       path = ext4_find_extent(inode, map->m_lblk, NULL, 0);
        if (IS_ERR(path)) {
                err = PTR_ERR(path);
                path = NULL;
@@ -4291,7 +4285,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
        /*
         * consistent leaf must not be empty;
         * this situation is possible, though, _during_ tree modification;
-        * this is why assert can't be put in ext4_ext_find_extent()
+        * this is why assert can't be put in ext4_find_extent()
         */
        if (unlikely(path[depth].p_ext == NULL && depth != 0)) {
                EXT4_ERROR_INODE(inode, "bad extent address "
@@ -4331,15 +4325,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
                         */
                        if ((!ext4_ext_is_unwritten(ex)) &&
                            (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) {
-                               allocated = ext4_ext_convert_initialized_extent(
-                                               handle, inode, map, path, flags,
-                                               allocated, newblock);
+                               allocated = convert_initialized_extent(
+                                               handle, inode, map, &path,
+                                               flags, allocated, newblock);
                                goto out2;
                        } else if (!ext4_ext_is_unwritten(ex))
                                goto out;
 
                        ret = ext4_ext_handle_unwritten_extents(
-                               handle, inode, map, path, flags,
+                               handle, inode, map, &path, flags,
                                allocated, newblock);
                        if (ret < 0)
                                err = ret;
@@ -4376,7 +4370,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
 
        /*
         * If we are doing bigalloc, check to see if the extent returned
-        * by ext4_ext_find_extent() implies a cluster we can use.
+        * by ext4_find_extent() implies a cluster we can use.
         */
        if (cluster_offset && ex &&
            get_implied_cluster_alloc(inode->i_sb, map, ex, path)) {
@@ -4451,6 +4445,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
                ar.flags = 0;
        if (flags & EXT4_GET_BLOCKS_NO_NORMALIZE)
                ar.flags |= EXT4_MB_HINT_NOPREALLOC;
+       if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               ar.flags |= EXT4_MB_DELALLOC_RESERVED;
        newblock = ext4_mb_new_blocks(handle, &ar, &err);
        if (!newblock)
                goto out2;
@@ -4486,7 +4482,7 @@ got_allocated_blocks:
                err = check_eofblocks_fl(handle, inode, map->m_lblk,
                                         path, ar.len);
        if (!err)
-               err = ext4_ext_insert_extent(handle, inode, path,
+               err = ext4_ext_insert_extent(handle, inode, &path,
                                             &newex, flags);
 
        if (!err && set_unwritten) {
@@ -4619,10 +4615,8 @@ out:
        map->m_pblk = newblock;
        map->m_len = allocated;
 out2:
-       if (path) {
-               ext4_ext_drop_refs(path);
-               kfree(path);
-       }
+       ext4_ext_drop_refs(path);
+       kfree(path);
 
        trace_ext4_ext_map_blocks_exit(inode, flags, map,
                                       err ? err : allocated);
@@ -4799,7 +4793,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
                max_blocks -= lblk;
 
        flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT |
-               EXT4_GET_BLOCKS_CONVERT_UNWRITTEN;
+               EXT4_GET_BLOCKS_CONVERT_UNWRITTEN |
+               EXT4_EX_NOCACHE;
        if (mode & FALLOC_FL_KEEP_SIZE)
                flags |= EXT4_GET_BLOCKS_KEEP_SIZE;
 
@@ -4837,15 +4832,21 @@ static long ext4_zero_range(struct file *file, loff_t offset,
                ext4_inode_block_unlocked_dio(inode);
                inode_dio_wait(inode);
 
+               ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
+                                            flags, mode);
+               if (ret)
+                       goto out_dio;
                /*
                 * Remove entire range from the extent status tree.
+                *
+                * ext4_es_remove_extent(inode, lblk, max_blocks) is
+                * NOT sufficient.  I'm not sure why this is the case,
+                * but let's be conservative and remove the extent
+                * status tree for the entire inode.  There should be
+                * no outstanding delalloc extents thanks to the
+                * filemap_write_and_wait_range() call above.
                 */
-               ret = ext4_es_remove_extent(inode, lblk, max_blocks);
-               if (ret)
-                       goto out_dio;
-
-               ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
-                                            flags, mode);
+               ret = ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);
                if (ret)
                        goto out_dio;
        }
@@ -5304,36 +5305,31 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
        struct ext4_ext_path *path;
        int ret = 0, depth;
        struct ext4_extent *extent;
-       ext4_lblk_t stop_block, current_block;
+       ext4_lblk_t stop_block;
        ext4_lblk_t ex_start, ex_end;
 
        /* Let path point to the last extent */
-       path = ext4_ext_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
+       path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
        if (IS_ERR(path))
                return PTR_ERR(path);
 
        depth = path->p_depth;
        extent = path[depth].p_ext;
-       if (!extent) {
-               ext4_ext_drop_refs(path);
-               kfree(path);
-               return ret;
-       }
+       if (!extent)
+               goto out;
 
        stop_block = le32_to_cpu(extent->ee_block) +
                        ext4_ext_get_actual_len(extent);
-       ext4_ext_drop_refs(path);
-       kfree(path);
 
        /* Nothing to shift, if hole is at the end of file */
        if (start >= stop_block)
-               return ret;
+               goto out;
 
        /*
         * Don't start shifting extents until we make sure the hole is big
         * enough to accomodate the shift.
         */
-       path = ext4_ext_find_extent(inode, start - 1, NULL, 0);
+       path = ext4_find_extent(inode, start - 1, &path, 0);
        if (IS_ERR(path))
                return PTR_ERR(path);
        depth = path->p_depth;
@@ -5346,8 +5342,6 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
                ex_start = 0;
                ex_end = 0;
        }
-       ext4_ext_drop_refs(path);
-       kfree(path);
 
        if ((start == ex_start && shift > ex_start) ||
            (shift > start - ex_end))
@@ -5355,7 +5349,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
 
        /* Its safe to start updating extents */
        while (start < stop_block) {
-               path = ext4_ext_find_extent(inode, start, NULL, 0);
+               path = ext4_find_extent(inode, start, &path, 0);
                if (IS_ERR(path))
                        return PTR_ERR(path);
                depth = path->p_depth;
@@ -5365,27 +5359,23 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
                                         (unsigned long) start);
                        return -EIO;
                }
-
-               current_block = le32_to_cpu(extent->ee_block);
-               if (start > current_block) {
+               if (start > le32_to_cpu(extent->ee_block)) {
                        /* Hole, move to the next extent */
-                       ret = mext_next_extent(inode, path, &extent);
-                       if (ret != 0) {
-                               ext4_ext_drop_refs(path);
-                               kfree(path);
-                               if (ret == 1)
-                                       ret = 0;
-                               break;
+                       if (extent < EXT_LAST_EXTENT(path[depth].p_hdr)) {
+                               path[depth].p_ext++;
+                       } else {
+                               start = ext4_ext_next_allocated_block(path);
+                               continue;
                        }
                }
                ret = ext4_ext_shift_path_extents(path, shift, inode,
                                handle, &start);
-               ext4_ext_drop_refs(path);
-               kfree(path);
                if (ret)
                        break;
        }
-
+out:
+       ext4_ext_drop_refs(path);
+       kfree(path);
        return ret;
 }
 
@@ -5508,3 +5498,199 @@ out_mutex:
        mutex_unlock(&inode->i_mutex);
        return ret;
 }
+
+/**
+ * ext4_swap_extents - Swap extents between two inodes
+ *
+ * @inode1:    First inode
+ * @inode2:    Second inode
+ * @lblk1:     Start block for first inode
+ * @lblk2:     Start block for second inode
+ * @count:     Number of blocks to swap
+ * @mark_unwritten: Mark second inode's extents as unwritten after swap
+ * @erp:       Pointer to save error value
+ *
+ * This helper routine does exactly what is promise "swap extents". All other
+ * stuff such as page-cache locking consistency, bh mapping consistency or
+ * extent's data copying must be performed by caller.
+ * Locking:
+ *             i_mutex is held for both inodes
+ *             i_data_sem is locked for write for both inodes
+ * Assumptions:
+ *             All pages from requested range are locked for both inodes
+ */
+int
+ext4_swap_extents(handle_t *handle, struct inode *inode1,
+                    struct inode *inode2, ext4_lblk_t lblk1, ext4_lblk_t lblk2,
+                 ext4_lblk_t count, int unwritten, int *erp)
+{
+       struct ext4_ext_path *path1 = NULL;
+       struct ext4_ext_path *path2 = NULL;
+       int replaced_count = 0;
+
+       BUG_ON(!rwsem_is_locked(&EXT4_I(inode1)->i_data_sem));
+       BUG_ON(!rwsem_is_locked(&EXT4_I(inode2)->i_data_sem));
+       BUG_ON(!mutex_is_locked(&inode1->i_mutex));
+       BUG_ON(!mutex_is_locked(&inode1->i_mutex));
+
+       *erp = ext4_es_remove_extent(inode1, lblk1, count);
+       if (unlikely(*erp))
+               return 0;
+       *erp = ext4_es_remove_extent(inode2, lblk2, count);
+       if (unlikely(*erp))
+               return 0;
+
+       while (count) {
+               struct ext4_extent *ex1, *ex2, tmp_ex;
+               ext4_lblk_t e1_blk, e2_blk;
+               int e1_len, e2_len, len;
+               int split = 0;
+
+               path1 = ext4_find_extent(inode1, lblk1, NULL, EXT4_EX_NOCACHE);
+               if (unlikely(IS_ERR(path1))) {
+                       *erp = PTR_ERR(path1);
+                       path1 = NULL;
+               finish:
+                       count = 0;
+                       goto repeat;
+               }
+               path2 = ext4_find_extent(inode2, lblk2, NULL, EXT4_EX_NOCACHE);
+               if (unlikely(IS_ERR(path2))) {
+                       *erp = PTR_ERR(path2);
+                       path2 = NULL;
+                       goto finish;
+               }
+               ex1 = path1[path1->p_depth].p_ext;
+               ex2 = path2[path2->p_depth].p_ext;
+               /* Do we have somthing to swap ? */
+               if (unlikely(!ex2 || !ex1))
+                       goto finish;
+
+               e1_blk = le32_to_cpu(ex1->ee_block);
+               e2_blk = le32_to_cpu(ex2->ee_block);
+               e1_len = ext4_ext_get_actual_len(ex1);
+               e2_len = ext4_ext_get_actual_len(ex2);
+
+               /* Hole handling */
+               if (!in_range(lblk1, e1_blk, e1_len) ||
+                   !in_range(lblk2, e2_blk, e2_len)) {
+                       ext4_lblk_t next1, next2;
+
+                       /* if hole after extent, then go to next extent */
+                       next1 = ext4_ext_next_allocated_block(path1);
+                       next2 = ext4_ext_next_allocated_block(path2);
+                       /* If hole before extent, then shift to that extent */
+                       if (e1_blk > lblk1)
+                               next1 = e1_blk;
+                       if (e2_blk > lblk2)
+                               next2 = e1_blk;
+                       /* Do we have something to swap */
+                       if (next1 == EXT_MAX_BLOCKS || next2 == EXT_MAX_BLOCKS)
+                               goto finish;
+                       /* Move to the rightest boundary */
+                       len = next1 - lblk1;
+                       if (len < next2 - lblk2)
+                               len = next2 - lblk2;
+                       if (len > count)
+                               len = count;
+                       lblk1 += len;
+                       lblk2 += len;
+                       count -= len;
+                       goto repeat;
+               }
+
+               /* Prepare left boundary */
+               if (e1_blk < lblk1) {
+                       split = 1;
+                       *erp = ext4_force_split_extent_at(handle, inode1,
+                                               &path1, lblk1, 0);
+                       if (unlikely(*erp))
+                               goto finish;
+               }
+               if (e2_blk < lblk2) {
+                       split = 1;
+                       *erp = ext4_force_split_extent_at(handle, inode2,
+                                               &path2,  lblk2, 0);
+                       if (unlikely(*erp))
+                               goto finish;
+               }
+               /* ext4_split_extent_at() may result in leaf extent split,
+                * path must to be revalidated. */
+               if (split)
+                       goto repeat;
+
+               /* Prepare right boundary */
+               len = count;
+               if (len > e1_blk + e1_len - lblk1)
+                       len = e1_blk + e1_len - lblk1;
+               if (len > e2_blk + e2_len - lblk2)
+                       len = e2_blk + e2_len - lblk2;
+
+               if (len != e1_len) {
+                       split = 1;
+                       *erp = ext4_force_split_extent_at(handle, inode1,
+                                               &path1, lblk1 + len, 0);
+                       if (unlikely(*erp))
+                               goto finish;
+               }
+               if (len != e2_len) {
+                       split = 1;
+                       *erp = ext4_force_split_extent_at(handle, inode2,
+                                               &path2, lblk2 + len, 0);
+                       if (*erp)
+                               goto finish;
+               }
+               /* ext4_split_extent_at() may result in leaf extent split,
+                * path must to be revalidated. */
+               if (split)
+                       goto repeat;
+
+               BUG_ON(e2_len != e1_len);
+               *erp = ext4_ext_get_access(handle, inode1, path1 + path1->p_depth);
+               if (unlikely(*erp))
+                       goto finish;
+               *erp = ext4_ext_get_access(handle, inode2, path2 + path2->p_depth);
+               if (unlikely(*erp))
+                       goto finish;
+
+               /* Both extents are fully inside boundaries. Swap it now */
+               tmp_ex = *ex1;
+               ext4_ext_store_pblock(ex1, ext4_ext_pblock(ex2));
+               ext4_ext_store_pblock(ex2, ext4_ext_pblock(&tmp_ex));
+               ex1->ee_len = cpu_to_le16(e2_len);
+               ex2->ee_len = cpu_to_le16(e1_len);
+               if (unwritten)
+                       ext4_ext_mark_unwritten(ex2);
+               if (ext4_ext_is_unwritten(&tmp_ex))
+                       ext4_ext_mark_unwritten(ex1);
+
+               ext4_ext_try_to_merge(handle, inode2, path2, ex2);
+               ext4_ext_try_to_merge(handle, inode1, path1, ex1);
+               *erp = ext4_ext_dirty(handle, inode2, path2 +
+                                     path2->p_depth);
+               if (unlikely(*erp))
+                       goto finish;
+               *erp = ext4_ext_dirty(handle, inode1, path1 +
+                                     path1->p_depth);
+               /*
+                * Looks scarry ah..? second inode already points to new blocks,
+                * and it was successfully dirtied. But luckily error may happen
+                * only due to journal error, so full transaction will be
+                * aborted anyway.
+                */
+               if (unlikely(*erp))
+                       goto finish;
+               lblk1 += len;
+               lblk2 += len;
+               replaced_count += len;
+               count -= len;
+
+       repeat:
+               ext4_ext_drop_refs(path1);
+               kfree(path1);
+               ext4_ext_drop_refs(path2);
+               kfree(path2);
+               path1 = path2 = NULL;
+       }
+       return replaced_count;
+}
index 0b7e28e7eaa4303938877743114bce5e367a8c2d..94e7855ae71b03e26559e02cbe6491e9d8be2767 100644 (file)
@@ -11,6 +11,8 @@
  */
 #include <linux/rbtree.h>
 #include <linux/list_sort.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include "ext4.h"
 #include "extents_status.h"
 
@@ -313,19 +315,27 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
         */
        if (!ext4_es_is_delayed(es)) {
                EXT4_I(inode)->i_es_lru_nr++;
-               percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
+               percpu_counter_inc(&EXT4_SB(inode->i_sb)->
+                                       s_es_stats.es_stats_lru_cnt);
        }
 
+       EXT4_I(inode)->i_es_all_nr++;
+       percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt);
+
        return es;
 }
 
 static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
 {
+       EXT4_I(inode)->i_es_all_nr--;
+       percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt);
+
        /* Decrease the lru counter when this es is not delayed */
        if (!ext4_es_is_delayed(es)) {
                BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0);
                EXT4_I(inode)->i_es_lru_nr--;
-               percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
+               percpu_counter_dec(&EXT4_SB(inode->i_sb)->
+                                       s_es_stats.es_stats_lru_cnt);
        }
 
        kmem_cache_free(ext4_es_cachep, es);
@@ -426,7 +436,7 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
        unsigned short ee_len;
        int depth, ee_status, es_status;
 
-       path = ext4_ext_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
+       path = ext4_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
        if (IS_ERR(path))
                return;
 
@@ -499,10 +509,8 @@ static void ext4_es_insert_extent_ext_check(struct inode *inode,
                }
        }
 out:
-       if (path) {
-               ext4_ext_drop_refs(path);
-               kfree(path);
-       }
+       ext4_ext_drop_refs(path);
+       kfree(path);
 }
 
 static void ext4_es_insert_extent_ind_check(struct inode *inode,
@@ -731,6 +739,7 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
                          struct extent_status *es)
 {
        struct ext4_es_tree *tree;
+       struct ext4_es_stats *stats;
        struct extent_status *es1 = NULL;
        struct rb_node *node;
        int found = 0;
@@ -767,11 +776,15 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
        }
 
 out:
+       stats = &EXT4_SB(inode->i_sb)->s_es_stats;
        if (found) {
                BUG_ON(!es1);
                es->es_lblk = es1->es_lblk;
                es->es_len = es1->es_len;
                es->es_pblk = es1->es_pblk;
+               stats->es_stats_cache_hits++;
+       } else {
+               stats->es_stats_cache_misses++;
        }
 
        read_unlock(&EXT4_I(inode)->i_es_lock);
@@ -933,11 +946,16 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
                            struct ext4_inode_info *locked_ei)
 {
        struct ext4_inode_info *ei;
+       struct ext4_es_stats *es_stats;
        struct list_head *cur, *tmp;
        LIST_HEAD(skipped);
+       ktime_t start_time;
+       u64 scan_time;
        int nr_shrunk = 0;
        int retried = 0, skip_precached = 1, nr_skipped = 0;
 
+       es_stats = &sbi->s_es_stats;
+       start_time = ktime_get();
        spin_lock(&sbi->s_es_lru_lock);
 
 retry:
@@ -948,7 +966,8 @@ retry:
                 * If we have already reclaimed all extents from extent
                 * status tree, just stop the loop immediately.
                 */
-               if (percpu_counter_read_positive(&sbi->s_extent_cache_cnt) == 0)
+               if (percpu_counter_read_positive(
+                               &es_stats->es_stats_lru_cnt) == 0)
                        break;
 
                ei = list_entry(cur, struct ext4_inode_info, i_es_lru);
@@ -958,7 +977,7 @@ retry:
                 * time.  Normally we try hard to avoid shrinking
                 * precached inodes, but we will as a last resort.
                 */
-               if ((sbi->s_es_last_sorted < ei->i_touch_when) ||
+               if ((es_stats->es_stats_last_sorted < ei->i_touch_when) ||
                    (skip_precached && ext4_test_inode_state(&ei->vfs_inode,
                                                EXT4_STATE_EXT_PRECACHED))) {
                        nr_skipped++;
@@ -992,7 +1011,7 @@ retry:
        if ((nr_shrunk == 0) && nr_skipped && !retried) {
                retried++;
                list_sort(NULL, &sbi->s_es_lru, ext4_inode_touch_time_cmp);
-               sbi->s_es_last_sorted = jiffies;
+               es_stats->es_stats_last_sorted = jiffies;
                ei = list_first_entry(&sbi->s_es_lru, struct ext4_inode_info,
                                      i_es_lru);
                /*
@@ -1010,6 +1029,22 @@ retry:
        if (locked_ei && nr_shrunk == 0)
                nr_shrunk = __es_try_to_reclaim_extents(locked_ei, nr_to_scan);
 
+       scan_time = ktime_to_ns(ktime_sub(ktime_get(), start_time));
+       if (likely(es_stats->es_stats_scan_time))
+               es_stats->es_stats_scan_time = (scan_time +
+                               es_stats->es_stats_scan_time*3) / 4;
+       else
+               es_stats->es_stats_scan_time = scan_time;
+       if (scan_time > es_stats->es_stats_max_scan_time)
+               es_stats->es_stats_max_scan_time = scan_time;
+       if (likely(es_stats->es_stats_shrunk))
+               es_stats->es_stats_shrunk = (nr_shrunk +
+                               es_stats->es_stats_shrunk*3) / 4;
+       else
+               es_stats->es_stats_shrunk = nr_shrunk;
+
+       trace_ext4_es_shrink(sbi->s_sb, nr_shrunk, scan_time, skip_precached,
+                            nr_skipped, retried);
        return nr_shrunk;
 }
 
@@ -1020,8 +1055,8 @@ static unsigned long ext4_es_count(struct shrinker *shrink,
        struct ext4_sb_info *sbi;
 
        sbi = container_of(shrink, struct ext4_sb_info, s_es_shrinker);
-       nr = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
-       trace_ext4_es_shrink_enter(sbi->s_sb, sc->nr_to_scan, nr);
+       nr = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_lru_cnt);
+       trace_ext4_es_shrink_count(sbi->s_sb, sc->nr_to_scan, nr);
        return nr;
 }
 
@@ -1033,31 +1068,160 @@ static unsigned long ext4_es_scan(struct shrinker *shrink,
        int nr_to_scan = sc->nr_to_scan;
        int ret, nr_shrunk;
 
-       ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
-       trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
+       ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_lru_cnt);
+       trace_ext4_es_shrink_scan_enter(sbi->s_sb, nr_to_scan, ret);
 
        if (!nr_to_scan)
                return ret;
 
        nr_shrunk = __ext4_es_shrink(sbi, nr_to_scan, NULL);
 
-       trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
+       trace_ext4_es_shrink_scan_exit(sbi->s_sb, nr_shrunk, ret);
        return nr_shrunk;
 }
 
-void ext4_es_register_shrinker(struct ext4_sb_info *sbi)
+static void *ext4_es_seq_shrinker_info_start(struct seq_file *seq, loff_t *pos)
 {
+       return *pos ? NULL : SEQ_START_TOKEN;
+}
+
+static void *
+ext4_es_seq_shrinker_info_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       return NULL;
+}
+
+static int ext4_es_seq_shrinker_info_show(struct seq_file *seq, void *v)
+{
+       struct ext4_sb_info *sbi = seq->private;
+       struct ext4_es_stats *es_stats = &sbi->s_es_stats;
+       struct ext4_inode_info *ei, *max = NULL;
+       unsigned int inode_cnt = 0;
+
+       if (v != SEQ_START_TOKEN)
+               return 0;
+
+       /* here we just find an inode that has the max nr. of objects */
+       spin_lock(&sbi->s_es_lru_lock);
+       list_for_each_entry(ei, &sbi->s_es_lru, i_es_lru) {
+               inode_cnt++;
+               if (max && max->i_es_all_nr < ei->i_es_all_nr)
+                       max = ei;
+               else if (!max)
+                       max = ei;
+       }
+       spin_unlock(&sbi->s_es_lru_lock);
+
+       seq_printf(seq, "stats:\n  %lld objects\n  %lld reclaimable objects\n",
+                  percpu_counter_sum_positive(&es_stats->es_stats_all_cnt),
+                  percpu_counter_sum_positive(&es_stats->es_stats_lru_cnt));
+       seq_printf(seq, "  %lu/%lu cache hits/misses\n",
+                  es_stats->es_stats_cache_hits,
+                  es_stats->es_stats_cache_misses);
+       if (es_stats->es_stats_last_sorted != 0)
+               seq_printf(seq, "  %u ms last sorted interval\n",
+                          jiffies_to_msecs(jiffies -
+                                           es_stats->es_stats_last_sorted));
+       if (inode_cnt)
+               seq_printf(seq, "  %d inodes on lru list\n", inode_cnt);
+
+       seq_printf(seq, "average:\n  %llu us scan time\n",
+           div_u64(es_stats->es_stats_scan_time, 1000));
+       seq_printf(seq, "  %lu shrunk objects\n", es_stats->es_stats_shrunk);
+       if (inode_cnt)
+               seq_printf(seq,
+                   "maximum:\n  %lu inode (%u objects, %u reclaimable)\n"
+                   "  %llu us max scan time\n",
+                   max->vfs_inode.i_ino, max->i_es_all_nr, max->i_es_lru_nr,
+                   div_u64(es_stats->es_stats_max_scan_time, 1000));
+
+       return 0;
+}
+
+static void ext4_es_seq_shrinker_info_stop(struct seq_file *seq, void *v)
+{
+}
+
+static const struct seq_operations ext4_es_seq_shrinker_info_ops = {
+       .start = ext4_es_seq_shrinker_info_start,
+       .next  = ext4_es_seq_shrinker_info_next,
+       .stop  = ext4_es_seq_shrinker_info_stop,
+       .show  = ext4_es_seq_shrinker_info_show,
+};
+
+static int
+ext4_es_seq_shrinker_info_open(struct inode *inode, struct file *file)
+{
+       int ret;
+
+       ret = seq_open(file, &ext4_es_seq_shrinker_info_ops);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+               m->private = PDE_DATA(inode);
+       }
+
+       return ret;
+}
+
+static int
+ext4_es_seq_shrinker_info_release(struct inode *inode, struct file *file)
+{
+       return seq_release(inode, file);
+}
+
+static const struct file_operations ext4_es_seq_shrinker_info_fops = {
+       .owner          = THIS_MODULE,
+       .open           = ext4_es_seq_shrinker_info_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = ext4_es_seq_shrinker_info_release,
+};
+
+int ext4_es_register_shrinker(struct ext4_sb_info *sbi)
+{
+       int err;
+
        INIT_LIST_HEAD(&sbi->s_es_lru);
        spin_lock_init(&sbi->s_es_lru_lock);
-       sbi->s_es_last_sorted = 0;
+       sbi->s_es_stats.es_stats_last_sorted = 0;
+       sbi->s_es_stats.es_stats_shrunk = 0;
+       sbi->s_es_stats.es_stats_cache_hits = 0;
+       sbi->s_es_stats.es_stats_cache_misses = 0;
+       sbi->s_es_stats.es_stats_scan_time = 0;
+       sbi->s_es_stats.es_stats_max_scan_time = 0;
+       err = percpu_counter_init(&sbi->s_es_stats.es_stats_all_cnt, 0, GFP_KERNEL);
+       if (err)
+               return err;
+       err = percpu_counter_init(&sbi->s_es_stats.es_stats_lru_cnt, 0, GFP_KERNEL);
+       if (err)
+               goto err1;
+
        sbi->s_es_shrinker.scan_objects = ext4_es_scan;
        sbi->s_es_shrinker.count_objects = ext4_es_count;
        sbi->s_es_shrinker.seeks = DEFAULT_SEEKS;
-       register_shrinker(&sbi->s_es_shrinker);
+       err = register_shrinker(&sbi->s_es_shrinker);
+       if (err)
+               goto err2;
+
+       if (sbi->s_proc)
+               proc_create_data("es_shrinker_info", S_IRUGO, sbi->s_proc,
+                                &ext4_es_seq_shrinker_info_fops, sbi);
+
+       return 0;
+
+err2:
+       percpu_counter_destroy(&sbi->s_es_stats.es_stats_lru_cnt);
+err1:
+       percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
+       return err;
 }
 
 void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi)
 {
+       if (sbi->s_proc)
+               remove_proc_entry("es_shrinker_info", sbi->s_proc);
+       percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
+       percpu_counter_destroy(&sbi->s_es_stats.es_stats_lru_cnt);
        unregister_shrinker(&sbi->s_es_shrinker);
 }
 
index f1b62a41992059f3cbebd16ee6caaf25ee156283..efd5f970b5013085dec20e421b8ff3ced53246c2 100644 (file)
@@ -64,6 +64,17 @@ struct ext4_es_tree {
        struct extent_status *cache_es; /* recently accessed extent */
 };
 
+struct ext4_es_stats {
+       unsigned long es_stats_last_sorted;
+       unsigned long es_stats_shrunk;
+       unsigned long es_stats_cache_hits;
+       unsigned long es_stats_cache_misses;
+       u64 es_stats_scan_time;
+       u64 es_stats_max_scan_time;
+       struct percpu_counter es_stats_all_cnt;
+       struct percpu_counter es_stats_lru_cnt;
+};
+
 extern int __init ext4_init_es(void);
 extern void ext4_exit_es(void);
 extern void ext4_es_init_tree(struct ext4_es_tree *tree);
@@ -138,7 +149,7 @@ static inline void ext4_es_store_pblock_status(struct extent_status *es,
                       (pb & ~ES_MASK));
 }
 
-extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi);
+extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi);
 extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
 extern void ext4_es_lru_add(struct inode *inode);
 extern void ext4_es_lru_del(struct inode *inode);
index aca7b24a443243c3415221edd082c71e2a1a2ce5..8131be8c0af3166aac865557baa9f0371564a397 100644 (file)
@@ -137,10 +137,10 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                        iov_iter_truncate(from, sbi->s_bitmap_maxbytes - pos);
        }
 
+       iocb->private = &overwrite;
        if (o_direct) {
                blk_start_plug(&plug);
 
-               iocb->private = &overwrite;
 
                /* check whether we do a DIO overwrite or not */
                if (ext4_should_dioread_nolock(inode) && !aio_mutex &&
index 5b87fc36aab863d073de371bd8e9ae0159281917..ac644c31ca67472f3a16f91c6107e3d06772f66f 100644 (file)
@@ -887,6 +887,10 @@ got:
                struct buffer_head *block_bitmap_bh;
 
                block_bitmap_bh = ext4_read_block_bitmap(sb, group);
+               if (!block_bitmap_bh) {
+                       err = -EIO;
+                       goto out;
+               }
                BUFFER_TRACE(block_bitmap_bh, "get block bitmap access");
                err = ext4_journal_get_write_access(handle, block_bitmap_bh);
                if (err) {
@@ -1011,8 +1015,7 @@ got:
        spin_unlock(&sbi->s_next_gen_lock);
 
        /* Precompute checksum seed for inode metadata */
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+       if (ext4_has_metadata_csum(sb)) {
                __u32 csum;
                __le32 inum = cpu_to_le32(inode->i_ino);
                __le32 gen = cpu_to_le32(inode->i_generation);
index e75f840000a02f4fa1313ff027a5b071a6a7abc3..36b369697a131523f26f6a6336eec17b4da3ae4f 100644 (file)
@@ -318,34 +318,24 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned int blks,
  *     ext4_alloc_block() (normally -ENOSPC). Otherwise we set the chain
  *     as described above and return 0.
  */
-static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
-                            ext4_lblk_t iblock, int indirect_blks,
-                            int *blks, ext4_fsblk_t goal,
-                            ext4_lblk_t *offsets, Indirect *branch)
+static int ext4_alloc_branch(handle_t *handle,
+                            struct ext4_allocation_request *ar,
+                            int indirect_blks, ext4_lblk_t *offsets,
+                            Indirect *branch)
 {
-       struct ext4_allocation_request  ar;
        struct buffer_head *            bh;
        ext4_fsblk_t                    b, new_blocks[4];
        __le32                          *p;
        int                             i, j, err, len = 1;
 
-       /*
-        * Set up for the direct block allocation
-        */
-       memset(&ar, 0, sizeof(ar));
-       ar.inode = inode;
-       ar.len = *blks;
-       ar.logical = iblock;
-       if (S_ISREG(inode->i_mode))
-               ar.flags = EXT4_MB_HINT_DATA;
-
        for (i = 0; i <= indirect_blks; i++) {
                if (i == indirect_blks) {
-                       ar.goal = goal;
-                       new_blocks[i] = ext4_mb_new_blocks(handle, &ar, &err);
+                       new_blocks[i] = ext4_mb_new_blocks(handle, ar, &err);
                } else
-                       goal = new_blocks[i] = ext4_new_meta_blocks(handle, inode,
-                                                       goal, 0, NULL, &err);
+                       ar->goal = new_blocks[i] = ext4_new_meta_blocks(handle,
+                                       ar->inode, ar->goal,
+                                       ar->flags & EXT4_MB_DELALLOC_RESERVED,
+                                       NULL, &err);
                if (err) {
                        i--;
                        goto failed;
@@ -354,7 +344,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
                if (i == 0)
                        continue;
 
-               bh = branch[i].bh = sb_getblk(inode->i_sb, new_blocks[i-1]);
+               bh = branch[i].bh = sb_getblk(ar->inode->i_sb, new_blocks[i-1]);
                if (unlikely(!bh)) {
                        err = -ENOMEM;
                        goto failed;
@@ -372,7 +362,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
                b = new_blocks[i];
 
                if (i == indirect_blks)
-                       len = ar.len;
+                       len = ar->len;
                for (j = 0; j < len; j++)
                        *p++ = cpu_to_le32(b++);
 
@@ -381,11 +371,10 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
                unlock_buffer(bh);
 
                BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
-               err = ext4_handle_dirty_metadata(handle, inode, bh);
+               err = ext4_handle_dirty_metadata(handle, ar->inode, bh);
                if (err)
                        goto failed;
        }
-       *blks = ar.len;
        return 0;
 failed:
        for (; i >= 0; i--) {
@@ -396,10 +385,10 @@ failed:
                 * existing before ext4_alloc_branch() was called.
                 */
                if (i > 0 && i != indirect_blks && branch[i].bh)
-                       ext4_forget(handle, 1, inode, branch[i].bh,
+                       ext4_forget(handle, 1, ar->inode, branch[i].bh,
                                    branch[i].bh->b_blocknr);
-               ext4_free_blocks(handle, inode, NULL, new_blocks[i],
-                                (i == indirect_blks) ? ar.len : 1, 0);
+               ext4_free_blocks(handle, ar->inode, NULL, new_blocks[i],
+                                (i == indirect_blks) ? ar->len : 1, 0);
        }
        return err;
 }
@@ -419,9 +408,9 @@ failed:
  * inode (->i_blocks, etc.). In case of success we end up with the full
  * chain to new block and return 0.
  */
-static int ext4_splice_branch(handle_t *handle, struct inode *inode,
-                             ext4_lblk_t block, Indirect *where, int num,
-                             int blks)
+static int ext4_splice_branch(handle_t *handle,
+                             struct ext4_allocation_request *ar,
+                             Indirect *where, int num)
 {
        int i;
        int err = 0;
@@ -446,9 +435,9 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
         * Update the host buffer_head or inode to point to more just allocated
         * direct blocks blocks
         */
-       if (num == 0 && blks > 1) {
+       if (num == 0 && ar->len > 1) {
                current_block = le32_to_cpu(where->key) + 1;
-               for (i = 1; i < blks; i++)
+               for (i = 1; i < ar->len; i++)
                        *(where->p + i) = cpu_to_le32(current_block++);
        }
 
@@ -465,14 +454,14 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
                 */
                jbd_debug(5, "splicing indirect only\n");
                BUFFER_TRACE(where->bh, "call ext4_handle_dirty_metadata");
-               err = ext4_handle_dirty_metadata(handle, inode, where->bh);
+               err = ext4_handle_dirty_metadata(handle, ar->inode, where->bh);
                if (err)
                        goto err_out;
        } else {
                /*
                 * OK, we spliced it into the inode itself on a direct block.
                 */
-               ext4_mark_inode_dirty(handle, inode);
+               ext4_mark_inode_dirty(handle, ar->inode);
                jbd_debug(5, "splicing direct\n");
        }
        return err;
@@ -484,11 +473,11 @@ err_out:
                 * need to revoke the block, which is why we don't
                 * need to set EXT4_FREE_BLOCKS_METADATA.
                 */
-               ext4_free_blocks(handle, inode, where[i].bh, 0, 1,
+               ext4_free_blocks(handle, ar->inode, where[i].bh, 0, 1,
                                 EXT4_FREE_BLOCKS_FORGET);
        }
-       ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key),
-                        blks, 0);
+       ext4_free_blocks(handle, ar->inode, NULL, le32_to_cpu(where[num].key),
+                        ar->len, 0);
 
        return err;
 }
@@ -525,11 +514,11 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
                        struct ext4_map_blocks *map,
                        int flags)
 {
+       struct ext4_allocation_request ar;
        int err = -EIO;
        ext4_lblk_t offsets[4];
        Indirect chain[4];
        Indirect *partial;
-       ext4_fsblk_t goal;
        int indirect_blks;
        int blocks_to_boundary = 0;
        int depth;
@@ -579,7 +568,16 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
                return -ENOSPC;
        }
 
-       goal = ext4_find_goal(inode, map->m_lblk, partial);
+       /* Set up for the direct block allocation */
+       memset(&ar, 0, sizeof(ar));
+       ar.inode = inode;
+       ar.logical = map->m_lblk;
+       if (S_ISREG(inode->i_mode))
+               ar.flags = EXT4_MB_HINT_DATA;
+       if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               ar.flags |= EXT4_MB_DELALLOC_RESERVED;
+
+       ar.goal = ext4_find_goal(inode, map->m_lblk, partial);
 
        /* the number of blocks need to allocate for [d,t]indirect blocks */
        indirect_blks = (chain + depth) - partial - 1;
@@ -588,13 +586,13 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
         * Next look up the indirect map to count the totoal number of
         * direct blocks to allocate for this branch.
         */
-       count = ext4_blks_to_allocate(partial, indirect_blks,
-                                     map->m_len, blocks_to_boundary);
+       ar.len = ext4_blks_to_allocate(partial, indirect_blks,
+                                      map->m_len, blocks_to_boundary);
+
        /*
         * Block out ext4_truncate while we alter the tree
         */
-       err = ext4_alloc_branch(handle, inode, map->m_lblk, indirect_blks,
-                               &count, goal,
+       err = ext4_alloc_branch(handle, &ar, indirect_blks,
                                offsets + (partial - chain), partial);
 
        /*
@@ -605,14 +603,14 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
         * may need to return -EAGAIN upwards in the worst case.  --sct
         */
        if (!err)
-               err = ext4_splice_branch(handle, inode, map->m_lblk,
-                                        partial, indirect_blks, count);
+               err = ext4_splice_branch(handle, &ar, partial, indirect_blks);
        if (err)
                goto cleanup;
 
        map->m_flags |= EXT4_MAP_NEW;
 
        ext4_update_inode_fsync_trans(handle, inode, 1);
+       count = ar.len;
 got_it:
        map->m_flags |= EXT4_MAP_MAPPED;
        map->m_pblk = le32_to_cpu(chain[depth-1].key);
index bea662bd0ca6b921b15c1bda0aab950a2fec2c78..3ea62695abce7b40e8d0e4969ad3fc1041358e4a 100644 (file)
@@ -594,6 +594,7 @@ retry:
        if (ret) {
                unlock_page(page);
                page_cache_release(page);
+               page = NULL;
                ext4_orphan_add(handle, inode);
                up_write(&EXT4_I(inode)->xattr_sem);
                sem_held = 0;
@@ -613,7 +614,8 @@ retry:
        if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
 
-       block_commit_write(page, from, to);
+       if (page)
+               block_commit_write(page, from, to);
 out:
        if (page) {
                unlock_page(page);
@@ -1126,8 +1128,7 @@ static int ext4_finish_convert_inline_dir(handle_t *handle,
        memcpy((void *)de, buf + EXT4_INLINE_DOTDOT_SIZE,
                inline_size - EXT4_INLINE_DOTDOT_SIZE);
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        inode->i_size = inode->i_sb->s_blocksize;
index 3aa26e9117c440b7145cd4196433cd1568a9b20b..3356ab5395f469c0db1eaa8da1cb79ed58277e93 100644 (file)
@@ -83,8 +83,7 @@ static int ext4_inode_csum_verify(struct inode *inode, struct ext4_inode *raw,
 
        if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
            cpu_to_le32(EXT4_OS_LINUX) ||
-           !EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+           !ext4_has_metadata_csum(inode->i_sb))
                return 1;
 
        provided = le16_to_cpu(raw->i_checksum_lo);
@@ -105,8 +104,7 @@ static void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw,
 
        if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
            cpu_to_le32(EXT4_OS_LINUX) ||
-           !EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+           !ext4_has_metadata_csum(inode->i_sb))
                return;
 
        csum = ext4_inode_csum(inode, raw, ei);
@@ -224,16 +222,15 @@ void ext4_evict_inode(struct inode *inode)
                goto no_delete;
        }
 
-       if (!is_bad_inode(inode))
-               dquot_initialize(inode);
+       if (is_bad_inode(inode))
+               goto no_delete;
+       dquot_initialize(inode);
 
        if (ext4_should_order_data(inode))
                ext4_begin_ordered_truncate(inode, 0);
        truncate_inode_pages_final(&inode->i_data);
 
        WARN_ON(atomic_read(&EXT4_I(inode)->i_ioend_count));
-       if (is_bad_inode(inode))
-               goto no_delete;
 
        /*
         * Protect us against freezing - iput() caller didn't have to have any
@@ -590,19 +587,11 @@ found:
        /*
         * New blocks allocate and/or writing to unwritten extent
         * will possibly result in updating i_data, so we take
-        * the write lock of i_data_sem, and call get_blocks()
+        * the write lock of i_data_sem, and call get_block()
         * with create == 1 flag.
         */
        down_write(&EXT4_I(inode)->i_data_sem);
 
-       /*
-        * if the caller is from delayed allocation writeout path
-        * we have already reserved fs blocks for allocation
-        * let the underlying get_block() function know to
-        * avoid double accounting
-        */
-       if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
-               ext4_set_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
        /*
         * We need to check for EXT4 here because migrate
         * could have changed the inode type in between
@@ -631,8 +620,6 @@ found:
                        (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE))
                        ext4_da_update_reserve_space(inode, retval, 1);
        }
-       if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
-               ext4_clear_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED);
 
        if (retval > 0) {
                unsigned int status;
@@ -734,11 +721,11 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
  * `handle' can be NULL if create is zero
  */
 struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
-                               ext4_lblk_t block, int create, int *errp)
+                               ext4_lblk_t block, int create)
 {
        struct ext4_map_blocks map;
        struct buffer_head *bh;
-       int fatal = 0, err;
+       int err;
 
        J_ASSERT(handle != NULL || create == 0);
 
@@ -747,21 +734,14 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
        err = ext4_map_blocks(handle, inode, &map,
                              create ? EXT4_GET_BLOCKS_CREATE : 0);
 
-       /* ensure we send some value back into *errp */
-       *errp = 0;
-
-       if (create && err == 0)
-               err = -ENOSPC;  /* should never happen */
+       if (err == 0)
+               return create ? ERR_PTR(-ENOSPC) : NULL;
        if (err < 0)
-               *errp = err;
-       if (err <= 0)
-               return NULL;
+               return ERR_PTR(err);
 
        bh = sb_getblk(inode->i_sb, map.m_pblk);
-       if (unlikely(!bh)) {
-               *errp = -ENOMEM;
-               return NULL;
-       }
+       if (unlikely(!bh))
+               return ERR_PTR(-ENOMEM);
        if (map.m_flags & EXT4_MAP_NEW) {
                J_ASSERT(create != 0);
                J_ASSERT(handle != NULL);
@@ -775,44 +755,44 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode,
                 */
                lock_buffer(bh);
                BUFFER_TRACE(bh, "call get_create_access");
-               fatal = ext4_journal_get_create_access(handle, bh);
-               if (!fatal && !buffer_uptodate(bh)) {
+               err = ext4_journal_get_create_access(handle, bh);
+               if (unlikely(err)) {
+                       unlock_buffer(bh);
+                       goto errout;
+               }
+               if (!buffer_uptodate(bh)) {
                        memset(bh->b_data, 0, inode->i_sb->s_blocksize);
                        set_buffer_uptodate(bh);
                }
                unlock_buffer(bh);
                BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
                err = ext4_handle_dirty_metadata(handle, inode, bh);
-               if (!fatal)
-                       fatal = err;
-       } else {
+               if (unlikely(err))
+                       goto errout;
+       } else
                BUFFER_TRACE(bh, "not a new buffer");
-       }
-       if (fatal) {
-               *errp = fatal;
-               brelse(bh);
-               bh = NULL;
-       }
        return bh;
+errout:
+       brelse(bh);
+       return ERR_PTR(err);
 }
 
 struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
-                              ext4_lblk_t block, int create, int *err)
+                              ext4_lblk_t block, int create)
 {
        struct buffer_head *bh;
 
-       bh = ext4_getblk(handle, inode, block, create, err);
-       if (!bh)
+       bh = ext4_getblk(handle, inode, block, create);
+       if (IS_ERR(bh))
                return bh;
-       if (buffer_uptodate(bh))
+       if (!bh || buffer_uptodate(bh))
                return bh;
        ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);
        wait_on_buffer(bh);
        if (buffer_uptodate(bh))
                return bh;
        put_bh(bh);
-       *err = -EIO;
-       return NULL;
+       return ERR_PTR(-EIO);
 }
 
 int ext4_walk_page_buffers(handle_t *handle,
@@ -1536,7 +1516,7 @@ out_unlock:
 }
 
 /*
- * This is a special get_blocks_t callback which is used by
+ * This is a special get_block_t callback which is used by
  * ext4_da_write_begin().  It will either return mapped block or
  * reserve space for a single block.
  *
@@ -2011,12 +1991,10 @@ static int mpage_map_one_extent(handle_t *handle, struct mpage_da_data *mpd)
         * in data loss.  So use reserved blocks to allocate metadata if
         * possible.
         *
-        * We pass in the magic EXT4_GET_BLOCKS_DELALLOC_RESERVE if the blocks
-        * in question are delalloc blocks.  This affects functions in many
-        * different parts of the allocation call path.  This flag exists
-        * primarily because we don't want to change *many* call functions, so
-        * ext4_map_blocks() will set the EXT4_STATE_DELALLOC_RESERVED flag
-        * once the inode's allocation semaphore is taken.
+        * We pass in the magic EXT4_GET_BLOCKS_DELALLOC_RESERVE if
+        * the blocks in question are delalloc blocks.  This indicates
+        * that the blocks and quotas has already been checked when
+        * the data was copied into the page cache.
         */
        get_blocks_flags = EXT4_GET_BLOCKS_CREATE |
                           EXT4_GET_BLOCKS_METADATA_NOFAIL;
@@ -2515,6 +2493,20 @@ static int ext4_nonda_switch(struct super_block *sb)
        return 0;
 }
 
+/* We always reserve for an inode update; the superblock could be there too */
+static int ext4_da_write_credits(struct inode *inode, loff_t pos, unsigned len)
+{
+       if (likely(EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
+                               EXT4_FEATURE_RO_COMPAT_LARGE_FILE)))
+               return 1;
+
+       if (pos + len <= 0x7fffffffULL)
+               return 1;
+
+       /* We might need to update the superblock to set LARGE_FILE */
+       return 2;
+}
+
 static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
                               loff_t pos, unsigned len, unsigned flags,
                               struct page **pagep, void **fsdata)
@@ -2565,7 +2557,8 @@ retry_grab:
         * of file which has an already mapped buffer.
         */
 retry_journal:
-       handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, 1);
+       handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE,
+                               ext4_da_write_credits(inode, pos, len));
        if (IS_ERR(handle)) {
                page_cache_release(page);
                return PTR_ERR(handle);
@@ -2658,10 +2651,7 @@ static int ext4_da_write_end(struct file *file,
        if (copied && new_i_size > EXT4_I(inode)->i_disksize) {
                if (ext4_has_inline_data(inode) ||
                    ext4_da_should_update_i_disksize(page, end)) {
-                       down_write(&EXT4_I(inode)->i_data_sem);
-                       if (new_i_size > EXT4_I(inode)->i_disksize)
-                               EXT4_I(inode)->i_disksize = new_i_size;
-                       up_write(&EXT4_I(inode)->i_data_sem);
+                       ext4_update_i_disksize(inode, new_i_size);
                        /* We need to mark inode dirty even if
                         * new_i_size is less that inode->i_size
                         * bu greater than i_disksize.(hint delalloc)
@@ -3936,8 +3926,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                ei->i_extra_isize = 0;
 
        /* Precompute checksum seed for inode metadata */
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+       if (ext4_has_metadata_csum(sb)) {
                struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
                __u32 csum;
                __le32 inum = cpu_to_le32(inode->i_ino);
@@ -4127,6 +4116,13 @@ bad_inode:
        return ERR_PTR(ret);
 }
 
+struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino)
+{
+       if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
+               return ERR_PTR(-EIO);
+       return ext4_iget(sb, ino);
+}
+
 static int ext4_inode_blocks_set(handle_t *handle,
                                struct ext4_inode *raw_inode,
                                struct ext4_inode_info *ei)
@@ -4226,7 +4222,8 @@ static int ext4_do_update_inode(handle_t *handle,
        EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode);
        EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode);
 
-       if (ext4_inode_blocks_set(handle, raw_inode, ei)) {
+       err = ext4_inode_blocks_set(handle, raw_inode, ei);
+       if (err) {
                spin_unlock(&ei->i_raw_lock);
                goto out_brelse;
        }
@@ -4536,8 +4533,12 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
                                ext4_orphan_del(NULL, inode);
                                goto err_out;
                        }
-               } else
+               } else {
+                       loff_t oldsize = inode->i_size;
+
                        i_size_write(inode, attr->ia_size);
+                       pagecache_isize_extended(inode, oldsize, inode->i_size);
+               }
 
                /*
                 * Blocks are going to be removed from the inode. Wait
@@ -4958,7 +4959,12 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
        if (val)
                ext4_set_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
        else {
-               jbd2_journal_flush(journal);
+               err = jbd2_journal_flush(journal);
+               if (err < 0) {
+                       jbd2_journal_unlock_updates(journal);
+                       ext4_inode_resume_unlocked_dio(inode);
+                       return err;
+               }
                ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
        }
        ext4_set_aops(inode);
index 0f2252ec274d6c3bd0fc47a45a902ad043cd3ddf..bfda18a155922c1224cf12e6630d75c692c38d8f 100644 (file)
@@ -331,8 +331,7 @@ flags_out:
                if (!inode_owner_or_capable(inode))
                        return -EPERM;
 
-               if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+               if (ext4_has_metadata_csum(inode->i_sb)) {
                        ext4_warning(sb, "Setting inode version is not "
                                     "supported with metadata_csum enabled.");
                        return -ENOTTY;
@@ -532,9 +531,17 @@ group_add_out:
        }
 
        case EXT4_IOC_SWAP_BOOT:
+       {
+               int err;
                if (!(filp->f_mode & FMODE_WRITE))
                        return -EBADF;
-               return swap_inode_boot_loader(sb, inode);
+               err = mnt_want_write_file(filp);
+               if (err)
+                       return err;
+               err = swap_inode_boot_loader(sb, inode);
+               mnt_drop_write_file(filp);
+               return err;
+       }
 
        case EXT4_IOC_RESIZE_FS: {
                ext4_fsblk_t n_blocks_count;
index 748c9136a60a4e5fba2967fac108d298abf110ea..dbfe15c2533c93a299a484afb1ce32a7ca9a57f1 100644 (file)
@@ -3155,9 +3155,8 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
                         "start %lu, size %lu, fe_logical %lu",
                         (unsigned long) start, (unsigned long) size,
                         (unsigned long) ac->ac_o_ex.fe_logical);
+               BUG();
        }
-       BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
-                       start > ac->ac_o_ex.fe_logical);
        BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
 
        /* now prepare goal request */
@@ -4410,14 +4409,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
        if (IS_NOQUOTA(ar->inode))
                ar->flags |= EXT4_MB_USE_ROOT_BLOCKS;
 
-       /*
-        * For delayed allocation, we could skip the ENOSPC and
-        * EDQUOT check, as blocks and quotas have been already
-        * reserved when data being copied into pagecache.
-        */
-       if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED))
-               ar->flags |= EXT4_MB_DELALLOC_RESERVED;
-       else {
+       if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0) {
                /* Without delayed allocation we need to verify
                 * there is enough free blocks to do block allocation
                 * and verify allocation doesn't exceed the quota limits.
@@ -4528,8 +4520,7 @@ out:
        if (inquota && ar->len < inquota)
                dquot_free_block(ar->inode, EXT4_C2B(sbi, inquota - ar->len));
        if (!ar->len) {
-               if (!ext4_test_inode_state(ar->inode,
-                                          EXT4_STATE_DELALLOC_RESERVED))
+               if ((ar->flags & EXT4_MB_DELALLOC_RESERVED) == 0)
                        /* release all the reserved blocks if non delalloc */
                        percpu_counter_sub(&sbi->s_dirtyclusters_counter,
                                                reserv_clstrs);
index d3567f27bae7071931bcc4b06470caf69d123d7b..a432634f2e6a7243d4e5f3beaa088b6911281a0d 100644 (file)
@@ -41,8 +41,7 @@ static int finish_range(handle_t *handle, struct inode *inode,
        ext4_ext_store_pblock(&newext, lb->first_pblock);
        /* Locking only for convinience since we are operating on temp inode */
        down_write(&EXT4_I(inode)->i_data_sem);
-       path = ext4_ext_find_extent(inode, lb->first_block, NULL, 0);
-
+       path = ext4_find_extent(inode, lb->first_block, NULL, 0);
        if (IS_ERR(path)) {
                retval = PTR_ERR(path);
                path = NULL;
@@ -81,13 +80,11 @@ static int finish_range(handle_t *handle, struct inode *inode,
                                goto err_out;
                }
        }
-       retval = ext4_ext_insert_extent(handle, inode, path, &newext, 0);
+       retval = ext4_ext_insert_extent(handle, inode, &path, &newext, 0);
 err_out:
        up_write((&EXT4_I(inode)->i_data_sem));
-       if (path) {
-               ext4_ext_drop_refs(path);
-               kfree(path);
-       }
+       ext4_ext_drop_refs(path);
+       kfree(path);
        lb->first_pblock = 0;
        return retval;
 }
index 32bce844c2e13ce8147ec1977bb51838b040f7fb..8313ca3324ec96a1c3413d0041817a5f1726e4f4 100644 (file)
@@ -20,8 +20,7 @@ static __le32 ext4_mmp_csum(struct super_block *sb, struct mmp_struct *mmp)
 
 static int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp)
 {
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return 1;
 
        return mmp->mmp_checksum == ext4_mmp_csum(sb, mmp);
@@ -29,8 +28,7 @@ static int ext4_mmp_csum_verify(struct super_block *sb, struct mmp_struct *mmp)
 
 static void ext4_mmp_csum_set(struct super_block *sb, struct mmp_struct *mmp)
 {
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return;
 
        mmp->mmp_checksum = ext4_mmp_csum(sb, mmp);
index 671a74b14fd768ef6515811500a37269bad680b8..9f2311bc9c4f3b5fbf2d839a7491da49c174cd4c 100644 (file)
  * @lblock:    logical block number to find an extent path
  * @path:      pointer to an extent path pointer (for output)
  *
- * ext4_ext_find_extent wrapper. Return 0 on success, or a negative error value
+ * ext4_find_extent wrapper. Return 0 on success, or a negative error value
  * on failure.
  */
 static inline int
 get_ext_path(struct inode *inode, ext4_lblk_t lblock,
-               struct ext4_ext_path **orig_path)
+               struct ext4_ext_path **ppath)
 {
-       int ret = 0;
        struct ext4_ext_path *path;
 
-       path = ext4_ext_find_extent(inode, lblock, *orig_path, EXT4_EX_NOCACHE);
+       path = ext4_find_extent(inode, lblock, ppath, EXT4_EX_NOCACHE);
        if (IS_ERR(path))
-               ret = PTR_ERR(path);
-       else if (path[ext_depth(inode)].p_ext == NULL)
-               ret = -ENODATA;
-       else
-               *orig_path = path;
-
-       return ret;
-}
-
-/**
- * copy_extent_status - Copy the extent's initialization status
- *
- * @src:       an extent for getting initialize status
- * @dest:      an extent to be set the status
- */
-static void
-copy_extent_status(struct ext4_extent *src, struct ext4_extent *dest)
-{
-       if (ext4_ext_is_unwritten(src))
-               ext4_ext_mark_unwritten(dest);
-       else
-               dest->ee_len = cpu_to_le16(ext4_ext_get_actual_len(dest));
-}
-
-/**
- * mext_next_extent - Search for the next extent and set it to "extent"
- *
- * @inode:     inode which is searched
- * @path:      this will obtain data for the next extent
- * @extent:    pointer to the next extent we have just gotten
- *
- * Search the next extent in the array of ext4_ext_path structure (@path)
- * and set it to ext4_extent structure (@extent). In addition, the member of
- * @path (->p_ext) also points the next extent. Return 0 on success, 1 if
- * ext4_ext_path structure refers to the last extent, or a negative error
- * value on failure.
- */
-int
-mext_next_extent(struct inode *inode, struct ext4_ext_path *path,
-                     struct ext4_extent **extent)
-{
-       struct ext4_extent_header *eh;
-       int ppos, leaf_ppos = path->p_depth;
-
-       ppos = leaf_ppos;
-       if (EXT_LAST_EXTENT(path[ppos].p_hdr) > path[ppos].p_ext) {
-               /* leaf block */
-               *extent = ++path[ppos].p_ext;
-               path[ppos].p_block = ext4_ext_pblock(path[ppos].p_ext);
-               return 0;
-       }
-
-       while (--ppos >= 0) {
-               if (EXT_LAST_INDEX(path[ppos].p_hdr) >
-                   path[ppos].p_idx) {
-                       int cur_ppos = ppos;
-
-                       /* index block */
-                       path[ppos].p_idx++;
-                       path[ppos].p_block = ext4_idx_pblock(path[ppos].p_idx);
-                       if (path[ppos+1].p_bh)
-                               brelse(path[ppos+1].p_bh);
-                       path[ppos+1].p_bh =
-                               sb_bread(inode->i_sb, path[ppos].p_block);
-                       if (!path[ppos+1].p_bh)
-                               return -EIO;
-                       path[ppos+1].p_hdr =
-                               ext_block_hdr(path[ppos+1].p_bh);
-
-                       /* Halfway index block */
-                       while (++cur_ppos < leaf_ppos) {
-                               path[cur_ppos].p_idx =
-                                       EXT_FIRST_INDEX(path[cur_ppos].p_hdr);
-                               path[cur_ppos].p_block =
-                                       ext4_idx_pblock(path[cur_ppos].p_idx);
-                               if (path[cur_ppos+1].p_bh)
-                                       brelse(path[cur_ppos+1].p_bh);
-                               path[cur_ppos+1].p_bh = sb_bread(inode->i_sb,
-                                       path[cur_ppos].p_block);
-                               if (!path[cur_ppos+1].p_bh)
-                                       return -EIO;
-                               path[cur_ppos+1].p_hdr =
-                                       ext_block_hdr(path[cur_ppos+1].p_bh);
-                       }
-
-                       path[leaf_ppos].p_ext = *extent = NULL;
-
-                       eh = path[leaf_ppos].p_hdr;
-                       if (le16_to_cpu(eh->eh_entries) == 0)
-                               /* empty leaf is found */
-                               return -ENODATA;
-
-                       /* leaf block */
-                       path[leaf_ppos].p_ext = *extent =
-                               EXT_FIRST_EXTENT(path[leaf_ppos].p_hdr);
-                       path[leaf_ppos].p_block =
-                                       ext4_ext_pblock(path[leaf_ppos].p_ext);
-                       return 0;
-               }
+               return PTR_ERR(path);
+       if (path[ext_depth(inode)].p_ext == NULL) {
+               ext4_ext_drop_refs(path);
+               kfree(path);
+               *ppath = NULL;
+               return -ENODATA;
        }
-       /* We found the last extent */
-       return 1;
+       *ppath = path;
+       return 0;
 }
 
 /**
@@ -177,417 +83,6 @@ ext4_double_up_write_data_sem(struct inode *orig_inode,
        up_write(&EXT4_I(donor_inode)->i_data_sem);
 }
 
-/**
- * mext_insert_across_blocks - Insert extents across leaf block
- *
- * @handle:            journal handle
- * @orig_inode:                original inode
- * @o_start:           first original extent to be changed
- * @o_end:             last original extent to be changed
- * @start_ext:         first new extent to be inserted
- * @new_ext:           middle of new extent to be inserted
- * @end_ext:           last new extent to be inserted
- *
- * Allocate a new leaf block and insert extents into it. Return 0 on success,
- * or a negative error value on failure.
- */
-static int
-mext_insert_across_blocks(handle_t *handle, struct inode *orig_inode,
-               struct ext4_extent *o_start, struct ext4_extent *o_end,
-               struct ext4_extent *start_ext, struct ext4_extent *new_ext,
-               struct ext4_extent *end_ext)
-{
-       struct ext4_ext_path *orig_path = NULL;
-       ext4_lblk_t eblock = 0;
-       int new_flag = 0;
-       int end_flag = 0;
-       int err = 0;
-
-       if (start_ext->ee_len && new_ext->ee_len && end_ext->ee_len) {
-               if (o_start == o_end) {
-
-                       /*       start_ext   new_ext    end_ext
-                        * donor |---------|-----------|--------|
-                        * orig  |------------------------------|
-                        */
-                       end_flag = 1;
-               } else {
-
-                       /*       start_ext   new_ext   end_ext
-                        * donor |---------|----------|---------|
-                        * orig  |---------------|--------------|
-                        */
-                       o_end->ee_block = end_ext->ee_block;
-                       o_end->ee_len = end_ext->ee_len;
-                       ext4_ext_store_pblock(o_end, ext4_ext_pblock(end_ext));
-               }
-
-               o_start->ee_len = start_ext->ee_len;
-               eblock = le32_to_cpu(start_ext->ee_block);
-               new_flag = 1;
-
-       } else if (start_ext->ee_len && new_ext->ee_len &&
-                  !end_ext->ee_len && o_start == o_end) {
-
-               /*       start_ext      new_ext
-                * donor |--------------|---------------|
-                * orig  |------------------------------|
-                */
-               o_start->ee_len = start_ext->ee_len;
-               eblock = le32_to_cpu(start_ext->ee_block);
-               new_flag = 1;
-
-       } else if (!start_ext->ee_len && new_ext->ee_len &&
-                  end_ext->ee_len && o_start == o_end) {
-
-               /*        new_ext       end_ext
-                * donor |--------------|---------------|
-                * orig  |------------------------------|
-                */
-               o_end->ee_block = end_ext->ee_block;
-               o_end->ee_len = end_ext->ee_len;
-               ext4_ext_store_pblock(o_end, ext4_ext_pblock(end_ext));
-
-               /*
-                * Set 0 to the extent block if new_ext was
-                * the first block.
-                */
-               if (new_ext->ee_block)
-                       eblock = le32_to_cpu(new_ext->ee_block);
-
-               new_flag = 1;
-       } else {
-               ext4_debug("ext4 move extent: Unexpected insert case\n");
-               return -EIO;
-       }
-
-       if (new_flag) {
-               err = get_ext_path(orig_inode, eblock, &orig_path);
-               if (err)
-                       goto out;
-
-               if (ext4_ext_insert_extent(handle, orig_inode,
-                                       orig_path, new_ext, 0))
-                       goto out;
-       }
-
-       if (end_flag) {
-               err = get_ext_path(orig_inode,
-                               le32_to_cpu(end_ext->ee_block) - 1, &orig_path);
-               if (err)
-                       goto out;
-
-               if (ext4_ext_insert_extent(handle, orig_inode,
-                                          orig_path, end_ext, 0))
-                       goto out;
-       }
-out:
-       if (orig_path) {
-               ext4_ext_drop_refs(orig_path);
-               kfree(orig_path);
-       }
-
-       return err;
-
-}
-
-/**
- * mext_insert_inside_block - Insert new extent to the extent block
- *
- * @o_start:           first original extent to be moved
- * @o_end:             last original extent to be moved
- * @start_ext:         first new extent to be inserted
- * @new_ext:           middle of new extent to be inserted
- * @end_ext:           last new extent to be inserted
- * @eh:                        extent header of target leaf block
- * @range_to_move:     used to decide how to insert extent
- *
- * Insert extents into the leaf block. The extent (@o_start) is overwritten
- * by inserted extents.
- */
-static void
-mext_insert_inside_block(struct ext4_extent *o_start,
-                             struct ext4_extent *o_end,
-                             struct ext4_extent *start_ext,
-                             struct ext4_extent *new_ext,
-                             struct ext4_extent *end_ext,
-                             struct ext4_extent_header *eh,
-                             int range_to_move)
-{
-       int i = 0;
-       unsigned long len;
-
-       /* Move the existing extents */
-       if (range_to_move && o_end < EXT_LAST_EXTENT(eh)) {
-               len = (unsigned long)(EXT_LAST_EXTENT(eh) + 1) -
-                       (unsigned long)(o_end + 1);
-               memmove(o_end + 1 + range_to_move, o_end + 1, len);
-       }
-
-       /* Insert start entry */
-       if (start_ext->ee_len)
-               o_start[i++].ee_len = start_ext->ee_len;
-
-       /* Insert new entry */
-       if (new_ext->ee_len) {
-               o_start[i] = *new_ext;
-               ext4_ext_store_pblock(&o_start[i++], ext4_ext_pblock(new_ext));
-       }
-
-       /* Insert end entry */
-       if (end_ext->ee_len)
-               o_start[i] = *end_ext;
-
-       /* Increment the total entries counter on the extent block */
-       le16_add_cpu(&eh->eh_entries, range_to_move);
-}
-
-/**
- * mext_insert_extents - Insert new extent
- *
- * @handle:    journal handle
- * @orig_inode:        original inode
- * @orig_path: path indicates first extent to be changed
- * @o_start:   first original extent to be changed
- * @o_end:     last original extent to be changed
- * @start_ext: first new extent to be inserted
- * @new_ext:   middle of new extent to be inserted
- * @end_ext:   last new extent to be inserted
- *
- * Call the function to insert extents. If we cannot add more extents into
- * the leaf block, we call mext_insert_across_blocks() to create a
- * new leaf block. Otherwise call mext_insert_inside_block(). Return 0
- * on success, or a negative error value on failure.
- */
-static int
-mext_insert_extents(handle_t *handle, struct inode *orig_inode,
-                        struct ext4_ext_path *orig_path,
-                        struct ext4_extent *o_start,
-                        struct ext4_extent *o_end,
-                        struct ext4_extent *start_ext,
-                        struct ext4_extent *new_ext,
-                        struct ext4_extent *end_ext)
-{
-       struct  ext4_extent_header *eh;
-       unsigned long need_slots, slots_range;
-       int     range_to_move, depth, ret;
-
-       /*
-        * The extents need to be inserted
-        * start_extent + new_extent + end_extent.
-        */
-       need_slots = (start_ext->ee_len ? 1 : 0) + (end_ext->ee_len ? 1 : 0) +
-               (new_ext->ee_len ? 1 : 0);
-
-       /* The number of slots between start and end */
-       slots_range = ((unsigned long)(o_end + 1) - (unsigned long)o_start + 1)
-               / sizeof(struct ext4_extent);
-
-       /* Range to move the end of extent */
-       range_to_move = need_slots - slots_range;
-       depth = orig_path->p_depth;
-       orig_path += depth;
-       eh = orig_path->p_hdr;
-
-       if (depth) {
-               /* Register to journal */
-               BUFFER_TRACE(orig_path->p_bh, "get_write_access");
-               ret = ext4_journal_get_write_access(handle, orig_path->p_bh);
-               if (ret)
-                       return ret;
-       }
-
-       /* Expansion */
-       if (range_to_move > 0 &&
-               (range_to_move > le16_to_cpu(eh->eh_max)
-                       - le16_to_cpu(eh->eh_entries))) {
-
-               ret = mext_insert_across_blocks(handle, orig_inode, o_start,
-                                       o_end, start_ext, new_ext, end_ext);
-               if (ret < 0)
-                       return ret;
-       } else
-               mext_insert_inside_block(o_start, o_end, start_ext, new_ext,
-                                               end_ext, eh, range_to_move);
-
-       return ext4_ext_dirty(handle, orig_inode, orig_path);
-}
-
-/**
- * mext_leaf_block - Move one leaf extent block into the inode.
- *
- * @handle:            journal handle
- * @orig_inode:                original inode
- * @orig_path:         path indicates first extent to be changed
- * @dext:              donor extent
- * @from:              start offset on the target file
- *
- * In order to insert extents into the leaf block, we must divide the extent
- * in the leaf block into three extents. The one is located to be inserted
- * extents, and the others are located around it.
- *
- * Therefore, this function creates structures to save extents of the leaf
- * block, and inserts extents by calling mext_insert_extents() with
- * created extents. Return 0 on success, or a negative error value on failure.
- */
-static int
-mext_leaf_block(handle_t *handle, struct inode *orig_inode,
-                    struct ext4_ext_path *orig_path, struct ext4_extent *dext,
-                    ext4_lblk_t *from)
-{
-       struct ext4_extent *oext, *o_start, *o_end, *prev_ext;
-       struct ext4_extent new_ext, start_ext, end_ext;
-       ext4_lblk_t new_ext_end;
-       int oext_alen, new_ext_alen, end_ext_alen;
-       int depth = ext_depth(orig_inode);
-       int ret;
-
-       start_ext.ee_block = end_ext.ee_block = 0;
-       o_start = o_end = oext = orig_path[depth].p_ext;
-       oext_alen = ext4_ext_get_actual_len(oext);
-       start_ext.ee_len = end_ext.ee_len = 0;
-
-       new_ext.ee_block = cpu_to_le32(*from);
-       ext4_ext_store_pblock(&new_ext, ext4_ext_pblock(dext));
-       new_ext.ee_len = dext->ee_len;
-       new_ext_alen = ext4_ext_get_actual_len(&new_ext);
-       new_ext_end = le32_to_cpu(new_ext.ee_block) + new_ext_alen - 1;
-
-       /*
-        * Case: original extent is first
-        * oext      |--------|
-        * new_ext      |--|
-        * start_ext |--|
-        */
-       if (le32_to_cpu(oext->ee_block) < le32_to_cpu(new_ext.ee_block) &&
-               le32_to_cpu(new_ext.ee_block) <
-               le32_to_cpu(oext->ee_block) + oext_alen) {
-               start_ext.ee_len = cpu_to_le16(le32_to_cpu(new_ext.ee_block) -
-                                              le32_to_cpu(oext->ee_block));
-               start_ext.ee_block = oext->ee_block;
-               copy_extent_status(oext, &start_ext);
-       } else if (oext > EXT_FIRST_EXTENT(orig_path[depth].p_hdr)) {
-               prev_ext = oext - 1;
-               /*
-                * We can merge new_ext into previous extent,
-                * if these are contiguous and same extent type.
-                */
-               if (ext4_can_extents_be_merged(orig_inode, prev_ext,
-                                              &new_ext)) {
-                       o_start = prev_ext;
-                       start_ext.ee_len = cpu_to_le16(
-                               ext4_ext_get_actual_len(prev_ext) +
-                               new_ext_alen);
-                       start_ext.ee_block = oext->ee_block;
-                       copy_extent_status(prev_ext, &start_ext);
-                       new_ext.ee_len = 0;
-               }
-       }
-
-       /*
-        * Case: new_ext_end must be less than oext
-        * oext      |-----------|
-        * new_ext       |-------|
-        */
-       if (le32_to_cpu(oext->ee_block) + oext_alen - 1 < new_ext_end) {
-               EXT4_ERROR_INODE(orig_inode,
-                       "new_ext_end(%u) should be less than or equal to "
-                       "oext->ee_block(%u) + oext_alen(%d) - 1",
-                       new_ext_end, le32_to_cpu(oext->ee_block),
-                       oext_alen);
-               ret = -EIO;
-               goto out;
-       }
-
-       /*
-        * Case: new_ext is smaller than original extent
-        * oext    |---------------|
-        * new_ext |-----------|
-        * end_ext             |---|
-        */
-       if (le32_to_cpu(oext->ee_block) <= new_ext_end &&
-               new_ext_end < le32_to_cpu(oext->ee_block) + oext_alen - 1) {
-               end_ext.ee_len =
-                       cpu_to_le16(le32_to_cpu(oext->ee_block) +
-                       oext_alen - 1 - new_ext_end);
-               copy_extent_status(oext, &end_ext);
-               end_ext_alen = ext4_ext_get_actual_len(&end_ext);
-               ext4_ext_store_pblock(&end_ext,
-                       (ext4_ext_pblock(o_end) + oext_alen - end_ext_alen));
-               end_ext.ee_block =
-                       cpu_to_le32(le32_to_cpu(o_end->ee_block) +
-                       oext_alen - end_ext_alen);
-       }
-
-       ret = mext_insert_extents(handle, orig_inode, orig_path, o_start,
-                               o_end, &start_ext, &new_ext, &end_ext);
-out:
-       return ret;
-}
-
-/**
- * mext_calc_swap_extents - Calculate extents for extent swapping.
- *
- * @tmp_dext:          the extent that will belong to the original inode
- * @tmp_oext:          the extent that will belong to the donor inode
- * @orig_off:          block offset of original inode
- * @donor_off:         block offset of donor inode
- * @max_count:         the maximum length of extents
- *
- * Return 0 on success, or a negative error value on failure.
- */
-static int
-mext_calc_swap_extents(struct ext4_extent *tmp_dext,
-                             struct ext4_extent *tmp_oext,
-                             ext4_lblk_t orig_off, ext4_lblk_t donor_off,
-                             ext4_lblk_t max_count)
-{
-       ext4_lblk_t diff, orig_diff;
-       struct ext4_extent dext_old, oext_old;
-
-       BUG_ON(orig_off != donor_off);
-
-       /* original and donor extents have to cover the same block offset */
-       if (orig_off < le32_to_cpu(tmp_oext->ee_block) ||
-           le32_to_cpu(tmp_oext->ee_block) +
-                       ext4_ext_get_actual_len(tmp_oext) - 1 < orig_off)
-               return -ENODATA;
-
-       if (orig_off < le32_to_cpu(tmp_dext->ee_block) ||
-           le32_to_cpu(tmp_dext->ee_block) +
-                       ext4_ext_get_actual_len(tmp_dext) - 1 < orig_off)
-               return -ENODATA;
-
-       dext_old = *tmp_dext;
-       oext_old = *tmp_oext;
-
-       /* When tmp_dext is too large, pick up the target range. */
-       diff = donor_off - le32_to_cpu(tmp_dext->ee_block);
-
-       ext4_ext_store_pblock(tmp_dext, ext4_ext_pblock(tmp_dext) + diff);
-       le32_add_cpu(&tmp_dext->ee_block, diff);
-       le16_add_cpu(&tmp_dext->ee_len, -diff);
-
-       if (max_count < ext4_ext_get_actual_len(tmp_dext))
-               tmp_dext->ee_len = cpu_to_le16(max_count);
-
-       orig_diff = orig_off - le32_to_cpu(tmp_oext->ee_block);
-       ext4_ext_store_pblock(tmp_oext, ext4_ext_pblock(tmp_oext) + orig_diff);
-
-       /* Adjust extent length if donor extent is larger than orig */
-       if (ext4_ext_get_actual_len(tmp_dext) >
-           ext4_ext_get_actual_len(tmp_oext) - orig_diff)
-               tmp_dext->ee_len = cpu_to_le16(le16_to_cpu(tmp_oext->ee_len) -
-                                               orig_diff);
-
-       tmp_oext->ee_len = cpu_to_le16(ext4_ext_get_actual_len(tmp_dext));
-
-       copy_extent_status(&oext_old, tmp_dext);
-       copy_extent_status(&dext_old, tmp_oext);
-
-       return 0;
-}
-
 /**
  * mext_check_coverage - Check that all extents in range has the same type
  *
@@ -619,171 +114,25 @@ mext_check_coverage(struct inode *inode, ext4_lblk_t from, ext4_lblk_t count,
        }
        ret = 1;
 out:
-       if (path) {
-               ext4_ext_drop_refs(path);
-               kfree(path);
-       }
+       ext4_ext_drop_refs(path);
+       kfree(path);
        return ret;
 }
 
-/**
- * mext_replace_branches - Replace original extents with new extents
- *
- * @handle:            journal handle
- * @orig_inode:                original inode
- * @donor_inode:       donor inode
- * @from:              block offset of orig_inode
- * @count:             block count to be replaced
- * @err:               pointer to save return value
- *
- * Replace original inode extents and donor inode extents page by page.
- * We implement this replacement in the following three steps:
- * 1. Save the block information of original and donor inodes into
- *    dummy extents.
- * 2. Change the block information of original inode to point at the
- *    donor inode blocks.
- * 3. Change the block information of donor inode to point at the saved
- *    original inode blocks in the dummy extents.
- *
- * Return replaced block count.
- */
-static int
-mext_replace_branches(handle_t *handle, struct inode *orig_inode,
-                          struct inode *donor_inode, ext4_lblk_t from,
-                          ext4_lblk_t count, int *err)
-{
-       struct ext4_ext_path *orig_path = NULL;
-       struct ext4_ext_path *donor_path = NULL;
-       struct ext4_extent *oext, *dext;
-       struct ext4_extent tmp_dext, tmp_oext;
-       ext4_lblk_t orig_off = from, donor_off = from;
-       int depth;
-       int replaced_count = 0;
-       int dext_alen;
-
-       *err = ext4_es_remove_extent(orig_inode, from, count);
-       if (*err)
-               goto out;
-
-       *err = ext4_es_remove_extent(donor_inode, from, count);
-       if (*err)
-               goto out;
-
-       /* Get the original extent for the block "orig_off" */
-       *err = get_ext_path(orig_inode, orig_off, &orig_path);
-       if (*err)
-               goto out;
-
-       /* Get the donor extent for the head */
-       *err = get_ext_path(donor_inode, donor_off, &donor_path);
-       if (*err)
-               goto out;
-       depth = ext_depth(orig_inode);
-       oext = orig_path[depth].p_ext;
-       tmp_oext = *oext;
-
-       depth = ext_depth(donor_inode);
-       dext = donor_path[depth].p_ext;
-       if (unlikely(!dext))
-               goto missing_donor_extent;
-       tmp_dext = *dext;
-
-       *err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off,
-                                     donor_off, count);
-       if (*err)
-               goto out;
-
-       /* Loop for the donor extents */
-       while (1) {
-               /* The extent for donor must be found. */
-               if (unlikely(!dext)) {
-               missing_donor_extent:
-                       EXT4_ERROR_INODE(donor_inode,
-                                  "The extent for donor must be found");
-                       *err = -EIO;
-                       goto out;
-               } else if (donor_off != le32_to_cpu(tmp_dext.ee_block)) {
-                       EXT4_ERROR_INODE(donor_inode,
-                               "Donor offset(%u) and the first block of donor "
-                               "extent(%u) should be equal",
-                               donor_off,
-                               le32_to_cpu(tmp_dext.ee_block));
-                       *err = -EIO;
-                       goto out;
-               }
-
-               /* Set donor extent to orig extent */
-               *err = mext_leaf_block(handle, orig_inode,
-                                          orig_path, &tmp_dext, &orig_off);
-               if (*err)
-                       goto out;
-
-               /* Set orig extent to donor extent */
-               *err = mext_leaf_block(handle, donor_inode,
-                                          donor_path, &tmp_oext, &donor_off);
-               if (*err)
-                       goto out;
-
-               dext_alen = ext4_ext_get_actual_len(&tmp_dext);
-               replaced_count += dext_alen;
-               donor_off += dext_alen;
-               orig_off += dext_alen;
-
-               BUG_ON(replaced_count > count);
-               /* Already moved the expected blocks */
-               if (replaced_count >= count)
-                       break;
-
-               if (orig_path)
-                       ext4_ext_drop_refs(orig_path);
-               *err = get_ext_path(orig_inode, orig_off, &orig_path);
-               if (*err)
-                       goto out;
-               depth = ext_depth(orig_inode);
-               oext = orig_path[depth].p_ext;
-               tmp_oext = *oext;
-
-               if (donor_path)
-                       ext4_ext_drop_refs(donor_path);
-               *err = get_ext_path(donor_inode, donor_off, &donor_path);
-               if (*err)
-                       goto out;
-               depth = ext_depth(donor_inode);
-               dext = donor_path[depth].p_ext;
-               tmp_dext = *dext;
-
-               *err = mext_calc_swap_extents(&tmp_dext, &tmp_oext, orig_off,
-                                          donor_off, count - replaced_count);
-               if (*err)
-                       goto out;
-       }
-
-out:
-       if (orig_path) {
-               ext4_ext_drop_refs(orig_path);
-               kfree(orig_path);
-       }
-       if (donor_path) {
-               ext4_ext_drop_refs(donor_path);
-               kfree(donor_path);
-       }
-
-       return replaced_count;
-}
-
 /**
  * mext_page_double_lock - Grab and lock pages on both @inode1 and @inode2
  *
  * @inode1:    the inode structure
  * @inode2:    the inode structure
- * @index:     page index
+ * @index1:    page index
+ * @index2:    page index
  * @page:      result page vector
  *
  * Grab two locked pages for inode's by inode order
  */
 static int
 mext_page_double_lock(struct inode *inode1, struct inode *inode2,
-                     pgoff_t index, struct page *page[2])
+                     pgoff_t index1, pgoff_t index2, struct page *page[2])
 {
        struct address_space *mapping[2];
        unsigned fl = AOP_FLAG_NOFS;
@@ -793,15 +142,18 @@ mext_page_double_lock(struct inode *inode1, struct inode *inode2,
                mapping[0] = inode1->i_mapping;
                mapping[1] = inode2->i_mapping;
        } else {
+               pgoff_t tmp = index1;
+               index1 = index2;
+               index2 = tmp;
                mapping[0] = inode2->i_mapping;
                mapping[1] = inode1->i_mapping;
        }
 
-       page[0] = grab_cache_page_write_begin(mapping[0], index, fl);
+       page[0] = grab_cache_page_write_begin(mapping[0], index1, fl);
        if (!page[0])
                return -ENOMEM;
 
-       page[1] = grab_cache_page_write_begin(mapping[1], index, fl);
+       page[1] = grab_cache_page_write_begin(mapping[1], index2, fl);
        if (!page[1]) {
                unlock_page(page[0]);
                page_cache_release(page[0]);
@@ -893,25 +245,27 @@ out:
  * @o_filp:                    file structure of original file
  * @donor_inode:               donor inode
  * @orig_page_offset:          page index on original file
+ * @donor_page_offset:         page index on donor file
  * @data_offset_in_page:       block index where data swapping starts
  * @block_len_in_page:         the number of blocks to be swapped
  * @unwritten:                 orig extent is unwritten or not
  * @err:                       pointer to save return value
  *
  * Save the data in original inode blocks and replace original inode extents
- * with donor inode extents by calling mext_replace_branches().
+ * with donor inode extents by calling ext4_swap_extents().
  * Finally, write out the saved data in new original inode blocks. Return
  * replaced block count.
  */
 static int
 move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
-                 pgoff_t orig_page_offset, int data_offset_in_page,
-                 int block_len_in_page, int unwritten, int *err)
+                    pgoff_t orig_page_offset, pgoff_t donor_page_offset,
+                    int data_offset_in_page,
+                    int block_len_in_page, int unwritten, int *err)
 {
        struct inode *orig_inode = file_inode(o_filp);
        struct page *pagep[2] = {NULL, NULL};
        handle_t *handle;
-       ext4_lblk_t orig_blk_offset;
+       ext4_lblk_t orig_blk_offset, donor_blk_offset;
        unsigned long blocksize = orig_inode->i_sb->s_blocksize;
        unsigned int w_flags = 0;
        unsigned int tmp_data_size, data_size, replaced_size;
@@ -939,6 +293,9 @@ again:
        orig_blk_offset = orig_page_offset * blocks_per_page +
                data_offset_in_page;
 
+       donor_blk_offset = donor_page_offset * blocks_per_page +
+               data_offset_in_page;
+
        /* Calculate data_size */
        if ((orig_blk_offset + block_len_in_page - 1) ==
            ((orig_inode->i_size - 1) >> orig_inode->i_blkbits)) {
@@ -959,7 +316,7 @@ again:
        replaced_size = data_size;
 
        *err = mext_page_double_lock(orig_inode, donor_inode, orig_page_offset,
-                                    pagep);
+                                    donor_page_offset, pagep);
        if (unlikely(*err < 0))
                goto stop_journal;
        /*
@@ -978,7 +335,7 @@ again:
                if (*err)
                        goto drop_data_sem;
 
-               unwritten &= mext_check_coverage(donor_inode, orig_blk_offset,
+               unwritten &= mext_check_coverage(donor_inode, donor_blk_offset,
                                                 block_len_in_page, 1, err);
                if (*err)
                        goto drop_data_sem;
@@ -994,9 +351,10 @@ again:
                        *err = -EBUSY;
                        goto drop_data_sem;
                }
-               replaced_count = mext_replace_branches(handle, orig_inode,
-                                               donor_inode, orig_blk_offset,
-                                               block_len_in_page, err);
+               replaced_count = ext4_swap_extents(handle, orig_inode,
+                                                  donor_inode, orig_blk_offset,
+                                                  donor_blk_offset,
+                                                  block_len_in_page, 1, err);
        drop_data_sem:
                ext4_double_up_write_data_sem(orig_inode, donor_inode);
                goto unlock_pages;
@@ -1014,9 +372,9 @@ data_copy:
                goto unlock_pages;
        }
        ext4_double_down_write_data_sem(orig_inode, donor_inode);
-       replaced_count = mext_replace_branches(handle, orig_inode, donor_inode,
-                                              orig_blk_offset,
-                                              block_len_in_page, err);
+       replaced_count = ext4_swap_extents(handle, orig_inode, donor_inode,
+                                              orig_blk_offset, donor_blk_offset,
+                                          block_len_in_page, 1, err);
        ext4_double_up_write_data_sem(orig_inode, donor_inode);
        if (*err) {
                if (replaced_count) {
@@ -1061,9 +419,9 @@ repair_branches:
         * Try to swap extents to it's original places
         */
        ext4_double_down_write_data_sem(orig_inode, donor_inode);
-       replaced_count = mext_replace_branches(handle, donor_inode, orig_inode,
-                                              orig_blk_offset,
-                                              block_len_in_page, &err2);
+       replaced_count = ext4_swap_extents(handle, donor_inode, orig_inode,
+                                              orig_blk_offset, donor_blk_offset,
+                                          block_len_in_page, 0, &err2);
        ext4_double_up_write_data_sem(orig_inode, donor_inode);
        if (replaced_count != block_len_in_page) {
                EXT4_ERROR_INODE_BLOCK(orig_inode, (sector_t)(orig_blk_offset),
@@ -1093,10 +451,14 @@ mext_check_arguments(struct inode *orig_inode,
                     struct inode *donor_inode, __u64 orig_start,
                     __u64 donor_start, __u64 *len)
 {
-       ext4_lblk_t orig_blocks, donor_blocks;
+       __u64 orig_eof, donor_eof;
        unsigned int blkbits = orig_inode->i_blkbits;
        unsigned int blocksize = 1 << blkbits;
 
+       orig_eof = (i_size_read(orig_inode) + blocksize - 1) >> blkbits;
+       donor_eof = (i_size_read(donor_inode) + blocksize - 1) >> blkbits;
+
+
        if (donor_inode->i_mode & (S_ISUID|S_ISGID)) {
                ext4_debug("ext4 move extent: suid or sgid is set"
                           " to donor file [ino:orig %lu, donor %lu]\n",
@@ -1112,7 +474,7 @@ mext_check_arguments(struct inode *orig_inode,
                ext4_debug("ext4 move extent: The argument files should "
                        "not be swapfile [ino:orig %lu, donor %lu]\n",
                        orig_inode->i_ino, donor_inode->i_ino);
-               return -EINVAL;
+               return -EBUSY;
        }
 
        /* Ext4 move extent supports only extent based file */
@@ -1132,67 +494,28 @@ mext_check_arguments(struct inode *orig_inode,
        }
 
        /* Start offset should be same */
-       if (orig_start != donor_start) {
+       if ((orig_start & ~(PAGE_MASK >> orig_inode->i_blkbits)) !=
+           (donor_start & ~(PAGE_MASK >> orig_inode->i_blkbits))) {
                ext4_debug("ext4 move extent: orig and donor's start "
-                       "offset are not same [ino:orig %lu, donor %lu]\n",
+                       "offset are not alligned [ino:orig %lu, donor %lu]\n",
                        orig_inode->i_ino, donor_inode->i_ino);
                return -EINVAL;
        }
 
        if ((orig_start >= EXT_MAX_BLOCKS) ||
+           (donor_start >= EXT_MAX_BLOCKS) ||
            (*len > EXT_MAX_BLOCKS) ||
+           (donor_start + *len >= EXT_MAX_BLOCKS) ||
            (orig_start + *len >= EXT_MAX_BLOCKS))  {
                ext4_debug("ext4 move extent: Can't handle over [%u] blocks "
                        "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCKS,
                        orig_inode->i_ino, donor_inode->i_ino);
                return -EINVAL;
        }
-
-       if (orig_inode->i_size > donor_inode->i_size) {
-               donor_blocks = (donor_inode->i_size + blocksize - 1) >> blkbits;
-               /* TODO: eliminate this artificial restriction */
-               if (orig_start >= donor_blocks) {
-                       ext4_debug("ext4 move extent: orig start offset "
-                       "[%llu] should be less than donor file blocks "
-                       "[%u] [ino:orig %lu, donor %lu]\n",
-                       orig_start, donor_blocks,
-                       orig_inode->i_ino, donor_inode->i_ino);
-                       return -EINVAL;
-               }
-
-               /* TODO: eliminate this artificial restriction */
-               if (orig_start + *len > donor_blocks) {
-                       ext4_debug("ext4 move extent: End offset [%llu] should "
-                               "be less than donor file blocks [%u]."
-                               "So adjust length from %llu to %llu "
-                               "[ino:orig %lu, donor %lu]\n",
-                               orig_start + *len, donor_blocks,
-                               *len, donor_blocks - orig_start,
-                               orig_inode->i_ino, donor_inode->i_ino);
-                       *len = donor_blocks - orig_start;
-               }
-       } else {
-               orig_blocks = (orig_inode->i_size + blocksize - 1) >> blkbits;
-               if (orig_start >= orig_blocks) {
-                       ext4_debug("ext4 move extent: start offset [%llu] "
-                               "should be less than original file blocks "
-                               "[%u] [ino:orig %lu, donor %lu]\n",
-                                orig_start, orig_blocks,
-                               orig_inode->i_ino, donor_inode->i_ino);
-                       return -EINVAL;
-               }
-
-               if (orig_start + *len > orig_blocks) {
-                       ext4_debug("ext4 move extent: Adjust length "
-                               "from %llu to %llu. Because it should be "
-                               "less than original file blocks "
-                               "[ino:orig %lu, donor %lu]\n",
-                               *len, orig_blocks - orig_start,
-                               orig_inode->i_ino, donor_inode->i_ino);
-                       *len = orig_blocks - orig_start;
-               }
-       }
-
+       if (orig_eof < orig_start + *len - 1)
+               *len = orig_eof - orig_start;
+       if (donor_eof < donor_start + *len - 1)
+               *len = donor_eof - donor_start;
        if (!*len) {
                ext4_debug("ext4 move extent: len should not be 0 "
                        "[ino:orig %lu, donor %lu]\n", orig_inode->i_ino,
@@ -1208,60 +531,26 @@ mext_check_arguments(struct inode *orig_inode,
  *
  * @o_filp:            file structure of the original file
  * @d_filp:            file structure of the donor file
- * @orig_start:                start offset in block for orig
- * @donor_start:       start offset in block for donor
+ * @orig_blk:          start offset in block for orig
+ * @donor_blk:         start offset in block for donor
  * @len:               the number of blocks to be moved
  * @moved_len:         moved block length
  *
  * This function returns 0 and moved block length is set in moved_len
  * if succeed, otherwise returns error value.
  *
- * Note: ext4_move_extents() proceeds the following order.
- * 1:ext4_move_extents() calculates the last block number of moving extent
- *   function by the start block number (orig_start) and the number of blocks
- *   to be moved (len) specified as arguments.
- *   If the {orig, donor}_start points a hole, the extent's start offset
- *   pointed by ext_cur (current extent), holecheck_path, orig_path are set
- *   after hole behind.
- * 2:Continue step 3 to step 5, until the holecheck_path points to last_extent
- *   or the ext_cur exceeds the block_end which is last logical block number.
- * 3:To get the length of continues area, call mext_next_extent()
- *   specified with the ext_cur (initial value is holecheck_path) re-cursive,
- *   until find un-continuous extent, the start logical block number exceeds
- *   the block_end or the extent points to the last extent.
- * 4:Exchange the original inode data with donor inode data
- *   from orig_page_offset to seq_end_page.
- *   The start indexes of data are specified as arguments.
- *   That of the original inode is orig_page_offset,
- *   and the donor inode is also orig_page_offset
- *   (To easily handle blocksize != pagesize case, the offset for the
- *   donor inode is block unit).
- * 5:Update holecheck_path and orig_path to points a next proceeding extent,
- *   then returns to step 2.
- * 6:Release holecheck_path, orig_path and set the len to moved_len
- *   which shows the number of moved blocks.
- *   The moved_len is useful for the command to calculate the file offset
- *   for starting next move extent ioctl.
- * 7:Return 0 on success, or a negative error value on failure.
  */
 int
-ext4_move_extents(struct file *o_filp, struct file *d_filp,
-                __u64 orig_start, __u64 donor_start, __u64 len,
-                __u64 *moved_len)
+ext4_move_extents(struct file *o_filp, struct file *d_filp, __u64 orig_blk,
+                 __u64 donor_blk, __u64 len, __u64 *moved_len)
 {
        struct inode *orig_inode = file_inode(o_filp);
        struct inode *donor_inode = file_inode(d_filp);
-       struct ext4_ext_path *orig_path = NULL, *holecheck_path = NULL;
-       struct ext4_extent *ext_prev, *ext_cur, *ext_dummy;
-       ext4_lblk_t block_start = orig_start;
-       ext4_lblk_t block_end, seq_start, add_blocks, file_end, seq_blocks = 0;
-       ext4_lblk_t rest_blocks;
-       pgoff_t orig_page_offset = 0, seq_end_page;
-       int ret, depth, last_extent = 0;
+       struct ext4_ext_path *path = NULL;
        int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
-       int data_offset_in_page;
-       int block_len_in_page;
-       int unwritten;
+       ext4_lblk_t o_end, o_start = orig_blk;
+       ext4_lblk_t d_start = donor_blk;
+       int ret;
 
        if (orig_inode->i_sb != donor_inode->i_sb) {
                ext4_debug("ext4 move extent: The argument files "
@@ -1303,121 +592,58 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
        /* Protect extent tree against block allocations via delalloc */
        ext4_double_down_write_data_sem(orig_inode, donor_inode);
        /* Check the filesystem environment whether move_extent can be done */
-       ret = mext_check_arguments(orig_inode, donor_inode, orig_start,
-                                   donor_start, &len);
+       ret = mext_check_arguments(orig_inode, donor_inode, orig_blk,
+                                   donor_blk, &len);
        if (ret)
                goto out;
+       o_end = o_start + len;
 
-       file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits;
-       block_end = block_start + len - 1;
-       if (file_end < block_end)
-               len -= block_end - file_end;
+       while (o_start < o_end) {
+               struct ext4_extent *ex;
+               ext4_lblk_t cur_blk, next_blk;
+               pgoff_t orig_page_index, donor_page_index;
+               int offset_in_page;
+               int unwritten, cur_len;
 
-       ret = get_ext_path(orig_inode, block_start, &orig_path);
-       if (ret)
-               goto out;
-
-       /* Get path structure to check the hole */
-       ret = get_ext_path(orig_inode, block_start, &holecheck_path);
-       if (ret)
-               goto out;
-
-       depth = ext_depth(orig_inode);
-       ext_cur = holecheck_path[depth].p_ext;
-
-       /*
-        * Get proper starting location of block replacement if block_start was
-        * within the hole.
-        */
-       if (le32_to_cpu(ext_cur->ee_block) +
-               ext4_ext_get_actual_len(ext_cur) - 1 < block_start) {
-               /*
-                * The hole exists between extents or the tail of
-                * original file.
-                */
-               last_extent = mext_next_extent(orig_inode,
-                                       holecheck_path, &ext_cur);
-               if (last_extent < 0) {
-                       ret = last_extent;
-                       goto out;
-               }
-               last_extent = mext_next_extent(orig_inode, orig_path,
-                                                       &ext_dummy);
-               if (last_extent < 0) {
-                       ret = last_extent;
+               ret = get_ext_path(orig_inode, o_start, &path);
+               if (ret)
                        goto out;
-               }
-               seq_start = le32_to_cpu(ext_cur->ee_block);
-       } else if (le32_to_cpu(ext_cur->ee_block) > block_start)
-               /* The hole exists at the beginning of original file. */
-               seq_start = le32_to_cpu(ext_cur->ee_block);
-       else
-               seq_start = block_start;
-
-       /* No blocks within the specified range. */
-       if (le32_to_cpu(ext_cur->ee_block) > block_end) {
-               ext4_debug("ext4 move extent: The specified range of file "
-                                                       "may be the hole\n");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* Adjust start blocks */
-       add_blocks = min(le32_to_cpu(ext_cur->ee_block) +
-                        ext4_ext_get_actual_len(ext_cur), block_end + 1) -
-                    max(le32_to_cpu(ext_cur->ee_block), block_start);
-
-       while (!last_extent && le32_to_cpu(ext_cur->ee_block) <= block_end) {
-               seq_blocks += add_blocks;
-
-               /* Adjust tail blocks */
-               if (seq_start + seq_blocks - 1 > block_end)
-                       seq_blocks = block_end - seq_start + 1;
-
-               ext_prev = ext_cur;
-               last_extent = mext_next_extent(orig_inode, holecheck_path,
-                                               &ext_cur);
-               if (last_extent < 0) {
-                       ret = last_extent;
-                       break;
-               }
-               add_blocks = ext4_ext_get_actual_len(ext_cur);
-
-               /*
-                * Extend the length of contiguous block (seq_blocks)
-                * if extents are contiguous.
-                */
-               if (ext4_can_extents_be_merged(orig_inode,
-                                              ext_prev, ext_cur) &&
-                   block_end >= le32_to_cpu(ext_cur->ee_block) &&
-                   !last_extent)
+               ex = path[path->p_depth].p_ext;
+               next_blk = ext4_ext_next_allocated_block(path);
+               cur_blk = le32_to_cpu(ex->ee_block);
+               cur_len = ext4_ext_get_actual_len(ex);
+               /* Check hole before the start pos */
+               if (cur_blk + cur_len - 1 < o_start) {
+                       if (next_blk == EXT_MAX_BLOCKS) {
+                               o_start = o_end;
+                               ret = -ENODATA;
+                               goto out;
+                       }
+                       d_start += next_blk - o_start;
+                       o_start = next_blk;
                        continue;
-
-               /* Is original extent is unwritten */
-               unwritten = ext4_ext_is_unwritten(ext_prev);
-
-               data_offset_in_page = seq_start % blocks_per_page;
-
-               /*
-                * Calculate data blocks count that should be swapped
-                * at the first page.
-                */
-               if (data_offset_in_page + seq_blocks > blocks_per_page) {
-                       /* Swapped blocks are across pages */
-                       block_len_in_page =
-                                       blocks_per_page - data_offset_in_page;
-               } else {
-                       /* Swapped blocks are in a page */
-                       block_len_in_page = seq_blocks;
+               /* Check hole after the start pos */
+               } else if (cur_blk > o_start) {
+                       /* Skip hole */
+                       d_start += cur_blk - o_start;
+                       o_start = cur_blk;
+                       /* Extent inside requested range ?*/
+                       if (cur_blk >= o_end)
+                               goto out;
+               } else { /* in_range(o_start, o_blk, o_len) */
+                       cur_len += cur_blk - o_start;
                }
-
-               orig_page_offset = seq_start >>
-                               (PAGE_CACHE_SHIFT - orig_inode->i_blkbits);
-               seq_end_page = (seq_start + seq_blocks - 1) >>
-                               (PAGE_CACHE_SHIFT - orig_inode->i_blkbits);
-               seq_start = le32_to_cpu(ext_cur->ee_block);
-               rest_blocks = seq_blocks;
-
+               unwritten = ext4_ext_is_unwritten(ex);
+               if (o_end - o_start < cur_len)
+                       cur_len = o_end - o_start;
+
+               orig_page_index = o_start >> (PAGE_CACHE_SHIFT -
+                                              orig_inode->i_blkbits);
+               donor_page_index = d_start >> (PAGE_CACHE_SHIFT -
+                                              donor_inode->i_blkbits);
+               offset_in_page = o_start % blocks_per_page;
+               if (cur_len > blocks_per_page- offset_in_page)
+                       cur_len = blocks_per_page - offset_in_page;
                /*
                 * Up semaphore to avoid following problems:
                 * a. transaction deadlock among ext4_journal_start,
@@ -1426,77 +652,29 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp,
                 *    in move_extent_per_page
                 */
                ext4_double_up_write_data_sem(orig_inode, donor_inode);
-
-               while (orig_page_offset <= seq_end_page) {
-
-                       /* Swap original branches with new branches */
-                       block_len_in_page = move_extent_per_page(
-                                               o_filp, donor_inode,
-                                               orig_page_offset,
-                                               data_offset_in_page,
-                                               block_len_in_page,
-                                               unwritten, &ret);
-
-                       /* Count how many blocks we have exchanged */
-                       *moved_len += block_len_in_page;
-                       if (ret < 0)
-                               break;
-                       if (*moved_len > len) {
-                               EXT4_ERROR_INODE(orig_inode,
-                                       "We replaced blocks too much! "
-                                       "sum of replaced: %llu requested: %llu",
-                                       *moved_len, len);
-                               ret = -EIO;
-                               break;
-                       }
-
-                       orig_page_offset++;
-                       data_offset_in_page = 0;
-                       rest_blocks -= block_len_in_page;
-                       if (rest_blocks > blocks_per_page)
-                               block_len_in_page = blocks_per_page;
-                       else
-                               block_len_in_page = rest_blocks;
-               }
-
+               /* Swap original branches with new branches */
+               move_extent_per_page(o_filp, donor_inode,
+                                    orig_page_index, donor_page_index,
+                                    offset_in_page, cur_len,
+                                    unwritten, &ret);
                ext4_double_down_write_data_sem(orig_inode, donor_inode);
                if (ret < 0)
                        break;
-
-               /* Decrease buffer counter */
-               if (holecheck_path)
-                       ext4_ext_drop_refs(holecheck_path);
-               ret = get_ext_path(orig_inode, seq_start, &holecheck_path);
-               if (ret)
-                       break;
-               depth = holecheck_path->p_depth;
-
-               /* Decrease buffer counter */
-               if (orig_path)
-                       ext4_ext_drop_refs(orig_path);
-               ret = get_ext_path(orig_inode, seq_start, &orig_path);
-               if (ret)
-                       break;
-
-               ext_cur = holecheck_path[depth].p_ext;
-               add_blocks = ext4_ext_get_actual_len(ext_cur);
-               seq_blocks = 0;
-
+               o_start += cur_len;
+               d_start += cur_len;
        }
+       *moved_len = o_start - orig_blk;
+       if (*moved_len > len)
+               *moved_len = len;
+
 out:
        if (*moved_len) {
                ext4_discard_preallocations(orig_inode);
                ext4_discard_preallocations(donor_inode);
        }
 
-       if (orig_path) {
-               ext4_ext_drop_refs(orig_path);
-               kfree(orig_path);
-       }
-       if (holecheck_path) {
-               ext4_ext_drop_refs(holecheck_path);
-               kfree(holecheck_path);
-       }
+       ext4_ext_drop_refs(path);
+       kfree(path);
        ext4_double_up_write_data_sem(orig_inode, donor_inode);
        ext4_inode_resume_unlocked_dio(orig_inode);
        ext4_inode_resume_unlocked_dio(donor_inode);
index 603e4ebbd0ac1a8eb33f27f0e06cf302d3ce3352..426211882f7274b496c5c94ecac30fbd18a57325 100644 (file)
@@ -53,7 +53,7 @@ static struct buffer_head *ext4_append(handle_t *handle,
                                        ext4_lblk_t *block)
 {
        struct buffer_head *bh;
-       int err = 0;
+       int err;
 
        if (unlikely(EXT4_SB(inode->i_sb)->s_max_dir_size_kb &&
                     ((inode->i_size >> 10) >=
@@ -62,9 +62,9 @@ static struct buffer_head *ext4_append(handle_t *handle,
 
        *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-       bh = ext4_bread(handle, inode, *block, 1, &err);
-       if (!bh)
-               return ERR_PTR(err);
+       bh = ext4_bread(handle, inode, *block, 1);
+       if (IS_ERR(bh))
+               return bh;
        inode->i_size += inode->i_sb->s_blocksize;
        EXT4_I(inode)->i_disksize = inode->i_size;
        BUFFER_TRACE(bh, "get_write_access");
@@ -94,20 +94,20 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
 {
        struct buffer_head *bh;
        struct ext4_dir_entry *dirent;
-       int err = 0, is_dx_block = 0;
+       int is_dx_block = 0;
 
-       bh = ext4_bread(NULL, inode, block, 0, &err);
-       if (!bh) {
-               if (err == 0) {
-                       ext4_error_inode(inode, __func__, line, block,
-                                              "Directory hole found");
-                       return ERR_PTR(-EIO);
-               }
+       bh = ext4_bread(NULL, inode, block, 0);
+       if (IS_ERR(bh)) {
                __ext4_warning(inode->i_sb, __func__, line,
-                              "error reading directory block "
-                              "(ino %lu, block %lu)", inode->i_ino,
+                              "error %ld reading directory block "
+                              "(ino %lu, block %lu)", PTR_ERR(bh), inode->i_ino,
                               (unsigned long) block);
-               return ERR_PTR(err);
+
+               return bh;
+       }
+       if (!bh) {
+               ext4_error_inode(inode, __func__, line, block, "Directory hole found");
+               return ERR_PTR(-EIO);
        }
        dirent = (struct ext4_dir_entry *) bh->b_data;
        /* Determine whether or not we have an index block */
@@ -124,8 +124,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
                       "directory leaf block found instead of index block");
                return ERR_PTR(-EIO);
        }
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) ||
+       if (!ext4_has_metadata_csum(inode->i_sb) ||
            buffer_verified(bh))
                return bh;
 
@@ -253,8 +252,7 @@ static unsigned dx_node_limit(struct inode *dir);
 static struct dx_frame *dx_probe(const struct qstr *d_name,
                                 struct inode *dir,
                                 struct dx_hash_info *hinfo,
-                                struct dx_frame *frame,
-                                int *err);
+                                struct dx_frame *frame);
 static void dx_release(struct dx_frame *frames);
 static int dx_make_map(struct ext4_dir_entry_2 *de, unsigned blocksize,
                       struct dx_hash_info *hinfo, struct dx_map_entry map[]);
@@ -270,8 +268,7 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash,
                                 __u32 *start_hash);
 static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
                const struct qstr *d_name,
-               struct ext4_dir_entry_2 **res_dir,
-               int *err);
+               struct ext4_dir_entry_2 **res_dir);
 static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
                             struct inode *inode);
 
@@ -340,8 +337,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent)
 {
        struct ext4_dir_entry_tail *t;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return 1;
 
        t = get_dirent_tail(inode, dirent);
@@ -362,8 +358,7 @@ static void ext4_dirent_csum_set(struct inode *inode,
 {
        struct ext4_dir_entry_tail *t;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return;
 
        t = get_dirent_tail(inode, dirent);
@@ -438,8 +433,7 @@ static int ext4_dx_csum_verify(struct inode *inode,
        struct dx_tail *t;
        int count_offset, limit, count;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return 1;
 
        c = get_dx_countlimit(inode, dirent, &count_offset);
@@ -468,8 +462,7 @@ static void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent)
        struct dx_tail *t;
        int count_offset, limit, count;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return;
 
        c = get_dx_countlimit(inode, dirent, &count_offset);
@@ -557,8 +550,7 @@ static inline unsigned dx_root_limit(struct inode *dir, unsigned infosize)
        unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(1) -
                EXT4_DIR_REC_LEN(2) - infosize;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                entry_space -= sizeof(struct dx_tail);
        return entry_space / sizeof(struct dx_entry);
 }
@@ -567,8 +559,7 @@ static inline unsigned dx_node_limit(struct inode *dir)
 {
        unsigned entry_space = dir->i_sb->s_blocksize - EXT4_DIR_REC_LEN(0);
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                entry_space -= sizeof(struct dx_tail);
        return entry_space / sizeof(struct dx_entry);
 }
@@ -641,7 +632,9 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
                u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
                struct stats stats;
                printk("%s%3u:%03u hash %8x/%8x ",levels?"":"   ", i, block, hash, range);
-               if (!(bh = ext4_bread (NULL,dir, block, 0,&err))) continue;
+               bh = ext4_bread(NULL,dir, block, 0);
+               if (!bh || IS_ERR(bh))
+                       continue;
                stats = levels?
                   dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
                   dx_show_leaf(hinfo, (struct ext4_dir_entry_2 *) bh->b_data, blocksize, 0);
@@ -669,29 +662,25 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
  */
 static struct dx_frame *
 dx_probe(const struct qstr *d_name, struct inode *dir,
-        struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
+        struct dx_hash_info *hinfo, struct dx_frame *frame_in)
 {
        unsigned count, indirect;
        struct dx_entry *at, *entries, *p, *q, *m;
        struct dx_root *root;
-       struct buffer_head *bh;
        struct dx_frame *frame = frame_in;
+       struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR);
        u32 hash;
 
-       frame->bh = NULL;
-       bh = ext4_read_dirblock(dir, 0, INDEX);
-       if (IS_ERR(bh)) {
-               *err = PTR_ERR(bh);
-               goto fail;
-       }
-       root = (struct dx_root *) bh->b_data;
+       frame->bh = ext4_read_dirblock(dir, 0, INDEX);
+       if (IS_ERR(frame->bh))
+               return (struct dx_frame *) frame->bh;
+
+       root = (struct dx_root *) frame->bh->b_data;
        if (root->info.hash_version != DX_HASH_TEA &&
            root->info.hash_version != DX_HASH_HALF_MD4 &&
            root->info.hash_version != DX_HASH_LEGACY) {
                ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
                             root->info.hash_version);
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
        hinfo->hash_version = root->info.hash_version;
@@ -705,16 +694,12 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
        if (root->info.unused_flags & 1) {
                ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
                             root->info.unused_flags);
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
 
        if ((indirect = root->info.indirect_levels) > 1) {
                ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
                             root->info.indirect_levels);
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
 
@@ -724,27 +709,21 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
        if (dx_get_limit(entries) != dx_root_limit(dir,
                                                   root->info.info_length)) {
                ext4_warning(dir->i_sb, "dx entry: limit != root limit");
-               brelse(bh);
-               *err = ERR_BAD_DX_DIR;
                goto fail;
        }
 
        dxtrace(printk("Look up %x", hash));
-       while (1)
-       {
+       while (1) {
                count = dx_get_count(entries);
                if (!count || count > dx_get_limit(entries)) {
                        ext4_warning(dir->i_sb,
                                     "dx entry: no count or count > limit");
-                       brelse(bh);
-                       *err = ERR_BAD_DX_DIR;
-                       goto fail2;
+                       goto fail;
                }
 
                p = entries + 1;
                q = entries + count - 1;
-               while (p <= q)
-               {
+               while (p <= q) {
                        m = p + (q - p)/2;
                        dxtrace(printk("."));
                        if (dx_get_hash(m) > hash)
@@ -753,8 +732,7 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
                                p = m + 1;
                }
 
-               if (0) // linear search cross check
-               {
+               if (0) { // linear search cross check
                        unsigned n = count - 1;
                        at = entries;
                        while (n--)
@@ -771,38 +749,35 @@ dx_probe(const struct qstr *d_name, struct inode *dir,
 
                at = p - 1;
                dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-               frame->bh = bh;
                frame->entries = entries;
                frame->at = at;
-               if (!indirect--) return frame;
-               bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
-               if (IS_ERR(bh)) {
-                       *err = PTR_ERR(bh);
-                       goto fail2;
+               if (!indirect--)
+                       return frame;
+               frame++;
+               frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX);
+               if (IS_ERR(frame->bh)) {
+                       ret_err = (struct dx_frame *) frame->bh;
+                       frame->bh = NULL;
+                       goto fail;
                }
-               entries = ((struct dx_node *) bh->b_data)->entries;
+               entries = ((struct dx_node *) frame->bh->b_data)->entries;
 
                if (dx_get_limit(entries) != dx_node_limit (dir)) {
                        ext4_warning(dir->i_sb,
                                     "dx entry: limit != node limit");
-                       brelse(bh);
-                       *err = ERR_BAD_DX_DIR;
-                       goto fail2;
+                       goto fail;
                }
-               frame++;
-               frame->bh = NULL;
        }
-fail2:
+fail:
        while (frame >= frame_in) {
                brelse(frame->bh);
                frame--;
        }
-fail:
-       if (*err == ERR_BAD_DX_DIR)
+       if (ret_err == ERR_PTR(ERR_BAD_DX_DIR))
                ext4_warning(dir->i_sb,
                             "Corrupt dir inode %lu, running e2fsck is "
                             "recommended.", dir->i_ino);
-       return NULL;
+       return ret_err;
 }
 
 static void dx_release (struct dx_frame *frames)
@@ -988,9 +963,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
        }
        hinfo.hash = start_hash;
        hinfo.minor_hash = 0;
-       frame = dx_probe(NULL, dir, &hinfo, frames, &err);
-       if (!frame)
-               return err;
+       frame = dx_probe(NULL, dir, &hinfo, frames);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
 
        /* Add '.' and '..' from the htree header */
        if (!start_hash && !start_minor_hash) {
@@ -1227,8 +1202,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
                                   buffer */
        int num = 0;
        ext4_lblk_t  nblocks;
-       int i, err = 0;
-       int namelen;
+       int i, namelen;
 
        *res_dir = NULL;
        sb = dir->i_sb;
@@ -1258,17 +1232,13 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
                goto restart;
        }
        if (is_dx(dir)) {
-               bh = ext4_dx_find_entry(dir, d_name, res_dir, &err);
+               bh = ext4_dx_find_entry(dir, d_name, res_dir);
                /*
                 * On success, or if the error was file not found,
                 * return.  Otherwise, fall back to doing a search the
                 * old fashioned way.
                 */
-               if (err == -ENOENT)
-                       return NULL;
-               if (err && err != ERR_BAD_DX_DIR)
-                       return ERR_PTR(err);
-               if (bh)
+               if (!IS_ERR(bh) || PTR_ERR(bh) != ERR_BAD_DX_DIR)
                        return bh;
                dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
                               "falling back\n"));
@@ -1298,10 +1268,10 @@ restart:
                                        break;
                                }
                                num++;
-                               bh = ext4_getblk(NULL, dir, b++, 0, &err);
-                               if (unlikely(err)) {
+                               bh = ext4_getblk(NULL, dir, b++, 0);
+                               if (unlikely(IS_ERR(bh))) {
                                        if (ra_max == 0)
-                                               return ERR_PTR(err);
+                                               return bh;
                                        break;
                                }
                                bh_use[ra_max] = bh;
@@ -1366,7 +1336,7 @@ cleanup_and_exit:
 }
 
 static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct qstr *d_name,
-                      struct ext4_dir_entry_2 **res_dir, int *err)
+                      struct ext4_dir_entry_2 **res_dir)
 {
        struct super_block * sb = dir->i_sb;
        struct dx_hash_info     hinfo;
@@ -1375,25 +1345,23 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
        ext4_lblk_t block;
        int retval;
 
-       if (!(frame = dx_probe(d_name, dir, &hinfo, frames, err)))
-               return NULL;
+       frame = dx_probe(d_name, dir, &hinfo, frames);
+       if (IS_ERR(frame))
+               return (struct buffer_head *) frame;
        do {
                block = dx_get_block(frame->at);
                bh = ext4_read_dirblock(dir, block, DIRENT);
-               if (IS_ERR(bh)) {
-                       *err = PTR_ERR(bh);
+               if (IS_ERR(bh))
                        goto errout;
-               }
+
                retval = search_dirblock(bh, dir, d_name,
                                         block << EXT4_BLOCK_SIZE_BITS(sb),
                                         res_dir);
-               if (retval == 1) {      /* Success! */
-                       dx_release(frames);
-                       return bh;
-               }
+               if (retval == 1)
+                       goto success;
                brelse(bh);
                if (retval == -1) {
-                       *err = ERR_BAD_DX_DIR;
+                       bh = ERR_PTR(ERR_BAD_DX_DIR);
                        goto errout;
                }
 
@@ -1402,18 +1370,19 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q
                                               frames, NULL);
                if (retval < 0) {
                        ext4_warning(sb,
-                            "error reading index page in directory #%lu",
-                            dir->i_ino);
-                       *err = retval;
+                            "error %d reading index page in directory #%lu",
+                            retval, dir->i_ino);
+                       bh = ERR_PTR(retval);
                        goto errout;
                }
        } while (retval == 1);
 
-       *err = -ENOENT;
+       bh = NULL;
 errout:
        dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name));
-       dx_release (frames);
-       return NULL;
+success:
+       dx_release(frames);
+       return bh;
 }
 
 static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
@@ -1441,7 +1410,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
                                         dentry);
                        return ERR_PTR(-EIO);
                }
-               inode = ext4_iget(dir->i_sb, ino);
+               inode = ext4_iget_normal(dir->i_sb, ino);
                if (inode == ERR_PTR(-ESTALE)) {
                        EXT4_ERROR_INODE(dir,
                                         "deleted inode referenced: %u",
@@ -1474,7 +1443,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
                return ERR_PTR(-EIO);
        }
 
-       return d_obtain_alias(ext4_iget(child->d_inode->i_sb, ino));
+       return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino));
 }
 
 /*
@@ -1533,7 +1502,7 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, unsigned blocksize)
  */
 static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                        struct buffer_head **bh,struct dx_frame *frame,
-                       struct dx_hash_info *hinfo, int *error)
+                       struct dx_hash_info *hinfo)
 {
        unsigned blocksize = dir->i_sb->s_blocksize;
        unsigned count, continued;
@@ -1548,16 +1517,14 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        int     csum_size = 0;
        int     err = 0, i;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        bh2 = ext4_append(handle, dir, &newblock);
        if (IS_ERR(bh2)) {
                brelse(*bh);
                *bh = NULL;
-               *error = PTR_ERR(bh2);
-               return NULL;
+               return (struct ext4_dir_entry_2 *) bh2;
        }
 
        BUFFER_TRACE(*bh, "get_write_access");
@@ -1617,8 +1584,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
 
        /* Which block gets the new entry? */
-       if (hinfo->hash >= hash2)
-       {
+       if (hinfo->hash >= hash2) {
                swap(*bh, bh2);
                de = de2;
        }
@@ -1638,8 +1604,7 @@ journal_error:
        brelse(bh2);
        *bh = NULL;
        ext4_std_error(dir->i_sb, err);
-       *error = err;
-       return NULL;
+       return ERR_PTR(err);
 }
 
 int ext4_find_dest_de(struct inode *dir, struct inode *inode,
@@ -1718,8 +1683,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
        int             csum_size = 0;
        int             err;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        if (!de) {
@@ -1786,8 +1750,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
        struct fake_dirent *fde;
        int             csum_size = 0;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        blocksize =  dir->i_sb->s_blocksize;
@@ -1853,31 +1816,39 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
                hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
        hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
        ext4fs_dirhash(name, namelen, &hinfo);
+       memset(frames, 0, sizeof(frames));
        frame = frames;
        frame->entries = entries;
        frame->at = entries;
        frame->bh = bh;
        bh = bh2;
 
-       ext4_handle_dirty_dx_node(handle, dir, frame->bh);
-       ext4_handle_dirty_dirent_node(handle, dir, bh);
+       retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
+       if (retval)
+               goto out_frames;        
+       retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
+       if (retval)
+               goto out_frames;        
 
-       de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-       if (!de) {
-               /*
-                * Even if the block split failed, we have to properly write
-                * out all the changes we did so far. Otherwise we can end up
-                * with corrupted filesystem.
-                */
-               ext4_mark_inode_dirty(handle, dir);
-               dx_release(frames);
-               return retval;
+       de = do_split(handle,dir, &bh, frame, &hinfo);
+       if (IS_ERR(de)) {
+               retval = PTR_ERR(de);
+               goto out_frames;
        }
        dx_release(frames);
 
        retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
        brelse(bh);
        return retval;
+out_frames:
+       /*
+        * Even if the block split failed, we have to properly write
+        * out all the changes we did so far. Otherwise we can end up
+        * with corrupted filesystem.
+        */
+       ext4_mark_inode_dirty(handle, dir);
+       dx_release(frames);
+       return retval;
 }
 
 /*
@@ -1904,8 +1875,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        ext4_lblk_t block, blocks;
        int     csum_size = 0;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(inode->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        sb = dir->i_sb;
@@ -1982,9 +1952,9 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
        struct ext4_dir_entry_2 *de;
        int err;
 
-       frame = dx_probe(&dentry->d_name, dir, &hinfo, frames, &err);
-       if (!frame)
-               return err;
+       frame = dx_probe(&dentry->d_name, dir, &hinfo, frames);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
        entries = frame->entries;
        at = frame->at;
        bh = ext4_read_dirblock(dir, dx_get_block(frame->at), DIRENT);
@@ -2095,9 +2065,11 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
                        goto cleanup;
                }
        }
-       de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-       if (!de)
+       de = do_split(handle, dir, &bh, frame, &hinfo);
+       if (IS_ERR(de)) {
+               err = PTR_ERR(de);
                goto cleanup;
+       }
        err = add_dirent_to_buf(handle, dentry, inode, de, bh);
        goto cleanup;
 
@@ -2167,8 +2139,7 @@ static int ext4_delete_entry(handle_t *handle,
                        return err;
        }
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        BUFFER_TRACE(bh, "get_write_access");
@@ -2387,8 +2358,7 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
        int csum_size = 0;
        int err;
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(dir->i_sb))
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) {
@@ -2403,10 +2373,6 @@ static int ext4_init_new_dir(handle_t *handle, struct inode *dir,
        dir_block = ext4_append(handle, inode, &block);
        if (IS_ERR(dir_block))
                return PTR_ERR(dir_block);
-       BUFFER_TRACE(dir_block, "get_write_access");
-       err = ext4_journal_get_write_access(handle, dir_block);
-       if (err)
-               goto out;
        de = (struct ext4_dir_entry_2 *)dir_block->b_data;
        ext4_init_dot_dotdot(inode, de, blocksize, csum_size, dir->i_ino, 0);
        set_nlink(inode, 2);
@@ -2573,7 +2539,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
        int err = 0, rc;
        bool dirty = false;
 
-       if (!sbi->s_journal)
+       if (!sbi->s_journal || is_bad_inode(inode))
                return 0;
 
        WARN_ON_ONCE(!(inode->i_state & (I_NEW | I_FREEING)) &&
@@ -3190,6 +3156,39 @@ static void ext4_update_dir_count(handle_t *handle, struct ext4_renament *ent)
        }
 }
 
+static struct inode *ext4_whiteout_for_rename(struct ext4_renament *ent,
+                                             int credits, handle_t **h)
+{
+       struct inode *wh;
+       handle_t *handle;
+       int retries = 0;
+
+       /*
+        * for inode block, sb block, group summaries,
+        * and inode bitmap
+        */
+       credits += (EXT4_MAXQUOTAS_TRANS_BLOCKS(ent->dir->i_sb) +
+                   EXT4_XATTR_TRANS_BLOCKS + 4);
+retry:
+       wh = ext4_new_inode_start_handle(ent->dir, S_IFCHR | WHITEOUT_MODE,
+                                        &ent->dentry->d_name, 0, NULL,
+                                        EXT4_HT_DIR, credits);
+
+       handle = ext4_journal_current_handle();
+       if (IS_ERR(wh)) {
+               if (handle)
+                       ext4_journal_stop(handle);
+               if (PTR_ERR(wh) == -ENOSPC &&
+                   ext4_should_retry_alloc(ent->dir->i_sb, &retries))
+                       goto retry;
+       } else {
+               *h = handle;
+               init_special_inode(wh, wh->i_mode, WHITEOUT_DEV);
+               wh->i_op = &ext4_special_inode_operations;
+       }
+       return wh;
+}
+
 /*
  * Anybody can rename anything with this: the permission checks are left to the
  * higher-level routines.
@@ -3199,7 +3198,8 @@ static void ext4_update_dir_count(handle_t *handle, struct ext4_renament *ent)
  * This comes from rename(const char *oldpath, const char *newpath)
  */
 static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
-                      struct inode *new_dir, struct dentry *new_dentry)
+                      struct inode *new_dir, struct dentry *new_dentry,
+                      unsigned int flags)
 {
        handle_t *handle = NULL;
        struct ext4_renament old = {
@@ -3214,6 +3214,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        };
        int force_reread;
        int retval;
+       struct inode *whiteout = NULL;
+       int credits;
+       u8 old_file_type;
 
        dquot_initialize(old.dir);
        dquot_initialize(new.dir);
@@ -3252,11 +3255,17 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (new.inode && !test_opt(new.dir->i_sb, NO_AUTO_DA_ALLOC))
                ext4_alloc_da_blocks(old.inode);
 
-       handle = ext4_journal_start(old.dir, EXT4_HT_DIR,
-               (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) +
-                EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2));
-       if (IS_ERR(handle))
-               return PTR_ERR(handle);
+       credits = (2 * EXT4_DATA_TRANS_BLOCKS(old.dir->i_sb) +
+                  EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2);
+       if (!(flags & RENAME_WHITEOUT)) {
+               handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits);
+               if (IS_ERR(handle))
+                       return PTR_ERR(handle);
+       } else {
+               whiteout = ext4_whiteout_for_rename(&old, credits, &handle);
+               if (IS_ERR(whiteout))
+                       return PTR_ERR(whiteout);
+       }
 
        if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
                ext4_handle_sync(handle);
@@ -3284,13 +3293,26 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
         */
        force_reread = (new.dir->i_ino == old.dir->i_ino &&
                        ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
+
+       old_file_type = old.de->file_type;
+       if (whiteout) {
+               /*
+                * Do this before adding a new entry, so the old entry is sure
+                * to be still pointing to the valid old entry.
+                */
+               retval = ext4_setent(handle, &old, whiteout->i_ino,
+                                    EXT4_FT_CHRDEV);
+               if (retval)
+                       goto end_rename;
+               ext4_mark_inode_dirty(handle, whiteout);
+       }
        if (!new.bh) {
                retval = ext4_add_entry(handle, new.dentry, old.inode);
                if (retval)
                        goto end_rename;
        } else {
                retval = ext4_setent(handle, &new,
-                                    old.inode->i_ino, old.de->file_type);
+                                    old.inode->i_ino, old_file_type);
                if (retval)
                        goto end_rename;
        }
@@ -3305,10 +3327,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        old.inode->i_ctime = ext4_current_time(old.inode);
        ext4_mark_inode_dirty(handle, old.inode);
 
-       /*
-        * ok, that's it
-        */
-       ext4_rename_delete(handle, &old, force_reread);
+       if (!whiteout) {
+               /*
+                * ok, that's it
+                */
+               ext4_rename_delete(handle, &old, force_reread);
+       }
 
        if (new.inode) {
                ext4_dec_count(handle, new.inode);
@@ -3344,6 +3368,12 @@ end_rename:
        brelse(old.dir_bh);
        brelse(old.bh);
        brelse(new.bh);
+       if (whiteout) {
+               if (retval)
+                       drop_nlink(whiteout);
+               unlock_new_inode(whiteout);
+               iput(whiteout);
+       }
        if (handle)
                ext4_journal_stop(handle);
        return retval;
@@ -3476,18 +3506,15 @@ static int ext4_rename2(struct inode *old_dir, struct dentry *old_dentry,
                        struct inode *new_dir, struct dentry *new_dentry,
                        unsigned int flags)
 {
-       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
                return -EINVAL;
 
        if (flags & RENAME_EXCHANGE) {
                return ext4_cross_rename(old_dir, old_dentry,
                                         new_dir, new_dentry);
        }
-       /*
-        * Existence checking was done by the VFS, otherwise "RENAME_NOREPLACE"
-        * is equivalent to regular rename.
-        */
-       return ext4_rename(old_dir, old_dentry, new_dir, new_dentry);
+
+       return ext4_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
 }
 
 /*
index 1e43b905ff9854d7a6f45eab3da091b5867a0188..ca4588388fc30bca45887f0f9af9fb8422d9af7f 100644 (file)
@@ -1081,7 +1081,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data,
                        break;
 
                if (meta_bg == 0)
-                       backup_block = group * bpg + blk_off;
+                       backup_block = ((ext4_fsblk_t)group) * bpg + blk_off;
                else
                        backup_block = (ext4_group_first_block_no(sb, group) +
                                        ext4_bg_has_super(sb, group));
@@ -1212,8 +1212,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb,
 {
        struct buffer_head *bh;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return 0;
 
        bh = ext4_get_bitmap(sb, group_data->inode_bitmap);
index 05c159218bc267431ee4e7a865a0e20a5867c949..2c9e6864abd932f007d107c65615ad440cd56f2c 100644 (file)
@@ -70,7 +70,6 @@ static void ext4_mark_recovery_complete(struct super_block *sb,
 static void ext4_clear_journal_err(struct super_block *sb,
                                   struct ext4_super_block *es);
 static int ext4_sync_fs(struct super_block *sb, int wait);
-static int ext4_sync_fs_nojournal(struct super_block *sb, int wait);
 static int ext4_remount(struct super_block *sb, int *flags, char *data);
 static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int ext4_unfreeze(struct super_block *sb);
@@ -141,8 +140,7 @@ static __le32 ext4_superblock_csum(struct super_block *sb,
 static int ext4_superblock_csum_verify(struct super_block *sb,
                                       struct ext4_super_block *es)
 {
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return 1;
 
        return es->s_checksum == ext4_superblock_csum(sb, es);
@@ -152,8 +150,7 @@ void ext4_superblock_csum_set(struct super_block *sb)
 {
        struct ext4_super_block *es = EXT4_SB(sb)->s_es;
 
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(sb))
                return;
 
        es->s_checksum = ext4_superblock_csum(sb, es);
@@ -820,10 +817,9 @@ static void ext4_put_super(struct super_block *sb)
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
        percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
-       percpu_counter_destroy(&sbi->s_extent_cache_cnt);
        brelse(sbi->s_sbh);
 #ifdef CONFIG_QUOTA
-       for (i = 0; i < MAXQUOTAS; i++)
+       for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(sbi->s_qf_names[i]);
 #endif
 
@@ -885,6 +881,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        ext4_es_init_tree(&ei->i_es_tree);
        rwlock_init(&ei->i_es_lock);
        INIT_LIST_HEAD(&ei->i_es_lru);
+       ei->i_es_all_nr = 0;
        ei->i_es_lru_nr = 0;
        ei->i_touch_when = 0;
        ei->i_reserved_data_blocks = 0;
@@ -1002,7 +999,7 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
         * Currently we don't know the generation for parent directory, so
         * a generation of 0 means "accept any"
         */
-       inode = ext4_iget(sb, ino);
+       inode = ext4_iget_normal(sb, ino);
        if (IS_ERR(inode))
                return ERR_CAST(inode);
        if (generation && inode->i_generation != generation) {
@@ -1124,25 +1121,6 @@ static const struct super_operations ext4_sops = {
        .bdev_try_to_free_page = bdev_try_to_free_page,
 };
 
-static const struct super_operations ext4_nojournal_sops = {
-       .alloc_inode    = ext4_alloc_inode,
-       .destroy_inode  = ext4_destroy_inode,
-       .write_inode    = ext4_write_inode,
-       .dirty_inode    = ext4_dirty_inode,
-       .drop_inode     = ext4_drop_inode,
-       .evict_inode    = ext4_evict_inode,
-       .sync_fs        = ext4_sync_fs_nojournal,
-       .put_super      = ext4_put_super,
-       .statfs         = ext4_statfs,
-       .remount_fs     = ext4_remount,
-       .show_options   = ext4_show_options,
-#ifdef CONFIG_QUOTA
-       .quota_read     = ext4_quota_read,
-       .quota_write    = ext4_quota_write,
-#endif
-       .bdev_try_to_free_page = bdev_try_to_free_page,
-};
-
 static const struct export_operations ext4_export_ops = {
        .fh_to_dentry = ext4_fh_to_dentry,
        .fh_to_parent = ext4_fh_to_parent,
@@ -1712,13 +1690,6 @@ static int parse_options(char *options, struct super_block *sb,
                                        "not specified");
                        return 0;
                }
-       } else {
-               if (sbi->s_jquota_fmt) {
-                       ext4_msg(sb, KERN_ERR, "journaled quota format "
-                                       "specified with no journaling "
-                                       "enabled");
-                       return 0;
-               }
        }
 #endif
        if (test_opt(sb, DIOREAD_NOLOCK)) {
@@ -2016,8 +1987,7 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group,
        __u16 crc = 0;
        __le32 le_group = cpu_to_le32(block_group);
 
-       if ((sbi->s_es->s_feature_ro_compat &
-            cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))) {
+       if (ext4_has_metadata_csum(sbi->s_sb)) {
                /* Use new metadata_csum algorithm */
                __le16 save_csum;
                __u32 csum32;
@@ -2035,6 +2005,10 @@ static __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 block_group,
        }
 
        /* old crc16 code */
+       if (!(sbi->s_es->s_feature_ro_compat &
+             cpu_to_le32(EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
+               return 0;
+
        offset = offsetof(struct ext4_group_desc, bg_checksum);
 
        crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
@@ -2191,7 +2165,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
        if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
                /* don't clear list on RO mount w/ errors */
                if (es->s_last_orphan && !(s_flags & MS_RDONLY)) {
-                       jbd_debug(1, "Errors on filesystem, "
+                       ext4_msg(sb, KERN_INFO, "Errors on filesystem, "
                                  "clearing orphan list.\n");
                        es->s_last_orphan = 0;
                }
@@ -2207,7 +2181,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
        /* Needed for iput() to work correctly and not trash data */
        sb->s_flags |= MS_ACTIVE;
        /* Turn on quotas so that they are updated correctly */
-       for (i = 0; i < MAXQUOTAS; i++) {
+       for (i = 0; i < EXT4_MAXQUOTAS; i++) {
                if (EXT4_SB(sb)->s_qf_names[i]) {
                        int ret = ext4_quota_on_mount(sb, i);
                        if (ret < 0)
@@ -2263,7 +2237,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
                       PLURAL(nr_truncates));
 #ifdef CONFIG_QUOTA
        /* Turn quotas off */
-       for (i = 0; i < MAXQUOTAS; i++) {
+       for (i = 0; i < EXT4_MAXQUOTAS; i++) {
                if (sb_dqopt(sb)->files[i])
                        dquot_quota_off(sb, i);
        }
@@ -2548,6 +2522,16 @@ static ssize_t sbi_ui_store(struct ext4_attr *a,
        return count;
 }
 
+static ssize_t es_ui_show(struct ext4_attr *a,
+                          struct ext4_sb_info *sbi, char *buf)
+{
+
+       unsigned int *ui = (unsigned int *) (((char *) sbi->s_es) +
+                          a->u.offset);
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
+}
+
 static ssize_t reserved_clusters_show(struct ext4_attr *a,
                                  struct ext4_sb_info *sbi, char *buf)
 {
@@ -2601,14 +2585,29 @@ static struct ext4_attr ext4_attr_##_name = {                   \
                .offset = offsetof(struct ext4_sb_info, _elname),\
        },                                                      \
 }
+
+#define EXT4_ATTR_OFFSET_ES(_name,_mode,_show,_store,_elname)          \
+static struct ext4_attr ext4_attr_##_name = {                          \
+       .attr = {.name = __stringify(_name), .mode = _mode },           \
+       .show   = _show,                                                \
+       .store  = _store,                                               \
+       .u = {                                                          \
+               .offset = offsetof(struct ext4_super_block, _elname),   \
+       },                                                              \
+}
+
 #define EXT4_ATTR(name, mode, show, store) \
 static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store)
 
 #define EXT4_INFO_ATTR(name) EXT4_ATTR(name, 0444, NULL, NULL)
 #define EXT4_RO_ATTR(name) EXT4_ATTR(name, 0444, name##_show, NULL)
 #define EXT4_RW_ATTR(name) EXT4_ATTR(name, 0644, name##_show, name##_store)
+
+#define EXT4_RO_ATTR_ES_UI(name, elname)       \
+       EXT4_ATTR_OFFSET_ES(name, 0444, es_ui_show, NULL, elname)
 #define EXT4_RW_ATTR_SBI_UI(name, elname)      \
        EXT4_ATTR_OFFSET(name, 0644, sbi_ui_show, sbi_ui_store, elname)
+
 #define ATTR_LIST(name) &ext4_attr_##name.attr
 #define EXT4_DEPRECATED_ATTR(_name, _val)      \
 static struct ext4_attr ext4_attr_##_name = {                  \
@@ -2641,6 +2640,9 @@ EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.int
 EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst);
 EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval);
 EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);
+EXT4_RO_ATTR_ES_UI(errors_count, s_error_count);
+EXT4_RO_ATTR_ES_UI(first_error_time, s_first_error_time);
+EXT4_RO_ATTR_ES_UI(last_error_time, s_last_error_time);
 
 static struct attribute *ext4_attrs[] = {
        ATTR_LIST(delayed_allocation_blocks),
@@ -2664,6 +2666,9 @@ static struct attribute *ext4_attrs[] = {
        ATTR_LIST(warning_ratelimit_burst),
        ATTR_LIST(msg_ratelimit_interval_ms),
        ATTR_LIST(msg_ratelimit_burst),
+       ATTR_LIST(errors_count),
+       ATTR_LIST(first_error_time),
+       ATTR_LIST(last_error_time),
        NULL,
 };
 
@@ -2723,9 +2728,25 @@ static void ext4_feat_release(struct kobject *kobj)
        complete(&ext4_feat->f_kobj_unregister);
 }
 
+static ssize_t ext4_feat_show(struct kobject *kobj,
+                             struct attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "supported\n");
+}
+
+/*
+ * We can not use ext4_attr_show/store because it relies on the kobject
+ * being embedded in the ext4_sb_info structure which is definitely not
+ * true in this case.
+ */
+static const struct sysfs_ops ext4_feat_ops = {
+       .show   = ext4_feat_show,
+       .store  = NULL,
+};
+
 static struct kobj_type ext4_feat_ktype = {
        .default_attrs  = ext4_feat_attrs,
-       .sysfs_ops      = &ext4_attr_ops,
+       .sysfs_ops      = &ext4_feat_ops,
        .release        = ext4_feat_release,
 };
 
@@ -3179,8 +3200,7 @@ static int set_journal_csum_feature_set(struct super_block *sb)
        int compat, incompat;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                      EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+       if (ext4_has_metadata_csum(sb)) {
                /* journal checksum v3 */
                compat = 0;
                incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3;
@@ -3190,6 +3210,10 @@ static int set_journal_csum_feature_set(struct super_block *sb)
                incompat = 0;
        }
 
+       jbd2_journal_clear_features(sbi->s_journal,
+                       JBD2_FEATURE_COMPAT_CHECKSUM, 0,
+                       JBD2_FEATURE_INCOMPAT_CSUM_V3 |
+                       JBD2_FEATURE_INCOMPAT_CSUM_V2);
        if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
                ret = jbd2_journal_set_features(sbi->s_journal,
                                compat, 0,
@@ -3202,11 +3226,8 @@ static int set_journal_csum_feature_set(struct super_block *sb)
                jbd2_journal_clear_features(sbi->s_journal, 0, 0,
                                JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
        } else {
-               jbd2_journal_clear_features(sbi->s_journal,
-                               JBD2_FEATURE_COMPAT_CHECKSUM, 0,
-                               JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT |
-                               JBD2_FEATURE_INCOMPAT_CSUM_V3 |
-                               JBD2_FEATURE_INCOMPAT_CSUM_V2);
+               jbd2_journal_clear_features(sbi->s_journal, 0, 0,
+                               JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
        }
 
        return ret;
@@ -3436,7 +3457,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                logical_sb_block = sb_block;
        }
 
-       if (!(bh = sb_bread(sb, logical_sb_block))) {
+       if (!(bh = sb_bread_unmovable(sb, logical_sb_block))) {
                ext4_msg(sb, KERN_ERR, "unable to read superblock");
                goto out_fail;
        }
@@ -3487,8 +3508,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        /* Precompute checksum seed for all metadata */
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (ext4_has_metadata_csum(sb))
                sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid,
                                               sizeof(es->s_uuid));
 
@@ -3506,6 +3526,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
        set_opt(sb, POSIX_ACL);
 #endif
+       /* don't forget to enable journal_csum when metadata_csum is enabled. */
+       if (ext4_has_metadata_csum(sb))
+               set_opt(sb, JOURNAL_CHECKSUM);
+
        if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
                set_opt(sb, JOURNAL_DATA);
        else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
@@ -3519,8 +3543,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                set_opt(sb, ERRORS_CONT);
        else
                set_opt(sb, ERRORS_RO);
-       if (def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY)
-               set_opt(sb, BLOCK_VALIDITY);
+       /* block_validity enabled by default; disable with noblock_validity */
+       set_opt(sb, BLOCK_VALIDITY);
        if (def_mount_opts & EXT4_DEFM_DISCARD)
                set_opt(sb, DISCARD);
 
@@ -3646,7 +3670,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                brelse(bh);
                logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
                offset = do_div(logical_sb_block, blocksize);
-               bh = sb_bread(sb, logical_sb_block);
+               bh = sb_bread_unmovable(sb, logical_sb_block);
                if (!bh) {
                        ext4_msg(sb, KERN_ERR,
                               "Can't read superblock on 2nd try");
@@ -3868,7 +3892,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 
        for (i = 0; i < db_count; i++) {
                block = descriptor_loc(sb, logical_sb_block, i);
-               sbi->s_group_desc[i] = sb_bread(sb, block);
+               sbi->s_group_desc[i] = sb_bread_unmovable(sb, block);
                if (!sbi->s_group_desc[i]) {
                        ext4_msg(sb, KERN_ERR,
                               "can't read group descriptor %d", i);
@@ -3890,13 +3914,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_err_report.data = (unsigned long) sb;
 
        /* Register extent status tree shrinker */
-       ext4_es_register_shrinker(sbi);
-
-       err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0, GFP_KERNEL);
-       if (err) {
-               ext4_msg(sb, KERN_ERR, "insufficient memory");
+       if (ext4_es_register_shrinker(sbi))
                goto failed_mount3;
-       }
 
        sbi->s_stripe = ext4_get_stripe_size(sbi);
        sbi->s_extent_max_zeroout_kb = 32;
@@ -3904,11 +3923,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        /*
         * set up enough so that it can read an inode
         */
-       if (!test_opt(sb, NOLOAD) &&
-           EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL))
-               sb->s_op = &ext4_sops;
-       else
-               sb->s_op = &ext4_nojournal_sops;
+       sb->s_op = &ext4_sops;
        sb->s_export_op = &ext4_export_ops;
        sb->s_xattr = ext4_xattr_handlers;
 #ifdef CONFIG_QUOTA
@@ -3932,7 +3947,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_MMP) &&
            !(sb->s_flags & MS_RDONLY))
                if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
-                       goto failed_mount3;
+                       goto failed_mount3a;
 
        /*
         * The first inode we look at is the journal inode.  Don't try
@@ -3941,7 +3956,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        if (!test_opt(sb, NOLOAD) &&
            EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) {
                if (ext4_load_journal(sb, es, journal_devnum))
-                       goto failed_mount3;
+                       goto failed_mount3a;
        } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
              EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
                ext4_msg(sb, KERN_ERR, "required journal recovery "
@@ -4229,10 +4244,10 @@ failed_mount_wq:
                jbd2_journal_destroy(sbi->s_journal);
                sbi->s_journal = NULL;
        }
-failed_mount3:
+failed_mount3a:
        ext4_es_unregister_shrinker(sbi);
+failed_mount3:
        del_timer_sync(&sbi->s_err_report);
-       percpu_counter_destroy(&sbi->s_extent_cache_cnt);
        if (sbi->s_mmp_tsk)
                kthread_stop(sbi->s_mmp_tsk);
 failed_mount2:
@@ -4247,7 +4262,7 @@ failed_mount:
                remove_proc_entry(sb->s_id, ext4_proc_root);
        }
 #ifdef CONFIG_QUOTA
-       for (i = 0; i < MAXQUOTAS; i++)
+       for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(sbi->s_qf_names[i]);
 #endif
        ext4_blkdev_remove(sbi);
@@ -4375,6 +4390,15 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
                goto out_bdev;
        }
 
+       if ((le32_to_cpu(es->s_feature_ro_compat) &
+            EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+           es->s_checksum != ext4_superblock_csum(sb, es)) {
+               ext4_msg(sb, KERN_ERR, "external journal has "
+                                      "corrupt superblock");
+               brelse(bh);
+               goto out_bdev;
+       }
+
        if (memcmp(EXT4_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
                ext4_msg(sb, KERN_ERR, "journal UUID does not match");
                brelse(bh);
@@ -4677,15 +4701,19 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
         * being sent at the end of the function. But we can skip it if
         * transaction_commit will do it for us.
         */
-       target = jbd2_get_latest_transaction(sbi->s_journal);
-       if (wait && sbi->s_journal->j_flags & JBD2_BARRIER &&
-           !jbd2_trans_will_send_data_barrier(sbi->s_journal, target))
+       if (sbi->s_journal) {
+               target = jbd2_get_latest_transaction(sbi->s_journal);
+               if (wait && sbi->s_journal->j_flags & JBD2_BARRIER &&
+                   !jbd2_trans_will_send_data_barrier(sbi->s_journal, target))
+                       needs_barrier = true;
+
+               if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
+                       if (wait)
+                               ret = jbd2_log_wait_commit(sbi->s_journal,
+                                                          target);
+               }
+       } else if (wait && test_opt(sb, BARRIER))
                needs_barrier = true;
-
-       if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
-               if (wait)
-                       ret = jbd2_log_wait_commit(sbi->s_journal, target);
-       }
        if (needs_barrier) {
                int err;
                err = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
@@ -4696,19 +4724,6 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
        return ret;
 }
 
-static int ext4_sync_fs_nojournal(struct super_block *sb, int wait)
-{
-       int ret = 0;
-
-       trace_ext4_sync_fs(sb, wait);
-       flush_workqueue(EXT4_SB(sb)->rsv_conversion_wq);
-       dquot_writeback_dquots(sb, -1);
-       if (wait && test_opt(sb, BARRIER))
-               ret = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
-
-       return ret;
-}
-
 /*
  * LVM calls this function before a (read-only) snapshot is created.  This
  * gives us a chance to flush the journal completely and mark the fs clean.
@@ -4727,23 +4742,26 @@ static int ext4_freeze(struct super_block *sb)
 
        journal = EXT4_SB(sb)->s_journal;
 
-       /* Now we set up the journal barrier. */
-       jbd2_journal_lock_updates(journal);
+       if (journal) {
+               /* Now we set up the journal barrier. */
+               jbd2_journal_lock_updates(journal);
 
-       /*
-        * Don't clear the needs_recovery flag if we failed to flush
-        * the journal.
-        */
-       error = jbd2_journal_flush(journal);
-       if (error < 0)
-               goto out;
+               /*
+                * Don't clear the needs_recovery flag if we failed to
+                * flush the journal.
+                */
+               error = jbd2_journal_flush(journal);
+               if (error < 0)
+                       goto out;
+       }
 
        /* Journal blocked and flushed, clear needs_recovery flag. */
        EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
        error = ext4_commit_super(sb, 1);
 out:
-       /* we rely on upper layer to stop further updates */
-       jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+       if (journal)
+               /* we rely on upper layer to stop further updates */
+               jbd2_journal_unlock_updates(journal);
        return error;
 }
 
@@ -4774,7 +4792,7 @@ struct ext4_mount_options {
        u32 s_min_batch_time, s_max_batch_time;
 #ifdef CONFIG_QUOTA
        int s_jquota_fmt;
-       char *s_qf_names[MAXQUOTAS];
+       char *s_qf_names[EXT4_MAXQUOTAS];
 #endif
 };
 
@@ -4804,7 +4822,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
        old_opts.s_max_batch_time = sbi->s_max_batch_time;
 #ifdef CONFIG_QUOTA
        old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
-       for (i = 0; i < MAXQUOTAS; i++)
+       for (i = 0; i < EXT4_MAXQUOTAS; i++)
                if (sbi->s_qf_names[i]) {
                        old_opts.s_qf_names[i] = kstrdup(sbi->s_qf_names[i],
                                                         GFP_KERNEL);
@@ -4828,6 +4846,14 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
+       if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
+           test_opt(sb, JOURNAL_CHECKSUM)) {
+               ext4_msg(sb, KERN_ERR, "changing journal_checksum "
+                        "during remount not supported");
+               err = -EINVAL;
+               goto restore_opts;
+       }
+
        if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
                if (test_opt2(sb, EXPLICIT_DELALLOC)) {
                        ext4_msg(sb, KERN_ERR, "can't mount with "
@@ -4965,7 +4991,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
 
 #ifdef CONFIG_QUOTA
        /* Release old quota file names */
-       for (i = 0; i < MAXQUOTAS; i++)
+       for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(old_opts.s_qf_names[i]);
        if (enable_quota) {
                if (sb_any_quota_suspended(sb))
@@ -4994,7 +5020,7 @@ restore_opts:
        sbi->s_max_batch_time = old_opts.s_max_batch_time;
 #ifdef CONFIG_QUOTA
        sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
-       for (i = 0; i < MAXQUOTAS; i++) {
+       for (i = 0; i < EXT4_MAXQUOTAS; i++) {
                kfree(sbi->s_qf_names[i]);
                sbi->s_qf_names[i] = old_opts.s_qf_names[i];
        }
@@ -5197,7 +5223,7 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
 {
        int err;
        struct inode *qf_inode;
-       unsigned long qf_inums[MAXQUOTAS] = {
+       unsigned long qf_inums[EXT4_MAXQUOTAS] = {
                le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
                le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
        };
@@ -5225,13 +5251,13 @@ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
 static int ext4_enable_quotas(struct super_block *sb)
 {
        int type, err = 0;
-       unsigned long qf_inums[MAXQUOTAS] = {
+       unsigned long qf_inums[EXT4_MAXQUOTAS] = {
                le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
                le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum)
        };
 
        sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
-       for (type = 0; type < MAXQUOTAS; type++) {
+       for (type = 0; type < EXT4_MAXQUOTAS; type++) {
                if (qf_inums[type]) {
                        err = ext4_quota_enable(sb, type, QFMT_VFS_V1,
                                                DQUOT_USAGE_ENABLED);
@@ -5309,7 +5335,6 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
 {
        struct inode *inode = sb_dqopt(sb)->files[type];
        ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
-       int err = 0;
        int offset = off & (sb->s_blocksize - 1);
        int tocopy;
        size_t toread;
@@ -5324,9 +5349,9 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
        while (toread > 0) {
                tocopy = sb->s_blocksize - offset < toread ?
                                sb->s_blocksize - offset : toread;
-               bh = ext4_bread(NULL, inode, blk, 0, &err);
-               if (err)
-                       return err;
+               bh = ext4_bread(NULL, inode, blk, 0);
+               if (IS_ERR(bh))
+                       return PTR_ERR(bh);
                if (!bh)        /* A hole? */
                        memset(data, 0, tocopy);
                else
@@ -5347,8 +5372,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
 {
        struct inode *inode = sb_dqopt(sb)->files[type];
        ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
-       int err = 0;
-       int offset = off & (sb->s_blocksize - 1);
+       int err, offset = off & (sb->s_blocksize - 1);
        struct buffer_head *bh;
        handle_t *handle = journal_current_handle();
 
@@ -5369,14 +5393,16 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
                return -EIO;
        }
 
-       bh = ext4_bread(handle, inode, blk, 1, &err);
+       bh = ext4_bread(handle, inode, blk, 1);
+       if (IS_ERR(bh))
+               return PTR_ERR(bh);
        if (!bh)
                goto out;
        BUFFER_TRACE(bh, "get write access");
        err = ext4_journal_get_write_access(handle, bh);
        if (err) {
                brelse(bh);
-               goto out;
+               return err;
        }
        lock_buffer(bh);
        memcpy(bh->b_data+offset, data, len);
@@ -5385,8 +5411,6 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
        err = ext4_handle_dirty_metadata(handle, NULL, bh);
        brelse(bh);
 out:
-       if (err)
-               return err;
        if (inode->i_size < off + len) {
                i_size_write(inode, off + len);
                EXT4_I(inode)->i_disksize = inode->i_size;
index e7387337060c96f06fe9360966992bb286c20496..1e09fc77395ce0c7cc20496161f09cf0d6eefdbd 100644 (file)
@@ -142,8 +142,7 @@ static int ext4_xattr_block_csum_verify(struct inode *inode,
                                        sector_t block_nr,
                                        struct ext4_xattr_header *hdr)
 {
-       if (EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
+       if (ext4_has_metadata_csum(inode->i_sb) &&
            (hdr->h_checksum != ext4_xattr_block_csum(inode, block_nr, hdr)))
                return 0;
        return 1;
@@ -153,8 +152,7 @@ static void ext4_xattr_block_csum_set(struct inode *inode,
                                      sector_t block_nr,
                                      struct ext4_xattr_header *hdr)
 {
-       if (!EXT4_HAS_RO_COMPAT_FEATURE(inode->i_sb,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (!ext4_has_metadata_csum(inode->i_sb))
                return;
 
        hdr->h_checksum = ext4_xattr_block_csum(inode, block_nr, hdr);
@@ -190,14 +188,28 @@ ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
 }
 
 static int
-ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end)
+ext4_xattr_check_names(struct ext4_xattr_entry *entry, void *end,
+                      void *value_start)
 {
-       while (!IS_LAST_ENTRY(entry)) {
-               struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry);
+       struct ext4_xattr_entry *e = entry;
+
+       while (!IS_LAST_ENTRY(e)) {
+               struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e);
                if ((void *)next >= end)
                        return -EIO;
-               entry = next;
+               e = next;
        }
+
+       while (!IS_LAST_ENTRY(entry)) {
+               if (entry->e_value_size != 0 &&
+                   (value_start + le16_to_cpu(entry->e_value_offs) <
+                    (void *)e + sizeof(__u32) ||
+                    value_start + le16_to_cpu(entry->e_value_offs) +
+                   le32_to_cpu(entry->e_value_size) > end))
+                       return -EIO;
+               entry = EXT4_XATTR_NEXT(entry);
+       }
+
        return 0;
 }
 
@@ -214,7 +226,8 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh)
                return -EIO;
        if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh)))
                return -EIO;
-       error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size);
+       error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size,
+                                      bh->b_data);
        if (!error)
                set_buffer_verified(bh);
        return error;
@@ -331,7 +344,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
        header = IHDR(inode, raw_inode);
        entry = IFIRST(header);
        end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-       error = ext4_xattr_check_names(entry, end);
+       error = ext4_xattr_check_names(entry, end, entry);
        if (error)
                goto cleanup;
        error = ext4_xattr_find_entry(&entry, name_index, name,
@@ -463,7 +476,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
        raw_inode = ext4_raw_inode(&iloc);
        header = IHDR(inode, raw_inode);
        end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-       error = ext4_xattr_check_names(IFIRST(header), end);
+       error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header));
        if (error)
                goto cleanup;
        error = ext4_xattr_list_entries(dentry, IFIRST(header),
@@ -899,14 +912,8 @@ inserted:
                        if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
                                goal = goal & EXT4_MAX_BLOCK_FILE_PHYS;
 
-                       /*
-                        * take i_data_sem because we will test
-                        * i_delalloc_reserved_flag in ext4_mb_new_blocks
-                        */
-                       down_read(&EXT4_I(inode)->i_data_sem);
                        block = ext4_new_meta_blocks(handle, inode, goal, 0,
                                                     NULL, &error);
-                       up_read((&EXT4_I(inode)->i_data_sem));
                        if (error)
                                goto cleanup;
 
@@ -986,7 +993,8 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
        is->s.here = is->s.first;
        is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
        if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
-               error = ext4_xattr_check_names(IFIRST(header), is->s.end);
+               error = ext4_xattr_check_names(IFIRST(header), is->s.end,
+                                              IFIRST(header));
                if (error)
                        return error;
                /* Find the named attribute. */
index 6df8d3d885e5a56374dfeb61c90a7b6d6e148e15..b8b92c2f96834baa310a20b007557f1b9e69ae91 100644 (file)
@@ -736,7 +736,12 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
        }
 
        alias = d_find_alias(inode);
-       if (alias && !vfat_d_anon_disconn(alias)) {
+       /*
+        * Checking "alias->d_parent == dentry->d_parent" to make sure
+        * FS is not corrupted (especially double linked dir).
+        */
+       if (alias && alias->d_parent == dentry->d_parent &&
+           !vfat_d_anon_disconn(alias)) {
                /*
                 * This inode has non anonymous-DCACHE_DISCONNECTED
                 * dentry. This means, the user did ->lookup() by an
@@ -755,12 +760,9 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
 
 out:
        mutex_unlock(&MSDOS_SB(sb)->s_lock);
-       dentry->d_time = dentry->d_parent->d_inode->i_version;
-       dentry = d_splice_alias(inode, dentry);
-       if (dentry)
-               dentry->d_time = dentry->d_parent->d_inode->i_version;
-       return dentry;
-
+       if (!inode)
+               dentry->d_time = dir->i_version;
+       return d_splice_alias(inode, dentry);
 error:
        mutex_unlock(&MSDOS_SB(sb)->s_lock);
        return ERR_PTR(err);
@@ -793,7 +795,6 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
        /* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
-       dentry->d_time = dentry->d_parent->d_inode->i_version;
        d_instantiate(dentry, inode);
 out:
        mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -824,6 +825,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
        clear_nlink(inode);
        inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
        fat_detach(inode);
+       dentry->d_time = dir->i_version;
 out:
        mutex_unlock(&MSDOS_SB(sb)->s_lock);
 
@@ -849,6 +851,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
        clear_nlink(inode);
        inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
        fat_detach(inode);
+       dentry->d_time = dir->i_version;
 out:
        mutex_unlock(&MSDOS_SB(sb)->s_lock);
 
@@ -889,7 +892,6 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
        /* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
-       dentry->d_time = dentry->d_parent->d_inode->i_version;
        d_instantiate(dentry, inode);
 
        mutex_unlock(&MSDOS_SB(sb)->s_lock);
index 9477f8f6aefca491ec50be5c2fda03cf64997a65..757ba2abf21e6c205867960d5fa2ee3b2f77d46f 100644 (file)
@@ -47,7 +47,6 @@ extern void __init chrdev_init(void);
 /*
  * namei.c
  */
-extern int __inode_permission(struct inode *, int);
 extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
                           const char *, unsigned int, struct path *);
@@ -138,12 +137,6 @@ extern long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan,
  */
 extern int rw_verify_area(int, struct file *, const loff_t *, size_t);
 
-/*
- * splice.c
- */
-extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
-               loff_t *opos, size_t len, unsigned int flags);
-
 /*
  * pipe.c
  */
index 881b3bd0143faf9e1b492f64d752f16846fea66d..d67a16f2a45df8fcce56b9ff3ec56f334d951c9c 100644 (file)
 #define BEQUIET
 
 static int isofs_hashi(const struct dentry *parent, struct qstr *qstr);
-static int isofs_hash(const struct dentry *parent, struct qstr *qstr);
 static int isofs_dentry_cmpi(const struct dentry *parent,
                const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name);
-static int isofs_dentry_cmp(const struct dentry *parent,
-               const struct dentry *dentry,
-               unsigned int len, const char *str, const struct qstr *name);
 
 #ifdef CONFIG_JOLIET
 static int isofs_hashi_ms(const struct dentry *parent, struct qstr *qstr);
@@ -134,10 +130,6 @@ static const struct super_operations isofs_sops = {
 
 
 static const struct dentry_operations isofs_dentry_ops[] = {
-       {
-               .d_hash         = isofs_hash,
-               .d_compare      = isofs_dentry_cmp,
-       },
        {
                .d_hash         = isofs_hashi,
                .d_compare      = isofs_dentry_cmpi,
@@ -178,27 +170,6 @@ struct iso9660_options{
        s32 sbsector;
 };
 
-/*
- * Compute the hash for the isofs name corresponding to the dentry.
- */
-static int
-isofs_hash_common(struct qstr *qstr, int ms)
-{
-       const char *name;
-       int len;
-
-       len = qstr->len;
-       name = qstr->name;
-       if (ms) {
-               while (len && name[len-1] == '.')
-                       len--;
-       }
-
-       qstr->hash = full_name_hash(name, len);
-
-       return 0;
-}
-
 /*
  * Compute the hash for the isofs name corresponding to the dentry.
  */
@@ -257,12 +228,6 @@ static int isofs_dentry_cmp_common(
        return 1;
 }
 
-static int
-isofs_hash(const struct dentry *dentry, struct qstr *qstr)
-{
-       return isofs_hash_common(qstr, 0);
-}
-
 static int
 isofs_hashi(const struct dentry *dentry, struct qstr *qstr)
 {
@@ -270,20 +235,34 @@ isofs_hashi(const struct dentry *dentry, struct qstr *qstr)
 }
 
 static int
-isofs_dentry_cmp(const struct dentry *parent, const struct dentry *dentry,
+isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry,
                unsigned int len, const char *str, const struct qstr *name)
 {
-       return isofs_dentry_cmp_common(len, str, name, 0, 0);
+       return isofs_dentry_cmp_common(len, str, name, 0, 1);
 }
 
+#ifdef CONFIG_JOLIET
+/*
+ * Compute the hash for the isofs name corresponding to the dentry.
+ */
 static int
-isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry,
-               unsigned int len, const char *str, const struct qstr *name)
+isofs_hash_common(struct qstr *qstr, int ms)
 {
-       return isofs_dentry_cmp_common(len, str, name, 0, 1);
+       const char *name;
+       int len;
+
+       len = qstr->len;
+       name = qstr->name;
+       if (ms) {
+               while (len && name[len-1] == '.')
+                       len--;
+       }
+
+       qstr->hash = full_name_hash(name, len);
+
+       return 0;
 }
 
-#ifdef CONFIG_JOLIET
 static int
 isofs_hash_ms(const struct dentry *dentry, struct qstr *qstr)
 {
@@ -930,7 +909,8 @@ root_found:
        if (opt.check == 'r')
                table++;
 
-       s->s_d_op = &isofs_dentry_ops[table];
+       if (table)
+               s->s_d_op = &isofs_dentry_ops[table - 1];
 
        /* get the root dentry */
        s->s_root = d_make_root(inode);
index 95295640d9c8b0a36c4f6fae469e59488c21a52e..7b543e6b6526dc8ceebe9bd09aaa07e2d7045236 100644 (file)
@@ -18,25 +18,10 @@ static int
 isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
 {
        struct qstr qstr;
-
-       if (!compare)
-               return 1;
-
-       /* check special "." and ".." files */
-       if (dlen == 1) {
-               /* "." */
-               if (compare[0] == 0) {
-                       if (!dentry->d_name.len)
-                               return 0;
-                       compare = ".";
-               } else if (compare[0] == 1) {
-                       compare = "..";
-                       dlen = 2;
-               }
-       }
-
        qstr.name = compare;
        qstr.len = dlen;
+       if (likely(!dentry->d_op))
+               return dentry->d_name.len != dlen || memcmp(dentry->d_name.name, compare, dlen);
        return dentry->d_op->d_compare(NULL, NULL, dentry->d_name.len, dentry->d_name.name, &qstr);
 }
 
@@ -146,7 +131,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
                                (!(de->flags[-sbi->s_high_sierra] & 1))) &&
                        (sbi->s_showassoc ||
                                (!(de->flags[-sbi->s_high_sierra] & 4)))) {
-                       match = (isofs_cmp(dentry, dpnt, dlen) == 0);
+                       if (dpnt && (dlen > 1 || dpnt[0] > 1))
+                               match = (isofs_cmp(dentry, dpnt, dlen) == 0);
                }
                if (match) {
                        isofs_normalize_block_and_offset(de,
index 06fe11e0abfa02bf4ff9c7b9d0d6360537c84f4e..aab8549591e7ad7143e41a9957338cb8f5583fd6 100644 (file)
@@ -886,7 +886,7 @@ journal_t * journal_init_inode (struct inode *inode)
                goto out_err;
        }
 
-       bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+       bh = getblk_unmovable(journal->j_dev, blocknr, journal->j_blocksize);
        if (!bh) {
                printk(KERN_ERR
                       "%s: Cannot get buffer for journal superblock\n",
index 8898bbd2b61ee477b4f5168e9840c3a6d9048198..dcead636c33b5e5f3ef6b917966f44e007ce95e2 100644 (file)
@@ -93,6 +93,7 @@
 #include <linux/bio.h>
 #endif
 #include <linux/log2.h>
+#include <linux/hash.h>
 
 static struct kmem_cache *revoke_record_cache;
 static struct kmem_cache *revoke_table_cache;
@@ -129,15 +130,11 @@ static void flush_descriptor(journal_t *, struct journal_head *, int, int);
 
 /* Utility functions to maintain the revoke table */
 
-/* Borrowed from buffer.c: this is a tried and tested block hash function */
 static inline int hash(journal_t *journal, unsigned int block)
 {
        struct jbd_revoke_table_s *table = journal->j_revoke;
-       int hash_shift = table->hash_shift;
 
-       return ((block << (hash_shift - 6)) ^
-               (block >> 13) ^
-               (block << (hash_shift - 12))) & (table->hash_size - 1);
+       return hash_32(block, table->hash_shift);
 }
 
 static int insert_revoke_hash(journal_t *journal, unsigned int blocknr,
index 7f34f4716165311f66b62b81dd25a32e899dcf80..988b32ed4c8737db045b517714ee8bcc5698405f 100644 (file)
@@ -96,15 +96,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
 
        if (jh->b_transaction == NULL && !buffer_locked(bh) &&
            !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
-               /*
-                * Get our reference so that bh cannot be freed before
-                * we unlock it
-                */
-               get_bh(bh);
                JBUFFER_TRACE(jh, "remove from checkpoint list");
                ret = __jbd2_journal_remove_checkpoint(jh) + 1;
-               BUFFER_TRACE(bh, "release");
-               __brelse(bh);
        }
        return ret;
 }
@@ -122,8 +115,6 @@ void __jbd2_log_wait_for_space(journal_t *journal)
 
        nblocks = jbd2_space_needed(journal);
        while (jbd2_log_space_left(journal) < nblocks) {
-               if (journal->j_flags & JBD2_ABORT)
-                       return;
                write_unlock(&journal->j_state_lock);
                mutex_lock(&journal->j_checkpoint_mutex);
 
@@ -139,6 +130,10 @@ void __jbd2_log_wait_for_space(journal_t *journal)
                 * trace for forensic evidence.
                 */
                write_lock(&journal->j_state_lock);
+               if (journal->j_flags & JBD2_ABORT) {
+                       mutex_unlock(&journal->j_checkpoint_mutex);
+                       return;
+               }
                spin_lock(&journal->j_list_lock);
                nblocks = jbd2_space_needed(journal);
                space_left = jbd2_log_space_left(journal);
@@ -183,58 +178,6 @@ void __jbd2_log_wait_for_space(journal_t *journal)
        }
 }
 
-/*
- * Clean up transaction's list of buffers submitted for io.
- * We wait for any pending IO to complete and remove any clean
- * buffers. Note that we take the buffers in the opposite ordering
- * from the one in which they were submitted for IO.
- *
- * Return 0 on success, and return <0 if some buffers have failed
- * to be written out.
- *
- * Called with j_list_lock held.
- */
-static int __wait_cp_io(journal_t *journal, transaction_t *transaction)
-{
-       struct journal_head *jh;
-       struct buffer_head *bh;
-       tid_t this_tid;
-       int released = 0;
-       int ret = 0;
-
-       this_tid = transaction->t_tid;
-restart:
-       /* Did somebody clean up the transaction in the meanwhile? */
-       if (journal->j_checkpoint_transactions != transaction ||
-                       transaction->t_tid != this_tid)
-               return ret;
-       while (!released && transaction->t_checkpoint_io_list) {
-               jh = transaction->t_checkpoint_io_list;
-               bh = jh2bh(jh);
-               get_bh(bh);
-               if (buffer_locked(bh)) {
-                       spin_unlock(&journal->j_list_lock);
-                       wait_on_buffer(bh);
-                       /* the journal_head may have gone by now */
-                       BUFFER_TRACE(bh, "brelse");
-                       __brelse(bh);
-                       spin_lock(&journal->j_list_lock);
-                       goto restart;
-               }
-               if (unlikely(buffer_write_io_error(bh)))
-                       ret = -EIO;
-
-               /*
-                * Now in whatever state the buffer currently is, we know that
-                * it has been written out and so we can drop it from the list
-                */
-               released = __jbd2_journal_remove_checkpoint(jh);
-               __brelse(bh);
-       }
-
-       return ret;
-}
-
 static void
 __flush_batch(journal_t *journal, int *batch_count)
 {
@@ -254,81 +197,6 @@ __flush_batch(journal_t *journal, int *batch_count)
        *batch_count = 0;
 }
 
-/*
- * Try to flush one buffer from the checkpoint list to disk.
- *
- * Return 1 if something happened which requires us to abort the current
- * scan of the checkpoint list.  Return <0 if the buffer has failed to
- * be written out.
- *
- * Called with j_list_lock held and drops it if 1 is returned
- */
-static int __process_buffer(journal_t *journal, struct journal_head *jh,
-                           int *batch_count, transaction_t *transaction)
-{
-       struct buffer_head *bh = jh2bh(jh);
-       int ret = 0;
-
-       if (buffer_locked(bh)) {
-               get_bh(bh);
-               spin_unlock(&journal->j_list_lock);
-               wait_on_buffer(bh);
-               /* the journal_head may have gone by now */
-               BUFFER_TRACE(bh, "brelse");
-               __brelse(bh);
-               ret = 1;
-       } else if (jh->b_transaction != NULL) {
-               transaction_t *t = jh->b_transaction;
-               tid_t tid = t->t_tid;
-
-               transaction->t_chp_stats.cs_forced_to_close++;
-               spin_unlock(&journal->j_list_lock);
-               if (unlikely(journal->j_flags & JBD2_UNMOUNT))
-                       /*
-                        * The journal thread is dead; so starting and
-                        * waiting for a commit to finish will cause
-                        * us to wait for a _very_ long time.
-                        */
-                       printk(KERN_ERR "JBD2: %s: "
-                              "Waiting for Godot: block %llu\n",
-                              journal->j_devname,
-                              (unsigned long long) bh->b_blocknr);
-               jbd2_log_start_commit(journal, tid);
-               jbd2_log_wait_commit(journal, tid);
-               ret = 1;
-       } else if (!buffer_dirty(bh)) {
-               ret = 1;
-               if (unlikely(buffer_write_io_error(bh)))
-                       ret = -EIO;
-               get_bh(bh);
-               BUFFER_TRACE(bh, "remove from checkpoint");
-               __jbd2_journal_remove_checkpoint(jh);
-               spin_unlock(&journal->j_list_lock);
-               __brelse(bh);
-       } else {
-               /*
-                * Important: we are about to write the buffer, and
-                * possibly block, while still holding the journal lock.
-                * We cannot afford to let the transaction logic start
-                * messing around with this buffer before we write it to
-                * disk, as that would break recoverability.
-                */
-               BUFFER_TRACE(bh, "queue");
-               get_bh(bh);
-               J_ASSERT_BH(bh, !buffer_jwrite(bh));
-               journal->j_chkpt_bhs[*batch_count] = bh;
-               __buffer_relink_io(jh);
-               transaction->t_chp_stats.cs_written++;
-               (*batch_count)++;
-               if (*batch_count == JBD2_NR_BATCH) {
-                       spin_unlock(&journal->j_list_lock);
-                       __flush_batch(journal, batch_count);
-                       ret = 1;
-               }
-       }
-       return ret;
-}
-
 /*
  * Perform an actual checkpoint. We take the first transaction on the
  * list of transactions to be checkpointed and send all its buffers
@@ -339,9 +207,11 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
  */
 int jbd2_log_do_checkpoint(journal_t *journal)
 {
-       transaction_t *transaction;
-       tid_t this_tid;
-       int result;
+       struct journal_head     *jh;
+       struct buffer_head      *bh;
+       transaction_t           *transaction;
+       tid_t                   this_tid;
+       int                     result, batch_count = 0;
 
        jbd_debug(1, "Start checkpoint\n");
 
@@ -374,45 +244,117 @@ restart:
         * done (maybe it's a new transaction, but it fell at the same
         * address).
         */
-       if (journal->j_checkpoint_transactions == transaction &&
-                       transaction->t_tid == this_tid) {
-               int batch_count = 0;
-               struct journal_head *jh;
-               int retry = 0, err;
-
-               while (!retry && transaction->t_checkpoint_list) {
-                       jh = transaction->t_checkpoint_list;
-                       retry = __process_buffer(journal, jh, &batch_count,
-                                                transaction);
-                       if (retry < 0 && !result)
-                               result = retry;
-                       if (!retry && (need_resched() ||
-                               spin_needbreak(&journal->j_list_lock))) {
-                               spin_unlock(&journal->j_list_lock);
-                               retry = 1;
-                               break;
-                       }
+       if (journal->j_checkpoint_transactions != transaction ||
+           transaction->t_tid != this_tid)
+               goto out;
+
+       /* checkpoint all of the transaction's buffers */
+       while (transaction->t_checkpoint_list) {
+               jh = transaction->t_checkpoint_list;
+               bh = jh2bh(jh);
+
+               if (buffer_locked(bh)) {
+                       spin_unlock(&journal->j_list_lock);
+                       get_bh(bh);
+                       wait_on_buffer(bh);
+                       /* the journal_head may have gone by now */
+                       BUFFER_TRACE(bh, "brelse");
+                       __brelse(bh);
+                       goto retry;
                }
+               if (jh->b_transaction != NULL) {
+                       transaction_t *t = jh->b_transaction;
+                       tid_t tid = t->t_tid;
 
-               if (batch_count) {
-                       if (!retry) {
-                               spin_unlock(&journal->j_list_lock);
-                               retry = 1;
-                       }
-                       __flush_batch(journal, &batch_count);
+                       transaction->t_chp_stats.cs_forced_to_close++;
+                       spin_unlock(&journal->j_list_lock);
+                       if (unlikely(journal->j_flags & JBD2_UNMOUNT))
+                               /*
+                                * The journal thread is dead; so
+                                * starting and waiting for a commit
+                                * to finish will cause us to wait for
+                                * a _very_ long time.
+                                */
+                               printk(KERN_ERR
+               "JBD2: %s: Waiting for Godot: block %llu\n",
+               journal->j_devname, (unsigned long long) bh->b_blocknr);
+
+                       jbd2_log_start_commit(journal, tid);
+                       jbd2_log_wait_commit(journal, tid);
+                       goto retry;
+               }
+               if (!buffer_dirty(bh)) {
+                       if (unlikely(buffer_write_io_error(bh)) && !result)
+                               result = -EIO;
+                       BUFFER_TRACE(bh, "remove from checkpoint");
+                       if (__jbd2_journal_remove_checkpoint(jh))
+                               /* The transaction was released; we're done */
+                               goto out;
+                       continue;
                }
+               /*
+                * Important: we are about to write the buffer, and
+                * possibly block, while still holding the journal
+                * lock.  We cannot afford to let the transaction
+                * logic start messing around with this buffer before
+                * we write it to disk, as that would break
+                * recoverability.
+                */
+               BUFFER_TRACE(bh, "queue");
+               get_bh(bh);
+               J_ASSERT_BH(bh, !buffer_jwrite(bh));
+               journal->j_chkpt_bhs[batch_count++] = bh;
+               __buffer_relink_io(jh);
+               transaction->t_chp_stats.cs_written++;
+               if ((batch_count == JBD2_NR_BATCH) ||
+                   need_resched() ||
+                   spin_needbreak(&journal->j_list_lock))
+                       goto unlock_and_flush;
+       }
 
-               if (retry) {
+       if (batch_count) {
+               unlock_and_flush:
+                       spin_unlock(&journal->j_list_lock);
+               retry:
+                       if (batch_count)
+                               __flush_batch(journal, &batch_count);
                        spin_lock(&journal->j_list_lock);
                        goto restart;
+       }
+
+       /*
+        * Now we issued all of the transaction's buffers, let's deal
+        * with the buffers that are out for I/O.
+        */
+restart2:
+       /* Did somebody clean up the transaction in the meanwhile? */
+       if (journal->j_checkpoint_transactions != transaction ||
+           transaction->t_tid != this_tid)
+               goto out;
+
+       while (transaction->t_checkpoint_io_list) {
+               jh = transaction->t_checkpoint_io_list;
+               bh = jh2bh(jh);
+               if (buffer_locked(bh)) {
+                       spin_unlock(&journal->j_list_lock);
+                       get_bh(bh);
+                       wait_on_buffer(bh);
+                       /* the journal_head may have gone by now */
+                       BUFFER_TRACE(bh, "brelse");
+                       __brelse(bh);
+                       spin_lock(&journal->j_list_lock);
+                       goto restart2;
                }
+               if (unlikely(buffer_write_io_error(bh)) && !result)
+                       result = -EIO;
+
                /*
-                * Now we have cleaned up the first transaction's checkpoint
-                * list. Let's clean up the second one
+                * Now in whatever state the buffer currently is, we
+                * know that it has been written out and so we can
+                * drop it from the list
                 */
-               err = __wait_cp_io(journal, transaction);
-               if (!result)
-                       result = err;
+               if (__jbd2_journal_remove_checkpoint(jh))
+                       break;
        }
 out:
        spin_unlock(&journal->j_list_lock);
@@ -478,18 +420,16 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
  * Find all the written-back checkpoint buffers in the given list and
  * release them.
  *
- * Called with the journal locked.
  * Called with j_list_lock held.
- * Returns number of buffers reaped (for debug)
+ * Returns 1 if we freed the transaction, 0 otherwise.
  */
-
-static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
+static int journal_clean_one_cp_list(struct journal_head *jh)
 {
        struct journal_head *last_jh;
        struct journal_head *next_jh = jh;
-       int ret, freed = 0;
+       int ret;
+       int freed = 0;
 
-       *released = 0;
        if (!jh)
                return 0;
 
@@ -498,13 +438,11 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
                jh = next_jh;
                next_jh = jh->b_cpnext;
                ret = __try_to_free_cp_buf(jh);
-               if (ret) {
-                       freed++;
-                       if (ret == 2) {
-                               *released = 1;
-                               return freed;
-                       }
-               }
+               if (!ret)
+                       return freed;
+               if (ret == 2)
+                       return 1;
+               freed = 1;
                /*
                 * This function only frees up some memory
                 * if possible so we dont have an obligation
@@ -523,49 +461,49 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
  *
  * Find all the written-back checkpoint buffers in the journal and release them.
  *
- * Called with the journal locked.
  * Called with j_list_lock held.
- * Returns number of buffers reaped (for debug)
  */
-
-int __jbd2_journal_clean_checkpoint_list(journal_t *journal)
+void __jbd2_journal_clean_checkpoint_list(journal_t *journal)
 {
        transaction_t *transaction, *last_transaction, *next_transaction;
-       int ret = 0;
-       int released;
+       int ret;
 
        transaction = journal->j_checkpoint_transactions;
        if (!transaction)
-               goto out;
+               return;
 
        last_transaction = transaction->t_cpprev;
        next_transaction = transaction;
        do {
                transaction = next_transaction;
                next_transaction = transaction->t_cpnext;
-               ret += journal_clean_one_cp_list(transaction->
-                               t_checkpoint_list, &released);
+               ret = journal_clean_one_cp_list(transaction->t_checkpoint_list);
                /*
                 * This function only frees up some memory if possible so we
                 * dont have an obligation to finish processing. Bail out if
                 * preemption requested:
                 */
                if (need_resched())
-                       goto out;
-               if (released)
+                       return;
+               if (ret)
                        continue;
                /*
                 * It is essential that we are as careful as in the case of
                 * t_checkpoint_list with removing the buffer from the list as
                 * we can possibly see not yet submitted buffers on io_list
                 */
-               ret += journal_clean_one_cp_list(transaction->
-                               t_checkpoint_io_list, &released);
+               ret = journal_clean_one_cp_list(transaction->
+                               t_checkpoint_io_list);
                if (need_resched())
-                       goto out;
+                       return;
+               /*
+                * Stop scanning if we couldn't free the transaction. This
+                * avoids pointless scanning of transactions which still
+                * weren't checkpointed.
+                */
+               if (!ret)
+                       return;
        } while (transaction != last_transaction);
-out:
-       return ret;
 }
 
 /*
index 19d74d86d99cc630aec2c0ca8f7bf4ef619e3aa3..1df94fabe4eba015bba7e6681e5c17638a27d3df 100644 (file)
@@ -1237,7 +1237,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
                goto out_err;
        }
 
-       bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
+       bh = getblk_unmovable(journal->j_dev, blocknr, journal->j_blocksize);
        if (!bh) {
                printk(KERN_ERR
                       "%s: Cannot get buffer for journal superblock\n",
@@ -1522,14 +1522,6 @@ static int journal_get_superblock(journal_t *journal)
                goto out;
        }
 
-       if (jbd2_journal_has_csum_v2or3(journal) &&
-           JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) {
-               /* Can't have checksum v1 and v2 on at the same time! */
-               printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
-                      "at the same time!\n");
-               goto out;
-       }
-
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) &&
            JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
                /* Can't have checksum v2 and v3 at the same time! */
@@ -1538,6 +1530,14 @@ static int journal_get_superblock(journal_t *journal)
                goto out;
        }
 
+       if (jbd2_journal_has_csum_v2or3(journal) &&
+           JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) {
+               /* Can't have checksum v1 and v2 on at the same time! */
+               printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2/3 "
+                      "at the same time!\n");
+               goto out;
+       }
+
        if (!jbd2_verify_csum_type(journal, sb)) {
                printk(KERN_ERR "JBD2: Unknown checksum type\n");
                goto out;
@@ -1853,13 +1853,12 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
                                journal->j_chksum_driver = NULL;
                                return 0;
                        }
-               }
 
-               /* Precompute checksum seed for all metadata */
-               if (jbd2_journal_has_csum_v2or3(journal))
+                       /* Precompute checksum seed for all metadata */
                        journal->j_csum_seed = jbd2_chksum(journal, ~0,
                                                           sb->s_uuid,
                                                           sizeof(sb->s_uuid));
+               }
        }
 
        /* If enabling v1 checksums, downgrade superblock */
index 9b329b55ffe3726a611ccf8282190e420d173080..bcbef08a4d8fc8873994eb37d35881626f05af70 100644 (file)
@@ -525,6 +525,7 @@ static int do_one_pass(journal_t *journal,
                            !jbd2_descr_block_csum_verify(journal,
                                                          bh->b_data)) {
                                err = -EIO;
+                               brelse(bh);
                                goto failed;
                        }
 
index d5e95a175c9244a24f26b52b4b9755ceee6f1400..c6cbaef2bda1498d8f2e00eeca30a40c8a462361 100644 (file)
@@ -92,6 +92,7 @@
 #include <linux/init.h>
 #include <linux/bio.h>
 #include <linux/log2.h>
+#include <linux/hash.h>
 #endif
 
 static struct kmem_cache *jbd2_revoke_record_cache;
@@ -130,16 +131,9 @@ static void flush_descriptor(journal_t *, struct buffer_head *, int, int);
 
 /* Utility functions to maintain the revoke table */
 
-/* Borrowed from buffer.c: this is a tried and tested block hash function */
 static inline int hash(journal_t *journal, unsigned long long block)
 {
-       struct jbd2_revoke_table_s *table = journal->j_revoke;
-       int hash_shift = table->hash_shift;
-       int hash = (int)block ^ (int)((block >> 31) >> 1);
-
-       return ((hash << (hash_shift - 6)) ^
-               (hash >> 13) ^
-               (hash << (hash_shift - 12))) & (table->hash_size - 1);
+       return hash_64(block, journal->j_revoke->hash_shift);
 }
 
 static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr,
index 43927d14db67c68706ef8dd208c714ec2ec6addb..db5fe86319e69d51e59ff6dd0053d199b406bdc9 100644 (file)
@@ -416,6 +416,7 @@ int __inode_permission(struct inode *inode, int mask)
 
        return security_inode_permission(inode, mask);
 }
+EXPORT_SYMBOL(__inode_permission);
 
 /**
  * sb_permission - Check superblock-level permissions
@@ -2383,22 +2384,17 @@ kern_path_mountpoint(int dfd, const char *name, struct path *path,
 }
 EXPORT_SYMBOL(kern_path_mountpoint);
 
-/*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
- */
-static inline int check_sticky(struct inode *dir, struct inode *inode)
+int __check_sticky(struct inode *dir, struct inode *inode)
 {
        kuid_t fsuid = current_fsuid();
 
-       if (!(dir->i_mode & S_ISVTX))
-               return 0;
        if (uid_eq(inode->i_uid, fsuid))
                return 0;
        if (uid_eq(dir->i_uid, fsuid))
                return 0;
        return !capable_wrt_inode_uidgid(inode, CAP_FOWNER);
 }
+EXPORT_SYMBOL(__check_sticky);
 
 /*
  *     Check whether we can remove a link victim from directory dir, check
@@ -2501,7 +2497,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
        }
 
        mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
-       mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD);
+       mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT2);
        return NULL;
 }
 EXPORT_SYMBOL(lock_rename);
@@ -3064,9 +3060,12 @@ finish_open_created:
        error = may_open(&nd->path, acc_mode, open_flag);
        if (error)
                goto out;
-       file->f_path.mnt = nd->path.mnt;
-       error = finish_open(file, nd->path.dentry, NULL, opened);
-       if (error) {
+
+       BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
+       error = vfs_open(&nd->path, file, current_cred());
+       if (!error) {
+               *opened |= FILE_OPENED;
+       } else {
                if (error == -EOPENSTALE)
                        goto stale_open;
                goto out;
@@ -3155,7 +3154,8 @@ static int do_tmpfile(int dfd, struct filename *pathname,
        if (error)
                goto out2;
        audit_inode(pathname, nd->path.dentry, 0);
-       error = may_open(&nd->path, op->acc_mode, op->open_flag);
+       /* Don't check for other permissions, the inode was just created */
+       error = may_open(&nd->path, MAY_OPEN, op->open_flag);
        if (error)
                goto out2;
        file->f_path.mnt = nd->path.mnt;
@@ -4210,12 +4210,16 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
        bool should_retry = false;
        int error;
 
-       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
                return -EINVAL;
 
-       if ((flags & RENAME_NOREPLACE) && (flags & RENAME_EXCHANGE))
+       if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) &&
+           (flags & RENAME_EXCHANGE))
                return -EINVAL;
 
+       if ((flags & RENAME_WHITEOUT) && !capable(CAP_MKNOD))
+               return -EPERM;
+
 retry:
        from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags);
        if (IS_ERR(from)) {
@@ -4347,6 +4351,20 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna
        return sys_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
 }
 
+int vfs_whiteout(struct inode *dir, struct dentry *dentry)
+{
+       int error = may_create(dir, dentry);
+       if (error)
+               return error;
+
+       if (!dir->i_op->mknod)
+               return -EPERM;
+
+       return dir->i_op->mknod(dir, dentry,
+                               S_IFCHR | WHITEOUT_MODE, WHITEOUT_DEV);
+}
+EXPORT_SYMBOL(vfs_whiteout);
+
 int readlink_copy(char __user *buffer, int buflen, const char *link)
 {
        int len = PTR_ERR(link);
index fbba8b17330d40d4daff7cf61763853cfd414395..5b66b2b3624d0da0efe405a6ecb4c86e07a0b58f 100644 (file)
@@ -1686,6 +1686,33 @@ void drop_collected_mounts(struct vfsmount *mnt)
        namespace_unlock();
 }
 
+/**
+ * clone_private_mount - create a private clone of a path
+ *
+ * This creates a new vfsmount, which will be the clone of @path.  The new will
+ * not be attached anywhere in the namespace and will be private (i.e. changes
+ * to the originating mount won't be propagated into this).
+ *
+ * Release with mntput().
+ */
+struct vfsmount *clone_private_mount(struct path *path)
+{
+       struct mount *old_mnt = real_mount(path->mnt);
+       struct mount *new_mnt;
+
+       if (IS_MNT_UNBINDABLE(old_mnt))
+               return ERR_PTR(-EINVAL);
+
+       down_read(&namespace_sem);
+       new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
+       up_read(&namespace_sem);
+       if (IS_ERR(new_mnt))
+               return ERR_CAST(new_mnt);
+
+       return &new_mnt->mnt;
+}
+EXPORT_SYMBOL_GPL(clone_private_mount);
+
 int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
                   struct vfsmount *root)
 {
index 5228f201d3d53ed93966bc99e682077b9c78f107..4f46f7a05289ba957e219df793b68dfa2f037bb5 100644 (file)
@@ -378,7 +378,7 @@ bl_write_pagelist(struct nfs_pgio_header *header, int sync)
        loff_t offset = header->args.offset;
        size_t count = header->args.count;
        struct page **pages = header->args.pages;
-       int pg_index = pg_index = header->args.pgbase >> PAGE_CACHE_SHIFT;
+       int pg_index = header->args.pgbase >> PAGE_CACHE_SHIFT;
        unsigned int pg_len;
        struct blk_plug plug;
        int i;
index e966c023b1b74df4161461a7cad843e6b9bcfbda..acbf9ca4018ccb6c7cd3bf6d6281ae566cbe4448 100644 (file)
@@ -65,17 +65,18 @@ bl_resolve_deviceid(struct nfs_server *server, struct pnfs_block_volume *b,
 
        dprintk("%s CREATING PIPEFS MESSAGE\n", __func__);
 
+       mutex_lock(&nn->bl_mutex);
        bl_pipe_msg.bl_wq = &nn->bl_wq;
 
        b->simple.len += 4;     /* single volume */
        if (b->simple.len > PAGE_SIZE)
-               return -EIO;
+               goto out_unlock;
 
        memset(msg, 0, sizeof(*msg));
        msg->len = sizeof(*bl_msg) + b->simple.len;
        msg->data = kzalloc(msg->len, gfp_mask);
        if (!msg->data)
-               goto out;
+               goto out_free_data;
 
        bl_msg = msg->data;
        bl_msg->type = BL_DEVICE_MOUNT,
@@ -87,7 +88,7 @@ bl_resolve_deviceid(struct nfs_server *server, struct pnfs_block_volume *b,
        rc = rpc_queue_upcall(nn->bl_device_pipe, msg);
        if (rc < 0) {
                remove_wait_queue(&nn->bl_wq, &wq);
-               goto out;
+               goto out_free_data;
        }
 
        set_current_state(TASK_UNINTERRUPTIBLE);
@@ -97,12 +98,14 @@ bl_resolve_deviceid(struct nfs_server *server, struct pnfs_block_volume *b,
        if (reply->status != BL_DEVICE_REQUEST_PROC) {
                printk(KERN_WARNING "%s failed to decode device: %d\n",
                        __func__, reply->status);
-               goto out;
+               goto out_free_data;
        }
 
        dev = MKDEV(reply->major, reply->minor);
-out:
+out_free_data:
        kfree(msg->data);
+out_unlock:
+       mutex_unlock(&nn->bl_mutex);
        return dev;
 }
 
@@ -232,6 +235,7 @@ static int nfs4blocklayout_net_init(struct net *net)
        struct nfs_net *nn = net_generic(net, nfs_net_id);
        struct dentry *dentry;
 
+       mutex_init(&nn->bl_mutex);
        init_waitqueue_head(&nn->bl_wq);
        nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0);
        if (IS_ERR(nn->bl_device_pipe))
index 5853f53db73246df670ce9daedb73e10d62d2da3..7f3f60641344437ab4f493eebf6093e39957c3be 100644 (file)
@@ -125,6 +125,8 @@ again:
                        continue;
                if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
                        continue;
+               if (!nfs4_valid_open_stateid(state))
+                       continue;
                if (!nfs4_stateid_match(&state->stateid, stateid))
                        continue;
                get_nfs_open_context(ctx);
@@ -193,7 +195,11 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
 {
        int res = 0;
 
-       res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync);
+       if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
+               res = nfs4_proc_delegreturn(inode,
+                               delegation->cred,
+                               &delegation->stateid,
+                               issync);
        nfs_free_delegation(delegation);
        return res;
 }
@@ -380,11 +386,13 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
 {
        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
-       int err;
+       int err = 0;
 
        if (delegation == NULL)
                return 0;
        do {
+               if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
+                       break;
                err = nfs_delegation_claim_opens(inode, &delegation->stateid);
                if (!issync || err != -EAGAIN)
                        break;
@@ -605,10 +613,23 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl
        rcu_read_unlock();
 }
 
+static void nfs_revoke_delegation(struct inode *inode)
+{
+       struct nfs_delegation *delegation;
+       rcu_read_lock();
+       delegation = rcu_dereference(NFS_I(inode)->delegation);
+       if (delegation != NULL) {
+               set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
+               nfs_mark_return_delegation(NFS_SERVER(inode), delegation);
+       }
+       rcu_read_unlock();
+}
+
 void nfs_remove_bad_delegation(struct inode *inode)
 {
        struct nfs_delegation *delegation;
 
+       nfs_revoke_delegation(inode);
        delegation = nfs_inode_detach_delegation(inode);
        if (delegation) {
                nfs_inode_find_state_and_recover(inode, &delegation->stateid);
index 5c1cce39297f68fb178b4a125a83001aeac4afde..e3c20a3ccc937453b678e9bb02d1a46827f11be0 100644 (file)
@@ -31,6 +31,7 @@ enum {
        NFS_DELEGATION_RETURN_IF_CLOSED,
        NFS_DELEGATION_REFERENCED,
        NFS_DELEGATION_RETURNING,
+       NFS_DELEGATION_REVOKED,
 };
 
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
index 06e8cfcbb67053759d9b2b17e4c68a4547b257da..6e62155abf26d43c242c6e7de7250c120a5f1567 100644 (file)
@@ -1527,6 +1527,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
                case -ENOENT:
                        d_drop(dentry);
                        d_add(dentry, NULL);
+                       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
                        break;
                case -EISDIR:
                case -ENOTDIR:
index 20cffc830468d993b7222a05eba469a6637d09fa..10bf07280f4ab2715845003334b73d80bde15f44 100644 (file)
@@ -266,6 +266,7 @@ static void nfs_direct_req_free(struct kref *kref)
 {
        struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref);
 
+       nfs_free_pnfs_ds_cinfo(&dreq->ds_cinfo);
        if (dreq->l_ctx != NULL)
                nfs_put_lock_context(dreq->l_ctx);
        if (dreq->ctx != NULL)
index 46fab1cb455aa4b7deb177eb0e6bb87b786e06d9..7afb52f6a25a1b412bffac5829705bd8137eafbc 100644 (file)
@@ -145,9 +145,6 @@ static int filelayout_async_handle_error(struct rpc_task *task,
        case -NFS4ERR_DELEG_REVOKED:
        case -NFS4ERR_ADMIN_REVOKED:
        case -NFS4ERR_BAD_STATEID:
-               if (state == NULL)
-                       break;
-               nfs_remove_bad_delegation(state->inode);
        case -NFS4ERR_OPENMODE:
                if (state == NULL)
                        break;
index 6388a59f2add0683d759606c1925c35546e914c1..00689a8a85e44677d9a23c092b209ab6600928e4 100644 (file)
@@ -626,7 +626,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
        struct inode *inode = dentry->d_inode;
        int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
-       int err;
+       int err = 0;
 
        trace_nfs_getattr_enter(inode);
        /* Flush out writes to the server in order to update c/mtime.  */
index ef221fb8a18301d05282aa36a3c99ba2b1288b7c..f0e06e4acbef188988547eb4d8bf66178e6d3183 100644 (file)
@@ -19,6 +19,7 @@ struct nfs_net {
        struct rpc_pipe *bl_device_pipe;
        struct bl_dev_msg bl_mount_reply;
        wait_queue_head_t bl_wq;
+       struct mutex bl_mutex;
        struct list_head nfs_client_list;
        struct list_head nfs_volume_list;
 #if IS_ENABLED(CONFIG_NFS_V4)
index 405bd95c1f588739a511fb1566ed47f1513e696f..69dc20a743f9d35a8bc4b090b96e2c727c186e54 100644 (file)
@@ -370,11 +370,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_BAD_STATEID:
-                       if (inode != NULL && nfs4_have_delegation(inode, FMODE_READ)) {
-                               nfs_remove_bad_delegation(inode);
-                               exception->retry = 1;
-                               break;
-                       }
                        if (state == NULL)
                                break;
                        ret = nfs4_schedule_stateid_recovery(server, state);
@@ -1654,7 +1649,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
                        nfs_inode_find_state_and_recover(state->inode,
                                        stateid);
                        nfs4_schedule_stateid_recovery(server, state);
-                       return 0;
+                       return -EAGAIN;
                case -NFS4ERR_DELAY:
                case -NFS4ERR_GRACE:
                        set_bit(NFS_DELEGATED_STATE, &state->flags);
@@ -2109,46 +2104,60 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
        return ret;
 }
 
+static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state)
+{
+       nfs_remove_bad_delegation(state->inode);
+       write_seqlock(&state->seqlock);
+       nfs4_stateid_copy(&state->stateid, &state->open_stateid);
+       write_sequnlock(&state->seqlock);
+       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+}
+
+static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
+{
+       if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
+               nfs_finish_clear_delegation_stateid(state);
+}
+
+static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+       /* NFSv4.0 doesn't allow for delegation recovery on open expire */
+       nfs40_clear_delegation_stateid(state);
+       return nfs4_open_expired(sp, state);
+}
+
 #if defined(CONFIG_NFS_V4_1)
-static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
+static void nfs41_check_delegation_stateid(struct nfs4_state *state)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
-       nfs4_stateid *stateid = &state->stateid;
+       nfs4_stateid stateid;
        struct nfs_delegation *delegation;
-       struct rpc_cred *cred = NULL;
-       int status = -NFS4ERR_BAD_STATEID;
-
-       /* If a state reset has been done, test_stateid is unneeded */
-       if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
-               return;
+       struct rpc_cred *cred;
+       int status;
 
        /* Get the delegation credential for use by test/free_stateid */
        rcu_read_lock();
        delegation = rcu_dereference(NFS_I(state->inode)->delegation);
-       if (delegation != NULL &&
-           nfs4_stateid_match(&delegation->stateid, stateid)) {
-               cred = get_rpccred(delegation->cred);
-               rcu_read_unlock();
-               status = nfs41_test_stateid(server, stateid, cred);
-               trace_nfs4_test_delegation_stateid(state, NULL, status);
-       } else
+       if (delegation == NULL) {
                rcu_read_unlock();
+               return;
+       }
+
+       nfs4_stateid_copy(&stateid, &delegation->stateid);
+       cred = get_rpccred(delegation->cred);
+       rcu_read_unlock();
+       status = nfs41_test_stateid(server, &stateid, cred);
+       trace_nfs4_test_delegation_stateid(state, NULL, status);
 
        if (status != NFS_OK) {
                /* Free the stateid unless the server explicitly
                 * informs us the stateid is unrecognized. */
                if (status != -NFS4ERR_BAD_STATEID)
-                       nfs41_free_stateid(server, stateid, cred);
-               nfs_remove_bad_delegation(state->inode);
-
-               write_seqlock(&state->seqlock);
-               nfs4_stateid_copy(&state->stateid, &state->open_stateid);
-               write_sequnlock(&state->seqlock);
-               clear_bit(NFS_DELEGATED_STATE, &state->flags);
+                       nfs41_free_stateid(server, &stateid, cred);
+               nfs_finish_clear_delegation_stateid(state);
        }
 
-       if (cred != NULL)
-               put_rpccred(cred);
+       put_rpccred(cred);
 }
 
 /**
@@ -2192,7 +2201,7 @@ static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
 {
        int status;
 
-       nfs41_clear_delegation_stateid(state);
+       nfs41_check_delegation_stateid(state);
        status = nfs41_check_open_stateid(state);
        if (status != NFS_OK)
                status = nfs4_open_expired(sp, state);
@@ -2231,19 +2240,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
        seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
 
        ret = _nfs4_proc_open(opendata);
-       if (ret != 0) {
-               if (ret == -ENOENT) {
-                       dentry = opendata->dentry;
-                       if (dentry->d_inode)
-                               d_delete(dentry);
-                       else if (d_unhashed(dentry))
-                               d_add(dentry, NULL);
-
-                       nfs_set_verifier(dentry,
-                                        nfs_save_change_attribute(opendata->dir->d_inode));
-               }
+       if (ret != 0)
                goto out;
-       }
 
        state = nfs4_opendata_to_nfs4_state(opendata);
        ret = PTR_ERR(state);
@@ -4841,9 +4839,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                case -NFS4ERR_DELEG_REVOKED:
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_BAD_STATEID:
-                       if (state == NULL)
-                               break;
-                       nfs_remove_bad_delegation(state->inode);
                case -NFS4ERR_OPENMODE:
                        if (state == NULL)
                                break;
@@ -8341,7 +8336,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
 static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
        .owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
        .state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
-       .recover_open   = nfs4_open_expired,
+       .recover_open   = nfs40_open_expired,
        .recover_lock   = nfs4_lock_expired,
        .establish_clid = nfs4_init_clientid,
 };
@@ -8408,8 +8403,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
                | NFS_CAP_CHANGE_ATTR
                | NFS_CAP_POSIX_LOCK
                | NFS_CAP_STATEID_NFSV41
-               | NFS_CAP_ATOMIC_OPEN_V1
-               | NFS_CAP_SEEK,
+               | NFS_CAP_ATOMIC_OPEN_V1,
        .init_client = nfs41_init_client,
        .shutdown_client = nfs41_shutdown_client,
        .match_stateid = nfs41_match_stateid,
@@ -8431,7 +8425,8 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
                | NFS_CAP_CHANGE_ATTR
                | NFS_CAP_POSIX_LOCK
                | NFS_CAP_STATEID_NFSV41
-               | NFS_CAP_ATOMIC_OPEN_V1,
+               | NFS_CAP_ATOMIC_OPEN_V1
+               | NFS_CAP_SEEK,
        .init_client = nfs41_init_client,
        .shutdown_client = nfs41_shutdown_client,
        .match_stateid = nfs41_match_stateid,
index c6e4bda6300067caef8073b5b5e77f36f2fc408f..9e5bc42180e44d54311ceb3f853a21f42d78ad6b 100644 (file)
@@ -5,7 +5,7 @@
  *  All rights reserved.
  *
  *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <bharrosh@panasas.com>
+ *  Boaz Harrosh <ooo@electrozaur.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
index c89357c7a9143849c0fc0667f5348408e5918fe1..919efd4a1a23bfccf6a618e9f6a39df4b805086f 100644 (file)
@@ -5,7 +5,7 @@
  *  All rights reserved.
  *
  *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <bharrosh@panasas.com>
+ *  Boaz Harrosh <ooo@electrozaur.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
index 3a0828d57339fa8151e98d80c3a7f0a786fc8ef8..2641dbad345cee289626a9a6c4faae09793f3a3b 100644 (file)
@@ -6,7 +6,7 @@
  *  All rights reserved.
  *
  *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <bharrosh@panasas.com>
+ *  Boaz Harrosh <ooo@electrozaur.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
index b3918f7ac34d0eaa0f778fa0bb170fe5dedddcfe..f093c7ec983bbc2bb0b2cb21d0aa8c1eaba411d8 100644 (file)
@@ -5,7 +5,7 @@
  *  All rights reserved.
  *
  *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <bharrosh@panasas.com>
+ *  Boaz Harrosh <ooo@electrozaur.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
index 12493846a2d3ccc68323f11e34a396bbb487fe22..f83b02dc9166d1aaf48b76f816f96a1b908bcec1 100644 (file)
@@ -715,8 +715,6 @@ static void nfs_inode_remove_request(struct nfs_page *req)
 
        if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags))
                nfs_release_request(req);
-       else
-               WARN_ON_ONCE(1);
 }
 
 static void
index ed2b1151b171f275b6a5ebeea1946860876fb391..7cbdf1b2e4abd7286b6033c66a9d999e735737c9 100644 (file)
@@ -774,8 +774,12 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
 {
        if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
                rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
-               dprintk("%s slot is busy\n", __func__);
-               return false;
+               /* Race breaker */
+               if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
+                       dprintk("%s slot is busy\n", __func__);
+                       return false;
+               }
+               rpc_wake_up_queued_task(&clp->cl_cb_waitq, task);
        }
        return true;
 }
index cdeb3cfd6f32b2d412c8478283c8ffc732d6dc06..0beb023f25ace63a8b4ec270eb69bdbaa3e19cbe 100644 (file)
@@ -1272,7 +1272,8 @@ static bool need_wrongsec_check(struct svc_rqst *rqstp)
         */
        if (argp->opcnt == resp->opcnt)
                return false;
-
+       if (next->opnum == OP_ILLEGAL)
+               return false;
        nextd = OPDESC(next);
        /*
         * Rest of 2.6.3.1.1: certain operations will return WRONGSEC
@@ -1589,7 +1590,8 @@ static inline u32 nfsd4_rename_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op
 static inline u32 nfsd4_sequence_rsize(struct svc_rqst *rqstp,
                                       struct nfsd4_op *op)
 {
-       return NFS4_MAX_SESSIONID_LEN + 20;
+       return (op_encode_hdr_size
+               + XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) * sizeof(__be32);
 }
 
 static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
@@ -1893,6 +1895,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_func = (nfsd4op_func)nfsd4_sequence,
                .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
                .op_name = "OP_SEQUENCE",
+               .op_rsize_bop = (nfsd4op_rsize)nfsd4_sequence_rsize,
        },
        [OP_DESTROY_CLIENTID] = {
                .op_func = (nfsd4op_func)nfsd4_destroy_clientid,
index 747f3b95bd11118aa477153fa97594127e2fbc1c..33a46a8dfaf73aaa65ecec7b4603b86ea4e49d83 100644 (file)
@@ -335,12 +335,15 @@ void              nfsd_lockd_shutdown(void);
        (NFSD4_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SUPPATTR_EXCLCREAT)
 
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
-#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
-       (NFSD4_1_SUPPORTED_ATTRS_WORD2 | FATTR4_WORD2_SECURITY_LABEL)
+#define NFSD4_2_SECURITY_ATTRS         FATTR4_WORD2_SECURITY_LABEL
 #else
-#define NFSD4_2_SUPPORTED_ATTRS_WORD2 0
+#define NFSD4_2_SECURITY_ATTRS         0
 #endif
 
+#define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
+       (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
+       NFSD4_2_SECURITY_ATTRS)
+
 static inline u32 nfsd_suppattrs0(u32 minorversion)
 {
        return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD0
index 9d3e9c50066aaf5856350cf3bc85576a79bab900..89326acd45615e50cc60c09cdd3531137b813138 100644 (file)
@@ -229,8 +229,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
                                              &fsnotify_mark_srcu);
        }
 
+       /*
+        * We need to merge inode & vfsmount mark lists so that inode mark
+        * ignore masks are properly reflected for mount mark notifications.
+        * That's why this traversal is so complicated...
+        */
        while (inode_node || vfsmount_node) {
-               inode_group = vfsmount_group = NULL;
+               inode_group = NULL;
+               inode_mark = NULL;
+               vfsmount_group = NULL;
+               vfsmount_mark = NULL;
 
                if (inode_node) {
                        inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu),
@@ -244,21 +252,19 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
                        vfsmount_group = vfsmount_mark->group;
                }
 
-               if (inode_group > vfsmount_group) {
-                       /* handle inode */
-                       ret = send_to_group(to_tell, inode_mark, NULL, mask,
-                                           data, data_is, cookie, file_name);
-                       /* we didn't use the vfsmount_mark */
-                       vfsmount_group = NULL;
-               } else if (vfsmount_group > inode_group) {
-                       ret = send_to_group(to_tell, NULL, vfsmount_mark, mask,
-                                           data, data_is, cookie, file_name);
-                       inode_group = NULL;
-               } else {
-                       ret = send_to_group(to_tell, inode_mark, vfsmount_mark,
-                                           mask, data, data_is, cookie,
-                                           file_name);
+               if (inode_group && vfsmount_group) {
+                       int cmp = fsnotify_compare_groups(inode_group,
+                                                         vfsmount_group);
+                       if (cmp > 0) {
+                               inode_group = NULL;
+                               inode_mark = NULL;
+                       } else if (cmp < 0) {
+                               vfsmount_group = NULL;
+                               vfsmount_mark = NULL;
+                       }
                }
+               ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
+                                   data, data_is, cookie, file_name);
 
                if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
                        goto out;
index 9c0898c4cfe1ce771a8a0832adda51c80225ce59..3b68b0ae0a97cb6beb6b642f3098de5c8aaec4d0 100644 (file)
@@ -12,6 +12,10 @@ extern void fsnotify_flush_notify(struct fsnotify_group *group);
 /* protects reads of inode and vfsmount marks list */
 extern struct srcu_struct fsnotify_mark_srcu;
 
+/* compare two groups for sorting of marks lists */
+extern int fsnotify_compare_groups(struct fsnotify_group *a,
+                                  struct fsnotify_group *b);
+
 extern void fsnotify_set_inode_mark_mask_locked(struct fsnotify_mark *fsn_mark,
                                                __u32 mask);
 /* add a mark to an inode */
index 9ce062218de9cf2559c02b92a7a201224d1d67fc..dfbf5447eea4cea8fdf664ff5b0232f8a61e68b0 100644 (file)
@@ -194,6 +194,7 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
 {
        struct fsnotify_mark *lmark, *last = NULL;
        int ret = 0;
+       int cmp;
 
        mark->flags |= FSNOTIFY_MARK_FLAG_INODE;
 
@@ -219,11 +220,8 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
                        goto out;
                }
 
-               if (mark->group->priority < lmark->group->priority)
-                       continue;
-
-               if ((mark->group->priority == lmark->group->priority) &&
-                   (mark->group < lmark->group))
+               cmp = fsnotify_compare_groups(lmark->group, mark->group);
+               if (cmp < 0)
                        continue;
 
                hlist_add_before_rcu(&mark->i.i_list, &lmark->i.i_list);
@@ -288,20 +286,25 @@ void fsnotify_unmount_inodes(struct list_head *list)
                spin_unlock(&inode->i_lock);
 
                /* In case the dropping of a reference would nuke next_i. */
-               if ((&next_i->i_sb_list != list) &&
-                   atomic_read(&next_i->i_count)) {
+               while (&next_i->i_sb_list != list) {
                        spin_lock(&next_i->i_lock);
-                       if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) {
+                       if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) &&
+                                               atomic_read(&next_i->i_count)) {
                                __iget(next_i);
                                need_iput = next_i;
+                               spin_unlock(&next_i->i_lock);
+                               break;
                        }
                        spin_unlock(&next_i->i_lock);
+                       next_i = list_entry(next_i->i_sb_list.next,
+                                               struct inode, i_sb_list);
                }
 
                /*
-                * We can safely drop inode_sb_list_lock here because we hold
-                * references on both inode and next_i.  Also no new inodes
-                * will be added since the umount has begun.
+                * We can safely drop inode_sb_list_lock here because either
+                * we actually hold references on both inode and next_i or
+                * end of list.  Also no new inodes will be added since the
+                * umount has begun.
                 */
                spin_unlock(&inode_sb_list_lock);
 
index daf76652fe58c0534f355fd59f11ffbddcc43097..283aa312d7458a36bce37090fa10fdaf3dae48f1 100644 (file)
@@ -227,14 +227,13 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
        struct fsnotify_event *kevent;
        char __user *start;
        int ret;
-       DEFINE_WAIT(wait);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
        start = buf;
        group = file->private_data;
 
+       add_wait_queue(&group->notification_waitq, &wait);
        while (1) {
-               prepare_to_wait(&group->notification_waitq, &wait, TASK_INTERRUPTIBLE);
-
                mutex_lock(&group->notification_mutex);
                kevent = get_one_event(group, count);
                mutex_unlock(&group->notification_mutex);
@@ -264,10 +263,10 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
                if (start != buf)
                        break;
 
-               schedule();
+               wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
        }
+       remove_wait_queue(&group->notification_waitq, &wait);
 
-       finish_wait(&group->notification_waitq, &wait);
        if (start != buf && ret != -EFAULT)
                ret = buf - start;
        return ret;
index d90deaa08e78f6e82cde921f5914000bc9ca4a97..34c38fabf514f1a892e10e2e24ff4a3d252ec000 100644 (file)
@@ -209,6 +209,42 @@ void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mas
        mark->ignored_mask = mask;
 }
 
+/*
+ * Sorting function for lists of fsnotify marks.
+ *
+ * Fanotify supports different notification classes (reflected as priority of
+ * notification group). Events shall be passed to notification groups in
+ * decreasing priority order. To achieve this marks in notification lists for
+ * inodes and vfsmounts are sorted so that priorities of corresponding groups
+ * are descending.
+ *
+ * Furthermore correct handling of the ignore mask requires processing inode
+ * and vfsmount marks of each group together. Using the group address as
+ * further sort criterion provides a unique sorting order and thus we can
+ * merge inode and vfsmount lists of marks in linear time and find groups
+ * present in both lists.
+ *
+ * A return value of 1 signifies that b has priority over a.
+ * A return value of 0 signifies that the two marks have to be handled together.
+ * A return value of -1 signifies that a has priority over b.
+ */
+int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b)
+{
+       if (a == b)
+               return 0;
+       if (!a)
+               return 1;
+       if (!b)
+               return -1;
+       if (a->priority < b->priority)
+               return 1;
+       if (a->priority > b->priority)
+               return -1;
+       if (a < b)
+               return 1;
+       return -1;
+}
+
 /*
  * Attach an initialized mark to a given group and fs object.
  * These marks may be used for the fsnotify backend to determine which
index ac851e8376b1931d88adcf4ff5eaa8bd2445a635..faefa72a11ebaacff32569535e69a9005a0d4f0f 100644 (file)
@@ -153,6 +153,7 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
        struct mount *m = real_mount(mnt);
        struct fsnotify_mark *lmark, *last = NULL;
        int ret = 0;
+       int cmp;
 
        mark->flags |= FSNOTIFY_MARK_FLAG_VFSMOUNT;
 
@@ -178,11 +179,8 @@ int fsnotify_add_vfsmount_mark(struct fsnotify_mark *mark,
                        goto out;
                }
 
-               if (mark->group->priority < lmark->group->priority)
-                       continue;
-
-               if ((mark->group->priority == lmark->group->priority) &&
-                   (mark->group < lmark->group))
+               cmp = fsnotify_compare_groups(lmark->group, mark->group);
+               if (cmp < 0)
                        continue;
 
                hlist_add_before_rcu(&mark->m.m_list, &lmark->m.m_list);
index 97de0fbd9f784196312d2330b34e43873b6c6ecc..a9604400406491744281dfaee496491e36f5a074 100644 (file)
@@ -925,7 +925,7 @@ static int o2net_send_tcp_msg(struct socket *sock, struct kvec *vec,
                              size_t veclen, size_t total)
 {
        int ret;
-       struct msghdr msg;
+       struct msghdr msg = {.msg_flags = 0,};
 
        if (sock == NULL) {
                ret = -EINVAL;
index 8add6f1030d7c0d9afc9aa56c918eb9bc3a10659..b931e04e33889742a6192255b3bd95d8779203ea 100644 (file)
@@ -158,7 +158,7 @@ bail_add:
                 * NOTE: This dentry already has ->d_op set from
                 * ocfs2_get_parent() and ocfs2_get_dentry()
                 */
-               if (ret)
+               if (!IS_ERR_OR_NULL(ret))
                        dentry = ret;
 
                status = ocfs2_dentry_attach_lock(dentry, inode,
index d6fd3acde134d9669391cd064960790dea586042..de92c13b58be29e757cd58b53d10232439ad57c5 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -823,8 +823,7 @@ struct file *dentry_open(const struct path *path, int flags,
        f = get_empty_filp();
        if (!IS_ERR(f)) {
                f->f_flags = flags;
-               f->f_path = *path;
-               error = do_dentry_open(f, NULL, cred);
+               error = vfs_open(path, f, cred);
                if (!error) {
                        /* from now on we need fput() to dispose of f */
                        error = open_check_o_direct(f);
@@ -841,6 +840,26 @@ struct file *dentry_open(const struct path *path, int flags,
 }
 EXPORT_SYMBOL(dentry_open);
 
+/**
+ * vfs_open - open the file at the given path
+ * @path: path to open
+ * @filp: newly allocated file with f_flag initialized
+ * @cred: credentials to use
+ */
+int vfs_open(const struct path *path, struct file *filp,
+            const struct cred *cred)
+{
+       struct inode *inode = path->dentry->d_inode;
+
+       if (inode->i_op->dentry_open)
+               return inode->i_op->dentry_open(path->dentry, filp, cred);
+       else {
+               filp->f_path = *path;
+               return do_dentry_open(filp, NULL, cred);
+       }
+}
+EXPORT_SYMBOL(vfs_open);
+
 static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
 {
        int lookup_flags = 0;
diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig
new file mode 100644 (file)
index 0000000..3435581
--- /dev/null
@@ -0,0 +1,10 @@
+config OVERLAY_FS
+       tristate "Overlay filesystem support"
+       help
+         An overlay filesystem combines two filesystems - an 'upper' filesystem
+         and a 'lower' filesystem.  When a name exists in both filesystems, the
+         object in the 'upper' filesystem is visible while the object in the
+         'lower' filesystem is either hidden or, in the case of directories,
+         merged with the 'upper' object.
+
+         For more information see Documentation/filesystems/overlayfs.txt
diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile
new file mode 100644 (file)
index 0000000..900daed
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the overlay filesystem.
+#
+
+obj-$(CONFIG_OVERLAY_FS) += overlay.o
+
+overlay-objs := super.o inode.o dir.o readdir.o copy_up.o
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
new file mode 100644 (file)
index 0000000..ea10a87
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ *
+ * Copyright (C) 2011 Novell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/splice.h>
+#include <linux/xattr.h>
+#include <linux/security.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/namei.h>
+#include "overlayfs.h"
+
+#define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
+
+int ovl_copy_xattr(struct dentry *old, struct dentry *new)
+{
+       ssize_t list_size, size;
+       char *buf, *name, *value;
+       int error;
+
+       if (!old->d_inode->i_op->getxattr ||
+           !new->d_inode->i_op->getxattr)
+               return 0;
+
+       list_size = vfs_listxattr(old, NULL, 0);
+       if (list_size <= 0) {
+               if (list_size == -EOPNOTSUPP)
+                       return 0;
+               return list_size;
+       }
+
+       buf = kzalloc(list_size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       error = -ENOMEM;
+       value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
+       if (!value)
+               goto out;
+
+       list_size = vfs_listxattr(old, buf, list_size);
+       if (list_size <= 0) {
+               error = list_size;
+               goto out_free_value;
+       }
+
+       for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
+               size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX);
+               if (size <= 0) {
+                       error = size;
+                       goto out_free_value;
+               }
+               error = vfs_setxattr(new, name, value, size, 0);
+               if (error)
+                       goto out_free_value;
+       }
+
+out_free_value:
+       kfree(value);
+out:
+       kfree(buf);
+       return error;
+}
+
+static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
+{
+       struct file *old_file;
+       struct file *new_file;
+       loff_t old_pos = 0;
+       loff_t new_pos = 0;
+       int error = 0;
+
+       if (len == 0)
+               return 0;
+
+       old_file = ovl_path_open(old, O_RDONLY);
+       if (IS_ERR(old_file))
+               return PTR_ERR(old_file);
+
+       new_file = ovl_path_open(new, O_WRONLY);
+       if (IS_ERR(new_file)) {
+               error = PTR_ERR(new_file);
+               goto out_fput;
+       }
+
+       /* FIXME: copy up sparse files efficiently */
+       while (len) {
+               size_t this_len = OVL_COPY_UP_CHUNK_SIZE;
+               long bytes;
+
+               if (len < this_len)
+                       this_len = len;
+
+               if (signal_pending_state(TASK_KILLABLE, current)) {
+                       error = -EINTR;
+                       break;
+               }
+
+               bytes = do_splice_direct(old_file, &old_pos,
+                                        new_file, &new_pos,
+                                        this_len, SPLICE_F_MOVE);
+               if (bytes <= 0) {
+                       error = bytes;
+                       break;
+               }
+               WARN_ON(old_pos != new_pos);
+
+               len -= bytes;
+       }
+
+       fput(new_file);
+out_fput:
+       fput(old_file);
+       return error;
+}
+
+static char *ovl_read_symlink(struct dentry *realdentry)
+{
+       int res;
+       char *buf;
+       struct inode *inode = realdentry->d_inode;
+       mm_segment_t old_fs;
+
+       res = -EINVAL;
+       if (!inode->i_op->readlink)
+               goto err;
+
+       res = -ENOMEM;
+       buf = (char *) __get_free_page(GFP_KERNEL);
+       if (!buf)
+               goto err;
+
+       old_fs = get_fs();
+       set_fs(get_ds());
+       /* The cast to a user pointer is valid due to the set_fs() */
+       res = inode->i_op->readlink(realdentry,
+                                   (char __user *)buf, PAGE_SIZE - 1);
+       set_fs(old_fs);
+       if (res < 0) {
+               free_page((unsigned long) buf);
+               goto err;
+       }
+       buf[res] = '\0';
+
+       return buf;
+
+err:
+       return ERR_PTR(res);
+}
+
+static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
+{
+       struct iattr attr = {
+               .ia_valid =
+                    ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET,
+               .ia_atime = stat->atime,
+               .ia_mtime = stat->mtime,
+       };
+
+       return notify_change(upperdentry, &attr, NULL);
+}
+
+int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
+{
+       int err = 0;
+
+       if (!S_ISLNK(stat->mode)) {
+               struct iattr attr = {
+                       .ia_valid = ATTR_MODE,
+                       .ia_mode = stat->mode,
+               };
+               err = notify_change(upperdentry, &attr, NULL);
+       }
+       if (!err) {
+               struct iattr attr = {
+                       .ia_valid = ATTR_UID | ATTR_GID,
+                       .ia_uid = stat->uid,
+                       .ia_gid = stat->gid,
+               };
+               err = notify_change(upperdentry, &attr, NULL);
+       }
+       if (!err)
+               ovl_set_timestamps(upperdentry, stat);
+
+       return err;
+
+}
+
+static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
+                             struct dentry *dentry, struct path *lowerpath,
+                             struct kstat *stat, struct iattr *attr,
+                             const char *link)
+{
+       struct inode *wdir = workdir->d_inode;
+       struct inode *udir = upperdir->d_inode;
+       struct dentry *newdentry = NULL;
+       struct dentry *upper = NULL;
+       umode_t mode = stat->mode;
+       int err;
+
+       newdentry = ovl_lookup_temp(workdir, dentry);
+       err = PTR_ERR(newdentry);
+       if (IS_ERR(newdentry))
+               goto out;
+
+       upper = lookup_one_len(dentry->d_name.name, upperdir,
+                              dentry->d_name.len);
+       err = PTR_ERR(upper);
+       if (IS_ERR(upper))
+               goto out1;
+
+       /* Can't properly set mode on creation because of the umask */
+       stat->mode &= S_IFMT;
+       err = ovl_create_real(wdir, newdentry, stat, link, NULL, true);
+       stat->mode = mode;
+       if (err)
+               goto out2;
+
+       if (S_ISREG(stat->mode)) {
+               struct path upperpath;
+               ovl_path_upper(dentry, &upperpath);
+               BUG_ON(upperpath.dentry != NULL);
+               upperpath.dentry = newdentry;
+
+               err = ovl_copy_up_data(lowerpath, &upperpath, stat->size);
+               if (err)
+                       goto out_cleanup;
+       }
+
+       err = ovl_copy_xattr(lowerpath->dentry, newdentry);
+       if (err)
+               goto out_cleanup;
+
+       mutex_lock(&newdentry->d_inode->i_mutex);
+       err = ovl_set_attr(newdentry, stat);
+       if (!err && attr)
+               err = notify_change(newdentry, attr, NULL);
+       mutex_unlock(&newdentry->d_inode->i_mutex);
+       if (err)
+               goto out_cleanup;
+
+       err = ovl_do_rename(wdir, newdentry, udir, upper, 0);
+       if (err)
+               goto out_cleanup;
+
+       ovl_dentry_update(dentry, newdentry);
+       newdentry = NULL;
+
+       /*
+        * Non-directores become opaque when copied up.
+        */
+       if (!S_ISDIR(stat->mode))
+               ovl_dentry_set_opaque(dentry, true);
+out2:
+       dput(upper);
+out1:
+       dput(newdentry);
+out:
+       return err;
+
+out_cleanup:
+       ovl_cleanup(wdir, newdentry);
+       goto out;
+}
+
+/*
+ * Copy up a single dentry
+ *
+ * Directory renames only allowed on "pure upper" (already created on
+ * upper filesystem, never copied up).  Directories which are on lower or
+ * are merged may not be renamed.  For these -EXDEV is returned and
+ * userspace has to deal with it.  This means, when copying up a
+ * directory we can rely on it and ancestors being stable.
+ *
+ * Non-directory renames start with copy up of source if necessary.  The
+ * actual rename will only proceed once the copy up was successful.  Copy
+ * up uses upper parent i_mutex for exclusion.  Since rename can change
+ * d_parent it is possible that the copy up will lock the old parent.  At
+ * that point the file will have already been copied up anyway.
+ */
+int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
+                   struct path *lowerpath, struct kstat *stat,
+                   struct iattr *attr)
+{
+       struct dentry *workdir = ovl_workdir(dentry);
+       int err;
+       struct kstat pstat;
+       struct path parentpath;
+       struct dentry *upperdir;
+       struct dentry *upperdentry;
+       const struct cred *old_cred;
+       struct cred *override_cred;
+       char *link = NULL;
+
+       ovl_path_upper(parent, &parentpath);
+       upperdir = parentpath.dentry;
+
+       err = vfs_getattr(&parentpath, &pstat);
+       if (err)
+               return err;
+
+       if (S_ISLNK(stat->mode)) {
+               link = ovl_read_symlink(lowerpath->dentry);
+               if (IS_ERR(link))
+                       return PTR_ERR(link);
+       }
+
+       err = -ENOMEM;
+       override_cred = prepare_creds();
+       if (!override_cred)
+               goto out_free_link;
+
+       override_cred->fsuid = stat->uid;
+       override_cred->fsgid = stat->gid;
+       /*
+        * CAP_SYS_ADMIN for copying up extended attributes
+        * CAP_DAC_OVERRIDE for create
+        * CAP_FOWNER for chmod, timestamp update
+        * CAP_FSETID for chmod
+        * CAP_CHOWN for chown
+        * CAP_MKNOD for mknod
+        */
+       cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+       cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+       cap_raise(override_cred->cap_effective, CAP_FOWNER);
+       cap_raise(override_cred->cap_effective, CAP_FSETID);
+       cap_raise(override_cred->cap_effective, CAP_CHOWN);
+       cap_raise(override_cred->cap_effective, CAP_MKNOD);
+       old_cred = override_creds(override_cred);
+
+       err = -EIO;
+       if (lock_rename(workdir, upperdir) != NULL) {
+               pr_err("overlayfs: failed to lock workdir+upperdir\n");
+               goto out_unlock;
+       }
+       upperdentry = ovl_dentry_upper(dentry);
+       if (upperdentry) {
+               unlock_rename(workdir, upperdir);
+               err = 0;
+               /* Raced with another copy-up?  Do the setattr here */
+               if (attr) {
+                       mutex_lock(&upperdentry->d_inode->i_mutex);
+                       err = notify_change(upperdentry, attr, NULL);
+                       mutex_unlock(&upperdentry->d_inode->i_mutex);
+               }
+               goto out_put_cred;
+       }
+
+       err = ovl_copy_up_locked(workdir, upperdir, dentry, lowerpath,
+                                stat, attr, link);
+       if (!err) {
+               /* Restore timestamps on parent (best effort) */
+               ovl_set_timestamps(upperdir, &pstat);
+       }
+out_unlock:
+       unlock_rename(workdir, upperdir);
+out_put_cred:
+       revert_creds(old_cred);
+       put_cred(override_cred);
+
+out_free_link:
+       if (link)
+               free_page((unsigned long) link);
+
+       return err;
+}
+
+int ovl_copy_up(struct dentry *dentry)
+{
+       int err;
+
+       err = 0;
+       while (!err) {
+               struct dentry *next;
+               struct dentry *parent;
+               struct path lowerpath;
+               struct kstat stat;
+               enum ovl_path_type type = ovl_path_type(dentry);
+
+               if (type != OVL_PATH_LOWER)
+                       break;
+
+               next = dget(dentry);
+               /* find the topmost dentry not yet copied up */
+               for (;;) {
+                       parent = dget_parent(next);
+
+                       type = ovl_path_type(parent);
+                       if (type != OVL_PATH_LOWER)
+                               break;
+
+                       dput(next);
+                       next = parent;
+               }
+
+               ovl_path_lower(next, &lowerpath);
+               err = vfs_getattr(&lowerpath, &stat);
+               if (!err)
+                       err = ovl_copy_up_one(parent, next, &lowerpath, &stat, NULL);
+
+               dput(parent);
+               dput(next);
+       }
+
+       return err;
+}
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
new file mode 100644 (file)
index 0000000..8ffc4b9
--- /dev/null
@@ -0,0 +1,928 @@
+/*
+ *
+ * Copyright (C) 2011 Novell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/xattr.h>
+#include <linux/security.h>
+#include <linux/cred.h>
+#include "overlayfs.h"
+
+void ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
+{
+       int err;
+
+       dget(wdentry);
+       if (S_ISDIR(wdentry->d_inode->i_mode))
+               err = ovl_do_rmdir(wdir, wdentry);
+       else
+               err = ovl_do_unlink(wdir, wdentry);
+       dput(wdentry);
+
+       if (err) {
+               pr_err("overlayfs: cleanup of '%pd2' failed (%i)\n",
+                      wdentry, err);
+       }
+}
+
+struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry)
+{
+       struct dentry *temp;
+       char name[20];
+
+       snprintf(name, sizeof(name), "#%lx", (unsigned long) dentry);
+
+       temp = lookup_one_len(name, workdir, strlen(name));
+       if (!IS_ERR(temp) && temp->d_inode) {
+               pr_err("overlayfs: workdir/%s already exists\n", name);
+               dput(temp);
+               temp = ERR_PTR(-EIO);
+       }
+
+       return temp;
+}
+
+/* caller holds i_mutex on workdir */
+static struct dentry *ovl_whiteout(struct dentry *workdir,
+                                  struct dentry *dentry)
+{
+       int err;
+       struct dentry *whiteout;
+       struct inode *wdir = workdir->d_inode;
+
+       whiteout = ovl_lookup_temp(workdir, dentry);
+       if (IS_ERR(whiteout))
+               return whiteout;
+
+       err = ovl_do_whiteout(wdir, whiteout);
+       if (err) {
+               dput(whiteout);
+               whiteout = ERR_PTR(err);
+       }
+
+       return whiteout;
+}
+
+int ovl_create_real(struct inode *dir, struct dentry *newdentry,
+                   struct kstat *stat, const char *link,
+                   struct dentry *hardlink, bool debug)
+{
+       int err;
+
+       if (newdentry->d_inode)
+               return -ESTALE;
+
+       if (hardlink) {
+               err = ovl_do_link(hardlink, dir, newdentry, debug);
+       } else {
+               switch (stat->mode & S_IFMT) {
+               case S_IFREG:
+                       err = ovl_do_create(dir, newdentry, stat->mode, debug);
+                       break;
+
+               case S_IFDIR:
+                       err = ovl_do_mkdir(dir, newdentry, stat->mode, debug);
+                       break;
+
+               case S_IFCHR:
+               case S_IFBLK:
+               case S_IFIFO:
+               case S_IFSOCK:
+                       err = ovl_do_mknod(dir, newdentry,
+                                          stat->mode, stat->rdev, debug);
+                       break;
+
+               case S_IFLNK:
+                       err = ovl_do_symlink(dir, newdentry, link, debug);
+                       break;
+
+               default:
+                       err = -EPERM;
+               }
+       }
+       if (!err && WARN_ON(!newdentry->d_inode)) {
+               /*
+                * Not quite sure if non-instantiated dentry is legal or not.
+                * VFS doesn't seem to care so check and warn here.
+                */
+               err = -ENOENT;
+       }
+       return err;
+}
+
+static int ovl_set_opaque(struct dentry *upperdentry)
+{
+       return ovl_do_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0);
+}
+
+static void ovl_remove_opaque(struct dentry *upperdentry)
+{
+       int err;
+
+       err = ovl_do_removexattr(upperdentry, ovl_opaque_xattr);
+       if (err) {
+               pr_warn("overlayfs: failed to remove opaque from '%s' (%i)\n",
+                       upperdentry->d_name.name, err);
+       }
+}
+
+static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                        struct kstat *stat)
+{
+       int err;
+       enum ovl_path_type type;
+       struct path realpath;
+
+       type = ovl_path_real(dentry, &realpath);
+       err = vfs_getattr(&realpath, stat);
+       if (err)
+               return err;
+
+       stat->dev = dentry->d_sb->s_dev;
+       stat->ino = dentry->d_inode->i_ino;
+
+       /*
+        * It's probably not worth it to count subdirs to get the
+        * correct link count.  nlink=1 seems to pacify 'find' and
+        * other utilities.
+        */
+       if (type == OVL_PATH_MERGE)
+               stat->nlink = 1;
+
+       return 0;
+}
+
+static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
+                           struct kstat *stat, const char *link,
+                           struct dentry *hardlink)
+{
+       struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+       struct inode *udir = upperdir->d_inode;
+       struct dentry *newdentry;
+       int err;
+
+       mutex_lock_nested(&udir->i_mutex, I_MUTEX_PARENT);
+       newdentry = lookup_one_len(dentry->d_name.name, upperdir,
+                                  dentry->d_name.len);
+       err = PTR_ERR(newdentry);
+       if (IS_ERR(newdentry))
+               goto out_unlock;
+       err = ovl_create_real(udir, newdentry, stat, link, hardlink, false);
+       if (err)
+               goto out_dput;
+
+       ovl_dentry_version_inc(dentry->d_parent);
+       ovl_dentry_update(dentry, newdentry);
+       ovl_copyattr(newdentry->d_inode, inode);
+       d_instantiate(dentry, inode);
+       newdentry = NULL;
+out_dput:
+       dput(newdentry);
+out_unlock:
+       mutex_unlock(&udir->i_mutex);
+       return err;
+}
+
+static int ovl_lock_rename_workdir(struct dentry *workdir,
+                                  struct dentry *upperdir)
+{
+       /* Workdir should not be the same as upperdir */
+       if (workdir == upperdir)
+               goto err;
+
+       /* Workdir should not be subdir of upperdir and vice versa */
+       if (lock_rename(workdir, upperdir) != NULL)
+               goto err_unlock;
+
+       return 0;
+
+err_unlock:
+       unlock_rename(workdir, upperdir);
+err:
+       pr_err("overlayfs: failed to lock workdir+upperdir\n");
+       return -EIO;
+}
+
+static struct dentry *ovl_clear_empty(struct dentry *dentry,
+                                     struct list_head *list)
+{
+       struct dentry *workdir = ovl_workdir(dentry);
+       struct inode *wdir = workdir->d_inode;
+       struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+       struct inode *udir = upperdir->d_inode;
+       struct path upperpath;
+       struct dentry *upper;
+       struct dentry *opaquedir;
+       struct kstat stat;
+       int err;
+
+       err = ovl_lock_rename_workdir(workdir, upperdir);
+       if (err)
+               goto out;
+
+       ovl_path_upper(dentry, &upperpath);
+       err = vfs_getattr(&upperpath, &stat);
+       if (err)
+               goto out_unlock;
+
+       err = -ESTALE;
+       if (!S_ISDIR(stat.mode))
+               goto out_unlock;
+       upper = upperpath.dentry;
+       if (upper->d_parent->d_inode != udir)
+               goto out_unlock;
+
+       opaquedir = ovl_lookup_temp(workdir, dentry);
+       err = PTR_ERR(opaquedir);
+       if (IS_ERR(opaquedir))
+               goto out_unlock;
+
+       err = ovl_create_real(wdir, opaquedir, &stat, NULL, NULL, true);
+       if (err)
+               goto out_dput;
+
+       err = ovl_copy_xattr(upper, opaquedir);
+       if (err)
+               goto out_cleanup;
+
+       err = ovl_set_opaque(opaquedir);
+       if (err)
+               goto out_cleanup;
+
+       mutex_lock(&opaquedir->d_inode->i_mutex);
+       err = ovl_set_attr(opaquedir, &stat);
+       mutex_unlock(&opaquedir->d_inode->i_mutex);
+       if (err)
+               goto out_cleanup;
+
+       err = ovl_do_rename(wdir, opaquedir, udir, upper, RENAME_EXCHANGE);
+       if (err)
+               goto out_cleanup;
+
+       ovl_cleanup_whiteouts(upper, list);
+       ovl_cleanup(wdir, upper);
+       unlock_rename(workdir, upperdir);
+
+       /* dentry's upper doesn't match now, get rid of it */
+       d_drop(dentry);
+
+       return opaquedir;
+
+out_cleanup:
+       ovl_cleanup(wdir, opaquedir);
+out_dput:
+       dput(opaquedir);
+out_unlock:
+       unlock_rename(workdir, upperdir);
+out:
+       return ERR_PTR(err);
+}
+
+static struct dentry *ovl_check_empty_and_clear(struct dentry *dentry)
+{
+       int err;
+       struct dentry *ret = NULL;
+       LIST_HEAD(list);
+
+       err = ovl_check_empty_dir(dentry, &list);
+       if (err)
+               ret = ERR_PTR(err);
+       else {
+               /*
+                * If no upperdentry then skip clearing whiteouts.
+                *
+                * Can race with copy-up, since we don't hold the upperdir
+                * mutex.  Doesn't matter, since copy-up can't create a
+                * non-empty directory from an empty one.
+                */
+               if (ovl_dentry_upper(dentry))
+                       ret = ovl_clear_empty(dentry, &list);
+       }
+
+       ovl_cache_free(&list);
+
+       return ret;
+}
+
+static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
+                                   struct kstat *stat, const char *link,
+                                   struct dentry *hardlink)
+{
+       struct dentry *workdir = ovl_workdir(dentry);
+       struct inode *wdir = workdir->d_inode;
+       struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+       struct inode *udir = upperdir->d_inode;
+       struct dentry *upper;
+       struct dentry *newdentry;
+       int err;
+
+       err = ovl_lock_rename_workdir(workdir, upperdir);
+       if (err)
+               goto out;
+
+       newdentry = ovl_lookup_temp(workdir, dentry);
+       err = PTR_ERR(newdentry);
+       if (IS_ERR(newdentry))
+               goto out_unlock;
+
+       upper = lookup_one_len(dentry->d_name.name, upperdir,
+                              dentry->d_name.len);
+       err = PTR_ERR(upper);
+       if (IS_ERR(upper))
+               goto out_dput;
+
+       err = ovl_create_real(wdir, newdentry, stat, link, hardlink, true);
+       if (err)
+               goto out_dput2;
+
+       if (S_ISDIR(stat->mode)) {
+               err = ovl_set_opaque(newdentry);
+               if (err)
+                       goto out_cleanup;
+
+               err = ovl_do_rename(wdir, newdentry, udir, upper,
+                                   RENAME_EXCHANGE);
+               if (err)
+                       goto out_cleanup;
+
+               ovl_cleanup(wdir, upper);
+       } else {
+               err = ovl_do_rename(wdir, newdentry, udir, upper, 0);
+               if (err)
+                       goto out_cleanup;
+       }
+       ovl_dentry_version_inc(dentry->d_parent);
+       ovl_dentry_update(dentry, newdentry);
+       ovl_copyattr(newdentry->d_inode, inode);
+       d_instantiate(dentry, inode);
+       newdentry = NULL;
+out_dput2:
+       dput(upper);
+out_dput:
+       dput(newdentry);
+out_unlock:
+       unlock_rename(workdir, upperdir);
+out:
+       return err;
+
+out_cleanup:
+       ovl_cleanup(wdir, newdentry);
+       goto out_dput2;
+}
+
+static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
+                             const char *link, struct dentry *hardlink)
+{
+       int err;
+       struct inode *inode;
+       struct kstat stat = {
+               .mode = mode,
+               .rdev = rdev,
+       };
+
+       err = -ENOMEM;
+       inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata);
+       if (!inode)
+               goto out;
+
+       err = ovl_copy_up(dentry->d_parent);
+       if (err)
+               goto out_iput;
+
+       if (!ovl_dentry_is_opaque(dentry)) {
+               err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
+       } else {
+               const struct cred *old_cred;
+               struct cred *override_cred;
+
+               err = -ENOMEM;
+               override_cred = prepare_creds();
+               if (!override_cred)
+                       goto out_iput;
+
+               /*
+                * CAP_SYS_ADMIN for setting opaque xattr
+                * CAP_DAC_OVERRIDE for create in workdir, rename
+                * CAP_FOWNER for removing whiteout from sticky dir
+                */
+               cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+               cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+               cap_raise(override_cred->cap_effective, CAP_FOWNER);
+               old_cred = override_creds(override_cred);
+
+               err = ovl_create_over_whiteout(dentry, inode, &stat, link,
+                                              hardlink);
+
+               revert_creds(old_cred);
+               put_cred(override_cred);
+       }
+
+       if (!err)
+               inode = NULL;
+out_iput:
+       iput(inode);
+out:
+       return err;
+}
+
+static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
+                            const char *link)
+{
+       int err;
+
+       err = ovl_want_write(dentry);
+       if (!err) {
+               err = ovl_create_or_link(dentry, mode, rdev, link, NULL);
+               ovl_drop_write(dentry);
+       }
+
+       return err;
+}
+
+static int ovl_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+                     bool excl)
+{
+       return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL);
+}
+
+static int ovl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+       return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL);
+}
+
+static int ovl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+                    dev_t rdev)
+{
+       /* Don't allow creation of "whiteout" on overlay */
+       if (S_ISCHR(mode) && rdev == WHITEOUT_DEV)
+               return -EPERM;
+
+       return ovl_create_object(dentry, mode, rdev, NULL);
+}
+
+static int ovl_symlink(struct inode *dir, struct dentry *dentry,
+                      const char *link)
+{
+       return ovl_create_object(dentry, S_IFLNK, 0, link);
+}
+
+static int ovl_link(struct dentry *old, struct inode *newdir,
+                   struct dentry *new)
+{
+       int err;
+       struct dentry *upper;
+
+       err = ovl_want_write(old);
+       if (err)
+               goto out;
+
+       err = ovl_copy_up(old);
+       if (err)
+               goto out_drop_write;
+
+       upper = ovl_dentry_upper(old);
+       err = ovl_create_or_link(new, upper->d_inode->i_mode, 0, NULL, upper);
+
+out_drop_write:
+       ovl_drop_write(old);
+out:
+       return err;
+}
+
+static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
+{
+       struct dentry *workdir = ovl_workdir(dentry);
+       struct inode *wdir = workdir->d_inode;
+       struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+       struct inode *udir = upperdir->d_inode;
+       struct dentry *whiteout;
+       struct dentry *upper;
+       struct dentry *opaquedir = NULL;
+       int err;
+
+       if (is_dir) {
+               opaquedir = ovl_check_empty_and_clear(dentry);
+               err = PTR_ERR(opaquedir);
+               if (IS_ERR(opaquedir))
+                       goto out;
+       }
+
+       err = ovl_lock_rename_workdir(workdir, upperdir);
+       if (err)
+               goto out_dput;
+
+       whiteout = ovl_whiteout(workdir, dentry);
+       err = PTR_ERR(whiteout);
+       if (IS_ERR(whiteout))
+               goto out_unlock;
+
+       upper = ovl_dentry_upper(dentry);
+       if (!upper) {
+               upper = lookup_one_len(dentry->d_name.name, upperdir,
+                                      dentry->d_name.len);
+               err = PTR_ERR(upper);
+               if (IS_ERR(upper))
+                       goto kill_whiteout;
+
+               err = ovl_do_rename(wdir, whiteout, udir, upper, 0);
+               dput(upper);
+               if (err)
+                       goto kill_whiteout;
+       } else {
+               int flags = 0;
+
+               if (opaquedir)
+                       upper = opaquedir;
+               err = -ESTALE;
+               if (upper->d_parent != upperdir)
+                       goto kill_whiteout;
+
+               if (is_dir)
+                       flags |= RENAME_EXCHANGE;
+
+               err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
+               if (err)
+                       goto kill_whiteout;
+
+               if (is_dir)
+                       ovl_cleanup(wdir, upper);
+       }
+       ovl_dentry_version_inc(dentry->d_parent);
+out_d_drop:
+       d_drop(dentry);
+       dput(whiteout);
+out_unlock:
+       unlock_rename(workdir, upperdir);
+out_dput:
+       dput(opaquedir);
+out:
+       return err;
+
+kill_whiteout:
+       ovl_cleanup(wdir, whiteout);
+       goto out_d_drop;
+}
+
+static int ovl_remove_upper(struct dentry *dentry, bool is_dir)
+{
+       struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
+       struct inode *dir = upperdir->d_inode;
+       struct dentry *upper = ovl_dentry_upper(dentry);
+       int err;
+
+       mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
+       err = -ESTALE;
+       if (upper->d_parent == upperdir) {
+               /* Don't let d_delete() think it can reset d_inode */
+               dget(upper);
+               if (is_dir)
+                       err = vfs_rmdir(dir, upper);
+               else
+                       err = vfs_unlink(dir, upper, NULL);
+               dput(upper);
+               ovl_dentry_version_inc(dentry->d_parent);
+       }
+
+       /*
+        * Keeping this dentry hashed would mean having to release
+        * upperpath/lowerpath, which could only be done if we are the
+        * sole user of this dentry.  Too tricky...  Just unhash for
+        * now.
+        */
+       d_drop(dentry);
+       mutex_unlock(&dir->i_mutex);
+
+       return err;
+}
+
+static inline int ovl_check_sticky(struct dentry *dentry)
+{
+       struct inode *dir = ovl_dentry_real(dentry->d_parent)->d_inode;
+       struct inode *inode = ovl_dentry_real(dentry)->d_inode;
+
+       if (check_sticky(dir, inode))
+               return -EPERM;
+
+       return 0;
+}
+
+static int ovl_do_remove(struct dentry *dentry, bool is_dir)
+{
+       enum ovl_path_type type;
+       int err;
+
+       err = ovl_check_sticky(dentry);
+       if (err)
+               goto out;
+
+       err = ovl_want_write(dentry);
+       if (err)
+               goto out;
+
+       err = ovl_copy_up(dentry->d_parent);
+       if (err)
+               goto out_drop_write;
+
+       type = ovl_path_type(dentry);
+       if (type == OVL_PATH_PURE_UPPER) {
+               err = ovl_remove_upper(dentry, is_dir);
+       } else {
+               const struct cred *old_cred;
+               struct cred *override_cred;
+
+               err = -ENOMEM;
+               override_cred = prepare_creds();
+               if (!override_cred)
+                       goto out_drop_write;
+
+               /*
+                * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir
+                * CAP_DAC_OVERRIDE for create in workdir, rename
+                * CAP_FOWNER for removing whiteout from sticky dir
+                * CAP_FSETID for chmod of opaque dir
+                * CAP_CHOWN for chown of opaque dir
+                */
+               cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+               cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+               cap_raise(override_cred->cap_effective, CAP_FOWNER);
+               cap_raise(override_cred->cap_effective, CAP_FSETID);
+               cap_raise(override_cred->cap_effective, CAP_CHOWN);
+               old_cred = override_creds(override_cred);
+
+               err = ovl_remove_and_whiteout(dentry, is_dir);
+
+               revert_creds(old_cred);
+               put_cred(override_cred);
+       }
+out_drop_write:
+       ovl_drop_write(dentry);
+out:
+       return err;
+}
+
+static int ovl_unlink(struct inode *dir, struct dentry *dentry)
+{
+       return ovl_do_remove(dentry, false);
+}
+
+static int ovl_rmdir(struct inode *dir, struct dentry *dentry)
+{
+       return ovl_do_remove(dentry, true);
+}
+
+static int ovl_rename2(struct inode *olddir, struct dentry *old,
+                      struct inode *newdir, struct dentry *new,
+                      unsigned int flags)
+{
+       int err;
+       enum ovl_path_type old_type;
+       enum ovl_path_type new_type;
+       struct dentry *old_upperdir;
+       struct dentry *new_upperdir;
+       struct dentry *olddentry;
+       struct dentry *newdentry;
+       struct dentry *trap;
+       bool old_opaque;
+       bool new_opaque;
+       bool new_create = false;
+       bool cleanup_whiteout = false;
+       bool overwrite = !(flags & RENAME_EXCHANGE);
+       bool is_dir = S_ISDIR(old->d_inode->i_mode);
+       bool new_is_dir = false;
+       struct dentry *opaquedir = NULL;
+       const struct cred *old_cred = NULL;
+       struct cred *override_cred = NULL;
+
+       err = -EINVAL;
+       if (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE))
+               goto out;
+
+       flags &= ~RENAME_NOREPLACE;
+
+       err = ovl_check_sticky(old);
+       if (err)
+               goto out;
+
+       /* Don't copy up directory trees */
+       old_type = ovl_path_type(old);
+       err = -EXDEV;
+       if ((old_type == OVL_PATH_LOWER || old_type == OVL_PATH_MERGE) && is_dir)
+               goto out;
+
+       if (new->d_inode) {
+               err = ovl_check_sticky(new);
+               if (err)
+                       goto out;
+
+               if (S_ISDIR(new->d_inode->i_mode))
+                       new_is_dir = true;
+
+               new_type = ovl_path_type(new);
+               err = -EXDEV;
+               if (!overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir)
+                       goto out;
+
+               err = 0;
+               if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) {
+                       if (ovl_dentry_lower(old)->d_inode ==
+                           ovl_dentry_lower(new)->d_inode)
+                               goto out;
+               }
+               if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) {
+                       if (ovl_dentry_upper(old)->d_inode ==
+                           ovl_dentry_upper(new)->d_inode)
+                               goto out;
+               }
+       } else {
+               if (ovl_dentry_is_opaque(new))
+                       new_type = OVL_PATH_UPPER;
+               else
+                       new_type = OVL_PATH_PURE_UPPER;
+       }
+
+       err = ovl_want_write(old);
+       if (err)
+               goto out;
+
+       err = ovl_copy_up(old);
+       if (err)
+               goto out_drop_write;
+
+       err = ovl_copy_up(new->d_parent);
+       if (err)
+               goto out_drop_write;
+       if (!overwrite) {
+               err = ovl_copy_up(new);
+               if (err)
+                       goto out_drop_write;
+       }
+
+       old_opaque = old_type != OVL_PATH_PURE_UPPER;
+       new_opaque = new_type != OVL_PATH_PURE_UPPER;
+
+       if (old_opaque || new_opaque) {
+               err = -ENOMEM;
+               override_cred = prepare_creds();
+               if (!override_cred)
+                       goto out_drop_write;
+
+               /*
+                * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir
+                * CAP_DAC_OVERRIDE for create in workdir
+                * CAP_FOWNER for removing whiteout from sticky dir
+                * CAP_FSETID for chmod of opaque dir
+                * CAP_CHOWN for chown of opaque dir
+                */
+               cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+               cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+               cap_raise(override_cred->cap_effective, CAP_FOWNER);
+               cap_raise(override_cred->cap_effective, CAP_FSETID);
+               cap_raise(override_cred->cap_effective, CAP_CHOWN);
+               old_cred = override_creds(override_cred);
+       }
+
+       if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) {
+               opaquedir = ovl_check_empty_and_clear(new);
+               err = PTR_ERR(opaquedir);
+               if (IS_ERR(opaquedir)) {
+                       opaquedir = NULL;
+                       goto out_revert_creds;
+               }
+       }
+
+       if (overwrite) {
+               if (old_opaque) {
+                       if (new->d_inode || !new_opaque) {
+                               /* Whiteout source */
+                               flags |= RENAME_WHITEOUT;
+                       } else {
+                               /* Switch whiteouts */
+                               flags |= RENAME_EXCHANGE;
+                       }
+               } else if (is_dir && !new->d_inode && new_opaque) {
+                       flags |= RENAME_EXCHANGE;
+                       cleanup_whiteout = true;
+               }
+       }
+
+       old_upperdir = ovl_dentry_upper(old->d_parent);
+       new_upperdir = ovl_dentry_upper(new->d_parent);
+
+       trap = lock_rename(new_upperdir, old_upperdir);
+
+       olddentry = ovl_dentry_upper(old);
+       newdentry = ovl_dentry_upper(new);
+       if (newdentry) {
+               if (opaquedir) {
+                       newdentry = opaquedir;
+                       opaquedir = NULL;
+               } else {
+                       dget(newdentry);
+               }
+       } else {
+               new_create = true;
+               newdentry = lookup_one_len(new->d_name.name, new_upperdir,
+                                          new->d_name.len);
+               err = PTR_ERR(newdentry);
+               if (IS_ERR(newdentry))
+                       goto out_unlock;
+       }
+
+       err = -ESTALE;
+       if (olddentry->d_parent != old_upperdir)
+               goto out_dput;
+       if (newdentry->d_parent != new_upperdir)
+               goto out_dput;
+       if (olddentry == trap)
+               goto out_dput;
+       if (newdentry == trap)
+               goto out_dput;
+
+       if (is_dir && !old_opaque && new_opaque) {
+               err = ovl_set_opaque(olddentry);
+               if (err)
+                       goto out_dput;
+       }
+       if (!overwrite && new_is_dir && old_opaque && !new_opaque) {
+               err = ovl_set_opaque(newdentry);
+               if (err)
+                       goto out_dput;
+       }
+
+       if (old_opaque || new_opaque) {
+               err = ovl_do_rename(old_upperdir->d_inode, olddentry,
+                                   new_upperdir->d_inode, newdentry,
+                                   flags);
+       } else {
+               /* No debug for the plain case */
+               BUG_ON(flags & ~RENAME_EXCHANGE);
+               err = vfs_rename(old_upperdir->d_inode, olddentry,
+                                new_upperdir->d_inode, newdentry,
+                                NULL, flags);
+       }
+
+       if (err) {
+               if (is_dir && !old_opaque && new_opaque)
+                       ovl_remove_opaque(olddentry);
+               if (!overwrite && new_is_dir && old_opaque && !new_opaque)
+                       ovl_remove_opaque(newdentry);
+               goto out_dput;
+       }
+
+       if (is_dir && old_opaque && !new_opaque)
+               ovl_remove_opaque(olddentry);
+       if (!overwrite && new_is_dir && !old_opaque && new_opaque)
+               ovl_remove_opaque(newdentry);
+
+       if (old_opaque != new_opaque) {
+               ovl_dentry_set_opaque(old, new_opaque);
+               if (!overwrite)
+                       ovl_dentry_set_opaque(new, old_opaque);
+       }
+
+       if (cleanup_whiteout)
+               ovl_cleanup(old_upperdir->d_inode, newdentry);
+
+       ovl_dentry_version_inc(old->d_parent);
+       ovl_dentry_version_inc(new->d_parent);
+
+out_dput:
+       dput(newdentry);
+out_unlock:
+       unlock_rename(new_upperdir, old_upperdir);
+out_revert_creds:
+       if (old_opaque || new_opaque) {
+               revert_creds(old_cred);
+               put_cred(override_cred);
+       }
+out_drop_write:
+       ovl_drop_write(old);
+out:
+       dput(opaquedir);
+       return err;
+}
+
+const struct inode_operations ovl_dir_inode_operations = {
+       .lookup         = ovl_lookup,
+       .mkdir          = ovl_mkdir,
+       .symlink        = ovl_symlink,
+       .unlink         = ovl_unlink,
+       .rmdir          = ovl_rmdir,
+       .rename2        = ovl_rename2,
+       .link           = ovl_link,
+       .setattr        = ovl_setattr,
+       .create         = ovl_create,
+       .mknod          = ovl_mknod,
+       .permission     = ovl_permission,
+       .getattr        = ovl_dir_getattr,
+       .setxattr       = ovl_setxattr,
+       .getxattr       = ovl_getxattr,
+       .listxattr      = ovl_listxattr,
+       .removexattr    = ovl_removexattr,
+};
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
new file mode 100644 (file)
index 0000000..07d74b2
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ *
+ * Copyright (C) 2011 Novell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/xattr.h>
+#include "overlayfs.h"
+
+static int ovl_copy_up_last(struct dentry *dentry, struct iattr *attr,
+                           bool no_data)
+{
+       int err;
+       struct dentry *parent;
+       struct kstat stat;
+       struct path lowerpath;
+
+       parent = dget_parent(dentry);
+       err = ovl_copy_up(parent);
+       if (err)
+               goto out_dput_parent;
+
+       ovl_path_lower(dentry, &lowerpath);
+       err = vfs_getattr(&lowerpath, &stat);
+       if (err)
+               goto out_dput_parent;
+
+       if (no_data)
+               stat.size = 0;
+
+       err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat, attr);
+
+out_dput_parent:
+       dput(parent);
+       return err;
+}
+
+int ovl_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       int err;
+       struct dentry *upperdentry;
+
+       err = ovl_want_write(dentry);
+       if (err)
+               goto out;
+
+       upperdentry = ovl_dentry_upper(dentry);
+       if (upperdentry) {
+               mutex_lock(&upperdentry->d_inode->i_mutex);
+               err = notify_change(upperdentry, attr, NULL);
+               mutex_unlock(&upperdentry->d_inode->i_mutex);
+       } else {
+               err = ovl_copy_up_last(dentry, attr, false);
+       }
+       ovl_drop_write(dentry);
+out:
+       return err;
+}
+
+static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                        struct kstat *stat)
+{
+       struct path realpath;
+
+       ovl_path_real(dentry, &realpath);
+       return vfs_getattr(&realpath, stat);
+}
+
+int ovl_permission(struct inode *inode, int mask)
+{
+       struct ovl_entry *oe;
+       struct dentry *alias = NULL;
+       struct inode *realinode;
+       struct dentry *realdentry;
+       bool is_upper;
+       int err;
+
+       if (S_ISDIR(inode->i_mode)) {
+               oe = inode->i_private;
+       } else if (mask & MAY_NOT_BLOCK) {
+               return -ECHILD;
+       } else {
+               /*
+                * For non-directories find an alias and get the info
+                * from there.
+                */
+               alias = d_find_any_alias(inode);
+               if (WARN_ON(!alias))
+                       return -ENOENT;
+
+               oe = alias->d_fsdata;
+       }
+
+       realdentry = ovl_entry_real(oe, &is_upper);
+
+       /* Careful in RCU walk mode */
+       realinode = ACCESS_ONCE(realdentry->d_inode);
+       if (!realinode) {
+               WARN_ON(!(mask & MAY_NOT_BLOCK));
+               err = -ENOENT;
+               goto out_dput;
+       }
+
+       if (mask & MAY_WRITE) {
+               umode_t mode = realinode->i_mode;
+
+               /*
+                * Writes will always be redirected to upper layer, so
+                * ignore lower layer being read-only.
+                *
+                * If the overlay itself is read-only then proceed
+                * with the permission check, don't return EROFS.
+                * This will only happen if this is the lower layer of
+                * another overlayfs.
+                *
+                * If upper fs becomes read-only after the overlay was
+                * constructed return EROFS to prevent modification of
+                * upper layer.
+                */
+               err = -EROFS;
+               if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) &&
+                   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+                       goto out_dput;
+       }
+
+       err = __inode_permission(realinode, mask);
+out_dput:
+       dput(alias);
+       return err;
+}
+
+
+struct ovl_link_data {
+       struct dentry *realdentry;
+       void *cookie;
+};
+
+static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+       void *ret;
+       struct dentry *realdentry;
+       struct inode *realinode;
+
+       realdentry = ovl_dentry_real(dentry);
+       realinode = realdentry->d_inode;
+
+       if (WARN_ON(!realinode->i_op->follow_link))
+               return ERR_PTR(-EPERM);
+
+       ret = realinode->i_op->follow_link(realdentry, nd);
+       if (IS_ERR(ret))
+               return ret;
+
+       if (realinode->i_op->put_link) {
+               struct ovl_link_data *data;
+
+               data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL);
+               if (!data) {
+                       realinode->i_op->put_link(realdentry, nd, ret);
+                       return ERR_PTR(-ENOMEM);
+               }
+               data->realdentry = realdentry;
+               data->cookie = ret;
+
+               return data;
+       } else {
+               return NULL;
+       }
+}
+
+static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
+{
+       struct inode *realinode;
+       struct ovl_link_data *data = c;
+
+       if (!data)
+               return;
+
+       realinode = data->realdentry->d_inode;
+       realinode->i_op->put_link(data->realdentry, nd, data->cookie);
+       kfree(data);
+}
+
+static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
+{
+       struct path realpath;
+       struct inode *realinode;
+
+       ovl_path_real(dentry, &realpath);
+       realinode = realpath.dentry->d_inode;
+
+       if (!realinode->i_op->readlink)
+               return -EINVAL;
+
+       touch_atime(&realpath);
+
+       return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
+}
+
+
+static bool ovl_is_private_xattr(const char *name)
+{
+       return strncmp(name, "trusted.overlay.", 14) == 0;
+}
+
+int ovl_setxattr(struct dentry *dentry, const char *name,
+                const void *value, size_t size, int flags)
+{
+       int err;
+       struct dentry *upperdentry;
+
+       err = ovl_want_write(dentry);
+       if (err)
+               goto out;
+
+       err = -EPERM;
+       if (ovl_is_private_xattr(name))
+               goto out_drop_write;
+
+       err = ovl_copy_up(dentry);
+       if (err)
+               goto out_drop_write;
+
+       upperdentry = ovl_dentry_upper(dentry);
+       err = vfs_setxattr(upperdentry, name, value, size, flags);
+
+out_drop_write:
+       ovl_drop_write(dentry);
+out:
+       return err;
+}
+
+static bool ovl_need_xattr_filter(struct dentry *dentry,
+                                 enum ovl_path_type type)
+{
+       return type == OVL_PATH_UPPER && S_ISDIR(dentry->d_inode->i_mode);
+}
+
+ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
+                    void *value, size_t size)
+{
+       struct path realpath;
+       enum ovl_path_type type = ovl_path_real(dentry, &realpath);
+
+       if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
+               return -ENODATA;
+
+       return vfs_getxattr(realpath.dentry, name, value, size);
+}
+
+ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
+{
+       struct path realpath;
+       enum ovl_path_type type = ovl_path_real(dentry, &realpath);
+       ssize_t res;
+       int off;
+
+       res = vfs_listxattr(realpath.dentry, list, size);
+       if (res <= 0 || size == 0)
+               return res;
+
+       if (!ovl_need_xattr_filter(dentry, type))
+               return res;
+
+       /* filter out private xattrs */
+       for (off = 0; off < res;) {
+               char *s = list + off;
+               size_t slen = strlen(s) + 1;
+
+               BUG_ON(off + slen > res);
+
+               if (ovl_is_private_xattr(s)) {
+                       res -= slen;
+                       memmove(s, s + slen, res - off);
+               } else {
+                       off += slen;
+               }
+       }
+
+       return res;
+}
+
+int ovl_removexattr(struct dentry *dentry, const char *name)
+{
+       int err;
+       struct path realpath;
+       enum ovl_path_type type = ovl_path_real(dentry, &realpath);
+
+       err = ovl_want_write(dentry);
+       if (err)
+               goto out;
+
+       err = -ENODATA;
+       if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
+               goto out_drop_write;
+
+       if (type == OVL_PATH_LOWER) {
+               err = vfs_getxattr(realpath.dentry, name, NULL, 0);
+               if (err < 0)
+                       goto out_drop_write;
+
+               err = ovl_copy_up(dentry);
+               if (err)
+                       goto out_drop_write;
+
+               ovl_path_upper(dentry, &realpath);
+       }
+
+       err = vfs_removexattr(realpath.dentry, name);
+out_drop_write:
+       ovl_drop_write(dentry);
+out:
+       return err;
+}
+
+static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
+                                 struct dentry *realdentry)
+{
+       if (type != OVL_PATH_LOWER)
+               return false;
+
+       if (special_file(realdentry->d_inode->i_mode))
+               return false;
+
+       if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC))
+               return false;
+
+       return true;
+}
+
+static int ovl_dentry_open(struct dentry *dentry, struct file *file,
+                   const struct cred *cred)
+{
+       int err;
+       struct path realpath;
+       enum ovl_path_type type;
+       bool want_write = false;
+
+       type = ovl_path_real(dentry, &realpath);
+       if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) {
+               want_write = true;
+               err = ovl_want_write(dentry);
+               if (err)
+                       goto out;
+
+               if (file->f_flags & O_TRUNC)
+                       err = ovl_copy_up_last(dentry, NULL, true);
+               else
+                       err = ovl_copy_up(dentry);
+               if (err)
+                       goto out_drop_write;
+
+               ovl_path_upper(dentry, &realpath);
+       }
+
+       err = vfs_open(&realpath, file, cred);
+out_drop_write:
+       if (want_write)
+               ovl_drop_write(dentry);
+out:
+       return err;
+}
+
+static const struct inode_operations ovl_file_inode_operations = {
+       .setattr        = ovl_setattr,
+       .permission     = ovl_permission,
+       .getattr        = ovl_getattr,
+       .setxattr       = ovl_setxattr,
+       .getxattr       = ovl_getxattr,
+       .listxattr      = ovl_listxattr,
+       .removexattr    = ovl_removexattr,
+       .dentry_open    = ovl_dentry_open,
+};
+
+static const struct inode_operations ovl_symlink_inode_operations = {
+       .setattr        = ovl_setattr,
+       .follow_link    = ovl_follow_link,
+       .put_link       = ovl_put_link,
+       .readlink       = ovl_readlink,
+       .getattr        = ovl_getattr,
+       .setxattr       = ovl_setxattr,
+       .getxattr       = ovl_getxattr,
+       .listxattr      = ovl_listxattr,
+       .removexattr    = ovl_removexattr,
+};
+
+struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
+                           struct ovl_entry *oe)
+{
+       struct inode *inode;
+
+       inode = new_inode(sb);
+       if (!inode)
+               return NULL;
+
+       mode &= S_IFMT;
+
+       inode->i_ino = get_next_ino();
+       inode->i_mode = mode;
+       inode->i_flags |= S_NOATIME | S_NOCMTIME;
+
+       switch (mode) {
+       case S_IFDIR:
+               inode->i_private = oe;
+               inode->i_op = &ovl_dir_inode_operations;
+               inode->i_fop = &ovl_dir_operations;
+               break;
+
+       case S_IFLNK:
+               inode->i_op = &ovl_symlink_inode_operations;
+               break;
+
+       case S_IFREG:
+       case S_IFSOCK:
+       case S_IFBLK:
+       case S_IFCHR:
+       case S_IFIFO:
+               inode->i_op = &ovl_file_inode_operations;
+               break;
+
+       default:
+               WARN(1, "illegal file type: %i\n", mode);
+               iput(inode);
+               inode = NULL;
+       }
+
+       return inode;
+
+}
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
new file mode 100644 (file)
index 0000000..814bed3
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *
+ * Copyright (C) 2011 Novell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+
+struct ovl_entry;
+
+enum ovl_path_type {
+       OVL_PATH_PURE_UPPER,
+       OVL_PATH_UPPER,
+       OVL_PATH_MERGE,
+       OVL_PATH_LOWER,
+};
+
+extern const char *ovl_opaque_xattr;
+
+static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
+{
+       int err = vfs_rmdir(dir, dentry);
+       pr_debug("rmdir(%pd2) = %i\n", dentry, err);
+       return err;
+}
+
+static inline int ovl_do_unlink(struct inode *dir, struct dentry *dentry)
+{
+       int err = vfs_unlink(dir, dentry, NULL);
+       pr_debug("unlink(%pd2) = %i\n", dentry, err);
+       return err;
+}
+
+static inline int ovl_do_link(struct dentry *old_dentry, struct inode *dir,
+                             struct dentry *new_dentry, bool debug)
+{
+       int err = vfs_link(old_dentry, dir, new_dentry, NULL);
+       if (debug) {
+               pr_debug("link(%pd2, %pd2) = %i\n",
+                        old_dentry, new_dentry, err);
+       }
+       return err;
+}
+
+static inline int ovl_do_create(struct inode *dir, struct dentry *dentry,
+                            umode_t mode, bool debug)
+{
+       int err = vfs_create(dir, dentry, mode, true);
+       if (debug)
+               pr_debug("create(%pd2, 0%o) = %i\n", dentry, mode, err);
+       return err;
+}
+
+static inline int ovl_do_mkdir(struct inode *dir, struct dentry *dentry,
+                              umode_t mode, bool debug)
+{
+       int err = vfs_mkdir(dir, dentry, mode);
+       if (debug)
+               pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, err);
+       return err;
+}
+
+static inline int ovl_do_mknod(struct inode *dir, struct dentry *dentry,
+                              umode_t mode, dev_t dev, bool debug)
+{
+       int err = vfs_mknod(dir, dentry, mode, dev);
+       if (debug) {
+               pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n",
+                        dentry, mode, dev, err);
+       }
+       return err;
+}
+
+static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry,
+                                const char *oldname, bool debug)
+{
+       int err = vfs_symlink(dir, dentry, oldname);
+       if (debug)
+               pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err);
+       return err;
+}
+
+static inline int ovl_do_setxattr(struct dentry *dentry, const char *name,
+                                 const void *value, size_t size, int flags)
+{
+       int err = vfs_setxattr(dentry, name, value, size, flags);
+       pr_debug("setxattr(%pd2, \"%s\", \"%*s\", 0x%x) = %i\n",
+                dentry, name, (int) size, (char *) value, flags, err);
+       return err;
+}
+
+static inline int ovl_do_removexattr(struct dentry *dentry, const char *name)
+{
+       int err = vfs_removexattr(dentry, name);
+       pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err);
+       return err;
+}
+
+static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry,
+                               struct inode *newdir, struct dentry *newdentry,
+                               unsigned int flags)
+{
+       int err;
+
+       pr_debug("rename2(%pd2, %pd2, 0x%x)\n",
+                olddentry, newdentry, flags);
+
+       err = vfs_rename(olddir, olddentry, newdir, newdentry, NULL, flags);
+
+       if (err) {
+               pr_debug("...rename2(%pd2, %pd2, ...) = %i\n",
+                        olddentry, newdentry, err);
+       }
+       return err;
+}
+
+static inline int ovl_do_whiteout(struct inode *dir, struct dentry *dentry)
+{
+       int err = vfs_whiteout(dir, dentry);
+       pr_debug("whiteout(%pd2) = %i\n", dentry, err);
+       return err;
+}
+
+enum ovl_path_type ovl_path_type(struct dentry *dentry);
+u64 ovl_dentry_version_get(struct dentry *dentry);
+void ovl_dentry_version_inc(struct dentry *dentry);
+void ovl_path_upper(struct dentry *dentry, struct path *path);
+void ovl_path_lower(struct dentry *dentry, struct path *path);
+enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
+struct dentry *ovl_dentry_upper(struct dentry *dentry);
+struct dentry *ovl_dentry_lower(struct dentry *dentry);
+struct dentry *ovl_dentry_real(struct dentry *dentry);
+struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper);
+struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry);
+void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache);
+struct dentry *ovl_workdir(struct dentry *dentry);
+int ovl_want_write(struct dentry *dentry);
+void ovl_drop_write(struct dentry *dentry);
+bool ovl_dentry_is_opaque(struct dentry *dentry);
+void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque);
+bool ovl_is_whiteout(struct dentry *dentry);
+void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry);
+struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
+                         unsigned int flags);
+struct file *ovl_path_open(struct path *path, int flags);
+
+struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry,
+                               struct kstat *stat, const char *link);
+
+/* readdir.c */
+extern const struct file_operations ovl_dir_operations;
+int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list);
+void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list);
+void ovl_cache_free(struct list_head *list);
+
+/* inode.c */
+int ovl_setattr(struct dentry *dentry, struct iattr *attr);
+int ovl_permission(struct inode *inode, int mask);
+int ovl_setxattr(struct dentry *dentry, const char *name,
+                const void *value, size_t size, int flags);
+ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
+                    void *value, size_t size);
+ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
+int ovl_removexattr(struct dentry *dentry, const char *name);
+
+struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
+                           struct ovl_entry *oe);
+static inline void ovl_copyattr(struct inode *from, struct inode *to)
+{
+       to->i_uid = from->i_uid;
+       to->i_gid = from->i_gid;
+}
+
+/* dir.c */
+extern const struct inode_operations ovl_dir_inode_operations;
+struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry);
+int ovl_create_real(struct inode *dir, struct dentry *newdentry,
+                   struct kstat *stat, const char *link,
+                   struct dentry *hardlink, bool debug);
+void ovl_cleanup(struct inode *dir, struct dentry *dentry);
+
+/* copy_up.c */
+int ovl_copy_up(struct dentry *dentry);
+int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
+                   struct path *lowerpath, struct kstat *stat,
+                   struct iattr *attr);
+int ovl_copy_xattr(struct dentry *old, struct dentry *new);
+int ovl_set_attr(struct dentry *upper, struct kstat *stat);
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
new file mode 100644 (file)
index 0000000..ab1e3dc
--- /dev/null
@@ -0,0 +1,586 @@
+/*
+ *
+ * Copyright (C) 2011 Novell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+#include <linux/file.h>
+#include <linux/xattr.h>
+#include <linux/rbtree.h>
+#include <linux/security.h>
+#include <linux/cred.h>
+#include "overlayfs.h"
+
+struct ovl_cache_entry {
+       unsigned int len;
+       unsigned int type;
+       u64 ino;
+       struct list_head l_node;
+       struct rb_node node;
+       bool is_whiteout;
+       bool is_cursor;
+       char name[];
+};
+
+struct ovl_dir_cache {
+       long refcount;
+       u64 version;
+       struct list_head entries;
+};
+
+struct ovl_readdir_data {
+       struct dir_context ctx;
+       bool is_merge;
+       struct rb_root root;
+       struct list_head *list;
+       struct list_head middle;
+       int count;
+       int err;
+};
+
+struct ovl_dir_file {
+       bool is_real;
+       bool is_upper;
+       struct ovl_dir_cache *cache;
+       struct ovl_cache_entry cursor;
+       struct file *realfile;
+       struct file *upperfile;
+};
+
+static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n)
+{
+       return container_of(n, struct ovl_cache_entry, node);
+}
+
+static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root,
+                                                   const char *name, int len)
+{
+       struct rb_node *node = root->rb_node;
+       int cmp;
+
+       while (node) {
+               struct ovl_cache_entry *p = ovl_cache_entry_from_node(node);
+
+               cmp = strncmp(name, p->name, len);
+               if (cmp > 0)
+                       node = p->node.rb_right;
+               else if (cmp < 0 || len < p->len)
+                       node = p->node.rb_left;
+               else
+                       return p;
+       }
+
+       return NULL;
+}
+
+static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len,
+                                                  u64 ino, unsigned int d_type)
+{
+       struct ovl_cache_entry *p;
+       size_t size = offsetof(struct ovl_cache_entry, name[len + 1]);
+
+       p = kmalloc(size, GFP_KERNEL);
+       if (p) {
+               memcpy(p->name, name, len);
+               p->name[len] = '\0';
+               p->len = len;
+               p->type = d_type;
+               p->ino = ino;
+               p->is_whiteout = false;
+               p->is_cursor = false;
+       }
+
+       return p;
+}
+
+static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd,
+                                 const char *name, int len, u64 ino,
+                                 unsigned int d_type)
+{
+       struct rb_node **newp = &rdd->root.rb_node;
+       struct rb_node *parent = NULL;
+       struct ovl_cache_entry *p;
+
+       while (*newp) {
+               int cmp;
+               struct ovl_cache_entry *tmp;
+
+               parent = *newp;
+               tmp = ovl_cache_entry_from_node(*newp);
+               cmp = strncmp(name, tmp->name, len);
+               if (cmp > 0)
+                       newp = &tmp->node.rb_right;
+               else if (cmp < 0 || len < tmp->len)
+                       newp = &tmp->node.rb_left;
+               else
+                       return 0;
+       }
+
+       p = ovl_cache_entry_new(name, len, ino, d_type);
+       if (p == NULL)
+               return -ENOMEM;
+
+       list_add_tail(&p->l_node, rdd->list);
+       rb_link_node(&p->node, parent, newp);
+       rb_insert_color(&p->node, &rdd->root);
+
+       return 0;
+}
+
+static int ovl_fill_lower(struct ovl_readdir_data *rdd,
+                         const char *name, int namelen,
+                         loff_t offset, u64 ino, unsigned int d_type)
+{
+       struct ovl_cache_entry *p;
+
+       p = ovl_cache_entry_find(&rdd->root, name, namelen);
+       if (p) {
+               list_move_tail(&p->l_node, &rdd->middle);
+       } else {
+               p = ovl_cache_entry_new(name, namelen, ino, d_type);
+               if (p == NULL)
+                       rdd->err = -ENOMEM;
+               else
+                       list_add_tail(&p->l_node, &rdd->middle);
+       }
+
+       return rdd->err;
+}
+
+void ovl_cache_free(struct list_head *list)
+{
+       struct ovl_cache_entry *p;
+       struct ovl_cache_entry *n;
+
+       list_for_each_entry_safe(p, n, list, l_node)
+               kfree(p);
+
+       INIT_LIST_HEAD(list);
+}
+
+static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry)
+{
+       struct ovl_dir_cache *cache = od->cache;
+
+       list_del_init(&od->cursor.l_node);
+       WARN_ON(cache->refcount <= 0);
+       cache->refcount--;
+       if (!cache->refcount) {
+               if (ovl_dir_cache(dentry) == cache)
+                       ovl_set_dir_cache(dentry, NULL);
+
+               ovl_cache_free(&cache->entries);
+               kfree(cache);
+       }
+}
+
+static int ovl_fill_merge(void *buf, const char *name, int namelen,
+                         loff_t offset, u64 ino, unsigned int d_type)
+{
+       struct ovl_readdir_data *rdd = buf;
+
+       rdd->count++;
+       if (!rdd->is_merge)
+               return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type);
+       else
+               return ovl_fill_lower(rdd, name, namelen, offset, ino, d_type);
+}
+
+static inline int ovl_dir_read(struct path *realpath,
+                              struct ovl_readdir_data *rdd)
+{
+       struct file *realfile;
+       int err;
+
+       realfile = ovl_path_open(realpath, O_RDONLY | O_DIRECTORY);
+       if (IS_ERR(realfile))
+               return PTR_ERR(realfile);
+
+       rdd->ctx.pos = 0;
+       do {
+               rdd->count = 0;
+               rdd->err = 0;
+               err = iterate_dir(realfile, &rdd->ctx);
+               if (err >= 0)
+                       err = rdd->err;
+       } while (!err && rdd->count);
+       fput(realfile);
+
+       return err;
+}
+
+static void ovl_dir_reset(struct file *file)
+{
+       struct ovl_dir_file *od = file->private_data;
+       struct ovl_dir_cache *cache = od->cache;
+       struct dentry *dentry = file->f_path.dentry;
+       enum ovl_path_type type = ovl_path_type(dentry);
+
+       if (cache && ovl_dentry_version_get(dentry) != cache->version) {
+               ovl_cache_put(od, dentry);
+               od->cache = NULL;
+       }
+       WARN_ON(!od->is_real && type != OVL_PATH_MERGE);
+       if (od->is_real && type == OVL_PATH_MERGE)
+               od->is_real = false;
+}
+
+static int ovl_dir_mark_whiteouts(struct dentry *dir,
+                                 struct ovl_readdir_data *rdd)
+{
+       struct ovl_cache_entry *p;
+       struct dentry *dentry;
+       const struct cred *old_cred;
+       struct cred *override_cred;
+
+       override_cred = prepare_creds();
+       if (!override_cred) {
+               ovl_cache_free(rdd->list);
+               return -ENOMEM;
+       }
+
+       /*
+        * CAP_DAC_OVERRIDE for lookup
+        */
+       cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+       old_cred = override_creds(override_cred);
+
+       mutex_lock(&dir->d_inode->i_mutex);
+       list_for_each_entry(p, rdd->list, l_node) {
+               if (p->is_cursor)
+                       continue;
+
+               if (p->type != DT_CHR)
+                       continue;
+
+               dentry = lookup_one_len(p->name, dir, p->len);
+               if (IS_ERR(dentry))
+                       continue;
+
+               p->is_whiteout = ovl_is_whiteout(dentry);
+               dput(dentry);
+       }
+       mutex_unlock(&dir->d_inode->i_mutex);
+
+       revert_creds(old_cred);
+       put_cred(override_cred);
+
+       return 0;
+}
+
+static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list)
+{
+       int err;
+       struct path lowerpath;
+       struct path upperpath;
+       struct ovl_readdir_data rdd = {
+               .ctx.actor = ovl_fill_merge,
+               .list = list,
+               .root = RB_ROOT,
+               .is_merge = false,
+       };
+
+       ovl_path_lower(dentry, &lowerpath);
+       ovl_path_upper(dentry, &upperpath);
+
+       if (upperpath.dentry) {
+               err = ovl_dir_read(&upperpath, &rdd);
+               if (err)
+                       goto out;
+
+               if (lowerpath.dentry) {
+                       err = ovl_dir_mark_whiteouts(upperpath.dentry, &rdd);
+                       if (err)
+                               goto out;
+               }
+       }
+       if (lowerpath.dentry) {
+               /*
+                * Insert lowerpath entries before upperpath ones, this allows
+                * offsets to be reasonably constant
+                */
+               list_add(&rdd.middle, rdd.list);
+               rdd.is_merge = true;
+               err = ovl_dir_read(&lowerpath, &rdd);
+               list_del(&rdd.middle);
+       }
+out:
+       return err;
+}
+
+static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos)
+{
+       struct ovl_cache_entry *p;
+       loff_t off = 0;
+
+       list_for_each_entry(p, &od->cache->entries, l_node) {
+               if (p->is_cursor)
+                       continue;
+               if (off >= pos)
+                       break;
+               off++;
+       }
+       list_move_tail(&od->cursor.l_node, &p->l_node);
+}
+
+static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
+{
+       int res;
+       struct ovl_dir_cache *cache;
+
+       cache = ovl_dir_cache(dentry);
+       if (cache && ovl_dentry_version_get(dentry) == cache->version) {
+               cache->refcount++;
+               return cache;
+       }
+       ovl_set_dir_cache(dentry, NULL);
+
+       cache = kzalloc(sizeof(struct ovl_dir_cache), GFP_KERNEL);
+       if (!cache)
+               return ERR_PTR(-ENOMEM);
+
+       cache->refcount = 1;
+       INIT_LIST_HEAD(&cache->entries);
+
+       res = ovl_dir_read_merged(dentry, &cache->entries);
+       if (res) {
+               ovl_cache_free(&cache->entries);
+               kfree(cache);
+               return ERR_PTR(res);
+       }
+
+       cache->version = ovl_dentry_version_get(dentry);
+       ovl_set_dir_cache(dentry, cache);
+
+       return cache;
+}
+
+static int ovl_iterate(struct file *file, struct dir_context *ctx)
+{
+       struct ovl_dir_file *od = file->private_data;
+       struct dentry *dentry = file->f_path.dentry;
+
+       if (!ctx->pos)
+               ovl_dir_reset(file);
+
+       if (od->is_real)
+               return iterate_dir(od->realfile, ctx);
+
+       if (!od->cache) {
+               struct ovl_dir_cache *cache;
+
+               cache = ovl_cache_get(dentry);
+               if (IS_ERR(cache))
+                       return PTR_ERR(cache);
+
+               od->cache = cache;
+               ovl_seek_cursor(od, ctx->pos);
+       }
+
+       while (od->cursor.l_node.next != &od->cache->entries) {
+               struct ovl_cache_entry *p;
+
+               p = list_entry(od->cursor.l_node.next, struct ovl_cache_entry, l_node);
+               /* Skip cursors */
+               if (!p->is_cursor) {
+                       if (!p->is_whiteout) {
+                               if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
+                                       break;
+                       }
+                       ctx->pos++;
+               }
+               list_move(&od->cursor.l_node, &p->l_node);
+       }
+       return 0;
+}
+
+static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
+{
+       loff_t res;
+       struct ovl_dir_file *od = file->private_data;
+
+       mutex_lock(&file_inode(file)->i_mutex);
+       if (!file->f_pos)
+               ovl_dir_reset(file);
+
+       if (od->is_real) {
+               res = vfs_llseek(od->realfile, offset, origin);
+               file->f_pos = od->realfile->f_pos;
+       } else {
+               res = -EINVAL;
+
+               switch (origin) {
+               case SEEK_CUR:
+                       offset += file->f_pos;
+                       break;
+               case SEEK_SET:
+                       break;
+               default:
+                       goto out_unlock;
+               }
+               if (offset < 0)
+                       goto out_unlock;
+
+               if (offset != file->f_pos) {
+                       file->f_pos = offset;
+                       if (od->cache)
+                               ovl_seek_cursor(od, offset);
+               }
+               res = offset;
+       }
+out_unlock:
+       mutex_unlock(&file_inode(file)->i_mutex);
+
+       return res;
+}
+
+static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
+                        int datasync)
+{
+       struct ovl_dir_file *od = file->private_data;
+       struct dentry *dentry = file->f_path.dentry;
+       struct file *realfile = od->realfile;
+
+       /*
+        * Need to check if we started out being a lower dir, but got copied up
+        */
+       if (!od->is_upper && ovl_path_type(dentry) != OVL_PATH_LOWER) {
+               struct inode *inode = file_inode(file);
+
+               realfile = lockless_dereference(od->upperfile);
+               if (!realfile) {
+                       struct path upperpath;
+
+                       ovl_path_upper(dentry, &upperpath);
+                       realfile = ovl_path_open(&upperpath, O_RDONLY);
+                       smp_mb__before_spinlock();
+                       mutex_lock(&inode->i_mutex);
+                       if (!od->upperfile) {
+                               if (IS_ERR(realfile)) {
+                                       mutex_unlock(&inode->i_mutex);
+                                       return PTR_ERR(realfile);
+                               }
+                               od->upperfile = realfile;
+                       } else {
+                               /* somebody has beaten us to it */
+                               if (!IS_ERR(realfile))
+                                       fput(realfile);
+                               realfile = od->upperfile;
+                       }
+                       mutex_unlock(&inode->i_mutex);
+               }
+       }
+
+       return vfs_fsync_range(realfile, start, end, datasync);
+}
+
+static int ovl_dir_release(struct inode *inode, struct file *file)
+{
+       struct ovl_dir_file *od = file->private_data;
+
+       if (od->cache) {
+               mutex_lock(&inode->i_mutex);
+               ovl_cache_put(od, file->f_path.dentry);
+               mutex_unlock(&inode->i_mutex);
+       }
+       fput(od->realfile);
+       if (od->upperfile)
+               fput(od->upperfile);
+       kfree(od);
+
+       return 0;
+}
+
+static int ovl_dir_open(struct inode *inode, struct file *file)
+{
+       struct path realpath;
+       struct file *realfile;
+       struct ovl_dir_file *od;
+       enum ovl_path_type type;
+
+       od = kzalloc(sizeof(struct ovl_dir_file), GFP_KERNEL);
+       if (!od)
+               return -ENOMEM;
+
+       type = ovl_path_real(file->f_path.dentry, &realpath);
+       realfile = ovl_path_open(&realpath, file->f_flags);
+       if (IS_ERR(realfile)) {
+               kfree(od);
+               return PTR_ERR(realfile);
+       }
+       INIT_LIST_HEAD(&od->cursor.l_node);
+       od->realfile = realfile;
+       od->is_real = (type != OVL_PATH_MERGE);
+       od->is_upper = (type != OVL_PATH_LOWER);
+       od->cursor.is_cursor = true;
+       file->private_data = od;
+
+       return 0;
+}
+
+const struct file_operations ovl_dir_operations = {
+       .read           = generic_read_dir,
+       .open           = ovl_dir_open,
+       .iterate        = ovl_iterate,
+       .llseek         = ovl_dir_llseek,
+       .fsync          = ovl_dir_fsync,
+       .release        = ovl_dir_release,
+};
+
+int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
+{
+       int err;
+       struct ovl_cache_entry *p;
+
+       err = ovl_dir_read_merged(dentry, list);
+       if (err)
+               return err;
+
+       err = 0;
+
+       list_for_each_entry(p, list, l_node) {
+               if (p->is_whiteout)
+                       continue;
+
+               if (p->name[0] == '.') {
+                       if (p->len == 1)
+                               continue;
+                       if (p->len == 2 && p->name[1] == '.')
+                               continue;
+               }
+               err = -ENOTEMPTY;
+               break;
+       }
+
+       return err;
+}
+
+void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list)
+{
+       struct ovl_cache_entry *p;
+
+       mutex_lock_nested(&upper->d_inode->i_mutex, I_MUTEX_CHILD);
+       list_for_each_entry(p, list, l_node) {
+               struct dentry *dentry;
+
+               if (!p->is_whiteout)
+                       continue;
+
+               dentry = lookup_one_len(p->name, upper, p->len);
+               if (IS_ERR(dentry)) {
+                       pr_err("overlayfs: lookup '%s/%.*s' failed (%i)\n",
+                              upper->d_name.name, p->len, p->name,
+                              (int) PTR_ERR(dentry));
+                       continue;
+               }
+               ovl_cleanup(upper->d_inode, dentry);
+               dput(dentry);
+       }
+       mutex_unlock(&upper->d_inode->i_mutex);
+}
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
new file mode 100644 (file)
index 0000000..f16d318
--- /dev/null
@@ -0,0 +1,833 @@
+/*
+ *
+ * Copyright (C) 2011 Novell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/xattr.h>
+#include <linux/security.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/statfs.h>
+#include <linux/seq_file.h>
+#include "overlayfs.h"
+
+MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
+MODULE_DESCRIPTION("Overlay filesystem");
+MODULE_LICENSE("GPL");
+
+#define OVERLAYFS_SUPER_MAGIC 0x794c7630
+
+struct ovl_config {
+       char *lowerdir;
+       char *upperdir;
+       char *workdir;
+};
+
+/* private information held for overlayfs's superblock */
+struct ovl_fs {
+       struct vfsmount *upper_mnt;
+       struct vfsmount *lower_mnt;
+       struct dentry *workdir;
+       long lower_namelen;
+       /* pathnames of lower and upper dirs, for show_options */
+       struct ovl_config config;
+};
+
+struct ovl_dir_cache;
+
+/* private information held for every overlayfs dentry */
+struct ovl_entry {
+       struct dentry *__upperdentry;
+       struct dentry *lowerdentry;
+       struct ovl_dir_cache *cache;
+       union {
+               struct {
+                       u64 version;
+                       bool opaque;
+               };
+               struct rcu_head rcu;
+       };
+};
+
+const char *ovl_opaque_xattr = "trusted.overlay.opaque";
+
+
+enum ovl_path_type ovl_path_type(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       if (oe->__upperdentry) {
+               if (oe->lowerdentry) {
+                       if (S_ISDIR(dentry->d_inode->i_mode))
+                               return OVL_PATH_MERGE;
+                       else
+                               return OVL_PATH_UPPER;
+               } else {
+                       if (oe->opaque)
+                               return OVL_PATH_UPPER;
+                       else
+                               return OVL_PATH_PURE_UPPER;
+               }
+       } else {
+               return OVL_PATH_LOWER;
+       }
+}
+
+static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe)
+{
+       return lockless_dereference(oe->__upperdentry);
+}
+
+void ovl_path_upper(struct dentry *dentry, struct path *path)
+{
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       path->mnt = ofs->upper_mnt;
+       path->dentry = ovl_upperdentry_dereference(oe);
+}
+
+enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
+{
+
+       enum ovl_path_type type = ovl_path_type(dentry);
+
+       if (type == OVL_PATH_LOWER)
+               ovl_path_lower(dentry, path);
+       else
+               ovl_path_upper(dentry, path);
+
+       return type;
+}
+
+struct dentry *ovl_dentry_upper(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       return ovl_upperdentry_dereference(oe);
+}
+
+struct dentry *ovl_dentry_lower(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       return oe->lowerdentry;
+}
+
+struct dentry *ovl_dentry_real(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+       struct dentry *realdentry;
+
+       realdentry = ovl_upperdentry_dereference(oe);
+       if (!realdentry)
+               realdentry = oe->lowerdentry;
+
+       return realdentry;
+}
+
+struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper)
+{
+       struct dentry *realdentry;
+
+       realdentry = ovl_upperdentry_dereference(oe);
+       if (realdentry) {
+               *is_upper = true;
+       } else {
+               realdentry = oe->lowerdentry;
+               *is_upper = false;
+       }
+       return realdentry;
+}
+
+struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       return oe->cache;
+}
+
+void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       oe->cache = cache;
+}
+
+void ovl_path_lower(struct dentry *dentry, struct path *path)
+{
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       path->mnt = ofs->lower_mnt;
+       path->dentry = oe->lowerdentry;
+}
+
+int ovl_want_write(struct dentry *dentry)
+{
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+       return mnt_want_write(ofs->upper_mnt);
+}
+
+void ovl_drop_write(struct dentry *dentry)
+{
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+       mnt_drop_write(ofs->upper_mnt);
+}
+
+struct dentry *ovl_workdir(struct dentry *dentry)
+{
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+       return ofs->workdir;
+}
+
+bool ovl_dentry_is_opaque(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+       return oe->opaque;
+}
+
+void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+       oe->opaque = opaque;
+}
+
+void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       WARN_ON(!mutex_is_locked(&upperdentry->d_parent->d_inode->i_mutex));
+       WARN_ON(oe->__upperdentry);
+       BUG_ON(!upperdentry->d_inode);
+       /*
+        * Make sure upperdentry is consistent before making it visible to
+        * ovl_upperdentry_dereference().
+        */
+       smp_wmb();
+       oe->__upperdentry = upperdentry;
+}
+
+void ovl_dentry_version_inc(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+       oe->version++;
+}
+
+u64 ovl_dentry_version_get(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+       return oe->version;
+}
+
+bool ovl_is_whiteout(struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+
+       return inode && IS_WHITEOUT(inode);
+}
+
+static bool ovl_is_opaquedir(struct dentry *dentry)
+{
+       int res;
+       char val;
+       struct inode *inode = dentry->d_inode;
+
+       if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
+               return false;
+
+       res = inode->i_op->getxattr(dentry, ovl_opaque_xattr, &val, 1);
+       if (res == 1 && val == 'y')
+               return true;
+
+       return false;
+}
+
+static void ovl_dentry_release(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       if (oe) {
+               dput(oe->__upperdentry);
+               dput(oe->lowerdentry);
+               kfree_rcu(oe, rcu);
+       }
+}
+
+static const struct dentry_operations ovl_dentry_operations = {
+       .d_release = ovl_dentry_release,
+};
+
+static struct ovl_entry *ovl_alloc_entry(void)
+{
+       return kzalloc(sizeof(struct ovl_entry), GFP_KERNEL);
+}
+
+static inline struct dentry *ovl_lookup_real(struct dentry *dir,
+                                            struct qstr *name)
+{
+       struct dentry *dentry;
+
+       mutex_lock(&dir->d_inode->i_mutex);
+       dentry = lookup_one_len(name->name, dir, name->len);
+       mutex_unlock(&dir->d_inode->i_mutex);
+
+       if (IS_ERR(dentry)) {
+               if (PTR_ERR(dentry) == -ENOENT)
+                       dentry = NULL;
+       } else if (!dentry->d_inode) {
+               dput(dentry);
+               dentry = NULL;
+       }
+       return dentry;
+}
+
+struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
+                         unsigned int flags)
+{
+       struct ovl_entry *oe;
+       struct dentry *upperdir;
+       struct dentry *lowerdir;
+       struct dentry *upperdentry = NULL;
+       struct dentry *lowerdentry = NULL;
+       struct inode *inode = NULL;
+       int err;
+
+       err = -ENOMEM;
+       oe = ovl_alloc_entry();
+       if (!oe)
+               goto out;
+
+       upperdir = ovl_dentry_upper(dentry->d_parent);
+       lowerdir = ovl_dentry_lower(dentry->d_parent);
+
+       if (upperdir) {
+               upperdentry = ovl_lookup_real(upperdir, &dentry->d_name);
+               err = PTR_ERR(upperdentry);
+               if (IS_ERR(upperdentry))
+                       goto out_put_dir;
+
+               if (lowerdir && upperdentry) {
+                       if (ovl_is_whiteout(upperdentry)) {
+                               dput(upperdentry);
+                               upperdentry = NULL;
+                               oe->opaque = true;
+                       } else if (ovl_is_opaquedir(upperdentry)) {
+                               oe->opaque = true;
+                       }
+               }
+       }
+       if (lowerdir && !oe->opaque) {
+               lowerdentry = ovl_lookup_real(lowerdir, &dentry->d_name);
+               err = PTR_ERR(lowerdentry);
+               if (IS_ERR(lowerdentry))
+                       goto out_dput_upper;
+       }
+
+       if (lowerdentry && upperdentry &&
+           (!S_ISDIR(upperdentry->d_inode->i_mode) ||
+            !S_ISDIR(lowerdentry->d_inode->i_mode))) {
+               dput(lowerdentry);
+               lowerdentry = NULL;
+               oe->opaque = true;
+       }
+
+       if (lowerdentry || upperdentry) {
+               struct dentry *realdentry;
+
+               realdentry = upperdentry ? upperdentry : lowerdentry;
+               err = -ENOMEM;
+               inode = ovl_new_inode(dentry->d_sb, realdentry->d_inode->i_mode,
+                                     oe);
+               if (!inode)
+                       goto out_dput;
+               ovl_copyattr(realdentry->d_inode, inode);
+       }
+
+       oe->__upperdentry = upperdentry;
+       oe->lowerdentry = lowerdentry;
+
+       dentry->d_fsdata = oe;
+       d_add(dentry, inode);
+
+       return NULL;
+
+out_dput:
+       dput(lowerdentry);
+out_dput_upper:
+       dput(upperdentry);
+out_put_dir:
+       kfree(oe);
+out:
+       return ERR_PTR(err);
+}
+
+struct file *ovl_path_open(struct path *path, int flags)
+{
+       return dentry_open(path, flags, current_cred());
+}
+
+static void ovl_put_super(struct super_block *sb)
+{
+       struct ovl_fs *ufs = sb->s_fs_info;
+
+       dput(ufs->workdir);
+       mntput(ufs->upper_mnt);
+       mntput(ufs->lower_mnt);
+
+       kfree(ufs->config.lowerdir);
+       kfree(ufs->config.upperdir);
+       kfree(ufs->config.workdir);
+       kfree(ufs);
+}
+
+/**
+ * ovl_statfs
+ * @sb: The overlayfs super block
+ * @buf: The struct kstatfs to fill in with stats
+ *
+ * Get the filesystem statistics.  As writes always target the upper layer
+ * filesystem pass the statfs to the same filesystem.
+ */
+static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+       struct dentry *root_dentry = dentry->d_sb->s_root;
+       struct path path;
+       int err;
+
+       ovl_path_upper(root_dentry, &path);
+
+       err = vfs_statfs(&path, buf);
+       if (!err) {
+               buf->f_namelen = max(buf->f_namelen, ofs->lower_namelen);
+               buf->f_type = OVERLAYFS_SUPER_MAGIC;
+       }
+
+       return err;
+}
+
+/**
+ * ovl_show_options
+ *
+ * Prints the mount options for a given superblock.
+ * Returns zero; does not fail.
+ */
+static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
+{
+       struct super_block *sb = dentry->d_sb;
+       struct ovl_fs *ufs = sb->s_fs_info;
+
+       seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir);
+       seq_printf(m, ",upperdir=%s", ufs->config.upperdir);
+       seq_printf(m, ",workdir=%s", ufs->config.workdir);
+       return 0;
+}
+
+static const struct super_operations ovl_super_operations = {
+       .put_super      = ovl_put_super,
+       .statfs         = ovl_statfs,
+       .show_options   = ovl_show_options,
+};
+
+enum {
+       OPT_LOWERDIR,
+       OPT_UPPERDIR,
+       OPT_WORKDIR,
+       OPT_ERR,
+};
+
+static const match_table_t ovl_tokens = {
+       {OPT_LOWERDIR,                  "lowerdir=%s"},
+       {OPT_UPPERDIR,                  "upperdir=%s"},
+       {OPT_WORKDIR,                   "workdir=%s"},
+       {OPT_ERR,                       NULL}
+};
+
+static char *ovl_next_opt(char **s)
+{
+       char *sbegin = *s;
+       char *p;
+
+       if (sbegin == NULL)
+               return NULL;
+
+       for (p = sbegin; *p; p++) {
+               if (*p == '\\') {
+                       p++;
+                       if (!*p)
+                               break;
+               } else if (*p == ',') {
+                       *p = '\0';
+                       *s = p + 1;
+                       return sbegin;
+               }
+       }
+       *s = NULL;
+       return sbegin;
+}
+
+static int ovl_parse_opt(char *opt, struct ovl_config *config)
+{
+       char *p;
+
+       while ((p = ovl_next_opt(&opt)) != NULL) {
+               int token;
+               substring_t args[MAX_OPT_ARGS];
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, ovl_tokens, args);
+               switch (token) {
+               case OPT_UPPERDIR:
+                       kfree(config->upperdir);
+                       config->upperdir = match_strdup(&args[0]);
+                       if (!config->upperdir)
+                               return -ENOMEM;
+                       break;
+
+               case OPT_LOWERDIR:
+                       kfree(config->lowerdir);
+                       config->lowerdir = match_strdup(&args[0]);
+                       if (!config->lowerdir)
+                               return -ENOMEM;
+                       break;
+
+               case OPT_WORKDIR:
+                       kfree(config->workdir);
+                       config->workdir = match_strdup(&args[0]);
+                       if (!config->workdir)
+                               return -ENOMEM;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+#define OVL_WORKDIR_NAME "work"
+
+static struct dentry *ovl_workdir_create(struct vfsmount *mnt,
+                                        struct dentry *dentry)
+{
+       struct inode *dir = dentry->d_inode;
+       struct dentry *work;
+       int err;
+       bool retried = false;
+
+       err = mnt_want_write(mnt);
+       if (err)
+               return ERR_PTR(err);
+
+       mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
+retry:
+       work = lookup_one_len(OVL_WORKDIR_NAME, dentry,
+                             strlen(OVL_WORKDIR_NAME));
+
+       if (!IS_ERR(work)) {
+               struct kstat stat = {
+                       .mode = S_IFDIR | 0,
+               };
+
+               if (work->d_inode) {
+                       err = -EEXIST;
+                       if (retried)
+                               goto out_dput;
+
+                       retried = true;
+                       ovl_cleanup(dir, work);
+                       dput(work);
+                       goto retry;
+               }
+
+               err = ovl_create_real(dir, work, &stat, NULL, NULL, true);
+               if (err)
+                       goto out_dput;
+       }
+out_unlock:
+       mutex_unlock(&dir->i_mutex);
+       mnt_drop_write(mnt);
+
+       return work;
+
+out_dput:
+       dput(work);
+       work = ERR_PTR(err);
+       goto out_unlock;
+}
+
+static void ovl_unescape(char *s)
+{
+       char *d = s;
+
+       for (;; s++, d++) {
+               if (*s == '\\')
+                       s++;
+               *d = *s;
+               if (!*s)
+                       break;
+       }
+}
+
+static int ovl_mount_dir(const char *name, struct path *path)
+{
+       int err;
+       char *tmp = kstrdup(name, GFP_KERNEL);
+
+       if (!tmp)
+               return -ENOMEM;
+
+       ovl_unescape(tmp);
+       err = kern_path(tmp, LOOKUP_FOLLOW, path);
+       if (err) {
+               pr_err("overlayfs: failed to resolve '%s': %i\n", tmp, err);
+               err = -EINVAL;
+       }
+       kfree(tmp);
+       return err;
+}
+
+static bool ovl_is_allowed_fs_type(struct dentry *root)
+{
+       const struct dentry_operations *dop = root->d_op;
+
+       /*
+        * We don't support:
+        *  - automount filesystems
+        *  - filesystems with revalidate (FIXME for lower layer)
+        *  - filesystems with case insensitive names
+        */
+       if (dop &&
+           (dop->d_manage || dop->d_automount ||
+            dop->d_revalidate || dop->d_weak_revalidate ||
+            dop->d_compare || dop->d_hash)) {
+               return false;
+       }
+       return true;
+}
+
+/* Workdir should not be subdir of upperdir and vice versa */
+static bool ovl_workdir_ok(struct dentry *workdir, struct dentry *upperdir)
+{
+       bool ok = false;
+
+       if (workdir != upperdir) {
+               ok = (lock_rename(workdir, upperdir) == NULL);
+               unlock_rename(workdir, upperdir);
+       }
+       return ok;
+}
+
+static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct path lowerpath;
+       struct path upperpath;
+       struct path workpath;
+       struct inode *root_inode;
+       struct dentry *root_dentry;
+       struct ovl_entry *oe;
+       struct ovl_fs *ufs;
+       struct kstatfs statfs;
+       int err;
+
+       err = -ENOMEM;
+       ufs = kzalloc(sizeof(struct ovl_fs), GFP_KERNEL);
+       if (!ufs)
+               goto out;
+
+       err = ovl_parse_opt((char *) data, &ufs->config);
+       if (err)
+               goto out_free_config;
+
+       /* FIXME: workdir is not needed for a R/O mount */
+       err = -EINVAL;
+       if (!ufs->config.upperdir || !ufs->config.lowerdir ||
+           !ufs->config.workdir) {
+               pr_err("overlayfs: missing upperdir or lowerdir or workdir\n");
+               goto out_free_config;
+       }
+
+       err = -ENOMEM;
+       oe = ovl_alloc_entry();
+       if (oe == NULL)
+               goto out_free_config;
+
+       err = ovl_mount_dir(ufs->config.upperdir, &upperpath);
+       if (err)
+               goto out_free_oe;
+
+       err = ovl_mount_dir(ufs->config.lowerdir, &lowerpath);
+       if (err)
+               goto out_put_upperpath;
+
+       err = ovl_mount_dir(ufs->config.workdir, &workpath);
+       if (err)
+               goto out_put_lowerpath;
+
+       err = -EINVAL;
+       if (!S_ISDIR(upperpath.dentry->d_inode->i_mode) ||
+           !S_ISDIR(lowerpath.dentry->d_inode->i_mode) ||
+           !S_ISDIR(workpath.dentry->d_inode->i_mode)) {
+               pr_err("overlayfs: upperdir or lowerdir or workdir not a directory\n");
+               goto out_put_workpath;
+       }
+
+       if (upperpath.mnt != workpath.mnt) {
+               pr_err("overlayfs: workdir and upperdir must reside under the same mount\n");
+               goto out_put_workpath;
+       }
+       if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) {
+               pr_err("overlayfs: workdir and upperdir must be separate subtrees\n");
+               goto out_put_workpath;
+       }
+
+       if (!ovl_is_allowed_fs_type(upperpath.dentry)) {
+               pr_err("overlayfs: filesystem of upperdir is not supported\n");
+               goto out_put_workpath;
+       }
+
+       if (!ovl_is_allowed_fs_type(lowerpath.dentry)) {
+               pr_err("overlayfs: filesystem of lowerdir is not supported\n");
+               goto out_put_workpath;
+       }
+
+       err = vfs_statfs(&lowerpath, &statfs);
+       if (err) {
+               pr_err("overlayfs: statfs failed on lowerpath\n");
+               goto out_put_workpath;
+       }
+       ufs->lower_namelen = statfs.f_namelen;
+
+       sb->s_stack_depth = max(upperpath.mnt->mnt_sb->s_stack_depth,
+                               lowerpath.mnt->mnt_sb->s_stack_depth) + 1;
+
+       err = -EINVAL;
+       if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+               pr_err("overlayfs: maximum fs stacking depth exceeded\n");
+               goto out_put_workpath;
+       }
+
+       ufs->upper_mnt = clone_private_mount(&upperpath);
+       err = PTR_ERR(ufs->upper_mnt);
+       if (IS_ERR(ufs->upper_mnt)) {
+               pr_err("overlayfs: failed to clone upperpath\n");
+               goto out_put_workpath;
+       }
+
+       ufs->lower_mnt = clone_private_mount(&lowerpath);
+       err = PTR_ERR(ufs->lower_mnt);
+       if (IS_ERR(ufs->lower_mnt)) {
+               pr_err("overlayfs: failed to clone lowerpath\n");
+               goto out_put_upper_mnt;
+       }
+
+       ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
+       err = PTR_ERR(ufs->workdir);
+       if (IS_ERR(ufs->workdir)) {
+               pr_err("overlayfs: failed to create directory %s/%s\n",
+                      ufs->config.workdir, OVL_WORKDIR_NAME);
+               goto out_put_lower_mnt;
+       }
+
+       /*
+        * Make lower_mnt R/O.  That way fchmod/fchown on lower file
+        * will fail instead of modifying lower fs.
+        */
+       ufs->lower_mnt->mnt_flags |= MNT_READONLY;
+
+       /* If the upper fs is r/o, we mark overlayfs r/o too */
+       if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY)
+               sb->s_flags |= MS_RDONLY;
+
+       sb->s_d_op = &ovl_dentry_operations;
+
+       err = -ENOMEM;
+       root_inode = ovl_new_inode(sb, S_IFDIR, oe);
+       if (!root_inode)
+               goto out_put_workdir;
+
+       root_dentry = d_make_root(root_inode);
+       if (!root_dentry)
+               goto out_put_workdir;
+
+       mntput(upperpath.mnt);
+       mntput(lowerpath.mnt);
+       path_put(&workpath);
+
+       oe->__upperdentry = upperpath.dentry;
+       oe->lowerdentry = lowerpath.dentry;
+
+       root_dentry->d_fsdata = oe;
+
+       sb->s_magic = OVERLAYFS_SUPER_MAGIC;
+       sb->s_op = &ovl_super_operations;
+       sb->s_root = root_dentry;
+       sb->s_fs_info = ufs;
+
+       return 0;
+
+out_put_workdir:
+       dput(ufs->workdir);
+out_put_lower_mnt:
+       mntput(ufs->lower_mnt);
+out_put_upper_mnt:
+       mntput(ufs->upper_mnt);
+out_put_workpath:
+       path_put(&workpath);
+out_put_lowerpath:
+       path_put(&lowerpath);
+out_put_upperpath:
+       path_put(&upperpath);
+out_free_oe:
+       kfree(oe);
+out_free_config:
+       kfree(ufs->config.lowerdir);
+       kfree(ufs->config.upperdir);
+       kfree(ufs->config.workdir);
+       kfree(ufs);
+out:
+       return err;
+}
+
+static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags,
+                               const char *dev_name, void *raw_data)
+{
+       return mount_nodev(fs_type, flags, raw_data, ovl_fill_super);
+}
+
+static struct file_system_type ovl_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "overlay",
+       .mount          = ovl_mount,
+       .kill_sb        = kill_anon_super,
+};
+MODULE_ALIAS_FS("overlay");
+
+static int __init ovl_init(void)
+{
+       return register_filesystem(&ovl_fs_type);
+}
+
+static void __exit ovl_exit(void)
+{
+       unregister_filesystem(&ovl_fs_type);
+}
+
+module_init(ovl_init);
+module_exit(ovl_exit);
index 8b663b2d95622f98b704ed693b1177d13cfa79dd..6b4527216a7fe2c60ead15d57383648f25d4d3ef 100644 (file)
@@ -634,7 +634,7 @@ int dquot_writeback_dquots(struct super_block *sb, int type)
                        dqstats_inc(DQST_LOOKUPS);
                        err = sb->dq_op->write_dquot(dquot);
                        if (!ret && err)
-                               err = ret;
+                               ret = err;
                        dqput(dquot);
                        spin_lock(&dq_list_lock);
                }
index f5cb9ba84510fe5632a62af0bbf3843a45eeba23..75c6058eabf2e37b27df85fafe6e6b2b5b9379dd 100644 (file)
@@ -1330,6 +1330,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 
        return ret;
 }
+EXPORT_SYMBOL(do_splice_direct);
 
 static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe,
                               struct pipe_inode_info *opipe,
index 92e8f99a58575b0667be026c9bfc6da5eeeae76d..281002689d64f858c605ce4a8d2aa72864034549 100644 (file)
@@ -1338,7 +1338,10 @@ xfs_free_file_space(
        goto out;
 }
 
-
+/*
+ * Preallocate and zero a range of a file. This mechanism has the allocation
+ * semantics of fallocate and in addition converts data in the range to zeroes.
+ */
 int
 xfs_zero_file_space(
        struct xfs_inode        *ip,
@@ -1346,65 +1349,30 @@ xfs_zero_file_space(
        xfs_off_t               len)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       uint                    granularity;
-       xfs_off_t               start_boundary;
-       xfs_off_t               end_boundary;
+       uint                    blksize;
        int                     error;
 
        trace_xfs_zero_file_space(ip);
 
-       granularity = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
+       blksize = 1 << mp->m_sb.sb_blocklog;
 
        /*
-        * Round the range of extents we are going to convert inwards.  If the
-        * offset is aligned, then it doesn't get changed so we zero from the
-        * start of the block offset points to.
+        * Punch a hole and prealloc the range. We use hole punch rather than
+        * unwritten extent conversion for two reasons:
+        *
+        * 1.) Hole punch handles partial block zeroing for us.
+        *
+        * 2.) If prealloc returns ENOSPC, the file range is still zero-valued
+        * by virtue of the hole punch.
         */
-       start_boundary = round_up(offset, granularity);
-       end_boundary = round_down(offset + len, granularity);
-
-       ASSERT(start_boundary >= offset);
-       ASSERT(end_boundary <= offset + len);
-
-       if (start_boundary < end_boundary - 1) {
-               /*
-                * Writeback the range to ensure any inode size updates due to
-                * appending writes make it to disk (otherwise we could just
-                * punch out the delalloc blocks).
-                */
-               error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
-                               start_boundary, end_boundary - 1);
-               if (error)
-                       goto out;
-               truncate_pagecache_range(VFS_I(ip), start_boundary,
-                                        end_boundary - 1);
-
-               /* convert the blocks */
-               error = xfs_alloc_file_space(ip, start_boundary,
-                                       end_boundary - start_boundary - 1,
-                                       XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT);
-               if (error)
-                       goto out;
-
-               /* We've handled the interior of the range, now for the edges */
-               if (start_boundary != offset) {
-                       error = xfs_iozero(ip, offset, start_boundary - offset);
-                       if (error)
-                               goto out;
-               }
-
-               if (end_boundary != offset + len)
-                       error = xfs_iozero(ip, end_boundary,
-                                          offset + len - end_boundary);
-
-       } else {
-               /*
-                * It's either a sub-granularity range or the range spanned lies
-                * partially across two adjacent blocks.
-                */
-               error = xfs_iozero(ip, offset, len);
-       }
+       error = xfs_free_file_space(ip, offset, len);
+       if (error)
+               goto out;
 
+       error = xfs_alloc_file_space(ip, round_down(offset, blksize),
+                                    round_up(offset + len, blksize) -
+                                    round_down(offset, blksize),
+                                    XFS_BMAPI_PREALLOC);
 out:
        return error;
 
index f1deb961a296a300add3a6333eebd47619a2100c..894924a5129bea590e5fc3008d830889335e3fe1 100644 (file)
@@ -236,8 +236,10 @@ xfs_bulkstat_grab_ichunk(
        XFS_WANT_CORRUPTED_RETURN(stat == 1);
 
        /* Check if the record contains the inode in request */
-       if (irec->ir_startino + XFS_INODES_PER_CHUNK <= agino)
-               return -EINVAL;
+       if (irec->ir_startino + XFS_INODES_PER_CHUNK <= agino) {
+               *icount = 0;
+               return 0;
+       }
 
        idx = agino - irec->ir_startino + 1;
        if (idx < XFS_INODES_PER_CHUNK &&
@@ -262,75 +264,76 @@ xfs_bulkstat_grab_ichunk(
 
 #define XFS_BULKSTAT_UBLEFT(ubleft)    ((ubleft) >= statstruct_size)
 
+struct xfs_bulkstat_agichunk {
+       char            __user **ac_ubuffer;/* pointer into user's buffer */
+       int             ac_ubleft;      /* bytes left in user's buffer */
+       int             ac_ubelem;      /* spaces used in user's buffer */
+};
+
 /*
  * Process inodes in chunk with a pointer to a formatter function
  * that will iget the inode and fill in the appropriate structure.
  */
-int
+static int
 xfs_bulkstat_ag_ichunk(
        struct xfs_mount                *mp,
        xfs_agnumber_t                  agno,
        struct xfs_inobt_rec_incore     *irbp,
        bulkstat_one_pf                 formatter,
        size_t                          statstruct_size,
-       struct xfs_bulkstat_agichunk    *acp)
+       struct xfs_bulkstat_agichunk    *acp,
+       xfs_agino_t                     *last_agino)
 {
-       xfs_ino_t                       lastino = acp->ac_lastino;
        char                            __user **ubufp = acp->ac_ubuffer;
-       int                             ubleft = acp->ac_ubleft;
-       int                             ubelem = acp->ac_ubelem;
-       int                             chunkidx, clustidx;
+       int                             chunkidx;
        int                             error = 0;
-       xfs_agino_t                     agino;
+       xfs_agino_t                     agino = irbp->ir_startino;
 
-       for (agino = irbp->ir_startino, chunkidx = clustidx = 0;
-            XFS_BULKSTAT_UBLEFT(ubleft) &&
-            irbp->ir_freecount < XFS_INODES_PER_CHUNK;
-            chunkidx++, clustidx++, agino++) {
-               int             fmterror;       /* bulkstat formatter result */
+       for (chunkidx = 0; chunkidx < XFS_INODES_PER_CHUNK;
+            chunkidx++, agino++) {
+               int             fmterror;
                int             ubused;
-               xfs_ino_t       ino = XFS_AGINO_TO_INO(mp, agno, agino);
 
-               ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
+               /* inode won't fit in buffer, we are done */
+               if (acp->ac_ubleft < statstruct_size)
+                       break;
 
                /* Skip if this inode is free */
-               if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) {
-                       lastino = ino;
+               if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free)
                        continue;
-               }
-
-               /*
-                * Count used inodes as free so we can tell when the
-                * chunk is used up.
-                */
-               irbp->ir_freecount++;
 
                /* Get the inode and fill in a single buffer */
                ubused = statstruct_size;
-               error = formatter(mp, ino, *ubufp, ubleft, &ubused, &fmterror);
-               if (fmterror == BULKSTAT_RV_NOTHING) {
-                       if (error && error != -ENOENT && error != -EINVAL) {
-                               ubleft = 0;
-                               break;
-                       }
-                       lastino = ino;
-                       continue;
-               }
-               if (fmterror == BULKSTAT_RV_GIVEUP) {
-                       ubleft = 0;
+               error = formatter(mp, XFS_AGINO_TO_INO(mp, agno, agino),
+                                 *ubufp, acp->ac_ubleft, &ubused, &fmterror);
+
+               if (fmterror == BULKSTAT_RV_GIVEUP ||
+                   (error && error != -ENOENT && error != -EINVAL)) {
+                       acp->ac_ubleft = 0;
                        ASSERT(error);
                        break;
                }
-               if (*ubufp)
-                       *ubufp += ubused;
-               ubleft -= ubused;
-               ubelem++;
-               lastino = ino;
+
+               /* be careful not to leak error if at end of chunk */
+               if (fmterror == BULKSTAT_RV_NOTHING || error) {
+                       error = 0;
+                       continue;
+               }
+
+               *ubufp += ubused;
+               acp->ac_ubleft -= ubused;
+               acp->ac_ubelem++;
        }
 
-       acp->ac_lastino = lastino;
-       acp->ac_ubleft = ubleft;
-       acp->ac_ubelem = ubelem;
+       /*
+        * Post-update *last_agino. At this point, agino will always point one
+        * inode past the last inode we processed successfully. Hence we
+        * substract that inode when setting the *last_agino cursor so that we
+        * return the correct cookie to userspace. On the next bulkstat call,
+        * the inode under the lastino cookie will be skipped as we have already
+        * processed it here.
+        */
+       *last_agino = agino - 1;
 
        return error;
 }
@@ -353,45 +356,33 @@ xfs_bulkstat(
        xfs_agino_t             agino;  /* inode # in allocation group */
        xfs_agnumber_t          agno;   /* allocation group number */
        xfs_btree_cur_t         *cur;   /* btree cursor for ialloc btree */
-       int                     end_of_ag; /* set if we've seen the ag end */
-       int                     error;  /* error code */
-       int                     fmterror;/* bulkstat formatter result */
-       int                     i;      /* loop index */
-       int                     icount; /* count of inodes good in irbuf */
        size_t                  irbsize; /* size of irec buffer in bytes */
-       xfs_ino_t               ino;    /* inode number (filesystem) */
-       xfs_inobt_rec_incore_t  *irbp;  /* current irec buffer pointer */
        xfs_inobt_rec_incore_t  *irbuf; /* start of irec buffer */
-       xfs_inobt_rec_incore_t  *irbufend; /* end of good irec buffer entries */
-       xfs_ino_t               lastino; /* last inode number returned */
        int                     nirbuf; /* size of irbuf */
-       int                     rval;   /* return value error code */
-       int                     tmp;    /* result value from btree calls */
        int                     ubcount; /* size of user's buffer */
-       int                     ubleft; /* bytes left in user's buffer */
-       char                    __user *ubufp;  /* pointer into user's buffer */
-       int                     ubelem; /* spaces used in user's buffer */
+       struct xfs_bulkstat_agichunk ac;
+       int                     error = 0;
 
        /*
         * Get the last inode value, see if there's nothing to do.
         */
-       ino = (xfs_ino_t)*lastinop;
-       lastino = ino;
-       agno = XFS_INO_TO_AGNO(mp, ino);
-       agino = XFS_INO_TO_AGINO(mp, ino);
+       agno = XFS_INO_TO_AGNO(mp, *lastinop);
+       agino = XFS_INO_TO_AGINO(mp, *lastinop);
        if (agno >= mp->m_sb.sb_agcount ||
-           ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
+           *lastinop != XFS_AGINO_TO_INO(mp, agno, agino)) {
                *done = 1;
                *ubcountp = 0;
                return 0;
        }
 
        ubcount = *ubcountp; /* statstruct's */
-       ubleft = ubcount * statstruct_size; /* bytes */
-       *ubcountp = ubelem = 0;
+       ac.ac_ubuffer = &ubuffer;
+       ac.ac_ubleft = ubcount * statstruct_size; /* bytes */;
+       ac.ac_ubelem = 0;
+
+       *ubcountp = 0;
        *done = 0;
-       fmterror = 0;
-       ubufp = ubuffer;
+
        irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4);
        if (!irbuf)
                return -ENOMEM;
@@ -402,9 +393,13 @@ xfs_bulkstat(
         * Loop over the allocation groups, starting from the last
         * inode returned; 0 means start of the allocation group.
         */
-       rval = 0;
-       while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) {
-               cond_resched();
+       while (agno < mp->m_sb.sb_agcount) {
+               struct xfs_inobt_rec_incore     *irbp = irbuf;
+               struct xfs_inobt_rec_incore     *irbufend = irbuf + nirbuf;
+               bool                            end_of_ag = false;
+               int                             icount = 0;
+               int                             stat;
+
                error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
                if (error)
                        break;
@@ -414,10 +409,6 @@ xfs_bulkstat(
                 */
                cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno,
                                            XFS_BTNUM_INO);
-               irbp = irbuf;
-               irbufend = irbuf + nirbuf;
-               end_of_ag = 0;
-               icount = 0;
                if (agino > 0) {
                        /*
                         * In the middle of an allocation group, we need to get
@@ -427,22 +418,23 @@ xfs_bulkstat(
 
                        error = xfs_bulkstat_grab_ichunk(cur, agino, &icount, &r);
                        if (error)
-                               break;
+                               goto del_cursor;
                        if (icount) {
                                irbp->ir_startino = r.ir_startino;
                                irbp->ir_freecount = r.ir_freecount;
                                irbp->ir_free = r.ir_free;
                                irbp++;
-                               agino = r.ir_startino + XFS_INODES_PER_CHUNK;
                        }
                        /* Increment to the next record */
-                       error = xfs_btree_increment(cur, 0, &tmp);
+                       error = xfs_btree_increment(cur, 0, &stat);
                } else {
                        /* Start of ag.  Lookup the first inode chunk */
-                       error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &tmp);
+                       error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &stat);
+               }
+               if (error || stat == 0) {
+                       end_of_ag = true;
+                       goto del_cursor;
                }
-               if (error)
-                       break;
 
                /*
                 * Loop through inode btree records in this ag,
@@ -451,10 +443,10 @@ xfs_bulkstat(
                while (irbp < irbufend && icount < ubcount) {
                        struct xfs_inobt_rec_incore     r;
 
-                       error = xfs_inobt_get_rec(cur, &r, &i);
-                       if (error || i == 0) {
-                               end_of_ag = 1;
-                               break;
+                       error = xfs_inobt_get_rec(cur, &r, &stat);
+                       if (error || stat == 0) {
+                               end_of_ag = true;
+                               goto del_cursor;
                        }
 
                        /*
@@ -469,77 +461,79 @@ xfs_bulkstat(
                                irbp++;
                                icount += XFS_INODES_PER_CHUNK - r.ir_freecount;
                        }
-                       /*
-                        * Set agino to after this chunk and bump the cursor.
-                        */
-                       agino = r.ir_startino + XFS_INODES_PER_CHUNK;
-                       error = xfs_btree_increment(cur, 0, &tmp);
+                       error = xfs_btree_increment(cur, 0, &stat);
+                       if (error || stat == 0) {
+                               end_of_ag = true;
+                               goto del_cursor;
+                       }
                        cond_resched();
                }
+
                /*
-                * Drop the btree buffers and the agi buffer.
-                * We can't hold any of the locks these represent
-                * when calling iget.
+                * Drop the btree buffers and the agi buffer as we can't hold any
+                * of the locks these represent when calling iget. If there is a
+                * pending error, then we are done.
                 */
+del_cursor:
                xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
                xfs_buf_relse(agbp);
+               if (error)
+                       break;
                /*
-                * Now format all the good inodes into the user's buffer.
+                * Now format all the good inodes into the user's buffer. The
+                * call to xfs_bulkstat_ag_ichunk() sets up the agino pointer
+                * for the next loop iteration.
                 */
                irbufend = irbp;
                for (irbp = irbuf;
-                    irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) {
-                       struct xfs_bulkstat_agichunk ac;
-
-                       ac.ac_lastino = lastino;
-                       ac.ac_ubuffer = &ubuffer;
-                       ac.ac_ubleft = ubleft;
-                       ac.ac_ubelem = ubelem;
+                    irbp < irbufend && ac.ac_ubleft >= statstruct_size;
+                    irbp++) {
                        error = xfs_bulkstat_ag_ichunk(mp, agno, irbp,
-                                       formatter, statstruct_size, &ac);
+                                       formatter, statstruct_size, &ac,
+                                       &agino);
                        if (error)
-                               rval = error;
-
-                       lastino = ac.ac_lastino;
-                       ubleft = ac.ac_ubleft;
-                       ubelem = ac.ac_ubelem;
+                               break;
 
                        cond_resched();
                }
+
                /*
-                * Set up for the next loop iteration.
+                * If we've run out of space or had a formatting error, we
+                * are now done
                 */
-               if (XFS_BULKSTAT_UBLEFT(ubleft)) {
-                       if (end_of_ag) {
-                               agno++;
-                               agino = 0;
-                       } else
-                               agino = XFS_INO_TO_AGINO(mp, lastino);
-               } else
+               if (ac.ac_ubleft < statstruct_size || error)
                        break;
+
+               if (end_of_ag) {
+                       agno++;
+                       agino = 0;
+               }
        }
        /*
         * Done, we're either out of filesystem or space to put the data.
         */
        kmem_free(irbuf);
-       *ubcountp = ubelem;
+       *ubcountp = ac.ac_ubelem;
+
        /*
-        * Found some inodes, return them now and return the error next time.
+        * We found some inodes, so clear the error status and return them.
+        * The lastino pointer will point directly at the inode that triggered
+        * any error that occurred, so on the next call the error will be
+        * triggered again and propagated to userspace as there will be no
+        * formatted inodes in the buffer.
         */
-       if (ubelem)
-               rval = 0;
-       if (agno >= mp->m_sb.sb_agcount) {
-               /*
-                * If we ran out of filesystem, mark lastino as off
-                * the end of the filesystem, so the next call
-                * will return immediately.
-                */
-               *lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0);
+       if (ac.ac_ubelem)
+               error = 0;
+
+       /*
+        * If we ran out of filesystem, lastino will point off the end of
+        * the filesystem so the next call will return immediately.
+        */
+       *lastinop = XFS_AGINO_TO_INO(mp, agno, agino);
+       if (agno >= mp->m_sb.sb_agcount)
                *done = 1;
-       } else
-               *lastinop = (xfs_ino_t)lastino;
 
-       return rval;
+       return error;
 }
 
 int
index aaed08022eb9e9cd7e271d86d54e308e01427c77..6ea8b3912fa4fcb5b67ac9fd0d9c24164c12f6c1 100644 (file)
@@ -30,22 +30,6 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount      *mp,
                               int              *ubused,
                               int              *stat);
 
-struct xfs_bulkstat_agichunk {
-       xfs_ino_t       ac_lastino;     /* last inode returned */
-       char            __user **ac_ubuffer;/* pointer into user's buffer */
-       int             ac_ubleft;      /* bytes left in user's buffer */
-       int             ac_ubelem;      /* spaces used in user's buffer */
-};
-
-int
-xfs_bulkstat_ag_ichunk(
-       struct xfs_mount                *mp,
-       xfs_agnumber_t                  agno,
-       struct xfs_inobt_rec_incore     *irbp,
-       bulkstat_one_pf                 formatter,
-       size_t                          statstruct_size,
-       struct xfs_bulkstat_agichunk    *acp);
-
 /*
  * Values for stat return value.
  */
index f97804bdf1ff93a8d1923bc4fe75b6abc36e097d..7461327e14e43ade9065e56b9dab955a33970f3c 100644 (file)
@@ -52,6 +52,7 @@
 #define METHOD_NAME__CBA        "_CBA"
 #define METHOD_NAME__CID        "_CID"
 #define METHOD_NAME__CRS        "_CRS"
+#define METHOD_NAME__DDN        "_DDN"
 #define METHOD_NAME__HID        "_HID"
 #define METHOD_NAME__INI        "_INI"
 #define METHOD_NAME__PLD        "_PLD"
index 57ee0528aacb16db912a11571c518bd0fc9eb5b5..f34a0835aa4f230f47c57d67e64425d80ba851b7 100644 (file)
@@ -433,6 +433,7 @@ int acpi_device_set_power(struct acpi_device *device, int state);
 int acpi_bus_init_power(struct acpi_device *device);
 int acpi_device_fix_up_power(struct acpi_device *device);
 int acpi_bus_update_power(acpi_handle handle, int *state_p);
+int acpi_device_update_power(struct acpi_device *device, int *state_p);
 bool acpi_bus_power_manageable(acpi_handle handle);
 
 #ifdef CONFIG_PM
index 9fc1d71c82bc13faec7d409ebdc280f947544774..ab2acf629a649a4ae399bf00581ed8dfb6dea530 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20140828
+#define ACPI_CA_VERSION                 0x20140926
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index ac03ec81d342c3a1cb6d25861c51b1b5c6a14dd8..7000e66f768eabd9893484d22b7b86055b8c471f 100644 (file)
@@ -721,7 +721,7 @@ typedef u32 acpi_event_type;
  *          |     | | +--- Enabled for wake?
  *          |     | +----- Set?
  *          |     +------- Has a handler?
- *          +----------- <Reserved>
+ *          +------------- <Reserved>
  */
 typedef u32 acpi_event_status;
 
@@ -729,7 +729,7 @@ typedef u32 acpi_event_status;
 #define ACPI_EVENT_FLAG_ENABLED         (acpi_event_status) 0x01
 #define ACPI_EVENT_FLAG_WAKE_ENABLED    (acpi_event_status) 0x02
 #define ACPI_EVENT_FLAG_SET             (acpi_event_status) 0x04
-#define ACPI_EVENT_FLAG_HANDLE         (acpi_event_status) 0x08
+#define ACPI_EVENT_FLAG_HAS_HANDLER     (acpi_event_status) 0x08
 
 /* Actions for acpi_set_gpe, acpi_gpe_wakeup, acpi_hw_low_set_gpe */
 
index 01f227e14254f21b86e8c4b44d84ed3f81a55850..b59b5a52637ec78397262862b06796b5d2fa2329 100644 (file)
@@ -5,6 +5,119 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
+#ifndef CONFIG_SMP
+/*
+ * The following implementation only for uniprocessor machines.
+ * For UP, it's relies on the fact that pagefault_disable() also disables
+ * preemption to ensure mutual exclusion.
+ *
+ */
+
+/**
+ * futex_atomic_op_inuser() - Atomic arithmetic operation with constant
+ *                       argument and comparison of the previous
+ *                       futex value with another constant.
+ *
+ * @encoded_op:        encoded operation to execute
+ * @uaddr:     pointer to user space address
+ *
+ * Return:
+ * 0 - On success
+ * <0 - On error
+ */
+static inline int
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval, ret;
+       u32 tmp;
+
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       pagefault_disable();
+
+       ret = -EFAULT;
+       if (unlikely(get_user(oldval, uaddr) != 0))
+               goto out_pagefault_enable;
+
+       ret = 0;
+       tmp = oldval;
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               tmp = oparg;
+               break;
+       case FUTEX_OP_ADD:
+               tmp += oparg;
+               break;
+       case FUTEX_OP_OR:
+               tmp |= oparg;
+               break;
+       case FUTEX_OP_ANDN:
+               tmp &= ~oparg;
+               break;
+       case FUTEX_OP_XOR:
+               tmp ^= oparg;
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
+               ret = -EFAULT;
+
+out_pagefault_enable:
+       pagefault_enable();
+
+       if (ret == 0) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+/**
+ * futex_atomic_cmpxchg_inatomic() - Compare and exchange the content of the
+ *                             uaddr with newval if the current value is
+ *                             oldval.
+ * @uval:      pointer to store content of @uaddr
+ * @uaddr:     pointer to user space address
+ * @oldval:    old value
+ * @newval:    new value to store to @uaddr
+ *
+ * Return:
+ * 0 - On success
+ * <0 - On error
+ */
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+                             u32 oldval, u32 newval)
+{
+       u32 val;
+
+       if (unlikely(get_user(val, uaddr) != 0))
+               return -EFAULT;
+
+       if (val == oldval && unlikely(put_user(newval, uaddr) != 0))
+               return -EFAULT;
+
+       *uval = val;
+
+       return 0;
+}
+
+#else
 static inline int
 futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
@@ -54,4 +167,5 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
        return -ENOSYS;
 }
 
+#endif /* CONFIG_SMP */
 #endif
index b8fdc57a733515b8b0b031da68ac5a9f8eda74ae..9db042304df37d0c97eea09be466fa403d505603 100644 (file)
@@ -12,6 +12,7 @@
 #define __ASM_GENERIC_IO_H
 
 #include <asm/page.h> /* I/O is all done through memory accesses */
+#include <linux/string.h> /* for memset() and memcpy() */
 #include <linux/types.h>
 
 #ifdef CONFIG_GENERIC_IOMAP
 #define mmiowb() do {} while (0)
 #endif
 
-/*****************************************************************************/
 /*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the simple architectures, we just read/write the
- * memory location directly.
+ * __raw_{read,write}{b,w,l,q}() access memory in native endianness.
+ *
+ * On some architectures memory mapped IO needs to be accessed differently.
+ * On the simple architectures, we just read/write the memory location
+ * directly.
  */
+
 #ifndef __raw_readb
+#define __raw_readb __raw_readb
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
-       return *(const volatile u8 __force *) addr;
+       return *(const volatile u8 __force *)addr;
 }
 #endif
 
 #ifndef __raw_readw
+#define __raw_readw __raw_readw
 static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
-       return *(const volatile u16 __force *) addr;
+       return *(const volatile u16 __force *)addr;
 }
 #endif
 
 #ifndef __raw_readl
+#define __raw_readl __raw_readl
 static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
-       return *(const volatile u32 __force *) addr;
+       return *(const volatile u32 __force *)addr;
 }
 #endif
 
-#define readb __raw_readb
-
-#define readw readw
-static inline u16 readw(const volatile void __iomem *addr)
-{
-       return __le16_to_cpu(__raw_readw(addr));
-}
-
-#define readl readl
-static inline u32 readl(const volatile void __iomem *addr)
+#ifdef CONFIG_64BIT
+#ifndef __raw_readq
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
 {
-       return __le32_to_cpu(__raw_readl(addr));
+       return *(const volatile u64 __force *)addr;
 }
+#endif
+#endif /* CONFIG_64BIT */
 
 #ifndef __raw_writeb
-static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 value, volatile void __iomem *addr)
 {
-       *(volatile u8 __force *) addr = b;
+       *(volatile u8 __force *)addr = value;
 }
 #endif
 
 #ifndef __raw_writew
-static inline void __raw_writew(u16 b, volatile void __iomem *addr)
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 value, volatile void __iomem *addr)
 {
-       *(volatile u16 __force *) addr = b;
+       *(volatile u16 __force *)addr = value;
 }
 #endif
 
 #ifndef __raw_writel
-static inline void __raw_writel(u32 b, volatile void __iomem *addr)
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 value, volatile void __iomem *addr)
 {
-       *(volatile u32 __force *) addr = b;
+       *(volatile u32 __force *)addr = value;
 }
 #endif
 
-#define writeb __raw_writeb
-#define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr)
-#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr)
-
 #ifdef CONFIG_64BIT
-#ifndef __raw_readq
-static inline u64 __raw_readq(const volatile void __iomem *addr)
+#ifndef __raw_writeq
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 value, volatile void __iomem *addr)
 {
-       return *(const volatile u64 __force *) addr;
+       *(volatile u64 __force *)addr = value;
 }
 #endif
+#endif /* CONFIG_64BIT */
 
-#define readq readq
-static inline u64 readq(const volatile void __iomem *addr)
-{
-       return __le64_to_cpu(__raw_readq(addr));
-}
+/*
+ * {read,write}{b,w,l,q}() access little endian memory and return result in
+ * native endianness.
+ */
 
-#ifndef __raw_writeq
-static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
+#ifndef readb
+#define readb readb
+static inline u8 readb(const volatile void __iomem *addr)
 {
-       *(volatile u64 __force *) addr = b;
+       return __raw_readb(addr);
 }
 #endif
 
-#define writeq(b, addr) __raw_writeq(__cpu_to_le64(b), addr)
-#endif /* CONFIG_64BIT */
-
-#ifndef PCI_IOBASE
-#define PCI_IOBASE ((void __iomem *) 0)
+#ifndef readw
+#define readw readw
+static inline u16 readw(const volatile void __iomem *addr)
+{
+       return __le16_to_cpu(__raw_readw(addr));
+}
 #endif
 
-/*****************************************************************************/
-/*
- * traditional input/output functions
- */
-
-static inline u8 inb(unsigned long addr)
+#ifndef readl
+#define readl readl
+static inline u32 readl(const volatile void __iomem *addr)
 {
-       return readb(addr + PCI_IOBASE);
+       return __le32_to_cpu(__raw_readl(addr));
 }
+#endif
 
-static inline u16 inw(unsigned long addr)
+#ifdef CONFIG_64BIT
+#ifndef readq
+#define readq readq
+static inline u64 readq(const volatile void __iomem *addr)
 {
-       return readw(addr + PCI_IOBASE);
+       return __le64_to_cpu(__raw_readq(addr));
 }
+#endif
+#endif /* CONFIG_64BIT */
 
-static inline u32 inl(unsigned long addr)
+#ifndef writeb
+#define writeb writeb
+static inline void writeb(u8 value, volatile void __iomem *addr)
 {
-       return readl(addr + PCI_IOBASE);
+       __raw_writeb(value, addr);
 }
+#endif
 
-static inline void outb(u8 b, unsigned long addr)
+#ifndef writew
+#define writew writew
+static inline void writew(u16 value, volatile void __iomem *addr)
 {
-       writeb(b, addr + PCI_IOBASE);
+       __raw_writew(cpu_to_le16(value), addr);
 }
+#endif
 
-static inline void outw(u16 b, unsigned long addr)
+#ifndef writel
+#define writel writel
+static inline void writel(u32 value, volatile void __iomem *addr)
 {
-       writew(b, addr + PCI_IOBASE);
+       __raw_writel(__cpu_to_le32(value), addr);
 }
+#endif
 
-static inline void outl(u32 b, unsigned long addr)
+#ifdef CONFIG_64BIT
+#ifndef writeq
+#define writeq writeq
+static inline void writeq(u64 value, volatile void __iomem *addr)
 {
-       writel(b, addr + PCI_IOBASE);
+       __raw_writeq(__cpu_to_le64(value), addr);
 }
+#endif
+#endif /* CONFIG_64BIT */
+
+/*
+ * {read,write}{b,w,l,q}_relaxed() are like the regular version, but
+ * are not guaranteed to provide ordering against spinlocks or memory
+ * accesses.
+ */
+#ifndef readb_relaxed
+#define readb_relaxed readb
+#endif
 
-#define inb_p(addr)    inb(addr)
-#define inw_p(addr)    inw(addr)
-#define inl_p(addr)    inl(addr)
-#define outb_p(x, addr)        outb((x), (addr))
-#define outw_p(x, addr)        outw((x), (addr))
-#define outl_p(x, addr)        outl((x), (addr))
+#ifndef readw_relaxed
+#define readw_relaxed readw
+#endif
 
-#ifndef insb
-static inline void insb(unsigned long addr, void *buffer, int count)
+#ifndef readl_relaxed
+#define readl_relaxed readl
+#endif
+
+#ifndef readq_relaxed
+#define readq_relaxed readq
+#endif
+
+#ifndef writeb_relaxed
+#define writeb_relaxed writeb
+#endif
+
+#ifndef writew_relaxed
+#define writew_relaxed writew
+#endif
+
+#ifndef writel_relaxed
+#define writel_relaxed writel
+#endif
+
+#ifndef writeq_relaxed
+#define writeq_relaxed writeq
+#endif
+
+/*
+ * {read,write}s{b,w,l,q}() repeatedly access the same memory address in
+ * native endianness in 8-, 16-, 32- or 64-bit chunks (@count times).
+ */
+#ifndef readsb
+#define readsb readsb
+static inline void readsb(const volatile void __iomem *addr, void *buffer,
+                         unsigned int count)
 {
        if (count) {
                u8 *buf = buffer;
+
                do {
-                       u8 x = __raw_readb(addr + PCI_IOBASE);
+                       u8 x = __raw_readb(addr);
                        *buf++ = x;
                } while (--count);
        }
 }
 #endif
 
-#ifndef insw
-static inline void insw(unsigned long addr, void *buffer, int count)
+#ifndef readsw
+#define readsw readsw
+static inline void readsw(const volatile void __iomem *addr, void *buffer,
+                         unsigned int count)
 {
        if (count) {
                u16 *buf = buffer;
+
                do {
-                       u16 x = __raw_readw(addr + PCI_IOBASE);
+                       u16 x = __raw_readw(addr);
                        *buf++ = x;
                } while (--count);
        }
 }
 #endif
 
-#ifndef insl
-static inline void insl(unsigned long addr, void *buffer, int count)
+#ifndef readsl
+#define readsl readsl
+static inline void readsl(const volatile void __iomem *addr, void *buffer,
+                         unsigned int count)
 {
        if (count) {
                u32 *buf = buffer;
+
                do {
-                       u32 x = __raw_readl(addr + PCI_IOBASE);
+                       u32 x = __raw_readl(addr);
                        *buf++ = x;
                } while (--count);
        }
 }
 #endif
 
-#ifndef outsb
-static inline void outsb(unsigned long addr, const void *buffer, int count)
+#ifdef CONFIG_64BIT
+#ifndef readsq
+#define readsq readsq
+static inline void readsq(const volatile void __iomem *addr, void *buffer,
+                         unsigned int count)
+{
+       if (count) {
+               u64 *buf = buffer;
+
+               do {
+                       u64 x = __raw_readq(addr);
+                       *buf++ = x;
+               } while (--count);
+       }
+}
+#endif
+#endif /* CONFIG_64BIT */
+
+#ifndef writesb
+#define writesb writesb
+static inline void writesb(volatile void __iomem *addr, const void *buffer,
+                          unsigned int count)
 {
        if (count) {
                const u8 *buf = buffer;
+
                do {
-                       __raw_writeb(*buf++, addr + PCI_IOBASE);
+                       __raw_writeb(*buf++, addr);
                } while (--count);
        }
 }
 #endif
 
-#ifndef outsw
-static inline void outsw(unsigned long addr, const void *buffer, int count)
+#ifndef writesw
+#define writesw writesw
+static inline void writesw(volatile void __iomem *addr, const void *buffer,
+                          unsigned int count)
 {
        if (count) {
                const u16 *buf = buffer;
+
                do {
-                       __raw_writew(*buf++, addr + PCI_IOBASE);
+                       __raw_writew(*buf++, addr);
                } while (--count);
        }
 }
 #endif
 
-#ifndef outsl
-static inline void outsl(unsigned long addr, const void *buffer, int count)
+#ifndef writesl
+#define writesl writesl
+static inline void writesl(volatile void __iomem *addr, const void *buffer,
+                          unsigned int count)
 {
        if (count) {
                const u32 *buf = buffer;
+
                do {
-                       __raw_writel(*buf++, addr + PCI_IOBASE);
+                       __raw_writel(*buf++, addr);
                } while (--count);
        }
 }
 #endif
 
-#ifndef CONFIG_GENERIC_IOMAP
-#define ioread8(addr)          readb(addr)
-#define ioread16(addr)         readw(addr)
-#define ioread16be(addr)       __be16_to_cpu(__raw_readw(addr))
-#define ioread32(addr)         readl(addr)
-#define ioread32be(addr)       __be32_to_cpu(__raw_readl(addr))
-
-#define iowrite8(v, addr)      writeb((v), (addr))
-#define iowrite16(v, addr)     writew((v), (addr))
-#define iowrite16be(v, addr)   __raw_writew(__cpu_to_be16(v), addr)
-#define iowrite32(v, addr)     writel((v), (addr))
-#define iowrite32be(v, addr)   __raw_writel(__cpu_to_be32(v), addr)
-
-#define ioread8_rep(p, dst, count) \
-       insb((unsigned long) (p), (dst), (count))
-#define ioread16_rep(p, dst, count) \
-       insw((unsigned long) (p), (dst), (count))
-#define ioread32_rep(p, dst, count) \
-       insl((unsigned long) (p), (dst), (count))
-
-#define iowrite8_rep(p, src, count) \
-       outsb((unsigned long) (p), (src), (count))
-#define iowrite16_rep(p, src, count) \
-       outsw((unsigned long) (p), (src), (count))
-#define iowrite32_rep(p, src, count) \
-       outsl((unsigned long) (p), (src), (count))
-#endif /* CONFIG_GENERIC_IOMAP */
+#ifdef CONFIG_64BIT
+#ifndef writesq
+#define writesq writesq
+static inline void writesq(volatile void __iomem *addr, const void *buffer,
+                          unsigned int count)
+{
+       if (count) {
+               const u64 *buf = buffer;
+
+               do {
+                       __raw_writeq(*buf++, addr);
+               } while (--count);
+       }
+}
+#endif
+#endif /* CONFIG_64BIT */
+
+#ifndef PCI_IOBASE
+#define PCI_IOBASE ((void __iomem *)0)
+#endif
 
 #ifndef IO_SPACE_LIMIT
 #define IO_SPACE_LIMIT 0xffff
 #endif
 
+/*
+ * {in,out}{b,w,l}() access little endian I/O. {in,out}{b,w,l}_p() can be
+ * implemented on hardware that needs an additional delay for I/O accesses to
+ * take effect.
+ */
+
+#ifndef inb
+#define inb inb
+static inline u8 inb(unsigned long addr)
+{
+       return readb(PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef inw
+#define inw inw
+static inline u16 inw(unsigned long addr)
+{
+       return readw(PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef inl
+#define inl inl
+static inline u32 inl(unsigned long addr)
+{
+       return readl(PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef outb
+#define outb outb
+static inline void outb(u8 value, unsigned long addr)
+{
+       writeb(value, PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef outw
+#define outw outw
+static inline void outw(u16 value, unsigned long addr)
+{
+       writew(value, PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef outl
+#define outl outl
+static inline void outl(u32 value, unsigned long addr)
+{
+       writel(value, PCI_IOBASE + addr);
+}
+#endif
+
+#ifndef inb_p
+#define inb_p inb_p
+static inline u8 inb_p(unsigned long addr)
+{
+       return inb(addr);
+}
+#endif
+
+#ifndef inw_p
+#define inw_p inw_p
+static inline u16 inw_p(unsigned long addr)
+{
+       return inw(addr);
+}
+#endif
+
+#ifndef inl_p
+#define inl_p inl_p
+static inline u32 inl_p(unsigned long addr)
+{
+       return inl(addr);
+}
+#endif
+
+#ifndef outb_p
+#define outb_p outb_p
+static inline void outb_p(u8 value, unsigned long addr)
+{
+       outb(value, addr);
+}
+#endif
+
+#ifndef outw_p
+#define outw_p outw_p
+static inline void outw_p(u16 value, unsigned long addr)
+{
+       outw(value, addr);
+}
+#endif
+
+#ifndef outl_p
+#define outl_p outl_p
+static inline void outl_p(u32 value, unsigned long addr)
+{
+       outl(value, addr);
+}
+#endif
+
+/*
+ * {in,out}s{b,w,l}{,_p}() are variants of the above that repeatedly access a
+ * single I/O port multiple times.
+ */
+
+#ifndef insb
+#define insb insb
+static inline void insb(unsigned long addr, void *buffer, unsigned int count)
+{
+       readsb(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef insw
+#define insw insw
+static inline void insw(unsigned long addr, void *buffer, unsigned int count)
+{
+       readsw(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef insl
+#define insl insl
+static inline void insl(unsigned long addr, void *buffer, unsigned int count)
+{
+       readsl(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef outsb
+#define outsb outsb
+static inline void outsb(unsigned long addr, const void *buffer,
+                        unsigned int count)
+{
+       writesb(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef outsw
+#define outsw outsw
+static inline void outsw(unsigned long addr, const void *buffer,
+                        unsigned int count)
+{
+       writesw(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef outsl
+#define outsl outsl
+static inline void outsl(unsigned long addr, const void *buffer,
+                        unsigned int count)
+{
+       writesl(PCI_IOBASE + addr, buffer, count);
+}
+#endif
+
+#ifndef insb_p
+#define insb_p insb_p
+static inline void insb_p(unsigned long addr, void *buffer, unsigned int count)
+{
+       insb(addr, buffer, count);
+}
+#endif
+
+#ifndef insw_p
+#define insw_p insw_p
+static inline void insw_p(unsigned long addr, void *buffer, unsigned int count)
+{
+       insw(addr, buffer, count);
+}
+#endif
+
+#ifndef insl_p
+#define insl_p insl_p
+static inline void insl_p(unsigned long addr, void *buffer, unsigned int count)
+{
+       insl(addr, buffer, count);
+}
+#endif
+
+#ifndef outsb_p
+#define outsb_p outsb_p
+static inline void outsb_p(unsigned long addr, const void *buffer,
+                          unsigned int count)
+{
+       outsb(addr, buffer, count);
+}
+#endif
+
+#ifndef outsw_p
+#define outsw_p outsw_p
+static inline void outsw_p(unsigned long addr, const void *buffer,
+                          unsigned int count)
+{
+       outsw(addr, buffer, count);
+}
+#endif
+
+#ifndef outsl_p
+#define outsl_p outsl_p
+static inline void outsl_p(unsigned long addr, const void *buffer,
+                          unsigned int count)
+{
+       outsl(addr, buffer, count);
+}
+#endif
+
+#ifndef CONFIG_GENERIC_IOMAP
+#ifndef ioread8
+#define ioread8 ioread8
+static inline u8 ioread8(const volatile void __iomem *addr)
+{
+       return readb(addr);
+}
+#endif
+
+#ifndef ioread16
+#define ioread16 ioread16
+static inline u16 ioread16(const volatile void __iomem *addr)
+{
+       return readw(addr);
+}
+#endif
+
+#ifndef ioread32
+#define ioread32 ioread32
+static inline u32 ioread32(const volatile void __iomem *addr)
+{
+       return readl(addr);
+}
+#endif
+
+#ifndef iowrite8
+#define iowrite8 iowrite8
+static inline void iowrite8(u8 value, volatile void __iomem *addr)
+{
+       writeb(value, addr);
+}
+#endif
+
+#ifndef iowrite16
+#define iowrite16 iowrite16
+static inline void iowrite16(u16 value, volatile void __iomem *addr)
+{
+       writew(value, addr);
+}
+#endif
+
+#ifndef iowrite32
+#define iowrite32 iowrite32
+static inline void iowrite32(u32 value, volatile void __iomem *addr)
+{
+       writel(value, addr);
+}
+#endif
+
+#ifndef ioread16be
+#define ioread16be ioread16be
+static inline u16 ioread16be(const volatile void __iomem *addr)
+{
+       return __be16_to_cpu(__raw_readw(addr));
+}
+#endif
+
+#ifndef ioread32be
+#define ioread32be ioread32be
+static inline u32 ioread32be(const volatile void __iomem *addr)
+{
+       return __be32_to_cpu(__raw_readl(addr));
+}
+#endif
+
+#ifndef iowrite16be
+#define iowrite16be iowrite16be
+static inline void iowrite16be(u16 value, void volatile __iomem *addr)
+{
+       __raw_writew(__cpu_to_be16(value), addr);
+}
+#endif
+
+#ifndef iowrite32be
+#define iowrite32be iowrite32be
+static inline void iowrite32be(u32 value, volatile void __iomem *addr)
+{
+       __raw_writel(__cpu_to_be32(value), addr);
+}
+#endif
+
+#ifndef ioread8_rep
+#define ioread8_rep ioread8_rep
+static inline void ioread8_rep(const volatile void __iomem *addr, void *buffer,
+                              unsigned int count)
+{
+       readsb(addr, buffer, count);
+}
+#endif
+
+#ifndef ioread16_rep
+#define ioread16_rep ioread16_rep
+static inline void ioread16_rep(const volatile void __iomem *addr,
+                               void *buffer, unsigned int count)
+{
+       readsw(addr, buffer, count);
+}
+#endif
+
+#ifndef ioread32_rep
+#define ioread32_rep ioread32_rep
+static inline void ioread32_rep(const volatile void __iomem *addr,
+                               void *buffer, unsigned int count)
+{
+       readsl(addr, buffer, count);
+}
+#endif
+
+#ifndef iowrite8_rep
+#define iowrite8_rep iowrite8_rep
+static inline void iowrite8_rep(volatile void __iomem *addr,
+                               const void *buffer,
+                               unsigned int count)
+{
+       writesb(addr, buffer, count);
+}
+#endif
+
+#ifndef iowrite16_rep
+#define iowrite16_rep iowrite16_rep
+static inline void iowrite16_rep(volatile void __iomem *addr,
+                                const void *buffer,
+                                unsigned int count)
+{
+       writesw(addr, buffer, count);
+}
+#endif
+
+#ifndef iowrite32_rep
+#define iowrite32_rep iowrite32_rep
+static inline void iowrite32_rep(volatile void __iomem *addr,
+                                const void *buffer,
+                                unsigned int count)
+{
+       writesl(addr, buffer, count);
+}
+#endif
+#endif /* CONFIG_GENERIC_IOMAP */
+
 #ifdef __KERNEL__
 
 #include <linux/vmalloc.h>
-#define __io_virt(x) ((void __force *) (x))
+#define __io_virt(x) ((void __force *)(x))
 
 #ifndef CONFIG_GENERIC_IOMAP
 struct pci_dev;
 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
 
 #ifndef pci_iounmap
+#define pci_iounmap pci_iounmap
 static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
 {
 }
@@ -289,11 +721,15 @@ static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
  * These are pretty trivial
  */
 #ifndef virt_to_phys
+#define virt_to_phys virt_to_phys
 static inline unsigned long virt_to_phys(volatile void *address)
 {
        return __pa((unsigned long)address);
 }
+#endif
 
+#ifndef phys_to_virt
+#define phys_to_virt phys_to_virt
 static inline void *phys_to_virt(unsigned long address)
 {
        return __va(address);
@@ -306,37 +742,65 @@ static inline void *phys_to_virt(unsigned long address)
  * This implementation is for the no-MMU case only... if you have an MMU
  * you'll need to provide your own definitions.
  */
+
 #ifndef CONFIG_MMU
-static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
+#ifndef ioremap
+#define ioremap ioremap
+static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
 {
-       return (void __iomem*) (unsigned long)offset;
+       return (void __iomem *)(unsigned long)offset;
 }
+#endif
 
-#define __ioremap(offset, size, flags) ioremap(offset, size)
+#ifndef __ioremap
+#define __ioremap __ioremap
+static inline void __iomem *__ioremap(phys_addr_t offset, size_t size,
+                                     unsigned long flags)
+{
+       return ioremap(offset, size);
+}
+#endif
 
 #ifndef ioremap_nocache
-#define ioremap_nocache ioremap
+#define ioremap_nocache ioremap_nocache
+static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
+{
+       return ioremap(offset, size);
+}
 #endif
 
 #ifndef ioremap_wc
-#define ioremap_wc ioremap_nocache
+#define ioremap_wc ioremap_wc
+static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
+{
+       return ioremap_nocache(offset, size);
+}
 #endif
 
+#ifndef iounmap
+#define iounmap iounmap
 static inline void iounmap(void __iomem *addr)
 {
 }
+#endif
 #endif /* CONFIG_MMU */
 
 #ifdef CONFIG_HAS_IOPORT_MAP
 #ifndef CONFIG_GENERIC_IOMAP
+#ifndef ioport_map
+#define ioport_map ioport_map
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
        return PCI_IOBASE + (port & IO_SPACE_LIMIT);
 }
+#endif
 
+#ifndef ioport_unmap
+#define ioport_unmap ioport_unmap
 static inline void ioport_unmap(void __iomem *p)
 {
 }
+#endif
 #else /* CONFIG_GENERIC_IOMAP */
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
 extern void ioport_unmap(void __iomem *p);
@@ -344,35 +808,68 @@ extern void ioport_unmap(void __iomem *p);
 #endif /* CONFIG_HAS_IOPORT_MAP */
 
 #ifndef xlate_dev_kmem_ptr
-#define xlate_dev_kmem_ptr(p)  p
+#define xlate_dev_kmem_ptr xlate_dev_kmem_ptr
+static inline void *xlate_dev_kmem_ptr(void *addr)
+{
+       return addr;
+}
 #endif
+
 #ifndef xlate_dev_mem_ptr
-#define xlate_dev_mem_ptr(p)   __va(p)
+#define xlate_dev_mem_ptr xlate_dev_mem_ptr
+static inline void *xlate_dev_mem_ptr(phys_addr_t addr)
+{
+       return __va(addr);
+}
+#endif
+
+#ifndef unxlate_dev_mem_ptr
+#define unxlate_dev_mem_ptr unxlate_dev_mem_ptr
+static inline void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
+{
+}
 #endif
 
 #ifdef CONFIG_VIRT_TO_BUS
 #ifndef virt_to_bus
-static inline unsigned long virt_to_bus(volatile void *address)
+static inline unsigned long virt_to_bus(void *address)
 {
-       return ((unsigned long) address);
+       return (unsigned long)address;
 }
 
 static inline void *bus_to_virt(unsigned long address)
 {
-       return (void *) address;
+       return (void *)address;
 }
 #endif
 #endif
 
 #ifndef memset_io
-#define memset_io(a, b, c)     memset(__io_virt(a), (b), (c))
+#define memset_io memset_io
+static inline void memset_io(volatile void __iomem *addr, int value,
+                            size_t size)
+{
+       memset(__io_virt(addr), value, size);
+}
 #endif
 
 #ifndef memcpy_fromio
-#define memcpy_fromio(a, b, c) memcpy((a), __io_virt(b), (c))
+#define memcpy_fromio memcpy_fromio
+static inline void memcpy_fromio(void *buffer,
+                                const volatile void __iomem *addr,
+                                size_t size)
+{
+       memcpy(buffer, __io_virt(addr), size);
+}
 #endif
+
 #ifndef memcpy_toio
-#define memcpy_toio(a, b, c)   memcpy(__io_virt(a), (b), (c))
+#define memcpy_toio memcpy_toio
+static inline void memcpy_toio(volatile void __iomem *addr, const void *buffer,
+                              size_t size)
+{
+       memcpy(__io_virt(addr), buffer, size);
+}
 #endif
 
 #endif /* __KERNEL__ */
index 1cd3f5d767a81b18b8c3950701506e3f8bfcfc6c..eb6f9e6c30756f5f39605582cf34c0e48c6a3df1 100644 (file)
@@ -23,9 +23,6 @@ static __always_inline void preempt_count_set(int pc)
 /*
  * must be macros to avoid header recursion hell
  */
-#define task_preempt_count(p) \
-       (task_thread_info(p)->preempt_count & ~PREEMPT_NEED_RESCHED)
-
 #define init_task_preempt_count(p) do { \
        task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \
 } while (0)
diff --git a/include/asm-generic/seccomp.h b/include/asm-generic/seccomp.h
new file mode 100644 (file)
index 0000000..9fa1f65
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * include/asm-generic/seccomp.h
+ *
+ * Copyright (C) 2014 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@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_GENERIC_SECCOMP_H
+#define _ASM_GENERIC_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#if defined(CONFIG_COMPAT) && !defined(__NR_seccomp_read_32)
+#define __NR_seccomp_read_32           __NR_read
+#define __NR_seccomp_write_32          __NR_write
+#define __NR_seccomp_exit_32           __NR_exit
+#define __NR_seccomp_sigreturn_32      __NR_rt_sigreturn
+#endif /* CONFIG_COMPAT && ! already defined */
+
+#define __NR_seccomp_read              __NR_read
+#define __NR_seccomp_write             __NR_write
+#define __NR_seccomp_exit              __NR_exit
+#ifndef __NR_seccomp_sigreturn
+#define __NR_seccomp_sigreturn         __NR_rt_sigreturn
+#endif
+
+#endif /* _ASM_GENERIC_SECCOMP_H */
index 5672d7ea1fa066175b33c8f4c19457fcdc0614ed..08848050922e613f28a1d8f7e4b3ad4c34b463be 100644 (file)
@@ -96,10 +96,9 @@ struct mmu_gather {
 #endif
        unsigned long           start;
        unsigned long           end;
-       unsigned int            need_flush : 1, /* Did free PTEs */
        /* we are in the middle of an operation to clear
         * a full mm and can make some optimizations */
-                               fullmm : 1,
+       unsigned int            fullmm : 1,
        /* we have performed an operation which
         * requires a complete flush of the tlb */
                                need_flush_all : 1;
@@ -128,16 +127,54 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
                tlb_flush_mmu(tlb);
 }
 
+static inline void __tlb_adjust_range(struct mmu_gather *tlb,
+                                     unsigned long address)
+{
+       tlb->start = min(tlb->start, address);
+       tlb->end = max(tlb->end, address + PAGE_SIZE);
+}
+
+static inline void __tlb_reset_range(struct mmu_gather *tlb)
+{
+       tlb->start = TASK_SIZE;
+       tlb->end = 0;
+}
+
+/*
+ * In the case of tlb vma handling, we can optimise these away in the
+ * case where we're doing a full MM flush.  When we're doing a munmap,
+ * the vmas are adjusted to only cover the region to be torn down.
+ */
+#ifndef tlb_start_vma
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#endif
+
+#define __tlb_end_vma(tlb, vma)                                        \
+       do {                                                    \
+               if (!tlb->fullmm && tlb->end) {                 \
+                       tlb_flush(tlb);                         \
+                       __tlb_reset_range(tlb);                 \
+               }                                               \
+       } while (0)
+
+#ifndef tlb_end_vma
+#define tlb_end_vma    __tlb_end_vma
+#endif
+
+#ifndef __tlb_remove_tlb_entry
+#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
+#endif
+
 /**
  * tlb_remove_tlb_entry - remember a pte unmapping for later tlb invalidation.
  *
- * Record the fact that pte's were really umapped in ->need_flush, so we can
- * later optimise away the tlb invalidate.   This helps when userspace is
- * unmapping already-unmapped pages, which happens quite a lot.
+ * Record the fact that pte's were really unmapped by updating the range,
+ * so we can later optimise away the tlb invalidate.   This helps when
+ * userspace is unmapping already-unmapped pages, which happens quite a lot.
  */
 #define tlb_remove_tlb_entry(tlb, ptep, address)               \
        do {                                                    \
-               tlb->need_flush = 1;                            \
+               __tlb_adjust_range(tlb, address);               \
                __tlb_remove_tlb_entry(tlb, ptep, address);     \
        } while (0)
 
@@ -151,27 +188,27 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 
 #define tlb_remove_pmd_tlb_entry(tlb, pmdp, address)           \
        do {                                                    \
-               tlb->need_flush = 1;                            \
+               __tlb_adjust_range(tlb, address);               \
                __tlb_remove_pmd_tlb_entry(tlb, pmdp, address); \
        } while (0)
 
 #define pte_free_tlb(tlb, ptep, address)                       \
        do {                                                    \
-               tlb->need_flush = 1;                            \
+               __tlb_adjust_range(tlb, address);               \
                __pte_free_tlb(tlb, ptep, address);             \
        } while (0)
 
 #ifndef __ARCH_HAS_4LEVEL_HACK
 #define pud_free_tlb(tlb, pudp, address)                       \
        do {                                                    \
-               tlb->need_flush = 1;                            \
+               __tlb_adjust_range(tlb, address);               \
                __pud_free_tlb(tlb, pudp, address);             \
        } while (0)
 #endif
 
 #define pmd_free_tlb(tlb, pmdp, address)                       \
        do {                                                    \
-               tlb->need_flush = 1;                            \
+               __tlb_adjust_range(tlb, address);               \
                __pmd_free_tlb(tlb, pmdp, address);             \
        } while (0)
 
index e973540cd15baac6ab16836cdea2ce1df5ab10c7..2dd405c9be78d474fe4c1c11a70651b6741ab396 100644 (file)
@@ -74,7 +74,6 @@
        {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4C6E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
diff --git a/include/dt-bindings/arm/ux500_pm_domains.h b/include/dt-bindings/arm/ux500_pm_domains.h
new file mode 100644 (file)
index 0000000..398a6c0
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2014 Linaro Ltd.
+ *
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef _DT_BINDINGS_ARM_UX500_PM_DOMAINS_H
+#define _DT_BINDINGS_ARM_UX500_PM_DOMAINS_H
+
+#define DOMAIN_VAPE            0
+
+/* Number of PM domains. */
+#define NR_DOMAINS             (DOMAIN_VAPE + 1)
+
+#endif
index 5f2667ecd98ea07a170e49b4e016738587ada122..f4b7478e23c893b28893c6f262a1e1c29fe122d6 100644 (file)
 #define IMX5_CLK_OCRAM                 186
 #define IMX5_CLK_SAHARA_IPG_GATE       187
 #define IMX5_CLK_SATA_REF              188
-#define IMX5_CLK_END                   189
+#define IMX5_CLK_STEP_SEL              189
+#define IMX5_CLK_CPU_PODF_SEL          190
+#define IMX5_CLK_ARM                   191
+#define IMX5_CLK_END                   192
 
 #endif /* __DT_BINDINGS_CLOCK_IMX5_H */
index ddaef8620b2c2b72bbceb19e1068e302b8711ff4..b690cdba163b85b7c81a60cb1ac0cea8253dcc5c 100644 (file)
@@ -62,8 +62,8 @@
 #define IMX6QDL_CLK_USDHC3_SEL                 50
 #define IMX6QDL_CLK_USDHC4_SEL                 51
 #define IMX6QDL_CLK_ENFC_SEL                   52
-#define IMX6QDL_CLK_EMI_SEL                    53
-#define IMX6QDL_CLK_EMI_SLOW_SEL               54
+#define IMX6QDL_CLK_EIM_SEL                    53
+#define IMX6QDL_CLK_EIM_SLOW_SEL               54
 #define IMX6QDL_CLK_VDO_AXI_SEL                        55
 #define IMX6QDL_CLK_VPU_AXI_SEL                        56
 #define IMX6QDL_CLK_CKO1_SEL                   57
 #define IMX6QDL_CLK_USDHC4_PODF                        94
 #define IMX6QDL_CLK_ENFC_PRED                  95
 #define IMX6QDL_CLK_ENFC_PODF                  96
-#define IMX6QDL_CLK_EMI_PODF                   97
-#define IMX6QDL_CLK_EMI_SLOW_PODF              98
+#define IMX6QDL_CLK_EIM_PODF                   97
+#define IMX6QDL_CLK_EIM_SLOW_PODF              98
 #define IMX6QDL_CLK_VPU_AXI_PODF               99
 #define IMX6QDL_CLK_CKO1_PODF                  100
 #define IMX6QDL_CLK_AXI                                101
index a929f86d0dddd52816d6fdfc41905b8fab76da88..d72b5b35f15edd965b89de2c4759bd9bc964f14f 100644 (file)
@@ -60,7 +60,7 @@
 #define ESC1_CLK_SRC                   43
 #define HDMI_CLK_SRC                   44
 #define VSYNC_CLK_SRC                  45
-#define RBCPR_CLK_SRC                  46
+#define MMSS_RBCPR_CLK_SRC             46
 #define RBBMTIMER_CLK_SRC              47
 #define MAPLE_CLK_SRC                  48
 #define VDP_CLK_SRC                    49
index f6b4b0fe7a43313c2ee7ba60b8fd915e3cbf0a84..476135da0f238811889460a6ca524230fc51a368 100644 (file)
@@ -40,6 +40,7 @@
 
 /* MSTP2 */
 #define R8A7740_CLK_SCIFA6     30
+#define R8A7740_CLK_INTCA      29
 #define R8A7740_CLK_SCIFA7     22
 #define R8A7740_CLK_DMAC1      18
 #define R8A7740_CLK_DMAC2      17
index 8ea7ab0346ad9c28e248ad648401aff57a8c94bc..c27b3b5133b9442ea11bbe4d19e39769fad7956b 100644 (file)
 #define R8A7790_CLK_MSIOF0             0
 
 /* MSTP1 */
-#define R8A7790_CLK_JPU                6
+#define R8A7790_CLK_VCP1               0
+#define R8A7790_CLK_VCP0               1
+#define R8A7790_CLK_VPC1               2
+#define R8A7790_CLK_VPC0               3
+#define R8A7790_CLK_JPU                        6
+#define R8A7790_CLK_SSP1               9
 #define R8A7790_CLK_TMU1               11
+#define R8A7790_CLK_3DG                        12
+#define R8A7790_CLK_2DDMAC             15
+#define R8A7790_CLK_FDP1_2             17
+#define R8A7790_CLK_FDP1_1             18
+#define R8A7790_CLK_FDP1_0             19
 #define R8A7790_CLK_TMU3               21
 #define R8A7790_CLK_TMU2               22
 #define R8A7790_CLK_CMT0               24
@@ -68,6 +78,8 @@
 #define R8A7790_CLK_USBDMAC1           31
 
 /* MSTP5 */
+#define R8A7790_CLK_AUDIO_DMAC1                1
+#define R8A7790_CLK_AUDIO_DMAC0                2
 #define R8A7790_CLK_THERMAL            22
 #define R8A7790_CLK_PWM                        23
 
index 58c3f49d068c0e75887aa468f038d1d5fa5dd730..3ea2bbc0da3f585331ad1669a625b382860bd778 100644 (file)
 #define R8A7791_CLK_MSIOF0             0
 
 /* MSTP1 */
-#define R8A7791_CLK_JPU                6
+#define R8A7791_CLK_VCP0               1
+#define R8A7791_CLK_VPC0               3
+#define R8A7791_CLK_JPU                        6
+#define R8A7791_CLK_SSP1               9
 #define R8A7791_CLK_TMU1               11
+#define R8A7791_CLK_3DG                        12
+#define R8A7791_CLK_2DDMAC             15
+#define R8A7791_CLK_FDP1_1             18
+#define R8A7791_CLK_FDP1_0             19
 #define R8A7791_CLK_TMU3               21
 #define R8A7791_CLK_TMU2               22
 #define R8A7791_CLK_CMT0               24
@@ -62,6 +69,8 @@
 #define R8A7791_CLK_USBDMAC1           31
 
 /* MSTP5 */
+#define R8A7791_CLK_AUDIO_DMAC1                1
+#define R8A7791_CLK_AUDIO_DMAC0                2
 #define R8A7791_CLK_THERMAL            22
 #define R8A7791_CLK_PWM                        23
 
index 9ac1043e25bce45a20b45cf116404a0ccb9cdd26..aa9c286e60c0a322d10d45273686adb034591fa1 100644 (file)
 #define R8A7794_CLK_MSIOF0             0
 
 /* MSTP1 */
+#define R8A7794_CLK_VCP0               1
+#define R8A7794_CLK_VPC0               3
 #define R8A7794_CLK_TMU1               11
+#define R8A7794_CLK_3DG                        12
+#define R8A7794_CLK_2DDMAC             15
+#define R8A7794_CLK_FDP1_0             19
 #define R8A7794_CLK_TMU3               21
 #define R8A7794_CLK_TMU2               22
 #define R8A7794_CLK_CMT0               24
 #define R8A7794_CLK_TMU0               25
+#define R8A7794_CLK_VSP1_DU0           28
+#define R8A7794_CLK_VSP1_S             31
 
 /* MSTP2 */
 #define R8A7794_CLK_SCIFA2             2
@@ -61,6 +68,8 @@
 #define R8A7794_CLK_SCIF0              21
 
 /* MSTP8 */
+#define R8A7794_CLK_VIN1               10
+#define R8A7794_CLK_VIN0               11
 #define R8A7794_CLK_ETHER              13
 
 /* MSTP9 */
diff --git a/include/dt-bindings/clock/stih407-clks.h b/include/dt-bindings/clock/stih407-clks.h
new file mode 100644 (file)
index 0000000..7af2b71
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * This header provides constants clk index STMicroelectronics
+ * STiH407 SoC.
+ */
+#ifndef _DT_BINDINGS_CLK_STIH407
+#define _DT_BINDINGS_CLK_STIH407
+
+/* CLOCKGEN C0 */
+#define CLK_ICN_GPU            0
+#define CLK_FDMA               1
+#define CLK_NAND               2
+#define CLK_HVA                        3
+#define CLK_PROC_STFE          4
+#define CLK_PROC_TP            5
+#define CLK_RX_ICN_DMU         6
+#define CLK_RX_ICN_DISP_0      6
+#define CLK_RX_ICN_DISP_1      6
+#define CLK_RX_ICN_HVA         7
+#define CLK_RX_ICN_TS          7
+#define CLK_ICN_CPU            8
+#define CLK_TX_ICN_DMU         9
+#define CLK_TX_ICN_HVA         9
+#define CLK_TX_ICN_TS          9
+#define CLK_ICN_COMPO          9
+#define CLK_MMC_0              10
+#define CLK_MMC_1              11
+#define CLK_JPEGDEC            12
+#define CLK_ICN_REG            13
+#define CLK_TRACE_A9           13
+#define CLK_PTI_STM            13
+#define CLK_EXT2F_A9           13
+#define CLK_IC_BDISP_0         14
+#define CLK_IC_BDISP_1         15
+#define CLK_PP_DMU             16
+#define CLK_VID_DMU            17
+#define CLK_DSS_LPC            18
+#define CLK_ST231_AUD_0                19
+#define CLK_ST231_GP_0         19
+#define CLK_ST231_GP_1         20
+#define CLK_ST231_DMU          21
+#define CLK_ICN_LMI            22
+#define CLK_TX_ICN_DISP_0      23
+#define CLK_TX_ICN_DISP_1      23
+#define CLK_ICN_SBC            24
+#define CLK_STFE_FRC2          25
+#define CLK_ETH_PHY            26
+#define CLK_ETH_REF_PHYCLK     27
+#define CLK_FLASH_PROMIP       28
+#define CLK_MAIN_DISP          29
+#define CLK_AUX_DISP           30
+#define CLK_COMPO_DVP          31
+
+/* CLOCKGEN D0 */
+#define CLK_PCM_0              0
+#define CLK_PCM_1              1
+#define CLK_PCM_2              2
+#define CLK_SPDIFF             3
+
+/* CLOCKGEN D2 */
+#define CLK_PIX_MAIN_DISP      0
+#define CLK_PIX_PIP            1
+#define CLK_PIX_GDP1           2
+#define CLK_PIX_GDP2           3
+#define CLK_PIX_GDP3           4
+#define CLK_PIX_GDP4           5
+#define CLK_PIX_AUX_DISP       6
+#define CLK_DENC               7
+#define CLK_PIX_HDDAC          8
+#define CLK_HDDAC              9
+#define CLK_SDDAC              10
+#define CLK_PIX_DVO            11
+#define CLK_DVO                        12
+#define CLK_PIX_HDMI           13
+#define CLK_TMDS_HDMI          14
+#define CLK_REF_HDMIPHY                15
+
+/* CLOCKGEN D3 */
+#define CLK_STFE_FRC1          0
+#define CLK_TSOUT_0            1
+#define CLK_TSOUT_1            2
+#define CLK_MCHI               3
+#define CLK_VSENS_COMPO                4
+#define CLK_FRC1_REMOTE                5
+#define CLK_LPC_0              6
+#define CLK_LPC_1              7
+#endif
diff --git a/include/dt-bindings/clock/stih410-clks.h b/include/dt-bindings/clock/stih410-clks.h
new file mode 100644 (file)
index 0000000..2097a4b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This header provides constants clk index STMicroelectronics
+ * STiH410 SoC.
+ */
+#ifndef _DT_BINDINGS_CLK_STIH410
+#define _DT_BINDINGS_CLK_STIH410
+
+#include "stih407-clks.h"
+
+/* STiH410 introduces new clock outputs compared to STiH407 */
+
+/* CLOCKGEN C0 */
+#define CLK_TX_ICN_HADES       32
+#define CLK_RX_ICN_HADES       33
+#define CLK_ICN_REG_16         34
+#define CLK_PP_HADES           35
+#define CLK_CLUST_HADES                36
+#define CLK_HWPE_HADES         37
+#define CLK_FC_HADES           38
+
+/* CLOCKGEN D0 */
+#define CLK_PCMR10_MASTER      4
+#define CLK_USB2_PHY           5
+
+#endif
index fc12621fb4329188ed6a6a9da2efe8b7da3603a7..534c03f8ad72bc23675e0a4fe7761b2257f1b741 100644 (file)
@@ -49,7 +49,7 @@
 #define TEGRA114_CLK_I2S0 30
 /* 31 */
 
-/* 32 */
+#define TEGRA114_CLK_MC 32
 /* 33 */
 #define TEGRA114_CLK_APBDMA 34
 /* 35 */
index 6bac637fd635d16717b027b136ba70bba465276b..af9bc9a3ddbc561840b60f6f5416f19f846e8567 100644 (file)
@@ -48,7 +48,7 @@
 #define TEGRA124_CLK_I2S0 30
 /* 31 */
 
-/* 32 */
+#define TEGRA124_CLK_MC 32
 /* 33 */
 #define TEGRA124_CLK_APBDMA 34
 /* 35 */
index 9406207cfac8715b2545a8e77ae8bc7866e838fb..04500b243a4d89be0731a326baca289ee4efbd29 100644 (file)
@@ -49,7 +49,7 @@
 /* 30 */
 #define TEGRA20_CLK_CACHE2 31
 
-#define TEGRA20_CLK_MEM 32
+#define TEGRA20_CLK_MC 32
 #define TEGRA20_CLK_AHBDMA 33
 #define TEGRA20_CLK_APBDMA 34
 /* 35 */
index d6b56b21539b7e4e73bb80d927fc906d4d811e5c..801c0ac50c47f3ba80df69b9db99fda95d0db5e2 100644 (file)
 #define VF610_CLK_FASK_CLK_SEL         8
 #define VF610_CLK_AUDIO_EXT            9
 #define VF610_CLK_ENET_EXT             10
-#define VF610_CLK_PLL1_MAIN            11
+#define VF610_CLK_PLL1_SYS             11
 #define VF610_CLK_PLL1_PFD1            12
 #define VF610_CLK_PLL1_PFD2            13
 #define VF610_CLK_PLL1_PFD3            14
 #define VF610_CLK_PLL1_PFD4            15
-#define VF610_CLK_PLL2_MAIN            16
+#define VF610_CLK_PLL2_BUS             16
 #define VF610_CLK_PLL2_PFD1            17
 #define VF610_CLK_PLL2_PFD2            18
 #define VF610_CLK_PLL2_PFD3            19
 #define VF610_CLK_PLL2_PFD4            20
-#define VF610_CLK_PLL3_MAIN            21
+#define VF610_CLK_PLL3_USB_OTG         21
 #define VF610_CLK_PLL3_PFD1            22
 #define VF610_CLK_PLL3_PFD2            23
 #define VF610_CLK_PLL3_PFD3            24
 #define VF610_CLK_PLL3_PFD4            25
-#define VF610_CLK_PLL4_MAIN            26
-#define VF610_CLK_PLL5_MAIN            27
-#define VF610_CLK_PLL6_MAIN            28
+#define VF610_CLK_PLL4_AUDIO           26
+#define VF610_CLK_PLL5_ENET            27
+#define VF610_CLK_PLL6_VIDEO           28
 #define VF610_CLK_PLL3_MAIN_DIV                29
 #define VF610_CLK_PLL4_MAIN_DIV                30
 #define VF610_CLK_PLL6_MAIN_DIV                31
 #define VF610_CLK_DMAMUX3              153
 #define VF610_CLK_FLEXCAN0_EN          154
 #define VF610_CLK_FLEXCAN1_EN          155
-#define VF610_CLK_PLL7_MAIN            156
+#define VF610_CLK_PLL7_USB_HOST                156
 #define VF610_CLK_USBPHY0              157
 #define VF610_CLK_USBPHY1              158
-#define VF610_CLK_END                  159
+#define VF610_CLK_LVDS1_IN             159
+#define VF610_CLK_ANACLK1              160
+#define VF610_CLK_PLL1_BYPASS_SRC      161
+#define VF610_CLK_PLL2_BYPASS_SRC      162
+#define VF610_CLK_PLL3_BYPASS_SRC      163
+#define VF610_CLK_PLL4_BYPASS_SRC      164
+#define VF610_CLK_PLL5_BYPASS_SRC      165
+#define VF610_CLK_PLL6_BYPASS_SRC      166
+#define VF610_CLK_PLL7_BYPASS_SRC      167
+#define VF610_CLK_PLL1                 168
+#define VF610_CLK_PLL2                 169
+#define VF610_CLK_PLL3                 170
+#define VF610_CLK_PLL4                 171
+#define VF610_CLK_PLL5                 172
+#define VF610_CLK_PLL6                 173
+#define VF610_CLK_PLL7                 174
+#define VF610_PLL1_BYPASS              175
+#define VF610_PLL2_BYPASS              176
+#define VF610_PLL3_BYPASS              177
+#define VF610_PLL4_BYPASS              178
+#define VF610_PLL5_BYPASS              179
+#define VF610_PLL6_BYPASS              180
+#define VF610_PLL7_BYPASS              181
+#define VF610_CLK_END                  182
 
 #endif /* __DT_BINDINGS_CLOCK_VF610_H */
diff --git a/include/dt-bindings/memory/tegra114-mc.h b/include/dt-bindings/memory/tegra114-mc.h
new file mode 100644 (file)
index 0000000..8f48985
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef DT_BINDINGS_MEMORY_TEGRA114_MC_H
+#define DT_BINDINGS_MEMORY_TEGRA114_MC_H
+
+#define TEGRA_SWGROUP_PTC      0
+#define TEGRA_SWGROUP_DC       1
+#define TEGRA_SWGROUP_DCB      2
+#define TEGRA_SWGROUP_EPP      3
+#define TEGRA_SWGROUP_G2       4
+#define TEGRA_SWGROUP_AVPC     5
+#define TEGRA_SWGROUP_NV       6
+#define TEGRA_SWGROUP_HDA      7
+#define TEGRA_SWGROUP_HC       8
+#define TEGRA_SWGROUP_MSENC    9
+#define TEGRA_SWGROUP_PPCS     10
+#define TEGRA_SWGROUP_VDE      11
+#define TEGRA_SWGROUP_MPCORELP 12
+#define TEGRA_SWGROUP_MPCORE   13
+#define TEGRA_SWGROUP_VI       14
+#define TEGRA_SWGROUP_ISP      15
+#define TEGRA_SWGROUP_XUSB_HOST        16
+#define TEGRA_SWGROUP_XUSB_DEV 17
+#define TEGRA_SWGROUP_EMUCIF   18
+#define TEGRA_SWGROUP_TSEC     19
+
+#endif
diff --git a/include/dt-bindings/memory/tegra124-mc.h b/include/dt-bindings/memory/tegra124-mc.h
new file mode 100644 (file)
index 0000000..7d8ee79
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef DT_BINDINGS_MEMORY_TEGRA124_MC_H
+#define DT_BINDINGS_MEMORY_TEGRA124_MC_H
+
+#define TEGRA_SWGROUP_PTC      0
+#define TEGRA_SWGROUP_DC       1
+#define TEGRA_SWGROUP_DCB      2
+#define TEGRA_SWGROUP_AFI      3
+#define TEGRA_SWGROUP_AVPC     4
+#define TEGRA_SWGROUP_HDA      5
+#define TEGRA_SWGROUP_HC       6
+#define TEGRA_SWGROUP_MSENC    7
+#define TEGRA_SWGROUP_PPCS     8
+#define TEGRA_SWGROUP_SATA     9
+#define TEGRA_SWGROUP_VDE      10
+#define TEGRA_SWGROUP_MPCORELP 11
+#define TEGRA_SWGROUP_MPCORE   12
+#define TEGRA_SWGROUP_ISP2     13
+#define TEGRA_SWGROUP_XUSB_HOST        14
+#define TEGRA_SWGROUP_XUSB_DEV 15
+#define TEGRA_SWGROUP_ISP2B    16
+#define TEGRA_SWGROUP_TSEC     17
+#define TEGRA_SWGROUP_A9AVP    18
+#define TEGRA_SWGROUP_GPU      19
+#define TEGRA_SWGROUP_SDMMC1A  20
+#define TEGRA_SWGROUP_SDMMC2A  21
+#define TEGRA_SWGROUP_SDMMC3A  22
+#define TEGRA_SWGROUP_SDMMC4A  23
+#define TEGRA_SWGROUP_VIC      24
+#define TEGRA_SWGROUP_VI       25
+
+#endif
diff --git a/include/dt-bindings/memory/tegra30-mc.h b/include/dt-bindings/memory/tegra30-mc.h
new file mode 100644 (file)
index 0000000..502beb0
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef DT_BINDINGS_MEMORY_TEGRA30_MC_H
+#define DT_BINDINGS_MEMORY_TEGRA30_MC_H
+
+#define TEGRA_SWGROUP_PTC      0
+#define TEGRA_SWGROUP_DC       1
+#define TEGRA_SWGROUP_DCB      2
+#define TEGRA_SWGROUP_EPP      3
+#define TEGRA_SWGROUP_G2       4
+#define TEGRA_SWGROUP_MPE      5
+#define TEGRA_SWGROUP_VI       6
+#define TEGRA_SWGROUP_AFI      7
+#define TEGRA_SWGROUP_AVPC     8
+#define TEGRA_SWGROUP_NV       9
+#define TEGRA_SWGROUP_NV2      10
+#define TEGRA_SWGROUP_HDA      11
+#define TEGRA_SWGROUP_HC       12
+#define TEGRA_SWGROUP_PPCS     13
+#define TEGRA_SWGROUP_SATA     14
+#define TEGRA_SWGROUP_VDE      15
+#define TEGRA_SWGROUP_MPCORELP 16
+#define TEGRA_SWGROUP_MPCORE   17
+#define TEGRA_SWGROUP_ISP      18
+
+#endif
index 3d33794e4f3edd75950e58cb7d5c49f69e33795b..7448edff4723101b44877090ce9463bdb98d6d9c 100644 (file)
@@ -40,8 +40,8 @@
 
 /* Active pin states */
 #define PIN_OUTPUT             (0 | PULL_DIS)
-#define PIN_OUTPUT_PULLUP      (PIN_OUTPUT | PULL_ENA | PULL_UP)
-#define PIN_OUTPUT_PULLDOWN    (PIN_OUTPUT | PULL_ENA)
+#define PIN_OUTPUT_PULLUP      (PULL_UP)
+#define PIN_OUTPUT_PULLDOWN    (0)
 #define PIN_INPUT              (INPUT_EN | PULL_DIS)
 #define PIN_INPUT_SLEW         (INPUT_EN | SLEWCONTROL)
 #define PIN_INPUT_PULLUP       (PULL_ENA | INPUT_EN | PULL_UP)
diff --git a/include/dt-bindings/regulator/maxim,max77802.h b/include/dt-bindings/regulator/maxim,max77802.h
new file mode 100644 (file)
index 0000000..cf28631
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Device Tree binding constants for the Maxim 77802 PMIC regulators
+ */
+
+#ifndef _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H
+#define _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H
+
+/* Regulator operating modes */
+#define MAX77802_OPMODE_LP     1
+#define MAX77802_OPMODE_NORMAL 3
+
+#endif /* _DT_BINDINGS_REGULATOR_MAXIM_MAX77802_H */
diff --git a/include/dt-bindings/reset-controller/stih407-resets.h b/include/dt-bindings/reset-controller/stih407-resets.h
new file mode 100644 (file)
index 0000000..02d4328
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This header provides constants for the reset controller
+ * based peripheral powerdown requests on the STMicroelectronics
+ * STiH407 SoC.
+ */
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_STIH407
+#define _DT_BINDINGS_RESET_CONTROLLER_STIH407
+
+/* Powerdown requests control 0 */
+#define STIH407_EMISS_POWERDOWN                0
+#define STIH407_NAND_POWERDOWN         1
+
+/* Synp GMAC PowerDown */
+#define STIH407_ETH1_POWERDOWN         2
+
+/* Powerdown requests control 1 */
+#define STIH407_USB3_POWERDOWN         3
+#define STIH407_USB2_PORT1_POWERDOWN   4
+#define STIH407_USB2_PORT0_POWERDOWN   5
+#define STIH407_PCIE1_POWERDOWN                6
+#define STIH407_PCIE0_POWERDOWN                7
+#define STIH407_SATA1_POWERDOWN                8
+#define STIH407_SATA0_POWERDOWN                9
+
+/* Reset defines */
+#define STIH407_ETH1_SOFTRESET         0
+#define STIH407_MMC1_SOFTRESET         1
+#define STIH407_PICOPHY_SOFTRESET      2
+#define STIH407_IRB_SOFTRESET          3
+#define STIH407_PCIE0_SOFTRESET                4
+#define STIH407_PCIE1_SOFTRESET                5
+#define STIH407_SATA0_SOFTRESET                6
+#define STIH407_SATA1_SOFTRESET                7
+#define STIH407_MIPHY0_SOFTRESET       8
+#define STIH407_MIPHY1_SOFTRESET       9
+#define STIH407_MIPHY2_SOFTRESET       10
+#define STIH407_SATA0_PWR_SOFTRESET    11
+#define STIH407_SATA1_PWR_SOFTRESET    12
+#define STIH407_DELTA_SOFTRESET                13
+#define STIH407_BLITTER_SOFTRESET      14
+#define STIH407_HDTVOUT_SOFTRESET      15
+#define STIH407_HDQVDP_SOFTRESET       16
+#define STIH407_VDP_AUX_SOFTRESET      17
+#define STIH407_COMPO_SOFTRESET                18
+#define STIH407_HDMI_TX_PHY_SOFTRESET  19
+#define STIH407_JPEG_DEC_SOFTRESET     20
+#define STIH407_VP8_DEC_SOFTRESET      21
+#define STIH407_GPU_SOFTRESET          22
+#define STIH407_HVA_SOFTRESET          23
+#define STIH407_ERAM_HVA_SOFTRESET     24
+#define STIH407_LPM_SOFTRESET          25
+#define STIH407_KEYSCAN_SOFTRESET      26
+#define STIH407_USB2_PORT0_SOFTRESET   27
+#define STIH407_USB2_PORT1_SOFTRESET   28
+
+/* Picophy reset defines */
+#define STIH407_PICOPHY0_RESET         0
+#define STIH407_PICOPHY1_RESET         1
+#define STIH407_PICOPHY2_RESET         2
+
+#endif /* _DT_BINDINGS_RESET_CONTROLLER_STIH407 */
index b7926bb9b4442f90d2d7f32d8c11a07370bfe8c9..407a12f663ebdd313c166dcc4f5c892da1453ecf 100644 (file)
@@ -432,6 +432,7 @@ static inline bool acpi_driver_match_device(struct device *dev,
 int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
 int acpi_device_modalias(struct device *, char *, int);
 
+struct platform_device *acpi_create_platform_device(struct acpi_device *);
 #define ACPI_PTR(_ptr) (_ptr)
 
 #else  /* !CONFIG_ACPI */
index 91b77f8d495da646da8975014e9ce118f405880e..9177947bf032f2c19c01e3a9b5385741cfede896 100644 (file)
@@ -11,6 +11,7 @@
  * @detect_pin: GPIO pin wired to the card detect switch
  * @wp_pin: GPIO pin wired to the write protect sensor
  * @detect_is_active_high: The state of the detect pin when it is active
+ * @non_removable: The slot is not removable, only detect once
  *
  * If a given slot is not present on the board, @bus_width should be
  * set to 0. The other fields are ignored in this case.
@@ -26,6 +27,7 @@ struct mci_slot_pdata {
        int                     detect_pin;
        int                     wp_pin;
        bool                    detect_is_active_high;
+       bool                    non_removable;
 };
 
 /**
index 36dffeccebdbe4d9c76cecd02e400c82ef74998d..e58fe7df8b9c7eddf11e9995f3c95792b4923dc3 100644 (file)
@@ -90,7 +90,7 @@ extern unsigned compat_dir_class[];
 extern unsigned compat_chattr_class[];
 extern unsigned compat_signal_class[];
 
-extern int __weak audit_classify_compat_syscall(int abi, unsigned syscall);
+extern int audit_classify_compat_syscall(int abi, unsigned syscall);
 
 /* audit_names->type values */
 #define        AUDIT_TYPE_UNKNOWN      0       /* we don't know yet */
index be5fd38bd5a05d83eaac250055defcccacafe054..5d858e02997f5248d8a50150d870248e8146f4e6 100644 (file)
  * position @h. For example
  * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
  */
-#define GENMASK(h, l)          (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
-#define GENMASK_ULL(h, l)      (((U64_C(1) << ((h) - (l) + 1)) - 1) << (l))
+#define GENMASK(h, l) \
+       (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+#define GENMASK_ULL(h, l) \
+       (((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
 
 extern unsigned int __sw_hweight8(unsigned int w);
 extern unsigned int __sw_hweight16(unsigned int w);
index c9be1589415a0447a459bfec550d67115c2879d6..15f7034aa377ecd00367cb46d69003077ebadb06 100644 (file)
@@ -167,6 +167,23 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw,
                gfp_t gfp, bool reserved);
 struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag);
 
+enum {
+       BLK_MQ_UNIQUE_TAG_BITS = 16,
+       BLK_MQ_UNIQUE_TAG_MASK = (1 << BLK_MQ_UNIQUE_TAG_BITS) - 1,
+};
+
+u32 blk_mq_unique_tag(struct request *rq);
+
+static inline u16 blk_mq_unique_tag_to_hwq(u32 unique_tag)
+{
+       return unique_tag >> BLK_MQ_UNIQUE_TAG_BITS;
+}
+
+static inline u16 blk_mq_unique_tag_to_tag(u32 unique_tag)
+{
+       return unique_tag & BLK_MQ_UNIQUE_TAG_MASK;
+}
+
 struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index);
 struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *, unsigned int, int);
 
index 0207a78a8d82274546cb2436c2568a53559317f9..6d76b8b4aa2b04bb36add2778d42dd2bdce2a891 100644 (file)
@@ -1136,8 +1136,6 @@ static inline bool blk_needs_flush_plug(struct task_struct *tsk)
 /*
  * tag stuff
  */
-#define blk_rq_tagged(rq) \
-       ((rq)->mq_ctx || ((rq)->cmd_flags & REQ_QUEUED))
 extern int blk_queue_start_tag(struct request_queue *, struct request *);
 extern struct request *blk_queue_find_tag(struct request_queue *, int);
 extern void blk_queue_end_tag(struct request_queue *, struct request *);
@@ -1583,13 +1581,13 @@ static inline bool blk_integrity_merge_rq(struct request_queue *rq,
                                          struct request *r1,
                                          struct request *r2)
 {
-       return 0;
+       return true;
 }
 static inline bool blk_integrity_merge_bio(struct request_queue *rq,
                                           struct request *r,
                                           struct bio *b)
 {
-       return 0;
+       return true;
 }
 static inline bool blk_integrity_is_initialized(struct gendisk *g)
 {
index 4e2bd4c95b66ff245fa78d64a455267ac646fcff..0995c2de8162c2f6368647503ddda9017a68f6c6 100644 (file)
@@ -46,6 +46,7 @@ extern unsigned long init_bootmem_node(pg_data_t *pgdat,
 extern unsigned long init_bootmem(unsigned long addr, unsigned long memend);
 
 extern unsigned long free_all_bootmem(void);
+extern void reset_node_managed_pages(pg_data_t *pgdat);
 extern void reset_all_zones_managed_pages(void);
 
 extern void free_bootmem_node(pg_data_t *pgdat,
index 324329ceea1e89c48b8170f8886e4b0c88066e91..73b45225a7ca1bbe749ea3b62e38a35add22936b 100644 (file)
@@ -175,12 +175,13 @@ void __wait_on_buffer(struct buffer_head *);
 wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
 struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
                        unsigned size);
-struct buffer_head *__getblk(struct block_device *bdev, sector_t block,
-                       unsigned size);
+struct buffer_head *__getblk_gfp(struct block_device *bdev, sector_t block,
+                                 unsigned size, gfp_t gfp);
 void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
 void __breadahead(struct block_device *, sector_t block, unsigned int size);
-struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
+struct buffer_head *__bread_gfp(struct block_device *,
+                               sector_t block, unsigned size, gfp_t gfp);
 void invalidate_bh_lrus(void);
 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
 void free_buffer_head(struct buffer_head * bh);
@@ -295,7 +296,13 @@ static inline void bforget(struct buffer_head *bh)
 static inline struct buffer_head *
 sb_bread(struct super_block *sb, sector_t block)
 {
-       return __bread(sb->s_bdev, block, sb->s_blocksize);
+       return __bread_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
+}
+
+static inline struct buffer_head *
+sb_bread_unmovable(struct super_block *sb, sector_t block)
+{
+       return __bread_gfp(sb->s_bdev, block, sb->s_blocksize, 0);
 }
 
 static inline void
@@ -307,7 +314,7 @@ sb_breadahead(struct super_block *sb, sector_t block)
 static inline struct buffer_head *
 sb_getblk(struct super_block *sb, sector_t block)
 {
-       return __getblk(sb->s_bdev, block, sb->s_blocksize);
+       return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
 }
 
 static inline struct buffer_head *
@@ -344,6 +351,36 @@ static inline void lock_buffer(struct buffer_head *bh)
                __lock_buffer(bh);
 }
 
+static inline struct buffer_head *getblk_unmovable(struct block_device *bdev,
+                                                  sector_t block,
+                                                  unsigned size)
+{
+       return __getblk_gfp(bdev, block, size, 0);
+}
+
+static inline struct buffer_head *__getblk(struct block_device *bdev,
+                                          sector_t block,
+                                          unsigned size)
+{
+       return __getblk_gfp(bdev, block, size, __GFP_MOVABLE);
+}
+
+/**
+ *  __bread() - reads a specified block and returns the bh
+ *  @bdev: the block_device to read from
+ *  @block: number of block
+ *  @size: size (in bytes) to read
+ *
+ *  Reads a specified block, and returns buffer head that contains it.
+ *  The page cache is allocated from movable area so that it can be migrated.
+ *  It returns NULL if the block was unreadable.
+ */
+static inline struct buffer_head *
+__bread(struct block_device *bdev, sector_t block, unsigned size)
+{
+       return __bread_gfp(bdev, block, size, __GFP_MOVABLE);
+}
+
 extern int __set_page_dirty_buffers(struct page *page);
 
 #else /* CONFIG_BLOCK */
index 6992afc6ba7f96fda9dba202f771fe7e28f807fe..b37ea95bc348f15b16a9c0d095588379b12edbee 100644 (file)
@@ -99,6 +99,12 @@ inval_skb:
        return 1;
 }
 
+static inline bool can_is_canfd_skb(const struct sk_buff *skb)
+{
+       /* the CAN specific type of skb is identified by its data length */
+       return skb->len == CANFD_MTU;
+}
+
 /* get data length from can_dlc with sanitized can_dlc */
 u8 can_dlc2len(u8 can_dlc);
 
index be21af149f119394c68bd8018a8de39f2db067ee..2839c639f0920942d1e835dd464598432e22e974 100644 (file)
@@ -352,7 +352,6 @@ struct clk_divider {
 #define CLK_DIVIDER_READ_ONLY          BIT(5)
 
 extern const struct clk_ops clk_divider_ops;
-extern const struct clk_ops clk_divider_ro_ops;
 struct clk *clk_register_divider(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 shift, u8 width,
index f75acbf70e9630631e03bd49e43414d7b3b4b9e3..74e5341463c91d06c1d5578d93f722358e340929 100644 (file)
@@ -254,13 +254,26 @@ extern const struct clk_ops ti_clk_mux_ops;
 void omap2_init_clk_hw_omap_clocks(struct clk *clk);
 int omap3_noncore_dpll_enable(struct clk_hw *hw);
 void omap3_noncore_dpll_disable(struct clk_hw *hw);
+int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index);
 int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long parent_rate);
+int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
+                                          unsigned long rate,
+                                          unsigned long parent_rate,
+                                          u8 index);
+long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
+                                      unsigned long rate,
+                                      unsigned long *best_parent_rate,
+                                      struct clk **best_parent_clk);
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
                                         unsigned long parent_rate);
 long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
                                    unsigned long target_rate,
                                    unsigned long *parent_rate);
+long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
+                                       unsigned long rate,
+                                       unsigned long *best_parent_rate,
+                                       struct clk **best_parent_clk);
 u8 omap2_init_dpll_parent(struct clk_hw *hw);
 unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
 long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
@@ -278,6 +291,8 @@ int omap2_clk_disable_autoidle_all(void);
 void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
                         unsigned long parent_rate);
+int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate, u8 index);
 int omap2_dflt_clk_enable(struct clk_hw *hw);
 void omap2_dflt_clk_disable(struct clk_hw *hw);
 int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
index 653f0e2b6ca9a62a450b876c3cf902ea392430d1..abcafaa20b868f6b836eb7aa17ce168a41b97fc8 100644 (file)
@@ -287,7 +287,7 @@ extern struct clocksource* clocksource_get_next(void);
 extern void clocksource_change_rating(struct clocksource *cs, int rating);
 extern void clocksource_suspend(void);
 extern void clocksource_resume(void);
-extern struct clocksource * __init __weak clocksource_default_clock(void);
+extern struct clocksource * __init clocksource_default_clock(void);
 extern void clocksource_mark_unstable(struct clocksource *cs);
 
 extern u64
index 0430ed05d3b9f0511975fbef5ca89ec14faf3e92..a93438beb33cf12529c44a8cb905e35df125edae 100644 (file)
@@ -18,12 +18,12 @@ struct cma;
 extern phys_addr_t cma_get_base(struct cma *cma);
 extern unsigned long cma_get_size(struct cma *cma);
 
-extern int __init cma_declare_contiguous(phys_addr_t size,
-                       phys_addr_t base, phys_addr_t limit,
+extern int __init cma_declare_contiguous(phys_addr_t base,
+                       phys_addr_t size, phys_addr_t limit,
                        phys_addr_t alignment, unsigned int order_per_bit,
                        bool fixed, struct cma **res_cma);
-extern int cma_init_reserved_mem(phys_addr_t size,
-                                       phys_addr_t base, int order_per_bit,
+extern int cma_init_reserved_mem(phys_addr_t base,
+                                       phys_addr_t size, int order_per_bit,
                                        struct cma **res_cma);
 extern struct page *cma_alloc(struct cma *cma, int count, unsigned int align);
 extern bool cma_release(struct cma *cma, struct page *pages, int count);
index 2507fd2a1eb4f9d4971b9de5344e8f250570c012..d1a558239b1a189768d804c13b39617677cd93b4 100644 (file)
@@ -71,7 +71,6 @@
  *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
  *
  * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
- * Fixed in GCC 4.8.2 and later versions.
  *
  * (asm goto is automatically volatile - the naming reflects this.)
  */
index cdd1cc202d51ef2c33654630023022284977ea8d..c8c565952548e6ca834425b51dce65c34e5255e7 100644 (file)
@@ -53,7 +53,6 @@
  *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
  *
  * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
- * Fixed in GCC 4.8.2 and later versions.
  *
  * (asm goto is automatically volatile - the naming reflects this.)
  */
diff --git a/include/linux/cpufreq-dt.h b/include/linux/cpufreq-dt.h
new file mode 100644 (file)
index 0000000..0414009
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 Marvell
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CPUFREQ_DT_H__
+#define __CPUFREQ_DT_H__
+
+struct cpufreq_dt_platform_data {
+       /*
+        * True when each CPU has its own clock to control its
+        * frequency, false when all CPUs are controlled by a single
+        * clock.
+        */
+       bool independent_clocks;
+};
+
+#endif /* __CPUFREQ_DT_H__ */
index 138336b6bb0437f4cc0972f7c4ce34a59bf9b2ec..503b085b7832f66a9207b2fdcb8a2f3e98a6bf3e 100644 (file)
@@ -219,6 +219,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
 struct cpufreq_driver {
        char                    name[CPUFREQ_NAME_LEN];
        u8                      flags;
+       void                    *driver_data;
 
        /* needed by all drivers */
        int     (*init)         (struct cpufreq_policy *policy);
@@ -312,6 +313,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 
 const char *cpufreq_get_current_driver(void);
+void *cpufreq_get_driver_data(void);
 
 static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
                unsigned int min, unsigned int max)
index 72ab536ad3de7614b4f9f84754457f391949de78..3849fce7ecfe6df067f365d44bd8951c87cd0184 100644 (file)
 extern unsigned long long elfcorehdr_addr;
 extern unsigned long long elfcorehdr_size;
 
-extern int __weak elfcorehdr_alloc(unsigned long long *addr,
-                                  unsigned long long *size);
-extern void __weak elfcorehdr_free(unsigned long long addr);
-extern ssize_t __weak elfcorehdr_read(char *buf, size_t count, u64 *ppos);
-extern ssize_t __weak elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos);
-extern int __weak remap_oldmem_pfn_range(struct vm_area_struct *vma,
-                                        unsigned long from, unsigned long pfn,
-                                        unsigned long size, pgprot_t prot);
+extern int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size);
+extern void elfcorehdr_free(unsigned long long addr);
+extern ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos);
+extern ssize_t elfcorehdr_read_notes(char *buf, size_t count, u64 *ppos);
+extern int remap_oldmem_pfn_range(struct vm_area_struct *vma,
+                                 unsigned long from, unsigned long pfn,
+                                 unsigned long size, pgprot_t prot);
 
 extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
                                                unsigned long, int);
index e1707de043ae7bad7f6165ee34841f39abd5cc6c..ca6d2acc5eb76f75781fb77dd12eb671642c8d36 100644 (file)
@@ -64,6 +64,7 @@ typedef int (*dm_request_endio_fn) (struct dm_target *ti,
                                    union map_info *map_context);
 
 typedef void (*dm_presuspend_fn) (struct dm_target *ti);
+typedef void (*dm_presuspend_undo_fn) (struct dm_target *ti);
 typedef void (*dm_postsuspend_fn) (struct dm_target *ti);
 typedef int (*dm_preresume_fn) (struct dm_target *ti);
 typedef void (*dm_resume_fn) (struct dm_target *ti);
@@ -145,6 +146,7 @@ struct target_type {
        dm_endio_fn end_io;
        dm_request_endio_fn rq_end_io;
        dm_presuspend_fn presuspend;
+       dm_presuspend_undo_fn presuspend_undo;
        dm_postsuspend_fn postsuspend;
        dm_preresume_fn preresume;
        dm_resume_fn resume;
index e1e68da6f35c2edd71a08c47ddede967c90db3f9..da3b72e95db3cb0ba734ff736ad94aab6fd5b175 100644 (file)
@@ -194,7 +194,8 @@ static inline char *mc_event_error_type(const unsigned int err_type)
  * @MEM_DDR3:          DDR3 RAM
  * @MEM_RDDR3:         Registered DDR3 RAM
  *                     This is a variant of the DDR3 memories.
- * @MEM_DDR4:          DDR4 RAM
+ * @MEM_LRDDR3         Load-Reduced DDR3 memory.
+ * @MEM_DDR4:          Unbuffered DDR4 RAM
  * @MEM_RDDR4:         Registered DDR4 RAM
  *                     This is a variant of the DDR4 memories.
  */
@@ -216,6 +217,7 @@ enum mem_type {
        MEM_XDR,
        MEM_DDR3,
        MEM_RDDR3,
+       MEM_LRDDR3,
        MEM_DDR4,
        MEM_RDDR4,
 };
index e50f98b0297a36b1d844ca5ca1d7c9f074e8677a..eb0b1988050aeb786d8e52d6ebaa128e3b421700 100644 (file)
@@ -75,6 +75,10 @@ extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
        const u8 word, u16 *data);
 extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
        const u8 word, __le16 *data, const u16 words);
+extern void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom,
+       const u8 byte, u8 *data);
+extern void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom,
+       const u8 byte, u8 *data, const u16 bytes);
 
 extern void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable);
 
index 45cb4ffdea621281aa2068676b9cad9115e48c65..0238d612750e9f14b7b5d2cb15e6560061adcc0e 100644 (file)
@@ -92,6 +92,7 @@ typedef       struct {
 #define EFI_MEMORY_WC          ((u64)0x0000000000000002ULL)    /* write-coalescing */
 #define EFI_MEMORY_WT          ((u64)0x0000000000000004ULL)    /* write-through */
 #define EFI_MEMORY_WB          ((u64)0x0000000000000008ULL)    /* write-back */
+#define EFI_MEMORY_UCE         ((u64)0x0000000000000010ULL)    /* uncached, exported */
 #define EFI_MEMORY_WP          ((u64)0x0000000000001000ULL)    /* write-protect */
 #define EFI_MEMORY_RP          ((u64)0x0000000000002000ULL)    /* read-protect */
 #define EFI_MEMORY_XP          ((u64)0x0000000000004000ULL)    /* execute-protect */
@@ -502,6 +503,10 @@ typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char
 typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, 
                                         u32 attr, unsigned long data_size,
                                         void *data);
+typedef efi_status_t
+efi_set_variable_nonblocking_t(efi_char16_t *name, efi_guid_t *vendor,
+                              u32 attr, unsigned long data_size, void *data);
+
 typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
 typedef void efi_reset_system_t (int reset_type, efi_status_t status,
                                 unsigned long data_size, efi_char16_t *data);
@@ -542,6 +547,9 @@ void efi_native_runtime_setup(void);
 #define SMBIOS_TABLE_GUID    \
     EFI_GUID(  0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
+#define SMBIOS3_TABLE_GUID    \
+    EFI_GUID(  0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 )
+
 #define SAL_SYSTEM_TABLE_GUID    \
     EFI_GUID(  0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
 
@@ -805,7 +813,8 @@ extern struct efi {
        unsigned long mps;              /* MPS table */
        unsigned long acpi;             /* ACPI table  (IA64 ext 0.71) */
        unsigned long acpi20;           /* ACPI table  (ACPI 2.0) */
-       unsigned long smbios;           /* SM BIOS table */
+       unsigned long smbios;           /* SMBIOS table (32 bit entry point) */
+       unsigned long smbios3;          /* SMBIOS table (64 bit entry point) */
        unsigned long sal_systab;       /* SAL system table */
        unsigned long boot_info;        /* boot info table */
        unsigned long hcdp;             /* HCDP table */
@@ -821,6 +830,7 @@ extern struct efi {
        efi_get_variable_t *get_variable;
        efi_get_next_variable_t *get_next_variable;
        efi_set_variable_t *set_variable;
+       efi_set_variable_nonblocking_t *set_variable_nonblocking;
        efi_query_variable_info_t *query_variable_info;
        efi_update_capsule_t *update_capsule;
        efi_query_capsule_caps_t *query_capsule_caps;
@@ -886,6 +896,13 @@ extern bool efi_poweroff_required(void);
             (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \
             (md) = (void *)(md) + (m)->desc_size)
 
+/*
+ * Format an EFI memory descriptor's type and attributes to a user-provided
+ * character buffer, as per snprintf(), and return the buffer.
+ */
+char * __init efi_md_typeattr_format(char *buf, size_t size,
+                                    const efi_memory_desc_t *md);
+
 /**
  * efi_range_is_wc - check the WC bit on an address range
  * @start: starting kvirt address
@@ -1034,6 +1051,7 @@ struct efivar_operations {
        efi_get_variable_t *get_variable;
        efi_get_next_variable_t *get_next_variable;
        efi_set_variable_t *set_variable;
+       efi_set_variable_nonblocking_t *set_variable_nonblocking;
        efi_query_variable_store_t *query_variable_store;
 };
 
@@ -1227,4 +1245,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
                                  unsigned long *load_addr,
                                  unsigned long *load_size);
 
+efi_status_t efi_parse_options(char *cmdline);
+
+bool efi_runtime_disabled(void);
 #endif /* _LINUX_EFI_H */
index 7fd81b8c48971676cd52362f09722dfd2dd28153..6b7fd9cf5ea2f282b4972c0245ba33f807c61f2f 100644 (file)
@@ -246,15 +246,6 @@ static inline int freezable_schedule_hrtimeout_range(ktime_t *expires,
  * defined in <linux/wait.h>
  */
 
-#define wait_event_freezekillable(wq, condition)                       \
-({                                                                     \
-       int __retval;                                                   \
-       freezer_do_not_count();                                         \
-       __retval = wait_event_killable(wq, (condition));                \
-       freezer_count();                                                \
-       __retval;                                                       \
-})
-
 /* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
 #define wait_event_freezekillable_unsafe(wq, condition)                        \
 ({                                                                     \
@@ -265,35 +256,6 @@ static inline int freezable_schedule_hrtimeout_range(ktime_t *expires,
        __retval;                                                       \
 })
 
-#define wait_event_freezable(wq, condition)                            \
-({                                                                     \
-       int __retval;                                                   \
-       freezer_do_not_count();                                         \
-       __retval = wait_event_interruptible(wq, (condition));           \
-       freezer_count();                                                \
-       __retval;                                                       \
-})
-
-#define wait_event_freezable_timeout(wq, condition, timeout)           \
-({                                                                     \
-       long __retval = timeout;                                        \
-       freezer_do_not_count();                                         \
-       __retval = wait_event_interruptible_timeout(wq, (condition),    \
-                               __retval);                              \
-       freezer_count();                                                \
-       __retval;                                                       \
-})
-
-#define wait_event_freezable_exclusive(wq, condition)                  \
-({                                                                     \
-       int __retval;                                                   \
-       freezer_do_not_count();                                         \
-       __retval = wait_event_interruptible_exclusive(wq, condition);   \
-       freezer_count();                                                \
-       __retval;                                                       \
-})
-
-
 #else /* !CONFIG_FREEZER */
 static inline bool frozen(struct task_struct *p) { return false; }
 static inline bool freezing(struct task_struct *p) { return false; }
@@ -331,18 +293,6 @@ static inline void set_freezable(void) {}
 #define freezable_schedule_hrtimeout_range(expires, delta, mode)       \
        schedule_hrtimeout_range(expires, delta, mode)
 
-#define wait_event_freezable(wq, condition)                            \
-               wait_event_interruptible(wq, condition)
-
-#define wait_event_freezable_timeout(wq, condition, timeout)           \
-               wait_event_interruptible_timeout(wq, condition, timeout)
-
-#define wait_event_freezable_exclusive(wq, condition)                  \
-               wait_event_interruptible_exclusive(wq, condition)
-
-#define wait_event_freezekillable(wq, condition)               \
-               wait_event_killable(wq, condition)
-
 #define wait_event_freezekillable_unsafe(wq, condition)                        \
                wait_event_killable(wq, condition)
 
index a957d4366c240fbf80d6470f3808316dd8def6b2..9ab779e8a63ccd7785637dd9017fc3bc69ff260f 100644 (file)
@@ -222,6 +222,13 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 #define ATTR_OPEN      (1 << 15) /* Truncating from open(O_TRUNC) */
 #define ATTR_TIMES_SET (1 << 16)
 
+/*
+ * Whiteout is represented by a char device.  The following constants define the
+ * mode and device number to use.
+ */
+#define WHITEOUT_MODE 0
+#define WHITEOUT_DEV 0
+
 /*
  * This is the Inode Attributes structure, used for notify_change().  It
  * uses the above definitions as flags, to know which values have changed.
@@ -254,6 +261,12 @@ struct iattr {
  */
 #include <linux/quota.h>
 
+/*
+ * Maximum number of layers of fs stack.  Needs to be limited to
+ * prevent kernel stack overflow
+ */
+#define FILESYSTEM_MAX_STACK_DEPTH 2
+
 /** 
  * enum positive_aop_returns - aop return codes with specific semantics
  *
@@ -626,11 +639,13 @@ static inline int inode_unhashed(struct inode *inode)
  * 2: child/target
  * 3: xattr
  * 4: second non-directory
- * The last is for certain operations (such as rename) which lock two
+ * 5: second parent (when locking independent directories in rename)
+ *
+ * I_MUTEX_NONDIR2 is for certain operations (such as rename) which lock two
  * non-directories at once.
  *
  * The locking order between these classes is
- * parent -> child -> normal -> xattr -> second non-directory
+ * parent[2] -> child -> grandchild -> normal -> xattr -> second non-directory
  */
 enum inode_i_mutex_lock_class
 {
@@ -638,7 +653,8 @@ enum inode_i_mutex_lock_class
        I_MUTEX_PARENT,
        I_MUTEX_CHILD,
        I_MUTEX_XATTR,
-       I_MUTEX_NONDIR2
+       I_MUTEX_NONDIR2,
+       I_MUTEX_PARENT2,
 };
 
 void lock_two_nondirectories(struct inode *, struct inode*);
@@ -1266,6 +1282,11 @@ struct super_block {
        struct list_lru         s_dentry_lru ____cacheline_aligned_in_smp;
        struct list_lru         s_inode_lru ____cacheline_aligned_in_smp;
        struct rcu_head         rcu;
+
+       /*
+        * Indicates how deep in a filesystem stack this SB is
+        */
+       int s_stack_depth;
 };
 
 extern struct timespec current_fs_time(struct super_block *sb);
@@ -1398,6 +1419,7 @@ extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct ino
 extern int vfs_rmdir(struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **, unsigned int);
+extern int vfs_whiteout(struct inode *, struct dentry *);
 
 /*
  * VFS dentry helper functions.
@@ -1528,6 +1550,9 @@ struct inode_operations {
                           umode_t create_mode, int *opened);
        int (*tmpfile) (struct inode *, struct dentry *, umode_t);
        int (*set_acl)(struct inode *, struct posix_acl *, int);
+
+       /* WARNING: probably going away soon, do not use! */
+       int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
 } ____cacheline_aligned;
 
 ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
@@ -1625,6 +1650,9 @@ struct super_operations {
 #define IS_AUTOMOUNT(inode)    ((inode)->i_flags & S_AUTOMOUNT)
 #define IS_NOSEC(inode)                ((inode)->i_flags & S_NOSEC)
 
+#define IS_WHITEOUT(inode)     (S_ISCHR(inode->i_mode) && \
+                                (inode)->i_rdev == WHITEOUT_DEV)
+
 /*
  * Inode state bits.  Protected by inode->i_lock
  *
@@ -2040,6 +2068,7 @@ extern struct file *file_open_name(struct filename *, int, umode_t);
 extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
                                   const char *, int);
+extern int vfs_open(const struct path *, struct file *, const struct cred *);
 extern struct file * dentry_open(const struct path *, int, const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
 
@@ -2253,7 +2282,9 @@ extern sector_t bmap(struct inode *, sector_t);
 #endif
 extern int notify_change(struct dentry *, struct iattr *, struct inode **);
 extern int inode_permission(struct inode *, int);
+extern int __inode_permission(struct inode *, int);
 extern int generic_permission(struct inode *, int);
+extern int __check_sticky(struct inode *dir, struct inode *inode);
 
 static inline bool execute_ok(struct inode *inode)
 {
@@ -2438,6 +2469,7 @@ extern ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, lo
 extern ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
 
 /* fs/block_dev.c */
+extern ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to);
 extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from);
 extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
                        int datasync);
@@ -2452,6 +2484,9 @@ extern ssize_t iter_file_splice_write(struct pipe_inode_info *,
                struct file *, loff_t *, size_t, unsigned int);
 extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe,
                struct file *out, loff_t *, size_t len, unsigned int flags);
+extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+               loff_t *opos, size_t len, unsigned int flags);
+
 
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
@@ -2737,6 +2772,14 @@ static inline int is_sxid(umode_t mode)
        return (mode & S_ISUID) || ((mode & S_ISGID) && (mode & S_IXGRP));
 }
 
+static inline int check_sticky(struct inode *dir, struct inode *inode)
+{
+       if (!(dir->i_mode & S_ISVTX))
+               return 0;
+
+       return __check_sticky(dir, inode);
+}
+
 static inline void inode_has_no_xattr(struct inode *inode)
 {
        if (!is_sxid(inode->i_mode) && (inode->i_sb->s_flags & MS_NOSEC))
index 69280db02c4107ecba915c443365ea64f0b17b06..ee3c2aba2a8ec24c5782cc0ada22add609db7345 100644 (file)
 
 struct pmbus_platform_data {
        u32 flags;              /* Device specific flags */
+
+       /* regulator support */
+       int num_regulators;
+       struct regulator_init_data *reg_init_data;
 };
 
 #endif /* _PMBUS_H_ */
index 8bbd7bc1043d9c4d26ffff38b35b8540093fdb71..03fa332ad2a8cec4e26c212b9333e56f0c6d6169 100644 (file)
@@ -72,7 +72,7 @@ struct iio_event_data {
 
 #define IIO_EVENT_CODE_EXTRACT_TYPE(mask) ((mask >> 56) & 0xFF)
 
-#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0xCF)
+#define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 48) & 0x7F)
 
 #define IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(mask) ((mask >> 32) & 0xFF)
 
index 0068708161ffa6954f320d7de7d4ebb86dd2a889..0a21fbefdfbec1a693ed09c3d256b8059760655e 100644 (file)
@@ -242,7 +242,7 @@ static inline void in_dev_put(struct in_device *idev)
 static __inline__ __be32 inet_make_mask(int logmask)
 {
        if (logmask)
-               return htonl(~((1<<(32-logmask))-1));
+               return htonl(~((1U<<(32-logmask))-1));
        return 0;
 }
 
index 77fc43f8fb72ce05210badb40d44abc29323d40e..3037fc085e8e16817f37a57621fde22659f64012 100644 (file)
@@ -102,7 +102,7 @@ extern struct group_info init_groups;
 #define INIT_IDS
 #endif
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
 #define INIT_TASK_RCU_TREE_PREEMPT()                                   \
        .rcu_blocked_node = NULL,
 #else
@@ -166,6 +166,15 @@ extern struct task_group root_task_group;
 # define INIT_RT_MUTEXES(tsk)
 #endif
 
+#ifdef CONFIG_NUMA_BALANCING
+# define INIT_NUMA_BALANCING(tsk)                                      \
+       .numa_preferred_nid = -1,                                       \
+       .numa_group = NULL,                                             \
+       .numa_faults = NULL,
+#else
+# define INIT_NUMA_BALANCING(tsk)
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -237,6 +246,7 @@ extern struct task_group root_task_group;
        INIT_CPUSET_SEQ(tsk)                                            \
        INIT_RT_MUTEXES(tsk)                                            \
        INIT_VTIME(tsk)                                                 \
+       INIT_NUMA_BALANCING(tsk)                                        \
 }
 
 
index e6a7c9ff72f2a717ba643d4a2a7786f93a33497e..b29a5982e1c3381052a170e7c0fa898e61147a2f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/types.h>
+#include <linux/scatterlist.h>
 #include <trace/events/iommu.h>
 
 #define IOMMU_READ     (1 << 0)
@@ -97,6 +98,8 @@ enum iommu_attr {
  * @detach_dev: detach device from an iommu domain
  * @map: map a physically contiguous memory region to an iommu domain
  * @unmap: unmap a physically contiguous memory region from an iommu domain
+ * @map_sg: map a scatter-gather list of physically contiguous memory chunks
+ * to an iommu domain
  * @iova_to_phys: translate iova to physical address
  * @add_device: add device to iommu grouping
  * @remove_device: remove device from iommu grouping
@@ -114,6 +117,8 @@ struct iommu_ops {
                   phys_addr_t paddr, size_t size, int prot);
        size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
                     size_t size);
+       size_t (*map_sg)(struct iommu_domain *domain, unsigned long iova,
+                        struct scatterlist *sg, unsigned int nents, int prot);
        phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova);
        int (*add_device)(struct device *dev);
        void (*remove_device)(struct device *dev);
@@ -156,6 +161,9 @@ extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
                     phys_addr_t paddr, size_t size, int prot);
 extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
                       size_t size);
+extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+                               struct scatterlist *sg,unsigned int nents,
+                               int prot);
 extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova);
 extern void iommu_set_fault_handler(struct iommu_domain *domain,
                        iommu_fault_handler_t handler, void *token);
@@ -241,6 +249,13 @@ static inline int report_iommu_fault(struct iommu_domain *domain,
        return ret;
 }
 
+static inline size_t iommu_map_sg(struct iommu_domain *domain,
+                                 unsigned long iova, struct scatterlist *sg,
+                                 unsigned int nents, int prot)
+{
+       return domain->ops->map_sg(domain, iova, sg, nents, prot);
+}
+
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
@@ -293,6 +308,13 @@ static inline int iommu_unmap(struct iommu_domain *domain, unsigned long iova,
        return -ENODEV;
 }
 
+static inline size_t iommu_map_sg(struct iommu_domain *domain,
+                                 unsigned long iova, struct scatterlist *sg,
+                                 unsigned int nents, int prot)
+{
+       return -ENODEV;
+}
+
 static inline int iommu_domain_window_enable(struct iommu_domain *domain,
                                             u32 wnd_nr, phys_addr_t paddr,
                                             u64 size, int prot)
index 0dae71e9971c434cef33c13572dbd13018f3604e..704b9a599b268dd9c7d0b9d45b97c5b67245700b 100644 (file)
@@ -1042,7 +1042,7 @@ void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block);
 extern void jbd2_journal_commit_transaction(journal_t *);
 
 /* Checkpoint list management */
-int __jbd2_journal_clean_checkpoint_list(journal_t *journal);
+void __jbd2_journal_clean_checkpoint_list(journal_t *journal);
 int __jbd2_journal_remove_checkpoint(struct journal_head *);
 void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
index 40728cf1c452a8d5fbf8a7065864ad5f34656ad8..446d76a87ba17f8b3116482a8617df1c5972bc1a 100644 (file)
@@ -162,6 +162,7 @@ extern int _cond_resched(void);
 #endif
 
 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+  void ___might_sleep(const char *file, int line, int preempt_offset);
   void __might_sleep(const char *file, int line, int preempt_offset);
 /**
  * might_sleep - annotation for functions that can sleep
@@ -175,10 +176,14 @@ extern int _cond_resched(void);
  */
 # define might_sleep() \
        do { __might_sleep(__FILE__, __LINE__, 0); might_resched(); } while (0)
+# define sched_annotate_sleep()        __set_current_state(TASK_RUNNING)
 #else
+  static inline void ___might_sleep(const char *file, int line,
+                                  int preempt_offset) { }
   static inline void __might_sleep(const char *file, int line,
                                   int preempt_offset) { }
 # define might_sleep() do { might_resched(); } while (0)
+# define sched_annotate_sleep() do { } while (0)
 #endif
 
 #define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0)
@@ -403,6 +408,7 @@ int vsscanf(const char *, const char *, va_list);
 extern int get_option(char **str, int *pint);
 extern char *get_options(const char *str, int nints, int *ints);
 extern unsigned long long memparse(const char *ptr, char **retptr);
+extern bool parse_option_str(const char *str, const char *option);
 
 extern int core_kernel_text(unsigned long addr);
 extern int core_kernel_data(unsigned long addr);
index 8422b4ed6882be8e8ece65f9a1bcd2ceb5af2bfb..b9376cd5a187e818c28c09935eb022a1920848a8 100644 (file)
@@ -77,11 +77,6 @@ static inline unsigned int kstat_cpu_irqs_sum(unsigned int cpu)
        return kstat_cpu(cpu).irqs_sum;
 }
 
-/*
- * Lock/unlock the current runqueue - to extract task statistics:
- */
-extern unsigned long long task_delta_exec(struct task_struct *);
-
 extern void account_user_time(struct task_struct *, cputime_t, cputime_t);
 extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t);
 extern void account_steal_time(cputime_t);
index 6b06d378f3dfed9b6e2876cdd3eb563d4d7483e9..e465bb15912d98cd1136f985a110bf0347667bd1 100644 (file)
@@ -283,7 +283,7 @@ struct kgdb_io {
 
 extern struct kgdb_arch                arch_kgdb_ops;
 
-extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs);
+extern unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs);
 
 #ifdef CONFIG_SERIAL_KGDB_NMI
 extern int kgdb_register_nmi_console(void);
index 6b394f0b51485076b28ed9fc2136d854b5d1c677..eeb3079857155355161047eda5d2d298d7fd2a3f 100644 (file)
@@ -6,7 +6,8 @@
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 extern int __khugepaged_enter(struct mm_struct *mm);
 extern void __khugepaged_exit(struct mm_struct *mm);
-extern int khugepaged_enter_vma_merge(struct vm_area_struct *vma);
+extern int khugepaged_enter_vma_merge(struct vm_area_struct *vma,
+                                     unsigned long vm_flags);
 
 #define khugepaged_enabled()                                          \
        (transparent_hugepage_flags &                                  \
@@ -35,13 +36,13 @@ static inline void khugepaged_exit(struct mm_struct *mm)
                __khugepaged_exit(mm);
 }
 
-static inline int khugepaged_enter(struct vm_area_struct *vma)
+static inline int khugepaged_enter(struct vm_area_struct *vma,
+                                  unsigned long vm_flags)
 {
        if (!test_bit(MMF_VM_HUGEPAGE, &vma->vm_mm->flags))
                if ((khugepaged_always() ||
-                    (khugepaged_req_madv() &&
-                     vma->vm_flags & VM_HUGEPAGE)) &&
-                   !(vma->vm_flags & VM_NOHUGEPAGE))
+                    (khugepaged_req_madv() && (vm_flags & VM_HUGEPAGE))) &&
+                   !(vm_flags & VM_NOHUGEPAGE))
                        if (__khugepaged_enter(vma->vm_mm))
                                return -ENOMEM;
        return 0;
@@ -54,11 +55,13 @@ static inline int khugepaged_fork(struct mm_struct *mm, struct mm_struct *oldmm)
 static inline void khugepaged_exit(struct mm_struct *mm)
 {
 }
-static inline int khugepaged_enter(struct vm_area_struct *vma)
+static inline int khugepaged_enter(struct vm_area_struct *vma,
+                                  unsigned long vm_flags)
 {
        return 0;
 }
-static inline int khugepaged_enter_vma_merge(struct vm_area_struct *vma)
+static inline int khugepaged_enter_vma_merge(struct vm_area_struct *vma,
+                                            unsigned long vm_flags)
 {
        return 0;
 }
index 28be31f49250a65e54f5d785cdd48d5676a5d045..a6059bdf7b03baa4955c069637f686b3d709d819 100644 (file)
@@ -703,7 +703,7 @@ void kvm_arch_sync_events(struct kvm *kvm);
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu);
 void kvm_vcpu_kick(struct kvm_vcpu *vcpu);
 
-bool kvm_is_mmio_pfn(pfn_t pfn);
+bool kvm_is_reserved_pfn(pfn_t pfn);
 
 struct kvm_irq_ack_notifier {
        struct hlist_node link;
@@ -1080,6 +1080,7 @@ void kvm_device_get(struct kvm_device *dev);
 void kvm_device_put(struct kvm_device *dev);
 struct kvm_device *kvm_device_from_filp(struct file *filp);
 int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type);
+void kvm_unregister_device_ops(u32 type);
 
 extern struct kvm_device_ops kvm_mpic_ops;
 extern struct kvm_device_ops kvm_xics_ops;
index e436864721971c81383a323bf3951e19632475a0..a57611d0c94e147433336fa5277aa755d07076d6 100644 (file)
@@ -13,8 +13,8 @@
 #define __LINUX_LEDS_H_INCLUDED
 
 #include <linux/list.h>
-#include <linux/spinlock.h>
 #include <linux/rwsem.h>
+#include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 
@@ -31,8 +31,8 @@ enum led_brightness {
 
 struct led_classdev {
        const char              *name;
-       int                      brightness;
-       int                      max_brightness;
+       enum led_brightness      brightness;
+       enum led_brightness      max_brightness;
        int                      flags;
 
        /* Lower 16 bits reflect status */
@@ -140,6 +140,16 @@ extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
  */
 extern void led_set_brightness(struct led_classdev *led_cdev,
                               enum led_brightness brightness);
+/**
+ * led_update_brightness - update LED brightness
+ * @led_cdev: the LED to query
+ *
+ * Get an LED's current brightness and update led_cdev->brightness
+ * member with the obtained value.
+ *
+ * Returns: 0 on success or negative error value on failure
+ */
+extern int led_update_brightness(struct led_classdev *led_cdev);
 
 /*
  * LED Triggers
index bd5fefeaf548670d706af4b850121ed28b7091df..bfbc817c34eee29be2749f2b7ab39f8b0d657ca8 100644 (file)
@@ -1191,9 +1191,9 @@ extern void ata_scsi_unlock_native_capacity(struct scsi_device *sdev);
 extern int ata_scsi_slave_config(struct scsi_device *sdev);
 extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
-                                      int queue_depth, int reason);
+                                      int queue_depth);
 extern int __ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
-                                   int queue_depth, int reason);
+                                   int queue_depth);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
 extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap);
diff --git a/include/linux/mailbox.h b/include/linux/mailbox.h
deleted file mode 100644 (file)
index 5161f63..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * 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/>.
- */
-
-int pl320_ipc_transmit(u32 *data);
-int pl320_ipc_register_notifier(struct notifier_block *nb);
-int pl320_ipc_unregister_notifier(struct notifier_block *nb);
diff --git a/include/linux/mailbox_client.h b/include/linux/mailbox_client.h
new file mode 100644 (file)
index 0000000..307d9ca
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013-2014 Linaro Ltd.
+ * Author: Jassi Brar <jassisinghbrar@gmail.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 __MAILBOX_CLIENT_H
+#define __MAILBOX_CLIENT_H
+
+#include <linux/of.h>
+#include <linux/device.h>
+
+struct mbox_chan;
+
+/**
+ * struct mbox_client - User of a mailbox
+ * @dev:               The client device
+ * @tx_block:          If the mbox_send_message should block until data is
+ *                     transmitted.
+ * @tx_tout:           Max block period in ms before TX is assumed failure
+ * @knows_txdone:      If the client could run the TX state machine. Usually
+ *                     if the client receives some ACK packet for transmission.
+ *                     Unused if the controller already has TX_Done/RTR IRQ.
+ * @rx_callback:       Atomic callback to provide client the data received
+ * @tx_done:           Atomic callback to tell client of data transmission
+ */
+struct mbox_client {
+       struct device *dev;
+       bool tx_block;
+       unsigned long tx_tout;
+       bool knows_txdone;
+
+       void (*rx_callback)(struct mbox_client *cl, void *mssg);
+       void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
+};
+
+struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
+int mbox_send_message(struct mbox_chan *chan, void *mssg);
+void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */
+bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */
+void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
+
+#endif /* __MAILBOX_CLIENT_H */
diff --git a/include/linux/mailbox_controller.h b/include/linux/mailbox_controller.h
new file mode 100644 (file)
index 0000000..d4cf96f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * This program is free software; you can 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 __MAILBOX_CONTROLLER_H
+#define __MAILBOX_CONTROLLER_H
+
+#include <linux/of.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/completion.h>
+
+struct mbox_chan;
+
+/**
+ * struct mbox_chan_ops - methods to control mailbox channels
+ * @send_data: The API asks the MBOX controller driver, in atomic
+ *             context try to transmit a message on the bus. Returns 0 if
+ *             data is accepted for transmission, -EBUSY while rejecting
+ *             if the remote hasn't yet read the last data sent. Actual
+ *             transmission of data is reported by the controller via
+ *             mbox_chan_txdone (if it has some TX ACK irq). It must not
+ *             sleep.
+ * @startup:   Called when a client requests the chan. The controller
+ *             could ask clients for additional parameters of communication
+ *             to be provided via client's chan_data. This call may
+ *             block. After this call the Controller must forward any
+ *             data received on the chan by calling mbox_chan_received_data.
+ *             The controller may do stuff that need to sleep.
+ * @shutdown:  Called when a client relinquishes control of a chan.
+ *             This call may block too. The controller must not forward
+ *             any received data anymore.
+ *             The controller may do stuff that need to sleep.
+ * @last_tx_done: If the controller sets 'txdone_poll', the API calls
+ *               this to poll status of last TX. The controller must
+ *               give priority to IRQ method over polling and never
+ *               set both txdone_poll and txdone_irq. Only in polling
+ *               mode 'send_data' is expected to return -EBUSY.
+ *               The controller may do stuff that need to sleep/block.
+ *               Used only if txdone_poll:=true && txdone_irq:=false
+ * @peek_data: Atomic check for any received data. Return true if controller
+ *               has some data to push to the client. False otherwise.
+ */
+struct mbox_chan_ops {
+       int (*send_data)(struct mbox_chan *chan, void *data);
+       int (*startup)(struct mbox_chan *chan);
+       void (*shutdown)(struct mbox_chan *chan);
+       bool (*last_tx_done)(struct mbox_chan *chan);
+       bool (*peek_data)(struct mbox_chan *chan);
+};
+
+/**
+ * struct mbox_controller - Controller of a class of communication channels
+ * @dev:               Device backing this controller
+ * @ops:               Operators that work on each communication chan
+ * @chans:             Array of channels
+ * @num_chans:         Number of channels in the 'chans' array.
+ * @txdone_irq:                Indicates if the controller can report to API when
+ *                     the last transmitted data was read by the remote.
+ *                     Eg, if it has some TX ACK irq.
+ * @txdone_poll:       If the controller can read but not report the TX
+ *                     done. Ex, some register shows the TX status but
+ *                     no interrupt rises. Ignored if 'txdone_irq' is set.
+ * @txpoll_period:     If 'txdone_poll' is in effect, the API polls for
+ *                     last TX's status after these many millisecs
+ * @of_xlate:          Controller driver specific mapping of channel via DT
+ * @poll:              API private. Used to poll for TXDONE on all channels.
+ * @node:              API private. To hook into list of controllers.
+ */
+struct mbox_controller {
+       struct device *dev;
+       struct mbox_chan_ops *ops;
+       struct mbox_chan *chans;
+       int num_chans;
+       bool txdone_irq;
+       bool txdone_poll;
+       unsigned txpoll_period;
+       struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
+                                     const struct of_phandle_args *sp);
+       /* Internal to API */
+       struct timer_list poll;
+       struct list_head node;
+};
+
+/*
+ * The length of circular buffer for queuing messages from a client.
+ * 'msg_count' tracks the number of buffered messages while 'msg_free'
+ * is the index where the next message would be buffered.
+ * We shouldn't need it too big because every transfer is interrupt
+ * triggered and if we have lots of data to transfer, the interrupt
+ * latencies are going to be the bottleneck, not the buffer length.
+ * Besides, mbox_send_message could be called from atomic context and
+ * the client could also queue another message from the notifier 'tx_done'
+ * of the last transfer done.
+ * REVISIT: If too many platforms see the "Try increasing MBOX_TX_QUEUE_LEN"
+ * print, it needs to be taken from config option or somesuch.
+ */
+#define MBOX_TX_QUEUE_LEN      20
+
+/**
+ * struct mbox_chan - s/w representation of a communication chan
+ * @mbox:              Pointer to the parent/provider of this channel
+ * @txdone_method:     Way to detect TXDone chosen by the API
+ * @cl:                        Pointer to the current owner of this channel
+ * @tx_complete:       Transmission completion
+ * @active_req:                Currently active request hook
+ * @msg_count:         No. of mssg currently queued
+ * @msg_free:          Index of next available mssg slot
+ * @msg_data:          Hook for data packet
+ * @lock:              Serialise access to the channel
+ * @con_priv:          Hook for controller driver to attach private data
+ */
+struct mbox_chan {
+       struct mbox_controller *mbox;
+       unsigned txdone_method;
+       struct mbox_client *cl;
+       struct completion tx_complete;
+       void *active_req;
+       unsigned msg_count, msg_free;
+       void *msg_data[MBOX_TX_QUEUE_LEN];
+       spinlock_t lock; /* Serialise access to the channel */
+       void *con_priv;
+};
+
+int mbox_controller_register(struct mbox_controller *mbox); /* can sleep */
+void mbox_controller_unregister(struct mbox_controller *mbox); /* can sleep */
+void mbox_chan_received_data(struct mbox_chan *chan, void *data); /* atomic */
+void mbox_chan_txdone(struct mbox_chan *chan, int r); /* atomic */
+
+#endif /* __MAILBOX_CONTROLLER_H */
index 550c88fb0267f158c26d05714e411805ba15ee90..611b69fa85941ebae8d4f61ab61221a469e1c079 100644 (file)
@@ -61,6 +61,7 @@ static inline const struct mbus_dram_target_info *mv_mbus_dram_info(void)
 }
 #endif
 
+int mvebu_mbus_save_cpu_target(u32 *store_addr);
 void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
 void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
 int mvebu_mbus_add_window_remap_by_id(unsigned int target,
index 19df5d857411a7cc567fa7571985bfdcd65c28b0..6b75640ef5ab553a4e0292940bacc466db1a6437 100644 (file)
@@ -139,48 +139,23 @@ static inline bool mem_cgroup_disabled(void)
        return false;
 }
 
-void __mem_cgroup_begin_update_page_stat(struct page *page, bool *locked,
-                                        unsigned long *flags);
-
-extern atomic_t memcg_moving;
-
-static inline void mem_cgroup_begin_update_page_stat(struct page *page,
-                                       bool *locked, unsigned long *flags)
-{
-       if (mem_cgroup_disabled())
-               return;
-       rcu_read_lock();
-       *locked = false;
-       if (atomic_read(&memcg_moving))
-               __mem_cgroup_begin_update_page_stat(page, locked, flags);
-}
-
-void __mem_cgroup_end_update_page_stat(struct page *page,
-                               unsigned long *flags);
-static inline void mem_cgroup_end_update_page_stat(struct page *page,
-                                       bool *locked, unsigned long *flags)
-{
-       if (mem_cgroup_disabled())
-               return;
-       if (*locked)
-               __mem_cgroup_end_update_page_stat(page, flags);
-       rcu_read_unlock();
-}
-
-void mem_cgroup_update_page_stat(struct page *page,
-                                enum mem_cgroup_stat_index idx,
-                                int val);
-
-static inline void mem_cgroup_inc_page_stat(struct page *page,
+struct mem_cgroup *mem_cgroup_begin_page_stat(struct page *page, bool *locked,
+                                             unsigned long *flags);
+void mem_cgroup_end_page_stat(struct mem_cgroup *memcg, bool locked,
+                             unsigned long flags);
+void mem_cgroup_update_page_stat(struct mem_cgroup *memcg,
+                                enum mem_cgroup_stat_index idx, int val);
+
+static inline void mem_cgroup_inc_page_stat(struct mem_cgroup *memcg,
                                            enum mem_cgroup_stat_index idx)
 {
-       mem_cgroup_update_page_stat(page, idx, 1);
+       mem_cgroup_update_page_stat(memcg, idx, 1);
 }
 
-static inline void mem_cgroup_dec_page_stat(struct page *page,
+static inline void mem_cgroup_dec_page_stat(struct mem_cgroup *memcg,
                                            enum mem_cgroup_stat_index idx)
 {
-       mem_cgroup_update_page_stat(page, idx, -1);
+       mem_cgroup_update_page_stat(memcg, idx, -1);
 }
 
 unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
@@ -315,13 +290,14 @@ mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
 {
 }
 
-static inline void mem_cgroup_begin_update_page_stat(struct page *page,
+static inline struct mem_cgroup *mem_cgroup_begin_page_stat(struct page *page,
                                        bool *locked, unsigned long *flags)
 {
+       return NULL;
 }
 
-static inline void mem_cgroup_end_update_page_stat(struct page *page,
-                                       bool *locked, unsigned long *flags)
+static inline void mem_cgroup_end_page_stat(struct mem_cgroup *memcg,
+                                       bool locked, unsigned long flags)
 {
 }
 
@@ -343,12 +319,12 @@ static inline bool mem_cgroup_oom_synchronize(bool wait)
        return false;
 }
 
-static inline void mem_cgroup_inc_page_stat(struct page *page,
+static inline void mem_cgroup_inc_page_stat(struct mem_cgroup *memcg,
                                            enum mem_cgroup_stat_index idx)
 {
 }
 
-static inline void mem_cgroup_dec_page_stat(struct page *page,
+static inline void mem_cgroup_dec_page_stat(struct mem_cgroup *memcg,
                                            enum mem_cgroup_stat_index idx)
 {
 }
index bb7384e3c3d89fbd1a36504587035cc0325953e7..8b8d8d12348e59219dbbce03c22a749a49368deb 100644 (file)
@@ -35,7 +35,7 @@ struct memory_block {
 };
 
 int arch_get_memory_phys_device(unsigned long start_pfn);
-unsigned long __weak memory_block_size_bytes(void);
+unsigned long memory_block_size_bytes(void);
 
 /* These states are exposed to userspace as text strings in sysfs */
 #define        MEM_ONLINE              (1<<0) /* exposed to userspace */
index adba89d9c6601b54eff0d5faffc3e521e71fbb41..689312745b2fa2de679bbfe3e2aff074f72dc8db 100644 (file)
@@ -12,7 +12,6 @@
 
 int ab8500_sysctrl_read(u16 reg, u8 *value);
 int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value);
-void ab8500_restart(char mode, const char *cmd);
 
 #else
 
index c0b075f6bc35e8b1b0fd51b347ca8b18e70b6eea..aacc10d7789c339aedb5e3e2d4d420f207c2e2ee 100644 (file)
 #define ARIZONA_MIC_BIAS_CTRL_1                  0x218
 #define ARIZONA_MIC_BIAS_CTRL_2                  0x219
 #define ARIZONA_MIC_BIAS_CTRL_3                  0x21A
+#define ARIZONA_HP_CTRL_1L                       0x225
+#define ARIZONA_HP_CTRL_1R                       0x226
 #define ARIZONA_ACCESSORY_DETECT_MODE_1          0x293
 #define ARIZONA_HEADPHONE_DETECT_1               0x29B
 #define ARIZONA_HEADPHONE_DETECT_2               0x29C
 #define ARIZONA_AIF2_FRAME_CTRL_2                0x548
 #define ARIZONA_AIF2_FRAME_CTRL_3                0x549
 #define ARIZONA_AIF2_FRAME_CTRL_4                0x54A
+#define ARIZONA_AIF2_FRAME_CTRL_5                0x54B
+#define ARIZONA_AIF2_FRAME_CTRL_6                0x54C
+#define ARIZONA_AIF2_FRAME_CTRL_7                0x54D
+#define ARIZONA_AIF2_FRAME_CTRL_8                0x54E
 #define ARIZONA_AIF2_FRAME_CTRL_11               0x551
 #define ARIZONA_AIF2_FRAME_CTRL_12               0x552
+#define ARIZONA_AIF2_FRAME_CTRL_13               0x553
+#define ARIZONA_AIF2_FRAME_CTRL_14               0x554
+#define ARIZONA_AIF2_FRAME_CTRL_15               0x555
+#define ARIZONA_AIF2_FRAME_CTRL_16               0x556
 #define ARIZONA_AIF2_TX_ENABLES                  0x559
 #define ARIZONA_AIF2_RX_ENABLES                  0x55A
 #define ARIZONA_AIF2_FORCE_WRITE                 0x55B
 #define ARIZONA_MICB3_ENA_SHIFT                       0  /* MICB3_ENA */
 #define ARIZONA_MICB3_ENA_WIDTH                       1  /* MICB3_ENA */
 
+/*
+ * R549 (0x225) - HP Ctrl 1L
+ */
+#define ARIZONA_RMV_SHRT_HP1L                    0x4000  /* RMV_SHRT_HP1L */
+#define ARIZONA_RMV_SHRT_HP1L_MASK               0x4000  /* RMV_SHRT_HP1L */
+#define ARIZONA_RMV_SHRT_HP1L_SHIFT                  14  /* RMV_SHRT_HP1L */
+#define ARIZONA_RMV_SHRT_HP1L_WIDTH                   1  /* RMV_SHRT_HP1L */
+#define ARIZONA_HP1L_FLWR                        0x0004  /* HP1L_FLWR */
+#define ARIZONA_HP1L_FLWR_MASK                   0x0004  /* HP1L_FLWR */
+#define ARIZONA_HP1L_FLWR_SHIFT                       2  /* HP1L_FLWR */
+#define ARIZONA_HP1L_FLWR_WIDTH                       1  /* HP1L_FLWR */
+#define ARIZONA_HP1L_SHRTI                       0x0002  /* HP1L_SHRTI */
+#define ARIZONA_HP1L_SHRTI_MASK                  0x0002  /* HP1L_SHRTI */
+#define ARIZONA_HP1L_SHRTI_SHIFT                      1  /* HP1L_SHRTI */
+#define ARIZONA_HP1L_SHRTI_WIDTH                      1  /* HP1L_SHRTI */
+#define ARIZONA_HP1L_SHRTO                       0x0001  /* HP1L_SHRTO */
+#define ARIZONA_HP1L_SHRTO_MASK                  0x0001  /* HP1L_SHRTO */
+#define ARIZONA_HP1L_SHRTO_SHIFT                      0  /* HP1L_SHRTO */
+#define ARIZONA_HP1L_SHRTO_WIDTH                      1  /* HP1L_SHRTO */
+
+/*
+ * R550 (0x226) - HP Ctrl 1R
+ */
+#define ARIZONA_RMV_SHRT_HP1R                    0x4000  /* RMV_SHRT_HP1R */
+#define ARIZONA_RMV_SHRT_HP1R_MASK               0x4000  /* RMV_SHRT_HP1R */
+#define ARIZONA_RMV_SHRT_HP1R_SHIFT                  14  /* RMV_SHRT_HP1R */
+#define ARIZONA_RMV_SHRT_HP1R_WIDTH                   1  /* RMV_SHRT_HP1R */
+#define ARIZONA_HP1R_FLWR                        0x0004  /* HP1R_FLWR */
+#define ARIZONA_HP1R_FLWR_MASK                   0x0004  /* HP1R_FLWR */
+#define ARIZONA_HP1R_FLWR_SHIFT                       2  /* HP1R_FLWR */
+#define ARIZONA_HP1R_FLWR_WIDTH                       1  /* HP1R_FLWR */
+#define ARIZONA_HP1R_SHRTI                       0x0002  /* HP1R_SHRTI */
+#define ARIZONA_HP1R_SHRTI_MASK                  0x0002  /* HP1R_SHRTI */
+#define ARIZONA_HP1R_SHRTI_SHIFT                      1  /* HP1R_SHRTI */
+#define ARIZONA_HP1R_SHRTI_WIDTH                      1  /* HP1R_SHRTI */
+#define ARIZONA_HP1R_SHRTO                       0x0001  /* HP1R_SHRTO */
+#define ARIZONA_HP1R_SHRTO_MASK                  0x0001  /* HP1R_SHRTO */
+#define ARIZONA_HP1R_SHRTO_SHIFT                      0  /* HP1R_SHRTO */
+#define ARIZONA_HP1R_SHRTO_WIDTH                      1  /* HP1R_SHRTO */
+
 /*
  * R659 (0x293) - Accessory Detect Mode 1
  */
diff --git a/include/linux/mfd/atmel-hlcdc.h b/include/linux/mfd/atmel-hlcdc.h
new file mode 100644 (file)
index 0000000..1279ab1
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ * Copyright (C) 2014 Atmel
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * 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 __LINUX_MFD_HLCDC_H
+#define __LINUX_MFD_HLCDC_H
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+
+#define ATMEL_HLCDC_CFG(i)             ((i) * 0x4)
+#define ATMEL_HLCDC_SIG_CFG            LCDCFG(5)
+#define ATMEL_HLCDC_HSPOL              BIT(0)
+#define ATMEL_HLCDC_VSPOL              BIT(1)
+#define ATMEL_HLCDC_VSPDLYS            BIT(2)
+#define ATMEL_HLCDC_VSPDLYE            BIT(3)
+#define ATMEL_HLCDC_DISPPOL            BIT(4)
+#define ATMEL_HLCDC_DITHER             BIT(6)
+#define ATMEL_HLCDC_DISPDLY            BIT(7)
+#define ATMEL_HLCDC_MODE_MASK          GENMASK(9, 8)
+#define ATMEL_HLCDC_PP                 BIT(10)
+#define ATMEL_HLCDC_VSPSU              BIT(12)
+#define ATMEL_HLCDC_VSPHO              BIT(13)
+#define ATMEL_HLCDC_GUARDTIME_MASK     GENMASK(20, 16)
+
+#define ATMEL_HLCDC_EN                 0x20
+#define ATMEL_HLCDC_DIS                        0x24
+#define ATMEL_HLCDC_SR                 0x28
+#define ATMEL_HLCDC_IER                        0x2c
+#define ATMEL_HLCDC_IDR                        0x30
+#define ATMEL_HLCDC_IMR                        0x34
+#define ATMEL_HLCDC_ISR                        0x38
+
+#define ATMEL_HLCDC_CLKPOL             BIT(0)
+#define ATMEL_HLCDC_CLKSEL             BIT(2)
+#define ATMEL_HLCDC_CLKPWMSEL          BIT(3)
+#define ATMEL_HLCDC_CGDIS(i)           BIT(8 + (i))
+#define ATMEL_HLCDC_CLKDIV_SHFT                16
+#define ATMEL_HLCDC_CLKDIV_MASK                GENMASK(23, 16)
+#define ATMEL_HLCDC_CLKDIV(div)                ((div - 2) << ATMEL_HLCDC_CLKDIV_SHFT)
+
+#define ATMEL_HLCDC_PIXEL_CLK          BIT(0)
+#define ATMEL_HLCDC_SYNC               BIT(1)
+#define ATMEL_HLCDC_DISP               BIT(2)
+#define ATMEL_HLCDC_PWM                        BIT(3)
+#define ATMEL_HLCDC_SIP                        BIT(4)
+
+#define ATMEL_HLCDC_SOF                        BIT(0)
+#define ATMEL_HLCDC_SYNCDIS            BIT(1)
+#define ATMEL_HLCDC_FIFOERR            BIT(4)
+#define ATMEL_HLCDC_LAYER_STATUS(x)    BIT((x) + 8)
+
+/**
+ * Structure shared by the MFD device and its subdevices.
+ *
+ * @regmap: register map used to access HLCDC IP registers
+ * @periph_clk: the hlcdc peripheral clock
+ * @sys_clk: the hlcdc system clock
+ * @slow_clk: the system slow clk
+ * @irq: the hlcdc irq
+ */
+struct atmel_hlcdc {
+       struct regmap *regmap;
+       struct clk *periph_clk;
+       struct clk *sys_clk;
+       struct clk *slow_clk;
+       int irq;
+};
+
+#endif /* __LINUX_MFD_HLCDC_H */
index d0e31a2287ac1b95996225be09c01f5b826dadb9..81589d176ae873c3dbd9cec1c27bdfcadb3679fb 100644 (file)
@@ -14,6 +14,8 @@
 enum {
        AXP202_ID = 0,
        AXP209_ID,
+       AXP288_ID,
+       NR_AXP20X_VARIANTS,
 };
 
 #define AXP20X_DATACACHE(m)            (0x04 + (m))
@@ -49,11 +51,13 @@ enum {
 #define AXP20X_IRQ3_EN                 0x42
 #define AXP20X_IRQ4_EN                 0x43
 #define AXP20X_IRQ5_EN                 0x44
+#define AXP20X_IRQ6_EN                 0x45
 #define AXP20X_IRQ1_STATE              0x48
 #define AXP20X_IRQ2_STATE              0x49
 #define AXP20X_IRQ3_STATE              0x4a
 #define AXP20X_IRQ4_STATE              0x4b
 #define AXP20X_IRQ5_STATE              0x4c
+#define AXP20X_IRQ6_STATE              0x4d
 
 /* ADC */
 #define AXP20X_ACIN_V_ADC_H            0x56
@@ -116,6 +120,15 @@ enum {
 #define AXP20X_CC_CTRL                 0xb8
 #define AXP20X_FG_RES                  0xb9
 
+/* AXP288 specific registers */
+#define AXP288_PMIC_ADC_H               0x56
+#define AXP288_PMIC_ADC_L               0x57
+#define AXP288_ADC_TS_PIN_CTRL          0x84
+
+#define AXP288_PMIC_ADC_EN              0x84
+#define AXP288_FG_TUNE5                        0xed
+
+
 /* Regulators IDs */
 enum {
        AXP20X_LDO1 = 0,
@@ -169,12 +182,58 @@ enum {
        AXP20X_IRQ_GPIO0_INPUT,
 };
 
+enum axp288_irqs {
+       AXP288_IRQ_VBUS_FALL     = 2,
+       AXP288_IRQ_VBUS_RISE,
+       AXP288_IRQ_OV,
+       AXP288_IRQ_FALLING_ALT,
+       AXP288_IRQ_RISING_ALT,
+       AXP288_IRQ_OV_ALT,
+       AXP288_IRQ_DONE          = 10,
+       AXP288_IRQ_CHARGING,
+       AXP288_IRQ_SAFE_QUIT,
+       AXP288_IRQ_SAFE_ENTER,
+       AXP288_IRQ_ABSENT,
+       AXP288_IRQ_APPEND,
+       AXP288_IRQ_QWBTU,
+       AXP288_IRQ_WBTU,
+       AXP288_IRQ_QWBTO,
+       AXP288_IRQ_WBTO,
+       AXP288_IRQ_QCBTU,
+       AXP288_IRQ_CBTU,
+       AXP288_IRQ_QCBTO,
+       AXP288_IRQ_CBTO,
+       AXP288_IRQ_WL2,
+       AXP288_IRQ_WL1,
+       AXP288_IRQ_GPADC,
+       AXP288_IRQ_OT            = 31,
+       AXP288_IRQ_GPIO0,
+       AXP288_IRQ_GPIO1,
+       AXP288_IRQ_POKO,
+       AXP288_IRQ_POKL,
+       AXP288_IRQ_POKS,
+       AXP288_IRQ_POKN,
+       AXP288_IRQ_POKP,
+       AXP288_IRQ_TIMER,
+       AXP288_IRQ_MV_CHNG,
+       AXP288_IRQ_BC_USB_CHNG,
+};
+
+#define AXP288_TS_ADC_H                0x58
+#define AXP288_TS_ADC_L                0x59
+#define AXP288_GP_ADC_H                0x5a
+#define AXP288_GP_ADC_L                0x5b
+
 struct axp20x_dev {
        struct device                   *dev;
        struct i2c_client               *i2c_client;
        struct regmap                   *regmap;
        struct regmap_irq_chip_data     *regmap_irqc;
        long                            variant;
+       int                             nr_cells;
+       struct mfd_cell                 *cells;
+       const struct regmap_config      *regmap_cfg;
+       const struct regmap_irq_chip    *regmap_irq_chip;
 };
 
 #endif /* __LINUX_MFD_AXP20X_H */
index 73e1709d4c093de820fa0584f5f28f48ea41b543..a76bc100bf974d667f64fec5dc4619297a8d71b7 100644 (file)
@@ -111,6 +111,13 @@ extern int mfd_add_devices(struct device *parent, int id,
                           struct resource *mem_base,
                           int irq_base, struct irq_domain *irq_domain);
 
+static inline int mfd_add_hotplug_devices(struct device *parent,
+               const struct mfd_cell *cells, int n_devs)
+{
+       return mfd_add_devices(parent, PLATFORM_DEVID_AUTO, cells, n_devs,
+                       NULL, 0, NULL);
+}
+
 extern void mfd_remove_devices(struct device *parent);
 
 #endif
diff --git a/include/linux/mfd/dln2.h b/include/linux/mfd/dln2.h
new file mode 100644 (file)
index 0000000..004b245
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef __LINUX_USB_DLN2_H
+#define __LINUX_USB_DLN2_H
+
+#define DLN2_CMD(cmd, id)              ((cmd) | ((id) << 8))
+
+struct dln2_platform_data {
+       u16 handle;             /* sub-driver handle (internally used only) */
+       u8 port;                /* I2C/SPI port */
+};
+
+/**
+ * dln2_event_cb_t - event callback function signature
+ *
+ * @pdev - the sub-device that registered this callback
+ * @echo - the echo header field received in the message
+ * @data - the data payload
+ * @len  - the data payload length
+ *
+ * The callback function is called in interrupt context and the data payload is
+ * only valid during the call. If the user needs later access of the data, it
+ * must copy it.
+ */
+
+typedef void (*dln2_event_cb_t)(struct platform_device *pdev, u16 echo,
+                               const void *data, int len);
+
+/**
+ * dl2n_register_event_cb - register a callback function for an event
+ *
+ * @pdev - the sub-device that registers the callback
+ * @event - the event for which to register a callback
+ * @event_cb - the callback function
+ *
+ * @return 0 in case of success, negative value in case of error
+ */
+int dln2_register_event_cb(struct platform_device *pdev, u16 event,
+                          dln2_event_cb_t event_cb);
+
+/**
+ * dln2_unregister_event_cb - unregister the callback function for an event
+ *
+ * @pdev - the sub-device that registered the callback
+ * @event - the event for which to register a callback
+ */
+void dln2_unregister_event_cb(struct platform_device *pdev, u16 event);
+
+/**
+ * dln2_transfer - issue a DLN2 command and wait for a response and the
+ * associated data
+ *
+ * @pdev - the sub-device which is issuing this transfer
+ * @cmd - the command to be sent to the device
+ * @obuf - the buffer to be sent to the device; it can be NULL if the user
+ *     doesn't need to transmit data with this command
+ * @obuf_len - the size of the buffer to be sent to the device
+ * @ibuf - any data associated with the response will be copied here; it can be
+ *     NULL if the user doesn't need the response data
+ * @ibuf_len - must be initialized to the input buffer size; it will be modified
+ *     to indicate the actual data transferred;
+ *
+ * @return 0 for success, negative value for errors
+ */
+int dln2_transfer(struct platform_device *pdev, u16 cmd,
+                 const void *obuf, unsigned obuf_len,
+                 void *ibuf, unsigned *ibuf_len);
+
+/**
+ * dln2_transfer_rx - variant of @dln2_transfer() where TX buffer is not needed
+ *
+ * @pdev - the sub-device which is issuing this transfer
+ * @cmd - the command to be sent to the device
+ * @ibuf - any data associated with the response will be copied here; it can be
+ *     NULL if the user doesn't need the response data
+ * @ibuf_len - must be initialized to the input buffer size; it will be modified
+ *     to indicate the actual data transferred;
+ *
+ * @return 0 for success, negative value for errors
+ */
+
+static inline int dln2_transfer_rx(struct platform_device *pdev, u16 cmd,
+                                  void *ibuf, unsigned *ibuf_len)
+{
+       return dln2_transfer(pdev, cmd, NULL, 0, ibuf, ibuf_len);
+}
+
+/**
+ * dln2_transfer_tx - variant of @dln2_transfer() where RX buffer is not needed
+ *
+ * @pdev - the sub-device which is issuing this transfer
+ * @cmd - the command to be sent to the device
+ * @obuf - the buffer to be sent to the device; it can be NULL if the
+ *     user doesn't need to transmit data with this command
+ * @obuf_len - the size of the buffer to be sent to the device
+ *
+ * @return 0 for success, negative value for errors
+ */
+static inline int dln2_transfer_tx(struct platform_device *pdev, u16 cmd,
+                                  const void *obuf, unsigned obuf_len)
+{
+       return dln2_transfer(pdev, cmd, obuf, obuf_len, NULL, NULL);
+}
+
+#endif
index 7e6dc4b2b795b99b37865aba5e07eacb93ebe3df..553f7d09258acc9348fef7ad989c3d97db600e1d 100644 (file)
@@ -131,13 +131,6 @@ enum max77686_opmode {
        MAX77686_OPMODE_STANDBY,
 };
 
-enum max77802_opmode {
-       MAX77802_OPMODE_OFF,
-       MAX77802_OPMODE_STANDBY,
-       MAX77802_OPMODE_LP,
-       MAX77802_OPMODE_NORMAL,
-};
-
 struct max77686_opmode_data {
        int id;
        int mode;
index fc17d56581b2954c877eebcc637adca43a45321f..08dae01258b9f1861cba7b025b414c0820cbb86e 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <linux/i2c.h>
 
-#define MAX77693_NUM_IRQ_MUIC_REGS     3
 #define MAX77693_REG_INVALID           (0xff)
 
 /* Slave addr = 0xCC: PMIC, Charger, Flash LED */
@@ -330,6 +329,13 @@ enum max77693_irq_source {
        MAX77693_IRQ_GROUP_NR,
 };
 
+#define SRC_IRQ_CHARGER                        BIT(0)
+#define SRC_IRQ_TOP                    BIT(1)
+#define SRC_IRQ_FLASH                  BIT(2)
+#define SRC_IRQ_MUIC                   BIT(3)
+#define SRC_IRQ_ALL                    (SRC_IRQ_CHARGER | SRC_IRQ_TOP \
+                                               | SRC_IRQ_FLASH | SRC_IRQ_MUIC)
+
 #define LED_IRQ_FLED2_OPEN             BIT(0)
 #define LED_IRQ_FLED2_SHORT            BIT(1)
 #define LED_IRQ_FLED1_OPEN             BIT(2)
index 74346d5e789900b360b262f2bc92757996d87825..0c12628e91c6a9f9af0910f69c77b235f182aa49 100644 (file)
 #define SD_SAMPLE_POINT_CTL            0xFDA7
 #define SD_PUSH_POINT_CTL              0xFDA8
 #define SD_CMD0                                0xFDA9
+#define   SD_CMD_START                 0x40
 #define SD_CMD1                                0xFDAA
 #define SD_CMD2                                0xFDAB
 #define SD_CMD3                                0xFDAC
 #define PM_CTRL1                       0xFF44
 #define PM_CTRL2                       0xFF45
 #define PM_CTRL3                       0xFF46
+#define   SDIO_SEND_PME_EN             0x80
+#define   FORCE_RC_MODE_ON             0x40
+#define   FORCE_RX50_LINK_ON           0x20
+#define   D3_DELINK_MODE_EN            0x10
+#define   USE_PESRTB_CTL_DELINK                0x08
+#define   DELAY_PIN_WAKE               0x04
+#define   RESET_PIN_WAKE               0x02
+#define   PM_WAKE_EN                   0x01
 #define PM_CTRL4                       0xFF47
 
 /* Memory mapping */
 #define PHY_DUM_REG                    0x1F
 
 #define LCTLR                          0x80
+#define   LCTLR_EXT_SYNC               0x80
+#define   LCTLR_COMMON_CLOCK_CFG       0x40
+#define   LCTLR_RETRAIN_LINK           0x20
+#define   LCTLR_LINK_DISABLE           0x10
+#define   LCTLR_RCB                    0x08
+#define   LCTLR_RESERVED               0x04
+#define   LCTLR_ASPM_CTL_MASK          0x03
+
 #define PCR_SETTING_REG1               0x724
 #define PCR_SETTING_REG2               0x814
 #define PCR_SETTING_REG3               0x747
@@ -967,4 +984,24 @@ static inline u8 *rtsx_pci_get_cmd_data(struct rtsx_pcr *pcr)
        return (u8 *)(pcr->host_cmds_ptr);
 }
 
+static inline int rtsx_pci_update_cfg_byte(struct rtsx_pcr *pcr, int addr,
+               u8 mask, u8 append)
+{
+       int err;
+       u8 val;
+
+       err = pci_read_config_byte(pcr->pci, addr, &val);
+       if (err < 0)
+               return err;
+       return pci_write_config_byte(pcr->pci, addr, (val & mask) | append);
+}
+
+static inline void rtsx_pci_write_be32(struct rtsx_pcr *pcr, u16 reg, u32 val)
+{
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg,     0xFF, val >> 24);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 1, 0xFF, val >> 16);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 2, 0xFF, val >> 8);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 3, 0xFF, val);
+}
+
 #endif
index 1825edacbda7aa57fa53792bf513fe058d61110a..3fdb7cfbffb3acf09b133f97f42cf248fb65ee8a 100644 (file)
@@ -28,6 +28,7 @@
 #define MIN_800_MV             800000
 #define MIN_750_MV             750000
 #define MIN_600_MV             600000
+#define MIN_500_MV             500000
 
 /* Macros to represent steps for LDO/BUCK */
 #define STEP_50_MV             50000
@@ -41,6 +42,7 @@ enum sec_device_type {
        S5M8767X,
        S2MPA01,
        S2MPS11X,
+       S2MPS13X,
        S2MPS14X,
        S2MPU02,
 };
diff --git a/include/linux/mfd/samsung/s2mps13.h b/include/linux/mfd/samsung/s2mps13.h
new file mode 100644 (file)
index 0000000..ce5dda8
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * s2mps13.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *              http://www.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LINUX_MFD_S2MPS13_H
+#define __LINUX_MFD_S2MPS13_H
+
+/* S2MPS13 registers */
+enum s2mps13_reg {
+       S2MPS13_REG_ID,
+       S2MPS13_REG_INT1,
+       S2MPS13_REG_INT2,
+       S2MPS13_REG_INT3,
+       S2MPS13_REG_INT1M,
+       S2MPS13_REG_INT2M,
+       S2MPS13_REG_INT3M,
+       S2MPS13_REG_ST1,
+       S2MPS13_REG_ST2,
+       S2MPS13_REG_PWRONSRC,
+       S2MPS13_REG_OFFSRC,
+       S2MPS13_REG_BU_CHG,
+       S2MPS13_REG_RTCCTRL,
+       S2MPS13_REG_CTRL1,
+       S2MPS13_REG_CTRL2,
+       S2MPS13_REG_RSVD1,
+       S2MPS13_REG_RSVD2,
+       S2MPS13_REG_RSVD3,
+       S2MPS13_REG_RSVD4,
+       S2MPS13_REG_RSVD5,
+       S2MPS13_REG_RSVD6,
+       S2MPS13_REG_CTRL3,
+       S2MPS13_REG_RSVD7,
+       S2MPS13_REG_RSVD8,
+       S2MPS13_REG_WRSTBI,
+       S2MPS13_REG_B1CTRL,
+       S2MPS13_REG_B1OUT,
+       S2MPS13_REG_B2CTRL,
+       S2MPS13_REG_B2OUT,
+       S2MPS13_REG_B3CTRL,
+       S2MPS13_REG_B3OUT,
+       S2MPS13_REG_B4CTRL,
+       S2MPS13_REG_B4OUT,
+       S2MPS13_REG_B5CTRL,
+       S2MPS13_REG_B5OUT,
+       S2MPS13_REG_B6CTRL,
+       S2MPS13_REG_B6OUT,
+       S2MPS13_REG_B7CTRL,
+       S2MPS13_REG_B7OUT,
+       S2MPS13_REG_B8CTRL,
+       S2MPS13_REG_B8OUT,
+       S2MPS13_REG_B9CTRL,
+       S2MPS13_REG_B9OUT,
+       S2MPS13_REG_B10CTRL,
+       S2MPS13_REG_B10OUT,
+       S2MPS13_REG_BB1CTRL,
+       S2MPS13_REG_BB1OUT,
+       S2MPS13_REG_BUCK_RAMP1,
+       S2MPS13_REG_BUCK_RAMP2,
+       S2MPS13_REG_LDO_DVS1,
+       S2MPS13_REG_LDO_DVS2,
+       S2MPS13_REG_LDO_DVS3,
+       S2MPS13_REG_B6OUT2,
+       S2MPS13_REG_L1CTRL,
+       S2MPS13_REG_L2CTRL,
+       S2MPS13_REG_L3CTRL,
+       S2MPS13_REG_L4CTRL,
+       S2MPS13_REG_L5CTRL,
+       S2MPS13_REG_L6CTRL,
+       S2MPS13_REG_L7CTRL,
+       S2MPS13_REG_L8CTRL,
+       S2MPS13_REG_L9CTRL,
+       S2MPS13_REG_L10CTRL,
+       S2MPS13_REG_L11CTRL,
+       S2MPS13_REG_L12CTRL,
+       S2MPS13_REG_L13CTRL,
+       S2MPS13_REG_L14CTRL,
+       S2MPS13_REG_L15CTRL,
+       S2MPS13_REG_L16CTRL,
+       S2MPS13_REG_L17CTRL,
+       S2MPS13_REG_L18CTRL,
+       S2MPS13_REG_L19CTRL,
+       S2MPS13_REG_L20CTRL,
+       S2MPS13_REG_L21CTRL,
+       S2MPS13_REG_L22CTRL,
+       S2MPS13_REG_L23CTRL,
+       S2MPS13_REG_L24CTRL,
+       S2MPS13_REG_L25CTRL,
+       S2MPS13_REG_L26CTRL,
+       S2MPS13_REG_L27CTRL,
+       S2MPS13_REG_L28CTRL,
+       S2MPS13_REG_L30CTRL,
+       S2MPS13_REG_L31CTRL,
+       S2MPS13_REG_L32CTRL,
+       S2MPS13_REG_L33CTRL,
+       S2MPS13_REG_L34CTRL,
+       S2MPS13_REG_L35CTRL,
+       S2MPS13_REG_L36CTRL,
+       S2MPS13_REG_L37CTRL,
+       S2MPS13_REG_L38CTRL,
+       S2MPS13_REG_L39CTRL,
+       S2MPS13_REG_L40CTRL,
+       S2MPS13_REG_LDODSCH1,
+       S2MPS13_REG_LDODSCH2,
+       S2MPS13_REG_LDODSCH3,
+       S2MPS13_REG_LDODSCH4,
+       S2MPS13_REG_LDODSCH5,
+};
+
+/*  regulator ids */
+enum s2mps13_regulators {
+       S2MPS13_LDO1,
+       S2MPS13_LDO2,
+       S2MPS13_LDO3,
+       S2MPS13_LDO4,
+       S2MPS13_LDO5,
+       S2MPS13_LDO6,
+       S2MPS13_LDO7,
+       S2MPS13_LDO8,
+       S2MPS13_LDO9,
+       S2MPS13_LDO10,
+       S2MPS13_LDO11,
+       S2MPS13_LDO12,
+       S2MPS13_LDO13,
+       S2MPS13_LDO14,
+       S2MPS13_LDO15,
+       S2MPS13_LDO16,
+       S2MPS13_LDO17,
+       S2MPS13_LDO18,
+       S2MPS13_LDO19,
+       S2MPS13_LDO20,
+       S2MPS13_LDO21,
+       S2MPS13_LDO22,
+       S2MPS13_LDO23,
+       S2MPS13_LDO24,
+       S2MPS13_LDO25,
+       S2MPS13_LDO26,
+       S2MPS13_LDO27,
+       S2MPS13_LDO28,
+       S2MPS13_LDO29,
+       S2MPS13_LDO30,
+       S2MPS13_LDO31,
+       S2MPS13_LDO32,
+       S2MPS13_LDO33,
+       S2MPS13_LDO34,
+       S2MPS13_LDO35,
+       S2MPS13_LDO36,
+       S2MPS13_LDO37,
+       S2MPS13_LDO38,
+       S2MPS13_LDO39,
+       S2MPS13_LDO40,
+       S2MPS13_BUCK1,
+       S2MPS13_BUCK2,
+       S2MPS13_BUCK3,
+       S2MPS13_BUCK4,
+       S2MPS13_BUCK5,
+       S2MPS13_BUCK6,
+       S2MPS13_BUCK7,
+       S2MPS13_BUCK8,
+       S2MPS13_BUCK9,
+       S2MPS13_BUCK10,
+
+       S2MPS13_REGULATOR_MAX,
+};
+
+/*
+ * Default ramp delay in uv/us. Datasheet says that ramp delay can be
+ * controlled however it does not specify which register is used for that.
+ * Let's assume that default value will be set.
+ */
+#define S2MPS13_BUCK_RAMP_DELAY                12500
+
+#endif /*  __LINUX_MFD_S2MPS13_H */
index ff44374a1a4e0ea4b90418c49514f7f39a7b79e8..c877cad61a132586086c6c51ef327a2877d393d2 100644 (file)
 #define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK    (0x3 << 17)
 #define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK    (0x1 << 14)
 
+/* For imx6sx iomux gpr register field define */
+#define IMX6SX_GPR1_VDEC_SW_RST_MASK                   (0x1 << 20)
+#define IMX6SX_GPR1_VDEC_SW_RST_RESET                  (0x1 << 20)
+#define IMX6SX_GPR1_VDEC_SW_RST_RELEASE                        (0x0 << 20)
+#define IMX6SX_GPR1_VADC_SW_RST_MASK                   (0x1 << 19)
+#define IMX6SX_GPR1_VADC_SW_RST_RESET                  (0x1 << 19)
+#define IMX6SX_GPR1_VADC_SW_RST_RELEASE                        (0x0 << 19)
+#define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK             (0x3 << 13)
+#define IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK             (0x3 << 17)
+#define IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_EXT              (0x3 << 13)
+
+#define IMX6SX_GPR4_FEC_ENET1_STOP_REQ                 (0x1 << 3)
+#define IMX6SX_GPR4_FEC_ENET2_STOP_REQ                 (0x1 << 4)
+
+#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_MASK             (0x1 << 3)
+#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF1           (0x0 << 3)
+#define IMX6SX_GPR5_DISP_MUX_LDB_CTRL_LCDIF2           (0x1 << 3)
+
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_MASK                 (0x3 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_EXT_PIN              (0x0 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_CVD                  (0x1 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_VDAC_TO_CSI          (0x2 << 27)
+#define IMX6SX_GPR5_CSI2_MUX_CTRL_GND                  (0x3 << 27)
+#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_MASK                (0x1 << 26)
+#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_ENABLE      (0x1 << 26)
+#define IMX6SX_GPR5_VADC_TO_CSI_CAPTURE_EN_DISABLE     (0x0 << 26)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_MASK                 (0x3 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_EXT_PIN              (0x0 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_CVD                  (0x1 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_VDAC_TO_CSI          (0x2 << 4)
+#define IMX6SX_GPR5_CSI1_MUX_CTRL_GND                  (0x3 << 4)
+
+#define IMX6SX_GPR5_DISP_MUX_DCIC2_LCDIF2              (0x0 << 2)
+#define IMX6SX_GPR5_DISP_MUX_DCIC2_LVDS                        (0x1 << 2)
+#define IMX6SX_GPR5_DISP_MUX_DCIC2_MASK                        (0x1 << 2)
+#define IMX6SX_GPR5_DISP_MUX_DCIC1_LCDIF1              (0x0 << 1)
+#define IMX6SX_GPR5_DISP_MUX_DCIC1_LVDS                        (0x1 << 1)
+#define IMX6SX_GPR5_DISP_MUX_DCIC1_MASK                        (0x1 << 1)
+
 #endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
index e6088c2e2092f0db394940d0a91802de5297c01c..e1c12d84c26af4c6f0a7bdcb7e7d4df4bf4b81da 100644 (file)
@@ -164,13 +164,10 @@ struct tc3589x_keypad_platform_data {
 
 /**
  * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data
- * @gpio_base: first gpio number assigned to TC3589x.  A maximum of
- *            %TC3589x_NR_GPIOS GPIOs will be allocated.
  * @setup: callback for board-specific initialization
  * @remove: callback for board-specific teardown
  */
 struct tc3589x_gpio_platform_data {
-       int gpio_base;
        void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base);
        void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base);
 };
@@ -178,18 +175,13 @@ struct tc3589x_gpio_platform_data {
 /**
  * struct tc3589x_platform_data - TC3589x platform data
  * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*)
- * @irq_base: base IRQ number.  %TC3589x_NR_IRQS irqs will be used.
  * @gpio: GPIO-specific platform data
  * @keypad: keypad-specific platform data
  */
 struct tc3589x_platform_data {
        unsigned int block;
-       int irq_base;
        struct tc3589x_gpio_platform_data *gpio;
        const struct tc3589x_keypad_platform_data *keypad;
 };
 
-#define TC3589x_NR_GPIOS       24
-#define TC3589x_NR_IRQS                TC3589x_INT_GPIO(TC3589x_NR_GPIOS)
-
 #endif
index 02d11ee7f19d1515ac47178575d653e52fc8e4e8..b46461116cd2c49333ee26767a4ff5af01dd8ffa 100644 (file)
@@ -1176,6 +1176,7 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
 
 extern void truncate_pagecache(struct inode *inode, loff_t new);
 extern void truncate_setsize(struct inode *inode, loff_t newsize);
+void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to);
 void truncate_pagecache_range(struct inode *inode, loff_t offset, loff_t end);
 int truncate_inode_page(struct address_space *mapping, struct page *page);
 int generic_error_remove_page(struct address_space *mapping, struct page *page);
@@ -1234,7 +1235,6 @@ int __set_page_dirty_no_writeback(struct page *page);
 int redirty_page_for_writepage(struct writeback_control *wbc,
                                struct page *page);
 void account_page_dirtied(struct page *page, struct address_space *mapping);
-void account_page_writeback(struct page *page);
 int set_page_dirty(struct page *page);
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
index b0692d28f8e649ec64d5f38db0a18967b547ff29..4d69c00497bdf4de58334a4c9805d6defea7957b 100644 (file)
@@ -88,6 +88,9 @@ struct mmc_ext_csd {
        unsigned int            data_tag_unit_size;     /* DATA TAG UNIT size */
        unsigned int            boot_ro_lock;           /* ro lock support */
        bool                    boot_ro_lockable;
+       bool                    ffu_capable;    /* Firmware upgrade support */
+#define MMC_FIRMWARE_LEN 8
+       u8                      fwrev[MMC_FIRMWARE_LEN];  /* FW version */
        u8                      raw_exception_status;   /* 54 */
        u8                      raw_partition_support;  /* 160 */
        u8                      raw_rpmb_size_mult;     /* 168 */
@@ -509,24 +512,8 @@ 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)
 
-#define mmc_list_to_card(l)    container_of(l, struct mmc_card, node)
-#define mmc_get_drvdata(c)     dev_get_drvdata(&(c)->dev)
-#define mmc_set_drvdata(c,d)   dev_set_drvdata(&(c)->dev, d)
-
-/*
- * 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 *);
-       int (*suspend)(struct mmc_card *);
-       int (*resume)(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 int mmc_register_driver(struct device_driver *);
+extern void mmc_unregister_driver(struct device_driver *);
 
 extern void mmc_fixup_device(struct mmc_card *card,
                             const struct mmc_fixup *table);
index f206e29f94d72cb74afbcf10bd14111676424c80..cb2b0400d2840982a3a57ffb1cb51b0723b6fa85 100644 (file)
@@ -154,7 +154,8 @@ extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
 extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool,
                        bool, bool);
 extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
-extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
+extern int mmc_send_tuning(struct mmc_host *host);
+extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
 
 #define MMC_ERASE_ARG          0x00000000
 #define MMC_SECURE_ERASE_ARG   0x80000000
index 001366927cf443aa4ca46275cf8d0c5c3a601b86..42b724e8d503f3a368fd26c061a7f779df028966 100644 (file)
@@ -54,6 +54,7 @@ struct mmc_data;
  *     transfer is in progress.
  * @use_dma: Whether DMA channel is initialized or not.
  * @using_dma: Whether DMA is in use for the current transfer.
+ * @dma_64bit_address: Whether DMA supports 64-bit address mode or not.
  * @sg_dma: Bus address of DMA buffer.
  * @sg_cpu: Virtual address of DMA buffer.
  * @dma_ops: Pointer to platform-specific DMA callbacks.
@@ -96,6 +97,7 @@ struct mmc_data;
  * @quirks: Set of quirks that apply to specific versions of the IP.
  * @irq_flags: The flags to be passed to request_irq.
  * @irq: The irq value to be passed to request_irq.
+ * @sdio_id0: Number of slot0 in the SDIO interrupt registers.
  *
  * Locking
  * =======
@@ -135,11 +137,11 @@ struct dw_mci {
        struct mmc_command      stop_abort;
        unsigned int            prev_blksz;
        unsigned char           timing;
-       struct workqueue_struct *card_workqueue;
 
        /* DMA interface members*/
        int                     use_dma;
        int                     using_dma;
+       int                     dma_64bit_address;
 
        dma_addr_t              sg_dma;
        void                    *sg_cpu;
@@ -154,7 +156,6 @@ struct dw_mci {
        u32                     stop_cmdr;
        u32                     dir_status;
        struct tasklet_struct   tasklet;
-       struct work_struct      card_work;
        unsigned long           pending_events;
        unsigned long           completed_events;
        enum dw_mci_state       state;
@@ -193,6 +194,8 @@ struct dw_mci {
        bool                    vqmmc_enabled;
        unsigned long           irq_flags; /* IRQ flags */
        int                     irq;
+
+       int                     sdio_id0;
 };
 
 /* DMA ops for Internal/External DMAC interface */
index df0c15396bbfcce6c01eabe49778c4584d4b2d69..9f322706f7cb26a69c9f7ad4d21c195a8befe1aa 100644 (file)
@@ -289,6 +289,7 @@ struct mmc_host {
 #define MMC_CAP2_HS400_1_2V    (1 << 16)       /* Can support HS400 1.2V */
 #define MMC_CAP2_HS400         (MMC_CAP2_HS400_1_8V | \
                                 MMC_CAP2_HS400_1_2V)
+#define MMC_CAP2_HSX00_1_2V    (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V)
 #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
index 1cd00b3a75b9e33ee0d2353f92231440802ae920..49ad7a9436384107375a0e2c8141a43faddc1e6d 100644 (file)
@@ -296,6 +296,7 @@ struct _mmc_csd {
 #define EXT_CSD_SANITIZE_START         165     /* W */
 #define EXT_CSD_WR_REL_PARAM           166     /* RO */
 #define EXT_CSD_RPMB_MULT              168     /* RO */
+#define EXT_CSD_FW_CONFIG              169     /* R/W */
 #define EXT_CSD_BOOT_WP                        173     /* R/W */
 #define EXT_CSD_ERASE_GROUP_DEF                175     /* R/W */
 #define EXT_CSD_PART_CONFIG            179     /* R/W */
@@ -332,6 +333,8 @@ struct _mmc_csd {
 #define EXT_CSD_GENERIC_CMD6_TIME      248     /* RO */
 #define EXT_CSD_CACHE_SIZE             249     /* RO, 4 bytes */
 #define EXT_CSD_PWR_CL_DDR_200_360     253     /* RO */
+#define EXT_CSD_FIRMWARE_VERSION       254     /* RO, 8 bytes */
+#define EXT_CSD_SUPPORTED_MODE         493     /* RO */
 #define EXT_CSD_TAG_UNIT_SIZE          498     /* RO */
 #define EXT_CSD_DATA_TAG_SUPPORT       499     /* RO */
 #define EXT_CSD_MAX_PACKED_WRITES      500     /* RO */
index dba793e3a331f1d3039b7c5e96eb2a5ccba188b3..375af80bde7d7c90bb1c09efb3edc297dbe4d864 100644 (file)
@@ -100,6 +100,12 @@ struct sdhci_host {
 #define SDHCI_QUIRK2_BROKEN_DDR50                      (1<<7)
 /* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */
 #define SDHCI_QUIRK2_STOP_WITH_TC                      (1<<8)
+/* Controller does not support 64-bit DMA */
+#define SDHCI_QUIRK2_BROKEN_64_BIT_DMA                 (1<<9)
+/* need clear transfer mode register before send cmd */
+#define SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1<<10)
+/* Capability register bit-63 indicates HS400 support */
+#define SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400              (1<<11)
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */
@@ -130,6 +136,7 @@ struct sdhci_host {
 #define SDHCI_SDIO_IRQ_ENABLED (1<<9)  /* SDIO irq enabled */
 #define SDHCI_SDR104_NEEDS_TUNING (1<<10)      /* SDR104/HS200 needs tuning */
 #define SDHCI_USING_RETUNING_TIMER (1<<11)     /* Host is using a retuning timer for the card */
+#define SDHCI_USE_64_BIT_DMA   (1<<12) /* Use 64-bit DMA */
 
        unsigned int version;   /* SDHCI spec. version */
 
@@ -155,12 +162,19 @@ struct sdhci_host {
 
        int sg_count;           /* Mapped sg entries */
 
-       u8 *adma_desc;          /* ADMA descriptor table */
-       u8 *align_buffer;       /* Bounce buffer */
+       void *adma_table;       /* ADMA descriptor table */
+       void *align_buffer;     /* Bounce buffer */
+
+       size_t adma_table_sz;   /* ADMA descriptor table size */
+       size_t align_buffer_sz; /* Bounce buffer size */
 
        dma_addr_t adma_addr;   /* Mapped ADMA descr. table */
        dma_addr_t align_addr;  /* Mapped bounce buffer */
 
+       unsigned int desc_sz;   /* ADMA descriptor size */
+       unsigned int align_sz;  /* ADMA alignment */
+       unsigned int align_mask;        /* ADMA alignment mask */
+
        struct tasklet_struct finish_tasklet;   /* Tasklet structures */
 
        struct timer_list timer;        /* Timer for timeouts */
index 50f0bc952328ba0eefdb901f31424821a8765539..aab032a6ae6124de63b7934f49d0dc564b0d2dc3 100644 (file)
@@ -84,8 +84,6 @@ struct sdio_driver {
        struct device_driver drv;
 };
 
-#define to_sdio_driver(d)      container_of(d, struct sdio_driver, drv)
-
 /**
  * SDIO_DEVICE - macro used to describe a specific SDIO device
  * @vend: the 16 bit manufacturer code
index 48bf12ef6620ccc863c27afc615a2e2e460a6c99..ffe66e381c04237fb54a0447741f39a40d7c5d71 100644 (file)
@@ -431,6 +431,15 @@ struct zone {
         */
        int                     nr_migrate_reserve_block;
 
+#ifdef CONFIG_MEMORY_ISOLATION
+       /*
+        * Number of isolated pageblock. It is used to solve incorrect
+        * freepage counting problem due to racy retrieving migratetype
+        * of pageblock. Protected by zone->lock.
+        */
+       unsigned long           nr_isolate_pageblock;
+#endif
+
 #ifdef CONFIG_MEMORY_HOTPLUG
        /* see spanned/present_pages for more description */
        seqlock_t               span_seqlock;
index 9262e4bf0cc3408588adc819abc7ea9be69b88dd..c2c561dc011440ee83f395aba0a226ab467204a0 100644 (file)
@@ -81,6 +81,9 @@ extern struct vfsmount *mntget(struct vfsmount *mnt);
 extern struct vfsmount *mnt_clone_internal(struct path *path);
 extern int __mnt_is_readonly(struct vfsmount *mnt);
 
+struct path;
+extern struct vfsmount *clone_private_mount(struct path *path);
+
 struct file_system_type;
 extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
                                      int flags, const char *name,
index 9e6294f32ba88fffb4c126c6ee7478c04f657eba..046a0a2e4c4efd41c78bcd38cff00f1030b7f3e2 100644 (file)
@@ -187,32 +187,17 @@ struct spi_nor {
 /**
  * spi_nor_scan() - scan the SPI NOR
  * @nor:       the spi_nor structure
- * @id:                the spi_device_id provided by the driver
+ * @name:      the chip type name
  * @mode:      the read mode supported by the driver
  *
  * The drivers can use this fuction to scan the SPI NOR.
  * In the scanning, it will try to get all the necessary information to
  * fill the mtd_info{} and the spi_nor{}.
  *
- * The board may assigns a spi_device_id with @id which be used to compared with
- * the spi_device_id detected by the scanning.
+ * The chip type name can be provided through the @name parameter.
  *
  * Return: 0 for success, others for failure.
  */
-int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
-                       enum read_mode mode);
-extern const struct spi_device_id spi_nor_ids[];
-
-/**
- * spi_nor_match_id() - find the spi_device_id by the name
- * @name:      the name of the spi_device_id
- *
- * The drivers use this function to find the spi_device_id
- * specified by the @name.
- *
- * Return: returns the right spi_device_id pointer on success,
- *         and returns NULL on failure.
- */
-const struct spi_device_id *spi_nor_match_id(char *name);
+int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode);
 
 #endif
index 983876f24aed06ce26c7e33d8c83d77fa4736381..47ebb4fafd87f7ba0f37b36b22f54952f6f823c8 100644 (file)
@@ -1224,11 +1224,22 @@ struct nfs41_free_stateid_res {
        unsigned int                    status;
 };
 
+static inline void
+nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo)
+{
+       kfree(cinfo->buckets);
+}
+
 #else
 
 struct pnfs_ds_commit_info {
 };
 
+static inline void
+nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo)
+{
+}
+
 #endif /* CONFIG_NFS_V4_1 */
 
 #ifdef CONFIG_NFS_V4_2
index 6545e7aec7bb95dc41ad6225050cb19e7038287a..c55b50018ac4316c7874c2a5bf43f51a67296a4b 100644 (file)
@@ -267,14 +267,12 @@ extern int of_property_read_u64(const struct device_node *np,
 extern int of_property_read_string(struct device_node *np,
                                   const char *propname,
                                   const char **out_string);
-extern int of_property_read_string_index(struct device_node *np,
-                                        const char *propname,
-                                        int index, const char **output);
 extern int of_property_match_string(struct device_node *np,
                                    const char *propname,
                                    const char *string);
-extern int of_property_count_strings(struct device_node *np,
-                                    const char *propname);
+extern int of_property_read_string_helper(struct device_node *np,
+                                             const char *propname,
+                                             const char **out_strs, size_t sz, int index);
 extern int of_device_is_compatible(const struct device_node *device,
                                   const char *);
 extern int of_device_is_available(const struct device_node *device);
@@ -486,15 +484,9 @@ static inline int of_property_read_string(struct device_node *np,
        return -ENOSYS;
 }
 
-static inline int of_property_read_string_index(struct device_node *np,
-                                               const char *propname, int index,
-                                               const char **out_string)
-{
-       return -ENOSYS;
-}
-
-static inline int of_property_count_strings(struct device_node *np,
-                                           const char *propname)
+static inline int of_property_read_string_helper(struct device_node *np,
+                                                const char *propname,
+                                                const char **out_strs, size_t sz, int index)
 {
        return -ENOSYS;
 }
@@ -667,6 +659,70 @@ static inline int of_property_count_u64_elems(const struct device_node *np,
        return of_property_count_elems_of_size(np, propname, sizeof(u64));
 }
 
+/**
+ * of_property_read_string_array() - Read an array of strings from a multiple
+ * strings property.
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_strs:  output array of string pointers.
+ * @sz:                number of array elements to read.
+ *
+ * Search for a property in a device tree node and retrieve a list of
+ * terminated string values (pointer to data, not a copy) in that property.
+ *
+ * If @out_strs is NULL, the number of strings in the property is returned.
+ */
+static inline int of_property_read_string_array(struct device_node *np,
+                                               const char *propname, const char **out_strs,
+                                               size_t sz)
+{
+       return of_property_read_string_helper(np, propname, out_strs, sz, 0);
+}
+
+/**
+ * of_property_count_strings() - Find and return the number of strings from a
+ * multiple strings property.
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+static inline int of_property_count_strings(struct device_node *np,
+                                           const char *propname)
+{
+       return of_property_read_string_helper(np, propname, NULL, 0, 0);
+}
+
+/**
+ * of_property_read_string_index() - Find and read a string from a multiple
+ * strings property.
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @index:     index of the string in the list of strings
+ * @out_string:        pointer to null terminated return string, modified only if
+ *             return value is 0.
+ *
+ * Search for a property in a device tree node and retrieve a null
+ * terminated string value (pointer to data, not a copy) in the list of strings
+ * contained in that property.
+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EILSEQ if the string is not
+ * null-terminated within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+static inline int of_property_read_string_index(struct device_node *np,
+                                               const char *propname,
+                                               int index, const char **output)
+{
+       int rc = of_property_read_string_helper(np, propname, output, 1, index);
+       return rc < 0 ? rc : 0;
+}
+
 /**
  * of_property_read_bool - Findfrom a property
  * @np:                device node from which the property value is to be read.
@@ -866,4 +922,15 @@ static inline int of_changeset_update_property(struct of_changeset *ocs,
 /* CONFIG_OF_RESOLVE api */
 extern int of_resolve_phandles(struct device_node *tree);
 
+/**
+ * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node
+ * @np: Pointer to the given device_node
+ *
+ * return true if present false otherwise
+ */
+static inline bool of_device_is_system_power_controller(const struct device_node *np)
+{
+       return of_property_read_bool(np, "system-power-controller");
+}
+
 #endif /* _LINUX_OF_H */
index 5b5efae091350a839e5b27ff5c5b5b34406e9f29..ad2f6705437266373ff1bb73881df0a5da8f0d3b 100644 (file)
@@ -16,7 +16,7 @@ struct reserved_mem {
 };
 
 struct reserved_mem_ops {
-       void    (*device_init)(struct reserved_mem *rmem,
+       int     (*device_init)(struct reserved_mem *rmem,
                               struct device *dev);
        void    (*device_release)(struct reserved_mem *rmem,
                                  struct device *dev);
@@ -28,14 +28,17 @@ typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
        _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
 
 #ifdef CONFIG_OF_RESERVED_MEM
-void of_reserved_mem_device_init(struct device *dev);
+int of_reserved_mem_device_init(struct device *dev);
 void of_reserved_mem_device_release(struct device *dev);
 
 void fdt_init_reserved_mem(void);
 void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
                               phys_addr_t base, phys_addr_t size);
 #else
-static inline void of_reserved_mem_device_init(struct device *dev) { }
+static inline int of_reserved_mem_device_init(struct device *dev)
+{
+       return -ENOSYS;
+}
 static inline void of_reserved_mem_device_release(struct device *pdev) { }
 
 static inline void fdt_init_reserved_mem(void) { }
diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
new file mode 100644 (file)
index 0000000..c2080ee
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ *  OMAP GPMC (General Purpose Memory Controller) defines
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+/* Maximum Number of Chip Selects */
+#define GPMC_CS_NUM            8
+
+#define GPMC_CONFIG_WP         0x00000005
+
+#define GPMC_IRQ_FIFOEVENTENABLE       0x01
+#define GPMC_IRQ_COUNT_EVENT           0x02
+
+#define GPMC_BURST_4                   4       /* 4 word burst */
+#define GPMC_BURST_8                   8       /* 8 word burst */
+#define GPMC_BURST_16                  16      /* 16 word burst */
+#define GPMC_DEVWIDTH_8BIT             1       /* 8-bit device width */
+#define GPMC_DEVWIDTH_16BIT            2       /* 16-bit device width */
+#define GPMC_MUX_AAD                   1       /* Addr-Addr-Data multiplex */
+#define GPMC_MUX_AD                    2       /* Addr-Data multiplex */
+
+/* bool type time settings */
+struct gpmc_bool_timings {
+       bool cycle2cyclediffcsen;
+       bool cycle2cyclesamecsen;
+       bool we_extra_delay;
+       bool oe_extra_delay;
+       bool adv_extra_delay;
+       bool cs_extra_delay;
+       bool time_para_granularity;
+};
+
+/*
+ * Note that all values in this struct are in nanoseconds except sync_clk
+ * (which is in picoseconds), while the register values are in gpmc_fck cycles.
+ */
+struct gpmc_timings {
+       /* Minimum clock period for synchronous mode (in picoseconds) */
+       u32 sync_clk;
+
+       /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
+       u32 cs_on;              /* Assertion time */
+       u32 cs_rd_off;          /* Read deassertion time */
+       u32 cs_wr_off;          /* Write deassertion time */
+
+       /* ADV signal timings corresponding to GPMC_CONFIG3 */
+       u32 adv_on;             /* Assertion time */
+       u32 adv_rd_off;         /* Read deassertion time */
+       u32 adv_wr_off;         /* Write deassertion time */
+
+       /* WE signals timings corresponding to GPMC_CONFIG4 */
+       u32 we_on;              /* WE assertion time */
+       u32 we_off;             /* WE deassertion time */
+
+       /* OE signals timings corresponding to GPMC_CONFIG4 */
+       u32 oe_on;              /* OE assertion time */
+       u32 oe_off;             /* OE deassertion time */
+
+       /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
+       u32 page_burst_access;  /* Multiple access word delay */
+       u32 access;             /* Start-cycle to first data valid delay */
+       u32 rd_cycle;           /* Total read cycle time */
+       u32 wr_cycle;           /* Total write cycle time */
+
+       u32 bus_turnaround;
+       u32 cycle2cycle_delay;
+
+       u32 wait_monitoring;
+       u32 clk_activation;
+
+       /* The following are only on OMAP3430 */
+       u32 wr_access;          /* WRACCESSTIME */
+       u32 wr_data_mux_bus;    /* WRDATAONADMUXBUS */
+
+       struct gpmc_bool_timings bool_timings;
+};
+
+/* Device timings in picoseconds */
+struct gpmc_device_timings {
+       u32 t_ceasu;    /* address setup to CS valid */
+       u32 t_avdasu;   /* address setup to ADV valid */
+       /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is
+        * of tusb using these timings even for sync whilst
+        * ideally for adv_rd/(wr)_off it should have considered
+        * t_avdh instead. This indirectly necessitates r/w
+        * variations of t_avdp as it is possible to have one
+        * sync & other async
+        */
+       u32 t_avdp_r;   /* ADV low time (what about t_cer ?) */
+       u32 t_avdp_w;
+       u32 t_aavdh;    /* address hold time */
+       u32 t_oeasu;    /* address setup to OE valid */
+       u32 t_aa;       /* access time from ADV assertion */
+       u32 t_iaa;      /* initial access time */
+       u32 t_oe;       /* access time from OE assertion */
+       u32 t_ce;       /* access time from CS asertion */
+       u32 t_rd_cycle; /* read cycle time */
+       u32 t_cez_r;    /* read CS deassertion to high Z */
+       u32 t_cez_w;    /* write CS deassertion to high Z */
+       u32 t_oez;      /* OE deassertion to high Z */
+       u32 t_weasu;    /* address setup to WE valid */
+       u32 t_wpl;      /* write assertion time */
+       u32 t_wph;      /* write deassertion time */
+       u32 t_wr_cycle; /* write cycle time */
+
+       u32 clk;
+       u32 t_bacc;     /* burst access valid clock to output delay */
+       u32 t_ces;      /* CS setup time to clk */
+       u32 t_avds;     /* ADV setup time to clk */
+       u32 t_avdh;     /* ADV hold time from clk */
+       u32 t_ach;      /* address hold time from clk */
+       u32 t_rdyo;     /* clk to ready valid */
+
+       u32 t_ce_rdyz;  /* XXX: description ?, or use t_cez instead */
+       u32 t_ce_avd;   /* CS on to ADV on delay */
+
+       /* XXX: check the possibility of combining
+        * cyc_aavhd_oe & cyc_aavdh_we
+        */
+       u8 cyc_aavdh_oe;/* read address hold time in cycles */
+       u8 cyc_aavdh_we;/* write address hold time in cycles */
+       u8 cyc_oe;      /* access time from OE assertion in cycles */
+       u8 cyc_wpl;     /* write deassertion time in cycles */
+       u32 cyc_iaa;    /* initial access time in cycles */
+
+       /* extra delays */
+       bool ce_xdelay;
+       bool avd_xdelay;
+       bool oe_xdelay;
+       bool we_xdelay;
+};
+
+struct gpmc_settings {
+       bool burst_wrap;        /* enables wrap bursting */
+       bool burst_read;        /* enables read page/burst mode */
+       bool burst_write;       /* enables write page/burst mode */
+       bool device_nand;       /* device is NAND */
+       bool sync_read;         /* enables synchronous reads */
+       bool sync_write;        /* enables synchronous writes */
+       bool wait_on_read;      /* monitor wait on reads */
+       bool wait_on_write;     /* monitor wait on writes */
+       u32 burst_len;          /* page/burst length */
+       u32 device_width;       /* device bus width (8 or 16 bit) */
+       u32 mux_add_data;       /* multiplex address & data */
+       u32 wait_pin;           /* wait-pin to be used */
+};
+
+extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
+                            struct gpmc_settings *gpmc_s,
+                            struct gpmc_device_timings *dev_t);
+
+struct gpmc_nand_regs;
+struct device_node;
+
+extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+extern int gpmc_get_client_irq(unsigned irq_config);
+
+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_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);
+extern int gpmc_configure(int cmd, int wval);
+extern void gpmc_read_settings_dt(struct device_node *np,
+                                 struct gpmc_settings *p);
+
+extern void omap3_gpmc_save_context(void);
+extern void omap3_gpmc_restore_context(void);
+
+struct gpmc_timings;
+struct omap_nand_platform_data;
+struct omap_onenand_platform_data;
+
+#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
+extern int gpmc_nand_init(struct omap_nand_platform_data *d,
+                         struct gpmc_timings *gpmc_t);
+#else
+static inline int gpmc_nand_init(struct omap_nand_platform_data *d,
+                                struct gpmc_timings *gpmc_t)
+{
+       return 0;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
+extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+#else
+#define board_onenand_data     NULL
+static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+{
+}
+#endif
index 647395a1a5508f7f138e80ad24afea4fd09638d3..e8d6e10587233466c666d6be2e3fb21603a82552 100644 (file)
@@ -50,6 +50,9 @@ static inline bool oom_task_origin(const struct task_struct *p)
 extern unsigned long oom_badness(struct task_struct *p,
                struct mem_cgroup *memcg, const nodemask_t *nodemask,
                unsigned long totalpages);
+
+extern int oom_kills_count(void);
+extern void note_oom_kill(void);
 extern void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
                             unsigned int points, unsigned long totalpages,
                             struct mem_cgroup *memcg, nodemask_t *nodemask,
index 3fff8e774067904bb73b5817ba471099a80555da..2dc1e1697b451ce678781a55776a15c8934be7a5 100644 (file)
@@ -2,6 +2,10 @@
 #define __LINUX_PAGEISOLATION_H
 
 #ifdef CONFIG_MEMORY_ISOLATION
+static inline bool has_isolate_pageblock(struct zone *zone)
+{
+       return zone->nr_isolate_pageblock;
+}
 static inline bool is_migrate_isolate_page(struct page *page)
 {
        return get_pageblock_migratetype(page) == MIGRATE_ISOLATE;
@@ -11,6 +15,10 @@ static inline bool is_migrate_isolate(int migratetype)
        return migratetype == MIGRATE_ISOLATE;
 }
 #else
+static inline bool has_isolate_pageblock(struct zone *zone)
+{
+       return false;
+}
 static inline bool is_migrate_isolate_page(struct page *page)
 {
        return false;
index 64dacb7288a6fc79e86ca536753f342a37252949..24c7728ca681f997a3a5b10f78ec7af13fd558d3 100644 (file)
@@ -41,8 +41,13 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus)
 
        if (pci_is_root_bus(pbus))
                dev = pbus->bridge;
-       else
+       else {
+               /* If pbus is a virtual bus, there is no bridge to it */
+               if (!pbus->self)
+                       return NULL;
+
                dev = &pbus->self->dev;
+       }
 
        return ACPI_HANDLE(dev);
 }
index 5be8db45e368b23eb4c0d7b16b92f9db49290998..4c8ac5fcc224e2ab4c6af62cd01e130b2bf7dbb1 100644 (file)
@@ -331,6 +331,7 @@ struct pci_dev {
        unsigned int    is_added:1;
        unsigned int    is_busmaster:1; /* device is busmaster */
        unsigned int    no_msi:1;       /* device may not use msi */
+       unsigned int    no_64bit_msi:1; /* device may only use 32-bit MSIs */
        unsigned int    block_cfg_access:1;     /* config space access is blocked */
        unsigned int    broken_parity_status:1; /* Device generates false positive parity */
        unsigned int    irq_reroute_variant:2;  /* device needs IRQ rerouting variant */
index 1fa99a3018171d4a7403f50987eb4e3ae819e0dc..97fb9f69aaedbba28dc16d6de018116d1b1c3f42 100644 (file)
 #define PCI_DEVICE_ID_AMD_15H_M10H_F3  0x1403
 #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d
 #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e
+#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573
+#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F4 0x1574
 #define PCI_DEVICE_ID_AMD_15H_NB_F0    0x1600
 #define PCI_DEVICE_ID_AMD_15H_NB_F1    0x1601
 #define PCI_DEVICE_ID_AMD_15H_NB_F2    0x1602
index d5c89e0dd0e6725c614b491c78b5bfafe9cc46f4..51ce60c35f4c69a6df45d1e104d56d5e47798a78 100644 (file)
@@ -133,7 +133,13 @@ static inline bool __ref_is_percpu(struct percpu_ref *ref,
        /* paired with smp_store_release() in percpu_ref_reinit() */
        smp_read_barrier_depends();
 
-       if (unlikely(percpu_ptr & __PERCPU_REF_ATOMIC))
+       /*
+        * Theoretically, the following could test just ATOMIC; however,
+        * then we'd have to mask off DEAD separately as DEAD may be
+        * visible without ATOMIC if we race with percpu_ref_kill().  DEAD
+        * implies ATOMIC anyway.  Test them together.
+        */
+       if (unlikely(percpu_ptr & __PERCPU_REF_ATOMIC_DEAD))
                return false;
 
        *percpu_countp = (unsigned long __percpu *)percpu_ptr;
index 893a0d07986f526b1402ef19238f6e2dccd70973..486e84ccb1f92545ec0d4f74aaa153abf0ff8049 100644 (file)
@@ -79,7 +79,7 @@ struct perf_branch_stack {
        struct perf_branch_entry        entries[0];
 };
 
-struct perf_regs_user {
+struct perf_regs {
        __u64           abi;
        struct pt_regs  *regs;
 };
@@ -580,34 +580,40 @@ extern u64 perf_event_read_value(struct perf_event *event,
 
 
 struct perf_sample_data {
-       u64                             type;
+       /*
+        * Fields set by perf_sample_data_init(), group so as to
+        * minimize the cachelines touched.
+        */
+       u64                             addr;
+       struct perf_raw_record          *raw;
+       struct perf_branch_stack        *br_stack;
+       u64                             period;
+       u64                             weight;
+       u64                             txn;
+       union  perf_mem_data_src        data_src;
 
+       /*
+        * The other fields, optionally {set,used} by
+        * perf_{prepare,output}_sample().
+        */
+       u64                             type;
        u64                             ip;
        struct {
                u32     pid;
                u32     tid;
        }                               tid_entry;
        u64                             time;
-       u64                             addr;
        u64                             id;
        u64                             stream_id;
        struct {
                u32     cpu;
                u32     reserved;
        }                               cpu_entry;
-       u64                             period;
-       union  perf_mem_data_src        data_src;
        struct perf_callchain_entry     *callchain;
-       struct perf_raw_record          *raw;
-       struct perf_branch_stack        *br_stack;
-       struct perf_regs_user           regs_user;
+       struct perf_regs                regs_user;
+       struct perf_regs                regs_intr;
        u64                             stack_user_size;
-       u64                             weight;
-       /*
-        * Transaction flags for abort events:
-        */
-       u64                             txn;
-};
+} ____cacheline_aligned;
 
 /* default value for data source */
 #define PERF_MEM_NA (PERF_MEM_S(OP, NA)   |\
@@ -624,9 +630,6 @@ static inline void perf_sample_data_init(struct perf_sample_data *data,
        data->raw  = NULL;
        data->br_stack = NULL;
        data->period = period;
-       data->regs_user.abi = PERF_SAMPLE_REGS_ABI_NONE;
-       data->regs_user.regs = NULL;
-       data->stack_user_size = 0;
        data->weight = 0;
        data->data_src.val = PERF_MEM_NA;
        data->txn = 0;
diff --git a/include/linux/pl320-ipc.h b/include/linux/pl320-ipc.h
new file mode 100644 (file)
index 0000000..5161f63
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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/>.
+ */
+
+int pl320_ipc_transmit(u32 *data);
+int pl320_ipc_register_notifier(struct notifier_block *nb);
+int pl320_ipc_unregister_notifier(struct notifier_block *nb);
diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h
new file mode 100644 (file)
index 0000000..67bbcf0
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * MMC definitions for OMAP2
+ *
+ * Copyright (C) 2006 Nokia 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.
+ */
+
+/*
+ * struct omap_hsmmc_dev_attr.flags possibilities
+ *
+ * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
+ *    operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
+ *    should be set if this is the case.  See for example Section 22.5.3
+ *    "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
+ *    Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
+ *
+ * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
+ *    don't work correctly on some MMC controller instances on some
+ *    OMAP3 SoCs; this flag should be set if this is the case.  See
+ *    for example Advisory 2.1.1.128 "MMC: Multiple Block Read
+ *    Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
+ *    Revision F (October 2010) (SPRZ278F).
+ */
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT          BIT(0)
+#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ      BIT(1)
+#define OMAP_HSMMC_SWAKEUP_MISSING             BIT(2)
+
+struct omap_hsmmc_dev_attr {
+       u8 flags;
+};
+
+struct mmc_card;
+
+struct omap_hsmmc_platform_data {
+       /* back-link to device */
+       struct device *dev;
+
+       /* set if your board has components or wiring that limits the
+        * maximum frequency on the MMC bus */
+       unsigned int max_freq;
+
+       /* Integrating attributes from the omap_hwmod layer */
+       u8 controller_flags;
+
+       /* Register offset deviation */
+       u16 reg_offset;
+
+       /*
+        * 4/8 wires and any additional host capabilities
+        * need to OR'd all capabilities (ref. linux/mmc/host.h)
+        */
+       u32 caps;       /* Used for the MMC driver on 2430 and later */
+       u32 pm_caps;    /* PM capabilities of the mmc */
+
+       /* switch pin can be for card detect (default) or card cover */
+       unsigned cover:1;
+
+       /* use the internal clock */
+       unsigned internal_clock:1;
+
+       /* nonremovable e.g. eMMC */
+       unsigned nonremovable:1;
+
+       /* eMMC does not handle power off when not in sleep state */
+       unsigned no_regulator_off_init:1;
+
+       /* we can put the features above into this variable */
+#define HSMMC_HAS_PBIAS                (1 << 0)
+#define HSMMC_HAS_UPDATED_RESET        (1 << 1)
+#define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
+       unsigned features;
+
+       int switch_pin;                 /* gpio (card detect) */
+       int gpio_wp;                    /* gpio (write protect) */
+
+       int (*set_power)(struct device *dev, int power_on, int vdd);
+       void (*remux)(struct device *dev, int power_on);
+       /* Call back before enabling / disabling regulators */
+       void (*before_set_reg)(struct device *dev, int power_on, int vdd);
+       /* Call back after enabling / disabling regulators */
+       void (*after_set_reg)(struct device *dev, int power_on, int vdd);
+       /* if we have special card, init it using this callback */
+       void (*init_card)(struct mmc_card *card);
+
+       const char *name;
+       u32 ocr_mask;
+};
diff --git a/include/linux/platform_data/mmc-atmel-mci.h b/include/linux/platform_data/mmc-atmel-mci.h
new file mode 100644 (file)
index 0000000..399a2d5
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __MMC_ATMEL_MCI_H
+#define __MMC_ATMEL_MCI_H
+
+#include <linux/platform_data/dma-atmel.h>
+#include <linux/platform_data/dma-dw.h>
+
+/**
+ * struct mci_dma_data - DMA data for MCI interface
+ */
+struct mci_dma_data {
+#ifdef CONFIG_ARM
+       struct at_dma_slave     sdata;
+#else
+       struct dw_dma_slave     sdata;
+#endif
+};
+
+/* accessor macros */
+#define        slave_data_ptr(s)       (&(s)->sdata)
+#define find_slave_dev(s)      ((s)->sdata.dma_dev)
+
+#endif /* __MMC_ATMEL_MCI_H */
index 51e70cf25cbcb3476999372baeb605f0e96261dd..5c188f4e9bec04f474598ac0e237340f18114d11 100644 (file)
 
 #define OMAP_MMC_MAX_SLOTS     2
 
-/*
- * struct omap_mmc_dev_attr.flags possibilities
- *
- * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
- *    operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
- *    should be set if this is the case.  See for example Section 22.5.3
- *    "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
- *    Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
- *
- * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
- *    don't work correctly on some MMC controller instances on some
- *    OMAP3 SoCs; this flag should be set if this is the case.  See
- *    for example Advisory 2.1.1.128 "MMC: Multiple Block Read
- *    Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
- *    Revision F (October 2010) (SPRZ278F).
- */
-#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT          BIT(0)
-#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ      BIT(1)
-#define OMAP_HSMMC_SWAKEUP_MISSING             BIT(2)
-
 struct mmc_card;
 
-struct omap_mmc_dev_attr {
-       u8 flags;
-};
-
 struct omap_mmc_platform_data {
        /* back-link to device */
        struct device *dev;
@@ -106,9 +82,6 @@ struct omap_mmc_platform_data {
                unsigned vcc_aux_disable_is_sleep:1;
 
                /* we can put the features above into this variable */
-#define HSMMC_HAS_PBIAS                (1 << 0)
-#define HSMMC_HAS_UPDATED_RESET        (1 << 1)
-#define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
 #define MMC_OMAP7XX            (1 << 3)
 #define MMC_OMAP15XX           (1 << 4)
 #define MMC_OMAP16XX           (1 << 5)
index 27d3156d093ae4f05ac09da2ddf5b58c4292d8ec..9e20c2fb4ffd3852d056ca781300d9a23492af04 100644 (file)
@@ -55,9 +55,4 @@ struct sdhci_pxa_platdata {
        unsigned int    quirks2;
        unsigned int    pm_caps;
 };
-
-struct sdhci_pxa {
-       u8      clk_enable;
-       u8      power_mode;
-};
 #endif /* _PXA_SDHCI_H_ */
index c860c1b314c0473a7737cd6c7dacd65344fbc656..d09275f3cde3d852bfec79c25359e4d76f37eb01 100644 (file)
@@ -38,9 +38,6 @@ struct omap_uart_port_info {
        unsigned int            dma_rx_timeout;
        unsigned int            autosuspend_timeout;
        unsigned int            dma_rx_poll_rate;
-       int                     DTR_gpio;
-       int                     DTR_inverted;
-       int                     DTR_present;
 
        int (*get_context_loss_count)(struct device *);
        void (*enable_wakeup)(struct device *, bool);
index 73e938b7e9374c68ac00fd99c65247eac9241fd4..2e0e06daf8c0692c16561eb35928b1502647f1ff 100644 (file)
@@ -72,8 +72,10 @@ struct generic_pm_domain {
        bool max_off_time_changed;
        bool cached_power_down_ok;
        struct gpd_cpuidle_data *cpuidle_data;
-       void (*attach_dev)(struct device *dev);
-       void (*detach_dev)(struct device *dev);
+       int (*attach_dev)(struct generic_pm_domain *domain,
+                         struct device *dev);
+       void (*detach_dev)(struct generic_pm_domain *domain,
+                          struct device *dev);
 };
 
 static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
@@ -104,7 +106,7 @@ struct generic_pm_domain_data {
        struct notifier_block nb;
        struct mutex lock;
        unsigned int refcount;
-       bool need_restore;
+       int need_restore;
 };
 
 #ifdef CONFIG_PM_GENERIC_DOMAINS
index 9ab4bf7c464660821b976afad421d4b86d5811ac..636e8283450674587e0c9118717a8e2339a1d1b6 100644 (file)
@@ -15,6 +15,7 @@ enum {
        PM_QOS_CPU_DMA_LATENCY,
        PM_QOS_NETWORK_LATENCY,
        PM_QOS_NETWORK_THROUGHPUT,
+       PM_QOS_MEMORY_BANDWIDTH,
 
        /* insert new class ID */
        PM_QOS_NUM_CLASSES,
@@ -32,6 +33,7 @@ enum pm_qos_flags_status {
 #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE       (2000 * USEC_PER_SEC)
 #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE       (2000 * USEC_PER_SEC)
 #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE        0
+#define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE  0
 #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE    0
 #define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0
 #define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1)
@@ -69,7 +71,8 @@ struct dev_pm_qos_request {
 enum pm_qos_type {
        PM_QOS_UNITIALIZED,
        PM_QOS_MAX,             /* return the largest value */
-       PM_QOS_MIN              /* return the smallest value */
+       PM_QOS_MIN,             /* return the smallest value */
+       PM_QOS_SUM              /* return the sum */
 };
 
 /*
index fe25876c1a5d6035551cba79e1d0caf6daacda84..17d7d0d20ecaa872327de7fcfd071564ba9556a3 100644 (file)
@@ -5,7 +5,7 @@
  *  All rights reserved.
  *
  *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <bharrosh@panasas.com>
+ *  Boaz Harrosh <ooo@electrozaur.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
index 07e7945a1ff292048da586ac9709d17691a29fca..e97fc656a058c07d7c0c79a807cb3e04bec6dbf1 100644 (file)
@@ -253,9 +253,6 @@ struct charger_manager {
        struct device *dev;
        struct charger_desc *desc;
 
-       struct power_supply *fuel_gauge;
-       struct power_supply **charger_stat;
-
 #ifdef CONFIG_THERMAL
        struct thermal_zone_device *tzd_batt;
 #endif
index 3ed0496730229556921e3e77a5deeeecbb20bbac..096dbced02ac4b7cb9d18de6a8aa65e0592d78e9 100644 (file)
@@ -200,6 +200,12 @@ struct power_supply {
        void (*external_power_changed)(struct power_supply *psy);
        void (*set_charged)(struct power_supply *psy);
 
+       /*
+        * Set if thermal zone should not be created for this power supply.
+        * For example for virtual supplies forwarding calls to actual
+        * sensors or other supplies.
+        */
+       bool no_thermal;
        /* For APM emulation, think legacy userspace. */
        int use_for_apm;
 
index a4a819ffb2d116d1225608393481521ad3cacc88..ed4f5939a452cb424671f87dc9911fe318cb1fc3 100644 (file)
@@ -57,7 +57,7 @@ enum rcutorture_type {
        INVALID_RCU_FLAVOR
 };
 
-#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
+#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
 void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags,
                            unsigned long *gpnum, unsigned long *completed);
 void rcutorture_record_test_transition(void);
@@ -260,7 +260,7 @@ static inline int rcu_preempt_depth(void)
 void rcu_init(void);
 void rcu_sched_qs(void);
 void rcu_bh_qs(void);
-void rcu_check_callbacks(int cpu, int user);
+void rcu_check_callbacks(int user);
 struct notifier_block;
 void rcu_idle_enter(void);
 void rcu_idle_exit(void);
@@ -348,8 +348,8 @@ extern struct srcu_struct tasks_rcu_exit_srcu;
  */
 #define cond_resched_rcu_qs() \
 do { \
-       rcu_note_voluntary_context_switch(current); \
-       cond_resched(); \
+       if (!cond_resched()) \
+               rcu_note_voluntary_context_switch(current); \
 } while (0)
 
 #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP)
@@ -365,7 +365,7 @@ typedef void call_rcu_func_t(struct rcu_head *head,
                             void (*func)(struct rcu_head *head));
 void wait_rcu_gp(call_rcu_func_t crf);
 
-#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
+#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
 #include <linux/rcutree.h>
 #elif defined(CONFIG_TINY_RCU)
 #include <linux/rcutiny.h>
@@ -616,6 +616,21 @@ static inline void rcu_preempt_sleep_check(void)
  */
 #define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
 
+/**
+ * lockless_dereference() - safely load a pointer for later dereference
+ * @p: The pointer to load
+ *
+ * Similar to rcu_dereference(), but for situations where the pointed-to
+ * object's lifetime is managed by something other than RCU.  That
+ * "something other" might be reference counting or simple immortality.
+ */
+#define lockless_dereference(p) \
+({ \
+       typeof(p) _________p1 = ACCESS_ONCE(p); \
+       smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
+       (_________p1); \
+})
+
 /**
  * rcu_assign_pointer() - assign to RCU-protected pointer
  * @p: pointer to assign to
@@ -852,7 +867,7 @@ static inline void rcu_preempt_sleep_check(void)
  *
  * In non-preemptible RCU implementations (TREE_RCU and TINY_RCU),
  * it is illegal to block while in an RCU read-side critical section.
- * In preemptible RCU implementations (TREE_PREEMPT_RCU) in CONFIG_PREEMPT
+ * In preemptible RCU implementations (PREEMPT_RCU) in CONFIG_PREEMPT
  * kernel builds, RCU read-side critical sections may be preempted,
  * but explicit blocking is illegal.  Finally, in preemptible RCU
  * implementations in real-time (with -rt patchset) kernel builds, RCU
@@ -887,7 +902,9 @@ static inline void rcu_read_lock(void)
  * Unfortunately, this function acquires the scheduler's runqueue and
  * priority-inheritance spinlocks.  This means that deadlock could result
  * if the caller of rcu_read_unlock() already holds one of these locks or
- * any lock that is ever acquired while holding them.
+ * any lock that is ever acquired while holding them; or any lock which
+ * can be taken from interrupt context because rcu_boost()->rt_mutex_lock()
+ * does not disable irqs while taking ->wait_lock.
  *
  * That said, RCU readers are never priority boosted unless they were
  * preempted.  Therefore, one way to avoid deadlock is to make sure
@@ -1047,6 +1064,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  */
 #define RCU_INIT_POINTER(p, v) \
        do { \
+               rcu_dereference_sparse(p, __rcu); \
                p = RCU_INITIALIZER(v); \
        } while (0)
 
@@ -1103,7 +1121,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
        __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
 
 #if defined(CONFIG_TINY_RCU) || defined(CONFIG_RCU_NOCB_CPU_ALL)
-static inline int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
+static inline int rcu_needs_cpu(unsigned long *delta_jiffies)
 {
        *delta_jiffies = ULONG_MAX;
        return 0;
index 38cc5b1e252d2f2ddcc9b2d9e0e1617321ced6d4..0e5366200154e87e394b61c52a60fad72f2050ff 100644 (file)
@@ -78,7 +78,7 @@ static inline void kfree_call_rcu(struct rcu_head *head,
        call_rcu(head, func);
 }
 
-static inline void rcu_note_context_switch(int cpu)
+static inline void rcu_note_context_switch(void)
 {
        rcu_sched_qs();
 }
index 3e2f5d432743cc1fb9a86e8af651a5340ebd5d4e..52953790dcca2089527ec9f48725fd7d31fb0da0 100644 (file)
@@ -30,9 +30,9 @@
 #ifndef __LINUX_RCUTREE_H
 #define __LINUX_RCUTREE_H
 
-void rcu_note_context_switch(int cpu);
+void rcu_note_context_switch(void);
 #ifndef CONFIG_RCU_NOCB_CPU_ALL
-int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies);
+int rcu_needs_cpu(unsigned long *delta_jiffies);
 #endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 void rcu_cpu_stall_reset(void);
 
@@ -43,7 +43,7 @@ void rcu_cpu_stall_reset(void);
  */
 static inline void rcu_virt_note_context_switch(int cpu)
 {
-       rcu_note_context_switch(cpu);
+       rcu_note_context_switch();
 }
 
 void synchronize_rcu_bh(void);
index c5ed83f49c4eada4e30dabde2968fa2c79e396ec..4419b99d8d6ec19010815c7ed759e513abccb95d 100644 (file)
@@ -27,6 +27,7 @@ struct spmi_device;
 struct regmap;
 struct regmap_range_cfg;
 struct regmap_field;
+struct snd_ac97;
 
 /* An enum of all the supported cache types */
 enum regcache_type {
@@ -340,6 +341,8 @@ struct regmap *regmap_init_spmi_ext(struct spmi_device *dev,
 struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
                                    void __iomem *regs,
                                    const struct regmap_config *config);
+struct regmap *regmap_init_ac97(struct snd_ac97 *ac97,
+                               const struct regmap_config *config);
 
 struct regmap *devm_regmap_init(struct device *dev,
                                const struct regmap_bus *bus,
@@ -356,6 +359,10 @@ struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *dev,
 struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id,
                                         void __iomem *regs,
                                         const struct regmap_config *config);
+struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97,
+                                    const struct regmap_config *config);
+
+bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg);
 
 /**
  * regmap_init_mmio(): Initialise register map
index d347c805f923f8539b6430fa30119527edb7f244..d17e1ff7ad019987d4c4f944dd3a6b20aa571807 100644 (file)
@@ -35,6 +35,8 @@
 #ifndef __LINUX_REGULATOR_CONSUMER_H_
 #define __LINUX_REGULATOR_CONSUMER_H_
 
+#include <linux/err.h>
+
 struct device;
 struct notifier_block;
 struct regmap;
@@ -99,6 +101,8 @@ struct regmap;
  *                      Data passed is "struct pre_voltage_change_data"
  * ABORT_VOLTAGE_CHANGE Regulator voltage change failed for some reason.
  *                      Data passed is old voltage cast to (void *).
+ * PRE_DISABLE    Regulator is about to be disabled
+ * ABORT_DISABLE  Regulator disable failed for some reason
  *
  * NOTE: These events can be OR'ed together when passed into handler.
  */
@@ -113,6 +117,8 @@ struct regmap;
 #define REGULATOR_EVENT_DISABLE                0x80
 #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE     0x100
 #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE   0x200
+#define REGULATOR_EVENT_PRE_DISABLE            0x400
+#define REGULATOR_EVENT_ABORT_DISABLE          0x800
 
 /**
  * struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event
@@ -282,7 +288,7 @@ devm_regulator_get(struct device *dev, const char *id)
 static inline struct regulator *__must_check
 regulator_get_exclusive(struct device *dev, const char *id)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 static inline struct regulator *__must_check
index fc0ee0ce8325e1162b95034d00721d7f6dcf3764..5f1e9ca47417febff0811df407abe43d99563786 100644 (file)
@@ -243,6 +243,8 @@ enum regulator_type {
  *
  * @enable_time: Time taken for initial enable of regulator (in uS).
  * @off_on_delay: guard time (in uS), before re-enabling a regulator
+ *
+ * @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode
  */
 struct regulator_desc {
        const char *name;
@@ -285,6 +287,8 @@ struct regulator_desc {
        unsigned int enable_time;
 
        unsigned int off_on_delay;
+
+       unsigned int (*of_map_mode)(unsigned int mode);
 };
 
 /**
@@ -301,6 +305,9 @@ struct regulator_desc {
  *           NULL).
  * @regmap: regmap to use for core regmap helpers if dev_get_regulator() is
  *          insufficient.
+ * @ena_gpio_initialized: GPIO controlling regulator enable was properly
+ *                        initialized, meaning that >= 0 is a valid gpio
+ *                        identifier and < 0 is a non existent gpio.
  * @ena_gpio: GPIO controlling regulator enable.
  * @ena_gpio_invert: Sense for GPIO enable control.
  * @ena_gpio_flags: Flags to use when calling gpio_request_one()
@@ -312,6 +319,7 @@ struct regulator_config {
        struct device_node *of_node;
        struct regmap *regmap;
 
+       bool ena_gpio_initialized;
        int ena_gpio;
        unsigned int ena_gpio_invert:1;
        unsigned int ena_gpio_flags;
index f9217965aaa38a8f585eadc712eac62257e91fae..763953f7e3b8a4f65c7cb8fdd4fdf4ecdc4722e0 100644 (file)
@@ -6,24 +6,29 @@
 #ifndef __LINUX_OF_REG_H
 #define __LINUX_OF_REG_H
 
+struct regulator_desc;
+
 struct of_regulator_match {
        const char *name;
        void *driver_data;
        struct regulator_init_data *init_data;
        struct device_node *of_node;
+       const struct regulator_desc *desc;
 };
 
 #if defined(CONFIG_OF)
 extern struct regulator_init_data
        *of_get_regulator_init_data(struct device *dev,
-                                   struct device_node *node);
+                                   struct device_node *node,
+                                   const struct regulator_desc *desc);
 extern int of_regulator_match(struct device *dev, struct device_node *node,
                              struct of_regulator_match *matches,
                              unsigned int num_matches);
 #else
 static inline struct regulator_init_data
        *of_get_regulator_init_data(struct device *dev,
-                                   struct device_node *node)
+                                   struct device_node *node,
+                                   const struct regulator_desc *desc)
 {
        return NULL;
 }
index 41a4695fde08ca9414f6c541aaa16077b215d3d2..ce6b962ffed43d892aa1bea3749e923f0032ea1f 100644 (file)
@@ -12,11 +12,13 @@ struct reset_controller_dev;
  *         things to reset the device
  * @assert: manually assert the reset line, if supported
  * @deassert: manually deassert the reset line, if supported
+ * @status: return the status of the reset line, if supported
  */
 struct reset_control_ops {
        int (*reset)(struct reset_controller_dev *rcdev, unsigned long id);
        int (*assert)(struct reset_controller_dev *rcdev, unsigned long id);
        int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id);
+       int (*status)(struct reset_controller_dev *rcdev, unsigned long id);
 };
 
 struct module;
index 349f150ae12cb4f896eea2aafc73cfcb3fcfd26c..da5602bd77d75996f78114b7369b409ea52f007d 100644 (file)
@@ -10,6 +10,7 @@ struct reset_control;
 int reset_control_reset(struct reset_control *rstc);
 int reset_control_assert(struct reset_control *rstc);
 int reset_control_deassert(struct reset_control *rstc);
+int reset_control_status(struct reset_control *rstc);
 
 struct reset_control *reset_control_get(struct device *dev, const char *id);
 void reset_control_put(struct reset_control *rstc);
@@ -57,6 +58,12 @@ static inline int reset_control_deassert(struct reset_control *rstc)
        return 0;
 }
 
+static inline int reset_control_status(struct reset_control *rstc)
+{
+       WARN_ON(1);
+       return 0;
+}
+
 static inline void reset_control_put(struct reset_control *rstc)
 {
        WARN_ON(1);
index 49a4d6f59108f957d4534190c161344981c48e46..e2c13cd863bdc5b41a65731a4e55018aee3762f4 100644 (file)
@@ -97,7 +97,7 @@ __ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *k
        __ring_buffer_alloc((size), (flags), &__key);   \
 })
 
-int ring_buffer_wait(struct ring_buffer *buffer, int cpu);
+int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full);
 int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
                          struct file *filp, poll_table *poll_table);
 
index c2c28975293cf01714dde23876b801c696897161..6d6be09a2fe50fff38f54d582aa547eccf24296c 100644 (file)
 extern int rtc_month_days(unsigned int month, unsigned int year);
 extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year);
 extern int rtc_valid_tm(struct rtc_time *tm);
-extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
-extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
+extern time64_t rtc_tm_to_time64(struct rtc_time *tm);
+extern void rtc_time64_to_tm(time64_t time, struct rtc_time *tm);
 ktime_t rtc_tm_to_ktime(struct rtc_time tm);
 struct rtc_time rtc_ktime_to_tm(ktime_t kt);
 
+/**
+ * Deprecated. Use rtc_time64_to_tm().
+ */
+static inline void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
+{
+       rtc_time64_to_tm(time, tm);
+}
+
+/**
+ * Deprecated. Use rtc_tm_to_time64().
+ */
+static inline int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+{
+       *time = rtc_tm_to_time64(tm);
+
+       return 0;
+}
 
 #include <linux/device.h>
 #include <linux/seq_file.h>
index 5e344bbe63ec29c16845623603c58a192159b7f9..55f5ee7cc3d3aa1f0e608adce1126c331c9b0656 100644 (file)
@@ -243,6 +243,43 @@ extern char ___assert_task_state[1 - 2*!!(
                                ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
                                 (task->flags & PF_FROZEN) == 0)
 
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+
+#define __set_task_state(tsk, state_value)                     \
+       do {                                                    \
+               (tsk)->task_state_change = _THIS_IP_;           \
+               (tsk)->state = (state_value);                   \
+       } while (0)
+#define set_task_state(tsk, state_value)                       \
+       do {                                                    \
+               (tsk)->task_state_change = _THIS_IP_;           \
+               set_mb((tsk)->state, (state_value));            \
+       } while (0)
+
+/*
+ * set_current_state() includes a barrier so that the write of current->state
+ * is correctly serialised wrt the caller's subsequent test of whether to
+ * actually sleep:
+ *
+ *     set_current_state(TASK_UNINTERRUPTIBLE);
+ *     if (do_i_need_to_sleep())
+ *             schedule();
+ *
+ * If the caller does not need such serialisation then use __set_current_state()
+ */
+#define __set_current_state(state_value)                       \
+       do {                                                    \
+               current->task_state_change = _THIS_IP_;         \
+               current->state = (state_value);                 \
+       } while (0)
+#define set_current_state(state_value)                         \
+       do {                                                    \
+               current->task_state_change = _THIS_IP_;         \
+               set_mb(current->state, (state_value));          \
+       } while (0)
+
+#else
+
 #define __set_task_state(tsk, state_value)             \
        do { (tsk)->state = (state_value); } while (0)
 #define set_task_state(tsk, state_value)               \
@@ -259,11 +296,13 @@ extern char ___assert_task_state[1 - 2*!!(
  *
  * If the caller does not need such serialisation then use __set_current_state()
  */
-#define __set_current_state(state_value)                       \
+#define __set_current_state(state_value)               \
        do { current->state = (state_value); } while (0)
-#define set_current_state(state_value)         \
+#define set_current_state(state_value)                 \
        set_mb(current->state, (state_value))
 
+#endif
+
 /* Task command name length */
 #define TASK_COMM_LEN 16
 
@@ -1278,9 +1317,9 @@ struct task_struct {
        union rcu_special rcu_read_unlock_special;
        struct list_head rcu_node_entry;
 #endif /* #ifdef CONFIG_PREEMPT_RCU */
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
        struct rcu_node *rcu_blocked_node;
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
+#endif /* #ifdef CONFIG_PREEMPT_RCU */
 #ifdef CONFIG_TASKS_RCU
        unsigned long rcu_tasks_nvcsw;
        bool rcu_tasks_holdout;
@@ -1558,27 +1597,22 @@ struct task_struct {
        struct numa_group *numa_group;
 
        /*
-        * Exponential decaying average of faults on a per-node basis.
-        * Scheduling placement decisions are made based on the these counts.
-        * The values remain static for the duration of a PTE scan
+        * numa_faults is an array split into four regions:
+        * faults_memory, faults_cpu, faults_memory_buffer, faults_cpu_buffer
+        * in this precise order.
+        *
+        * faults_memory: Exponential decaying average of faults on a per-node
+        * basis. Scheduling placement decisions are made based on these
+        * counts. The values remain static for the duration of a PTE scan.
+        * faults_cpu: Track the nodes the process was running on when a NUMA
+        * hinting fault was incurred.
+        * faults_memory_buffer and faults_cpu_buffer: Record faults per node
+        * during the current scan window. When the scan completes, the counts
+        * in faults_memory and faults_cpu decay and these values are copied.
         */
-       unsigned long *numa_faults_memory;
+       unsigned long *numa_faults;
        unsigned long total_numa_faults;
 
-       /*
-        * numa_faults_buffer records faults per node during the current
-        * scan window. When the scan completes, the counts in
-        * numa_faults_memory decay and these values are copied.
-        */
-       unsigned long *numa_faults_buffer_memory;
-
-       /*
-        * Track the nodes the process was running on when a NUMA hinting
-        * fault was incurred.
-        */
-       unsigned long *numa_faults_cpu;
-       unsigned long *numa_faults_buffer_cpu;
-
        /*
         * numa_faults_locality tracks if faults recorded during the last
         * scan window were remote/local. The task scan period is adapted
@@ -1661,6 +1695,9 @@ struct task_struct {
        unsigned int    sequential_io;
        unsigned int    sequential_io_avg;
 #endif
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+       unsigned long   task_state_change;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
@@ -2052,6 +2089,10 @@ static inline void tsk_restore_flags(struct task_struct *task,
        task->flags |= orig_flags & flags;
 }
 
+extern int cpuset_cpumask_can_shrink(const struct cpumask *cur,
+                                    const struct cpumask *trial);
+extern int task_can_attach(struct task_struct *p,
+                          const struct cpumask *cs_cpus_allowed);
 #ifdef CONFIG_SMP
 extern void do_set_cpus_allowed(struct task_struct *p,
                               const struct cpumask *new_mask);
@@ -2760,7 +2801,7 @@ static inline int signal_pending_state(long state, struct task_struct *p)
 extern int _cond_resched(void);
 
 #define cond_resched() ({                      \
-       __might_sleep(__FILE__, __LINE__, 0);   \
+       ___might_sleep(__FILE__, __LINE__, 0);  \
        _cond_resched();                        \
 })
 
@@ -2773,14 +2814,14 @@ extern int __cond_resched_lock(spinlock_t *lock);
 #endif
 
 #define cond_resched_lock(lock) ({                             \
-       __might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET); \
+       ___might_sleep(__FILE__, __LINE__, PREEMPT_LOCK_OFFSET);\
        __cond_resched_lock(lock);                              \
 })
 
 extern int __cond_resched_softirq(void);
 
 #define cond_resched_softirq() ({                                      \
-       __might_sleep(__FILE__, __LINE__, SOFTIRQ_DISABLE_OFFSET);      \
+       ___might_sleep(__FILE__, __LINE__, SOFTIRQ_DISABLE_OFFSET);     \
        __cond_resched_softirq();                                       \
 })
 
index a59d9343c25bdc9575eefa1ac361732599db9ddf..6c8b6f604e7609f2d320a7aa572a8ec6a870f4b8 100644 (file)
@@ -557,7 +557,9 @@ struct sk_buff {
        /* fields enclosed in headers_start/headers_end are copied
         * using a single memcpy() in __copy_skb_header()
         */
+       /* private: */
        __u32                   headers_start[0];
+       /* public: */
 
 /* if you move pkt_type around you also must adapt those constants */
 #ifdef __BIG_ENDIAN_BITFIELD
@@ -642,7 +644,9 @@ struct sk_buff {
        __u16                   network_header;
        __u16                   mac_header;
 
+       /* private: */
        __u32                   headers_end[0];
+       /* public: */
 
        /* These elements must be at the end, see alloc_skb() for details.  */
        sk_buff_data_t          tail;
@@ -795,15 +799,19 @@ struct sk_buff_fclones {
  *     @skb: buffer
  *
  * Returns true is skb is a fast clone, and its clone is not freed.
+ * Some drivers call skb_orphan() in their ndo_start_xmit(),
+ * so we also check that this didnt happen.
  */
-static inline bool skb_fclone_busy(const struct sk_buff *skb)
+static inline bool skb_fclone_busy(const struct sock *sk,
+                                  const struct sk_buff *skb)
 {
        const struct sk_buff_fclones *fclones;
 
        fclones = container_of(skb, struct sk_buff_fclones, skb1);
 
        return skb->fclone == SKB_FCLONE_ORIG &&
-              fclones->skb2.fclone == SKB_FCLONE_CLONE;
+              fclones->skb2.fclone == SKB_FCLONE_CLONE &&
+              fclones->skb2.sk == sk;
 }
 
 static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
index ec538fc287a66000f7ce357f4bfe8012223acc26..bb9b83640070f4a366a8ca67f56495f07aaa7830 100644 (file)
@@ -256,7 +256,7 @@ struct ucred {
 #define MSG_EOF         MSG_FIN
 
 #define MSG_FASTOPEN   0x20000000      /* Send data in TCP SYN */
-#define MSG_CMSG_CLOEXEC 0x40000000    /* Set close_on_exit for file
+#define MSG_CMSG_CLOEXEC 0x40000000    /* Set close_on_exec for file
                                           descriptor received through
                                           SCM_RIGHTS */
 #if defined(CONFIG_COMPAT)
index e6edfe51575a6f5a452e937376add0afdb7c5d48..2e22a2e58f3af56018c0e68cda2603211ecc3aca 100644 (file)
@@ -132,7 +132,7 @@ int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4);
 #endif
 
 extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
-                       const void *from, size_t available);
+                                      const void *from, size_t available);
 
 /**
  * strstarts - does @str start with @prefix?
@@ -144,7 +144,8 @@ static inline bool strstarts(const char *str, const char *prefix)
        return strncmp(str, prefix, strlen(prefix)) == 0;
 }
 
-extern size_t memweight(const void *ptr, size_t bytes);
+size_t memweight(const void *ptr, size_t bytes);
+void memzero_explicit(void *s, size_t count);
 
 /**
  * kbasename - return the last part of a pathname.
index 0305cde21a74d0bd37cf8ce707d8033632182cd6..ef90838b36a072eeed278789c9bbe625fabe32f1 100644 (file)
 #define KELVIN_TO_CELSIUS(t)   (long)(((long)t-2732 >= 0) ?    \
                                ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
 #define CELSIUS_TO_KELVIN(t)   ((t)*10+2732)
+#define DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, off) (((t) - (off)) * 100)
+#define DECI_KELVIN_TO_MILLICELSIUS(t) DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(t, 2732)
+#define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off))
+#define MILLICELSIUS_TO_DECI_KELVIN(t) MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, 2732)
 
 /* Adding event notification support elements */
 #define THERMAL_GENL_FAMILY_NAME                "thermal_event"
index 8c42cf8d24440a595a670f0ae9db8edb47fcec1c..203c2ad40d7184726b585b7c644b0a7f11ad6894 100644 (file)
@@ -39,9 +39,20 @@ static inline int timeval_compare(const struct timeval *lhs, const struct timeva
        return lhs->tv_usec - rhs->tv_usec;
 }
 
-extern unsigned long mktime(const unsigned int year, const unsigned int mon,
-                           const unsigned int day, const unsigned int hour,
-                           const unsigned int min, const unsigned int sec);
+extern time64_t mktime64(const unsigned int year, const unsigned int mon,
+                       const unsigned int day, const unsigned int hour,
+                       const unsigned int min, const unsigned int sec);
+
+/**
+ * Deprecated. Use mktime64().
+ */
+static inline unsigned long mktime(const unsigned int year,
+                       const unsigned int mon, const unsigned int day,
+                       const unsigned int hour, const unsigned int min,
+                       const unsigned int sec)
+{
+       return mktime64(year, mon, day, hour, min, sec);
+}
 
 extern void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec);
 
index 1caa6b04fdc5ce09a0c27b4951ba03b200182940..961fea373f83e8ceb1ef0ec178b4fbe52f5de90f 100644 (file)
@@ -10,7 +10,7 @@ extern int timekeeping_suspended;
  * Get and set timeofday
  */
 extern void do_gettimeofday(struct timeval *tv);
-extern int do_settimeofday(const struct timespec *tv);
+extern int do_settimeofday64(const struct timespec64 *ts);
 extern int do_sys_settimeofday(const struct timespec *tv,
                               const struct timezone *tz);
 
@@ -25,14 +25,22 @@ struct timespec __current_kernel_time(void);
 /*
  * timespec based interfaces
  */
-struct timespec get_monotonic_coarse(void);
-extern void getrawmonotonic(struct timespec *ts);
+struct timespec64 get_monotonic_coarse64(void);
+extern void getrawmonotonic64(struct timespec64 *ts);
 extern void ktime_get_ts64(struct timespec64 *ts);
 
 extern int __getnstimeofday64(struct timespec64 *tv);
 extern void getnstimeofday64(struct timespec64 *tv);
 
 #if BITS_PER_LONG == 64
+/**
+ * Deprecated. Use do_settimeofday64().
+ */
+static inline int do_settimeofday(const struct timespec *ts)
+{
+       return do_settimeofday64(ts);
+}
+
 static inline int __getnstimeofday(struct timespec *ts)
 {
        return __getnstimeofday64(ts);
@@ -53,7 +61,27 @@ static inline void ktime_get_real_ts(struct timespec *ts)
        getnstimeofday64(ts);
 }
 
+static inline void getrawmonotonic(struct timespec *ts)
+{
+       getrawmonotonic64(ts);
+}
+
+static inline struct timespec get_monotonic_coarse(void)
+{
+       return get_monotonic_coarse64();
+}
 #else
+/**
+ * Deprecated. Use do_settimeofday64().
+ */
+static inline int do_settimeofday(const struct timespec *ts)
+{
+       struct timespec64 ts64;
+
+       ts64 = timespec_to_timespec64(*ts);
+       return do_settimeofday64(&ts64);
+}
+
 static inline int __getnstimeofday(struct timespec *ts)
 {
        struct timespec64 ts64;
@@ -86,6 +114,19 @@ static inline void ktime_get_real_ts(struct timespec *ts)
        getnstimeofday64(&ts64);
        *ts = timespec64_to_timespec(ts64);
 }
+
+static inline void getrawmonotonic(struct timespec *ts)
+{
+       struct timespec64 ts64;
+
+       getrawmonotonic64(&ts64);
+       *ts = timespec64_to_timespec(ts64);
+}
+
+static inline struct timespec get_monotonic_coarse(void)
+{
+       return timespec64_to_timespec(get_monotonic_coarse64());
+}
 #endif
 
 extern void getboottime(struct timespec *ts);
@@ -182,7 +223,7 @@ static inline void timekeeping_clocktai(struct timespec *ts)
 /*
  * RTC specific
  */
-extern void timekeeping_inject_sleeptime(struct timespec *delta);
+extern void timekeeping_inject_sleeptime64(struct timespec64 *delta);
 
 /*
  * PPS accessor
index 1ad4724458de0127424795eede13c63ef344476f..baa81718d985afd9e90d70e90f18e66f96da5f8d 100644 (file)
@@ -63,7 +63,17 @@ struct uio_port {
 
 #define MAX_UIO_PORT_REGIONS   5
 
-struct uio_device;
+struct uio_device {
+        struct module           *owner;
+        struct device           *dev;
+        int                     minor;
+        atomic_t                event;
+        struct fasync_struct    *async_queue;
+        wait_queue_head_t       wait;
+        struct uio_info         *info;
+        struct kobject          *map_dir;
+        struct kobject          *portio_dir;
+};
 
 /**
  * struct uio_info - UIO device capabilities
index 4f844c6b03ee2c8c04bd4c745fd292e4229b7989..60beb5dc7977b78c0badc92b17932a112919bc80 100644 (file)
@@ -98,11 +98,11 @@ struct uprobes_state {
        struct xol_area         *xol_area;
 };
 
-extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
-extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
-extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
-extern bool __weak is_trap_insn(uprobe_opcode_t *insn);
-extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
+extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
+extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
+extern bool is_swbp_insn(uprobe_opcode_t *insn);
+extern bool is_trap_insn(uprobe_opcode_t *insn);
+extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
 extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
 extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
 extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
@@ -128,8 +128,8 @@ extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
 extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
 extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
-extern bool __weak arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs);
-extern void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
+extern bool arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs);
+extern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
                                         void *src, unsigned long len);
 #else /* !CONFIG_UPROBES */
 struct uprobes_state {
index 26088feb660813448ac93391bee76c1e73b57d70..d9a4905e01d0c98b88e89c7db5c85bbf7d5be8a1 100644 (file)
@@ -78,6 +78,7 @@ struct usbnet {
 #              define EVENT_NO_RUNTIME_PM      9
 #              define EVENT_RX_KILL    10
 #              define EVENT_LINK_CHANGE        11
+#              define EVENT_SET_RX_MODE        12
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -159,6 +160,9 @@ struct driver_info {
        /* called by minidriver when receiving indication */
        void    (*indication)(struct usbnet *dev, void *ind, int indlen);
 
+       /* rx mode change (device changes address list filtering) */
+       void    (*set_rx_mode)(struct usbnet *dev);
+
        /* for new devices, use the descriptor-reading code instead */
        int             in;             /* rx endpoint */
        int             out;            /* tx endpoint */
index a4c9547aae64bb3a811a9d25a8f62c1963bbea7c..f8e76e08ebe47e78671369114d1cac0c5a079951 100644 (file)
@@ -15,8 +15,6 @@
 #define _LINUX_VEXPRESS_H
 
 #include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/reboot.h>
 #include <linux/regmap.h>
 
 #define VEXPRESS_SITE_MB               0
 #define VEXPRESS_SITE_DB2              2
 #define VEXPRESS_SITE_MASTER           0xf
 
-#define VEXPRESS_RES_FUNC(_site, _func)        \
-{                                      \
-       .start = (_site),               \
-       .end = (_func),                 \
-       .flags = IORESOURCE_BUS,        \
-}
-
 /* Config infrastructure */
 
 void vexpress_config_set_master(u32 site);
@@ -58,16 +49,6 @@ struct regmap *devm_regmap_init_vexpress_config(struct device *dev);
 
 /* Platform control */
 
-unsigned int vexpress_get_mci_cardin(struct device *dev);
-u32 vexpress_get_procid(int site);
-void *vexpress_get_24mhz_clock_base(void);
 void vexpress_flags_set(u32 data);
 
-void vexpress_sysreg_early_init(void __iomem *base);
-int vexpress_syscfg_device_register(struct platform_device *pdev);
-
-/* Clocks */
-
-void vexpress_clk_init(void __iomem *sp810_base);
-
 #endif
index e4a8eb9312eabb508c045b8e0274ae7dd3809a38..2232ed16635ae0929c97f62e1c8c1b09109f0649 100644 (file)
@@ -13,9 +13,12 @@ typedef struct __wait_queue wait_queue_t;
 typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
 int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key);
 
+/* __wait_queue::flags */
+#define WQ_FLAG_EXCLUSIVE      0x01
+#define WQ_FLAG_WOKEN          0x02
+
 struct __wait_queue {
        unsigned int            flags;
-#define WQ_FLAG_EXCLUSIVE      0x01
        void                    *private;
        wait_queue_func_t       func;
        struct list_head        task_list;
@@ -258,11 +261,37 @@ __out:    __ret;                                                          \
  */
 #define wait_event(wq, condition)                                      \
 do {                                                                   \
+       might_sleep();                                                  \
        if (condition)                                                  \
                break;                                                  \
        __wait_event(wq, condition);                                    \
 } while (0)
 
+#define __wait_event_freezable(wq, condition)                          \
+       ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,          \
+                           schedule(); try_to_freeze())
+
+/**
+ * wait_event - sleep (or freeze) until a condition gets true
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE -- so as not to contribute
+ * to system load) until the @condition evaluates to true. The
+ * @condition is checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ */
+#define wait_event_freezable(wq, condition)                            \
+({                                                                     \
+       int __ret = 0;                                                  \
+       might_sleep();                                                  \
+       if (!(condition))                                               \
+               __ret = __wait_event_freezable(wq, condition);          \
+       __ret;                                                          \
+})
+
 #define __wait_event_timeout(wq, condition, timeout)                   \
        ___wait_event(wq, ___wait_cond_timeout(condition),              \
                      TASK_UNINTERRUPTIBLE, 0, timeout,                 \
@@ -290,11 +319,30 @@ do {                                                                      \
 #define wait_event_timeout(wq, condition, timeout)                     \
 ({                                                                     \
        long __ret = timeout;                                           \
+       might_sleep();                                                  \
        if (!___wait_cond_timeout(condition))                           \
                __ret = __wait_event_timeout(wq, condition, timeout);   \
        __ret;                                                          \
 })
 
+#define __wait_event_freezable_timeout(wq, condition, timeout)         \
+       ___wait_event(wq, ___wait_cond_timeout(condition),              \
+                     TASK_INTERRUPTIBLE, 0, timeout,                   \
+                     __ret = schedule_timeout(__ret); try_to_freeze())
+
+/*
+ * like wait_event_timeout() -- except it uses TASK_INTERRUPTIBLE to avoid
+ * increasing load and is freezable.
+ */
+#define wait_event_freezable_timeout(wq, condition, timeout)           \
+({                                                                     \
+       long __ret = timeout;                                           \
+       might_sleep();                                                  \
+       if (!___wait_cond_timeout(condition))                           \
+               __ret = __wait_event_freezable_timeout(wq, condition, timeout); \
+       __ret;                                                          \
+})
+
 #define __wait_event_cmd(wq, condition, cmd1, cmd2)                    \
        (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0,  \
                            cmd1; schedule(); cmd2)
@@ -315,6 +363,7 @@ do {                                                                        \
  */
 #define wait_event_cmd(wq, condition, cmd1, cmd2)                      \
 do {                                                                   \
+       might_sleep();                                                  \
        if (condition)                                                  \
                break;                                                  \
        __wait_event_cmd(wq, condition, cmd1, cmd2);                    \
@@ -342,6 +391,7 @@ do {                                                                        \
 #define wait_event_interruptible(wq, condition)                                \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_interruptible(wq, condition);      \
        __ret;                                                          \
@@ -375,6 +425,7 @@ do {                                                                        \
 #define wait_event_interruptible_timeout(wq, condition, timeout)       \
 ({                                                                     \
        long __ret = timeout;                                           \
+       might_sleep();                                                  \
        if (!___wait_cond_timeout(condition))                           \
                __ret = __wait_event_interruptible_timeout(wq,          \
                                                condition, timeout);    \
@@ -425,6 +476,7 @@ do {                                                                        \
 #define wait_event_hrtimeout(wq, condition, timeout)                   \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_hrtimeout(wq, condition, timeout,  \
                                               TASK_UNINTERRUPTIBLE);   \
@@ -450,6 +502,7 @@ do {                                                                        \
 #define wait_event_interruptible_hrtimeout(wq, condition, timeout)     \
 ({                                                                     \
        long __ret = 0;                                                 \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_hrtimeout(wq, condition, timeout,  \
                                               TASK_INTERRUPTIBLE);     \
@@ -463,12 +516,27 @@ do {                                                                      \
 #define wait_event_interruptible_exclusive(wq, condition)              \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_interruptible_exclusive(wq, condition);\
        __ret;                                                          \
 })
 
 
+#define __wait_event_freezable_exclusive(wq, condition)                        \
+       ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 1, 0,          \
+                       schedule(); try_to_freeze())
+
+#define wait_event_freezable_exclusive(wq, condition)                  \
+({                                                                     \
+       int __ret = 0;                                                  \
+       might_sleep();                                                  \
+       if (!(condition))                                               \
+               __ret = __wait_event_freezable_exclusive(wq, condition);\
+       __ret;                                                          \
+})
+
+
 #define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \
 ({                                                                     \
        int __ret = 0;                                                  \
@@ -637,6 +705,7 @@ do {                                                                        \
 #define wait_event_killable(wq, condition)                             \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_killable(wq, condition);           \
        __ret;                                                          \
@@ -830,6 +899,8 @@ void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int sta
 long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state);
 void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
 void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, unsigned int mode, void *key);
+long wait_woken(wait_queue_t *wait, unsigned mode, long timeout);
+int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 
@@ -886,6 +957,7 @@ extern int bit_wait_io_timeout(struct wait_bit_key *);
 static inline int
 wait_on_bit(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
@@ -910,6 +982,7 @@ wait_on_bit(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_io(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
@@ -936,6 +1009,7 @@ wait_on_bit_io(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_action(void *word, int bit, wait_bit_action_f *action, unsigned mode)
 {
+       might_sleep();
        if (!test_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit, action, mode);
@@ -963,6 +1037,7 @@ wait_on_bit_action(void *word, int bit, wait_bit_action_f *action, unsigned mode
 static inline int
 wait_on_bit_lock(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_and_set_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit_lock(word, bit, bit_wait, mode);
@@ -986,6 +1061,7 @@ wait_on_bit_lock(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_lock_io(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_and_set_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit_lock(word, bit, bit_wait_io, mode);
@@ -1011,6 +1087,7 @@ wait_on_bit_lock_io(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_lock_action(void *word, int bit, wait_bit_action_f *action, unsigned mode)
 {
+       might_sleep();
        if (!test_and_set_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit_lock(word, bit, action, mode);
@@ -1029,6 +1106,7 @@ wait_on_bit_lock_action(void *word, int bit, wait_bit_action_f *action, unsigned
 static inline
 int wait_on_atomic_t(atomic_t *val, int (*action)(atomic_t *), unsigned mode)
 {
+       might_sleep();
        if (atomic_read(val) == 0)
                return 0;
        return out_of_line_wait_on_atomic_t(val, action, mode);
index 2a3038ee17a33a3f6b4b4bee7b25dc6f0f633b04..395b70e0eccf76e0cd31dc1e25afb5d3032fab50 100644 (file)
@@ -97,13 +97,8 @@ struct watchdog_device {
 #define WDOG_UNREGISTERED      4       /* Has the device been unregistered */
 };
 
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-#define WATCHDOG_NOWAYOUT              1
-#define WATCHDOG_NOWAYOUT_INIT_STATUS  (1 << WDOG_NO_WAY_OUT)
-#else
-#define WATCHDOG_NOWAYOUT              0
-#define WATCHDOG_NOWAYOUT_INIT_STATUS  0
-#endif
+#define WATCHDOG_NOWAYOUT              IS_BUILTIN(CONFIG_WATCHDOG_NOWAYOUT)
+#define WATCHDOG_NOWAYOUT_INIT_STATUS  (WATCHDOG_NOWAYOUT << WDOG_NO_WAY_OUT)
 
 /* Use the following function to check whether or not the watchdog is active */
 static inline bool watchdog_active(struct watchdog_device *wdd)
index d9fa68f26c41c34c33db5f743a4142faf7886792..2a25dec3021166d5aba52ad155e8ca01e0b1570e 100644 (file)
@@ -34,7 +34,6 @@
  * @list: used to maintain a list of currently available transports
  * @name: the human-readable name of the transport
  * @maxsize: transport provided maximum packet size
- * @pref: Preferences of this transport
  * @def: set if this transport should be considered the default
  * @create: member function to create a new connection on this transport
  * @close: member function to discard a connection on this transport
index fe7994c48b75685174134e7817bbb20ef375f890..b2828a06a5a63355f1aa2be27e74a472cc99fc62 100644 (file)
@@ -37,6 +37,8 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int inet_ctl_sock_create(struct sock **sk, unsigned short family,
                         unsigned short type, unsigned char protocol,
                         struct net *net);
+int inet_recv_error(struct sock *sk, struct msghdr *msg, int len,
+                   int *addr_len);
 
 static inline void inet_ctl_sock_destroy(struct sock *sk)
 {
index 97f472012438b10a0bcbff9eef6c553d7357ad35..4292929392b0127479c49c5da3bb33f053f4428c 100644 (file)
@@ -671,6 +671,8 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
        return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
 }
 
+void ipv6_proxy_select_ident(struct sk_buff *skb);
+
 int ip6_dst_hoplimit(struct dst_entry *dst);
 
 static inline int ip6_sk_dst_hoplimit(struct ipv6_pinfo *np, struct flowi6 *fl6,
index e8427193c777b884428aa1712ff18f910ab8d24a..03e928a552290f57b050c4ce7dbe6592d02102e4 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _IPV4_NF_REJECT_H
 #define _IPV4_NF_REJECT_H
 
+#include <linux/skbuff.h>
+#include <net/ip.h>
 #include <net/icmp.h>
 
 static inline void nf_send_unreach(struct sk_buff *skb_in, int code)
@@ -10,4 +12,12 @@ static inline void nf_send_unreach(struct sk_buff *skb_in, int code)
 
 void nf_send_reset(struct sk_buff *oldskb, int hook);
 
+const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
+                                            struct tcphdr *_oth, int hook);
+struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb,
+                                 const struct sk_buff *oldskb,
+                                 __be16 protocol, int ttl);
+void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
+                            const struct tcphdr *oth);
+
 #endif /* _IPV4_NF_REJECT_H */
index 48e18810a9be6fcc6250f80db0d8febcf4e3cdf4..23216d48abf9ddb79aa188cbf55e0a032e4f9e78 100644 (file)
@@ -15,4 +15,14 @@ nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code,
 
 void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook);
 
+const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
+                                             struct tcphdr *otcph,
+                                             unsigned int *otcplen, int hook);
+struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb,
+                                    const struct sk_buff *oldskb,
+                                    __be16 protocol, int hoplimit);
+void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
+                             const struct sk_buff *oldskb,
+                             const struct tcphdr *oth, unsigned int otcplen);
+
 #endif /* _IPV6_NF_REJECT_H */
index 3d7292392fac91ca806b12945fd9eb190c21a031..3ae969e3acf016474413e1209381c60091befe1a 100644 (file)
@@ -396,14 +396,12 @@ struct nft_rule {
 /**
  *     struct nft_trans - nf_tables object update in transaction
  *
- *     @rcu_head: rcu head to defer release of transaction data
  *     @list: used internally
  *     @msg_type: message type
  *     @ctx: transaction context
  *     @data: internal information related to the transaction
  */
 struct nft_trans {
-       struct rcu_head                 rcu_head;
        struct list_head                list;
        int                             msg_type;
        struct nft_ctx                  ctx;
@@ -530,6 +528,9 @@ enum nft_chain_type {
        NFT_CHAIN_T_MAX
 };
 
+int nft_chain_validate_dependency(const struct nft_chain *chain,
+                                 enum nft_chain_type type);
+
 struct nft_stats {
        u64                     bytes;
        u64                     pkts;
index c72729f954f41e2168d5a095db5cc1ad39f38878..e2a518b60e19039014e1298f3618046e9e030238 100644 (file)
@@ -13,4 +13,7 @@ int nft_masq_init(const struct nft_ctx *ctx,
 
 int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr);
 
+int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
+                     const struct nft_data **data);
+
 #endif /* _NFT_MASQ_H_ */
index 7db3db112baa5eaa9ce1958c7837f89dbafde6a8..e6f235ebf6c9299eba6cea962808cd12129426f0 100644 (file)
@@ -897,6 +897,7 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
                if (!__rc) {                                            \
                        *(__timeo) = schedule_timeout(*(__timeo));      \
                }                                                       \
+               sched_annotate_sleep();                                         \
                lock_sock(__sk);                                        \
                __rc = __condition;                                     \
                __rc;                                                   \
index a47790bcaa3831b1c2692b3cf27c4306ff39e631..2a50a70ef5870c76e0694ca460182671df46973e 100644 (file)
@@ -100,6 +100,15 @@ static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb,
        return iptunnel_handle_offloads(skb, udp_csum, type);
 }
 
+static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff)
+{
+       struct udphdr *uh;
+
+       uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr));
+       skb_shinfo(skb)->gso_type |= uh->check ?
+                               SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+}
+
 static inline void udp_tunnel_encap_enable(struct socket *sock)
 {
 #if IS_ENABLED(CONFIG_IPV6)
index d5f59f3fc35df67141c8234a8741ab5b49501ad1..57cccd0052e58dd124ec997174d8cd9ff885be99 100644 (file)
@@ -8,6 +8,12 @@
 #define VNI_HASH_BITS  10
 #define VNI_HASH_SIZE  (1<<VNI_HASH_BITS)
 
+/* VXLAN protocol header */
+struct vxlanhdr {
+       __be32 vx_flags;
+       __be32 vx_vni;
+};
+
 struct vxlan_sock;
 typedef void (vxlan_rcv_t)(struct vxlan_sock *vh, struct sk_buff *skb, __be32 key);
 
@@ -45,6 +51,18 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
                   __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
                   __be16 src_port, __be16 dst_port, __be32 vni, bool xnet);
 
+static inline bool vxlan_gso_check(struct sk_buff *skb)
+{
+       if ((skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) &&
+           (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
+            skb->inner_protocol != htons(ETH_P_TEB) ||
+            (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
+             sizeof(struct udphdr) + sizeof(struct vxlanhdr))))
+               return false;
+
+       return true;
+}
+
 /* IP header + UDP + VXLAN + Ethernet header */
 #define VXLAN_HEADROOM (20 + 8 + 8 + 14)
 /* IPv6 header + UDP + VXLAN + Ethernet header */
index 52beadf9a29be89592d41b6400c8e8d5d34e6036..93d14daf0994725822461a8dbe36e97d52f56e51 100644 (file)
@@ -1105,8 +1105,6 @@ int fc_eh_abort(struct scsi_cmnd *);
 int fc_eh_device_reset(struct scsi_cmnd *);
 int fc_eh_host_reset(struct scsi_cmnd *);
 int fc_slave_alloc(struct scsi_device *);
-int fc_change_queue_depth(struct scsi_device *, int qdepth, int reason);
-int fc_change_queue_type(struct scsi_device *, int tag_type);
 
 /*
  * ELS/CT interface
index 728c9ad9feb0485b9a3f0db6bc77fefa915594a0..4d1c46aac3319de315239dc1e1908c3204a8ad20 100644 (file)
@@ -378,8 +378,6 @@ struct iscsi_host {
 /*
  * scsi host template
  */
-extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth,
-                                   int reason);
 extern int iscsi_eh_abort(struct scsi_cmnd *sc);
 extern int iscsi_eh_recover_target(struct scsi_cmnd *sc);
 extern int iscsi_eh_session_reset(struct scsi_cmnd *sc);
index ef7872c20da9e5f2d16c5a950b0abd0d9e9e53b2..832dcc9f86ec9d7e2eef96a42de942a6d30cc679 100644 (file)
@@ -365,12 +365,6 @@ struct asd_sas_phy {
 struct scsi_core {
        struct Scsi_Host *shost;
 
-       struct mutex      task_queue_flush;
-       spinlock_t        task_queue_lock;
-       struct list_head  task_queue;
-       int               task_queue_size;
-
-       struct task_struct *queue_thread;
 };
 
 struct sas_ha_event {
@@ -422,9 +416,6 @@ struct sas_ha_struct {
        struct asd_sas_port **sas_port; /* array of valid pointers, must be set */
        int             num_phys; /* must be set, gt 0, static */
 
-       /* The class calls this to send a task for execution. */
-       int lldd_max_execute_num;
-       int lldd_queue_size;
        int strict_wide_ports; /* both sas_addr and attached_sas_addr must match
                                * their siblings when forming wide ports */
 
@@ -612,7 +603,6 @@ struct sas_ssp_task {
 
 struct sas_task {
        struct domain_device *dev;
-       struct list_head      list;
 
        spinlock_t   task_state_lock;
        unsigned     task_state_flags;
@@ -665,8 +655,7 @@ struct sas_domain_function_template {
        int  (*lldd_dev_found)(struct domain_device *);
        void (*lldd_dev_gone)(struct domain_device *);
 
-       int (*lldd_execute_task)(struct sas_task *, int num,
-                                gfp_t gfp_flags);
+       int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags);
 
        /* Task Management Functions. Must be called from process context. */
        int (*lldd_abort_task)(struct sas_task *);
@@ -700,12 +689,10 @@ extern void sas_suspend_ha(struct sas_ha_struct *sas_ha);
 int sas_set_phy_speed(struct sas_phy *phy,
                      struct sas_phy_linkrates *rates);
 int sas_phy_reset(struct sas_phy *phy, int hard_reset);
-int sas_queue_up(struct sas_task *task);
 extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *);
 extern int sas_target_alloc(struct scsi_target *);
 extern int sas_slave_configure(struct scsi_device *);
-extern int sas_change_queue_depth(struct scsi_device *, int new_depth,
-                                 int reason);
+extern int sas_change_queue_depth(struct scsi_device *, int new_depth);
 extern int sas_change_queue_type(struct scsi_device *, int qt);
 extern int sas_bios_param(struct scsi_device *,
                          struct block_device *,
index b2e85fdd2ae005369a9e75db6ae0a0ad5e98a356..a09cca829082c71b10ee9799742a97250f44d4c2 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
index 6ca3265a4dcacaff704e32a329f546a421c2971e..7a8d2cd30328389e23e7c49bef90efe17c9c4198 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011
- * Boaz Harrosh <bharrosh@panasas.com>
+ * Boaz Harrosh <ooo@electrozaur.com>
  *
  * Public Declarations of the ORE API
  *
index a2594afe05c733e7e7218d14dbba55de5785502f..e0ca835e7bf78f4e6ad51083734b5a3c0b86805a 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -496,7 +496,7 @@ struct osd_timestamp {
  */
 
 struct osd_key_identifier {
-       u8 id[7]; /* if you know why 7 please email bharrosh@panasas.com */
+       u8 id[7]; /* if you know why 7 please email ooo@electrozaur.com */
 } __packed;
 
 /* for osd_capability.format */
index f96151c9c9e8c17412908feeec85c151a8a21c7b..7abeb0f0db308065aa524fe882da7eebc5f61a73 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
index 91db543a550258ed256332104b77cd738ee382d5..d52aa93a0b2d194a006261026a09e1b29bafd111 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
index bd0be7ed4bcf619ca4aea8cfa3abc6d86d9c7aec..48e8a165e136379f2c6bd10bcf78cfa18390d2a3 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Panasas Inc.  All rights reserved.
  *
  * Authors:
- *   Boaz Harrosh <bharrosh@panasas.com>
+ *   Boaz Harrosh <ooo@electrozaur.com>
  *   Benny Halevy <bhalevy@panasas.com>
  *
  * This program is free software; you can redistribute it and/or modify
index d17178e6fcdd738a6e178d4e7ea226895a815827..8a7f8ad58aac2567b51b6c8e934077c4d16058be 100644 (file)
@@ -128,8 +128,10 @@ enum scsi_timeouts {
 #define MOVE_MEDIUM           0xa5
 #define EXCHANGE_MEDIUM       0xa6
 #define READ_12               0xa8
+#define SERVICE_ACTION_OUT_12 0xa9
 #define WRITE_12              0xaa
-#define READ_MEDIA_SERIAL_NUMBER 0xab
+#define READ_MEDIA_SERIAL_NUMBER 0xab /* Obsolete with SPC-2 */
+#define SERVICE_ACTION_IN_12  0xab
 #define WRITE_VERIFY_12       0xae
 #define VERIFY_12            0xaf
 #define SEARCH_HIGH_12        0xb0
@@ -151,7 +153,9 @@ enum scsi_timeouts {
 #define VERIFY_16            0x8f
 #define SYNCHRONIZE_CACHE_16  0x91
 #define WRITE_SAME_16        0x93
-#define SERVICE_ACTION_IN     0x9e
+#define SERVICE_ACTION_BIDIRECTIONAL 0x9d
+#define SERVICE_ACTION_IN_16  0x9e
+#define SERVICE_ACTION_OUT_16 0x9f
 /* values for service action in */
 #define        SAI_READ_CAPACITY_16  0x10
 #define SAI_GET_LBA_STATUS    0x12
@@ -165,8 +169,8 @@ enum scsi_timeouts {
 #define MI_REPORT_ALIASES     0x0b
 #define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c
 #define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d
-#define MI_REPORT_PRIORITY   0x0e
-#define MI_REPORT_TIMESTAMP  0x0f
+#define MI_REPORT_PRIORITY    0x0e
+#define MI_REPORT_TIMESTAMP   0x0f
 #define MI_MANAGEMENT_PROTOCOL_IN 0x10
 /* value for MI_REPORT_TARGET_PGS ext header */
 #define MI_EXT_HDR_PARAM_FMT  0x20
index 522a5f27f553a406c1879a294c95bf3a07de7cf6..9fc1aecfc81369b9cfc694bece77b9bdfde131e5 100644 (file)
@@ -53,6 +53,9 @@ struct scsi_pointer {
        volatile int phase;
 };
 
+/* for scmd->flags */
+#define SCMD_TAGGED            (1 << 0)
+
 struct scsi_cmnd {
        struct scsi_device *device;
        struct list_head list;  /* scsi_cmnd participates in queue lists */
@@ -132,6 +135,7 @@ struct scsi_cmnd {
                                         * to be at an address < 16Mb). */
 
        int result;             /* Status code from lower level driver */
+       int flags;              /* Command flags */
 
        unsigned char tag;      /* SCSI-II queued command tag */
 };
@@ -159,7 +163,7 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
                                 size_t *offset, size_t *len);
 extern void scsi_kunmap_atomic_sg(void *virt);
 
-extern int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask);
+extern int scsi_init_io(struct scsi_cmnd *cmd);
 
 extern int scsi_dma_map(struct scsi_cmnd *cmd);
 extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
index e89844cc2cd359bf281574f45f942826b1af9056..7982795df59592d8219e9ec6c4b5102b0593214d 100644 (file)
@@ -2,23 +2,27 @@
 #define _SCSI_SCSI_DBG_H
 
 struct scsi_cmnd;
+struct scsi_device;
 struct scsi_sense_hdr;
 
 extern void scsi_print_command(struct scsi_cmnd *);
-extern void __scsi_print_command(unsigned char *);
-extern void scsi_show_extd_sense(unsigned char, unsigned char);
-extern void scsi_show_sense_hdr(struct scsi_sense_hdr *);
-extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
-extern void scsi_cmd_print_sense_hdr(struct scsi_cmnd *, const char *,
-                                    struct scsi_sense_hdr *);
-extern void scsi_print_sense(char *, struct scsi_cmnd *);
-extern void __scsi_print_sense(const char *name,
+extern void __scsi_print_command(const unsigned char *, size_t);
+extern void scsi_show_extd_sense(const struct scsi_device *, const char *,
+                                unsigned char, unsigned char);
+extern void scsi_show_sense_hdr(const struct scsi_device *, const char *,
+                               const struct scsi_sense_hdr *);
+extern void scsi_print_sense_hdr(const struct scsi_device *, const char *,
+                                const struct scsi_sense_hdr *);
+extern void scsi_print_sense(const struct scsi_cmnd *);
+extern void __scsi_print_sense(const struct scsi_device *, const char *name,
                               const unsigned char *sense_buffer,
                               int sense_len);
-extern void scsi_show_result(int);
-extern void scsi_print_result(struct scsi_cmnd *);
-extern void scsi_print_status(unsigned char);
+extern void scsi_print_result(struct scsi_cmnd *, const char *, int);
+extern const char *scsi_hostbyte_string(int);
+extern const char *scsi_driverbyte_string(int);
+extern const char *scsi_mlreturn_string(int);
 extern const char *scsi_sense_key_string(unsigned char);
-extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
+extern const char *scsi_extd_sense_format(unsigned char, unsigned char,
+                                         const char **);
 
 #endif /* _SCSI_SCSI_DBG_H */
index 27ecee73bd72b35b6ad0029686a278ec3ae26de4..6364e23454dd7a8a8ea4b9d9b3289c48f75efddb 100644 (file)
@@ -141,7 +141,6 @@ struct scsi_device {
        unsigned ppr:1;         /* Device supports PPR messages */
        unsigned tagged_supported:1;    /* Supports SCSI-II tagged queuing */
        unsigned simple_tags:1; /* simple queue tag messages are enabled */
-       unsigned ordered_tags:1;/* ordered queue tag messages are enabled */
        unsigned was_reset:1;   /* There was a bus reset on the bus for 
                                 * this device */
        unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN
@@ -201,11 +200,6 @@ struct scsi_device {
        unsigned long           sdev_data[0];
 } __attribute__((aligned(sizeof(unsigned long))));
 
-struct scsi_dh_devlist {
-       char *vendor;
-       char *model;
-};
-
 typedef void (*activate_complete)(void *, int);
 struct scsi_device_handler {
        /* Used by the infrastructure */
@@ -214,9 +208,8 @@ struct scsi_device_handler {
        /* Filled by the hardware handler */
        struct module *module;
        const char *name;
-       const struct scsi_dh_devlist *devlist;
        int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *);
-       int (*attach)(struct scsi_device *);
+       struct scsi_dh_data *(*attach)(struct scsi_device *);
        void (*detach)(struct scsi_device *);
        int (*activate)(struct scsi_device *, activate_complete, void *);
        int (*prep_fn)(struct scsi_device *, struct request *);
@@ -228,7 +221,6 @@ struct scsi_dh_data {
        struct scsi_device_handler *scsi_dh;
        struct scsi_device *sdev;
        struct kref kref;
-       char buf[0];
 };
 
 #define        to_scsi_device(d)       \
@@ -244,6 +236,15 @@ struct scsi_dh_data {
 #define sdev_dbg(sdev, fmt, a...) \
        dev_dbg(&(sdev)->sdev_gendev, fmt, ##a)
 
+/*
+ * like scmd_printk, but the device name is passed in
+ * as a string pointer
+ */
+#define sdev_prefix_printk(l, sdev, p, fmt, a...)                      \
+       (p) ?                                                           \
+       sdev_printk(l, sdev, "[%s] " fmt, p, ##a) :                     \
+       sdev_printk(l, sdev, fmt, ##a)
+
 #define scmd_printk(prefix, scmd, fmt, a...)                           \
         (scmd)->request->rq_disk ?                                     \
        sdev_printk(prefix, (scmd)->device, "[%s] " fmt,                \
@@ -379,7 +380,7 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *,
 #define __shost_for_each_device(sdev, shost) \
        list_for_each_entry((sdev), &((shost)->__devices), siblings)
 
-extern void scsi_adjust_queue_depth(struct scsi_device *, int, int);
+extern int scsi_change_queue_depth(struct scsi_device *, int);
 extern int scsi_track_queue_full(struct scsi_device *, int);
 
 extern int scsi_set_medium_removal(struct scsi_device *, char);
index c2b759809d8acb800049dd63a26b6acfc59186f6..891a658aa8673d03b5ad8ac848f3318662d39707 100644 (file)
@@ -9,7 +9,6 @@ struct scsi_cmnd;
 struct scsi_device;
 
 struct scsi_driver {
-       struct module           *owner;
        struct device_driver    gendrv;
 
        void (*rescan)(struct device *);
index 06a8790893ef60e15cdd100550134e698e6a5e2e..1e1421b06565ca750b4326683f78a0e8ae276a1e 100644 (file)
@@ -27,10 +27,10 @@ struct scsi_sense_hdr {             /* See SPC-3 section 4.5 */
        u8 additional_length;   /* always 0 for fixed sense format */
 };
 
-static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr)
+static inline bool scsi_sense_valid(const struct scsi_sense_hdr *sshdr)
 {
        if (!sshdr)
-               return 0;
+               return false;
 
        return (sshdr->response_code & 0x70) == 0x70;
 }
@@ -42,12 +42,12 @@ extern void scsi_eh_flush_done_q(struct list_head *done_q);
 extern void scsi_report_bus_reset(struct Scsi_Host *, int);
 extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
 extern int scsi_block_when_processing_errors(struct scsi_device *);
-extern int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
-               struct scsi_sense_hdr *sshdr);
-extern int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
-               struct scsi_sense_hdr *sshdr);
+extern bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
+                                struct scsi_sense_hdr *sshdr);
+extern bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd,
+                                        struct scsi_sense_hdr *sshdr);
 
-static inline int scsi_sense_is_deferred(struct scsi_sense_hdr *sshdr)
+static inline bool scsi_sense_is_deferred(const struct scsi_sense_hdr *sshdr)
 {
        return ((sshdr->response_code >= 0x70) && (sshdr->response_code & 1));
 }
@@ -60,15 +60,7 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
 
 extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
 
-/*
- * Reset request from external source
- */
-#define SCSI_TRY_RESET_DEVICE  1
-#define SCSI_TRY_RESET_BUS     2
-#define SCSI_TRY_RESET_HOST    3
-#define SCSI_TRY_RESET_TARGET  4
-
-extern int scsi_reset_provider(struct scsi_device *, int);
+extern int scsi_ioctl_reset(struct scsi_device *, int __user *);
 
 struct scsi_eh_save {
        /* saved state */
index 5e362489ee88a024d8216c1740fa0b424e723bb2..c8a462ef9a4ee2896914e3f14bfa29e979d13c27 100644 (file)
@@ -46,12 +46,6 @@ struct blk_queue_tags;
 #define DISABLE_CLUSTERING 0
 #define ENABLE_CLUSTERING 1
 
-enum {
-       SCSI_QDEPTH_DEFAULT,    /* default requested change, e.g. from sysfs */
-       SCSI_QDEPTH_QFULL,      /* scsi-ml requested due to queue full */
-       SCSI_QDEPTH_RAMP_UP,    /* scsi-ml requested due to threshold event */
-};
-
 struct scsi_host_template {
        struct module *module;
        const char *name;
@@ -195,7 +189,7 @@ struct scsi_host_template {
         * Things currently recommended to be handled at this time include:
         *
         * 1.  Setting the device queue depth.  Proper setting of this is
-        *     described in the comments for scsi_adjust_queue_depth.
+        *     described in the comments for scsi_change_queue_depth.
         * 2.  Determining if the device supports the various synchronous
         *     negotiation protocols.  The device struct will already have
         *     responded to INQUIRY and the results of the standard items
@@ -281,7 +275,7 @@ struct scsi_host_template {
         *
         * Status: OPTIONAL
         */
-       int (* change_queue_depth)(struct scsi_device *, int, int);
+       int (* change_queue_depth)(struct scsi_device *, int);
 
        /*
         * Fill in this function to allow the changing of tag types
@@ -421,6 +415,16 @@ struct scsi_host_template {
         */
        unsigned char present;
 
+       /*
+        * Let the block layer assigns tags to all commands.
+        */
+       unsigned use_blk_tags:1;
+
+       /*
+        * Track QUEUE_FULL events and reduce queue depth on demand.
+        */
+       unsigned track_queue_depth:1;
+
        /*
         * This specifies the mode that a LLD supports.
         */
@@ -451,11 +455,6 @@ struct scsi_host_template {
         */
        unsigned skip_settle_delay:1;
 
-       /*
-        * True if we are using ordered write support.
-        */
-       unsigned ordered_tag:1;
-
        /* True if the controller does not support WRITE SAME */
        unsigned no_write_same:1;
 
@@ -638,6 +637,14 @@ struct Scsi_Host {
        short unsigned int sg_prot_tablesize;
        unsigned int max_sectors;
        unsigned long dma_boundary;
+       /*
+        * In scsi-mq mode, the number of hardware queues supported by the LLD.
+        *
+        * Note: it is assumed that each hardware queue has a queue depth of
+        * can_queue. In other words, the total queue depth per host
+        * is nr_hw_queues * can_queue.
+        */
+       unsigned nr_hw_queues;
        /* 
         * Used to assign serial numbers to the cmds.
         * Protected by the host lock.
@@ -647,7 +654,6 @@ struct Scsi_Host {
        unsigned active_mode:2;
        unsigned unchecked_isa_dma:1;
        unsigned use_clustering:1;
-       unsigned use_blk_tcq:1;
 
        /*
         * Host has requested that no further requests come through for the
@@ -662,11 +668,6 @@ struct Scsi_Host {
         */
        unsigned reverse_ordering:1;
 
-       /*
-        * Ordered write support
-        */
-       unsigned ordered_tag:1;
-
        /* Task mgmt function in progress */
        unsigned tmf_in_progress:1;
 
index b9006848b8134412cc29f67208890cbfdc2f370b..8d19d1d233c36a59ddc7b15c4fe066cae47f0a48 100644 (file)
@@ -40,9 +40,9 @@ typedef struct scsi_fctargaddress {
        unsigned char host_wwn[8]; // include NULL term.
 } Scsi_FCTargAddress;
 
+int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
+               int cmd, bool ndelay);
 extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
-                                  void __user *arg, int ndelay);
 
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */
index e64583560701bb1f2f0038717457321597b39e85..fe4a70299419cedc7160b08942bce7367517f3ab 100644 (file)
 
 #ifdef CONFIG_BLOCK
 
+int scsi_change_queue_type(struct scsi_device *sdev, int tag_type);
+
 /**
  * scsi_get_tag_type - get the type of tag the device supports
  * @sdev:      the scsi device
- *
- * Notes:
- *     If the drive only supports simple tags, returns MSG_SIMPLE_TAG
- *     if it supports all tag types, returns MSG_ORDERED_TAG.
  */
 static inline int scsi_get_tag_type(struct scsi_device *sdev)
 {
        if (!sdev->tagged_supported)
                return 0;
-       if (sdev->ordered_tags)
-               return MSG_ORDERED_TAG;
        if (sdev->simple_tags)
                return MSG_SIMPLE_TAG;
        return 0;
@@ -39,90 +35,33 @@ static inline void scsi_set_tag_type(struct scsi_device *sdev, int tag)
 {
        switch (tag) {
        case MSG_ORDERED_TAG:
-               sdev->ordered_tags = 1;
-               /* fall through */
        case MSG_SIMPLE_TAG:
                sdev->simple_tags = 1;
                break;
        case 0:
                /* fall through */
        default:
-               sdev->ordered_tags = 0;
                sdev->simple_tags = 0;
                break;
        }
 }
-/**
- * scsi_activate_tcq - turn on tag command queueing
- * @SDpnt:     device to turn on TCQ for
- * @depth:     queue depth
- *
- * Notes:
- *     Eventually, I hope depth would be the maximum depth
- *     the device could cope with and the real queue depth
- *     would be adjustable from 0 to depth.
- **/
-static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth)
-{
-       if (!sdev->tagged_supported)
-               return;
-
-       if (!shost_use_blk_mq(sdev->host) &&
-           !blk_queue_tagged(sdev->request_queue))
-               blk_queue_init_tags(sdev->request_queue, depth,
-                                   sdev->host->bqt);
-
-       scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-}
-
-/**
- * scsi_deactivate_tcq - turn off tag command queueing
- * @SDpnt:     device to turn off TCQ for
- **/
-static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
-{
-       if (!shost_use_blk_mq(sdev->host) &&
-           blk_queue_tagged(sdev->request_queue))
-               blk_queue_free_tags(sdev->request_queue);
-       scsi_adjust_queue_depth(sdev, 0, depth);
-}
-
-/**
- * scsi_populate_tag_msg - place a tag message in a buffer
- * @SCpnt:     pointer to the Scsi_Cmnd for the tag
- * @msg:       pointer to the area to place the tag
- *
- * Notes:
- *     designed to create the correct type of tag message for the 
- *     particular request.  Returns the size of the tag message.
- *     May return 0 if TCQ is disabled for this device.
- **/
-static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg)
-{
-        struct request *req = cmd->request;
-
-        if (blk_rq_tagged(req)) {
-               *msg++ = MSG_SIMPLE_TAG;
-               *msg++ = req->tag;
-               return 2;
-       }
-
-       return 0;
-}
 
 static inline struct scsi_cmnd *scsi_mq_find_tag(struct Scsi_Host *shost,
-               unsigned int hw_ctx, int tag)
+                                                int unique_tag)
 {
-       struct request *req;
+       u16 hwq = blk_mq_unique_tag_to_hwq(unique_tag);
+       struct request *req = NULL;
 
-       req = blk_mq_tag_to_rq(shost->tag_set.tags[hw_ctx], tag);
+       if (hwq < shost->tag_set.nr_hw_queues)
+               req = blk_mq_tag_to_rq(shost->tag_set.tags[hwq],
+                                      blk_mq_unique_tag_to_tag(unique_tag));
        return req ? (struct scsi_cmnd *)req->special : NULL;
 }
 
 /**
  * scsi_find_tag - find a tagged command by device
  * @SDpnt:     pointer to the ScSI device
- * @tag:       the tag number
+ * @tag:       tag generated by blk_mq_unique_tag()
  *
  * Notes:
  *     Only works with tags allocated by the generic blk layer.
@@ -133,9 +72,9 @@ static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag)
 
         if (tag != SCSI_NO_TAG) {
                if (shost_use_blk_mq(sdev->host))
-                       return scsi_mq_find_tag(sdev->host, 0, tag);
+                       return scsi_mq_find_tag(sdev->host, tag);
 
-               req = blk_queue_find_tag(sdev->request_queue, tag);
+               req = blk_queue_find_tag(sdev->request_queue, tag);
                return req ? (struct scsi_cmnd *)req->special : NULL;
        }
 
@@ -174,7 +113,7 @@ static inline int scsi_init_shared_tag_map(struct Scsi_Host *shost, int depth)
 /**
  * scsi_host_find_tag - find the tagged command by host
  * @shost:     pointer to scsi_host
- * @tag:       tag of the scsi_cmnd
+ * @tag:       tag generated by blk_mq_unique_tag()
  *
  * Notes:
  *     Only works with tags allocated by the generic blk layer.
@@ -186,7 +125,7 @@ static inline struct scsi_cmnd *scsi_host_find_tag(struct Scsi_Host *shost,
 
        if (tag != SCSI_NO_TAG) {
                if (shost_use_blk_mq(shost))
-                       return scsi_mq_find_tag(shost, 0, tag);
+                       return scsi_mq_find_tag(shost, tag);
                req = blk_map_queue_find_tag(shost->bqt, tag);
                return req ? (struct scsi_cmnd *)req->special : NULL;
        }
index 7497a383b1a4da6264abdd3892bddada0c34c75e..a4fa52b4d5c576676c37bc27610b28d2922c37fb 100644 (file)
@@ -157,5 +157,6 @@ int spi_populate_width_msg(unsigned char *msg, int width);
 int spi_populate_sync_msg(unsigned char *msg, int period, int offset);
 int spi_populate_ppr_msg(unsigned char *msg, int period, int offset, int width,
                int options);
+int spi_populate_tag_msg(unsigned char *msg, struct scsi_cmnd *cmd);
 
 #endif /* SCSI_TRANSPORT_SPI_H */
index 750e5db7c6bff10b04e7d5ee8853d244cb7fc610..3afec7032448c8927d2cd134111606ee0206ca3d 100644 (file)
@@ -164,12 +164,15 @@ typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
 
 /* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */
 #define SG_SCSI_RESET 0x2284
-/* Associated values that can be given to SG_SCSI_RESET follow */
+/* Associated values that can be given to SG_SCSI_RESET follow.
+ * SG_SCSI_RESET_NO_ESCALATE may be OR-ed to the _DEVICE, _TARGET, _BUS
+ * or _HOST reset value so only that action is attempted. */
 #define                SG_SCSI_RESET_NOTHING   0
 #define                SG_SCSI_RESET_DEVICE    1
 #define                SG_SCSI_RESET_BUS       2
 #define                SG_SCSI_RESET_HOST      3
 #define                SG_SCSI_RESET_TARGET    4
+#define                SG_SCSI_RESET_NO_ESCALATE       0x100
 
 /* synchronous SCSI command ioctl, (only in version 3 interface) */
 #define SG_IO 0x2285   /* similar effect as write() followed by read() */
diff --git a/include/soc/at91/at91rm9200_sdramc.h b/include/soc/at91/at91rm9200_sdramc.h
new file mode 100644 (file)
index 0000000..aa047f4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91rm9200_sdramc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Memory Controllers (SDRAMC only) - 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 AT91RM9200_SDRAMC_H
+#define AT91RM9200_SDRAMC_H
+
+/* SDRAM Controller registers */
+#define AT91RM9200_SDRAMC_MR           0x90                    /* Mode Register */
+#define                AT91RM9200_SDRAMC_MODE  (0xf << 0)              /* Command Mode */
+#define                        AT91RM9200_SDRAMC_MODE_NORMAL           (0 << 0)
+#define                        AT91RM9200_SDRAMC_MODE_NOP              (1 << 0)
+#define                        AT91RM9200_SDRAMC_MODE_PRECHARGE        (2 << 0)
+#define                        AT91RM9200_SDRAMC_MODE_LMR              (3 << 0)
+#define                        AT91RM9200_SDRAMC_MODE_REFRESH  (4 << 0)
+#define                AT91RM9200_SDRAMC_DBW           (1   << 4)              /* Data Bus Width */
+#define                        AT91RM9200_SDRAMC_DBW_32        (0 << 4)
+#define                        AT91RM9200_SDRAMC_DBW_16        (1 << 4)
+
+#define AT91RM9200_SDRAMC_TR           0x94                    /* Refresh Timer Register */
+#define                AT91RM9200_SDRAMC_COUNT (0xfff << 0)            /* Refresh Timer Count */
+
+#define AT91RM9200_SDRAMC_CR           0x98                    /* Configuration Register */
+#define                AT91RM9200_SDRAMC_NC            (3   <<  0)             /* Number of Column Bits */
+#define                        AT91RM9200_SDRAMC_NC_8  (0 << 0)
+#define                        AT91RM9200_SDRAMC_NC_9  (1 << 0)
+#define                        AT91RM9200_SDRAMC_NC_10 (2 << 0)
+#define                        AT91RM9200_SDRAMC_NC_11 (3 << 0)
+#define                AT91RM9200_SDRAMC_NR            (3   <<  2)             /* Number of Row Bits */
+#define                        AT91RM9200_SDRAMC_NR_11 (0 << 2)
+#define                        AT91RM9200_SDRAMC_NR_12 (1 << 2)
+#define                        AT91RM9200_SDRAMC_NR_13 (2 << 2)
+#define                AT91RM9200_SDRAMC_NB            (1   <<  4)             /* Number of Banks */
+#define                        AT91RM9200_SDRAMC_NB_2  (0 << 4)
+#define                        AT91RM9200_SDRAMC_NB_4  (1 << 4)
+#define                AT91RM9200_SDRAMC_CAS           (3   <<  5)             /* CAS Latency */
+#define                        AT91RM9200_SDRAMC_CAS_2 (2 << 5)
+#define                AT91RM9200_SDRAMC_TWR           (0xf <<  7)             /* Write Recovery Delay */
+#define                AT91RM9200_SDRAMC_TRC           (0xf << 11)             /* Row Cycle Delay */
+#define                AT91RM9200_SDRAMC_TRP           (0xf << 15)             /* Row Precharge Delay */
+#define                AT91RM9200_SDRAMC_TRCD  (0xf << 19)             /* Row to Column Delay */
+#define                AT91RM9200_SDRAMC_TRAS  (0xf << 23)             /* Active to Precharge Delay */
+#define                AT91RM9200_SDRAMC_TXSR  (0xf << 27)             /* Exit Self Refresh to Active Delay */
+
+#define AT91RM9200_SDRAMC_SRR          0x9c                    /* Self Refresh Register */
+#define AT91RM9200_SDRAMC_LPR          0xa0                    /* Low Power Register */
+#define AT91RM9200_SDRAMC_IER          0xa4                    /* Interrupt Enable Register */
+#define AT91RM9200_SDRAMC_IDR          0xa8                    /* Interrupt Disable Register */
+#define AT91RM9200_SDRAMC_IMR          0xac                    /* Interrupt Mask Register */
+#define AT91RM9200_SDRAMC_ISR          0xb0                    /* Interrupt Status Register */
+
+#endif
diff --git a/include/soc/at91/at91sam9_ddrsdr.h b/include/soc/at91/at91sam9_ddrsdr.h
new file mode 100644 (file)
index 0000000..0210797
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Header file for the Atmel DDR/SDR SDRAM Controller
+ *
+ * Copyright (C) 2010 Atmel Corporation
+ *     Nicolas Ferre <nicolas.ferre@atmel.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 AT91SAM9_DDRSDR_H
+#define AT91SAM9_DDRSDR_H
+
+#define AT91_DDRSDRC_MR                0x00    /* Mode Register */
+#define                AT91_DDRSDRC_MODE       (0x7 << 0)              /* Command Mode */
+#define                        AT91_DDRSDRC_MODE_NORMAL        0
+#define                        AT91_DDRSDRC_MODE_NOP           1
+#define                        AT91_DDRSDRC_MODE_PRECHARGE     2
+#define                        AT91_DDRSDRC_MODE_LMR           3
+#define                        AT91_DDRSDRC_MODE_REFRESH       4
+#define                        AT91_DDRSDRC_MODE_EXT_LMR       5
+#define                        AT91_DDRSDRC_MODE_DEEP          6
+
+#define AT91_DDRSDRC_RTR       0x04    /* Refresh Timer Register */
+#define                AT91_DDRSDRC_COUNT      (0xfff << 0)            /* Refresh Timer Counter */
+
+#define AT91_DDRSDRC_CR                0x08    /* Configuration Register */
+#define                AT91_DDRSDRC_NC         (3 << 0)                /* Number of Column Bits */
+#define                        AT91_DDRSDRC_NC_SDR8    (0 << 0)
+#define                        AT91_DDRSDRC_NC_SDR9    (1 << 0)
+#define                        AT91_DDRSDRC_NC_SDR10   (2 << 0)
+#define                        AT91_DDRSDRC_NC_SDR11   (3 << 0)
+#define                        AT91_DDRSDRC_NC_DDR9    (0 << 0)
+#define                        AT91_DDRSDRC_NC_DDR10   (1 << 0)
+#define                        AT91_DDRSDRC_NC_DDR11   (2 << 0)
+#define                        AT91_DDRSDRC_NC_DDR12   (3 << 0)
+#define                AT91_DDRSDRC_NR         (3 << 2)                /* Number of Row Bits */
+#define                        AT91_DDRSDRC_NR_11      (0 << 2)
+#define                        AT91_DDRSDRC_NR_12      (1 << 2)
+#define                        AT91_DDRSDRC_NR_13      (2 << 2)
+#define                        AT91_DDRSDRC_NR_14      (3 << 2)
+#define                AT91_DDRSDRC_CAS        (7 << 4)                /* CAS Latency */
+#define                        AT91_DDRSDRC_CAS_2      (2 << 4)
+#define                        AT91_DDRSDRC_CAS_3      (3 << 4)
+#define                        AT91_DDRSDRC_CAS_25     (6 << 4)
+#define                AT91_DDRSDRC_RST_DLL    (1 << 7)                /* Reset DLL */
+#define                AT91_DDRSDRC_DICDS      (1 << 8)                /* Output impedance control */
+#define                AT91_DDRSDRC_DIS_DLL    (1 << 9)                /* Disable DLL [SAM9 Only] */
+#define                AT91_DDRSDRC_OCD        (1 << 12)               /* Off-Chip Driver [SAM9 Only] */
+#define                AT91_DDRSDRC_DQMS       (1 << 16)               /* Mask Data is Shared [SAM9 Only] */
+#define                AT91_DDRSDRC_ACTBST     (1 << 18)               /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */
+
+#define AT91_DDRSDRC_T0PR      0x0C    /* Timing 0 Register */
+#define                AT91_DDRSDRC_TRAS       (0xf <<  0)             /* Active to Precharge delay */
+#define                AT91_DDRSDRC_TRCD       (0xf <<  4)             /* Row to Column delay */
+#define                AT91_DDRSDRC_TWR        (0xf <<  8)             /* Write recovery delay */
+#define                AT91_DDRSDRC_TRC        (0xf << 12)             /* Row cycle delay */
+#define                AT91_DDRSDRC_TRP        (0xf << 16)             /* Row precharge delay */
+#define                AT91_DDRSDRC_TRRD       (0xf << 20)             /* Active BankA to BankB */
+#define                AT91_DDRSDRC_TWTR       (0x7 << 24)             /* Internal Write to Read delay */
+#define                AT91_DDRSDRC_RED_WRRD   (0x1 << 27)             /* Reduce Write to Read Delay [SAM9 Only] */
+#define                AT91_DDRSDRC_TMRD       (0xf << 28)             /* Load mode to active/refresh delay */
+
+#define AT91_DDRSDRC_T1PR      0x10    /* Timing 1 Register */
+#define                AT91_DDRSDRC_TRFC       (0x1f << 0)             /* Row Cycle Delay */
+#define                AT91_DDRSDRC_TXSNR      (0xff << 8)             /* Exit self-refresh to non-read */
+#define                AT91_DDRSDRC_TXSRD      (0xff << 16)            /* Exit self-refresh to read */
+#define                AT91_DDRSDRC_TXP        (0xf  << 24)            /* Exit power-down delay */
+
+#define AT91_DDRSDRC_T2PR      0x14    /* Timing 2 Register [SAM9 Only] */
+#define                AT91_DDRSDRC_TXARD      (0xf  << 0)             /* Exit active power down delay to read command in mode "Fast Exit" */
+#define                AT91_DDRSDRC_TXARDS     (0xf  << 4)             /* Exit active power down delay to read command in mode "Slow Exit" */
+#define                AT91_DDRSDRC_TRPA       (0xf  << 8)             /* Row Precharge All delay */
+#define                AT91_DDRSDRC_TRTP       (0x7  << 12)            /* Read to Precharge delay */
+
+#define AT91_DDRSDRC_LPR       0x1C    /* Low Power Register */
+#define                AT91_DDRSDRC_LPCB       (3 << 0)                /* Low-power Configurations */
+#define                        AT91_DDRSDRC_LPCB_DISABLE               0
+#define                        AT91_DDRSDRC_LPCB_SELF_REFRESH          1
+#define                        AT91_DDRSDRC_LPCB_POWER_DOWN            2
+#define                        AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN       3
+#define                AT91_DDRSDRC_CLKFR      (1 << 2)        /* Clock Frozen */
+#define                AT91_DDRSDRC_PASR       (7 << 4)        /* Partial Array Self Refresh */
+#define                AT91_DDRSDRC_TCSR       (3 << 8)        /* Temperature Compensated Self Refresh */
+#define                AT91_DDRSDRC_DS         (3 << 10)       /* Drive Strength */
+#define                AT91_DDRSDRC_TIMEOUT    (3 << 12)       /* Time to define when Low Power Mode is enabled */
+#define                        AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES       (0 << 12)
+#define                        AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES      (1 << 12)
+#define                        AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES     (2 << 12)
+#define                AT91_DDRSDRC_APDE       (1 << 16)        /* Active power down exit time */
+#define                AT91_DDRSDRC_UPD_MR     (3 << 20)        /* Update load mode register and extended mode register */
+
+#define AT91_DDRSDRC_MDR       0x20    /* Memory Device Register */
+#define                AT91_DDRSDRC_MD         (3 << 0)                /* Memory Device Type */
+#define                        AT91_DDRSDRC_MD_SDR             0
+#define                        AT91_DDRSDRC_MD_LOW_POWER_SDR   1
+#define                        AT91_DDRSDRC_MD_LOW_POWER_DDR   3
+#define                        AT91_DDRSDRC_MD_DDR2            6       /* [SAM9 Only] */
+#define                AT91_DDRSDRC_DBW        (1 << 4)                /* Data Bus Width */
+#define                        AT91_DDRSDRC_DBW_32BITS         (0 <<  4)
+#define                        AT91_DDRSDRC_DBW_16BITS         (1 <<  4)
+
+#define AT91_DDRSDRC_DLL       0x24    /* DLL Information Register */
+#define                AT91_DDRSDRC_MDINC      (1 << 0)                /* Master Delay increment */
+#define                AT91_DDRSDRC_MDDEC      (1 << 1)                /* Master Delay decrement */
+#define                AT91_DDRSDRC_MDOVF      (1 << 2)                /* Master Delay Overflow */
+#define                AT91_DDRSDRC_MDVAL      (0xff <<  8)            /* Master Delay value */
+
+#define AT91_DDRSDRC_HS                0x2C    /* High Speed Register [SAM9 Only] */
+#define                AT91_DDRSDRC_DIS_ATCP_RD        (1 << 2)        /* Anticip read access is disabled */
+
+#define AT91_DDRSDRC_DELAY(n)  (0x30 + (0x4 * (n)))    /* Delay I/O Register n */
+
+#define AT91_DDRSDRC_WPMR      0xE4    /* Write Protect Mode Register [SAM9 Only] */
+#define                AT91_DDRSDRC_WP         (1 << 0)                /* Write protect enable */
+#define                AT91_DDRSDRC_WPKEY      (0xffffff << 8)         /* Write protect key */
+#define                AT91_DDRSDRC_KEY        (0x444452 << 8)         /* Write protect key = "DDR" */
+
+#define AT91_DDRSDRC_WPSR      0xE8    /* Write Protect Status Register [SAM9 Only] */
+#define                AT91_DDRSDRC_WPVS       (1 << 0)                /* Write protect violation status */
+#define                AT91_DDRSDRC_WPVSRC     (0xffff << 8)           /* Write protect violation source */
+
+#endif
diff --git a/include/soc/at91/at91sam9_sdramc.h b/include/soc/at91/at91sam9_sdramc.h
new file mode 100644 (file)
index 0000000..3d085a9
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91sam9_sdramc.h
+ *
+ * Copyright (C) 2007 Andrew Victor
+ * Copyright (C) 2007 Atmel Corporation.
+ *
+ * SDRAM Controllers (SDRAMC) - 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 AT91SAM9_SDRAMC_H
+#define AT91SAM9_SDRAMC_H
+
+/* SDRAM Controller (SDRAMC) registers */
+#define AT91_SDRAMC_MR         0x00    /* SDRAM Controller Mode Register */
+#define                AT91_SDRAMC_MODE        (0xf << 0)              /* Command Mode */
+#define                        AT91_SDRAMC_MODE_NORMAL         0
+#define                        AT91_SDRAMC_MODE_NOP            1
+#define                        AT91_SDRAMC_MODE_PRECHARGE      2
+#define                        AT91_SDRAMC_MODE_LMR            3
+#define                        AT91_SDRAMC_MODE_REFRESH        4
+#define                        AT91_SDRAMC_MODE_EXT_LMR        5
+#define                        AT91_SDRAMC_MODE_DEEP           6
+
+#define AT91_SDRAMC_TR         0x04    /* SDRAM Controller Refresh Timer Register */
+#define                AT91_SDRAMC_COUNT       (0xfff << 0)            /* Refresh Timer Counter */
+
+#define AT91_SDRAMC_CR         0x08    /* SDRAM Controller Configuration Register */
+#define                AT91_SDRAMC_NC          (3 << 0)                /* Number of Column Bits */
+#define                        AT91_SDRAMC_NC_8        (0 << 0)
+#define                        AT91_SDRAMC_NC_9        (1 << 0)
+#define                        AT91_SDRAMC_NC_10       (2 << 0)
+#define                        AT91_SDRAMC_NC_11       (3 << 0)
+#define                AT91_SDRAMC_NR          (3 << 2)                /* Number of Row Bits */
+#define                        AT91_SDRAMC_NR_11       (0 << 2)
+#define                        AT91_SDRAMC_NR_12       (1 << 2)
+#define                        AT91_SDRAMC_NR_13       (2 << 2)
+#define                AT91_SDRAMC_NB          (1 << 4)                /* Number of Banks */
+#define                        AT91_SDRAMC_NB_2        (0 << 4)
+#define                        AT91_SDRAMC_NB_4        (1 << 4)
+#define                AT91_SDRAMC_CAS         (3 << 5)                /* CAS Latency */
+#define                        AT91_SDRAMC_CAS_1       (1 << 5)
+#define                        AT91_SDRAMC_CAS_2       (2 << 5)
+#define                        AT91_SDRAMC_CAS_3       (3 << 5)
+#define                AT91_SDRAMC_DBW         (1 << 7)                /* Data Bus Width */
+#define                        AT91_SDRAMC_DBW_32      (0 << 7)
+#define                        AT91_SDRAMC_DBW_16      (1 << 7)
+#define                AT91_SDRAMC_TWR         (0xf <<  8)             /* Write Recovery Delay */
+#define                AT91_SDRAMC_TRC         (0xf << 12)             /* Row Cycle Delay */
+#define                AT91_SDRAMC_TRP         (0xf << 16)             /* Row Precharge Delay */
+#define                AT91_SDRAMC_TRCD        (0xf << 20)             /* Row to Column Delay */
+#define                AT91_SDRAMC_TRAS        (0xf << 24)             /* Active to Precharge Delay */
+#define                AT91_SDRAMC_TXSR        (0xf << 28)             /* Exit Self Refresh to Active Delay */
+
+#define AT91_SDRAMC_LPR                0x10    /* SDRAM Controller Low Power Register */
+#define                AT91_SDRAMC_LPCB                (3 << 0)        /* Low-power Configurations */
+#define                        AT91_SDRAMC_LPCB_DISABLE                0
+#define                        AT91_SDRAMC_LPCB_SELF_REFRESH           1
+#define                        AT91_SDRAMC_LPCB_POWER_DOWN             2
+#define                        AT91_SDRAMC_LPCB_DEEP_POWER_DOWN        3
+#define                AT91_SDRAMC_PASR                (7 << 4)        /* Partial Array Self Refresh */
+#define                AT91_SDRAMC_TCSR                (3 << 8)        /* Temperature Compensated Self Refresh */
+#define                AT91_SDRAMC_DS                  (3 << 10)       /* Drive Strength */
+#define                AT91_SDRAMC_TIMEOUT             (3 << 12)       /* Time to define when Low Power Mode is enabled */
+#define                        AT91_SDRAMC_TIMEOUT_0_CLK_CYCLES        (0 << 12)
+#define                        AT91_SDRAMC_TIMEOUT_64_CLK_CYCLES       (1 << 12)
+#define                        AT91_SDRAMC_TIMEOUT_128_CLK_CYCLES      (2 << 12)
+
+#define AT91_SDRAMC_IER                0x14    /* SDRAM Controller Interrupt Enable Register */
+#define AT91_SDRAMC_IDR                0x18    /* SDRAM Controller Interrupt Disable Register */
+#define AT91_SDRAMC_IMR                0x1C    /* SDRAM Controller Interrupt Mask Register */
+#define AT91_SDRAMC_ISR                0x20    /* SDRAM Controller Interrupt Status Register */
+#define                AT91_SDRAMC_RES         (1 << 0)                /* Refresh Error Status */
+
+#define AT91_SDRAMC_MDR                0x24    /* SDRAM Memory Device Register */
+#define                AT91_SDRAMC_MD          (3 << 0)                /* Memory Device Type */
+#define                        AT91_SDRAMC_MD_SDRAM            0
+#define                        AT91_SDRAMC_MD_LOW_POWER_SDRAM  1
+
+#endif
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
new file mode 100644 (file)
index 0000000..63deb8d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2014 NVIDIA 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 __SOC_TEGRA_MC_H__
+#define __SOC_TEGRA_MC_H__
+
+#include <linux/types.h>
+
+struct clk;
+struct device;
+struct page;
+
+struct tegra_smmu_enable {
+       unsigned int reg;
+       unsigned int bit;
+};
+
+/* latency allowance */
+struct tegra_mc_la {
+       unsigned int reg;
+       unsigned int shift;
+       unsigned int mask;
+       unsigned int def;
+};
+
+struct tegra_mc_client {
+       unsigned int id;
+       const char *name;
+       unsigned int swgroup;
+
+       unsigned int fifo_size;
+
+       struct tegra_smmu_enable smmu;
+       struct tegra_mc_la la;
+};
+
+struct tegra_smmu_swgroup {
+       unsigned int swgroup;
+       unsigned int reg;
+};
+
+struct tegra_smmu_ops {
+       void (*flush_dcache)(struct page *page, unsigned long offset,
+                            size_t size);
+};
+
+struct tegra_smmu_soc {
+       const struct tegra_mc_client *clients;
+       unsigned int num_clients;
+
+       const struct tegra_smmu_swgroup *swgroups;
+       unsigned int num_swgroups;
+
+       bool supports_round_robin_arbitration;
+       bool supports_request_limit;
+
+       unsigned int num_asids;
+
+       const struct tegra_smmu_ops *ops;
+};
+
+struct tegra_mc;
+struct tegra_smmu;
+
+#ifdef CONFIG_TEGRA_IOMMU_SMMU
+struct tegra_smmu *tegra_smmu_probe(struct device *dev,
+                                   const struct tegra_smmu_soc *soc,
+                                   struct tegra_mc *mc);
+#else
+static inline struct tegra_smmu *
+tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc,
+                struct tegra_mc *mc)
+{
+       return NULL;
+}
+#endif
+
+struct tegra_mc_soc {
+       const struct tegra_mc_client *clients;
+       unsigned int num_clients;
+
+       const unsigned int *emem_regs;
+       unsigned int num_emem_regs;
+
+       unsigned int num_address_bits;
+       unsigned int atom_size;
+
+       const struct tegra_smmu_soc *smmu;
+};
+
+struct tegra_mc {
+       struct device *dev;
+       struct tegra_smmu *smmu;
+       void __iomem *regs;
+       struct clk *clk;
+       int irq;
+
+       const struct tegra_mc_soc *soc;
+       unsigned long tick;
+};
+
+#endif /* __SOC_TEGRA_MC_H__ */
index e862497f75568d11cd4deb4f5f5a06712f63d6de..8bb00a27e219e902c9bdc2ac52f0a7c3ed53f005 100644 (file)
@@ -184,6 +184,8 @@ struct snd_pcm_ops {
 #define SNDRV_PCM_FMTBIT_DSD_U8                _SNDRV_PCM_FMTBIT(DSD_U8)
 #define SNDRV_PCM_FMTBIT_DSD_U16_LE    _SNDRV_PCM_FMTBIT(DSD_U16_LE)
 #define SNDRV_PCM_FMTBIT_DSD_U32_LE    _SNDRV_PCM_FMTBIT(DSD_U32_LE)
+#define SNDRV_PCM_FMTBIT_DSD_U16_BE    _SNDRV_PCM_FMTBIT(DSD_U16_BE)
+#define SNDRV_PCM_FMTBIT_DSD_U32_BE    _SNDRV_PCM_FMTBIT(DSD_U32_BE)
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #define SNDRV_PCM_FMTBIT_S16           SNDRV_PCM_FMTBIT_S16_LE
index 2883a7a6f9f3a932b38843d20a8887986804fc00..98f2ade0266eb9a28ae6340b2908bd8fabea0eca 100644 (file)
@@ -102,6 +102,8 @@ struct snd_soc_dpcm_runtime {
        /* state and update */
        enum snd_soc_dpcm_update runtime_update;
        enum snd_soc_dpcm_state state;
+
+       int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */
 };
 
 /* can this BE stop and free */
index 9ec9864ecf38629469ef0823baf153c33fb09472..23c518a0340c095f46fc94742bf8a033798f07fc 100644 (file)
 #define DA_EMULATE_ALUA                                0
 /* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
 #define DA_ENFORCE_PR_ISIDS                    1
+/* Force SPC-3 PR Activate Persistence across Target Power Loss */
+#define DA_FORCE_PR_APTPL                      0
 #define DA_STATUS_MAX_SECTORS_MIN              16
 #define DA_STATUS_MAX_SECTORS_MAX              8192
 /* By default don't report non-rotating (solid state) medium */
@@ -680,6 +682,7 @@ struct se_dev_attrib {
        enum target_prot_type pi_prot_type;
        enum target_prot_type hw_pi_prot_type;
        int             enforce_pr_isids;
+       int             force_pr_aptpl;
        int             is_nonrot;
        int             emulate_rest_reord;
        u32             hw_block_size;
@@ -903,4 +906,18 @@ struct se_wwn {
        struct config_group     fabric_stat_group;
 };
 
+static inline void atomic_inc_mb(atomic_t *v)
+{
+       smp_mb__before_atomic();
+       atomic_inc(v);
+       smp_mb__after_atomic();
+}
+
+static inline void atomic_dec_mb(atomic_t *v)
+{
+       smp_mb__before_atomic();
+       atomic_dec(v);
+       smp_mb__after_atomic();
+}
+
 #endif /* TARGET_CORE_BASE_H */
index d4f70a7fe8761a73e7128964e83b29f7809bd4e9..ff4bd1b35246a33482b997d2093dbedbe6079357 100644 (file)
@@ -2369,7 +2369,7 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
                  show_extent_status(__entry->found ? __entry->status : 0))
 );
 
-TRACE_EVENT(ext4_es_shrink_enter,
+DECLARE_EVENT_CLASS(ext4__es_shrink_enter,
        TP_PROTO(struct super_block *sb, int nr_to_scan, int cache_cnt),
 
        TP_ARGS(sb, nr_to_scan, cache_cnt),
@@ -2391,26 +2391,38 @@ TRACE_EVENT(ext4_es_shrink_enter,
                  __entry->nr_to_scan, __entry->cache_cnt)
 );
 
-TRACE_EVENT(ext4_es_shrink_exit,
-       TP_PROTO(struct super_block *sb, int shrunk_nr, int cache_cnt),
+DEFINE_EVENT(ext4__es_shrink_enter, ext4_es_shrink_count,
+       TP_PROTO(struct super_block *sb, int nr_to_scan, int cache_cnt),
 
-       TP_ARGS(sb, shrunk_nr, cache_cnt),
+       TP_ARGS(sb, nr_to_scan, cache_cnt)
+);
+
+DEFINE_EVENT(ext4__es_shrink_enter, ext4_es_shrink_scan_enter,
+       TP_PROTO(struct super_block *sb, int nr_to_scan, int cache_cnt),
+
+       TP_ARGS(sb, nr_to_scan, cache_cnt)
+);
+
+TRACE_EVENT(ext4_es_shrink_scan_exit,
+       TP_PROTO(struct super_block *sb, int nr_shrunk, int cache_cnt),
+
+       TP_ARGS(sb, nr_shrunk, cache_cnt),
 
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
-               __field(        int,    shrunk_nr               )
+               __field(        int,    nr_shrunk               )
                __field(        int,    cache_cnt               )
        ),
 
        TP_fast_assign(
                __entry->dev            = sb->s_dev;
-               __entry->shrunk_nr      = shrunk_nr;
+               __entry->nr_shrunk      = nr_shrunk;
                __entry->cache_cnt      = cache_cnt;
        ),
 
-       TP_printk("dev %d,%d shrunk_nr %d cache_cnt %d",
+       TP_printk("dev %d,%d nr_shrunk %d cache_cnt %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
-                 __entry->shrunk_nr, __entry->cache_cnt)
+                 __entry->nr_shrunk, __entry->cache_cnt)
 );
 
 TRACE_EVENT(ext4_collapse_range,
@@ -2438,6 +2450,37 @@ TRACE_EVENT(ext4_collapse_range,
                  __entry->offset, __entry->len)
 );
 
+TRACE_EVENT(ext4_es_shrink,
+       TP_PROTO(struct super_block *sb, int nr_shrunk, u64 scan_time,
+                int skip_precached, int nr_skipped, int retried),
+
+       TP_ARGS(sb, nr_shrunk, scan_time, skip_precached, nr_skipped, retried),
+
+       TP_STRUCT__entry(
+               __field(        dev_t,          dev             )
+               __field(        int,            nr_shrunk       )
+               __field(        unsigned long long, scan_time   )
+               __field(        int,            skip_precached  )
+               __field(        int,            nr_skipped      )
+               __field(        int,            retried         )
+       ),
+
+       TP_fast_assign(
+               __entry->dev            = sb->s_dev;
+               __entry->nr_shrunk      = nr_shrunk;
+               __entry->scan_time      = div_u64(scan_time, 1000);
+               __entry->skip_precached = skip_precached;
+               __entry->nr_skipped     = nr_skipped;
+               __entry->retried        = retried;
+       ),
+
+       TP_printk("dev %d,%d nr_shrunk %d, scan_time %llu skip_precached %d "
+                 "nr_skipped %d retried %d",
+                 MAJOR(__entry->dev), MINOR(__entry->dev), __entry->nr_shrunk,
+                 __entry->scan_time, __entry->skip_precached,
+                 __entry->nr_skipped, __entry->retried)
+);
+
 #endif /* _TRACE_EXT4_H */
 
 /* This part must be outside protection */
index 9b56f37148cfd91d57b849f88c8b1279220aa41a..c78e88ce5ea30bd85a70f8f7aef3378f4506f90d 100644 (file)
@@ -36,7 +36,7 @@ TRACE_EVENT(rcu_utilization,
 
 #ifdef CONFIG_RCU_TRACE
 
-#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
+#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
 
 /*
  * Tracepoint for grace-period events.  Takes a string identifying the
@@ -345,7 +345,7 @@ TRACE_EVENT(rcu_fqs,
                  __entry->cpu, __entry->qsevent)
 );
 
-#endif /* #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) */
+#endif /* #if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU) */
 
 /*
  * Tracepoint for dyntick-idle entry/exit events.  These take a string
@@ -660,18 +660,18 @@ TRACE_EVENT(rcu_torture_read,
 /*
  * Tracepoint for _rcu_barrier() execution.  The string "s" describes
  * the _rcu_barrier phase:
- *     "Begin": rcu_barrier_callback() started.
- *     "Check": rcu_barrier_callback() checking for piggybacking.
- *     "EarlyExit": rcu_barrier_callback() piggybacked, thus early exit.
- *     "Inc1": rcu_barrier_callback() piggyback check counter incremented.
- *     "Offline": rcu_barrier_callback() found offline CPU
- *     "OnlineNoCB": rcu_barrier_callback() found online no-CBs CPU.
- *     "OnlineQ": rcu_barrier_callback() found online CPU with callbacks.
- *     "OnlineNQ": rcu_barrier_callback() found online CPU, no callbacks.
+ *     "Begin": _rcu_barrier() started.
+ *     "Check": _rcu_barrier() checking for piggybacking.
+ *     "EarlyExit": _rcu_barrier() piggybacked, thus early exit.
+ *     "Inc1": _rcu_barrier() piggyback check counter incremented.
+ *     "OfflineNoCB": _rcu_barrier() found callback on never-online CPU
+ *     "OnlineNoCB": _rcu_barrier() found online no-CBs CPU.
+ *     "OnlineQ": _rcu_barrier() found online CPU with callbacks.
+ *     "OnlineNQ": _rcu_barrier() found online CPU, no callbacks.
  *     "IRQ": An rcu_barrier_callback() callback posted on remote CPU.
  *     "CB": An rcu_barrier_callback() invoked a callback, not the last.
  *     "LastCB": An rcu_barrier_callback() invoked the last callback.
- *     "Inc2": rcu_barrier_callback() piggyback check counter incremented.
+ *     "Inc2": _rcu_barrier() piggyback check counter incremented.
  * The "cpu" argument is the CPU or -1 if meaningless, the "cnt" argument
  * is the count of remaining callbacks, and "done" is the piggybacking count.
  */
index 0a68d5ae584e9dfada372fdae49c5d0934176402..30fedaf3e56a253175619fbef7a9f9a1f6dc15a3 100644 (file)
@@ -97,16 +97,19 @@ static inline long __trace_sched_switch_state(struct task_struct *p)
        long state = p->state;
 
 #ifdef CONFIG_PREEMPT
+#ifdef CONFIG_SCHED_DEBUG
+       BUG_ON(p != current);
+#endif /* CONFIG_SCHED_DEBUG */
        /*
         * For all intents and purposes a preempted task is a running task.
         */
-       if (task_preempt_count(p) & PREEMPT_ACTIVE)
+       if (preempt_count() & PREEMPT_ACTIVE)
                state = TASK_RUNNING | TASK_STATE_MAX;
-#endif
+#endif /* CONFIG_PREEMPT */
 
        return state;
 }
-#endif
+#endif /* CREATE_TRACE_POINTS */
 
 /*
  * Tracepoint for task switches, performed by the scheduler:
index db6c93510f74633fc032a2984a8624e36070b2bb..079bd10a01b4b3b2b1897cc281cbdb6fde605181 100644 (file)
@@ -94,7 +94,7 @@
                scsi_opcode_name(WRITE_16),                     \
                scsi_opcode_name(VERIFY_16),                    \
                scsi_opcode_name(WRITE_SAME_16),                \
-               scsi_opcode_name(SERVICE_ACTION_IN),            \
+               scsi_opcode_name(SERVICE_ACTION_IN_16),         \
                scsi_opcode_name(SAI_READ_CAPACITY_16),         \
                scsi_opcode_name(SAI_GET_LBA_STATUS),           \
                scsi_opcode_name(MI_REPORT_TARGET_PGS),         \
index da9cc0f05c93843e713923fc1b5d063e7d444cae..45403443dd82ed3ae3ae07813db72bda164c0de5 100644 (file)
@@ -96,7 +96,7 @@
                scsi_opcode_name(WRITE_16),                     \
                scsi_opcode_name(VERIFY_16),                    \
                scsi_opcode_name(WRITE_SAME_16),                \
-               scsi_opcode_name(SERVICE_ACTION_IN),            \
+               scsi_opcode_name(SERVICE_ACTION_IN_16),         \
                scsi_opcode_name(SAI_READ_CAPACITY_16),         \
                scsi_opcode_name(SAI_GET_LBA_STATUS),           \
                scsi_opcode_name(MI_REPORT_TARGET_PGS),         \
diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h
new file mode 100644 (file)
index 0000000..0f4f95d
--- /dev/null
@@ -0,0 +1,83 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM thermal
+
+#if !defined(_TRACE_THERMAL_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_THERMAL_H
+
+#include <linux/thermal.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(thermal_temperature,
+
+       TP_PROTO(struct thermal_zone_device *tz),
+
+       TP_ARGS(tz),
+
+       TP_STRUCT__entry(
+               __string(thermal_zone, tz->type)
+               __field(int, id)
+               __field(int, temp_prev)
+               __field(int, temp)
+       ),
+
+       TP_fast_assign(
+               __assign_str(thermal_zone, tz->type);
+               __entry->id = tz->id;
+               __entry->temp_prev = tz->last_temperature;
+               __entry->temp = tz->temperature;
+       ),
+
+       TP_printk("thermal_zone=%s id=%d temp_prev=%d temp=%d",
+               __get_str(thermal_zone), __entry->id, __entry->temp_prev,
+               __entry->temp)
+);
+
+TRACE_EVENT(cdev_update,
+
+       TP_PROTO(struct thermal_cooling_device *cdev, unsigned long target),
+
+       TP_ARGS(cdev, target),
+
+       TP_STRUCT__entry(
+               __string(type, cdev->type)
+               __field(unsigned long, target)
+       ),
+
+       TP_fast_assign(
+               __assign_str(type, cdev->type);
+               __entry->target = target;
+       ),
+
+       TP_printk("type=%s target=%lu", __get_str(type), __entry->target)
+);
+
+TRACE_EVENT(thermal_zone_trip,
+
+       TP_PROTO(struct thermal_zone_device *tz, int trip,
+               enum thermal_trip_type trip_type),
+
+       TP_ARGS(tz, trip, trip_type),
+
+       TP_STRUCT__entry(
+               __string(thermal_zone, tz->type)
+               __field(int, id)
+               __field(int, trip)
+               __field(enum thermal_trip_type, trip_type)
+       ),
+
+       TP_fast_assign(
+               __assign_str(thermal_zone, tz->type);
+               __entry->id = tz->id;
+               __entry->trip = trip;
+               __entry->trip_type = trip_type;
+       ),
+
+       TP_printk("thermal_zone=%s id=%d trip=%d trip_type=%d",
+               __get_str(thermal_zone), __entry->id, __entry->trip,
+               __entry->trip_type)
+);
+
+#endif /* _TRACE_THERMAL_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 6cad97485bad7fd5803f2f48aa1d8c1894208be1..8523f9bb72f2d0039963078d765084ee5dfdf155 100644 (file)
@@ -125,6 +125,7 @@ header-y += filter.h
 header-y += firewire-cdev.h
 header-y += firewire-constants.h
 header-y += flat.h
+header-y += fou.h
 header-y += fs.h
 header-y += fsl_hypervisor.h
 header-y += fuse.h
@@ -141,6 +142,7 @@ header-y += hid.h
 header-y += hiddev.h
 header-y += hidraw.h
 header-y += hpet.h
+header-y += hsr_netlink.h
 header-y += hyperv.h
 header-y += hysdn_if.h
 header-y += i2c-dev.h
@@ -251,6 +253,7 @@ header-y += mii.h
 header-y += minix_fs.h
 header-y += mman.h
 header-y += mmtimer.h
+header-y += mpls.h
 header-y += mqueue.h
 header-y += mroute.h
 header-y += mroute6.h
@@ -374,6 +377,7 @@ header-y += swab.h
 header-y += synclink.h
 header-y += sysctl.h
 header-y += sysinfo.h
+header-y += target_core_user.h
 header-y += taskstats.h
 header-y += tcp.h
 header-y += tcp_metrics.h
@@ -423,6 +427,7 @@ header-y += virtio_net.h
 header-y += virtio_pci.h
 header-y += virtio_ring.h
 header-y += virtio_rng.h
+header-y += vm_sockets.h
 header-y += vt.h
 header-y += wait.h
 header-y += wanrouter.h
index 3315ab21f7285dcfb218214a2f099949efe85005..a570d7b5796c58950ad3528a0f1b7eded09f234c 100644 (file)
@@ -267,9 +267,9 @@ enum {
 #define DM_DEV_SET_GEOMETRY    _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR       4
-#define DM_VERSION_MINOR       28
+#define DM_VERSION_MINOR       29
 #define DM_VERSION_PATCHLEVEL  0
-#define DM_VERSION_EXTRA       "-ioctl (2014-09-17)"
+#define DM_VERSION_EXTRA       "-ioctl (2014-10-28)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
@@ -352,4 +352,9 @@ enum {
  */
 #define DM_DEFERRED_REMOVE             (1 << 17) /* In/Out */
 
+/*
+ * If set, the device is suspended internally.
+ */
+#define DM_INTERNAL_SUSPEND_FLAG       (1 << 18) /* Out */
+
 #endif                         /* _LINUX_DM_IOCTL_H */
index aa90bc98b6e2b7e9c031cdf55b3521007a07860f..ae99f7743cf4886fc68f4af6a4fc24b4743366d2 100644 (file)
@@ -34,6 +34,7 @@
 #define EM_MN10300     89      /* Panasonic/MEI MN10300, AM33 */
 #define EM_OPENRISC     92     /* OpenRISC 32-bit embedded processor */
 #define EM_BLACKFIN     106     /* ADI Blackfin Processor */
+#define EM_ALTERA_NIOS2        113     /* Altera Nios II soft-core processor */
 #define EM_TI_C6000    140     /* TI C6X DSPs */
 #define EM_AARCH64     183     /* ARM 64 bit */
 #define EM_FRV         0x5441  /* Fujitsu FR-V */
index ea9bf2561b9efecb236959de88e57c94f96037fb..71e1d0ed92f73f40c1393e1d38d2588df97f5696 100644 (file)
@@ -397,6 +397,7 @@ typedef struct elf64_shdr {
 #define NT_ARM_TLS     0x401           /* ARM TLS register */
 #define NT_ARM_HW_BREAK        0x402           /* ARM hardware breakpoint registers */
 #define NT_ARM_HW_WATCH        0x403           /* ARM hardware watchpoint registers */
+#define NT_ARM_SYSTEM_CALL     0x404   /* ARM system call number */
 #define NT_METAG_CBUF  0x500           /* Metag catch buffer registers */
 #define NT_METAG_RPIPE 0x501           /* Metag read pipeline state */
 #define NT_METAG_TLS   0x502           /* Metag TLS pointer */
index ca1a11bb4443a7f09c3e4b9228c48a346eadce1c..3735fa0a67840ba1882fd42b343c01550a540944 100644 (file)
@@ -37,6 +37,7 @@
 
 #define RENAME_NOREPLACE       (1 << 0)        /* Don't overwrite target */
 #define RENAME_EXCHANGE                (1 << 1)        /* Exchange source and dest */
+#define RENAME_WHITEOUT                (1 << 2)        /* Whiteout source */
 
 struct fstrim_range {
        __u64 start;
index 39f621a9fe826cb9a0eab487cd36a51aed5440ab..da17e456908d2d16d1500499858296a042b3186c 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/types.h>
 #include <linux/if_ether.h>
+#include <linux/in6.h>
 
 #define SYSFS_BRIDGE_ATTR      "bridge"
 #define SYSFS_BRIDGE_FDB       "brforward"
index 1874ebe9ac1e505b0215a90f03a9b2ce57f6b2ff..a1d7e931ab72cdfb93db7f434275492d99aca77d 100644 (file)
@@ -739,6 +739,13 @@ struct input_keymap_entry {
 #define KEY_BRIGHTNESS_MIN             0x250   /* Set Brightness to Minimum */
 #define KEY_BRIGHTNESS_MAX             0x251   /* Set Brightness to Maximum */
 
+#define KEY_KBDINPUTASSIST_PREV                0x260
+#define KEY_KBDINPUTASSIST_NEXT                0x261
+#define KEY_KBDINPUTASSIST_PREVGROUP           0x262
+#define KEY_KBDINPUTASSIST_NEXTGROUP           0x263
+#define KEY_KBDINPUTASSIST_ACCEPT              0x264
+#define KEY_KBDINPUTASSIST_CANCEL              0x265
+
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
 #define BTN_TRIGGER_HAPPY2             0x2c1
index 9269de254874237c71b61713ee4bc9dc7a6aabe5..9b79abbd1ab80f765eb15b2d563f2c30262327d2 100644 (file)
@@ -137,8 +137,9 @@ enum perf_event_sample_format {
        PERF_SAMPLE_DATA_SRC                    = 1U << 15,
        PERF_SAMPLE_IDENTIFIER                  = 1U << 16,
        PERF_SAMPLE_TRANSACTION                 = 1U << 17,
+       PERF_SAMPLE_REGS_INTR                   = 1U << 18,
 
-       PERF_SAMPLE_MAX = 1U << 18,             /* non-ABI */
+       PERF_SAMPLE_MAX = 1U << 19,             /* non-ABI */
 };
 
 /*
@@ -238,6 +239,7 @@ enum perf_event_read_format {
 #define PERF_ATTR_SIZE_VER2    80      /* add: branch_sample_type */
 #define PERF_ATTR_SIZE_VER3    96      /* add: sample_regs_user */
                                        /* add: sample_stack_user */
+#define PERF_ATTR_SIZE_VER4    104     /* add: sample_regs_intr */
 
 /*
  * Hardware event_id to monitor via a performance monitoring event:
@@ -334,6 +336,15 @@ struct perf_event_attr {
 
        /* Align to u64. */
        __u32   __reserved_2;
+       /*
+        * Defines set of regs to dump for each sample
+        * state captured on:
+        *  - precise = 0: PMU interrupt
+        *  - precise > 0: sampled instruction
+        *
+        * See asm/perf_regs.h for details.
+        */
+       __u64   sample_regs_intr;
 };
 
 #define perf_flags(attr)       (*(&(attr)->read_format + 1))
@@ -364,7 +375,7 @@ struct perf_event_mmap_page {
        /*
         * Bits needed to read the hw events in user-space.
         *
-        *   u32 seq, time_mult, time_shift, idx, width;
+        *   u32 seq, time_mult, time_shift, index, width;
         *   u64 count, enabled, running;
         *   u64 cyc, time_offset;
         *   s64 pmc = 0;
@@ -383,11 +394,11 @@ struct perf_event_mmap_page {
         *       time_shift  = pc->time_shift;
         *     }
         *
-        *     idx = pc->index;
+        *     index = pc->index;
         *     count = pc->offset;
-        *     if (pc->cap_usr_rdpmc && idx) {
+        *     if (pc->cap_user_rdpmc && index) {
         *       width = pc->pmc_width;
-        *       pmc = rdpmc(idx - 1);
+        *       pmc = rdpmc(index - 1);
         *     }
         *
         *     barrier();
@@ -415,7 +426,7 @@ struct perf_event_mmap_page {
        };
 
        /*
-        * If cap_usr_rdpmc this field provides the bit-width of the value
+        * If cap_user_rdpmc this field provides the bit-width of the value
         * read using the rdpmc() or equivalent instruction. This can be used
         * to sign extend the result like:
         *
@@ -439,10 +450,10 @@ struct perf_event_mmap_page {
         *
         * Where time_offset,time_mult,time_shift and cyc are read in the
         * seqcount loop described above. This delta can then be added to
-        * enabled and possible running (if idx), improving the scaling:
+        * enabled and possible running (if index), improving the scaling:
         *
         *   enabled += delta;
-        *   if (idx)
+        *   if (index)
         *     running += delta;
         *
         *   quot = count / running;
@@ -686,6 +697,8 @@ enum perf_event_type {
         *      { u64                   weight;   } && PERF_SAMPLE_WEIGHT
         *      { u64                   data_src; } && PERF_SAMPLE_DATA_SRC
         *      { u64                   transaction; } && PERF_SAMPLE_TRANSACTION
+        *      { u64                   abi; # enum perf_sample_regs_abi
+        *        u64                   regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
         * };
         */
        PERF_RECORD_SAMPLE                      = 9,
index 34f9d7387d134a12923669e3516ad2892a41f84d..cc89ddefa926b4bc9f04164e4418863f20bda12e 100644 (file)
@@ -13,7 +13,7 @@
 #define CLONE_VFORK    0x00004000      /* set if the parent wants the child to wake it up on mm_release */
 #define CLONE_PARENT   0x00008000      /* set if we want to have the same parent as the cloner */
 #define CLONE_THREAD   0x00010000      /* Same thread group? */
-#define CLONE_NEWNS    0x00020000      /* New namespace group? */
+#define CLONE_NEWNS    0x00020000      /* New mount namespace group */
 #define CLONE_SYSVSEM  0x00040000      /* share system V SEM_UNDO semantics */
 #define CLONE_SETTLS   0x00080000      /* create a new TLS for the child */
 #define CLONE_PARENT_SETTID    0x00100000      /* set the TID in the parent */
@@ -23,8 +23,8 @@
 #define CLONE_CHILD_SETTID     0x01000000      /* set the TID in the child */
 /* 0x02000000 was previously the unused CLONE_STOPPED (Start in stopped state)
    and is now available for re-use. */
-#define CLONE_NEWUTS           0x04000000      /* New utsname group? */
-#define CLONE_NEWIPC           0x08000000      /* New ipcs */
+#define CLONE_NEWUTS           0x04000000      /* New utsname namespace */
+#define CLONE_NEWIPC           0x08000000      /* New ipc namespace */
 #define CLONE_NEWUSER          0x10000000      /* New user namespace */
 #define CLONE_NEWPID           0x20000000      /* New pid namespace */
 #define CLONE_NEWNET           0x40000000      /* New network namespace */
diff --git a/include/uapi/linux/target_core_user.h b/include/uapi/linux/target_core_user.h
new file mode 100644 (file)
index 0000000..7dcfbe6
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef __TARGET_CORE_USER_H
+#define __TARGET_CORE_USER_H
+
+/* This header will be used by application too */
+
+#include <linux/types.h>
+#include <linux/uio.h>
+
+#ifndef __packed
+#define __packed                        __attribute__((packed))
+#endif
+
+#define TCMU_VERSION "1.0"
+
+/*
+ * Ring Design
+ * -----------
+ *
+ * The mmaped area is divided into three parts:
+ * 1) The mailbox (struct tcmu_mailbox, below)
+ * 2) The command ring
+ * 3) Everything beyond the command ring (data)
+ *
+ * The mailbox tells userspace the offset of the command ring from the
+ * start of the shared memory region, and how big the command ring is.
+ *
+ * The kernel passes SCSI commands to userspace by putting a struct
+ * tcmu_cmd_entry in the ring, updating mailbox->cmd_head, and poking
+ * userspace via uio's interrupt mechanism.
+ *
+ * tcmu_cmd_entry contains a header. If the header type is PAD,
+ * userspace should skip hdr->length bytes (mod cmdr_size) to find the
+ * next cmd_entry.
+ *
+ * Otherwise, the entry will contain offsets into the mmaped area that
+ * contain the cdb and data buffers -- the latter accessible via the
+ * iov array. iov addresses are also offsets into the shared area.
+ *
+ * When userspace is completed handling the command, set
+ * entry->rsp.scsi_status, fill in rsp.sense_buffer if appropriate,
+ * and also set mailbox->cmd_tail equal to the old cmd_tail plus
+ * hdr->length, mod cmdr_size. If cmd_tail doesn't equal cmd_head, it
+ * should process the next packet the same way, and so on.
+ */
+
+#define TCMU_MAILBOX_VERSION 1
+#define ALIGN_SIZE 64 /* Should be enough for most CPUs */
+
+struct tcmu_mailbox {
+       __u16 version;
+       __u16 flags;
+       __u32 cmdr_off;
+       __u32 cmdr_size;
+
+       __u32 cmd_head;
+
+       /* Updated by user. On its own cacheline */
+       __u32 cmd_tail __attribute__((__aligned__(ALIGN_SIZE)));
+
+} __packed;
+
+enum tcmu_opcode {
+       TCMU_OP_PAD = 0,
+       TCMU_OP_CMD,
+};
+
+/*
+ * Only a few opcodes, and length is 8-byte aligned, so use low bits for opcode.
+ */
+struct tcmu_cmd_entry_hdr {
+               __u32 len_op;
+} __packed;
+
+#define TCMU_OP_MASK 0x7
+
+static inline enum tcmu_opcode tcmu_hdr_get_op(struct tcmu_cmd_entry_hdr *hdr)
+{
+       return hdr->len_op & TCMU_OP_MASK;
+}
+
+static inline void tcmu_hdr_set_op(struct tcmu_cmd_entry_hdr *hdr, enum tcmu_opcode op)
+{
+       hdr->len_op &= ~TCMU_OP_MASK;
+       hdr->len_op |= (op & TCMU_OP_MASK);
+}
+
+static inline __u32 tcmu_hdr_get_len(struct tcmu_cmd_entry_hdr *hdr)
+{
+       return hdr->len_op & ~TCMU_OP_MASK;
+}
+
+static inline void tcmu_hdr_set_len(struct tcmu_cmd_entry_hdr *hdr, __u32 len)
+{
+       hdr->len_op &= TCMU_OP_MASK;
+       hdr->len_op |= len;
+}
+
+/* Currently the same as SCSI_SENSE_BUFFERSIZE */
+#define TCMU_SENSE_BUFFERSIZE 96
+
+struct tcmu_cmd_entry {
+       struct tcmu_cmd_entry_hdr hdr;
+
+       uint16_t cmd_id;
+       uint16_t __pad1;
+
+       union {
+               struct {
+                       uint64_t cdb_off;
+                       uint64_t iov_cnt;
+                       struct iovec iov[0];
+               } req;
+               struct {
+                       uint8_t scsi_status;
+                       uint8_t __pad1;
+                       uint16_t __pad2;
+                       uint32_t __pad3;
+                       char sense_buffer[TCMU_SENSE_BUFFERSIZE];
+               } rsp;
+       };
+
+} __packed;
+
+#define TCMU_OP_ALIGN_SIZE sizeof(uint64_t)
+
+enum tcmu_genl_cmd {
+       TCMU_CMD_UNSPEC,
+       TCMU_CMD_ADDED_DEVICE,
+       TCMU_CMD_REMOVED_DEVICE,
+       __TCMU_CMD_MAX,
+};
+#define TCMU_CMD_MAX (__TCMU_CMD_MAX - 1)
+
+enum tcmu_genl_attr {
+       TCMU_ATTR_UNSPEC,
+       TCMU_ATTR_DEVICE,
+       TCMU_ATTR_MINOR,
+       __TCMU_ATTR_MAX,
+};
+#define TCMU_ATTR_MAX (__TCMU_ATTR_MAX - 1)
+
+#endif
index 6a0764c89fcbeaf29cee9bf5dcba996ed9bc3c98..6c8f159e416eea1b2781b4e00139b4b3afe2ea9a 100644 (file)
 #ifndef _V4L2_DV_TIMINGS_H
 #define _V4L2_DV_TIMINGS_H
 
+#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 6))
+/* Sadly gcc versions older than 4.6 have a bug in how they initialize
+   anonymous unions where they require additional curly brackets.
+   This violates the C1x standard. This workaround adds the curly brackets
+   if needed. */
 #define V4L2_INIT_BT_TIMINGS(_width, args...) \
        { .bt = { _width , ## args } }
+#else
+#define V4L2_INIT_BT_TIMINGS(_width, args...) \
+       .bt = { _width , ## args }
+#endif
 
 /* CEA-861-E timings (i.e. standard HDTV timings) */
 
index 6ee586728df97a0fc335a3c314e0828ac970023f..941d32f007dc250afb73a8045044d68b2646eecb 100644 (file)
@@ -220,7 +220,9 @@ typedef int __bitwise snd_pcm_format_t;
 #define        SNDRV_PCM_FORMAT_DSD_U8         ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
 #define        SNDRV_PCM_FORMAT_DSD_U16_LE     ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
 #define        SNDRV_PCM_FORMAT_DSD_U32_LE     ((__force snd_pcm_format_t) 50) /* DSD, 4-byte samples DSD (x32), little endian */
-#define        SNDRV_PCM_FORMAT_LAST           SNDRV_PCM_FORMAT_DSD_U32_LE
+#define        SNDRV_PCM_FORMAT_DSD_U16_BE     ((__force snd_pcm_format_t) 51) /* DSD, 2-byte samples DSD (x16), big endian */
+#define        SNDRV_PCM_FORMAT_DSD_U32_BE     ((__force snd_pcm_format_t) 52) /* DSD, 4-byte samples DSD (x32), big endian */
+#define        SNDRV_PCM_FORMAT_LAST           SNDRV_PCM_FORMAT_DSD_U32_BE
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #define        SNDRV_PCM_FORMAT_S16            SNDRV_PCM_FORMAT_S16_LE
index 3ee28ae02cc89cb0c0d3b2a9ca112c1edfda2e96..903505e66d1d710bc81416cc151e29533fea70c5 100644 (file)
@@ -477,7 +477,7 @@ config TREE_RCU
          thousands of CPUs.  It also scales down nicely to
          smaller systems.
 
-config TREE_PREEMPT_RCU
+config PREEMPT_RCU
        bool "Preemptible tree-based hierarchical RCU"
        depends on PREEMPT
        select IRQ_WORK
@@ -501,12 +501,6 @@ config TINY_RCU
 
 endchoice
 
-config PREEMPT_RCU
-       def_bool TREE_PREEMPT_RCU
-       help
-         This option enables preemptible-RCU code that is common between
-         TREE_PREEMPT_RCU and, in the old days, TINY_PREEMPT_RCU.
-
 config TASKS_RCU
        bool "Task_based RCU implementation using voluntary context switch"
        default n
@@ -518,7 +512,7 @@ config TASKS_RCU
          If unsure, say N.
 
 config RCU_STALL_COMMON
-       def_bool ( TREE_RCU || TREE_PREEMPT_RCU || RCU_TRACE )
+       def_bool ( TREE_RCU || PREEMPT_RCU || RCU_TRACE )
        help
          This option enables RCU CPU stall code that is common between
          the TINY and TREE variants of RCU.  The purpose is to allow
@@ -576,7 +570,7 @@ config RCU_FANOUT
        int "Tree-based hierarchical RCU fanout value"
        range 2 64 if 64BIT
        range 2 32 if !64BIT
-       depends on TREE_RCU || TREE_PREEMPT_RCU
+       depends on TREE_RCU || PREEMPT_RCU
        default 64 if 64BIT
        default 32 if !64BIT
        help
@@ -596,7 +590,7 @@ config RCU_FANOUT_LEAF
        int "Tree-based hierarchical RCU leaf-level fanout value"
        range 2 RCU_FANOUT if 64BIT
        range 2 RCU_FANOUT if !64BIT
-       depends on TREE_RCU || TREE_PREEMPT_RCU
+       depends on TREE_RCU || PREEMPT_RCU
        default 16
        help
          This option controls the leaf-level fanout of hierarchical
@@ -621,7 +615,7 @@ config RCU_FANOUT_LEAF
 
 config RCU_FANOUT_EXACT
        bool "Disable tree-based hierarchical RCU auto-balancing"
-       depends on TREE_RCU || TREE_PREEMPT_RCU
+       depends on TREE_RCU || PREEMPT_RCU
        default n
        help
          This option forces use of the exact RCU_FANOUT value specified,
@@ -652,11 +646,11 @@ config RCU_FAST_NO_HZ
          Say N if you are unsure.
 
 config TREE_RCU_TRACE
-       def_bool RCU_TRACE && ( TREE_RCU || TREE_PREEMPT_RCU )
+       def_bool RCU_TRACE && ( TREE_RCU || PREEMPT_RCU )
        select DEBUG_FS
        help
          This option provides tracing for the TREE_RCU and
-         TREE_PREEMPT_RCU implementations, permitting Makefile to
+         PREEMPT_RCU implementations, permitting Makefile to
          trivially select kernel/rcutree_trace.c.
 
 config RCU_BOOST
@@ -672,30 +666,31 @@ config RCU_BOOST
          Say Y here if you are working with real-time apps or heavy loads
          Say N here if you are unsure.
 
-config RCU_BOOST_PRIO
-       int "Real-time priority to boost RCU readers to"
+config RCU_KTHREAD_PRIO
+       int "Real-time priority to use for RCU worker threads"
        range 1 99
        depends on RCU_BOOST
        default 1
        help
-         This option specifies the real-time priority to which long-term
-         preempted RCU readers are to be boosted.  If you are working
-         with a real-time application that has one or more CPU-bound
-         threads running at a real-time priority level, you should set
-         RCU_BOOST_PRIO to a priority higher then the highest-priority
-         real-time CPU-bound thread.  The default RCU_BOOST_PRIO value
-         of 1 is appropriate in the common case, which is real-time
+         This option specifies the SCHED_FIFO priority value that will be
+         assigned to the rcuc/n and rcub/n threads and is also the value
+         used for RCU_BOOST (if enabled). If you are working with a
+         real-time application that has one or more CPU-bound threads
+         running at a real-time priority level, you should set
+         RCU_KTHREAD_PRIO to a priority higher than the highest-priority
+         real-time CPU-bound application thread.  The default RCU_KTHREAD_PRIO
+         value of 1 is appropriate in the common case, which is real-time
          applications that do not have any CPU-bound threads.
 
          Some real-time applications might not have a single real-time
          thread that saturates a given CPU, but instead might have
          multiple real-time threads that, taken together, fully utilize
-         that CPU.  In this case, you should set RCU_BOOST_PRIO to
+         that CPU.  In this case, you should set RCU_KTHREAD_PRIO to
          a priority higher than the lowest-priority thread that is
          conspiring to prevent the CPU from running any non-real-time
          tasks.  For example, if one thread at priority 10 and another
          thread at priority 5 are between themselves fully consuming
-         the CPU time on a given CPU, then RCU_BOOST_PRIO should be
+         the CPU time on a given CPU, then RCU_KTHREAD_PRIO should be
          set to priority 6 or higher.
 
          Specify the real-time priority, or take the default if unsure.
@@ -715,7 +710,7 @@ config RCU_BOOST_DELAY
 
 config RCU_NOCB_CPU
        bool "Offload RCU callback processing from boot-selected CPUs"
-       depends on TREE_RCU || TREE_PREEMPT_RCU
+       depends on TREE_RCU || PREEMPT_RCU
        default n
        help
          Use this option to reduce OS jitter for aggressive HPC or
@@ -739,6 +734,7 @@ config RCU_NOCB_CPU
 choice
        prompt "Build-forced no-CBs CPUs"
        default RCU_NOCB_CPU_NONE
+       depends on RCU_NOCB_CPU
        help
          This option allows no-CBs CPUs (whose RCU callbacks are invoked
          from kthreads rather than from softirq context) to be specified
@@ -747,7 +743,6 @@ choice
 
 config RCU_NOCB_CPU_NONE
        bool "No build_forced no-CBs CPUs"
-       depends on RCU_NOCB_CPU
        help
          This option does not force any of the CPUs to be no-CBs CPUs.
          Only CPUs designated by the rcu_nocbs= boot parameter will be
@@ -761,7 +756,6 @@ config RCU_NOCB_CPU_NONE
 
 config RCU_NOCB_CPU_ZERO
        bool "CPU 0 is a build_forced no-CBs CPU"
-       depends on RCU_NOCB_CPU
        help
          This option forces CPU 0 to be a no-CBs CPU, so that its RCU
          callbacks are invoked by a per-CPU kthread whose name begins
@@ -776,7 +770,6 @@ config RCU_NOCB_CPU_ZERO
 
 config RCU_NOCB_CPU_ALL
        bool "All CPUs are build_forced no-CBs CPUs"
-       depends on RCU_NOCB_CPU
        help
          This option forces all CPUs to be no-CBs CPUs.  The rcu_nocbs=
          boot parameter will be ignored.  All CPUs' RCU callbacks will
@@ -1341,6 +1334,10 @@ config SYSCTL_ARCH_UNALIGN_ALLOW
 config HAVE_PCSPKR_PLATFORM
        bool
 
+# interpreter that classic socket filters depend on
+config BPF
+       bool
+
 menuconfig EXPERT
        bool "Configure standard kernel features (expert users)"
        # Unhide debug options, to make the on-by-default options visible
@@ -1521,6 +1518,16 @@ config EVENTFD
 
          If unsure, say Y.
 
+# syscall, maps, verifier
+config BPF_SYSCALL
+       bool "Enable bpf() system call" if EXPERT
+       select ANON_INODES
+       select BPF
+       default n
+       help
+         Enable the bpf() system call that allows to manipulate eBPF
+         programs and maps via file descriptors.
+
 config SHMEM
        bool "Use full shmem filesystem" if EXPERT
        default y
index 800a0daede7e4d8b8940288bd30dfb43a6e922a8..321d0ceb26d3782ed6871feef4c52090e9872b23 100644 (file)
@@ -544,7 +544,7 @@ asmlinkage __visible void __init start_kernel(void)
                                  static_command_line, __start___param,
                                  __stop___param - __start___param,
                                  -1, -1, &unknown_bootoption);
-       if (after_dashes)
+       if (!IS_ERR_OR_NULL(after_dashes))
                parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
                           set_init_arg);
 
index 454f6c6020a8d98dccb167e46d3a5225d5f4ce2d..53c3310f41c6867fd4b5f3f0493a150184b8c617 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -507,13 +507,6 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
                return retval;
        }
 
-       id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
-       if (id < 0) {
-               ipc_rcu_putref(sma, sem_rcu_free);
-               return id;
-       }
-       ns->used_sems += nsems;
-
        sma->sem_base = (struct sem *) &sma[1];
 
        for (i = 0; i < nsems; i++) {
@@ -528,6 +521,14 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        INIT_LIST_HEAD(&sma->list_id);
        sma->sem_nsems = nsems;
        sma->sem_ctime = get_seconds();
+
+       id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
+       if (id < 0) {
+               ipc_rcu_putref(sma, sem_rcu_free);
+               return id;
+       }
+       ns->used_sems += nsems;
+
        sem_unlock(sma, -1);
        rcu_read_unlock();
 
index dc5c77544fd69f6924adc25c3f4a8d3530708392..17ea6d4a9a247ce261f8ae22a3f07f0bb80393e1 100644 (file)
@@ -86,7 +86,7 @@ obj-$(CONFIG_RING_BUFFER) += trace/
 obj-$(CONFIG_TRACEPOINTS) += trace/
 obj-$(CONFIG_IRQ_WORK) += irq_work.o
 obj-$(CONFIG_CPU_PM) += cpu_pm.o
-obj-$(CONFIG_NET) += bpf/
+obj-$(CONFIG_BPF) += bpf/
 
 obj-$(CONFIG_PERF_EVENTS) += events/
 
index 80983df92cd441f981090394252126fbde22cd64..1f37f15117e501f554b7ff4f2b734a8119757df3 100644 (file)
@@ -499,7 +499,6 @@ static int kauditd_thread(void *dummy)
        set_freezable();
        while (!kthread_should_stop()) {
                struct sk_buff *skb;
-               DECLARE_WAITQUEUE(wait, current);
 
                flush_hold_queue();
 
@@ -514,16 +513,8 @@ static int kauditd_thread(void *dummy)
                                audit_printk_skb(skb);
                        continue;
                }
-               set_current_state(TASK_INTERRUPTIBLE);
-               add_wait_queue(&kauditd_wait, &wait);
 
-               if (!skb_queue_len(&audit_skb_queue)) {
-                       try_to_freeze();
-                       schedule();
-               }
-
-               __set_current_state(TASK_RUNNING);
-               remove_wait_queue(&kauditd_wait, &wait);
+               wait_event_freezable(kauditd_wait, skb_queue_len(&audit_skb_queue));
        }
        return 0;
 }
@@ -739,7 +730,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE);
        audit_log_task_info(ab, current);
-       audit_log_format(ab, "feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d",
+       audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d",
                         audit_feature_names[which], !!old_feature, !!new_feature,
                         !!old_lock, !!new_lock, res);
        audit_log_end(ab);
index e242e3a9864ad6032e3d32704aa9b95550036b8a..80f29e0155705159fc83a80c1138e45b590661e2 100644 (file)
@@ -154,6 +154,7 @@ static struct audit_chunk *alloc_chunk(int count)
                chunk->owners[i].index = i;
        }
        fsnotify_init_mark(&chunk->mark, audit_tree_destroy_watch);
+       chunk->mark.mask = FS_IN_IGNORED;
        return chunk;
 }
 
index 45427239f375c564049951e00e3925aacff8bc3f..0daf7f6ae7df565c43273b8fb3a553bc1ffdd622 100644 (file)
@@ -1,5 +1,5 @@
-obj-y := core.o syscall.o verifier.o
-
+obj-y := core.o
+obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o
 ifdef CONFIG_TEST_BPF
-obj-y += test_stub.o
+obj-$(CONFIG_BPF_SYSCALL) += test_stub.o
 endif
index f0c30c59b31755ff1e124e0a5a0aaa0e356efc9e..d6594e457a25af32e41a4b46a00a43ddf0a2c46b 100644 (file)
@@ -655,3 +655,12 @@ void bpf_prog_free(struct bpf_prog *fp)
        schedule_work(&aux->work);
 }
 EXPORT_SYMBOL_GPL(bpf_prog_free);
+
+/* To execute LD_ABS/LD_IND instructions __bpf_prog_run() may call
+ * skb_copy_bits(), so provide a weak definition of it for NET-less config.
+ */
+int __weak skb_copy_bits(const struct sk_buff *skb, int offset, void *to,
+                        int len)
+{
+       return -EFAULT;
+}
index 801f5f3b9307cc5cbe8ed24f13e2aa1cbab53dc6..9f81818f294185988c9cc181274ed38789774871 100644 (file)
@@ -1409,7 +1409,8 @@ static bool states_equal(struct verifier_state *old, struct verifier_state *cur)
                if (memcmp(&old->regs[i], &cur->regs[i],
                           sizeof(old->regs[0])) != 0) {
                        if (old->regs[i].type == NOT_INIT ||
-                           old->regs[i].type == UNKNOWN_VALUE)
+                           (old->regs[i].type == UNKNOWN_VALUE &&
+                            cur->regs[i].type != NOT_INIT))
                                continue;
                        return false;
                }
index 5664985c46a0972b6961e117e99d7a399940e1c0..937ecdfdf2589cc896522286a4da2e3d4f097bf9 100644 (file)
@@ -107,46 +107,6 @@ void context_tracking_user_enter(void)
 }
 NOKPROBE_SYMBOL(context_tracking_user_enter);
 
-#ifdef CONFIG_PREEMPT
-/**
- * preempt_schedule_context - preempt_schedule called by tracing
- *
- * The tracing infrastructure uses preempt_enable_notrace to prevent
- * recursion and tracing preempt enabling caused by the tracing
- * infrastructure itself. But as tracing can happen in areas coming
- * from userspace or just about to enter userspace, a preempt enable
- * can occur before user_exit() is called. This will cause the scheduler
- * to be called when the system is still in usermode.
- *
- * To prevent this, the preempt_enable_notrace will use this function
- * instead of preempt_schedule() to exit user context if needed before
- * calling the scheduler.
- */
-asmlinkage __visible void __sched notrace preempt_schedule_context(void)
-{
-       enum ctx_state prev_ctx;
-
-       if (likely(!preemptible()))
-               return;
-
-       /*
-        * Need to disable preemption in case user_exit() is traced
-        * and the tracer calls preempt_enable_notrace() causing
-        * an infinite recursion.
-        */
-       preempt_disable_notrace();
-       prev_ctx = exception_enter();
-       preempt_enable_no_resched_notrace();
-
-       preempt_schedule();
-
-       preempt_disable_notrace();
-       exception_exit(prev_ctx);
-       preempt_enable_notrace();
-}
-EXPORT_SYMBOL_GPL(preempt_schedule_context);
-#endif /* CONFIG_PREEMPT */
-
 /**
  * context_tracking_user_exit - Inform the context tracking that the CPU is
  *                              exiting userspace mode and entering the kernel.
index 356450f09c1f89d1ee35820a59a59e3a68cebe63..5d220234b3ca5aa2feebe4b80ddba1bfd63a8eda 100644 (file)
@@ -64,6 +64,8 @@ static struct {
         * an ongoing cpu hotplug operation.
         */
        int refcount;
+       /* And allows lockless put_online_cpus(). */
+       atomic_t puts_pending;
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map dep_map;
@@ -84,6 +86,16 @@ static struct {
 #define cpuhp_lock_acquire()      lock_map_acquire(&cpu_hotplug.dep_map)
 #define cpuhp_lock_release()      lock_map_release(&cpu_hotplug.dep_map)
 
+static void apply_puts_pending(int max)
+{
+       int delta;
+
+       if (atomic_read(&cpu_hotplug.puts_pending) >= max) {
+               delta = atomic_xchg(&cpu_hotplug.puts_pending, 0);
+               cpu_hotplug.refcount -= delta;
+       }
+}
+
 void get_online_cpus(void)
 {
        might_sleep();
@@ -91,6 +103,7 @@ void get_online_cpus(void)
                return;
        cpuhp_lock_acquire_read();
        mutex_lock(&cpu_hotplug.lock);
+       apply_puts_pending(65536);
        cpu_hotplug.refcount++;
        mutex_unlock(&cpu_hotplug.lock);
 }
@@ -103,6 +116,7 @@ bool try_get_online_cpus(void)
        if (!mutex_trylock(&cpu_hotplug.lock))
                return false;
        cpuhp_lock_acquire_tryread();
+       apply_puts_pending(65536);
        cpu_hotplug.refcount++;
        mutex_unlock(&cpu_hotplug.lock);
        return true;
@@ -113,7 +127,11 @@ void put_online_cpus(void)
 {
        if (cpu_hotplug.active_writer == current)
                return;
-       mutex_lock(&cpu_hotplug.lock);
+       if (!mutex_trylock(&cpu_hotplug.lock)) {
+               atomic_inc(&cpu_hotplug.puts_pending);
+               cpuhp_lock_release();
+               return;
+       }
 
        if (WARN_ON(!cpu_hotplug.refcount))
                cpu_hotplug.refcount++; /* try to fix things up */
@@ -155,6 +173,7 @@ void cpu_hotplug_begin(void)
        cpuhp_lock_acquire();
        for (;;) {
                mutex_lock(&cpu_hotplug.lock);
+               apply_puts_pending(1);
                if (likely(!cpu_hotplug.refcount))
                        break;
                __set_current_state(TASK_UNINTERRUPTIBLE);
index 1f107c74087bc52f690d957dbe610472688b4c1b..723cfc9d0ad7ac417fdeb6ea2824f00129bcfaa1 100644 (file)
@@ -506,6 +506,16 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
                        goto out;
        }
 
+       /*
+        * We can't shrink if we won't have enough room for SCHED_DEADLINE
+        * tasks.
+        */
+       ret = -EBUSY;
+       if (is_cpu_exclusive(cur) &&
+           !cpuset_cpumask_can_shrink(cur->cpus_allowed,
+                                      trial->cpus_allowed))
+               goto out;
+
        ret = 0;
 out:
        rcu_read_unlock();
@@ -1429,17 +1439,8 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css,
                goto out_unlock;
 
        cgroup_taskset_for_each(task, tset) {
-               /*
-                * Kthreads which disallow setaffinity shouldn't be moved
-                * to a new cpuset; we don't want to change their cpu
-                * affinity and isolating such threads by their set of
-                * allowed nodes is unnecessary.  Thus, cpusets are not
-                * applicable for such threads.  This prevents checking for
-                * success of set_cpus_allowed_ptr() on all attached tasks
-                * before cpus_allowed may be changed.
-                */
-               ret = -EINVAL;
-               if (task->flags & PF_NO_SETAFFINITY)
+               ret = task_can_attach(task, cs->cpus_allowed);
+               if (ret)
                        goto out_unlock;
                ret = security_task_setscheduler(task);
                if (ret)
index 1425d07018de50987b5373dec88bff3438787426..3e19d3ebc29c33b6b1f3883c10f30f017c1aaca2 100644 (file)
@@ -1562,8 +1562,10 @@ static void perf_remove_from_context(struct perf_event *event, bool detach_group
 
        if (!task) {
                /*
-                * Per cpu events are removed via an smp call and
-                * the removal is always successful.
+                * Per cpu events are removed via an smp call. The removal can
+                * fail if the CPU is currently offline, but in that case we
+                * already called __perf_remove_from_context from
+                * perf_event_exit_cpu.
                 */
                cpu_function_call(event->cpu, __perf_remove_from_context, &re);
                return;
@@ -4458,7 +4460,7 @@ perf_output_sample_regs(struct perf_output_handle *handle,
        }
 }
 
-static void perf_sample_regs_user(struct perf_regs_user *regs_user,
+static void perf_sample_regs_user(struct perf_regs *regs_user,
                                  struct pt_regs *regs)
 {
        if (!user_mode(regs)) {
@@ -4469,11 +4471,22 @@ static void perf_sample_regs_user(struct perf_regs_user *regs_user,
        }
 
        if (regs) {
-               regs_user->regs = regs;
                regs_user->abi  = perf_reg_abi(current);
+               regs_user->regs = regs;
+       } else {
+               regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;
+               regs_user->regs = NULL;
        }
 }
 
+static void perf_sample_regs_intr(struct perf_regs *regs_intr,
+                                 struct pt_regs *regs)
+{
+       regs_intr->regs = regs;
+       regs_intr->abi  = perf_reg_abi(current);
+}
+
+
 /*
  * Get remaining task size from user stack pointer.
  *
@@ -4855,6 +4868,23 @@ void perf_output_sample(struct perf_output_handle *handle,
        if (sample_type & PERF_SAMPLE_TRANSACTION)
                perf_output_put(handle, data->txn);
 
+       if (sample_type & PERF_SAMPLE_REGS_INTR) {
+               u64 abi = data->regs_intr.abi;
+               /*
+                * If there are no regs to dump, notice it through
+                * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE).
+                */
+               perf_output_put(handle, abi);
+
+               if (abi) {
+                       u64 mask = event->attr.sample_regs_intr;
+
+                       perf_output_sample_regs(handle,
+                                               data->regs_intr.regs,
+                                               mask);
+               }
+       }
+
        if (!event->attr.watermark) {
                int wakeup_events = event->attr.wakeup_events;
 
@@ -4920,12 +4950,13 @@ void perf_prepare_sample(struct perf_event_header *header,
                header->size += size;
        }
 
+       if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER))
+               perf_sample_regs_user(&data->regs_user, regs);
+
        if (sample_type & PERF_SAMPLE_REGS_USER) {
                /* regs dump ABI info */
                int size = sizeof(u64);
 
-               perf_sample_regs_user(&data->regs_user, regs);
-
                if (data->regs_user.regs) {
                        u64 mask = event->attr.sample_regs_user;
                        size += hweight64(mask) * sizeof(u64);
@@ -4941,15 +4972,11 @@ void perf_prepare_sample(struct perf_event_header *header,
                 * in case new sample type is added, because we could eat
                 * up the rest of the sample size.
                 */
-               struct perf_regs_user *uregs = &data->regs_user;
                u16 stack_size = event->attr.sample_stack_user;
                u16 size = sizeof(u64);
 
-               if (!uregs->abi)
-                       perf_sample_regs_user(uregs, regs);
-
                stack_size = perf_sample_ustack_size(stack_size, header->size,
-                                                    uregs->regs);
+                                                    data->regs_user.regs);
 
                /*
                 * If there is something to dump, add space for the dump
@@ -4962,6 +4989,21 @@ void perf_prepare_sample(struct perf_event_header *header,
                data->stack_user_size = stack_size;
                header->size += size;
        }
+
+       if (sample_type & PERF_SAMPLE_REGS_INTR) {
+               /* regs dump ABI info */
+               int size = sizeof(u64);
+
+               perf_sample_regs_intr(&data->regs_intr, regs);
+
+               if (data->regs_intr.regs) {
+                       u64 mask = event->attr.sample_regs_intr;
+
+                       size += hweight64(mask) * sizeof(u64);
+               }
+
+               header->size += size;
+       }
 }
 
 static void perf_event_output(struct perf_event *event,
@@ -6071,11 +6113,6 @@ static int perf_swevent_init(struct perf_event *event)
        return 0;
 }
 
-static int perf_swevent_event_idx(struct perf_event *event)
-{
-       return 0;
-}
-
 static struct pmu perf_swevent = {
        .task_ctx_nr    = perf_sw_context,
 
@@ -6085,8 +6122,6 @@ static struct pmu perf_swevent = {
        .start          = perf_swevent_start,
        .stop           = perf_swevent_stop,
        .read           = perf_swevent_read,
-
-       .event_idx      = perf_swevent_event_idx,
 };
 
 #ifdef CONFIG_EVENT_TRACING
@@ -6204,8 +6239,6 @@ static struct pmu perf_tracepoint = {
        .start          = perf_swevent_start,
        .stop           = perf_swevent_stop,
        .read           = perf_swevent_read,
-
-       .event_idx      = perf_swevent_event_idx,
 };
 
 static inline void perf_tp_register(void)
@@ -6431,8 +6464,6 @@ static struct pmu perf_cpu_clock = {
        .start          = cpu_clock_event_start,
        .stop           = cpu_clock_event_stop,
        .read           = cpu_clock_event_read,
-
-       .event_idx      = perf_swevent_event_idx,
 };
 
 /*
@@ -6511,8 +6542,6 @@ static struct pmu perf_task_clock = {
        .start          = task_clock_event_start,
        .stop           = task_clock_event_stop,
        .read           = task_clock_event_read,
-
-       .event_idx      = perf_swevent_event_idx,
 };
 
 static void perf_pmu_nop_void(struct pmu *pmu)
@@ -6542,7 +6571,7 @@ static void perf_pmu_cancel_txn(struct pmu *pmu)
 
 static int perf_event_idx_default(struct perf_event *event)
 {
-       return event->hw.idx + 1;
+       return 0;
 }
 
 /*
@@ -7162,6 +7191,8 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
                        ret = -EINVAL;
        }
 
+       if (attr->sample_type & PERF_SAMPLE_REGS_INTR)
+               ret = perf_reg_validate(attr->sample_regs_intr);
 out:
        return ret;
 
@@ -8130,7 +8161,7 @@ static void perf_pmu_rotate_stop(struct pmu *pmu)
 
 static void __perf_event_exit_context(void *__info)
 {
-       struct remove_event re = { .detach_group = false };
+       struct remove_event re = { .detach_group = true };
        struct perf_event_context *ctx = __info;
 
        perf_pmu_rotate_stop(ctx->pmu);
index 1559fb0b929650fe8951ee4b5084717d9d0b4895..9803a6600d499681848290f9eff6254e53364dbf 100644 (file)
@@ -605,11 +605,6 @@ static void hw_breakpoint_stop(struct perf_event *bp, int flags)
        bp->hw.state = PERF_HES_STOPPED;
 }
 
-static int hw_breakpoint_event_idx(struct perf_event *bp)
-{
-       return 0;
-}
-
 static struct pmu perf_breakpoint = {
        .task_ctx_nr    = perf_sw_context, /* could eventually get its own */
 
@@ -619,8 +614,6 @@ static struct pmu perf_breakpoint = {
        .start          = hw_breakpoint_start,
        .stop           = hw_breakpoint_stop,
        .read           = hw_breakpoint_pmu_read,
-
-       .event_idx      = hw_breakpoint_event_idx,
 };
 
 int __init init_hw_breakpoint(void)
index 1d0af8a2c6469bda46438dbd8383cbf535d65077..ed8f2cde34c57acce554ee08d79625c3b260ada8 100644 (file)
@@ -1640,7 +1640,6 @@ bool uprobe_deny_signal(void)
                if (__fatal_signal_pending(t) || arch_uprobe_xol_was_trapped(t)) {
                        utask->state = UTASK_SSTEP_TRAPPED;
                        set_tsk_thread_flag(t, TIF_UPROBE);
-                       set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
                }
        }
 
index 5d30019ff953cf9cc421c1a37c850dca16e4c8a7..232c4bc8bcc9905a746e61cb302b961c9f4e1176 100644 (file)
@@ -997,6 +997,8 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
 
                get_task_struct(p);
                read_unlock(&tasklist_lock);
+               sched_annotate_sleep();
+
                if ((exit_code & 0x7f) == 0) {
                        why = CLD_EXITED;
                        status = exit_code >> 8;
@@ -1079,6 +1081,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
         * thread can reap it because we its state == DEAD/TRACE.
         */
        read_unlock(&tasklist_lock);
+       sched_annotate_sleep();
 
        retval = wo->wo_rusage
                ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0;
@@ -1210,6 +1213,7 @@ unlock_sig:
        pid = task_pid_vnr(p);
        why = ptrace ? CLD_TRAPPED : CLD_STOPPED;
        read_unlock(&tasklist_lock);
+       sched_annotate_sleep();
 
        if (unlikely(wo->wo_flags & WNOWAIT))
                return wait_noreap_copyout(wo, p, pid, uid, why, exit_code);
@@ -1272,6 +1276,7 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
        pid = task_pid_vnr(p);
        get_task_struct(p);
        read_unlock(&tasklist_lock);
+       sched_annotate_sleep();
 
        if (!wo->wo_info) {
                retval = wo->wo_rusage
index 9b7d746d6d629c3d9d1c937a677271f027a5fe2b..9ca84189cfc20ad34f6b745c10d753a461b89ee3 100644 (file)
@@ -1022,11 +1022,14 @@ void __cleanup_sighand(struct sighand_struct *sighand)
 {
        if (atomic_dec_and_test(&sighand->count)) {
                signalfd_cleanup(sighand);
+               /*
+                * sighand_cachep is SLAB_DESTROY_BY_RCU so we can free it
+                * without an RCU grace period, see __lock_task_sighand().
+                */
                kmem_cache_free(sighand_cachep, sighand);
        }
 }
 
-
 /*
  * Initialize POSIX timer handling for a thread group.
  */
index aa6a8aadb911fb323b4662a4652c95ff4319f0c5..a8900a3bc27a895b65580a23a144e581bfe0149d 100644 (file)
@@ -42,6 +42,9 @@ bool freezing_slow_path(struct task_struct *p)
        if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK))
                return false;
 
+       if (test_thread_flag(TIF_MEMDIE))
+               return false;
+
        if (pm_nosig_freezing || cgroup_freezing(p))
                return true;
 
@@ -147,12 +150,6 @@ void __thaw_task(struct task_struct *p)
 {
        unsigned long flags;
 
-       /*
-        * Clear freezing and kick @p if FROZEN.  Clearing is guaranteed to
-        * be visible to @p as waking up implies wmb.  Waking up inside
-        * freezer_lock also prevents wakeups from leaking outside
-        * refrigerator.
-        */
        spin_lock_irqsave(&freezer_lock, flags);
        if (frozen(p))
                wake_up_process(p);
index f3a3a071283cea232512370c2b9f5c87a0b440bf..63678b573d6135201700db85ede47d5111082a9c 100644 (file)
  *
  * Where (A) orders the waiters increment and the futex value read through
  * atomic operations (see hb_waiters_inc) and where (B) orders the write
- * to futex and the waiters read -- this is done by the barriers in
- * get_futex_key_refs(), through either ihold or atomic_inc, depending on the
- * futex type.
+ * to futex and the waiters read -- this is done by the barriers for both
+ * shared and private futexes in get_futex_key_refs().
  *
  * This yields the following case (where X:=waiters, Y:=futex):
  *
@@ -344,13 +343,20 @@ static void get_futex_key_refs(union futex_key *key)
                futex_get_mm(key); /* implies MB (B) */
                break;
        default:
+               /*
+                * Private futexes do not hold reference on an inode or
+                * mm, therefore the only purpose of calling get_futex_key_refs
+                * is because we need the barrier for the lockless waiter check.
+                */
                smp_mb(); /* explicit MB (B) */
        }
 }
 
 /*
  * Drop a reference to the resource addressed by a key.
- * The hash bucket spinlock must not be held.
+ * The hash bucket spinlock must not be held. This is
+ * a no-op for private futexes, see comment in the get
+ * counterpart.
  */
 static void drop_futex_key_refs(union futex_key *key)
 {
@@ -641,8 +647,14 @@ static struct futex_pi_state * alloc_pi_state(void)
        return pi_state;
 }
 
+/*
+ * Must be called with the hb lock held.
+ */
 static void free_pi_state(struct futex_pi_state *pi_state)
 {
+       if (!pi_state)
+               return;
+
        if (!atomic_dec_and_test(&pi_state->refcount))
                return;
 
@@ -1521,15 +1533,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
        }
 
 retry:
-       if (pi_state != NULL) {
-               /*
-                * We will have to lookup the pi_state again, so free this one
-                * to keep the accounting correct.
-                */
-               free_pi_state(pi_state);
-               pi_state = NULL;
-       }
-
        ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
        if (unlikely(ret != 0))
                goto out;
@@ -1619,6 +1622,8 @@ retry_private:
                case 0:
                        break;
                case -EFAULT:
+                       free_pi_state(pi_state);
+                       pi_state = NULL;
                        double_unlock_hb(hb1, hb2);
                        hb_waiters_dec(hb2);
                        put_futex_key(&key2);
@@ -1634,6 +1639,8 @@ retry_private:
                         *   exit to complete.
                         * - The user space value changed.
                         */
+                       free_pi_state(pi_state);
+                       pi_state = NULL;
                        double_unlock_hb(hb1, hb2);
                        hb_waiters_dec(hb2);
                        put_futex_key(&key2);
@@ -1710,6 +1717,7 @@ retry_private:
        }
 
 out_unlock:
+       free_pi_state(pi_state);
        double_unlock_hb(hb1, hb2);
        hb_waiters_dec(hb2);
 
@@ -1727,8 +1735,6 @@ out_put_keys:
 out_put_key1:
        put_futex_key(&key1);
 out:
-       if (pi_state != NULL)
-               free_pi_state(pi_state);
        return ret ? ret : task_count;
 }
 
index cf66c5c8458e66aef61834e977e55999b442360a..3b7408759bdfdfc4a5fe469df649d631efdae40d 100644 (file)
@@ -35,7 +35,7 @@ config GCOV_KERNEL
 config GCOV_PROFILE_ALL
        bool "Profile entire Kernel"
        depends on GCOV_KERNEL
-       depends on SUPERH || S390 || X86 || PPC || MICROBLAZE || ARM
+       depends on SUPERH || S390 || X86 || PPC || MICROBLAZE || ARM || ARM64
        default n
        ---help---
        This options activates profiling for the entire kernel.
index 8637e041a24722b7245f5a5cf24fa7dd71dce001..80f7a6d00519c863ac4e0ea94c86406532a6f65a 100644 (file)
@@ -196,12 +196,34 @@ int __request_module(bool wait, const char *fmt, ...)
 EXPORT_SYMBOL(__request_module);
 #endif /* CONFIG_MODULES */
 
+static void call_usermodehelper_freeinfo(struct subprocess_info *info)
+{
+       if (info->cleanup)
+               (*info->cleanup)(info);
+       kfree(info);
+}
+
+static void umh_complete(struct subprocess_info *sub_info)
+{
+       struct completion *comp = xchg(&sub_info->complete, NULL);
+       /*
+        * See call_usermodehelper_exec(). If xchg() returns NULL
+        * we own sub_info, the UMH_KILLABLE caller has gone away
+        * or the caller used UMH_NO_WAIT.
+        */
+       if (comp)
+               complete(comp);
+       else
+               call_usermodehelper_freeinfo(sub_info);
+}
+
 /*
  * This is the task which runs the usermode application
  */
 static int ____call_usermodehelper(void *data)
 {
        struct subprocess_info *sub_info = data;
+       int wait = sub_info->wait & ~UMH_KILLABLE;
        struct cred *new;
        int retval;
 
@@ -221,7 +243,7 @@ static int ____call_usermodehelper(void *data)
        retval = -ENOMEM;
        new = prepare_kernel_cred(current);
        if (!new)
-               goto fail;
+               goto out;
 
        spin_lock(&umh_sysctl_lock);
        new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset);
@@ -233,7 +255,7 @@ static int ____call_usermodehelper(void *data)
                retval = sub_info->init(sub_info, new);
                if (retval) {
                        abort_creds(new);
-                       goto fail;
+                       goto out;
                }
        }
 
@@ -242,12 +264,13 @@ static int ____call_usermodehelper(void *data)
        retval = do_execve(getname_kernel(sub_info->path),
                           (const char __user *const __user *)sub_info->argv,
                           (const char __user *const __user *)sub_info->envp);
+out:
+       sub_info->retval = retval;
+       /* wait_for_helper() will call umh_complete if UHM_WAIT_PROC. */
+       if (wait != UMH_WAIT_PROC)
+               umh_complete(sub_info);
        if (!retval)
                return 0;
-
-       /* Exec failed? */
-fail:
-       sub_info->retval = retval;
        do_exit(0);
 }
 
@@ -258,26 +281,6 @@ static int call_helper(void *data)
        return ____call_usermodehelper(data);
 }
 
-static void call_usermodehelper_freeinfo(struct subprocess_info *info)
-{
-       if (info->cleanup)
-               (*info->cleanup)(info);
-       kfree(info);
-}
-
-static void umh_complete(struct subprocess_info *sub_info)
-{
-       struct completion *comp = xchg(&sub_info->complete, NULL);
-       /*
-        * See call_usermodehelper_exec(). If xchg() returns NULL
-        * we own sub_info, the UMH_KILLABLE caller has gone away.
-        */
-       if (comp)
-               complete(comp);
-       else
-               call_usermodehelper_freeinfo(sub_info);
-}
-
 /* Keventd can't block, but this (a child) can. */
 static int wait_for_helper(void *data)
 {
@@ -336,18 +339,8 @@ static void __call_usermodehelper(struct work_struct *work)
                kmod_thread_locker = NULL;
        }
 
-       switch (wait) {
-       case UMH_NO_WAIT:
-               call_usermodehelper_freeinfo(sub_info);
-               break;
-
-       case UMH_WAIT_PROC:
-               if (pid > 0)
-                       break;
-               /* FALLTHROUGH */
-       case UMH_WAIT_EXEC:
-               if (pid < 0)
-                       sub_info->retval = pid;
+       if (pid < 0) {
+               sub_info->retval = pid;
                umh_complete(sub_info);
        }
 }
@@ -588,7 +581,12 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
                goto out;
        }
 
-       sub_info->complete = &done;
+       /*
+        * Set the completion pointer only if there is a waiter.
+        * This makes it possible to use umh_complete to free
+        * the data structure in case of UMH_NO_WAIT.
+        */
+       sub_info->complete = (wait == UMH_NO_WAIT) ? NULL : &done;
        sub_info->wait = wait;
 
        queue_work(khelper_wq, &sub_info->work);
index dadbf88c22c48cea044aac4e34fda9deec78636a..454195194d4a133f2d600d0d3659b2ee5306b7ad 100644 (file)
@@ -378,8 +378,14 @@ done:
         * reschedule now, before we try-lock the mutex. This avoids getting
         * scheduled out right after we obtained the mutex.
         */
-       if (need_resched())
+       if (need_resched()) {
+               /*
+                * We _should_ have TASK_RUNNING here, but just in case
+                * we do not, make it so, otherwise we might get stuck.
+                */
+               __set_current_state(TASK_RUNNING);
                schedule_preempt_disabled();
+       }
 
        return false;
 }
index 88cec1ddb1e3c516496b951ae192cba21ff80c90..e52a8739361aac595a5123b08404518fb1ab6fe5 100644 (file)
@@ -3096,6 +3096,32 @@ static int may_init_module(void)
        return 0;
 }
 
+/*
+ * Can't use wait_event_interruptible() because our condition
+ * 'finished_loading()' contains a blocking primitive itself (mutex_lock).
+ */
+static int wait_finished_loading(struct module *mod)
+{
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
+       int ret = 0;
+
+       add_wait_queue(&module_wq, &wait);
+       for (;;) {
+               if (finished_loading(mod->name))
+                       break;
+
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       break;
+               }
+
+               wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+       }
+       remove_wait_queue(&module_wq, &wait);
+
+       return ret;
+}
+
 /*
  * We try to place it in the list now to make sure it's unique before
  * we dedicate too many resources.  In particular, temporary percpu
@@ -3116,8 +3142,8 @@ again:
                    || old->state == MODULE_STATE_UNFORMED) {
                        /* Wait in case it fails to load. */
                        mutex_unlock(&module_mutex);
-                       err = wait_event_interruptible(module_wq,
-                                              finished_loading(mod->name));
+
+                       err = wait_finished_loading(mod);
                        if (err)
                                goto out_unlocked;
                        goto again;
index d09dc5c32c6740e41a5987cca0252ad86b43bdbd..cf80672b79246dd439f64cea16d3e631e7d35f2f 100644 (file)
@@ -244,6 +244,7 @@ static const struct tnt tnts[] = {
  *  'I' - Working around severe firmware bug.
  *  'O' - Out-of-tree module has been loaded.
  *  'E' - Unsigned module has been loaded.
+ *  'L' - A soft lockup has previously occurred.
  *
  *     The string is overwritten by the next call to print_tainted().
  */
index a9dfa79b6bab93f8cf62e24a0d3bd83c4d4534d5..1f35a3478f3c66af50b27aa580b3f99618789f5e 100644 (file)
@@ -502,8 +502,14 @@ int hibernation_restore(int platform_mode)
        error = dpm_suspend_start(PMSG_QUIESCE);
        if (!error) {
                error = resume_target_kernel(platform_mode);
-               dpm_resume_end(PMSG_RECOVER);
+               /*
+                * The above should either succeed and jump to the new kernel,
+                * or return with an error. Otherwise things are just
+                * undefined, so let's be paranoid.
+                */
+               BUG_ON(!error);
        }
+       dpm_resume_end(PMSG_RECOVER);
        pm_restore_gfp_mask();
        resume_console();
        pm_restore_console();
index 7b323221b9ee9ad015556cf965ab8f211a1ff8c8..5a6ec8678b9a0916922882589b9d32163aaefb3f 100644 (file)
@@ -46,13 +46,13 @@ static int try_to_freeze_tasks(bool user_only)
        while (true) {
                todo = 0;
                read_lock(&tasklist_lock);
-               do_each_thread(g, p) {
+               for_each_process_thread(g, p) {
                        if (p == current || !freeze_task(p))
                                continue;
 
                        if (!freezer_should_skip(p))
                                todo++;
-               } while_each_thread(g, p);
+               }
                read_unlock(&tasklist_lock);
 
                if (!user_only) {
@@ -93,11 +93,11 @@ static int try_to_freeze_tasks(bool user_only)
 
                if (!wakeup) {
                        read_lock(&tasklist_lock);
-                       do_each_thread(g, p) {
+                       for_each_process_thread(g, p) {
                                if (p != current && !freezer_should_skip(p)
                                    && freezing(p) && !frozen(p))
                                        sched_show_task(p);
-                       } while_each_thread(g, p);
+                       }
                        read_unlock(&tasklist_lock);
                }
        } else {
@@ -108,6 +108,30 @@ static int try_to_freeze_tasks(bool user_only)
        return todo ? -EBUSY : 0;
 }
 
+static bool __check_frozen_processes(void)
+{
+       struct task_struct *g, *p;
+
+       for_each_process_thread(g, p)
+               if (p != current && !freezer_should_skip(p) && !frozen(p))
+                       return false;
+
+       return true;
+}
+
+/*
+ * Returns true if all freezable tasks (except for current) are frozen already
+ */
+static bool check_frozen_processes(void)
+{
+       bool ret;
+
+       read_lock(&tasklist_lock);
+       ret = __check_frozen_processes();
+       read_unlock(&tasklist_lock);
+       return ret;
+}
+
 /**
  * freeze_processes - Signal user space processes to enter the refrigerator.
  * The current thread will not be frozen.  The same process that calls
@@ -118,6 +142,7 @@ static int try_to_freeze_tasks(bool user_only)
 int freeze_processes(void)
 {
        int error;
+       int oom_kills_saved;
 
        error = __usermodehelper_disable(UMH_FREEZING);
        if (error)
@@ -132,11 +157,25 @@ int freeze_processes(void)
        pm_wakeup_clear();
        printk("Freezing user space processes ... ");
        pm_freezing = true;
+       oom_kills_saved = oom_kills_count();
        error = try_to_freeze_tasks(true);
        if (!error) {
-               printk("done.");
                __usermodehelper_set_disable_depth(UMH_DISABLED);
                oom_killer_disable();
+
+               /*
+                * There might have been an OOM kill while we were
+                * freezing tasks and the killed task might be still
+                * on the way out so we have to double check for race.
+                */
+               if (oom_kills_count() != oom_kills_saved &&
+                   !check_frozen_processes()) {
+                       __usermodehelper_set_disable_depth(UMH_ENABLED);
+                       printk("OOM in progress.");
+                       error = -EBUSY;
+               } else {
+                       printk("done.");
+               }
        }
        printk("\n");
        BUG_ON(in_atomic());
@@ -191,11 +230,11 @@ void thaw_processes(void)
        thaw_workqueues();
 
        read_lock(&tasklist_lock);
-       do_each_thread(g, p) {
+       for_each_process_thread(g, p) {
                /* No other threads should have PF_SUSPEND_TASK set */
                WARN_ON((p != curr) && (p->flags & PF_SUSPEND_TASK));
                __thaw_task(p);
-       } while_each_thread(g, p);
+       }
        read_unlock(&tasklist_lock);
 
        WARN_ON(!(curr->flags & PF_SUSPEND_TASK));
@@ -218,10 +257,10 @@ void thaw_kernel_threads(void)
        thaw_workqueues();
 
        read_lock(&tasklist_lock);
-       do_each_thread(g, p) {
+       for_each_process_thread(g, p) {
                if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
                        __thaw_task(p);
-       } while_each_thread(g, p);
+       }
        read_unlock(&tasklist_lock);
 
        schedule();
index 884b77058864cd3596dd6f67d5d8c1dda77dedaf..5f4c006c4b1ea737497e4647be5e3c355cf2bd3a 100644 (file)
@@ -105,11 +105,27 @@ static struct pm_qos_object network_throughput_pm_qos = {
 };
 
 
+static BLOCKING_NOTIFIER_HEAD(memory_bandwidth_notifier);
+static struct pm_qos_constraints memory_bw_constraints = {
+       .list = PLIST_HEAD_INIT(memory_bw_constraints.list),
+       .target_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE,
+       .default_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE,
+       .no_constraint_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE,
+       .type = PM_QOS_SUM,
+       .notifiers = &memory_bandwidth_notifier,
+};
+static struct pm_qos_object memory_bandwidth_pm_qos = {
+       .constraints = &memory_bw_constraints,
+       .name = "memory_bandwidth",
+};
+
+
 static struct pm_qos_object *pm_qos_array[] = {
        &null_pm_qos,
        &cpu_dma_pm_qos,
        &network_lat_pm_qos,
-       &network_throughput_pm_qos
+       &network_throughput_pm_qos,
+       &memory_bandwidth_pm_qos,
 };
 
 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
@@ -130,6 +146,9 @@ static const struct file_operations pm_qos_power_fops = {
 /* unlocked internal variant */
 static inline int pm_qos_get_value(struct pm_qos_constraints *c)
 {
+       struct plist_node *node;
+       int total_value = 0;
+
        if (plist_head_empty(&c->list))
                return c->no_constraint_value;
 
@@ -140,6 +159,12 @@ static inline int pm_qos_get_value(struct pm_qos_constraints *c)
        case PM_QOS_MAX:
                return plist_last(&c->list)->prio;
 
+       case PM_QOS_SUM:
+               plist_for_each(node, &c->list)
+                       total_value += node->prio;
+
+               return total_value;
+
        default:
                /* runtime check for not using enum */
                BUG();
index 4ca9a33ff62020e63d15219ce9f097611ebf6507..c347e3ce3a55df9efe054caaffd08bed4bb9e886 100644 (file)
@@ -146,7 +146,7 @@ static int platform_suspend_prepare(suspend_state_t state)
 
 static int platform_suspend_prepare_late(suspend_state_t state)
 {
-       return state == PM_SUSPEND_FREEZE && freeze_ops->prepare ?
+       return state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->prepare ?
                freeze_ops->prepare() : 0;
 }
 
@@ -164,7 +164,7 @@ static void platform_resume_noirq(suspend_state_t state)
 
 static void platform_resume_early(suspend_state_t state)
 {
-       if (state == PM_SUSPEND_FREEZE && freeze_ops->restore)
+       if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->restore)
                freeze_ops->restore();
 }
 
index 807ccfbf69b3359fe85b736efd14d7050e5e4990..e6fae503d1bc54519a45ba838fe3d8622e4333f4 100644 (file)
@@ -1,6 +1,6 @@
 obj-y += update.o srcu.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_TREE_RCU) += tree.o
-obj-$(CONFIG_TREE_PREEMPT_RCU) += tree.o
+obj-$(CONFIG_PREEMPT_RCU) += tree.o
 obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
 obj-$(CONFIG_TINY_RCU) += tiny.o
index ff1a6de62f1789813260cbe719fd11ba448b946e..07bb02eda844bf16eee540ba01a99beb7c52ac60 100644 (file)
@@ -135,4 +135,6 @@ int rcu_jiffies_till_stall_check(void);
  */
 #define TPS(x)  tracepoint_string(x)
 
+void rcu_early_boot_tests(void);
+
 #endif /* __LINUX_RCU_H */
index 240fa9094f830cdc56565cb2ceb8233984564ac3..4d559baf06e0c7171a7a86acbeed9926fc8c9d7d 100644 (file)
@@ -812,6 +812,7 @@ rcu_torture_cbflood(void *arg)
                cur_ops->cb_barrier();
                stutter_wait("rcu_torture_cbflood");
        } while (!torture_must_stop());
+       vfree(rhp);
        torture_kthread_stopping("rcu_torture_cbflood");
        return 0;
 }
index c0623fc471256abb404a5d49e8d4d805b7fb4ba7..0db5649f88179958d7ab26f982036a70c388a817 100644 (file)
@@ -247,7 +247,7 @@ void rcu_bh_qs(void)
  * be called from hardirq context.  It is normally called from the
  * scheduling-clock interrupt.
  */
-void rcu_check_callbacks(int cpu, int user)
+void rcu_check_callbacks(int user)
 {
        RCU_TRACE(check_cpu_stalls());
        if (user || rcu_is_cpu_rrupt_from_idle())
@@ -380,7 +380,9 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
 }
 EXPORT_SYMBOL_GPL(call_rcu_bh);
 
-void rcu_init(void)
+void __init rcu_init(void)
 {
        open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
+
+       rcu_early_boot_tests();
 }
index 133e47223095d76fd1203f949a955009d1075688..7680fc2750361a91fc8f749a006555899aa92677 100644 (file)
@@ -105,7 +105,7 @@ struct rcu_state sname##_state = { \
        .name = RCU_STATE_NAME(sname), \
        .abbr = sabbr, \
 }; \
-DEFINE_PER_CPU(struct rcu_data, sname##_data)
+DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, sname##_data)
 
 RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched);
 RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh);
@@ -152,19 +152,6 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);
  */
 static int rcu_scheduler_fully_active __read_mostly;
 
-#ifdef CONFIG_RCU_BOOST
-
-/*
- * Control variables for per-CPU and per-rcu_node kthreads.  These
- * handle all flavors of RCU.
- */
-static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);
-DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
-DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
-DEFINE_PER_CPU(char, rcu_cpu_has_work);
-
-#endif /* #ifdef CONFIG_RCU_BOOST */
-
 static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu);
 static void invoke_rcu_core(void);
 static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
@@ -286,11 +273,11 @@ static void rcu_momentary_dyntick_idle(void)
  * and requires special handling for preemptible RCU.
  * The caller must have disabled preemption.
  */
-void rcu_note_context_switch(int cpu)
+void rcu_note_context_switch(void)
 {
        trace_rcu_utilization(TPS("Start context switch"));
        rcu_sched_qs();
-       rcu_preempt_note_context_switch(cpu);
+       rcu_preempt_note_context_switch();
        if (unlikely(raw_cpu_read(rcu_sched_qs_mask)))
                rcu_momentary_dyntick_idle();
        trace_rcu_utilization(TPS("End context switch"));
@@ -325,7 +312,7 @@ static void force_qs_rnp(struct rcu_state *rsp,
                                  unsigned long *maxj),
                         bool *isidle, unsigned long *maxj);
 static void force_quiescent_state(struct rcu_state *rsp);
-static int rcu_pending(int cpu);
+static int rcu_pending(void);
 
 /*
  * Return the number of RCU-sched batches processed thus far for debug & stats.
@@ -510,11 +497,11 @@ cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
  * we really have entered idle, and must do the appropriate accounting.
  * The caller must have disabled interrupts.
  */
-static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
-                               bool user)
+static void rcu_eqs_enter_common(long long oldval, bool user)
 {
        struct rcu_state *rsp;
        struct rcu_data *rdp;
+       struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 
        trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting);
        if (!user && !is_idle_task(current)) {
@@ -531,7 +518,7 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
                rdp = this_cpu_ptr(rsp->rda);
                do_nocb_deferred_wakeup(rdp);
        }
-       rcu_prepare_for_idle(smp_processor_id());
+       rcu_prepare_for_idle();
        /* CPUs seeing atomic_inc() must see prior RCU read-side crit sects */
        smp_mb__before_atomic();  /* See above. */
        atomic_inc(&rdtp->dynticks);
@@ -565,7 +552,7 @@ static void rcu_eqs_enter(bool user)
        WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0);
        if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE) {
                rdtp->dynticks_nesting = 0;
-               rcu_eqs_enter_common(rdtp, oldval, user);
+               rcu_eqs_enter_common(oldval, user);
        } else {
                rdtp->dynticks_nesting -= DYNTICK_TASK_NEST_VALUE;
        }
@@ -589,7 +576,7 @@ void rcu_idle_enter(void)
 
        local_irq_save(flags);
        rcu_eqs_enter(false);
-       rcu_sysidle_enter(this_cpu_ptr(&rcu_dynticks), 0);
+       rcu_sysidle_enter(0);
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(rcu_idle_enter);
@@ -639,8 +626,8 @@ void rcu_irq_exit(void)
        if (rdtp->dynticks_nesting)
                trace_rcu_dyntick(TPS("--="), oldval, rdtp->dynticks_nesting);
        else
-               rcu_eqs_enter_common(rdtp, oldval, true);
-       rcu_sysidle_enter(rdtp, 1);
+               rcu_eqs_enter_common(oldval, true);
+       rcu_sysidle_enter(1);
        local_irq_restore(flags);
 }
 
@@ -651,16 +638,17 @@ void rcu_irq_exit(void)
  * we really have exited idle, and must do the appropriate accounting.
  * The caller must have disabled interrupts.
  */
-static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval,
-                              int user)
+static void rcu_eqs_exit_common(long long oldval, int user)
 {
+       struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
+
        rcu_dynticks_task_exit();
        smp_mb__before_atomic();  /* Force ordering w/previous sojourn. */
        atomic_inc(&rdtp->dynticks);
        /* CPUs seeing atomic_inc() must see later RCU read-side crit sects */
        smp_mb__after_atomic();  /* See above. */
        WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1));
-       rcu_cleanup_after_idle(smp_processor_id());
+       rcu_cleanup_after_idle();
        trace_rcu_dyntick(TPS("End"), oldval, rdtp->dynticks_nesting);
        if (!user && !is_idle_task(current)) {
                struct task_struct *idle __maybe_unused =
@@ -691,7 +679,7 @@ static void rcu_eqs_exit(bool user)
                rdtp->dynticks_nesting += DYNTICK_TASK_NEST_VALUE;
        } else {
                rdtp->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
-               rcu_eqs_exit_common(rdtp, oldval, user);
+               rcu_eqs_exit_common(oldval, user);
        }
 }
 
@@ -712,7 +700,7 @@ void rcu_idle_exit(void)
 
        local_irq_save(flags);
        rcu_eqs_exit(false);
-       rcu_sysidle_exit(this_cpu_ptr(&rcu_dynticks), 0);
+       rcu_sysidle_exit(0);
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(rcu_idle_exit);
@@ -763,8 +751,8 @@ void rcu_irq_enter(void)
        if (oldval)
                trace_rcu_dyntick(TPS("++="), oldval, rdtp->dynticks_nesting);
        else
-               rcu_eqs_exit_common(rdtp, oldval, true);
-       rcu_sysidle_exit(rdtp, 1);
+               rcu_eqs_exit_common(oldval, true);
+       rcu_sysidle_exit(1);
        local_irq_restore(flags);
 }
 
@@ -2387,7 +2375,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
  * invoked from the scheduling-clock interrupt.  If rcu_pending returns
  * false, there is no point in invoking rcu_check_callbacks().
  */
-void rcu_check_callbacks(int cpu, int user)
+void rcu_check_callbacks(int user)
 {
        trace_rcu_utilization(TPS("Start scheduler-tick"));
        increment_cpu_stall_ticks();
@@ -2419,8 +2407,8 @@ void rcu_check_callbacks(int cpu, int user)
 
                rcu_bh_qs();
        }
-       rcu_preempt_check_callbacks(cpu);
-       if (rcu_pending(cpu))
+       rcu_preempt_check_callbacks();
+       if (rcu_pending())
                invoke_rcu_core();
        if (user)
                rcu_note_voluntary_context_switch(current);
@@ -2963,6 +2951,9 @@ static int synchronize_sched_expedited_cpu_stop(void *data)
  */
 void synchronize_sched_expedited(void)
 {
+       cpumask_var_t cm;
+       bool cma = false;
+       int cpu;
        long firstsnap, s, snap;
        int trycount = 0;
        struct rcu_state *rsp = &rcu_sched_state;
@@ -2997,11 +2988,26 @@ void synchronize_sched_expedited(void)
        }
        WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id()));
 
+       /* Offline CPUs, idle CPUs, and any CPU we run on are quiescent. */
+       cma = zalloc_cpumask_var(&cm, GFP_KERNEL);
+       if (cma) {
+               cpumask_copy(cm, cpu_online_mask);
+               cpumask_clear_cpu(raw_smp_processor_id(), cm);
+               for_each_cpu(cpu, cm) {
+                       struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+
+                       if (!(atomic_add_return(0, &rdtp->dynticks) & 0x1))
+                               cpumask_clear_cpu(cpu, cm);
+               }
+               if (cpumask_weight(cm) == 0)
+                       goto all_cpus_idle;
+       }
+
        /*
         * Each pass through the following loop attempts to force a
         * context switch on each CPU.
         */
-       while (try_stop_cpus(cpu_online_mask,
+       while (try_stop_cpus(cma ? cm : cpu_online_mask,
                             synchronize_sched_expedited_cpu_stop,
                             NULL) == -EAGAIN) {
                put_online_cpus();
@@ -3013,6 +3019,7 @@ void synchronize_sched_expedited(void)
                        /* ensure test happens before caller kfree */
                        smp_mb__before_atomic(); /* ^^^ */
                        atomic_long_inc(&rsp->expedited_workdone1);
+                       free_cpumask_var(cm);
                        return;
                }
 
@@ -3022,6 +3029,7 @@ void synchronize_sched_expedited(void)
                } else {
                        wait_rcu_gp(call_rcu_sched);
                        atomic_long_inc(&rsp->expedited_normal);
+                       free_cpumask_var(cm);
                        return;
                }
 
@@ -3031,6 +3039,7 @@ void synchronize_sched_expedited(void)
                        /* ensure test happens before caller kfree */
                        smp_mb__before_atomic(); /* ^^^ */
                        atomic_long_inc(&rsp->expedited_workdone2);
+                       free_cpumask_var(cm);
                        return;
                }
 
@@ -3045,6 +3054,7 @@ void synchronize_sched_expedited(void)
                        /* CPU hotplug operation in flight, use normal GP. */
                        wait_rcu_gp(call_rcu_sched);
                        atomic_long_inc(&rsp->expedited_normal);
+                       free_cpumask_var(cm);
                        return;
                }
                snap = atomic_long_read(&rsp->expedited_start);
@@ -3052,6 +3062,9 @@ void synchronize_sched_expedited(void)
        }
        atomic_long_inc(&rsp->expedited_stoppedcpus);
 
+all_cpus_idle:
+       free_cpumask_var(cm);
+
        /*
         * Everyone up to our most recent fetch is covered by our grace
         * period.  Update the counter, but only if our work is still
@@ -3143,12 +3156,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
  * by the current CPU, returning 1 if so.  This function is part of the
  * RCU implementation; it is -not- an exported member of the RCU API.
  */
-static int rcu_pending(int cpu)
+static int rcu_pending(void)
 {
        struct rcu_state *rsp;
 
        for_each_rcu_flavor(rsp)
-               if (__rcu_pending(rsp, per_cpu_ptr(rsp->rda, cpu)))
+               if (__rcu_pending(rsp, this_cpu_ptr(rsp->rda)))
                        return 1;
        return 0;
 }
@@ -3158,7 +3171,7 @@ static int rcu_pending(int cpu)
  * non-NULL, store an indication of whether all callbacks are lazy.
  * (If there are no callbacks, all of them are deemed to be lazy.)
  */
-static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
+static int __maybe_unused rcu_cpu_has_callbacks(bool *all_lazy)
 {
        bool al = true;
        bool hc = false;
@@ -3166,7 +3179,7 @@ static int __maybe_unused rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
        struct rcu_state *rsp;
 
        for_each_rcu_flavor(rsp) {
-               rdp = per_cpu_ptr(rsp->rda, cpu);
+               rdp = this_cpu_ptr(rsp->rda);
                if (!rdp->nxtlist)
                        continue;
                hc = true;
@@ -3299,11 +3312,16 @@ static void _rcu_barrier(struct rcu_state *rsp)
                        continue;
                rdp = per_cpu_ptr(rsp->rda, cpu);
                if (rcu_is_nocb_cpu(cpu)) {
-                       _rcu_barrier_trace(rsp, "OnlineNoCB", cpu,
-                                          rsp->n_barrier_done);
-                       atomic_inc(&rsp->barrier_cpu_count);
-                       __call_rcu(&rdp->barrier_head, rcu_barrier_callback,
-                                  rsp, cpu, 0);
+                       if (!rcu_nocb_cpu_needs_barrier(rsp, cpu)) {
+                               _rcu_barrier_trace(rsp, "OfflineNoCB", cpu,
+                                                  rsp->n_barrier_done);
+                       } else {
+                               _rcu_barrier_trace(rsp, "OnlineNoCB", cpu,
+                                                  rsp->n_barrier_done);
+                               atomic_inc(&rsp->barrier_cpu_count);
+                               __call_rcu(&rdp->barrier_head,
+                                          rcu_barrier_callback, rsp, cpu, 0);
+                       }
                } else if (ACCESS_ONCE(rdp->qlen)) {
                        _rcu_barrier_trace(rsp, "OnlineQ", cpu,
                                           rsp->n_barrier_done);
@@ -3480,8 +3498,10 @@ static int rcu_cpu_notify(struct notifier_block *self,
        case CPU_DEAD_FROZEN:
        case CPU_UP_CANCELED:
        case CPU_UP_CANCELED_FROZEN:
-               for_each_rcu_flavor(rsp)
+               for_each_rcu_flavor(rsp) {
                        rcu_cleanup_dead_cpu(cpu, rsp);
+                       do_nocb_deferred_wakeup(per_cpu_ptr(rsp->rda, cpu));
+               }
                break;
        default:
                break;
@@ -3761,6 +3781,8 @@ void __init rcu_init(void)
        pm_notifier(rcu_pm_notify, 0);
        for_each_online_cpu(cpu)
                rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
+
+       rcu_early_boot_tests();
 }
 
 #include "tree_plugin.h"
index d03764652d910cb6b8e7f4039ee184ff549187eb..8e7b1843896ebcc0fe13ed51da7cea68f14f0a36 100644 (file)
@@ -139,7 +139,7 @@ struct rcu_node {
        unsigned long expmask;  /* Groups that have ->blkd_tasks */
                                /*  elements that need to drain to allow the */
                                /*  current expedited grace period to */
-                               /*  complete (only for TREE_PREEMPT_RCU). */
+                               /*  complete (only for PREEMPT_RCU). */
        unsigned long qsmaskinit;
                                /* Per-GP initial value for qsmask & expmask. */
        unsigned long grpmask;  /* Mask to apply to parent qsmask. */
@@ -530,10 +530,10 @@ DECLARE_PER_CPU(struct rcu_data, rcu_sched_data);
 extern struct rcu_state rcu_bh_state;
 DECLARE_PER_CPU(struct rcu_data, rcu_bh_data);
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
 extern struct rcu_state rcu_preempt_state;
 DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
+#endif /* #ifdef CONFIG_PREEMPT_RCU */
 
 #ifdef CONFIG_RCU_BOOST
 DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
@@ -547,7 +547,7 @@ DECLARE_PER_CPU(char, rcu_cpu_has_work);
 /* Forward declarations for rcutree_plugin.h */
 static void rcu_bootup_announce(void);
 long rcu_batches_completed(void);
-static void rcu_preempt_note_context_switch(int cpu);
+static void rcu_preempt_note_context_switch(void);
 static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
@@ -561,12 +561,12 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
                                     struct rcu_node *rnp,
                                     struct rcu_data *rdp);
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
-static void rcu_preempt_check_callbacks(int cpu);
+static void rcu_preempt_check_callbacks(void);
 void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU)
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PREEMPT_RCU)
 static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
                               bool wake);
-#endif /* #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) */
+#endif /* #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PREEMPT_RCU) */
 static void __init __rcu_init_preempt(void);
 static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags);
 static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
@@ -579,14 +579,15 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
 #endif /* #ifdef CONFIG_RCU_BOOST */
 static void __init rcu_spawn_boost_kthreads(void);
 static void rcu_prepare_kthreads(int cpu);
-static void rcu_cleanup_after_idle(int cpu);
-static void rcu_prepare_for_idle(int cpu);
+static void rcu_cleanup_after_idle(void);
+static void rcu_prepare_for_idle(void);
 static void rcu_idle_count_callbacks_posted(void);
 static void print_cpu_stall_info_begin(void);
 static void print_cpu_stall_info(struct rcu_state *rsp, int cpu);
 static void print_cpu_stall_info_end(void);
 static void zero_cpu_stall_ticks(struct rcu_data *rdp);
 static void increment_cpu_stall_ticks(void);
+static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu);
 static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq);
 static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp);
 static void rcu_init_one_nocb(struct rcu_node *rnp);
@@ -605,8 +606,8 @@ static void __init rcu_organize_nocb_kthreads(struct rcu_state *rsp);
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
 static void __maybe_unused rcu_kick_nohz_cpu(int cpu);
 static bool init_nocb_callback_list(struct rcu_data *rdp);
-static void rcu_sysidle_enter(struct rcu_dynticks *rdtp, int irq);
-static void rcu_sysidle_exit(struct rcu_dynticks *rdtp, int irq);
+static void rcu_sysidle_enter(int irq);
+static void rcu_sysidle_exit(int irq);
 static void rcu_sysidle_check_cpu(struct rcu_data *rdp, bool *isidle,
                                  unsigned long *maxj);
 static bool is_sysidle_rcu_state(struct rcu_state *rsp);
index 387dd45993449f7a54310fd936693bbc16611f5b..3ec85cb5d544b8588fd574a80e19bd564079533f 100644 (file)
 #include <linux/smpboot.h>
 #include "../time/tick-internal.h"
 
-#define RCU_KTHREAD_PRIO 1
-
 #ifdef CONFIG_RCU_BOOST
+
 #include "../locking/rtmutex_common.h"
-#define RCU_BOOST_PRIO CONFIG_RCU_BOOST_PRIO
-#else
-#define RCU_BOOST_PRIO RCU_KTHREAD_PRIO
-#endif
+
+/* rcuc/rcub kthread realtime priority */
+static int kthread_prio = CONFIG_RCU_KTHREAD_PRIO;
+module_param(kthread_prio, int, 0644);
+
+/*
+ * Control variables for per-CPU and per-rcu_node kthreads.  These
+ * handle all flavors of RCU.
+ */
+static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);
+DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
+DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
+DEFINE_PER_CPU(char, rcu_cpu_has_work);
+
+#endif /* #ifdef CONFIG_RCU_BOOST */
 
 #ifdef CONFIG_RCU_NOCB_CPU
 static cpumask_var_t rcu_nocb_mask; /* CPUs to have callbacks offloaded. */
@@ -72,9 +82,6 @@ static void __init rcu_bootup_announce_oddness(void)
 #ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE
        pr_info("\tRCU torture testing starts during boot.\n");
 #endif
-#if defined(CONFIG_TREE_PREEMPT_RCU) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE)
-       pr_info("\tDump stacks of tasks blocking RCU-preempt GP.\n");
-#endif
 #if defined(CONFIG_RCU_CPU_STALL_INFO)
        pr_info("\tAdditional per-CPU info printed with stalls.\n");
 #endif
@@ -85,9 +92,12 @@ static void __init rcu_bootup_announce_oddness(void)
                pr_info("\tBoot-time adjustment of leaf fanout to %d.\n", rcu_fanout_leaf);
        if (nr_cpu_ids != NR_CPUS)
                pr_info("\tRCU restricting CPUs from NR_CPUS=%d to nr_cpu_ids=%d.\n", NR_CPUS, nr_cpu_ids);
+#ifdef CONFIG_RCU_BOOST
+       pr_info("\tRCU kthread priority: %d.\n", kthread_prio);
+#endif
 }
 
-#ifdef CONFIG_TREE_PREEMPT_RCU
+#ifdef CONFIG_PREEMPT_RCU
 
 RCU_STATE_INITIALIZER(rcu_preempt, 'p', call_rcu);
 static struct rcu_state *rcu_state_p = &rcu_preempt_state;
@@ -156,7 +166,7 @@ static void rcu_preempt_qs(void)
  *
  * Caller must disable preemption.
  */
-static void rcu_preempt_note_context_switch(int cpu)
+static void rcu_preempt_note_context_switch(void)
 {
        struct task_struct *t = current;
        unsigned long flags;
@@ -167,7 +177,7 @@ static void rcu_preempt_note_context_switch(int cpu)
            !t->rcu_read_unlock_special.b.blocked) {
 
                /* Possibly blocking in an RCU read-side critical section. */
-               rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
+               rdp = this_cpu_ptr(rcu_preempt_state.rda);
                rnp = rdp->mynode;
                raw_spin_lock_irqsave(&rnp->lock, flags);
                smp_mb__after_unlock_lock();
@@ -415,8 +425,6 @@ void rcu_read_unlock_special(struct task_struct *t)
        }
 }
 
-#ifdef CONFIG_RCU_CPU_STALL_VERBOSE
-
 /*
  * Dump detailed information for all tasks blocking the current RCU
  * grace period on the specified rcu_node structure.
@@ -451,14 +459,6 @@ static void rcu_print_detail_task_stall(struct rcu_state *rsp)
                rcu_print_detail_task_stall_rnp(rnp);
 }
 
-#else /* #ifdef CONFIG_RCU_CPU_STALL_VERBOSE */
-
-static void rcu_print_detail_task_stall(struct rcu_state *rsp)
-{
-}
-
-#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_VERBOSE */
-
 #ifdef CONFIG_RCU_CPU_STALL_INFO
 
 static void rcu_print_task_stall_begin(struct rcu_node *rnp)
@@ -621,7 +621,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
  *
  * Caller must disable hard irqs.
  */
-static void rcu_preempt_check_callbacks(int cpu)
+static void rcu_preempt_check_callbacks(void)
 {
        struct task_struct *t = current;
 
@@ -630,8 +630,8 @@ static void rcu_preempt_check_callbacks(int cpu)
                return;
        }
        if (t->rcu_read_lock_nesting > 0 &&
-           per_cpu(rcu_preempt_data, cpu).qs_pending &&
-           !per_cpu(rcu_preempt_data, cpu).passed_quiesce)
+           __this_cpu_read(rcu_preempt_data.qs_pending) &&
+           !__this_cpu_read(rcu_preempt_data.passed_quiesce))
                t->rcu_read_unlock_special.b.need_qs = true;
 }
 
@@ -919,7 +919,7 @@ void exit_rcu(void)
        __rcu_read_unlock();
 }
 
-#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
+#else /* #ifdef CONFIG_PREEMPT_RCU */
 
 static struct rcu_state *rcu_state_p = &rcu_sched_state;
 
@@ -945,7 +945,7 @@ EXPORT_SYMBOL_GPL(rcu_batches_completed);
  * Because preemptible RCU does not exist, we never have to check for
  * CPUs being in quiescent states.
  */
-static void rcu_preempt_note_context_switch(int cpu)
+static void rcu_preempt_note_context_switch(void)
 {
 }
 
@@ -1017,7 +1017,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
  * Because preemptible RCU does not exist, it never has any callbacks
  * to check.
  */
-static void rcu_preempt_check_callbacks(int cpu)
+static void rcu_preempt_check_callbacks(void)
 {
 }
 
@@ -1070,7 +1070,7 @@ void exit_rcu(void)
 {
 }
 
-#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
+#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
 
 #ifdef CONFIG_RCU_BOOST
 
@@ -1326,7 +1326,7 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
        smp_mb__after_unlock_lock();
        rnp->boost_kthread_task = t;
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
-       sp.sched_priority = RCU_BOOST_PRIO;
+       sp.sched_priority = kthread_prio;
        sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
        wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */
        return 0;
@@ -1343,7 +1343,7 @@ static void rcu_cpu_kthread_setup(unsigned int cpu)
 {
        struct sched_param sp;
 
-       sp.sched_priority = RCU_KTHREAD_PRIO;
+       sp.sched_priority = kthread_prio;
        sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
 }
 
@@ -1512,10 +1512,10 @@ static void rcu_prepare_kthreads(int cpu)
  * any flavor of RCU.
  */
 #ifndef CONFIG_RCU_NOCB_CPU_ALL
-int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
+int rcu_needs_cpu(unsigned long *delta_jiffies)
 {
        *delta_jiffies = ULONG_MAX;
-       return rcu_cpu_has_callbacks(cpu, NULL);
+       return rcu_cpu_has_callbacks(NULL);
 }
 #endif /* #ifndef CONFIG_RCU_NOCB_CPU_ALL */
 
@@ -1523,7 +1523,7 @@ int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
  * Because we do not have RCU_FAST_NO_HZ, don't bother cleaning up
  * after it.
  */
-static void rcu_cleanup_after_idle(int cpu)
+static void rcu_cleanup_after_idle(void)
 {
 }
 
@@ -1531,7 +1531,7 @@ static void rcu_cleanup_after_idle(int cpu)
  * Do the idle-entry grace-period work, which, because CONFIG_RCU_FAST_NO_HZ=n,
  * is nothing.
  */
-static void rcu_prepare_for_idle(int cpu)
+static void rcu_prepare_for_idle(void)
 {
 }
 
@@ -1624,15 +1624,15 @@ static bool __maybe_unused rcu_try_advance_all_cbs(void)
  * The caller must have disabled interrupts.
  */
 #ifndef CONFIG_RCU_NOCB_CPU_ALL
-int rcu_needs_cpu(int cpu, unsigned long *dj)
+int rcu_needs_cpu(unsigned long *dj)
 {
-       struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+       struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 
        /* Snapshot to detect later posting of non-lazy callback. */
        rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
 
        /* If no callbacks, RCU doesn't need the CPU. */
-       if (!rcu_cpu_has_callbacks(cpu, &rdtp->all_lazy)) {
+       if (!rcu_cpu_has_callbacks(&rdtp->all_lazy)) {
                *dj = ULONG_MAX;
                return 0;
        }
@@ -1666,12 +1666,12 @@ int rcu_needs_cpu(int cpu, unsigned long *dj)
  *
  * The caller must have disabled interrupts.
  */
-static void rcu_prepare_for_idle(int cpu)
+static void rcu_prepare_for_idle(void)
 {
 #ifndef CONFIG_RCU_NOCB_CPU_ALL
        bool needwake;
        struct rcu_data *rdp;
-       struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+       struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
        struct rcu_node *rnp;
        struct rcu_state *rsp;
        int tne;
@@ -1679,7 +1679,7 @@ static void rcu_prepare_for_idle(int cpu)
        /* Handle nohz enablement switches conservatively. */
        tne = ACCESS_ONCE(tick_nohz_active);
        if (tne != rdtp->tick_nohz_enabled_snap) {
-               if (rcu_cpu_has_callbacks(cpu, NULL))
+               if (rcu_cpu_has_callbacks(NULL))
                        invoke_rcu_core(); /* force nohz to see update. */
                rdtp->tick_nohz_enabled_snap = tne;
                return;
@@ -1688,7 +1688,7 @@ static void rcu_prepare_for_idle(int cpu)
                return;
 
        /* If this is a no-CBs CPU, no callbacks, just return. */
-       if (rcu_is_nocb_cpu(cpu))
+       if (rcu_is_nocb_cpu(smp_processor_id()))
                return;
 
        /*
@@ -1712,7 +1712,7 @@ static void rcu_prepare_for_idle(int cpu)
                return;
        rdtp->last_accelerate = jiffies;
        for_each_rcu_flavor(rsp) {
-               rdp = per_cpu_ptr(rsp->rda, cpu);
+               rdp = this_cpu_ptr(rsp->rda);
                if (!*rdp->nxttail[RCU_DONE_TAIL])
                        continue;
                rnp = rdp->mynode;
@@ -1731,10 +1731,10 @@ static void rcu_prepare_for_idle(int cpu)
  * any grace periods that elapsed while the CPU was idle, and if any
  * callbacks are now ready to invoke, initiate invocation.
  */
-static void rcu_cleanup_after_idle(int cpu)
+static void rcu_cleanup_after_idle(void)
 {
 #ifndef CONFIG_RCU_NOCB_CPU_ALL
-       if (rcu_is_nocb_cpu(cpu))
+       if (rcu_is_nocb_cpu(smp_processor_id()))
                return;
        if (rcu_try_advance_all_cbs())
                invoke_rcu_core();
@@ -2049,6 +2049,33 @@ static void wake_nocb_leader(struct rcu_data *rdp, bool force)
        }
 }
 
+/*
+ * Does the specified CPU need an RCU callback for the specified flavor
+ * of rcu_barrier()?
+ */
+static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu)
+{
+       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
+       struct rcu_head *rhp;
+
+       /* No-CBs CPUs might have callbacks on any of three lists. */
+       rhp = ACCESS_ONCE(rdp->nocb_head);
+       if (!rhp)
+               rhp = ACCESS_ONCE(rdp->nocb_gp_head);
+       if (!rhp)
+               rhp = ACCESS_ONCE(rdp->nocb_follower_head);
+
+       /* Having no rcuo kthread but CBs after scheduler starts is bad! */
+       if (!ACCESS_ONCE(rdp->nocb_kthread) && rhp) {
+               /* RCU callback enqueued before CPU first came online??? */
+               pr_err("RCU: Never-onlined no-CBs CPU %d has CB %p\n",
+                      cpu, rhp->func);
+               WARN_ON_ONCE(1);
+       }
+
+       return !!rhp;
+}
+
 /*
  * Enqueue the specified string of rcu_head structures onto the specified
  * CPU's no-CBs lists.  The CPU is specified by rdp, the head of the
@@ -2546,9 +2573,13 @@ static void rcu_spawn_one_nocb_kthread(struct rcu_state *rsp, int cpu)
                        rdp->nocb_leader = rdp_spawn;
                        if (rdp_last && rdp != rdp_spawn)
                                rdp_last->nocb_next_follower = rdp;
-                       rdp_last = rdp;
-                       rdp = rdp->nocb_next_follower;
-                       rdp_last->nocb_next_follower = NULL;
+                       if (rdp == rdp_spawn) {
+                               rdp = rdp->nocb_next_follower;
+                       } else {
+                               rdp_last = rdp;
+                               rdp = rdp->nocb_next_follower;
+                               rdp_last->nocb_next_follower = NULL;
+                       }
                } while (rdp);
                rdp_spawn->nocb_next_follower = rdp_old_leader;
        }
@@ -2642,6 +2673,12 @@ static bool init_nocb_callback_list(struct rcu_data *rdp)
 
 #else /* #ifdef CONFIG_RCU_NOCB_CPU */
 
+static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu)
+{
+       WARN_ON_ONCE(1); /* Should be dead code. */
+       return false;
+}
+
 static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
 {
 }
@@ -2728,9 +2765,10 @@ static int full_sysidle_state;           /* Current system-idle state. */
  * to detect full-system idle states, not RCU quiescent states and grace
  * periods.  The caller must have disabled interrupts.
  */
-static void rcu_sysidle_enter(struct rcu_dynticks *rdtp, int irq)
+static void rcu_sysidle_enter(int irq)
 {
        unsigned long j;
+       struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 
        /* If there are no nohz_full= CPUs, no need to track this. */
        if (!tick_nohz_full_enabled())
@@ -2799,8 +2837,10 @@ void rcu_sysidle_force_exit(void)
  * usermode execution does -not- count as idle here!  The caller must
  * have disabled interrupts.
  */
-static void rcu_sysidle_exit(struct rcu_dynticks *rdtp, int irq)
+static void rcu_sysidle_exit(int irq)
 {
+       struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
+
        /* If there are no nohz_full= CPUs, no need to track this. */
        if (!tick_nohz_full_enabled())
                return;
@@ -3094,11 +3134,11 @@ static void rcu_sysidle_init_percpu_data(struct rcu_dynticks *rdtp)
 
 #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
 
-static void rcu_sysidle_enter(struct rcu_dynticks *rdtp, int irq)
+static void rcu_sysidle_enter(int irq)
 {
 }
 
-static void rcu_sysidle_exit(struct rcu_dynticks *rdtp, int irq)
+static void rcu_sysidle_exit(int irq)
 {
 }
 
index 3ef8ba58694e95190e326986a252a276c9d721ed..e0d31a345ee6574fa5d7c949a8165f8374a9909f 100644 (file)
@@ -306,7 +306,7 @@ struct debug_obj_descr rcuhead_debug_descr = {
 EXPORT_SYMBOL_GPL(rcuhead_debug_descr);
 #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
-#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) || defined(CONFIG_RCU_TRACE)
+#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU) || defined(CONFIG_RCU_TRACE)
 void do_trace_rcu_torture_read(const char *rcutorturename, struct rcu_head *rhp,
                               unsigned long secs,
                               unsigned long c_old, unsigned long c)
@@ -531,7 +531,8 @@ static int __noreturn rcu_tasks_kthread(void *arg)
        struct rcu_head *next;
        LIST_HEAD(rcu_tasks_holdouts);
 
-       /* FIXME: Add housekeeping affinity. */
+       /* Run on housekeeping CPUs by default.  Sysadm can move if desired. */
+       housekeeping_affine(current);
 
        /*
         * Each pass through the following loop makes one check for
@@ -690,3 +691,87 @@ static void rcu_spawn_tasks_kthread(void)
 }
 
 #endif /* #ifdef CONFIG_TASKS_RCU */
+
+#ifdef CONFIG_PROVE_RCU
+
+/*
+ * Early boot self test parameters, one for each flavor
+ */
+static bool rcu_self_test;
+static bool rcu_self_test_bh;
+static bool rcu_self_test_sched;
+
+module_param(rcu_self_test, bool, 0444);
+module_param(rcu_self_test_bh, bool, 0444);
+module_param(rcu_self_test_sched, bool, 0444);
+
+static int rcu_self_test_counter;
+
+static void test_callback(struct rcu_head *r)
+{
+       rcu_self_test_counter++;
+       pr_info("RCU test callback executed %d\n", rcu_self_test_counter);
+}
+
+static void early_boot_test_call_rcu(void)
+{
+       static struct rcu_head head;
+
+       call_rcu(&head, test_callback);
+}
+
+static void early_boot_test_call_rcu_bh(void)
+{
+       static struct rcu_head head;
+
+       call_rcu_bh(&head, test_callback);
+}
+
+static void early_boot_test_call_rcu_sched(void)
+{
+       static struct rcu_head head;
+
+       call_rcu_sched(&head, test_callback);
+}
+
+void rcu_early_boot_tests(void)
+{
+       pr_info("Running RCU self tests\n");
+
+       if (rcu_self_test)
+               early_boot_test_call_rcu();
+       if (rcu_self_test_bh)
+               early_boot_test_call_rcu_bh();
+       if (rcu_self_test_sched)
+               early_boot_test_call_rcu_sched();
+}
+
+static int rcu_verify_early_boot_tests(void)
+{
+       int ret = 0;
+       int early_boot_test_counter = 0;
+
+       if (rcu_self_test) {
+               early_boot_test_counter++;
+               rcu_barrier();
+       }
+       if (rcu_self_test_bh) {
+               early_boot_test_counter++;
+               rcu_barrier_bh();
+       }
+       if (rcu_self_test_sched) {
+               early_boot_test_counter++;
+               rcu_barrier_sched();
+       }
+
+       if (rcu_self_test_counter != early_boot_test_counter) {
+               WARN_ON(1);
+               ret = -1;
+       }
+
+       return ret;
+}
+late_initcall(rcu_verify_early_boot_tests);
+#else
+void rcu_early_boot_tests(void) {}
+#endif /* CONFIG_PROVE_RCU */
index a63f4dc27909eededd3b5bd04febb2fab6d84280..607f852b4d04ab3b70379bf42528aa40e5f588c7 100644 (file)
@@ -148,7 +148,7 @@ EXPORT_SYMBOL(wait_for_completion_timeout);
  *
  * This waits to be signaled for completion of a specific task. It is NOT
  * interruptible and there is no timeout. The caller is accounted as waiting
- * for IO.
+ * for IO (which traditionally means blkio only).
  */
 void __sched wait_for_completion_io(struct completion *x)
 {
@@ -163,7 +163,8 @@ EXPORT_SYMBOL(wait_for_completion_io);
  *
  * This waits for either a completion of a specific task to be signaled or for a
  * specified timeout to expire. The timeout is in jiffies. It is not
- * interruptible. The caller is accounted as waiting for IO.
+ * interruptible. The caller is accounted as waiting for IO (which traditionally
+ * means blkio only).
  *
  * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
  * till timeout) if completed.
index 44999505e1bf6894bdcdb48531a49e5a07b88ac5..bb398c0c5f0850d42caf3b04aa5937b96be6a8b8 100644 (file)
@@ -1008,6 +1008,9 @@ inline int task_curr(const struct task_struct *p)
        return cpu_curr(task_cpu(p)) == p;
 }
 
+/*
+ * Can drop rq->lock because from sched_class::switched_from() methods drop it.
+ */
 static inline void check_class_changed(struct rq *rq, struct task_struct *p,
                                       const struct sched_class *prev_class,
                                       int oldprio)
@@ -1015,6 +1018,7 @@ static inline void check_class_changed(struct rq *rq, struct task_struct *p,
        if (prev_class != p->sched_class) {
                if (prev_class->switched_from)
                        prev_class->switched_from(rq, p);
+               /* Possble rq->lock 'hole'.  */
                p->sched_class->switched_to(rq, p);
        } else if (oldprio != p->prio || dl_task(p))
                p->sched_class->prio_changed(rq, p, oldprio);
@@ -1054,7 +1058,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
         * ttwu() will sort out the placement.
         */
        WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING &&
-                       !(task_preempt_count(p) & PREEMPT_ACTIVE));
+                       !p->on_rq);
 
 #ifdef CONFIG_LOCKDEP
        /*
@@ -1407,7 +1411,8 @@ out:
 static inline
 int select_task_rq(struct task_struct *p, int cpu, int sd_flags, int wake_flags)
 {
-       cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags);
+       if (p->nr_cpus_allowed > 1)
+               cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags);
 
        /*
         * In order not to call set_task_cpu() on a blocking task we need
@@ -1623,8 +1628,10 @@ void wake_up_if_idle(int cpu)
        struct rq *rq = cpu_rq(cpu);
        unsigned long flags;
 
-       if (!is_idle_task(rq->curr))
-               return;
+       rcu_read_lock();
+
+       if (!is_idle_task(rcu_dereference(rq->curr)))
+               goto out;
 
        if (set_nr_if_polling(rq->idle)) {
                trace_sched_wake_idle_without_ipi(cpu);
@@ -1635,6 +1642,9 @@ void wake_up_if_idle(int cpu)
                /* Else cpu is not in idle, do nothing here */
                raw_spin_unlock_irqrestore(&rq->lock, flags);
        }
+
+out:
+       rcu_read_unlock();
 }
 
 bool cpus_share_cache(int this_cpu, int that_cpu)
@@ -1853,12 +1863,10 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
        p->numa_scan_seq = p->mm ? p->mm->numa_scan_seq : 0;
        p->numa_scan_period = sysctl_numa_balancing_scan_delay;
        p->numa_work.next = &p->numa_work;
-       p->numa_faults_memory = NULL;
-       p->numa_faults_buffer_memory = NULL;
+       p->numa_faults = NULL;
        p->last_task_numa_placement = 0;
        p->last_sum_exec_runtime = 0;
 
-       INIT_LIST_HEAD(&p->numa_entry);
        p->numa_group = NULL;
 #endif /* CONFIG_NUMA_BALANCING */
 }
@@ -2034,25 +2042,6 @@ static inline int dl_bw_cpus(int i)
 }
 #endif
 
-static inline
-void __dl_clear(struct dl_bw *dl_b, u64 tsk_bw)
-{
-       dl_b->total_bw -= tsk_bw;
-}
-
-static inline
-void __dl_add(struct dl_bw *dl_b, u64 tsk_bw)
-{
-       dl_b->total_bw += tsk_bw;
-}
-
-static inline
-bool __dl_overflow(struct dl_bw *dl_b, int cpus, u64 old_bw, u64 new_bw)
-{
-       return dl_b->bw != -1 &&
-              dl_b->bw * cpus < dl_b->total_bw - old_bw + new_bw;
-}
-
 /*
  * We must be sure that accepting a new task (or allowing changing the
  * parameters of an existing one) is consistent with the bandwidth
@@ -2220,7 +2209,6 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
 
 /**
  * finish_task_switch - clean up after a task-switch
- * @rq: runqueue associated with task-switch
  * @prev: the thread we just switched away from.
  *
  * finish_task_switch must be called after the context switch, paired
@@ -2232,10 +2220,16 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
  * so, we finish that here outside of the runqueue lock. (Doing it
  * with the lock held can cause deadlocks; see schedule() for
  * details.)
+ *
+ * The context switch have flipped the stack from under us and restored the
+ * local variables which were saved when this task called schedule() in the
+ * past. prev == current is still correct but we need to recalculate this_rq
+ * because prev may have moved to another CPU.
  */
-static void finish_task_switch(struct rq *rq, struct task_struct *prev)
+static struct rq *finish_task_switch(struct task_struct *prev)
        __releases(rq->lock)
 {
+       struct rq *rq = this_rq();
        struct mm_struct *mm = rq->prev_mm;
        long prev_state;
 
@@ -2275,6 +2269,7 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
        }
 
        tick_nohz_task_switch(current);
+       return rq;
 }
 
 #ifdef CONFIG_SMP
@@ -2309,25 +2304,22 @@ static inline void post_schedule(struct rq *rq)
 asmlinkage __visible void schedule_tail(struct task_struct *prev)
        __releases(rq->lock)
 {
-       struct rq *rq = this_rq();
-
-       finish_task_switch(rq, prev);
+       struct rq *rq;
 
-       /*
-        * FIXME: do we need to worry about rq being invalidated by the
-        * task_switch?
-        */
+       /* finish_task_switch() drops rq->lock and enables preemtion */
+       preempt_disable();
+       rq = finish_task_switch(prev);
        post_schedule(rq);
+       preempt_enable();
 
        if (current->set_child_tid)
                put_user(task_pid_vnr(current), current->set_child_tid);
 }
 
 /*
- * context_switch - switch to the new MM and the new
- * thread's register state.
+ * context_switch - switch to the new MM and the new thread's register state.
  */
-static inline void
+static inline struct rq *
 context_switch(struct rq *rq, struct task_struct *prev,
               struct task_struct *next)
 {
@@ -2366,14 +2358,9 @@ context_switch(struct rq *rq, struct task_struct *prev,
        context_tracking_task_switch(prev, next);
        /* Here we just switch the register state and the stack. */
        switch_to(prev, next, prev);
-
        barrier();
-       /*
-        * this_rq must be evaluated again because prev may have moved
-        * CPUs since it called schedule(), thus the 'rq' on its stack
-        * frame will be invalid.
-        */
-       finish_task_switch(this_rq(), prev);
+
+       return finish_task_switch(prev);
 }
 
 /*
@@ -2474,44 +2461,6 @@ DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat);
 EXPORT_PER_CPU_SYMBOL(kstat);
 EXPORT_PER_CPU_SYMBOL(kernel_cpustat);
 
-/*
- * Return any ns on the sched_clock that have not yet been accounted in
- * @p in case that task is currently running.
- *
- * Called with task_rq_lock() held on @rq.
- */
-static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq)
-{
-       u64 ns = 0;
-
-       /*
-        * Must be ->curr _and_ ->on_rq.  If dequeued, we would
-        * project cycles that may never be accounted to this
-        * thread, breaking clock_gettime().
-        */
-       if (task_current(rq, p) && task_on_rq_queued(p)) {
-               update_rq_clock(rq);
-               ns = rq_clock_task(rq) - p->se.exec_start;
-               if ((s64)ns < 0)
-                       ns = 0;
-       }
-
-       return ns;
-}
-
-unsigned long long task_delta_exec(struct task_struct *p)
-{
-       unsigned long flags;
-       struct rq *rq;
-       u64 ns = 0;
-
-       rq = task_rq_lock(p, &flags);
-       ns = do_task_delta_exec(p, rq);
-       task_rq_unlock(rq, p, &flags);
-
-       return ns;
-}
-
 /*
  * Return accounted runtime for the task.
  * In case the task is currently running, return the runtime plus current's
@@ -2521,7 +2470,7 @@ unsigned long long task_sched_runtime(struct task_struct *p)
 {
        unsigned long flags;
        struct rq *rq;
-       u64 ns = 0;
+       u64 ns;
 
 #if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
        /*
@@ -2540,7 +2489,16 @@ unsigned long long task_sched_runtime(struct task_struct *p)
 #endif
 
        rq = task_rq_lock(p, &flags);
-       ns = p->se.sum_exec_runtime + do_task_delta_exec(p, rq);
+       /*
+        * Must be ->curr _and_ ->on_rq.  If dequeued, we would
+        * project cycles that may never be accounted to this
+        * thread, breaking clock_gettime().
+        */
+       if (task_current(rq, p) && task_on_rq_queued(p)) {
+               update_rq_clock(rq);
+               p->sched_class->update_curr(rq);
+       }
+       ns = p->se.sum_exec_runtime;
        task_rq_unlock(rq, p, &flags);
 
        return ns;
@@ -2802,7 +2760,7 @@ need_resched:
        preempt_disable();
        cpu = smp_processor_id();
        rq = cpu_rq(cpu);
-       rcu_note_context_switch(cpu);
+       rcu_note_context_switch();
        prev = rq->curr;
 
        schedule_debug(prev);
@@ -2855,15 +2813,8 @@ need_resched:
                rq->curr = next;
                ++*switch_count;
 
-               context_switch(rq, prev, next); /* unlocks the rq */
-               /*
-                * The context switch have flipped the stack from under us
-                * and restored the local variables which were saved when
-                * this task called schedule() in the past. prev == current
-                * is still correct, but it can be moved to another cpu/rq.
-                */
-               cpu = smp_processor_id();
-               rq = cpu_rq(cpu);
+               rq = context_switch(rq, prev, next); /* unlocks the rq */
+               cpu = cpu_of(rq);
        } else
                raw_spin_unlock_irq(&rq->lock);
 
@@ -2903,10 +2854,14 @@ asmlinkage __visible void __sched schedule_user(void)
         * or we have been woken up remotely but the IPI has not yet arrived,
         * we haven't yet exited the RCU idle mode. Do it here manually until
         * we find a better solution.
+        *
+        * NB: There are buggy callers of this function.  Ideally we
+        * should warn if prev_state != IN_USER, but that will trigger
+        * too frequently to make sense yet.
         */
-       user_exit();
+       enum ctx_state prev_state = exception_enter();
        schedule();
-       user_enter();
+       exception_exit(prev_state);
 }
 #endif
 
@@ -2951,6 +2906,47 @@ asmlinkage __visible void __sched notrace preempt_schedule(void)
 }
 NOKPROBE_SYMBOL(preempt_schedule);
 EXPORT_SYMBOL(preempt_schedule);
+
+#ifdef CONFIG_CONTEXT_TRACKING
+/**
+ * preempt_schedule_context - preempt_schedule called by tracing
+ *
+ * The tracing infrastructure uses preempt_enable_notrace to prevent
+ * recursion and tracing preempt enabling caused by the tracing
+ * infrastructure itself. But as tracing can happen in areas coming
+ * from userspace or just about to enter userspace, a preempt enable
+ * can occur before user_exit() is called. This will cause the scheduler
+ * to be called when the system is still in usermode.
+ *
+ * To prevent this, the preempt_enable_notrace will use this function
+ * instead of preempt_schedule() to exit user context if needed before
+ * calling the scheduler.
+ */
+asmlinkage __visible void __sched notrace preempt_schedule_context(void)
+{
+       enum ctx_state prev_ctx;
+
+       if (likely(!preemptible()))
+               return;
+
+       do {
+               __preempt_count_add(PREEMPT_ACTIVE);
+               /*
+                * Needs preempt disabled in case user_exit() is traced
+                * and the tracer calls preempt_enable_notrace() causing
+                * an infinite recursion.
+                */
+               prev_ctx = exception_enter();
+               __schedule();
+               exception_exit(prev_ctx);
+
+               __preempt_count_sub(PREEMPT_ACTIVE);
+               barrier();
+       } while (need_resched());
+}
+EXPORT_SYMBOL_GPL(preempt_schedule_context);
+#endif /* CONFIG_CONTEXT_TRACKING */
+
 #endif /* CONFIG_PREEMPT */
 
 /*
@@ -4637,6 +4633,81 @@ void init_idle(struct task_struct *idle, int cpu)
 #endif
 }
 
+int cpuset_cpumask_can_shrink(const struct cpumask *cur,
+                             const struct cpumask *trial)
+{
+       int ret = 1, trial_cpus;
+       struct dl_bw *cur_dl_b;
+       unsigned long flags;
+
+       rcu_read_lock_sched();
+       cur_dl_b = dl_bw_of(cpumask_any(cur));
+       trial_cpus = cpumask_weight(trial);
+
+       raw_spin_lock_irqsave(&cur_dl_b->lock, flags);
+       if (cur_dl_b->bw != -1 &&
+           cur_dl_b->bw * trial_cpus < cur_dl_b->total_bw)
+               ret = 0;
+       raw_spin_unlock_irqrestore(&cur_dl_b->lock, flags);
+       rcu_read_unlock_sched();
+
+       return ret;
+}
+
+int task_can_attach(struct task_struct *p,
+                   const struct cpumask *cs_cpus_allowed)
+{
+       int ret = 0;
+
+       /*
+        * Kthreads which disallow setaffinity shouldn't be moved
+        * to a new cpuset; we don't want to change their cpu
+        * affinity and isolating such threads by their set of
+        * allowed nodes is unnecessary.  Thus, cpusets are not
+        * applicable for such threads.  This prevents checking for
+        * success of set_cpus_allowed_ptr() on all attached tasks
+        * before cpus_allowed may be changed.
+        */
+       if (p->flags & PF_NO_SETAFFINITY) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+#ifdef CONFIG_SMP
+       if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
+                                             cs_cpus_allowed)) {
+               unsigned int dest_cpu = cpumask_any_and(cpu_active_mask,
+                                                       cs_cpus_allowed);
+               struct dl_bw *dl_b;
+               bool overflow;
+               int cpus;
+               unsigned long flags;
+
+               rcu_read_lock_sched();
+               dl_b = dl_bw_of(dest_cpu);
+               raw_spin_lock_irqsave(&dl_b->lock, flags);
+               cpus = dl_bw_cpus(dest_cpu);
+               overflow = __dl_overflow(dl_b, cpus, 0, p->dl.dl_bw);
+               if (overflow)
+                       ret = -EBUSY;
+               else {
+                       /*
+                        * We reserve space for this task in the destination
+                        * root_domain, as we can't fail after this point.
+                        * We will free resources in the source root_domain
+                        * later on (see set_cpus_allowed_dl()).
+                        */
+                       __dl_add(dl_b, p->dl.dl_bw);
+               }
+               raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+               rcu_read_unlock_sched();
+
+       }
+#endif
+out:
+       return ret;
+}
+
 #ifdef CONFIG_SMP
 /*
  * move_queued_task - move a queued task to new rq.
@@ -6087,7 +6158,9 @@ static void claim_allocations(int cpu, struct sched_domain *sd)
 
 #ifdef CONFIG_NUMA
 static int sched_domains_numa_levels;
+enum numa_topology_type sched_numa_topology_type;
 static int *sched_domains_numa_distance;
+int sched_max_numa_distance;
 static struct cpumask ***sched_domains_numa_masks;
 static int sched_domains_curr_level;
 #endif
@@ -6259,7 +6332,7 @@ static void sched_numa_warn(const char *str)
        printk(KERN_WARNING "\n");
 }
 
-static bool find_numa_distance(int distance)
+bool find_numa_distance(int distance)
 {
        int i;
 
@@ -6274,6 +6347,56 @@ static bool find_numa_distance(int distance)
        return false;
 }
 
+/*
+ * A system can have three types of NUMA topology:
+ * NUMA_DIRECT: all nodes are directly connected, or not a NUMA system
+ * NUMA_GLUELESS_MESH: some nodes reachable through intermediary nodes
+ * NUMA_BACKPLANE: nodes can reach other nodes through a backplane
+ *
+ * The difference between a glueless mesh topology and a backplane
+ * topology lies in whether communication between not directly
+ * connected nodes goes through intermediary nodes (where programs
+ * could run), or through backplane controllers. This affects
+ * placement of programs.
+ *
+ * The type of topology can be discerned with the following tests:
+ * - If the maximum distance between any nodes is 1 hop, the system
+ *   is directly connected.
+ * - If for two nodes A and B, located N > 1 hops away from each other,
+ *   there is an intermediary node C, which is < N hops away from both
+ *   nodes A and B, the system is a glueless mesh.
+ */
+static void init_numa_topology_type(void)
+{
+       int a, b, c, n;
+
+       n = sched_max_numa_distance;
+
+       if (n <= 1)
+               sched_numa_topology_type = NUMA_DIRECT;
+
+       for_each_online_node(a) {
+               for_each_online_node(b) {
+                       /* Find two nodes furthest removed from each other. */
+                       if (node_distance(a, b) < n)
+                               continue;
+
+                       /* Is there an intermediary node between a and b? */
+                       for_each_online_node(c) {
+                               if (node_distance(a, c) < n &&
+                                   node_distance(b, c) < n) {
+                                       sched_numa_topology_type =
+                                                       NUMA_GLUELESS_MESH;
+                                       return;
+                               }
+                       }
+
+                       sched_numa_topology_type = NUMA_BACKPLANE;
+                       return;
+               }
+       }
+}
+
 static void sched_init_numa(void)
 {
        int next_distance, curr_distance = node_distance(0, 0);
@@ -6327,6 +6450,10 @@ static void sched_init_numa(void)
                if (!sched_debug())
                        break;
        }
+
+       if (!level)
+               return;
+
        /*
         * 'level' contains the number of unique distances, excluding the
         * identity distance node_distance(i,i).
@@ -6406,6 +6533,9 @@ static void sched_init_numa(void)
        sched_domain_topology = tl;
 
        sched_domains_numa_levels = level;
+       sched_max_numa_distance = sched_domains_numa_distance[level - 1];
+
+       init_numa_topology_type();
 }
 
 static void sched_domains_numa_masks_set(int cpu)
@@ -7157,6 +7287,25 @@ static inline int preempt_count_equals(int preempt_offset)
 }
 
 void __might_sleep(const char *file, int line, int preempt_offset)
+{
+       /*
+        * Blocking primitives will set (and therefore destroy) current->state,
+        * since we will exit with TASK_RUNNING make sure we enter with it,
+        * otherwise we will destroy state.
+        */
+       if (WARN_ONCE(current->state != TASK_RUNNING,
+                       "do not call blocking ops when !TASK_RUNNING; "
+                       "state=%lx set at [<%p>] %pS\n",
+                       current->state,
+                       (void *)current->task_state_change,
+                       (void *)current->task_state_change))
+               __set_current_state(TASK_RUNNING);
+
+       ___might_sleep(file, line, preempt_offset);
+}
+EXPORT_SYMBOL(__might_sleep);
+
+void ___might_sleep(const char *file, int line, int preempt_offset)
 {
        static unsigned long prev_jiffy;        /* ratelimiting */
 
@@ -7189,7 +7338,7 @@ void __might_sleep(const char *file, int line, int preempt_offset)
 #endif
        dump_stack();
 }
-EXPORT_SYMBOL(__might_sleep);
+EXPORT_SYMBOL(___might_sleep);
 #endif
 
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -7403,8 +7552,12 @@ void sched_move_task(struct task_struct *tsk)
        if (unlikely(running))
                put_prev_task(rq, tsk);
 
-       tg = container_of(task_css_check(tsk, cpu_cgrp_id,
-                               lockdep_is_held(&tsk->sighand->siglock)),
+       /*
+        * All callers are synchronized by task_rq_lock(); we do not use RCU
+        * which is pointless here. Thus, we pass "true" to task_css_check()
+        * to prevent lockdep warnings.
+        */
+       tg = container_of(task_css_check(tsk, cpu_cgrp_id, true),
                          struct task_group, css);
        tg = autogroup_task_group(tsk, tg);
        tsk->sched_task_group = tg;
@@ -7833,6 +7986,11 @@ static void cpu_cgroup_css_offline(struct cgroup_subsys_state *css)
        sched_offline_group(tg);
 }
 
+static void cpu_cgroup_fork(struct task_struct *task)
+{
+       sched_move_task(task);
+}
+
 static int cpu_cgroup_can_attach(struct cgroup_subsys_state *css,
                                 struct cgroup_taskset *tset)
 {
@@ -8205,6 +8363,7 @@ struct cgroup_subsys cpu_cgrp_subsys = {
        .css_free       = cpu_cgroup_css_free,
        .css_online     = cpu_cgroup_css_online,
        .css_offline    = cpu_cgroup_css_offline,
+       .fork           = cpu_cgroup_fork,
        .can_attach     = cpu_cgroup_can_attach,
        .attach         = cpu_cgroup_attach,
        .exit           = cpu_cgroup_exit,
index 538c9796ad4a0b085e4c4284683fe7856b420153..020039bd1326852126480fa5e5038f58d26ca18c 100644 (file)
@@ -25,9 +25,6 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
 void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid);
 int cpudl_init(struct cpudl *cp);
 void cpudl_cleanup(struct cpudl *cp);
-#else
-#define cpudl_set(cp, cpu, dl) do { } while (0)
-#define cpudl_init() do { } while (0)
 #endif /* CONFIG_SMP */
 
 #endif /* _LINUX_CPUDL_H */
index 6b033347fdfd1c787bae013ba02d390e256a44f3..63cbb9ca049698ad1c8a0c0d5430b7911b253baf 100644 (file)
@@ -26,9 +26,6 @@ int  cpupri_find(struct cpupri *cp,
 void cpupri_set(struct cpupri *cp, int cpu, int pri);
 int cpupri_init(struct cpupri *cp);
 void cpupri_cleanup(struct cpupri *cp);
-#else
-#define cpupri_set(cp, cpu, pri) do { } while (0)
-#define cpupri_init() do { } while (0)
 #endif
 
 #endif /* _LINUX_CPUPRI_H */
index 256e577faf1bf977ae00a97f742103a826714f93..e5db8c6feebd7e319b20b482885a1bd5e8ad3be1 100644 (file)
@@ -518,12 +518,20 @@ again:
        }
 
        /*
-        * We need to take care of a possible races here. In fact, the
-        * task might have changed its scheduling policy to something
-        * different from SCHED_DEADLINE or changed its reservation
-        * parameters (through sched_setattr()).
+        * We need to take care of several possible races here:
+        *
+        *   - the task might have changed its scheduling policy
+        *     to something different than SCHED_DEADLINE
+        *   - the task might have changed its reservation parameters
+        *     (through sched_setattr())
+        *   - the task might have been boosted by someone else and
+        *     might be in the boosting/deboosting path
+        *
+        * In all this cases we bail out, as the task is already
+        * in the runqueue or is going to be enqueued back anyway.
         */
-       if (!dl_task(p) || dl_se->dl_new)
+       if (!dl_task(p) || dl_se->dl_new ||
+           dl_se->dl_boosted || !dl_se->dl_throttled)
                goto unlock;
 
        sched_clock_tick();
@@ -532,7 +540,7 @@ again:
        dl_se->dl_yielded = 0;
        if (task_on_rq_queued(p)) {
                enqueue_task_dl(rq, p, ENQUEUE_REPLENISH);
-               if (task_has_dl_policy(rq->curr))
+               if (dl_task(rq->curr))
                        check_preempt_curr_dl(rq, p, 0);
                else
                        resched_curr(rq);
@@ -555,11 +563,6 @@ void init_dl_task_timer(struct sched_dl_entity *dl_se)
 {
        struct hrtimer *timer = &dl_se->dl_timer;
 
-       if (hrtimer_active(timer)) {
-               hrtimer_try_to_cancel(timer);
-               return;
-       }
-
        hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        timer->function = dl_task_timer;
 }
@@ -625,7 +628,7 @@ static void update_curr_dl(struct rq *rq)
 
        sched_rt_avg_update(rq, delta_exec);
 
-       dl_se->runtime -= delta_exec;
+       dl_se->runtime -= dl_se->dl_yielded ? 0 : delta_exec;
        if (dl_runtime_exceeded(rq, dl_se)) {
                __dequeue_task_dl(rq, curr, 0);
                if (likely(start_dl_timer(dl_se, curr->dl.dl_boosted)))
@@ -847,8 +850,19 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags)
         * smaller than our one... OTW we keep our runtime and
         * deadline.
         */
-       if (pi_task && p->dl.dl_boosted && dl_prio(pi_task->normal_prio))
+       if (pi_task && p->dl.dl_boosted && dl_prio(pi_task->normal_prio)) {
                pi_se = &pi_task->dl;
+       } else if (!dl_prio(p->normal_prio)) {
+               /*
+                * Special case in which we have a !SCHED_DEADLINE task
+                * that is going to be deboosted, but exceedes its
+                * runtime while doing so. No point in replenishing
+                * it, as it's going to return back to its original
+                * scheduling class after this.
+                */
+               BUG_ON(!p->dl.dl_boosted || flags != ENQUEUE_REPLENISH);
+               return;
+       }
 
        /*
         * If p is throttled, we do nothing. In fact, if it exhausted
@@ -914,7 +928,7 @@ select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags)
        struct task_struct *curr;
        struct rq *rq;
 
-       if (sd_flag != SD_BALANCE_WAKE && sd_flag != SD_BALANCE_FORK)
+       if (sd_flag != SD_BALANCE_WAKE)
                goto out;
 
        rq = cpu_rq(cpu);
@@ -999,6 +1013,10 @@ static void start_hrtick_dl(struct rq *rq, struct task_struct *p)
 {
        hrtick_start(rq, p->dl.runtime);
 }
+#else /* !CONFIG_SCHED_HRTICK */
+static void start_hrtick_dl(struct rq *rq, struct task_struct *p)
+{
+}
 #endif
 
 static struct sched_dl_entity *pick_next_dl_entity(struct rq *rq,
@@ -1052,10 +1070,8 @@ struct task_struct *pick_next_task_dl(struct rq *rq, struct task_struct *prev)
        /* Running task will never be pushed. */
        dequeue_pushable_dl_task(rq, p);
 
-#ifdef CONFIG_SCHED_HRTICK
        if (hrtick_enabled(rq))
                start_hrtick_dl(rq, p);
-#endif
 
        set_post_schedule(rq);
 
@@ -1074,10 +1090,8 @@ static void task_tick_dl(struct rq *rq, struct task_struct *p, int queued)
 {
        update_curr_dl(rq);
 
-#ifdef CONFIG_SCHED_HRTICK
        if (hrtick_enabled(rq) && queued && p->dl.runtime > 0)
                start_hrtick_dl(rq, p);
-#endif
 }
 
 static void task_fork_dl(struct task_struct *p)
@@ -1314,6 +1328,7 @@ static int push_dl_task(struct rq *rq)
 {
        struct task_struct *next_task;
        struct rq *later_rq;
+       int ret = 0;
 
        if (!rq->dl.overloaded)
                return 0;
@@ -1359,7 +1374,6 @@ retry:
                         * The task is still there. We don't try
                         * again, some other cpu will pull it when ready.
                         */
-                       dequeue_pushable_dl_task(rq, next_task);
                        goto out;
                }
 
@@ -1375,6 +1389,7 @@ retry:
        deactivate_task(rq, next_task, 0);
        set_task_cpu(next_task, later_rq->cpu);
        activate_task(later_rq, next_task, 0);
+       ret = 1;
 
        resched_curr(later_rq);
 
@@ -1383,7 +1398,7 @@ retry:
 out:
        put_task_struct(next_task);
 
-       return 1;
+       return ret;
 }
 
 static void push_dl_tasks(struct rq *rq)
@@ -1489,7 +1504,7 @@ static void task_woken_dl(struct rq *rq, struct task_struct *p)
            p->nr_cpus_allowed > 1 &&
            dl_task(rq->curr) &&
            (rq->curr->nr_cpus_allowed < 2 ||
-            dl_entity_preempt(&rq->curr->dl, &p->dl))) {
+            !dl_entity_preempt(&p->dl, &rq->curr->dl))) {
                push_dl_tasks(rq);
        }
 }
@@ -1498,10 +1513,33 @@ static void set_cpus_allowed_dl(struct task_struct *p,
                                const struct cpumask *new_mask)
 {
        struct rq *rq;
+       struct root_domain *src_rd;
        int weight;
 
        BUG_ON(!dl_task(p));
 
+       rq = task_rq(p);
+       src_rd = rq->rd;
+       /*
+        * Migrating a SCHED_DEADLINE task between exclusive
+        * cpusets (different root_domains) entails a bandwidth
+        * update. We already made space for us in the destination
+        * domain (see cpuset_can_attach()).
+        */
+       if (!cpumask_intersects(src_rd->span, new_mask)) {
+               struct dl_bw *src_dl_b;
+
+               src_dl_b = dl_bw_of(cpu_of(rq));
+               /*
+                * We now free resources of the root_domain we are migrating
+                * off. In the worst case, sched_setattr() may temporary fail
+                * until we complete the update.
+                */
+               raw_spin_lock(&src_dl_b->lock);
+               __dl_clear(src_dl_b, p->dl.dl_bw);
+               raw_spin_unlock(&src_dl_b->lock);
+       }
+
        /*
         * Update only if the task is actually running (i.e.,
         * it is on the rq AND it is not throttled).
@@ -1518,8 +1556,6 @@ static void set_cpus_allowed_dl(struct task_struct *p,
        if ((p->nr_cpus_allowed > 1) == (weight > 1))
                return;
 
-       rq = task_rq(p);
-
        /*
         * The process used to be able to migrate OR it can now migrate
         */
@@ -1567,22 +1603,48 @@ void init_sched_dl_class(void)
 
 #endif /* CONFIG_SMP */
 
+/*
+ *  Ensure p's dl_timer is cancelled. May drop rq->lock for a while.
+ */
+static void cancel_dl_timer(struct rq *rq, struct task_struct *p)
+{
+       struct hrtimer *dl_timer = &p->dl.dl_timer;
+
+       /* Nobody will change task's class if pi_lock is held */
+       lockdep_assert_held(&p->pi_lock);
+
+       if (hrtimer_active(dl_timer)) {
+               int ret = hrtimer_try_to_cancel(dl_timer);
+
+               if (unlikely(ret == -1)) {
+                       /*
+                        * Note, p may migrate OR new deadline tasks
+                        * may appear in rq when we are unlocking it.
+                        * A caller of us must be fine with that.
+                        */
+                       raw_spin_unlock(&rq->lock);
+                       hrtimer_cancel(dl_timer);
+                       raw_spin_lock(&rq->lock);
+               }
+       }
+}
+
 static void switched_from_dl(struct rq *rq, struct task_struct *p)
 {
-       if (hrtimer_active(&p->dl.dl_timer) && !dl_policy(p->policy))
-               hrtimer_try_to_cancel(&p->dl.dl_timer);
+       cancel_dl_timer(rq, p);
 
        __dl_clear_params(p);
 
-#ifdef CONFIG_SMP
        /*
         * Since this might be the only -deadline task on the rq,
         * this is the right place to try to pull some other one
         * from an overloaded cpu, if any.
         */
-       if (!rq->dl.dl_nr_running)
-               pull_dl_task(rq);
-#endif
+       if (!task_on_rq_queued(p) || rq->dl.dl_nr_running)
+               return;
+
+       if (pull_dl_task(rq))
+               resched_curr(rq);
 }
 
 /*
@@ -1603,12 +1665,17 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
 
        if (task_on_rq_queued(p) && rq->curr != p) {
 #ifdef CONFIG_SMP
-               if (rq->dl.overloaded && push_dl_task(rq) && rq != task_rq(p))
+               if (p->nr_cpus_allowed > 1 && rq->dl.overloaded &&
+                       push_dl_task(rq) && rq != task_rq(p))
                        /* Only reschedule if pushing failed */
                        check_resched = 0;
 #endif /* CONFIG_SMP */
-               if (check_resched && task_has_dl_policy(rq->curr))
-                       check_preempt_curr_dl(rq, p, 0);
+               if (check_resched) {
+                       if (dl_task(rq->curr))
+                               check_preempt_curr_dl(rq, p, 0);
+                       else
+                               resched_curr(rq);
+               }
        }
 }
 
@@ -1678,4 +1745,15 @@ const struct sched_class dl_sched_class = {
        .prio_changed           = prio_changed_dl,
        .switched_from          = switched_from_dl,
        .switched_to            = switched_to_dl,
+
+       .update_curr            = update_curr_dl,
 };
+
+#ifdef CONFIG_SCHED_DEBUG
+extern void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq);
+
+void print_dl_stats(struct seq_file *m, int cpu)
+{
+       print_dl_rq(m, cpu, &cpu_rq(cpu)->dl);
+}
+#endif /* CONFIG_SCHED_DEBUG */
index ce33780d8f20122ec263021db060cdacbaee7e41..92cc52001e74d1f9298c13cf75c6b5c3501c6379 100644 (file)
@@ -261,6 +261,12 @@ void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq)
 #undef P
 }
 
+void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq)
+{
+       SEQ_printf(m, "\ndl_rq[%d]:\n", cpu);
+       SEQ_printf(m, "  .%-30s: %ld\n", "dl_nr_running", dl_rq->dl_nr_running);
+}
+
 extern __read_mostly int sched_clock_running;
 
 static void print_cpu(struct seq_file *m, int cpu)
@@ -329,6 +335,7 @@ do {                                                                        \
        spin_lock_irqsave(&sched_debug_lock, flags);
        print_cfs_stats(m, cpu);
        print_rt_stats(m, cpu);
+       print_dl_stats(m, cpu);
 
        print_rq(m, rq, cpu);
        spin_unlock_irqrestore(&sched_debug_lock, flags);
@@ -528,8 +535,8 @@ static void sched_show_numa(struct task_struct *p, struct seq_file *m)
                        unsigned long nr_faults = -1;
                        int cpu_current, home_node;
 
-                       if (p->numa_faults_memory)
-                               nr_faults = p->numa_faults_memory[2*node + i];
+                       if (p->numa_faults)
+                               nr_faults = p->numa_faults[2*node + i];
 
                        cpu_current = !i ? (task_node(p) == node) :
                                (pol && node_isset(node, pol->v.nodes));
index 0b069bf3e708e82ea0e08c5b204f931ca1d22a00..df2cdf77f8998d46f58cbf4bc0b3693311c96911 100644 (file)
@@ -726,6 +726,11 @@ static void update_curr(struct cfs_rq *cfs_rq)
        account_cfs_rq_runtime(cfs_rq, delta_exec);
 }
 
+static void update_curr_fair(struct rq *rq)
+{
+       update_curr(cfs_rq_of(&rq->curr->se));
+}
+
 static inline void
 update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
@@ -828,11 +833,12 @@ static unsigned int task_nr_scan_windows(struct task_struct *p)
 
 static unsigned int task_scan_min(struct task_struct *p)
 {
+       unsigned int scan_size = ACCESS_ONCE(sysctl_numa_balancing_scan_size);
        unsigned int scan, floor;
        unsigned int windows = 1;
 
-       if (sysctl_numa_balancing_scan_size < MAX_SCAN_WINDOW)
-               windows = MAX_SCAN_WINDOW / sysctl_numa_balancing_scan_size;
+       if (scan_size < MAX_SCAN_WINDOW)
+               windows = MAX_SCAN_WINDOW / scan_size;
        floor = 1000 / windows;
 
        scan = sysctl_numa_balancing_scan_period_min / task_nr_scan_windows(p);
@@ -867,7 +873,6 @@ struct numa_group {
        spinlock_t lock; /* nr_tasks, tasks */
        int nr_tasks;
        pid_t gid;
-       struct list_head task_list;
 
        struct rcu_head rcu;
        nodemask_t active_nodes;
@@ -895,18 +900,24 @@ pid_t task_numa_group_id(struct task_struct *p)
        return p->numa_group ? p->numa_group->gid : 0;
 }
 
-static inline int task_faults_idx(int nid, int priv)
+/*
+ * The averaged statistics, shared & private, memory & cpu,
+ * occupy the first half of the array. The second half of the
+ * array is for current counters, which are averaged into the
+ * first set by task_numa_placement.
+ */
+static inline int task_faults_idx(enum numa_faults_stats s, int nid, int priv)
 {
-       return NR_NUMA_HINT_FAULT_TYPES * nid + priv;
+       return NR_NUMA_HINT_FAULT_TYPES * (s * nr_node_ids + nid) + priv;
 }
 
 static inline unsigned long task_faults(struct task_struct *p, int nid)
 {
-       if (!p->numa_faults_memory)
+       if (!p->numa_faults)
                return 0;
 
-       return p->numa_faults_memory[task_faults_idx(nid, 0)] +
-               p->numa_faults_memory[task_faults_idx(nid, 1)];
+       return p->numa_faults[task_faults_idx(NUMA_MEM, nid, 0)] +
+               p->numa_faults[task_faults_idx(NUMA_MEM, nid, 1)];
 }
 
 static inline unsigned long group_faults(struct task_struct *p, int nid)
@@ -914,14 +925,79 @@ static inline unsigned long group_faults(struct task_struct *p, int nid)
        if (!p->numa_group)
                return 0;
 
-       return p->numa_group->faults[task_faults_idx(nid, 0)] +
-               p->numa_group->faults[task_faults_idx(nid, 1)];
+       return p->numa_group->faults[task_faults_idx(NUMA_MEM, nid, 0)] +
+               p->numa_group->faults[task_faults_idx(NUMA_MEM, nid, 1)];
 }
 
 static inline unsigned long group_faults_cpu(struct numa_group *group, int nid)
 {
-       return group->faults_cpu[task_faults_idx(nid, 0)] +
-               group->faults_cpu[task_faults_idx(nid, 1)];
+       return group->faults_cpu[task_faults_idx(NUMA_MEM, nid, 0)] +
+               group->faults_cpu[task_faults_idx(NUMA_MEM, nid, 1)];
+}
+
+/* Handle placement on systems where not all nodes are directly connected. */
+static unsigned long score_nearby_nodes(struct task_struct *p, int nid,
+                                       int maxdist, bool task)
+{
+       unsigned long score = 0;
+       int node;
+
+       /*
+        * All nodes are directly connected, and the same distance
+        * from each other. No need for fancy placement algorithms.
+        */
+       if (sched_numa_topology_type == NUMA_DIRECT)
+               return 0;
+
+       /*
+        * This code is called for each node, introducing N^2 complexity,
+        * which should be ok given the number of nodes rarely exceeds 8.
+        */
+       for_each_online_node(node) {
+               unsigned long faults;
+               int dist = node_distance(nid, node);
+
+               /*
+                * The furthest away nodes in the system are not interesting
+                * for placement; nid was already counted.
+                */
+               if (dist == sched_max_numa_distance || node == nid)
+                       continue;
+
+               /*
+                * On systems with a backplane NUMA topology, compare groups
+                * of nodes, and move tasks towards the group with the most
+                * memory accesses. When comparing two nodes at distance
+                * "hoplimit", only nodes closer by than "hoplimit" are part
+                * of each group. Skip other nodes.
+                */
+               if (sched_numa_topology_type == NUMA_BACKPLANE &&
+                                       dist > maxdist)
+                       continue;
+
+               /* Add up the faults from nearby nodes. */
+               if (task)
+                       faults = task_faults(p, node);
+               else
+                       faults = group_faults(p, node);
+
+               /*
+                * On systems with a glueless mesh NUMA topology, there are
+                * no fixed "groups of nodes". Instead, nodes that are not
+                * directly connected bounce traffic through intermediate
+                * nodes; a numa_group can occupy any set of nodes.
+                * The further away a node is, the less the faults count.
+                * This seems to result in good task placement.
+                */
+               if (sched_numa_topology_type == NUMA_GLUELESS_MESH) {
+                       faults *= (sched_max_numa_distance - dist);
+                       faults /= (sched_max_numa_distance - LOCAL_DISTANCE);
+               }
+
+               score += faults;
+       }
+
+       return score;
 }
 
 /*
@@ -930,11 +1006,12 @@ static inline unsigned long group_faults_cpu(struct numa_group *group, int nid)
  * larger multiplier, in order to group tasks together that are almost
  * evenly spread out between numa nodes.
  */
-static inline unsigned long task_weight(struct task_struct *p, int nid)
+static inline unsigned long task_weight(struct task_struct *p, int nid,
+                                       int dist)
 {
-       unsigned long total_faults;
+       unsigned long faults, total_faults;
 
-       if (!p->numa_faults_memory)
+       if (!p->numa_faults)
                return 0;
 
        total_faults = p->total_numa_faults;
@@ -942,15 +1019,29 @@ static inline unsigned long task_weight(struct task_struct *p, int nid)
        if (!total_faults)
                return 0;
 
-       return 1000 * task_faults(p, nid) / total_faults;
+       faults = task_faults(p, nid);
+       faults += score_nearby_nodes(p, nid, dist, true);
+
+       return 1000 * faults / total_faults;
 }
 
-static inline unsigned long group_weight(struct task_struct *p, int nid)
+static inline unsigned long group_weight(struct task_struct *p, int nid,
+                                        int dist)
 {
-       if (!p->numa_group || !p->numa_group->total_faults)
+       unsigned long faults, total_faults;
+
+       if (!p->numa_group)
+               return 0;
+
+       total_faults = p->numa_group->total_faults;
+
+       if (!total_faults)
                return 0;
 
-       return 1000 * group_faults(p, nid) / p->numa_group->total_faults;
+       faults = group_faults(p, nid);
+       faults += score_nearby_nodes(p, nid, dist, false);
+
+       return 1000 * faults / total_faults;
 }
 
 bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
@@ -1083,6 +1174,7 @@ struct task_numa_env {
        struct numa_stats src_stats, dst_stats;
 
        int imbalance_pct;
+       int dist;
 
        struct task_struct *best_task;
        long best_imp;
@@ -1162,11 +1254,29 @@ static void task_numa_compare(struct task_numa_env *env,
        long load;
        long imp = env->p->numa_group ? groupimp : taskimp;
        long moveimp = imp;
+       int dist = env->dist;
 
        rcu_read_lock();
-       cur = ACCESS_ONCE(dst_rq->curr);
-       if (cur->pid == 0) /* idle */
+
+       raw_spin_lock_irq(&dst_rq->lock);
+       cur = dst_rq->curr;
+       /*
+        * No need to move the exiting task, and this ensures that ->curr
+        * wasn't reaped and thus get_task_struct() in task_numa_assign()
+        * is safe under RCU read lock.
+        * Note that rcu_read_lock() itself can't protect from the final
+        * put_task_struct() after the last schedule().
+        */
+       if ((cur->flags & PF_EXITING) || is_idle_task(cur))
                cur = NULL;
+       raw_spin_unlock_irq(&dst_rq->lock);
+
+       /*
+        * Because we have preemption enabled we can get migrated around and
+        * end try selecting ourselves (current == env->p) as a swap candidate.
+        */
+       if (cur == env->p)
+               goto unlock;
 
        /*
         * "imp" is the fault differential for the source task between the
@@ -1185,8 +1295,8 @@ static void task_numa_compare(struct task_numa_env *env,
                 * in any group then look only at task weights.
                 */
                if (cur->numa_group == env->p->numa_group) {
-                       imp = taskimp + task_weight(cur, env->src_nid) -
-                             task_weight(cur, env->dst_nid);
+                       imp = taskimp + task_weight(cur, env->src_nid, dist) -
+                             task_weight(cur, env->dst_nid, dist);
                        /*
                         * Add some hysteresis to prevent swapping the
                         * tasks within a group over tiny differences.
@@ -1200,11 +1310,11 @@ static void task_numa_compare(struct task_numa_env *env,
                         * instead.
                         */
                        if (cur->numa_group)
-                               imp += group_weight(cur, env->src_nid) -
-                                      group_weight(cur, env->dst_nid);
+                               imp += group_weight(cur, env->src_nid, dist) -
+                                      group_weight(cur, env->dst_nid, dist);
                        else
-                               imp += task_weight(cur, env->src_nid) -
-                                      task_weight(cur, env->dst_nid);
+                               imp += task_weight(cur, env->src_nid, dist) -
+                                      task_weight(cur, env->dst_nid, dist);
                }
        }
 
@@ -1303,7 +1413,7 @@ static int task_numa_migrate(struct task_struct *p)
        };
        struct sched_domain *sd;
        unsigned long taskweight, groupweight;
-       int nid, ret;
+       int nid, ret, dist;
        long taskimp, groupimp;
 
        /*
@@ -1331,29 +1441,45 @@ static int task_numa_migrate(struct task_struct *p)
                return -EINVAL;
        }
 
-       taskweight = task_weight(p, env.src_nid);
-       groupweight = group_weight(p, env.src_nid);
-       update_numa_stats(&env.src_stats, env.src_nid);
        env.dst_nid = p->numa_preferred_nid;
-       taskimp = task_weight(p, env.dst_nid) - taskweight;
-       groupimp = group_weight(p, env.dst_nid) - groupweight;
+       dist = env.dist = node_distance(env.src_nid, env.dst_nid);
+       taskweight = task_weight(p, env.src_nid, dist);
+       groupweight = group_weight(p, env.src_nid, dist);
+       update_numa_stats(&env.src_stats, env.src_nid);
+       taskimp = task_weight(p, env.dst_nid, dist) - taskweight;
+       groupimp = group_weight(p, env.dst_nid, dist) - groupweight;
        update_numa_stats(&env.dst_stats, env.dst_nid);
 
        /* Try to find a spot on the preferred nid. */
        task_numa_find_cpu(&env, taskimp, groupimp);
 
-       /* No space available on the preferred nid. Look elsewhere. */
-       if (env.best_cpu == -1) {
+       /*
+        * Look at other nodes in these cases:
+        * - there is no space available on the preferred_nid
+        * - the task is part of a numa_group that is interleaved across
+        *   multiple NUMA nodes; in order to better consolidate the group,
+        *   we need to check other locations.
+        */
+       if (env.best_cpu == -1 || (p->numa_group &&
+                       nodes_weight(p->numa_group->active_nodes) > 1)) {
                for_each_online_node(nid) {
                        if (nid == env.src_nid || nid == p->numa_preferred_nid)
                                continue;
 
+                       dist = node_distance(env.src_nid, env.dst_nid);
+                       if (sched_numa_topology_type == NUMA_BACKPLANE &&
+                                               dist != env.dist) {
+                               taskweight = task_weight(p, env.src_nid, dist);
+                               groupweight = group_weight(p, env.src_nid, dist);
+                       }
+
                        /* Only consider nodes where both task and groups benefit */
-                       taskimp = task_weight(p, nid) - taskweight;
-                       groupimp = group_weight(p, nid) - groupweight;
+                       taskimp = task_weight(p, nid, dist) - taskweight;
+                       groupimp = group_weight(p, nid, dist) - groupweight;
                        if (taskimp < 0 && groupimp < 0)
                                continue;
 
+                       env.dist = dist;
                        env.dst_nid = nid;
                        update_numa_stats(&env.dst_stats, env.dst_nid);
                        task_numa_find_cpu(&env, taskimp, groupimp);
@@ -1408,7 +1534,7 @@ static void numa_migrate_preferred(struct task_struct *p)
        unsigned long interval = HZ;
 
        /* This task has no NUMA fault statistics yet */
-       if (unlikely(p->numa_preferred_nid == -1 || !p->numa_faults_memory))
+       if (unlikely(p->numa_preferred_nid == -1 || !p->numa_faults))
                return;
 
        /* Periodically retry migrating the task to the preferred node */
@@ -1520,7 +1646,7 @@ static void update_task_scan_period(struct task_struct *p,
                 * scanning faster if shared accesses dominate as it may
                 * simply bounce migrations uselessly
                 */
-               ratio = DIV_ROUND_UP(private * NUMA_PERIOD_SLOTS, (private + shared));
+               ratio = DIV_ROUND_UP(private * NUMA_PERIOD_SLOTS, (private + shared + 1));
                diff = (diff * ratio) / NUMA_PERIOD_SLOTS;
        }
 
@@ -1557,6 +1683,92 @@ static u64 numa_get_avg_runtime(struct task_struct *p, u64 *period)
        return delta;
 }
 
+/*
+ * Determine the preferred nid for a task in a numa_group. This needs to
+ * be done in a way that produces consistent results with group_weight,
+ * otherwise workloads might not converge.
+ */
+static int preferred_group_nid(struct task_struct *p, int nid)
+{
+       nodemask_t nodes;
+       int dist;
+
+       /* Direct connections between all NUMA nodes. */
+       if (sched_numa_topology_type == NUMA_DIRECT)
+               return nid;
+
+       /*
+        * On a system with glueless mesh NUMA topology, group_weight
+        * scores nodes according to the number of NUMA hinting faults on
+        * both the node itself, and on nearby nodes.
+        */
+       if (sched_numa_topology_type == NUMA_GLUELESS_MESH) {
+               unsigned long score, max_score = 0;
+               int node, max_node = nid;
+
+               dist = sched_max_numa_distance;
+
+               for_each_online_node(node) {
+                       score = group_weight(p, node, dist);
+                       if (score > max_score) {
+                               max_score = score;
+                               max_node = node;
+                       }
+               }
+               return max_node;
+       }
+
+       /*
+        * Finding the preferred nid in a system with NUMA backplane
+        * interconnect topology is more involved. The goal is to locate
+        * tasks from numa_groups near each other in the system, and
+        * untangle workloads from different sides of the system. This requires
+        * searching down the hierarchy of node groups, recursively searching
+        * inside the highest scoring group of nodes. The nodemask tricks
+        * keep the complexity of the search down.
+        */
+       nodes = node_online_map;
+       for (dist = sched_max_numa_distance; dist > LOCAL_DISTANCE; dist--) {
+               unsigned long max_faults = 0;
+               nodemask_t max_group;
+               int a, b;
+
+               /* Are there nodes at this distance from each other? */
+               if (!find_numa_distance(dist))
+                       continue;
+
+               for_each_node_mask(a, nodes) {
+                       unsigned long faults = 0;
+                       nodemask_t this_group;
+                       nodes_clear(this_group);
+
+                       /* Sum group's NUMA faults; includes a==b case. */
+                       for_each_node_mask(b, nodes) {
+                               if (node_distance(a, b) < dist) {
+                                       faults += group_faults(p, b);
+                                       node_set(b, this_group);
+                                       node_clear(b, nodes);
+                               }
+                       }
+
+                       /* Remember the top group. */
+                       if (faults > max_faults) {
+                               max_faults = faults;
+                               max_group = this_group;
+                               /*
+                                * subtle: at the smallest distance there is
+                                * just one node left in each "group", the
+                                * winner is the preferred nid.
+                                */
+                               nid = a;
+                       }
+               }
+               /* Next round, evaluate the nodes within max_group. */
+               nodes = max_group;
+       }
+       return nid;
+}
+
 static void task_numa_placement(struct task_struct *p)
 {
        int seq, nid, max_nid = -1, max_group_nid = -1;
@@ -1584,18 +1796,23 @@ static void task_numa_placement(struct task_struct *p)
 
        /* Find the node with the highest number of faults */
        for_each_online_node(nid) {
+               /* Keep track of the offsets in numa_faults array */
+               int mem_idx, membuf_idx, cpu_idx, cpubuf_idx;
                unsigned long faults = 0, group_faults = 0;
-               int priv, i;
+               int priv;
 
                for (priv = 0; priv < NR_NUMA_HINT_FAULT_TYPES; priv++) {
                        long diff, f_diff, f_weight;
 
-                       i = task_faults_idx(nid, priv);
+                       mem_idx = task_faults_idx(NUMA_MEM, nid, priv);
+                       membuf_idx = task_faults_idx(NUMA_MEMBUF, nid, priv);
+                       cpu_idx = task_faults_idx(NUMA_CPU, nid, priv);
+                       cpubuf_idx = task_faults_idx(NUMA_CPUBUF, nid, priv);
 
                        /* Decay existing window, copy faults since last scan */
-                       diff = p->numa_faults_buffer_memory[i] - p->numa_faults_memory[i] / 2;
-                       fault_types[priv] += p->numa_faults_buffer_memory[i];
-                       p->numa_faults_buffer_memory[i] = 0;
+                       diff = p->numa_faults[membuf_idx] - p->numa_faults[mem_idx] / 2;
+                       fault_types[priv] += p->numa_faults[membuf_idx];
+                       p->numa_faults[membuf_idx] = 0;
 
                        /*
                         * Normalize the faults_from, so all tasks in a group
@@ -1605,21 +1822,27 @@ static void task_numa_placement(struct task_struct *p)
                         * faults are less important.
                         */
                        f_weight = div64_u64(runtime << 16, period + 1);
-                       f_weight = (f_weight * p->numa_faults_buffer_cpu[i]) /
+                       f_weight = (f_weight * p->numa_faults[cpubuf_idx]) /
                                   (total_faults + 1);
-                       f_diff = f_weight - p->numa_faults_cpu[i] / 2;
-                       p->numa_faults_buffer_cpu[i] = 0;
+                       f_diff = f_weight - p->numa_faults[cpu_idx] / 2;
+                       p->numa_faults[cpubuf_idx] = 0;
 
-                       p->numa_faults_memory[i] += diff;
-                       p->numa_faults_cpu[i] += f_diff;
-                       faults += p->numa_faults_memory[i];
+                       p->numa_faults[mem_idx] += diff;
+                       p->numa_faults[cpu_idx] += f_diff;
+                       faults += p->numa_faults[mem_idx];
                        p->total_numa_faults += diff;
                        if (p->numa_group) {
-                               /* safe because we can only change our own group */
-                               p->numa_group->faults[i] += diff;
-                               p->numa_group->faults_cpu[i] += f_diff;
+                               /*
+                                * safe because we can only change our own group
+                                *
+                                * mem_idx represents the offset for a given
+                                * nid and priv in a specific region because it
+                                * is at the beginning of the numa_faults array.
+                                */
+                               p->numa_group->faults[mem_idx] += diff;
+                               p->numa_group->faults_cpu[mem_idx] += f_diff;
                                p->numa_group->total_faults += diff;
-                               group_faults += p->numa_group->faults[i];
+                               group_faults += p->numa_group->faults[mem_idx];
                        }
                }
 
@@ -1639,7 +1862,7 @@ static void task_numa_placement(struct task_struct *p)
        if (p->numa_group) {
                update_numa_active_node_mask(p->numa_group);
                spin_unlock_irq(group_lock);
-               max_nid = max_group_nid;
+               max_nid = preferred_group_nid(p, max_group_nid);
        }
 
        if (max_faults) {
@@ -1682,7 +1905,6 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
 
                atomic_set(&grp->refcount, 1);
                spin_lock_init(&grp->lock);
-               INIT_LIST_HEAD(&grp->task_list);
                grp->gid = p->pid;
                /* Second half of the array tracks nids where faults happen */
                grp->faults_cpu = grp->faults + NR_NUMA_HINT_FAULT_TYPES *
@@ -1691,11 +1913,10 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
                node_set(task_node(current), grp->active_nodes);
 
                for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
-                       grp->faults[i] = p->numa_faults_memory[i];
+                       grp->faults[i] = p->numa_faults[i];
 
                grp->total_faults = p->total_numa_faults;
 
-               list_add(&p->numa_entry, &grp->task_list);
                grp->nr_tasks++;
                rcu_assign_pointer(p->numa_group, grp);
        }
@@ -1750,13 +1971,12 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
        double_lock_irq(&my_grp->lock, &grp->lock);
 
        for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++) {
-               my_grp->faults[i] -= p->numa_faults_memory[i];
-               grp->faults[i] += p->numa_faults_memory[i];
+               my_grp->faults[i] -= p->numa_faults[i];
+               grp->faults[i] += p->numa_faults[i];
        }
        my_grp->total_faults -= p->total_numa_faults;
        grp->total_faults += p->total_numa_faults;
 
-       list_move(&p->numa_entry, &grp->task_list);
        my_grp->nr_tasks--;
        grp->nr_tasks++;
 
@@ -1776,27 +1996,23 @@ no_join:
 void task_numa_free(struct task_struct *p)
 {
        struct numa_group *grp = p->numa_group;
-       void *numa_faults = p->numa_faults_memory;
+       void *numa_faults = p->numa_faults;
        unsigned long flags;
        int i;
 
        if (grp) {
                spin_lock_irqsave(&grp->lock, flags);
                for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
-                       grp->faults[i] -= p->numa_faults_memory[i];
+                       grp->faults[i] -= p->numa_faults[i];
                grp->total_faults -= p->total_numa_faults;
 
-               list_del(&p->numa_entry);
                grp->nr_tasks--;
                spin_unlock_irqrestore(&grp->lock, flags);
                RCU_INIT_POINTER(p->numa_group, NULL);
                put_numa_group(grp);
        }
 
-       p->numa_faults_memory = NULL;
-       p->numa_faults_buffer_memory = NULL;
-       p->numa_faults_cpu= NULL;
-       p->numa_faults_buffer_cpu = NULL;
+       p->numa_faults = NULL;
        kfree(numa_faults);
 }
 
@@ -1819,24 +2035,14 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
                return;
 
        /* Allocate buffer to track faults on a per-node basis */
-       if (unlikely(!p->numa_faults_memory)) {
-               int size = sizeof(*p->numa_faults_memory) *
+       if (unlikely(!p->numa_faults)) {
+               int size = sizeof(*p->numa_faults) *
                           NR_NUMA_HINT_FAULT_BUCKETS * nr_node_ids;
 
-               p->numa_faults_memory = kzalloc(size, GFP_KERNEL|__GFP_NOWARN);
-               if (!p->numa_faults_memory)
+               p->numa_faults = kzalloc(size, GFP_KERNEL|__GFP_NOWARN);
+               if (!p->numa_faults)
                        return;
 
-               BUG_ON(p->numa_faults_buffer_memory);
-               /*
-                * The averaged statistics, shared & private, memory & cpu,
-                * occupy the first half of the array. The second half of the
-                * array is for current counters, which are averaged into the
-                * first set by task_numa_placement.
-                */
-               p->numa_faults_cpu = p->numa_faults_memory + (2 * nr_node_ids);
-               p->numa_faults_buffer_memory = p->numa_faults_memory + (4 * nr_node_ids);
-               p->numa_faults_buffer_cpu = p->numa_faults_memory + (6 * nr_node_ids);
                p->total_numa_faults = 0;
                memset(p->numa_faults_locality, 0, sizeof(p->numa_faults_locality));
        }
@@ -1876,8 +2082,8 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
        if (migrated)
                p->numa_pages_migrated += pages;
 
-       p->numa_faults_buffer_memory[task_faults_idx(mem_node, priv)] += pages;
-       p->numa_faults_buffer_cpu[task_faults_idx(cpu_node, priv)] += pages;
+       p->numa_faults[task_faults_idx(NUMA_MEMBUF, mem_node, priv)] += pages;
+       p->numa_faults[task_faults_idx(NUMA_CPUBUF, cpu_node, priv)] += pages;
        p->numa_faults_locality[local] += pages;
 }
 
@@ -4446,7 +4652,7 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
                                latest_idle_timestamp = rq->idle_stamp;
                                shallowest_idle_cpu = i;
                        }
-               } else {
+               } else if (shallowest_idle_cpu == -1) {
                        load = weighted_cpuload(i);
                        if (load < min_load || (load == min_load && i == this_cpu)) {
                                min_load = load;
@@ -4524,9 +4730,6 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
        int want_affine = 0;
        int sync = wake_flags & WF_SYNC;
 
-       if (p->nr_cpus_allowed == 1)
-               return prev_cpu;
-
        if (sd_flag & SD_BALANCE_WAKE)
                want_affine = cpumask_test_cpu(cpu, tsk_cpus_allowed(p));
 
@@ -5166,7 +5369,7 @@ static bool migrate_improves_locality(struct task_struct *p, struct lb_env *env)
        struct numa_group *numa_group = rcu_dereference(p->numa_group);
        int src_nid, dst_nid;
 
-       if (!sched_feat(NUMA_FAVOUR_HIGHER) || !p->numa_faults_memory ||
+       if (!sched_feat(NUMA_FAVOUR_HIGHER) || !p->numa_faults ||
            !(env->sd->flags & SD_NUMA)) {
                return false;
        }
@@ -5205,7 +5408,7 @@ static bool migrate_degrades_locality(struct task_struct *p, struct lb_env *env)
        if (!sched_feat(NUMA) || !sched_feat(NUMA_RESIST_LOWER))
                return false;
 
-       if (!p->numa_faults_memory || !(env->sd->flags & SD_NUMA))
+       if (!p->numa_faults || !(env->sd->flags & SD_NUMA))
                return false;
 
        src_nid = cpu_to_node(env->src_cpu);
@@ -6149,8 +6352,10 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd
                 * with a large weight task outweighs the tasks on the system).
                 */
                if (prefer_sibling && sds->local &&
-                   sds->local_stat.group_has_free_capacity)
+                   sds->local_stat.group_has_free_capacity) {
                        sgs->group_capacity_factor = min(sgs->group_capacity_factor, 1U);
+                       sgs->group_type = group_classify(sg, sgs);
+               }
 
                if (update_sd_pick_busiest(env, sds, sg, sgs)) {
                        sds->busiest = sg;
@@ -7938,6 +8143,8 @@ const struct sched_class fair_sched_class = {
 
        .get_rr_interval        = get_rr_interval_fair,
 
+       .update_curr            = update_curr_fair,
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
        .task_move_group        = task_move_group_fair,
 #endif
index 67ad4e7f506a2509a0493138662c0fec7dc4d7fa..c65dac8c97cdd5dd72f636455dcecc2742d9706d 100644 (file)
@@ -75,6 +75,10 @@ static unsigned int get_rr_interval_idle(struct rq *rq, struct task_struct *task
        return 0;
 }
 
+static void update_curr_idle(struct rq *rq)
+{
+}
+
 /*
  * Simple, special scheduling class for the per-CPU idle tasks:
  */
@@ -101,4 +105,5 @@ const struct sched_class idle_sched_class = {
 
        .prio_changed           = prio_changed_idle,
        .switched_to            = switched_to_idle,
+       .update_curr            = update_curr_idle,
 };
index d024e6ce30baf50037eac7c256dacc5bf27856f4..ee15f5a0d1c1896c1cc6edf2d202c3f1652c87f8 100644 (file)
@@ -1301,9 +1301,6 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags)
        struct task_struct *curr;
        struct rq *rq;
 
-       if (p->nr_cpus_allowed == 1)
-               goto out;
-
        /* For anything but wake ups, just return the task_cpu */
        if (sd_flag != SD_BALANCE_WAKE && sd_flag != SD_BALANCE_FORK)
                goto out;
@@ -1351,16 +1348,22 @@ out:
 
 static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p)
 {
-       if (rq->curr->nr_cpus_allowed == 1)
+       /*
+        * Current can't be migrated, useless to reschedule,
+        * let's hope p can move out.
+        */
+       if (rq->curr->nr_cpus_allowed == 1 ||
+           !cpupri_find(&rq->rd->cpupri, rq->curr, NULL))
                return;
 
+       /*
+        * p is migratable, so let's not schedule it and
+        * see if it is pushed or pulled somewhere else.
+        */
        if (p->nr_cpus_allowed != 1
            && cpupri_find(&rq->rd->cpupri, p, NULL))
                return;
 
-       if (!cpupri_find(&rq->rd->cpupri, rq->curr, NULL))
-               return;
-
        /*
         * There appears to be other cpus that can accept
         * current and none to run 'p', so lets reschedule
@@ -2128,6 +2131,8 @@ const struct sched_class rt_sched_class = {
 
        .prio_changed           = prio_changed_rt,
        .switched_to            = switched_to_rt,
+
+       .update_curr            = update_curr_rt,
 };
 
 #ifdef CONFIG_SCHED_DEBUG
index 24156c8434d1ebbe679a3fa6df45725aa7db3647..9a2a45c970e7dcbc0c146c027acc1bab713ff4ee 100644 (file)
@@ -176,6 +176,25 @@ struct dl_bw {
        u64 bw, total_bw;
 };
 
+static inline
+void __dl_clear(struct dl_bw *dl_b, u64 tsk_bw)
+{
+       dl_b->total_bw -= tsk_bw;
+}
+
+static inline
+void __dl_add(struct dl_bw *dl_b, u64 tsk_bw)
+{
+       dl_b->total_bw += tsk_bw;
+}
+
+static inline
+bool __dl_overflow(struct dl_bw *dl_b, int cpus, u64 old_bw, u64 new_bw)
+{
+       return dl_b->bw != -1 &&
+              dl_b->bw * cpus < dl_b->total_bw - old_bw + new_bw;
+}
+
 extern struct mutex sched_domains_mutex;
 
 #ifdef CONFIG_CGROUP_SCHED
@@ -678,7 +697,25 @@ static inline u64 rq_clock_task(struct rq *rq)
        return rq->clock_task;
 }
 
+#ifdef CONFIG_NUMA
+enum numa_topology_type {
+       NUMA_DIRECT,
+       NUMA_GLUELESS_MESH,
+       NUMA_BACKPLANE,
+};
+extern enum numa_topology_type sched_numa_topology_type;
+extern int sched_max_numa_distance;
+extern bool find_numa_distance(int distance);
+#endif
+
 #ifdef CONFIG_NUMA_BALANCING
+/* The regions in numa_faults array from task_struct */
+enum numa_faults_stats {
+       NUMA_MEM = 0,
+       NUMA_CPU,
+       NUMA_MEMBUF,
+       NUMA_CPUBUF
+};
 extern void sched_setnuma(struct task_struct *p, int node);
 extern int migrate_task_to(struct task_struct *p, int cpu);
 extern int migrate_swap(struct task_struct *, struct task_struct *);
@@ -1127,6 +1164,11 @@ struct sched_class {
        void (*task_fork) (struct task_struct *p);
        void (*task_dead) (struct task_struct *p);
 
+       /*
+        * The switched_from() call is allowed to drop rq->lock, therefore we
+        * cannot assume the switched_from/switched_to pair is serliazed by
+        * rq->lock. They are however serialized by p->pi_lock.
+        */
        void (*switched_from) (struct rq *this_rq, struct task_struct *task);
        void (*switched_to) (struct rq *this_rq, struct task_struct *task);
        void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
@@ -1135,6 +1177,8 @@ struct sched_class {
        unsigned int (*get_rr_interval) (struct rq *rq,
                                         struct task_struct *task);
 
+       void (*update_curr) (struct rq *rq);
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
        void (*task_move_group) (struct task_struct *p, int on_rq);
 #endif
@@ -1502,6 +1546,7 @@ extern struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq);
 extern struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq);
 extern void print_cfs_stats(struct seq_file *m, int cpu);
 extern void print_rt_stats(struct seq_file *m, int cpu);
+extern void print_dl_stats(struct seq_file *m, int cpu);
 
 extern void init_cfs_rq(struct cfs_rq *cfs_rq);
 extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
index 67426e529f59c044eef35c88c8d906cab641bb64..79ffec45a6acd9415d31d90906b529a6bc0d752b 100644 (file)
@@ -102,6 +102,10 @@ get_rr_interval_stop(struct rq *rq, struct task_struct *task)
        return 0;
 }
 
+static void update_curr_stop(struct rq *rq)
+{
+}
+
 /*
  * Simple, special scheduling class for the per-CPU stop tasks:
  */
@@ -128,4 +132,5 @@ const struct sched_class stop_sched_class = {
 
        .prio_changed           = prio_changed_stop,
        .switched_to            = switched_to_stop,
+       .update_curr            = update_curr_stop,
 };
index 5a62915f47a88564f69a37abd8990db508a27661..852143a79f367fb75fd73f6c60e2dcaf1ae77895 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/wait.h>
 #include <linux/hash.h>
+#include <linux/kthread.h>
 
 void __init_waitqueue_head(wait_queue_head_t *q, const char *name, struct lock_class_key *key)
 {
@@ -297,6 +298,71 @@ int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *
 }
 EXPORT_SYMBOL(autoremove_wake_function);
 
+static inline bool is_kthread_should_stop(void)
+{
+       return (current->flags & PF_KTHREAD) && kthread_should_stop();
+}
+
+/*
+ * DEFINE_WAIT_FUNC(wait, woken_wake_func);
+ *
+ * add_wait_queue(&wq, &wait);
+ * for (;;) {
+ *     if (condition)
+ *         break;
+ *
+ *     p->state = mode;                                condition = true;
+ *     smp_mb(); // A                          smp_wmb(); // C
+ *     if (!wait->flags & WQ_FLAG_WOKEN)       wait->flags |= WQ_FLAG_WOKEN;
+ *         schedule()                          try_to_wake_up();
+ *     p->state = TASK_RUNNING;                    ~~~~~~~~~~~~~~~~~~
+ *     wait->flags &= ~WQ_FLAG_WOKEN;          condition = true;
+ *     smp_mb() // B                           smp_wmb(); // C
+ *                                             wait->flags |= WQ_FLAG_WOKEN;
+ * }
+ * remove_wait_queue(&wq, &wait);
+ *
+ */
+long wait_woken(wait_queue_t *wait, unsigned mode, long timeout)
+{
+       set_current_state(mode); /* A */
+       /*
+        * The above implies an smp_mb(), which matches with the smp_wmb() from
+        * woken_wake_function() such that if we observe WQ_FLAG_WOKEN we must
+        * also observe all state before the wakeup.
+        */
+       if (!(wait->flags & WQ_FLAG_WOKEN) && !is_kthread_should_stop())
+               timeout = schedule_timeout(timeout);
+       __set_current_state(TASK_RUNNING);
+
+       /*
+        * The below implies an smp_mb(), it too pairs with the smp_wmb() from
+        * woken_wake_function() such that we must either observe the wait
+        * condition being true _OR_ WQ_FLAG_WOKEN such that we will not miss
+        * an event.
+        */
+       set_mb(wait->flags, wait->flags & ~WQ_FLAG_WOKEN); /* B */
+
+       return timeout;
+}
+EXPORT_SYMBOL(wait_woken);
+
+int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+       /*
+        * Although this function is called under waitqueue lock, LOCK
+        * doesn't imply write barrier and the users expects write
+        * barrier semantics on wakeup functions.  The following
+        * smp_wmb() is equivalent to smp_wmb() in try_to_wake_up()
+        * and is paired with set_mb() in wait_woken().
+        */
+       smp_wmb(); /* C */
+       wait->flags |= WQ_FLAG_WOKEN;
+
+       return default_wake_function(wait, mode, sync, key);
+}
+EXPORT_SYMBOL(woken_wake_function);
+
 int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *arg)
 {
        struct wait_bit_key *key = arg;
index 8f0876f9f6dd5deb400a1f3ef071b66da877a363..19e35135fc6047a333308f668779627218c39088 100644 (file)
@@ -1275,7 +1275,17 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
                        local_irq_restore(*flags);
                        break;
                }
-
+               /*
+                * This sighand can be already freed and even reused, but
+                * we rely on SLAB_DESTROY_BY_RCU and sighand_ctor() which
+                * initializes ->siglock: this slab can't go away, it has
+                * the same object type, ->siglock can't be reinitialized.
+                *
+                * We need to ensure that tsk->sighand is still the same
+                * after we take the lock, we can race with de_thread() or
+                * __exit_signal(). In the latter case the next iteration
+                * must see ->sighand == NULL.
+                */
                spin_lock(&sighand->siglock);
                if (likely(sighand == tsk->sighand)) {
                        rcu_read_unlock();
@@ -1331,23 +1341,21 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
        int error = -ESRCH;
        struct task_struct *p;
 
-       rcu_read_lock();
-retry:
-       p = pid_task(pid, PIDTYPE_PID);
-       if (p) {
-               error = group_send_sig_info(sig, info, p);
-               if (unlikely(error == -ESRCH))
-                       /*
-                        * The task was unhashed in between, try again.
-                        * If it is dead, pid_task() will return NULL,
-                        * if we race with de_thread() it will find the
-                        * new leader.
-                        */
-                       goto retry;
-       }
-       rcu_read_unlock();
+       for (;;) {
+               rcu_read_lock();
+               p = pid_task(pid, PIDTYPE_PID);
+               if (p)
+                       error = group_send_sig_info(sig, info, p);
+               rcu_read_unlock();
+               if (likely(!p || error != -ESRCH))
+                       return error;
 
-       return error;
+               /*
+                * The task was unhashed in between, try again.  If it
+                * is dead, pid_task() will return NULL, if we race with
+                * de_thread() it will find the new leader.
+                */
+       }
 }
 
 int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
index eb89e1807408575257b8ea60b64559b1adf8afde..f032fb5284e3a340108359a0a17eccfa3b20e115 100644 (file)
@@ -110,7 +110,7 @@ static int smpboot_thread_fn(void *data)
                set_current_state(TASK_INTERRUPTIBLE);
                preempt_disable();
                if (kthread_should_stop()) {
-                       set_current_state(TASK_RUNNING);
+                       __set_current_state(TASK_RUNNING);
                        preempt_enable();
                        if (ht->cleanup)
                                ht->cleanup(td->cpu, cpu_online(td->cpu));
@@ -136,26 +136,27 @@ static int smpboot_thread_fn(void *data)
                /* Check for state change setup */
                switch (td->status) {
                case HP_THREAD_NONE:
+                       __set_current_state(TASK_RUNNING);
                        preempt_enable();
                        if (ht->setup)
                                ht->setup(td->cpu);
                        td->status = HP_THREAD_ACTIVE;
-                       preempt_disable();
-                       break;
+                       continue;
+
                case HP_THREAD_PARKED:
+                       __set_current_state(TASK_RUNNING);
                        preempt_enable();
                        if (ht->unpark)
                                ht->unpark(td->cpu);
                        td->status = HP_THREAD_ACTIVE;
-                       preempt_disable();
-                       break;
+                       continue;
                }
 
                if (!ht->thread_should_run(td->cpu)) {
-                       preempt_enable();
+                       preempt_enable_no_resched();
                        schedule();
                } else {
-                       set_current_state(TASK_RUNNING);
+                       __set_current_state(TASK_RUNNING);
                        preempt_enable();
                        ht->thread_fn(td->cpu);
                }
index 0699add19164ca49838ed98538a8f020ae78c1b7..501baa9ac1be3ac37b1a7f7e1204aea2d5456971 100644 (file)
@@ -656,7 +656,7 @@ static void run_ksoftirqd(unsigned int cpu)
                 * in the task stack here.
                 */
                __do_softirq();
-               rcu_note_context_switch(cpu);
+               rcu_note_context_switch();
                local_irq_enable();
                cond_resched();
                return;
index 4aada6d9fe7445f53e88702fa5e983dc06abd367..15f2511a1b7c6e04a48f99c1b6a402f008607ba3 100644 (file)
@@ -387,7 +387,8 @@ static struct ctl_table kern_table[] = {
                .data           = &sysctl_numa_balancing_scan_size,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &one,
        },
        {
                .procname       = "numa_balancing",
index 7347426fa68da18862584ba888cd34e876a31417..f622cf28628adf6cd116bfdaa2c9acaf0212a392 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_TICK_ONESHOT)                    += tick-oneshot.o
 obj-$(CONFIG_TICK_ONESHOT)                     += tick-sched.o
 obj-$(CONFIG_TIMER_STATS)                      += timer_stats.o
 obj-$(CONFIG_DEBUG_FS)                         += timekeeping_debug.o
-obj-$(CONFIG_TEST_UDELAY)                      += udelay_test.o
+obj-$(CONFIG_TEST_UDELAY)                      += test_udelay.o
 
 $(obj)/time.o: $(obj)/timeconst.h
 
index 9c94c19f13052fb45391584cf14216f2eb494825..55449909f11475372135ac61b33e65114eb151ba 100644 (file)
@@ -72,7 +72,7 @@ static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt,
         * Also omit the add if it would overflow the u64 boundary.
         */
        if ((~0ULL - clc > rnd) &&
-           (!ismax || evt->mult <= (1U << evt->shift)))
+           (!ismax || evt->mult <= (1ULL << evt->shift)))
                clc += rnd;
 
        do_div(clc, evt->mult);
index 492b986195d53350abe899b0ecd059f91edb77a4..a16b67859e2a79929331c5008f96fd7f29ebbfc1 100644 (file)
@@ -553,7 +553,7 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
                *sample = cputime_to_expires(cputime.utime);
                break;
        case CPUCLOCK_SCHED:
-               *sample = cputime.sum_exec_runtime + task_delta_exec(p);
+               *sample = cputime.sum_exec_runtime;
                break;
        }
        return 0;
index 42b463ad90f299707ab66fef2810e179db649cd4..31ea01f42e1f088786a291199cc54e9bde4658c9 100644 (file)
@@ -636,6 +636,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
                        goto out;
                }
        } else {
+               memset(&event.sigev_value, 0, sizeof(event.sigev_value));
                event.sigev_notify = SIGEV_SIGNAL;
                event.sigev_signo = SIGALRM;
                event.sigev_value.sival_int = new_timer->it_id;
diff --git a/kernel/time/test_udelay.c b/kernel/time/test_udelay.c
new file mode 100644 (file)
index 0000000..e622ba3
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * udelay() test kernel module
+ *
+ * Test is executed by writing and reading to /sys/kernel/debug/udelay_test
+ * Tests are configured by writing: USECS ITERATIONS
+ * Tests are executed by reading from the same file.
+ * Specifying usecs of 0 or negative values will run multiples tests.
+ *
+ * Copyright (C) 2014 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/debugfs.h>
+#include <linux/delay.h>
+#include <linux/ktime.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+#define DEFAULT_ITERATIONS 100
+
+#define DEBUGFS_FILENAME "udelay_test"
+
+static DEFINE_MUTEX(udelay_test_lock);
+static struct dentry *udelay_test_debugfs_file;
+static int udelay_test_usecs;
+static int udelay_test_iterations = DEFAULT_ITERATIONS;
+
+static int udelay_test_single(struct seq_file *s, int usecs, uint32_t iters)
+{
+       int min = 0, max = 0, fail_count = 0;
+       uint64_t sum = 0;
+       uint64_t avg;
+       int i;
+       /* Allow udelay to be up to 0.5% fast */
+       int allowed_error_ns = usecs * 5;
+
+       for (i = 0; i < iters; ++i) {
+               struct timespec ts1, ts2;
+               int time_passed;
+
+               ktime_get_ts(&ts1);
+               udelay(usecs);
+               ktime_get_ts(&ts2);
+               time_passed = timespec_to_ns(&ts2) - timespec_to_ns(&ts1);
+
+               if (i == 0 || time_passed < min)
+                       min = time_passed;
+               if (i == 0 || time_passed > max)
+                       max = time_passed;
+               if ((time_passed + allowed_error_ns) / 1000 < usecs)
+                       ++fail_count;
+               WARN_ON(time_passed < 0);
+               sum += time_passed;
+       }
+
+       avg = sum;
+       do_div(avg, iters);
+       seq_printf(s, "%d usecs x %d: exp=%d allowed=%d min=%d avg=%lld max=%d",
+                       usecs, iters, usecs * 1000,
+                       (usecs * 1000) - allowed_error_ns, min, avg, max);
+       if (fail_count)
+               seq_printf(s, " FAIL=%d", fail_count);
+       seq_puts(s, "\n");
+
+       return 0;
+}
+
+static int udelay_test_show(struct seq_file *s, void *v)
+{
+       int usecs;
+       int iters;
+       int ret = 0;
+
+       mutex_lock(&udelay_test_lock);
+       usecs = udelay_test_usecs;
+       iters = udelay_test_iterations;
+       mutex_unlock(&udelay_test_lock);
+
+       if (usecs > 0 && iters > 0) {
+               return udelay_test_single(s, usecs, iters);
+       } else if (usecs == 0) {
+               struct timespec ts;
+
+               ktime_get_ts(&ts);
+               seq_printf(s, "udelay() test (lpj=%ld kt=%ld.%09ld)\n",
+                               loops_per_jiffy, ts.tv_sec, ts.tv_nsec);
+               seq_puts(s, "usage:\n");
+               seq_puts(s, "echo USECS [ITERS] > " DEBUGFS_FILENAME "\n");
+               seq_puts(s, "cat " DEBUGFS_FILENAME "\n");
+       }
+
+       return ret;
+}
+
+static int udelay_test_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, udelay_test_show, inode->i_private);
+}
+
+static ssize_t udelay_test_write(struct file *file, const char __user *buf,
+               size_t count, loff_t *pos)
+{
+       char lbuf[32];
+       int ret;
+       int usecs;
+       int iters;
+
+       if (count >= sizeof(lbuf))
+               return -EINVAL;
+
+       if (copy_from_user(lbuf, buf, count))
+               return -EFAULT;
+       lbuf[count] = '\0';
+
+       ret = sscanf(lbuf, "%d %d", &usecs, &iters);
+       if (ret < 1)
+               return -EINVAL;
+       else if (ret < 2)
+               iters = DEFAULT_ITERATIONS;
+
+       mutex_lock(&udelay_test_lock);
+       udelay_test_usecs = usecs;
+       udelay_test_iterations = iters;
+       mutex_unlock(&udelay_test_lock);
+
+       return count;
+}
+
+static const struct file_operations udelay_test_debugfs_ops = {
+       .owner = THIS_MODULE,
+       .open = udelay_test_open,
+       .read = seq_read,
+       .write = udelay_test_write,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int __init udelay_test_init(void)
+{
+       mutex_lock(&udelay_test_lock);
+       udelay_test_debugfs_file = debugfs_create_file(DEBUGFS_FILENAME,
+                       S_IRUSR, NULL, NULL, &udelay_test_debugfs_ops);
+       mutex_unlock(&udelay_test_lock);
+
+       return 0;
+}
+
+module_init(udelay_test_init);
+
+static void __exit udelay_test_exit(void)
+{
+       mutex_lock(&udelay_test_lock);
+       debugfs_remove(udelay_test_debugfs_file);
+       mutex_unlock(&udelay_test_lock);
+}
+
+module_exit(udelay_test_exit);
+
+MODULE_AUTHOR("David Riley <davidriley@chromium.org>");
+MODULE_LICENSE("GPL");
index 7b5741fc411007825ec0ba0839caf4e0870e46e3..1f4356037a7d5e1068c148640757870c1f3854d3 100644 (file)
@@ -585,7 +585,7 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
                last_jiffies = jiffies;
        } while (read_seqretry(&jiffies_lock, seq));
 
-       if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) ||
+       if (rcu_needs_cpu(&rcu_delta_jiffies) ||
            arch_needs_cpu() || irq_work_needs_cpu()) {
                next_jiffies = last_jiffies + 1;
                delta_jiffies = 1;
index a9ae20fb0b11ca879220b7c80467b7485fb3914f..65015ff2f07c6a6ba6144bc79e6fb85883bdceb2 100644 (file)
@@ -304,7 +304,9 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran)
 }
 EXPORT_SYMBOL(timespec_trunc);
 
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+/*
+ * mktime64 - Converts date to seconds.
+ * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  *
@@ -314,15 +316,10 @@ EXPORT_SYMBOL(timespec_trunc);
  * -year/100+year/400 terms, and add 10.]
  *
  * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines where long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
  */
-unsigned long
-mktime(const unsigned int year0, const unsigned int mon0,
-       const unsigned int day, const unsigned int hour,
-       const unsigned int min, const unsigned int sec)
+time64_t mktime64(const unsigned int year0, const unsigned int mon0,
+               const unsigned int day, const unsigned int hour,
+               const unsigned int min, const unsigned int sec)
 {
        unsigned int mon = mon0, year = year0;
 
@@ -332,15 +329,14 @@ mktime(const unsigned int year0, const unsigned int mon0,
                year -= 1;
        }
 
-       return ((((unsigned long)
+       return ((((time64_t)
                  (year/4 - year/100 + year/400 + 367*mon/12 + day) +
                  year*365 - 719499
            )*24 + hour /* now have hours */
          )*60 + min /* now have minutes */
        )*60 + sec; /* finally seconds */
 }
-
-EXPORT_SYMBOL(mktime);
+EXPORT_SYMBOL(mktime64);
 
 /**
  * set_normalized_timespec - set timespec sec and nsec parts and normalize
index ec1791fae96575ffe49c9aa1a2f42cbc6b21df2a..2dc0646258aeebd1102cde4db5bd20162f4d5a4e 100644 (file)
@@ -519,9 +519,9 @@ EXPORT_SYMBOL(__getnstimeofday64);
 
 /**
  * getnstimeofday64 - Returns the time of day in a timespec64.
- * @ts:                pointer to the timespec to be set
+ * @ts:                pointer to the timespec64 to be set
  *
- * Returns the time of day in a timespec (WARN if suspended).
+ * Returns the time of day in a timespec64 (WARN if suspended).
  */
 void getnstimeofday64(struct timespec64 *ts)
 {
@@ -623,7 +623,7 @@ EXPORT_SYMBOL_GPL(ktime_get_raw);
  *
  * The function calculates the monotonic clock from the realtime
  * clock and the wall_to_monotonic offset and stores the result
- * in normalized timespec format in the variable pointed to by @ts.
+ * in normalized timespec64 format in the variable pointed to by @ts.
  */
 void ktime_get_ts64(struct timespec64 *ts)
 {
@@ -703,18 +703,18 @@ void do_gettimeofday(struct timeval *tv)
 EXPORT_SYMBOL(do_gettimeofday);
 
 /**
- * do_settimeofday - Sets the time of day
- * @tv:                pointer to the timespec variable containing the new time
+ * do_settimeofday64 - Sets the time of day.
+ * @ts:     pointer to the timespec64 variable containing the new time
  *
  * Sets the time of day to the new time and update NTP and notify hrtimers
  */
-int do_settimeofday(const struct timespec *tv)
+int do_settimeofday64(const struct timespec64 *ts)
 {
        struct timekeeper *tk = &tk_core.timekeeper;
-       struct timespec64 ts_delta, xt, tmp;
+       struct timespec64 ts_delta, xt;
        unsigned long flags;
 
-       if (!timespec_valid_strict(tv))
+       if (!timespec64_valid_strict(ts))
                return -EINVAL;
 
        raw_spin_lock_irqsave(&timekeeper_lock, flags);
@@ -723,13 +723,12 @@ int do_settimeofday(const struct timespec *tv)
        timekeeping_forward_now(tk);
 
        xt = tk_xtime(tk);
-       ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
-       ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
+       ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
+       ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;
 
        tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));
 
-       tmp = timespec_to_timespec64(*tv);
-       tk_set_xtime(tk, &tmp);
+       tk_set_xtime(tk, ts);
 
        timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
 
@@ -741,7 +740,7 @@ int do_settimeofday(const struct timespec *tv)
 
        return 0;
 }
-EXPORT_SYMBOL(do_settimeofday);
+EXPORT_SYMBOL(do_settimeofday64);
 
 /**
  * timekeeping_inject_offset - Adds or subtracts from the current time.
@@ -895,12 +894,12 @@ int timekeeping_notify(struct clocksource *clock)
 }
 
 /**
- * getrawmonotonic - Returns the raw monotonic time in a timespec
- * @ts:                pointer to the timespec to be set
+ * getrawmonotonic64 - Returns the raw monotonic time in a timespec
+ * @ts:                pointer to the timespec64 to be set
  *
  * Returns the raw monotonic time (completely un-modified by ntp)
  */
-void getrawmonotonic(struct timespec *ts)
+void getrawmonotonic64(struct timespec64 *ts)
 {
        struct timekeeper *tk = &tk_core.timekeeper;
        struct timespec64 ts64;
@@ -915,9 +914,10 @@ void getrawmonotonic(struct timespec *ts)
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
        timespec64_add_ns(&ts64, nsecs);
-       *ts = timespec64_to_timespec(ts64);
+       *ts = ts64;
 }
-EXPORT_SYMBOL(getrawmonotonic);
+EXPORT_SYMBOL(getrawmonotonic64);
+
 
 /**
  * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres
@@ -1068,8 +1068,8 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
 }
 
 /**
- * timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values
- * @delta: pointer to a timespec delta value
+ * timekeeping_inject_sleeptime64 - Adds suspend interval to timeekeeping values
+ * @delta: pointer to a timespec64 delta value
  *
  * This hook is for architectures that cannot support read_persistent_clock
  * because their RTC/persistent clock is only accessible when irqs are enabled.
@@ -1077,10 +1077,9 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
  * This function should only be called by rtc_resume(), and allows
  * a suspend offset to be injected into the timekeeping values.
  */
-void timekeeping_inject_sleeptime(struct timespec *delta)
+void timekeeping_inject_sleeptime64(struct timespec64 *delta)
 {
        struct timekeeper *tk = &tk_core.timekeeper;
-       struct timespec64 tmp;
        unsigned long flags;
 
        /*
@@ -1095,8 +1094,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
 
        timekeeping_forward_now(tk);
 
-       tmp = timespec_to_timespec64(*delta);
-       __timekeeping_inject_sleeptime(tk, &tmp);
+       __timekeeping_inject_sleeptime(tk, delta);
 
        timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);
 
@@ -1332,6 +1330,12 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
         *
         * XXX - TODO: Doc ntp_error calculation.
         */
+       if ((mult_adj > 0) && (tk->tkr.mult + mult_adj < mult_adj)) {
+               /* NTP adjustment caused clocksource mult overflow */
+               WARN_ON_ONCE(1);
+               return;
+       }
+
        tk->tkr.mult += mult_adj;
        tk->xtime_interval += interval;
        tk->tkr.xtime_nsec -= offset;
@@ -1397,7 +1401,8 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
        }
 
        if (unlikely(tk->tkr.clock->maxadj &&
-               (tk->tkr.mult > tk->tkr.clock->mult + tk->tkr.clock->maxadj))) {
+               (abs(tk->tkr.mult - tk->tkr.clock->mult)
+                       > tk->tkr.clock->maxadj))) {
                printk_once(KERN_WARNING
                        "Adjusting %s more than 11%% (%ld vs %ld)\n",
                        tk->tkr.clock->name, (long)tk->tkr.mult,
@@ -1646,7 +1651,7 @@ struct timespec current_kernel_time(void)
 }
 EXPORT_SYMBOL(current_kernel_time);
 
-struct timespec get_monotonic_coarse(void)
+struct timespec64 get_monotonic_coarse64(void)
 {
        struct timekeeper *tk = &tk_core.timekeeper;
        struct timespec64 now, mono;
@@ -1662,7 +1667,7 @@ struct timespec get_monotonic_coarse(void)
        set_normalized_timespec64(&now, now.tv_sec + mono.tv_sec,
                                now.tv_nsec + mono.tv_nsec);
 
-       return timespec64_to_timespec(now);
+       return now;
 }
 
 /*
index 3260ffdb368fbd9ae4617bddfc7aecf888880351..2d3f5c5049394615912b09ad16a4e639cb6cba9b 100644 (file)
@@ -1377,12 +1377,11 @@ unsigned long get_next_timer_interrupt(unsigned long now)
 void update_process_times(int user_tick)
 {
        struct task_struct *p = current;
-       int cpu = smp_processor_id();
 
        /* Note: this timer irq context must be accounted for as well. */
        account_process_tick(p, user_tick);
        run_local_timers();
-       rcu_check_callbacks(cpu, user_tick);
+       rcu_check_callbacks(user_tick);
 #ifdef CONFIG_IRQ_WORK
        if (in_irq())
                irq_work_tick();
diff --git a/kernel/time/udelay_test.c b/kernel/time/udelay_test.c
deleted file mode 100644 (file)
index e622ba3..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * udelay() test kernel module
- *
- * Test is executed by writing and reading to /sys/kernel/debug/udelay_test
- * Tests are configured by writing: USECS ITERATIONS
- * Tests are executed by reading from the same file.
- * Specifying usecs of 0 or negative values will run multiples tests.
- *
- * Copyright (C) 2014 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/debugfs.h>
-#include <linux/delay.h>
-#include <linux/ktime.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-
-#define DEFAULT_ITERATIONS 100
-
-#define DEBUGFS_FILENAME "udelay_test"
-
-static DEFINE_MUTEX(udelay_test_lock);
-static struct dentry *udelay_test_debugfs_file;
-static int udelay_test_usecs;
-static int udelay_test_iterations = DEFAULT_ITERATIONS;
-
-static int udelay_test_single(struct seq_file *s, int usecs, uint32_t iters)
-{
-       int min = 0, max = 0, fail_count = 0;
-       uint64_t sum = 0;
-       uint64_t avg;
-       int i;
-       /* Allow udelay to be up to 0.5% fast */
-       int allowed_error_ns = usecs * 5;
-
-       for (i = 0; i < iters; ++i) {
-               struct timespec ts1, ts2;
-               int time_passed;
-
-               ktime_get_ts(&ts1);
-               udelay(usecs);
-               ktime_get_ts(&ts2);
-               time_passed = timespec_to_ns(&ts2) - timespec_to_ns(&ts1);
-
-               if (i == 0 || time_passed < min)
-                       min = time_passed;
-               if (i == 0 || time_passed > max)
-                       max = time_passed;
-               if ((time_passed + allowed_error_ns) / 1000 < usecs)
-                       ++fail_count;
-               WARN_ON(time_passed < 0);
-               sum += time_passed;
-       }
-
-       avg = sum;
-       do_div(avg, iters);
-       seq_printf(s, "%d usecs x %d: exp=%d allowed=%d min=%d avg=%lld max=%d",
-                       usecs, iters, usecs * 1000,
-                       (usecs * 1000) - allowed_error_ns, min, avg, max);
-       if (fail_count)
-               seq_printf(s, " FAIL=%d", fail_count);
-       seq_puts(s, "\n");
-
-       return 0;
-}
-
-static int udelay_test_show(struct seq_file *s, void *v)
-{
-       int usecs;
-       int iters;
-       int ret = 0;
-
-       mutex_lock(&udelay_test_lock);
-       usecs = udelay_test_usecs;
-       iters = udelay_test_iterations;
-       mutex_unlock(&udelay_test_lock);
-
-       if (usecs > 0 && iters > 0) {
-               return udelay_test_single(s, usecs, iters);
-       } else if (usecs == 0) {
-               struct timespec ts;
-
-               ktime_get_ts(&ts);
-               seq_printf(s, "udelay() test (lpj=%ld kt=%ld.%09ld)\n",
-                               loops_per_jiffy, ts.tv_sec, ts.tv_nsec);
-               seq_puts(s, "usage:\n");
-               seq_puts(s, "echo USECS [ITERS] > " DEBUGFS_FILENAME "\n");
-               seq_puts(s, "cat " DEBUGFS_FILENAME "\n");
-       }
-
-       return ret;
-}
-
-static int udelay_test_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, udelay_test_show, inode->i_private);
-}
-
-static ssize_t udelay_test_write(struct file *file, const char __user *buf,
-               size_t count, loff_t *pos)
-{
-       char lbuf[32];
-       int ret;
-       int usecs;
-       int iters;
-
-       if (count >= sizeof(lbuf))
-               return -EINVAL;
-
-       if (copy_from_user(lbuf, buf, count))
-               return -EFAULT;
-       lbuf[count] = '\0';
-
-       ret = sscanf(lbuf, "%d %d", &usecs, &iters);
-       if (ret < 1)
-               return -EINVAL;
-       else if (ret < 2)
-               iters = DEFAULT_ITERATIONS;
-
-       mutex_lock(&udelay_test_lock);
-       udelay_test_usecs = usecs;
-       udelay_test_iterations = iters;
-       mutex_unlock(&udelay_test_lock);
-
-       return count;
-}
-
-static const struct file_operations udelay_test_debugfs_ops = {
-       .owner = THIS_MODULE,
-       .open = udelay_test_open,
-       .read = seq_read,
-       .write = udelay_test_write,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int __init udelay_test_init(void)
-{
-       mutex_lock(&udelay_test_lock);
-       udelay_test_debugfs_file = debugfs_create_file(DEBUGFS_FILENAME,
-                       S_IRUSR, NULL, NULL, &udelay_test_debugfs_ops);
-       mutex_unlock(&udelay_test_lock);
-
-       return 0;
-}
-
-module_init(udelay_test_init);
-
-static void __exit udelay_test_exit(void)
-{
-       mutex_lock(&udelay_test_lock);
-       debugfs_remove(udelay_test_debugfs_file);
-       mutex_unlock(&udelay_test_lock);
-}
-
-module_exit(udelay_test_exit);
-
-MODULE_AUTHOR("David Riley <davidriley@chromium.org>");
-MODULE_LICENSE("GPL");
index fb186b9ddf519159d866fcaa8fc187328820f2bf..31c90fec415899bfb40927bbbcc8ad29657317ab 100644 (file)
@@ -1925,8 +1925,16 @@ ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec)
         * when we are adding another op to the rec or removing the
         * current one. Thus, if the op is being added, we can
         * ignore it because it hasn't attached itself to the rec
-        * yet. That means we just need to find the op that has a
-        * trampoline and is not beeing added.
+        * yet.
+        *
+        * If an ops is being modified (hooking to different functions)
+        * then we don't care about the new functions that are being
+        * added, just the old ones (that are probably being removed).
+        *
+        * If we are adding an ops to a function that already is using
+        * a trampoline, it needs to be removed (trampolines are only
+        * for single ops connected), then an ops that is not being
+        * modified also needs to be checked.
         */
        do_for_each_ftrace_op(op, ftrace_ops_list) {
 
@@ -1940,17 +1948,23 @@ ftrace_find_tramp_ops_curr(struct dyn_ftrace *rec)
                if (op->flags & FTRACE_OPS_FL_ADDING)
                        continue;
 
+
                /*
-                * If the ops is not being added and has a trampoline,
-                * then it must be the one that we want!
+                * If the ops is being modified and is in the old
+                * hash, then it is probably being removed from this
+                * function.
                 */
-               if (hash_contains_ip(ip, op->func_hash))
-                       return op;
-
-               /* If the ops is being modified, it may be in the old hash. */
                if ((op->flags & FTRACE_OPS_FL_MODIFYING) &&
                    hash_contains_ip(ip, &op->old_hash))
                        return op;
+               /*
+                * If the ops is not being added or modified, and it's
+                * in its normal filter hash, then this must be the one
+                * we want!
+                */
+               if (!(op->flags & FTRACE_OPS_FL_MODIFYING) &&
+                   hash_contains_ip(ip, op->func_hash))
+                       return op;
 
        } while_for_each_ftrace_op(op);
 
@@ -2293,10 +2307,13 @@ static void ftrace_run_update_code(int command)
        FTRACE_WARN_ON(ret);
 }
 
-static void ftrace_run_modify_code(struct ftrace_ops *ops, int command)
+static void ftrace_run_modify_code(struct ftrace_ops *ops, int command,
+                                  struct ftrace_hash *old_hash)
 {
        ops->flags |= FTRACE_OPS_FL_MODIFYING;
+       ops->old_hash.filter_hash = old_hash;
        ftrace_run_update_code(command);
+       ops->old_hash.filter_hash = NULL;
        ops->flags &= ~FTRACE_OPS_FL_MODIFYING;
 }
 
@@ -3340,7 +3357,7 @@ static struct ftrace_ops trace_probe_ops __read_mostly =
 
 static int ftrace_probe_registered;
 
-static void __enable_ftrace_function_probe(void)
+static void __enable_ftrace_function_probe(struct ftrace_hash *old_hash)
 {
        int ret;
        int i;
@@ -3348,7 +3365,8 @@ static void __enable_ftrace_function_probe(void)
        if (ftrace_probe_registered) {
                /* still need to update the function call sites */
                if (ftrace_enabled)
-                       ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS);
+                       ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS,
+                                              old_hash);
                return;
        }
 
@@ -3477,13 +3495,14 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
        } while_for_each_ftrace_rec();
 
        ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
+
+       __enable_ftrace_function_probe(old_hash);
+
        if (!ret)
                free_ftrace_hash_rcu(old_hash);
        else
                count = ret;
 
-       __enable_ftrace_function_probe();
-
  out_unlock:
        mutex_unlock(&ftrace_lock);
  out:
@@ -3764,10 +3783,11 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
        return add_hash_entry(hash, ip);
 }
 
-static void ftrace_ops_update_code(struct ftrace_ops *ops)
+static void ftrace_ops_update_code(struct ftrace_ops *ops,
+                                  struct ftrace_hash *old_hash)
 {
        if (ops->flags & FTRACE_OPS_FL_ENABLED && ftrace_enabled)
-               ftrace_run_modify_code(ops, FTRACE_UPDATE_CALLS);
+               ftrace_run_modify_code(ops, FTRACE_UPDATE_CALLS, old_hash);
 }
 
 static int
@@ -3813,7 +3833,7 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len,
        old_hash = *orig_hash;
        ret = ftrace_hash_move(ops, enable, orig_hash, hash);
        if (!ret) {
-               ftrace_ops_update_code(ops);
+               ftrace_ops_update_code(ops, old_hash);
                free_ftrace_hash_rcu(old_hash);
        }
        mutex_unlock(&ftrace_lock);
@@ -4058,7 +4078,7 @@ int ftrace_regex_release(struct inode *inode, struct file *file)
                ret = ftrace_hash_move(iter->ops, filter_hash,
                                       orig_hash, iter->hash);
                if (!ret) {
-                       ftrace_ops_update_code(iter->ops);
+                       ftrace_ops_update_code(iter->ops, old_hash);
                        free_ftrace_hash_rcu(old_hash);
                }
                mutex_unlock(&ftrace_lock);
index 2d75c94ae87d871bbf42db7b1ee949463bb7f65f..a56e07c8d15b8b730eb54f2020a018ff440eec6c 100644 (file)
@@ -538,16 +538,18 @@ static void rb_wake_up_waiters(struct irq_work *work)
  * ring_buffer_wait - wait for input to the ring buffer
  * @buffer: buffer to wait on
  * @cpu: the cpu buffer to wait on
+ * @full: wait until a full page is available, if @cpu != RING_BUFFER_ALL_CPUS
  *
  * If @cpu == RING_BUFFER_ALL_CPUS then the task will wake up as soon
  * as data is added to any of the @buffer's cpu buffers. Otherwise
  * it will wait for data to be added to a specific cpu buffer.
  */
-int ring_buffer_wait(struct ring_buffer *buffer, int cpu)
+int ring_buffer_wait(struct ring_buffer *buffer, int cpu, bool full)
 {
-       struct ring_buffer_per_cpu *cpu_buffer;
+       struct ring_buffer_per_cpu *uninitialized_var(cpu_buffer);
        DEFINE_WAIT(wait);
        struct rb_irq_work *work;
+       int ret = 0;
 
        /*
         * Depending on what the caller is waiting for, either any
@@ -564,36 +566,61 @@ int ring_buffer_wait(struct ring_buffer *buffer, int cpu)
        }
 
 
-       prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE);
+       while (true) {
+               prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE);
 
-       /*
-        * The events can happen in critical sections where
-        * checking a work queue can cause deadlocks.
-        * After adding a task to the queue, this flag is set
-        * only to notify events to try to wake up the queue
-        * using irq_work.
-        *
-        * We don't clear it even if the buffer is no longer
-        * empty. The flag only causes the next event to run
-        * irq_work to do the work queue wake up. The worse
-        * that can happen if we race with !trace_empty() is that
-        * an event will cause an irq_work to try to wake up
-        * an empty queue.
-        *
-        * There's no reason to protect this flag either, as
-        * the work queue and irq_work logic will do the necessary
-        * synchronization for the wake ups. The only thing
-        * that is necessary is that the wake up happens after
-        * a task has been queued. It's OK for spurious wake ups.
-        */
-       work->waiters_pending = true;
+               /*
+                * The events can happen in critical sections where
+                * checking a work queue can cause deadlocks.
+                * After adding a task to the queue, this flag is set
+                * only to notify events to try to wake up the queue
+                * using irq_work.
+                *
+                * We don't clear it even if the buffer is no longer
+                * empty. The flag only causes the next event to run
+                * irq_work to do the work queue wake up. The worse
+                * that can happen if we race with !trace_empty() is that
+                * an event will cause an irq_work to try to wake up
+                * an empty queue.
+                *
+                * There's no reason to protect this flag either, as
+                * the work queue and irq_work logic will do the necessary
+                * synchronization for the wake ups. The only thing
+                * that is necessary is that the wake up happens after
+                * a task has been queued. It's OK for spurious wake ups.
+                */
+               work->waiters_pending = true;
+
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+
+               if (cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer))
+                       break;
+
+               if (cpu != RING_BUFFER_ALL_CPUS &&
+                   !ring_buffer_empty_cpu(buffer, cpu)) {
+                       unsigned long flags;
+                       bool pagebusy;
+
+                       if (!full)
+                               break;
+
+                       raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
+                       pagebusy = cpu_buffer->reader_page == cpu_buffer->commit_page;
+                       raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
+
+                       if (!pagebusy)
+                               break;
+               }
 
-       if ((cpu == RING_BUFFER_ALL_CPUS && ring_buffer_empty(buffer)) ||
-           (cpu != RING_BUFFER_ALL_CPUS && ring_buffer_empty_cpu(buffer, cpu)))
                schedule();
+       }
 
        finish_wait(&work->waiters, &wait);
-       return 0;
+
+       return ret;
 }
 
 /**
index 8a528392b1f465da19d297a84699c4931102cf3d..92f4a6cee1727360ff9d739a126f168a6cacd980 100644 (file)
@@ -1076,13 +1076,14 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 }
 #endif /* CONFIG_TRACER_MAX_TRACE */
 
-static int wait_on_pipe(struct trace_iterator *iter)
+static int wait_on_pipe(struct trace_iterator *iter, bool full)
 {
        /* Iterators are static, they should be filled or empty */
        if (trace_buffer_iter(iter, iter->cpu_file))
                return 0;
 
-       return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
+       return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file,
+                               full);
 }
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
@@ -4434,15 +4435,12 @@ static int tracing_wait_pipe(struct file *filp)
 
                mutex_unlock(&iter->mutex);
 
-               ret = wait_on_pipe(iter);
+               ret = wait_on_pipe(iter, false);
 
                mutex_lock(&iter->mutex);
 
                if (ret)
                        return ret;
-
-               if (signal_pending(current))
-                       return -EINTR;
        }
 
        return 1;
@@ -5372,16 +5370,12 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
                                goto out_unlock;
                        }
                        mutex_unlock(&trace_types_lock);
-                       ret = wait_on_pipe(iter);
+                       ret = wait_on_pipe(iter, false);
                        mutex_lock(&trace_types_lock);
                        if (ret) {
                                size = ret;
                                goto out_unlock;
                        }
-                       if (signal_pending(current)) {
-                               size = -EINTR;
-                               goto out_unlock;
-                       }
                        goto again;
                }
                size = 0;
@@ -5500,7 +5494,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
        };
        struct buffer_ref *ref;
        int entries, size, i;
-       ssize_t ret;
+       ssize_t ret = 0;
 
        mutex_lock(&trace_types_lock);
 
@@ -5538,13 +5532,16 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                int r;
 
                ref = kzalloc(sizeof(*ref), GFP_KERNEL);
-               if (!ref)
+               if (!ref) {
+                       ret = -ENOMEM;
                        break;
+               }
 
                ref->ref = 1;
                ref->buffer = iter->trace_buffer->buffer;
                ref->page = ring_buffer_alloc_read_page(ref->buffer, iter->cpu_file);
                if (!ref->page) {
+                       ret = -ENOMEM;
                        kfree(ref);
                        break;
                }
@@ -5582,19 +5579,19 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 
        /* did we read anything? */
        if (!spd.nr_pages) {
+               if (ret)
+                       goto out;
+
                if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) {
                        ret = -EAGAIN;
                        goto out;
                }
                mutex_unlock(&trace_types_lock);
-               ret = wait_on_pipe(iter);
+               ret = wait_on_pipe(iter, true);
                mutex_lock(&trace_types_lock);
                if (ret)
                        goto out;
-               if (signal_pending(current)) {
-                       ret = -EINTR;
-                       goto out;
-               }
+
                goto again;
        }
 
index 4dc8b79c5f75d214919220bdc45232fe635e6af0..29228c4d569692ea4234d880d13e94233b3e32f4 100644 (file)
@@ -313,7 +313,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
        int size;
 
        syscall_nr = trace_get_syscall_nr(current, regs);
-       if (syscall_nr < 0)
+       if (syscall_nr < 0 || syscall_nr >= NR_syscalls)
                return;
 
        /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE) */
@@ -360,7 +360,7 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
        int syscall_nr;
 
        syscall_nr = trace_get_syscall_nr(current, regs);
-       if (syscall_nr < 0)
+       if (syscall_nr < 0 || syscall_nr >= NR_syscalls)
                return;
 
        /* Here we're inside tp handler's rcu_read_lock_sched (__DO_TRACE()) */
@@ -567,7 +567,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
        int size;
 
        syscall_nr = trace_get_syscall_nr(current, regs);
-       if (syscall_nr < 0)
+       if (syscall_nr < 0 || syscall_nr >= NR_syscalls)
                return;
        if (!test_bit(syscall_nr, enabled_perf_enter_syscalls))
                return;
@@ -641,7 +641,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
        int size;
 
        syscall_nr = trace_get_syscall_nr(current, regs);
-       if (syscall_nr < 0)
+       if (syscall_nr < 0 || syscall_nr >= NR_syscalls)
                return;
        if (!test_bit(syscall_nr, enabled_perf_exit_syscalls))
                return;
index 4e35a5d767ed2f50c69df7dbdbcf0e3d9885777f..d780351835e9cb9e0b9bcf26f0e85f43d11f15c4 100644 (file)
@@ -1238,21 +1238,9 @@ config RCU_CPU_STALL_TIMEOUT
          RCU grace period persists, additional CPU stall warnings are
          printed at more widely spaced intervals.
 
-config RCU_CPU_STALL_VERBOSE
-       bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR"
-       depends on TREE_PREEMPT_RCU
-       default y
-       help
-         This option causes RCU to printk detailed per-task information
-         for any tasks that are stalling the current RCU grace period.
-
-         Say N if you are unsure.
-
-         Say Y if you want to enable such checks.
-
 config RCU_CPU_STALL_INFO
        bool "Print additional diagnostics on RCU CPU stall"
-       depends on (TREE_RCU || TREE_PREEMPT_RCU) && DEBUG_KERNEL
+       depends on (TREE_RCU || PREEMPT_RCU) && DEBUG_KERNEL
        default n
        help
          For each stalled CPU that is aware of the current RCU grace
index 7512dc978f1872fe4a395868ed0f3cbd30de2ad0..0211d2bd5e17551856da7ca97aea0849528b2ead 100644 (file)
@@ -10,7 +10,7 @@ endif
 lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o dump_stack.o timerqueue.o\
         idr.o int_sqrt.o extable.o \
-        sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
+        sha1.o md5.o irq_regs.o argv_split.o \
         proportions.o flex_proportions.o ratelimit.o show_mem.o \
         is_single_threaded.o plist.o decompress.o kobject_uevent.o \
         earlycpio.o
@@ -26,7 +26,7 @@ obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
         bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
         gcd.o lcm.o list_sort.o uuid.o flex_array.o iovec.o clz_ctz.o \
         bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o kfifo.o \
-        percpu-refcount.o percpu_ida.o hash.o rhashtable.o
+        percpu-refcount.o percpu_ida.o hash.o rhashtable.o reciprocal_div.o
 obj-y += string_helpers.o
 obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
 obj-y += kstrtox.o
index cd250a2e14cb1381d256ef0590b63bfd653cb83d..b499ab6ada29a0d4db2e4692083c2d21441a42ee 100644 (file)
@@ -131,7 +131,9 @@ void __bitmap_shift_right(unsigned long *dst,
                lower = src[off + k];
                if (left && off + k == lim - 1)
                        lower &= mask;
-               dst[k] = upper << (BITS_PER_LONG - rem) | lower >> rem;
+               dst[k] = lower >> rem;
+               if (rem)
+                       dst[k] |= upper << (BITS_PER_LONG - rem);
                if (left && k == lim - 1)
                        dst[k] &= mask;
        }
@@ -172,7 +174,9 @@ void __bitmap_shift_left(unsigned long *dst,
                upper = src[k];
                if (left && k == lim - 1)
                        upper &= (1UL << left) - 1;
-               dst[k + off] = lower  >> (BITS_PER_LONG - rem) | upper << rem;
+               dst[k + off] = upper << rem;
+               if (rem)
+                       dst[k + off] |= lower >> (BITS_PER_LONG - rem);
                if (left && k + off == lim - 1)
                        dst[k + off] &= (1UL << left) - 1;
        }
index 76a712e6e20e3d0480d9f338565079a9089560dd..8f13cf73c2ecf916c203ef7e963d250a113c3dee 100644 (file)
@@ -160,3 +160,32 @@ unsigned long long memparse(const char *ptr, char **retptr)
        return ret;
 }
 EXPORT_SYMBOL(memparse);
+
+/**
+ *     parse_option_str - Parse a string and check an option is set or not
+ *     @str: String to be parsed
+ *     @option: option name
+ *
+ *     This function parses a string containing a comma-separated list of
+ *     strings like a=b,c.
+ *
+ *     Return true if there's such option in the string, or return false.
+ */
+bool parse_option_str(const char *str, const char *option)
+{
+       while (*str) {
+               if (!strncmp(str, option, strlen(option))) {
+                       str += strlen(option);
+                       if (!*str || *str == ',')
+                               return true;
+               }
+
+               while (*str && *str != ',')
+                       str++;
+
+               if (*str == ',')
+                       str++;
+       }
+
+       return false;
+}
index cce4dd68c40da211948177f6903917d4ac81b176..2e65d206b01c13d3ad02a57c3d0842b89c8637bd 100644 (file)
@@ -598,6 +598,7 @@ struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order,
 
        return pool;
 }
+EXPORT_SYMBOL(devm_gen_pool_create);
 
 /**
  * dev_get_gen_pool - Obtain the gen_pool (if any) for a device
index 081be3ba9ea8285b05374e6bb98299af541f567c..624a0b7c05ef15934cee4a2574852f74620878a9 100644 (file)
@@ -230,7 +230,7 @@ int rhashtable_expand(struct rhashtable *ht, gfp_t flags)
        ht->shift++;
 
        /* For each new bucket, search the corresponding old bucket
-        * for the rst entry that hashes to the new bucket, and
+        * for the first entry that hashes to the new bucket, and
         * link the new bucket to that entry. Since all the entries
         * which will end up in the new bucket appear in the same
         * old bucket, this constructs an entirely valid new hash
@@ -248,8 +248,8 @@ int rhashtable_expand(struct rhashtable *ht, gfp_t flags)
        }
 
        /* Publish the new table pointer. Lookups may now traverse
-        * the new table, but they will not benet from any
-        * additional efciency until later steps unzip the buckets.
+        * the new table, but they will not benefit from any
+        * additional efficiency until later steps unzip the buckets.
         */
        rcu_assign_pointer(ht->tbl, new_tbl);
 
@@ -306,14 +306,14 @@ int rhashtable_shrink(struct rhashtable *ht, gfp_t flags)
 
        ht->shift--;
 
-       /* Link each bucket in the new table to the rst bucket
+       /* Link each bucket in the new table to the first bucket
         * in the old table that contains entries which will hash
         * to the new bucket.
         */
        for (i = 0; i < ntbl->size; i++) {
                ntbl->buckets[i] = tbl->buckets[i];
 
-               /* Link each bucket in the new table to the rst bucket
+               /* Link each bucket in the new table to the first bucket
                 * in the old table that contains entries which will hash
                 * to the new bucket.
                 */
index 9cdf62f8accdeaf777e8661ba51e3c08617ad06e..c9f2e8c6ccc996c8a40bac6872749185170ec7f9 100644 (file)
@@ -203,10 +203,10 @@ void __sg_free_table(struct sg_table *table, unsigned int max_ents,
                }
 
                table->orig_nents -= sg_size;
-               if (!skip_first_chunk) {
-                       free_fn(sgl, alloc_size);
+               if (skip_first_chunk)
                        skip_first_chunk = false;
-               }
+               else
+                       free_fn(sgl, alloc_size);
                sgl = next;
        }
 
index 09225796991a83a9281194d855719021b8b18282..5e256271b47b02b1a0265ad6a89b2bccf5c40002 100644 (file)
@@ -28,7 +28,7 @@ void show_mem(unsigned int filter)
                                continue;
 
                        total += zone->present_pages;
-                       reserved = zone->present_pages - zone->managed_pages;
+                       reserved += zone->present_pages - zone->managed_pages;
 
                        if (is_highmem_idx(zoneid))
                                highmem += zone->present_pages;
index 2fc20aa06f848fcebd8aa30d238942f5ec399690..10063300b83009dfcdc08988d640fc191481dde5 100644 (file)
@@ -598,6 +598,22 @@ void *memset(void *s, int c, size_t count)
 EXPORT_SYMBOL(memset);
 #endif
 
+/**
+ * memzero_explicit - Fill a region of memory (e.g. sensitive
+ *                   keying data) with 0s.
+ * @s: Pointer to the start of the area.
+ * @count: The size of the area.
+ *
+ * memzero_explicit() doesn't need an arch-specific version as
+ * it just invokes the one of memset() implicitly.
+ */
+void memzero_explicit(void *s, size_t count)
+{
+       memset(s, 0, count);
+       OPTIMIZER_HIDE_VAR(s);
+}
+EXPORT_SYMBOL(memzero_explicit);
+
 #ifndef __HAVE_ARCH_MEMCPY
 /**
  * memcpy - Copy one area of memory to another
index b3cbe19f71b5fe48ca853b55b8d5c1163bfdea03..fcad8322ef36781c5c59e92ddee26caeb4c3c5f2 100644 (file)
@@ -68,11 +68,13 @@ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
                 * to be released by the balloon driver.
                 */
                if (trylock_page(page)) {
+#ifdef CONFIG_BALLOON_COMPACTION
                        if (!PagePrivate(page)) {
                                /* raced with isolation */
                                unlock_page(page);
                                continue;
                        }
+#endif
                        spin_lock_irqsave(&b_dev_info->pages_lock, flags);
                        balloon_page_delete(page);
                        __count_vm_event(BALLOON_DEFLATE);
index 8a000cebb0d7428d5ec48dcfa979086c57e85109..477be696511d669230b47c73d52a8b3c1836c457 100644 (file)
@@ -243,13 +243,10 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 
 static int reset_managed_pages_done __initdata;
 
-static inline void __init reset_node_managed_pages(pg_data_t *pgdat)
+void reset_node_managed_pages(pg_data_t *pgdat)
 {
        struct zone *z;
 
-       if (reset_managed_pages_done)
-               return;
-
        for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
                z->managed_pages = 0;
 }
@@ -258,8 +255,12 @@ void __init reset_all_zones_managed_pages(void)
 {
        struct pglist_data *pgdat;
 
+       if (reset_managed_pages_done)
+               return;
+
        for_each_online_pgdat(pgdat)
                reset_node_managed_pages(pgdat);
+
        reset_managed_pages_done = 1;
 }
 
index 963bc4add9af88838b494e6dd56b2bf2239548a2..fde706e1284fbc05edd04722fd8f0abf92d406bf 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -124,6 +124,7 @@ static int __init cma_activate_area(struct cma *cma)
 
 err:
        kfree(cma->bitmap);
+       cma->count = 0;
        return -EINVAL;
 }
 
@@ -217,9 +218,8 @@ int __init cma_declare_contiguous(phys_addr_t base,
        phys_addr_t highmem_start = __pa(high_memory);
        int ret = 0;
 
-       pr_debug("%s(size %lx, base %08lx, limit %08lx alignment %08lx)\n",
-               __func__, (unsigned long)size, (unsigned long)base,
-               (unsigned long)limit, (unsigned long)alignment);
+       pr_debug("%s(size %pa, base %pa, limit %pa alignment %pa)\n",
+               __func__, &size, &base, &limit, &alignment);
 
        if (cma_area_count == ARRAY_SIZE(cma_areas)) {
                pr_err("Not enough slots for CMA reserved regions!\n");
@@ -244,52 +244,72 @@ int __init cma_declare_contiguous(phys_addr_t base,
        size = ALIGN(size, alignment);
        limit &= ~(alignment - 1);
 
+       if (!base)
+               fixed = false;
+
        /* size should be aligned with order_per_bit */
        if (!IS_ALIGNED(size >> PAGE_SHIFT, 1 << order_per_bit))
                return -EINVAL;
 
        /*
-        * adjust limit to avoid crossing low/high memory boundary for
-        * automatically allocated regions
+        * If allocating at a fixed base the request region must not cross the
+        * low/high memory boundary.
         */
-       if (((limit == 0 || limit > memblock_end) &&
-            (memblock_end - size < highmem_start &&
-             memblock_end > highmem_start)) ||
-           (!fixed && limit > highmem_start && limit - size < highmem_start)) {
-               limit = highmem_start;
-       }
-
-       if (fixed && base < highmem_start && base+size > highmem_start) {
+       if (fixed && base < highmem_start && base + size > highmem_start) {
                ret = -EINVAL;
-               pr_err("Region at %08lx defined on low/high memory boundary (%08lx)\n",
-                       (unsigned long)base, (unsigned long)highmem_start);
+               pr_err("Region at %pa defined on low/high memory boundary (%pa)\n",
+                       &base, &highmem_start);
                goto err;
        }
 
+       /*
+        * If the limit is unspecified or above the memblock end, its effective
+        * value will be the memblock end. Set it explicitly to simplify further
+        * checks.
+        */
+       if (limit == 0 || limit > memblock_end)
+               limit = memblock_end;
+
        /* Reserve memory */
-       if (base && fixed) {
+       if (fixed) {
                if (memblock_is_region_reserved(base, size) ||
                    memblock_reserve(base, size) < 0) {
                        ret = -EBUSY;
                        goto err;
                }
        } else {
-               phys_addr_t addr = memblock_alloc_range(size, alignment, base,
-                                                       limit);
+               phys_addr_t addr = 0;
+
+               /*
+                * All pages in the reserved area must come from the same zone.
+                * If the requested region crosses the low/high memory boundary,
+                * try allocating from high memory first and fall back to low
+                * memory in case of failure.
+                */
+               if (base < highmem_start && limit > highmem_start) {
+                       addr = memblock_alloc_range(size, alignment,
+                                                   highmem_start, limit);
+                       limit = highmem_start;
+               }
+
                if (!addr) {
-                       ret = -ENOMEM;
-                       goto err;
-               } else {
-                       base = addr;
+                       addr = memblock_alloc_range(size, alignment, base,
+                                                   limit);
+                       if (!addr) {
+                               ret = -ENOMEM;
+                               goto err;
+                       }
                }
+
+               base = addr;
        }
 
        ret = cma_init_reserved_mem(base, size, order_per_bit, res_cma);
        if (ret)
                goto err;
 
-       pr_info("Reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
-               (unsigned long)base);
+       pr_info("Reserved %ld MiB at %pa\n", (unsigned long)size / SZ_1M,
+               &base);
        return 0;
 
 err:
index edba18aed1738c752793f63ae409c22ae373342a..f9792ba3537ccc830594e7954715ca66eb2e9654 100644 (file)
@@ -479,6 +479,16 @@ isolate_freepages_range(struct compact_control *cc,
 
                block_end_pfn = min(block_end_pfn, end_pfn);
 
+               /*
+                * pfn could pass the block_end_pfn if isolated freepage
+                * is more than pageblock order. In this case, we adjust
+                * scanning range to right one.
+                */
+               if (pfn >= block_end_pfn) {
+                       block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
+                       block_end_pfn = min(block_end_pfn, end_pfn);
+               }
+
                if (!pageblock_pfn_to_page(pfn, block_end_pfn, cc->zone))
                        break;
 
@@ -784,6 +794,9 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
                        cc->nr_migratepages = 0;
                        break;
                }
+
+               if (cc->nr_migratepages == COMPACT_CLUSTER_MAX)
+                       break;
        }
        acct_isolated(cc->zone, cc);
 
@@ -1026,8 +1039,12 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
        }
 
        acct_isolated(zone, cc);
-       /* Record where migration scanner will be restarted */
-       cc->migrate_pfn = low_pfn;
+       /*
+        * Record where migration scanner will be restarted. If we end up in
+        * the same pageblock as the free scanner, make the scanners fully
+        * meet so that compact_finished() terminates compaction.
+        */
+       cc->migrate_pfn = (end_pfn <= cc->free_pfn) ? low_pfn : cc->free_pfn;
 
        return cc->nr_migratepages ? ISOLATE_SUCCESS : ISOLATE_NONE;
 }
index c30eec536f03fb7148e3c7a08538f6a2c3571857..f2a3571c6e22573867cf6e4ba2d481a663a3d04e 100644 (file)
@@ -244,8 +244,10 @@ int __frontswap_store(struct page *page)
                  the (older) page from frontswap
                 */
                inc_frontswap_failed_stores();
-               if (dup)
+               if (dup) {
                        __frontswap_clear(sis, offset);
+                       frontswap_ops->invalidate_page(type, offset);
+               }
        }
        if (frontswap_writethrough_enabled)
                /* report failure so swap also writes to swap device */
index 74c78aa8bc2fa68454928b09f34a7b97f3419e05..de984159cf0b8a0be6a73b9f421e9a0b4f75c599 100644 (file)
@@ -200,7 +200,7 @@ retry:
        preempt_disable();
        if (cmpxchg(&huge_zero_page, NULL, zero_page)) {
                preempt_enable();
-               __free_page(zero_page);
+               __free_pages(zero_page, compound_order(zero_page));
                goto retry;
        }
 
@@ -232,7 +232,7 @@ static unsigned long shrink_huge_zero_page_scan(struct shrinker *shrink,
        if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) {
                struct page *zero_page = xchg(&huge_zero_page, NULL);
                BUG_ON(zero_page == NULL);
-               __free_page(zero_page);
+               __free_pages(zero_page, compound_order(zero_page));
                return HPAGE_PMD_NR;
        }
 
@@ -803,7 +803,7 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
                return VM_FAULT_FALLBACK;
        if (unlikely(anon_vma_prepare(vma)))
                return VM_FAULT_OOM;
-       if (unlikely(khugepaged_enter(vma)))
+       if (unlikely(khugepaged_enter(vma, vma->vm_flags)))
                return VM_FAULT_OOM;
        if (!(flags & FAULT_FLAG_WRITE) &&
                        transparent_hugepage_use_zero_page()) {
@@ -1970,7 +1970,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
                 * register it here without waiting a page fault that
                 * may not happen any time soon.
                 */
-               if (unlikely(khugepaged_enter_vma_merge(vma)))
+               if (unlikely(khugepaged_enter_vma_merge(vma, *vm_flags)))
                        return -ENOMEM;
                break;
        case MADV_NOHUGEPAGE:
@@ -2071,7 +2071,8 @@ int __khugepaged_enter(struct mm_struct *mm)
        return 0;
 }
 
-int khugepaged_enter_vma_merge(struct vm_area_struct *vma)
+int khugepaged_enter_vma_merge(struct vm_area_struct *vma,
+                              unsigned long vm_flags)
 {
        unsigned long hstart, hend;
        if (!vma->anon_vma)
@@ -2083,11 +2084,11 @@ int khugepaged_enter_vma_merge(struct vm_area_struct *vma)
        if (vma->vm_ops)
                /* khugepaged not yet working on file or special mappings */
                return 0;
-       VM_BUG_ON_VMA(vma->vm_flags & VM_NO_THP, vma);
+       VM_BUG_ON_VMA(vm_flags & VM_NO_THP, vma);
        hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
        hend = vma->vm_end & HPAGE_PMD_MASK;
        if (hstart < hend)
-               return khugepaged_enter(vma);
+               return khugepaged_enter(vma, vm_flags);
        return 0;
 }
 
index 829304090b90e8ff57ee3eaf5281987deccb7e55..a4f90ba7068ef0af12ccdff8b3dc7408f772b447 100644 (file)
@@ -108,6 +108,31 @@ extern pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address);
 /*
  * in mm/page_alloc.c
  */
+
+/*
+ * Locate the struct page for both the matching buddy in our
+ * pair (buddy1) and the combined O(n+1) page they form (page).
+ *
+ * 1) Any buddy B1 will have an order O twin B2 which satisfies
+ * the following equation:
+ *     B2 = B1 ^ (1 << O)
+ * For example, if the starting buddy (buddy2) is #8 its order
+ * 1 buddy is #10:
+ *     B2 = 8 ^ (1 << 1) = 8 ^ 2 = 10
+ *
+ * 2) Any buddy B will have an order O+1 parent P which
+ * satisfies the following equation:
+ *     P = B & ~(1 << O)
+ *
+ * Assumption: *_mem_map is contiguous at least up to MAX_ORDER
+ */
+static inline unsigned long
+__find_buddy_index(unsigned long page_idx, unsigned int order)
+{
+       return page_idx ^ (1 << order);
+}
+
+extern int __isolate_free_page(struct page *page, unsigned int order);
 extern void __free_pages_bootmem(struct page *page, unsigned int order);
 extern void prep_compound_page(struct page *page, unsigned long order);
 #ifdef CONFIG_MEMORY_FAILURE
index eafcf60f6b832b202a48f8a9ba66ac0d87989443..e34a3cb6aad6cb078c0801efc6891ba83f5db155 100644 (file)
@@ -911,9 +911,9 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i)
        if (i->nr_segs == 1)
                return i->count;
        else if (i->type & ITER_BVEC)
-               return min(i->count, i->iov->iov_len - i->iov_offset);
-       else
                return min(i->count, i->bvec->bv_len - i->iov_offset);
+       else
+               return min(i->count, i->iov->iov_len - i->iov_offset);
 }
 EXPORT_SYMBOL(iov_iter_single_seg_count);
 
index 23976fd885fd588a7687bf5631f98ea38f2235b4..d6ac0e33e150339cba37ecb3db98be3fecd3702a 100644 (file)
@@ -1536,12 +1536,8 @@ int mem_cgroup_swappiness(struct mem_cgroup *memcg)
  *         start move here.
  */
 
-/* for quick checking without looking up memcg */
-atomic_t memcg_moving __read_mostly;
-
 static void mem_cgroup_start_move(struct mem_cgroup *memcg)
 {
-       atomic_inc(&memcg_moving);
        atomic_inc(&memcg->moving_account);
        synchronize_rcu();
 }
@@ -1552,10 +1548,8 @@ static void mem_cgroup_end_move(struct mem_cgroup *memcg)
         * Now, mem_cgroup_clear_mc() may call this function with NULL.
         * We check NULL in callee rather than caller.
         */
-       if (memcg) {
-               atomic_dec(&memcg_moving);
+       if (memcg)
                atomic_dec(&memcg->moving_account);
-       }
 }
 
 /*
@@ -2204,41 +2198,52 @@ cleanup:
        return true;
 }
 
-/*
- * Used to update mapped file or writeback or other statistics.
+/**
+ * mem_cgroup_begin_page_stat - begin a page state statistics transaction
+ * @page: page that is going to change accounted state
+ * @locked: &memcg->move_lock slowpath was taken
+ * @flags: IRQ-state flags for &memcg->move_lock
  *
- * Notes: Race condition
+ * This function must mark the beginning of an accounted page state
+ * change to prevent double accounting when the page is concurrently
+ * being moved to another memcg:
  *
- * Charging occurs during page instantiation, while the page is
- * unmapped and locked in page migration, or while the page table is
- * locked in THP migration.  No race is possible.
+ *   memcg = mem_cgroup_begin_page_stat(page, &locked, &flags);
+ *   if (TestClearPageState(page))
+ *     mem_cgroup_update_page_stat(memcg, state, -1);
+ *   mem_cgroup_end_page_stat(memcg, locked, flags);
  *
- * Uncharge happens to pages with zero references, no race possible.
+ * The RCU lock is held throughout the transaction.  The fast path can
+ * get away without acquiring the memcg->move_lock (@locked is false)
+ * because page moving starts with an RCU grace period.
  *
- * Charge moving between groups is protected by checking mm->moving
- * account and taking the move_lock in the slowpath.
+ * The RCU lock also protects the memcg from being freed when the page
+ * state that is going to change is the only thing preventing the page
+ * from being uncharged.  E.g. end-writeback clearing PageWriteback(),
+ * which allows migration to go ahead and uncharge the page before the
+ * account transaction might be complete.
  */
-
-void __mem_cgroup_begin_update_page_stat(struct page *page,
-                               bool *locked, unsigned long *flags)
+struct mem_cgroup *mem_cgroup_begin_page_stat(struct page *page,
+                                             bool *locked,
+                                             unsigned long *flags)
 {
        struct mem_cgroup *memcg;
        struct page_cgroup *pc;
 
+       rcu_read_lock();
+
+       if (mem_cgroup_disabled())
+               return NULL;
+
        pc = lookup_page_cgroup(page);
 again:
        memcg = pc->mem_cgroup;
        if (unlikely(!memcg || !PageCgroupUsed(pc)))
-               return;
-       /*
-        * If this memory cgroup is not under account moving, we don't
-        * need to take move_lock_mem_cgroup(). Because we already hold
-        * rcu_read_lock(), any calls to move_account will be delayed until
-        * rcu_read_unlock().
-        */
-       VM_BUG_ON(!rcu_read_lock_held());
+               return NULL;
+
+       *locked = false;
        if (atomic_read(&memcg->moving_account) <= 0)
-               return;
+               return memcg;
 
        move_lock_mem_cgroup(memcg, flags);
        if (memcg != pc->mem_cgroup || !PageCgroupUsed(pc)) {
@@ -2246,36 +2251,40 @@ again:
                goto again;
        }
        *locked = true;
+
+       return memcg;
 }
 
-void __mem_cgroup_end_update_page_stat(struct page *page, unsigned long *flags)
+/**
+ * mem_cgroup_end_page_stat - finish a page state statistics transaction
+ * @memcg: the memcg that was accounted against
+ * @locked: value received from mem_cgroup_begin_page_stat()
+ * @flags: value received from mem_cgroup_begin_page_stat()
+ */
+void mem_cgroup_end_page_stat(struct mem_cgroup *memcg, bool locked,
+                             unsigned long flags)
 {
-       struct page_cgroup *pc = lookup_page_cgroup(page);
+       if (memcg && locked)
+               move_unlock_mem_cgroup(memcg, &flags);
 
-       /*
-        * It's guaranteed that pc->mem_cgroup never changes while
-        * lock is held because a routine modifies pc->mem_cgroup
-        * should take move_lock_mem_cgroup().
-        */
-       move_unlock_mem_cgroup(pc->mem_cgroup, flags);
+       rcu_read_unlock();
 }
 
-void mem_cgroup_update_page_stat(struct page *page,
+/**
+ * mem_cgroup_update_page_stat - update page state statistics
+ * @memcg: memcg to account against
+ * @idx: page state item to account
+ * @val: number of pages (positive or negative)
+ *
+ * See mem_cgroup_begin_page_stat() for locking requirements.
+ */
+void mem_cgroup_update_page_stat(struct mem_cgroup *memcg,
                                 enum mem_cgroup_stat_index idx, int val)
 {
-       struct mem_cgroup *memcg;
-       struct page_cgroup *pc = lookup_page_cgroup(page);
-       unsigned long uninitialized_var(flags);
-
-       if (mem_cgroup_disabled())
-               return;
-
        VM_BUG_ON(!rcu_read_lock_held());
-       memcg = pc->mem_cgroup;
-       if (unlikely(!memcg || !PageCgroupUsed(pc)))
-               return;
 
-       this_cpu_add(memcg->stat->count[idx], val);
+       if (memcg)
+               this_cpu_add(memcg->stat->count[idx], val);
 }
 
 /*
index 1cc6bfbd872ee17122b6e85859662696f595a363..0b3f6c71620db29506328e1085083081f64e7895 100644 (file)
@@ -220,9 +220,6 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long
        /* Is it from 0 to ~0? */
        tlb->fullmm     = !(start | (end+1));
        tlb->need_flush_all = 0;
-       tlb->start      = start;
-       tlb->end        = end;
-       tlb->need_flush = 0;
        tlb->local.next = NULL;
        tlb->local.nr   = 0;
        tlb->local.max  = ARRAY_SIZE(tlb->__pages);
@@ -232,15 +229,20 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb->batch = NULL;
 #endif
+
+       __tlb_reset_range(tlb);
 }
 
 static void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
 {
-       tlb->need_flush = 0;
+       if (!tlb->end)
+               return;
+
        tlb_flush(tlb);
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb_table_flush(tlb);
 #endif
+       __tlb_reset_range(tlb);
 }
 
 static void tlb_flush_mmu_free(struct mmu_gather *tlb)
@@ -256,8 +258,6 @@ static void tlb_flush_mmu_free(struct mmu_gather *tlb)
 
 void tlb_flush_mmu(struct mmu_gather *tlb)
 {
-       if (!tlb->need_flush)
-               return;
        tlb_flush_mmu_tlbonly(tlb);
        tlb_flush_mmu_free(tlb);
 }
@@ -292,7 +292,7 @@ int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
        struct mmu_gather_batch *batch;
 
-       VM_BUG_ON(!tlb->need_flush);
+       VM_BUG_ON(!tlb->end);
 
        batch = tlb->active;
        batch->pages[batch->nr++] = page;
@@ -359,8 +359,6 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
 {
        struct mmu_table_batch **batch = &tlb->batch;
 
-       tlb->need_flush = 1;
-
        /*
         * When there's less then two users of this mm there cannot be a
         * concurrent page-table walk.
@@ -815,20 +813,20 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                if (!pte_file(pte)) {
                        swp_entry_t entry = pte_to_swp_entry(pte);
 
-                       if (swap_duplicate(entry) < 0)
-                               return entry.val;
-
-                       /* make sure dst_mm is on swapoff's mmlist. */
-                       if (unlikely(list_empty(&dst_mm->mmlist))) {
-                               spin_lock(&mmlist_lock);
-                               if (list_empty(&dst_mm->mmlist))
-                                       list_add(&dst_mm->mmlist,
-                                                &src_mm->mmlist);
-                               spin_unlock(&mmlist_lock);
-                       }
-                       if (likely(!non_swap_entry(entry)))
+                       if (likely(!non_swap_entry(entry))) {
+                               if (swap_duplicate(entry) < 0)
+                                       return entry.val;
+
+                               /* make sure dst_mm is on swapoff's mmlist. */
+                               if (unlikely(list_empty(&dst_mm->mmlist))) {
+                                       spin_lock(&mmlist_lock);
+                                       if (list_empty(&dst_mm->mmlist))
+                                               list_add(&dst_mm->mmlist,
+                                                        &src_mm->mmlist);
+                                       spin_unlock(&mmlist_lock);
+                               }
                                rss[MM_SWAPENTS]++;
-                       else if (is_migration_entry(entry)) {
+                       else if (is_migration_entry(entry)) {
                                page = migration_entry_to_page(entry);
 
                                if (PageAnon(page))
@@ -1147,6 +1145,7 @@ again:
                                print_bad_pte(vma, addr, ptent, page);
                        if (unlikely(!__tlb_remove_page(tlb, page))) {
                                force_flush = 1;
+                               addr += PAGE_SIZE;
                                break;
                        }
                        continue;
@@ -1185,20 +1184,8 @@ again:
        arch_leave_lazy_mmu_mode();
 
        /* Do the actual TLB flush before dropping ptl */
-       if (force_flush) {
-               unsigned long old_end;
-
-               /*
-                * Flush the TLB just for the previous segment,
-                * then update the range to be the remaining
-                * TLB range.
-                */
-               old_end = tlb->end;
-               tlb->end = addr;
+       if (force_flush)
                tlb_flush_mmu_tlbonly(tlb);
-               tlb->start = addr;
-               tlb->end = old_end;
-       }
        pte_unmap_unlock(start_pte, ptl);
 
        /*
index 29d8693d0c61cf663ee45551aaecff29ff7237cf..1bf4807cb21e49ccbd1bb4232574507e8d41384c 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/stop_machine.h>
 #include <linux/hugetlb.h>
 #include <linux/memblock.h>
+#include <linux/bootmem.h>
 
 #include <asm/tlbflush.h>
 
@@ -1066,6 +1067,16 @@ out:
 }
 #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
 
+static void reset_node_present_pages(pg_data_t *pgdat)
+{
+       struct zone *z;
+
+       for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
+               z->present_pages = 0;
+
+       pgdat->node_present_pages = 0;
+}
+
 /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
 static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
 {
@@ -1096,6 +1107,21 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
        build_all_zonelists(pgdat, NULL);
        mutex_unlock(&zonelists_mutex);
 
+       /*
+        * zone->managed_pages is set to an approximate value in
+        * free_area_init_core(), which will cause
+        * /sys/device/system/node/nodeX/meminfo has wrong data.
+        * So reset it to 0 before any memory is onlined.
+        */
+       reset_node_managed_pages(pgdat);
+
+       /*
+        * When memory is hot-added, all the memory is in offline state. So
+        * clear all zones' present_pages because they will be updated in
+        * online_pages() and offline_pages().
+        */
+       reset_node_present_pages(pgdat);
+
        return pgdat;
 }
 
@@ -1912,7 +1938,6 @@ void try_offline_node(int nid)
        unsigned long start_pfn = pgdat->node_start_pfn;
        unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages;
        unsigned long pfn;
-       struct page *pgdat_page = virt_to_page(pgdat);
        int i;
 
        for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
@@ -1941,10 +1966,6 @@ void try_offline_node(int nid)
        node_set_offline(nid);
        unregister_one_node(nid);
 
-       if (!PageSlab(pgdat_page) && !PageCompound(pgdat_page))
-               /* node data is allocated from boot memory */
-               return;
-
        /* free waittable in each zone */
        for (i = 0; i < MAX_NR_ZONES; i++) {
                struct zone *zone = pgdat->node_zones + i;
index 7f855206e7fb2bb1f9a30fcf7745bff7a2ae3adb..ae919891a087e0d7f3a76c5b47f4f1d8326f6dfa 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -776,8 +776,11 @@ again:                     remove_next = 1 + (end > next->vm_end);
                 * shrinking vma had, to cover any anon pages imported.
                 */
                if (exporter && exporter->anon_vma && !importer->anon_vma) {
-                       if (anon_vma_clone(importer, exporter))
-                               return -ENOMEM;
+                       int error;
+
+                       error = anon_vma_clone(importer, exporter);
+                       if (error)
+                               return error;
                        importer->anon_vma = exporter->anon_vma;
                }
        }
@@ -1080,7 +1083,7 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
                                end, prev->vm_pgoff, NULL);
                if (err)
                        return NULL;
-               khugepaged_enter_vma_merge(prev);
+               khugepaged_enter_vma_merge(prev, vm_flags);
                return prev;
        }
 
@@ -1099,7 +1102,7 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
                                next->vm_pgoff - pglen, NULL);
                if (err)
                        return NULL;
-               khugepaged_enter_vma_merge(area);
+               khugepaged_enter_vma_merge(area, vm_flags);
                return area;
        }
 
@@ -2208,7 +2211,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
                }
        }
        vma_unlock_anon_vma(vma);
-       khugepaged_enter_vma_merge(vma);
+       khugepaged_enter_vma_merge(vma, vma->vm_flags);
        validate_mm(vma->vm_mm);
        return error;
 }
@@ -2277,7 +2280,7 @@ int expand_downwards(struct vm_area_struct *vma,
                }
        }
        vma_unlock_anon_vma(vma);
-       khugepaged_enter_vma_merge(vma);
+       khugepaged_enter_vma_merge(vma, vma->vm_flags);
        validate_mm(vma->vm_mm);
        return error;
 }
@@ -2469,7 +2472,8 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
        if (err)
                goto out_free_vma;
 
-       if (anon_vma_clone(new, vma))
+       err = anon_vma_clone(new, vma);
+       if (err)
                goto out_free_mpol;
 
        if (new->vm_file)
index 7c7ab32ee5032dad07354f438b5832649aaa044b..90b50468333e38563d4388096e584b6c23fa9132 100644 (file)
@@ -145,12 +145,10 @@ static unsigned long __init free_low_memory_core_early(void)
 
 static int reset_managed_pages_done __initdata;
 
-static inline void __init reset_node_managed_pages(pg_data_t *pgdat)
+void reset_node_managed_pages(pg_data_t *pgdat)
 {
        struct zone *z;
 
-       if (reset_managed_pages_done)
-               return;
        for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
                z->managed_pages = 0;
 }
@@ -159,8 +157,12 @@ void __init reset_all_zones_managed_pages(void)
 {
        struct pglist_data *pgdat;
 
+       if (reset_managed_pages_done)
+               return;
+
        for_each_online_pgdat(pgdat)
                reset_node_managed_pages(pgdat);
+
        reset_managed_pages_done = 1;
 }
 
index bbf405a3a18f5acd8fbe57fabc06c3e5ce973e29..5340f6b91312dee4bd18dd42efc7c9541ce5ed58 100644 (file)
@@ -404,6 +404,23 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
                dump_tasks(memcg, nodemask);
 }
 
+/*
+ * Number of OOM killer invocations (including memcg OOM killer).
+ * Primarily used by PM freezer to check for potential races with
+ * OOM killed frozen task.
+ */
+static atomic_t oom_kills = ATOMIC_INIT(0);
+
+int oom_kills_count(void)
+{
+       return atomic_read(&oom_kills);
+}
+
+void note_oom_kill(void)
+{
+       atomic_inc(&oom_kills);
+}
+
 #define K(x) ((x) << (PAGE_SHIFT-10))
 /*
  * Must be called while holding a reference to p, which will be released upon
index ff24c9d83112ece05dab0d3b5c941a92252deef0..19ceae87522d9a87ea23457e4ae9eec50882b194 100644 (file)
@@ -2115,23 +2115,6 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
 }
 EXPORT_SYMBOL(account_page_dirtied);
 
-/*
- * Helper function for set_page_writeback family.
- *
- * The caller must hold mem_cgroup_begin/end_update_page_stat() lock
- * while calling this function.
- * See test_set_page_writeback for example.
- *
- * NOTE: Unlike account_page_dirtied this does not rely on being atomic
- * wrt interrupts.
- */
-void account_page_writeback(struct page *page)
-{
-       mem_cgroup_inc_page_stat(page, MEM_CGROUP_STAT_WRITEBACK);
-       inc_zone_page_state(page, NR_WRITEBACK);
-}
-EXPORT_SYMBOL(account_page_writeback);
-
 /*
  * For address_spaces which do not use buffers.  Just tag the page as dirty in
  * its radix tree.
@@ -2344,11 +2327,12 @@ EXPORT_SYMBOL(clear_page_dirty_for_io);
 int test_clear_page_writeback(struct page *page)
 {
        struct address_space *mapping = page_mapping(page);
-       int ret;
-       bool locked;
        unsigned long memcg_flags;
+       struct mem_cgroup *memcg;
+       bool locked;
+       int ret;
 
-       mem_cgroup_begin_update_page_stat(page, &locked, &memcg_flags);
+       memcg = mem_cgroup_begin_page_stat(page, &locked, &memcg_flags);
        if (mapping) {
                struct backing_dev_info *bdi = mapping->backing_dev_info;
                unsigned long flags;
@@ -2369,22 +2353,23 @@ int test_clear_page_writeback(struct page *page)
                ret = TestClearPageWriteback(page);
        }
        if (ret) {
-               mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_WRITEBACK);
+               mem_cgroup_dec_page_stat(memcg, MEM_CGROUP_STAT_WRITEBACK);
                dec_zone_page_state(page, NR_WRITEBACK);
                inc_zone_page_state(page, NR_WRITTEN);
        }
-       mem_cgroup_end_update_page_stat(page, &locked, &memcg_flags);
+       mem_cgroup_end_page_stat(memcg, locked, memcg_flags);
        return ret;
 }
 
 int __test_set_page_writeback(struct page *page, bool keep_write)
 {
        struct address_space *mapping = page_mapping(page);
-       int ret;
-       bool locked;
        unsigned long memcg_flags;
+       struct mem_cgroup *memcg;
+       bool locked;
+       int ret;
 
-       mem_cgroup_begin_update_page_stat(page, &locked, &memcg_flags);
+       memcg = mem_cgroup_begin_page_stat(page, &locked, &memcg_flags);
        if (mapping) {
                struct backing_dev_info *bdi = mapping->backing_dev_info;
                unsigned long flags;
@@ -2410,9 +2395,11 @@ int __test_set_page_writeback(struct page *page, bool keep_write)
        } else {
                ret = TestSetPageWriteback(page);
        }
-       if (!ret)
-               account_page_writeback(page);
-       mem_cgroup_end_update_page_stat(page, &locked, &memcg_flags);
+       if (!ret) {
+               mem_cgroup_inc_page_stat(memcg, MEM_CGROUP_STAT_WRITEBACK);
+               inc_zone_page_state(page, NR_WRITEBACK);
+       }
+       mem_cgroup_end_page_stat(memcg, locked, memcg_flags);
        return ret;
 
 }
index 736d8e1b63817fcd8c715f2081a4f44ba43c9be9..616a2c956b4b2a6aee5cc1f7d0098cf4a4cd5912 100644 (file)
@@ -466,29 +466,6 @@ static inline void rmv_page_order(struct page *page)
        set_page_private(page, 0);
 }
 
-/*
- * Locate the struct page for both the matching buddy in our
- * pair (buddy1) and the combined O(n+1) page they form (page).
- *
- * 1) Any buddy B1 will have an order O twin B2 which satisfies
- * the following equation:
- *     B2 = B1 ^ (1 << O)
- * For example, if the starting buddy (buddy2) is #8 its order
- * 1 buddy is #10:
- *     B2 = 8 ^ (1 << 1) = 8 ^ 2 = 10
- *
- * 2) Any buddy B will have an order O+1 parent P which
- * satisfies the following equation:
- *     P = B & ~(1 << O)
- *
- * Assumption: *_mem_map is contiguous at least up to MAX_ORDER
- */
-static inline unsigned long
-__find_buddy_index(unsigned long page_idx, unsigned int order)
-{
-       return page_idx ^ (1 << order);
-}
-
 /*
  * This function checks whether a page is free && is the buddy
  * we can do coalesce a page and its buddy if
@@ -569,6 +546,7 @@ static inline void __free_one_page(struct page *page,
        unsigned long combined_idx;
        unsigned long uninitialized_var(buddy_idx);
        struct page *buddy;
+       int max_order = MAX_ORDER;
 
        VM_BUG_ON(!zone_is_initialized(zone));
 
@@ -577,13 +555,24 @@ static inline void __free_one_page(struct page *page,
                        return;
 
        VM_BUG_ON(migratetype == -1);
+       if (is_migrate_isolate(migratetype)) {
+               /*
+                * We restrict max order of merging to prevent merge
+                * between freepages on isolate pageblock and normal
+                * pageblock. Without this, pageblock isolation
+                * could cause incorrect freepage accounting.
+                */
+               max_order = min(MAX_ORDER, pageblock_order + 1);
+       } else {
+               __mod_zone_freepage_state(zone, 1 << order, migratetype);
+       }
 
-       page_idx = pfn & ((1 << MAX_ORDER) - 1);
+       page_idx = pfn & ((1 << max_order) - 1);
 
        VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page);
        VM_BUG_ON_PAGE(bad_range(zone, page), page);
 
-       while (order < MAX_ORDER-1) {
+       while (order < max_order - 1) {
                buddy_idx = __find_buddy_index(page_idx, order);
                buddy = page + (buddy_idx - page_idx);
                if (!page_is_buddy(page, buddy, order))
@@ -594,9 +583,11 @@ static inline void __free_one_page(struct page *page,
                 */
                if (page_is_guard(buddy)) {
                        clear_page_guard_flag(buddy);
-                       set_page_private(page, 0);
-                       __mod_zone_freepage_state(zone, 1 << order,
-                                                 migratetype);
+                       set_page_private(buddy, 0);
+                       if (!is_migrate_isolate(migratetype)) {
+                               __mod_zone_freepage_state(zone, 1 << order,
+                                                         migratetype);
+                       }
                } else {
                        list_del(&buddy->lru);
                        zone->free_area[order].nr_free--;
@@ -715,14 +706,12 @@ static void free_pcppages_bulk(struct zone *zone, int count,
                        /* must delete as __free_one_page list manipulates */
                        list_del(&page->lru);
                        mt = get_freepage_migratetype(page);
+                       if (unlikely(has_isolate_pageblock(zone)))
+                               mt = get_pageblock_migratetype(page);
+
                        /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
                        __free_one_page(page, page_to_pfn(page), zone, 0, mt);
                        trace_mm_page_pcpu_drain(page, 0, mt);
-                       if (likely(!is_migrate_isolate_page(page))) {
-                               __mod_zone_page_state(zone, NR_FREE_PAGES, 1);
-                               if (is_migrate_cma(mt))
-                                       __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, 1);
-                       }
                } while (--to_free && --batch_free && !list_empty(list));
        }
        spin_unlock(&zone->lock);
@@ -739,9 +728,11 @@ static void free_one_page(struct zone *zone,
        if (nr_scanned)
                __mod_zone_page_state(zone, NR_PAGES_SCANNED, -nr_scanned);
 
+       if (unlikely(has_isolate_pageblock(zone) ||
+               is_migrate_isolate(migratetype))) {
+               migratetype = get_pfnblock_migratetype(page, pfn);
+       }
        __free_one_page(page, pfn, zone, order, migratetype);
-       if (unlikely(!is_migrate_isolate(migratetype)))
-               __mod_zone_freepage_state(zone, 1 << order, migratetype);
        spin_unlock(&zone->lock);
 }
 
@@ -1484,7 +1475,7 @@ void split_page(struct page *page, unsigned int order)
 }
 EXPORT_SYMBOL_GPL(split_page);
 
-static int __isolate_free_page(struct page *page, unsigned int order)
+int __isolate_free_page(struct page *page, unsigned int order)
 {
        unsigned long watermark;
        struct zone *zone;
@@ -2251,6 +2242,14 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
                return NULL;
        }
 
+       /*
+        * PM-freezer should be notified that there might be an OOM killer on
+        * its way to kill and wake somebody up. This is too early and we might
+        * end up not killing anything but false positives are acceptable.
+        * See freeze_processes.
+        */
+       note_oom_kill();
+
        /*
         * Go through the zonelist yet one more time, keep very high watermark
         * here, this is only to catch a parallel oom killing, we must fail if
@@ -6400,13 +6399,12 @@ int alloc_contig_range(unsigned long start, unsigned long end,
 
        /* Make sure the range is really isolated. */
        if (test_pages_isolated(outer_start, end, false)) {
-               pr_warn("alloc_contig_range test_pages_isolated(%lx, %lx) failed\n",
-                      outer_start, end);
+               pr_info("%s: [%lx, %lx) PFNs busy\n",
+                       __func__, outer_start, end);
                ret = -EBUSY;
                goto done;
        }
 
-
        /* Grab isolated pages from freelists. */
        outer_end = isolate_freepages_range(&cc, outer_start, end);
        if (!outer_end) {
index 3708264d28332d4a8ec17bd929110a5b212f5529..5331c2bd85a2cc5c838881cdd12870ad9502029d 100644 (file)
@@ -171,6 +171,7 @@ static void free_page_cgroup(void *addr)
                        sizeof(struct page_cgroup) * PAGES_PER_SECTION;
 
                BUG_ON(PageReserved(page));
+               kmemleak_free(addr);
                free_pages_exact(addr, table_size);
        }
 }
index d1473b2e9481731988695755a618baa0991556a7..c8778f7e208e8a4a640e2c12f091956f4aa33575 100644 (file)
@@ -60,6 +60,7 @@ out:
                int migratetype = get_pageblock_migratetype(page);
 
                set_pageblock_migratetype(page, MIGRATE_ISOLATE);
+               zone->nr_isolate_pageblock++;
                nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE);
 
                __mod_zone_freepage_state(zone, -nr_pages, migratetype);
@@ -75,16 +76,54 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
 {
        struct zone *zone;
        unsigned long flags, nr_pages;
+       struct page *isolated_page = NULL;
+       unsigned int order;
+       unsigned long page_idx, buddy_idx;
+       struct page *buddy;
 
        zone = page_zone(page);
        spin_lock_irqsave(&zone->lock, flags);
        if (get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
                goto out;
-       nr_pages = move_freepages_block(zone, page, migratetype);
-       __mod_zone_freepage_state(zone, nr_pages, migratetype);
+
+       /*
+        * Because freepage with more than pageblock_order on isolated
+        * pageblock is restricted to merge due to freepage counting problem,
+        * it is possible that there is free buddy page.
+        * move_freepages_block() doesn't care of merge so we need other
+        * approach in order to merge them. Isolation and free will make
+        * these pages to be merged.
+        */
+       if (PageBuddy(page)) {
+               order = page_order(page);
+               if (order >= pageblock_order) {
+                       page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1);
+                       buddy_idx = __find_buddy_index(page_idx, order);
+                       buddy = page + (buddy_idx - page_idx);
+
+                       if (!is_migrate_isolate_page(buddy)) {
+                               __isolate_free_page(page, order);
+                               set_page_refcounted(page);
+                               isolated_page = page;
+                       }
+               }
+       }
+
+       /*
+        * If we isolate freepage with more than pageblock_order, there
+        * should be no freepage in the range, so we could avoid costly
+        * pageblock scanning for freepage moving.
+        */
+       if (!isolated_page) {
+               nr_pages = move_freepages_block(zone, page, migratetype);
+               __mod_zone_freepage_state(zone, nr_pages, migratetype);
+       }
        set_pageblock_migratetype(page, migratetype);
+       zone->nr_isolate_pageblock--;
 out:
        spin_unlock_irqrestore(&zone->lock, flags);
+       if (isolated_page)
+               __free_pages(isolated_page, order);
 }
 
 static inline struct page *
index 116a5053415b8dbc41c39622316e6b8b417a3727..3e4c7213210c6f22a0da6f88c13689a9c99b92f1 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -274,6 +274,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
 {
        struct anon_vma_chain *avc;
        struct anon_vma *anon_vma;
+       int error;
 
        /* Don't bother if the parent process has no anon_vma here. */
        if (!pvma->anon_vma)
@@ -283,8 +284,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
         * First, attach the new VMA to the parent VMA's anon_vmas,
         * so rmap can find non-COWed pages in child processes.
         */
-       if (anon_vma_clone(vma, pvma))
-               return -ENOMEM;
+       error = anon_vma_clone(vma, pvma);
+       if (error)
+               return error;
 
        /* Then add our own anon_vma. */
        anon_vma = anon_vma_alloc();
@@ -1042,15 +1044,46 @@ void page_add_new_anon_rmap(struct page *page,
  */
 void page_add_file_rmap(struct page *page)
 {
-       bool locked;
+       struct mem_cgroup *memcg;
        unsigned long flags;
+       bool locked;
 
-       mem_cgroup_begin_update_page_stat(page, &locked, &flags);
+       memcg = mem_cgroup_begin_page_stat(page, &locked, &flags);
        if (atomic_inc_and_test(&page->_mapcount)) {
                __inc_zone_page_state(page, NR_FILE_MAPPED);
-               mem_cgroup_inc_page_stat(page, MEM_CGROUP_STAT_FILE_MAPPED);
+               mem_cgroup_inc_page_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED);
        }
-       mem_cgroup_end_update_page_stat(page, &locked, &flags);
+       mem_cgroup_end_page_stat(memcg, locked, flags);
+}
+
+static void page_remove_file_rmap(struct page *page)
+{
+       struct mem_cgroup *memcg;
+       unsigned long flags;
+       bool locked;
+
+       memcg = mem_cgroup_begin_page_stat(page, &locked, &flags);
+
+       /* page still mapped by someone else? */
+       if (!atomic_add_negative(-1, &page->_mapcount))
+               goto out;
+
+       /* Hugepages are not counted in NR_FILE_MAPPED for now. */
+       if (unlikely(PageHuge(page)))
+               goto out;
+
+       /*
+        * We use the irq-unsafe __{inc|mod}_zone_page_stat because
+        * these counters are not modified in interrupt context, and
+        * pte lock(a spinlock) is held, which implies preemption disabled.
+        */
+       __dec_zone_page_state(page, NR_FILE_MAPPED);
+       mem_cgroup_dec_page_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED);
+
+       if (unlikely(PageMlocked(page)))
+               clear_page_mlock(page);
+out:
+       mem_cgroup_end_page_stat(memcg, locked, flags);
 }
 
 /**
@@ -1061,46 +1094,33 @@ void page_add_file_rmap(struct page *page)
  */
 void page_remove_rmap(struct page *page)
 {
-       bool anon = PageAnon(page);
-       bool locked;
-       unsigned long flags;
-
-       /*
-        * The anon case has no mem_cgroup page_stat to update; but may
-        * uncharge_page() below, where the lock ordering can deadlock if
-        * we hold the lock against page_stat move: so avoid it on anon.
-        */
-       if (!anon)
-               mem_cgroup_begin_update_page_stat(page, &locked, &flags);
+       if (!PageAnon(page)) {
+               page_remove_file_rmap(page);
+               return;
+       }
 
        /* page still mapped by someone else? */
        if (!atomic_add_negative(-1, &page->_mapcount))
-               goto out;
+               return;
+
+       /* Hugepages are not counted in NR_ANON_PAGES for now. */
+       if (unlikely(PageHuge(page)))
+               return;
 
        /*
-        * Hugepages are not counted in NR_ANON_PAGES nor NR_FILE_MAPPED
-        * and not charged by memcg for now.
-        *
         * We use the irq-unsafe __{inc|mod}_zone_page_stat because
         * these counters are not modified in interrupt context, and
-        * these counters are not modified in interrupt context, and
         * pte lock(a spinlock) is held, which implies preemption disabled.
         */
-       if (unlikely(PageHuge(page)))
-               goto out;
-       if (anon) {
-               if (PageTransHuge(page))
-                       __dec_zone_page_state(page,
-                                             NR_ANON_TRANSPARENT_HUGEPAGES);
-               __mod_zone_page_state(page_zone(page), NR_ANON_PAGES,
-                               -hpage_nr_pages(page));
-       } else {
-               __dec_zone_page_state(page, NR_FILE_MAPPED);
-               mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_FILE_MAPPED);
-               mem_cgroup_end_update_page_stat(page, &locked, &flags);
-       }
+       if (PageTransHuge(page))
+               __dec_zone_page_state(page, NR_ANON_TRANSPARENT_HUGEPAGES);
+
+       __mod_zone_page_state(page_zone(page), NR_ANON_PAGES,
+                             -hpage_nr_pages(page));
+
        if (unlikely(PageMlocked(page)))
                clear_page_mlock(page);
+
        /*
         * It would be tidy to reset the PageAnon mapping here,
         * but that might overwrite a racing page_add_anon_rmap
@@ -1110,10 +1130,6 @@ void page_remove_rmap(struct page *page)
         * Leaving it set also helps swapoff to reinstate ptes
         * faster for those pages still in swapcache.
         */
-       return;
-out:
-       if (!anon)
-               mem_cgroup_end_update_page_stat(page, &locked, &flags);
 }
 
 /*
index cd6fc7590e54f758adacdcfc9cdcb402c7cd3005..185836ba53ef6e23a63b6a0de7c22ebae19eac0b 100644 (file)
@@ -2345,6 +2345,32 @@ static int shmem_exchange(struct inode *old_dir, struct dentry *old_dentry, stru
        return 0;
 }
 
+static int shmem_whiteout(struct inode *old_dir, struct dentry *old_dentry)
+{
+       struct dentry *whiteout;
+       int error;
+
+       whiteout = d_alloc(old_dentry->d_parent, &old_dentry->d_name);
+       if (!whiteout)
+               return -ENOMEM;
+
+       error = shmem_mknod(old_dir, whiteout,
+                           S_IFCHR | WHITEOUT_MODE, WHITEOUT_DEV);
+       dput(whiteout);
+       if (error)
+               return error;
+
+       /*
+        * Cheat and hash the whiteout while the old dentry is still in
+        * place, instead of playing games with FS_RENAME_DOES_D_MOVE.
+        *
+        * d_lookup() will consistently find one of them at this point,
+        * not sure which one, but that isn't even important.
+        */
+       d_rehash(whiteout);
+       return 0;
+}
+
 /*
  * The VFS layer already does all the dentry stuff for rename,
  * we just have to decrement the usage count for the target if
@@ -2356,7 +2382,7 @@ static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struc
        struct inode *inode = old_dentry->d_inode;
        int they_are_dirs = S_ISDIR(inode->i_mode);
 
-       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
                return -EINVAL;
 
        if (flags & RENAME_EXCHANGE)
@@ -2365,6 +2391,14 @@ static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struc
        if (!simple_empty(new_dentry))
                return -ENOTEMPTY;
 
+       if (flags & RENAME_WHITEOUT) {
+               int error;
+
+               error = shmem_whiteout(old_dir, old_dentry);
+               if (error)
+                       return error;
+       }
+
        if (new_dentry->d_inode) {
                (void) shmem_unlink(new_dir, new_dentry);
                if (they_are_dirs) {
index eb2b2ea301309887972c148bb80aedf8a6731b9b..f34e053ec46e24bb364a847ac498ef61b5011b27 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3076,7 +3076,7 @@ static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
        void *obj;
        int x;
 
-       VM_BUG_ON(nodeid > num_online_nodes());
+       VM_BUG_ON(nodeid < 0 || nodeid >= MAX_NUMNODES);
        n = get_node(cachep, nodeid);
        BUG_ON(!n);
 
index 3a6e0cfdf03add7f19f4dc9ebdf7cc8bf6fad695..dcdab81bd240bafe3bec02cb32bf3390763a90e9 100644 (file)
@@ -93,16 +93,6 @@ static int kmem_cache_sanity_check(const char *name, size_t size)
                               s->object_size);
                        continue;
                }
-
-#if !defined(CONFIG_SLUB)
-               if (!strcmp(s->name, name)) {
-                       pr_err("%s (%s): Cache name already exists.\n",
-                              __func__, name);
-                       dump_stack();
-                       s = NULL;
-                       return -EINVAL;
-               }
-#endif
        }
 
        WARN_ON(strchr(name, ' '));     /* It confuses parsers */
@@ -269,6 +259,10 @@ struct kmem_cache *find_mergeable(size_t size, size_t align,
                if (s->size - size >= sizeof(void *))
                        continue;
 
+               if (IS_ENABLED(CONFIG_SLAB) && align &&
+                       (align > s->align || s->align % align))
+                       continue;
+
                return s;
        }
        return NULL;
index 96d167372d89405372ef7cd544799e76fd99a886..f1e4d60523694eb758b93fcd6487866c203956dd 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/buffer_head.h> /* grr. try_to_release_page,
                                   do_invalidatepage */
 #include <linux/cleancache.h>
+#include <linux/rmap.h>
 #include "internal.h"
 
 static void clear_exceptional_entry(struct address_space *mapping,
@@ -714,16 +715,72 @@ EXPORT_SYMBOL(truncate_pagecache);
  * necessary) to @newsize. It will be typically be called from the filesystem's
  * setattr function when ATTR_SIZE is passed in.
  *
- * Must be called with inode_mutex held and before all filesystem specific
- * block truncation has been performed.
+ * Must be called with a lock serializing truncates and writes (generally
+ * i_mutex but e.g. xfs uses a different lock) and before all filesystem
+ * specific block truncation has been performed.
  */
 void truncate_setsize(struct inode *inode, loff_t newsize)
 {
+       loff_t oldsize = inode->i_size;
+
        i_size_write(inode, newsize);
+       if (newsize > oldsize)
+               pagecache_isize_extended(inode, oldsize, newsize);
        truncate_pagecache(inode, newsize);
 }
 EXPORT_SYMBOL(truncate_setsize);
 
+/**
+ * pagecache_isize_extended - update pagecache after extension of i_size
+ * @inode:     inode for which i_size was extended
+ * @from:      original inode size
+ * @to:                new inode size
+ *
+ * Handle extension of inode size either caused by extending truncate or by
+ * write starting after current i_size. We mark the page straddling current
+ * i_size RO so that page_mkwrite() is called on the nearest write access to
+ * the page.  This way filesystem can be sure that page_mkwrite() is called on
+ * the page before user writes to the page via mmap after the i_size has been
+ * changed.
+ *
+ * The function must be called after i_size is updated so that page fault
+ * coming after we unlock the page will already see the new i_size.
+ * The function must be called while we still hold i_mutex - this not only
+ * makes sure i_size is stable but also that userspace cannot observe new
+ * i_size value before we are prepared to store mmap writes at new inode size.
+ */
+void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to)
+{
+       int bsize = 1 << inode->i_blkbits;
+       loff_t rounded_from;
+       struct page *page;
+       pgoff_t index;
+
+       WARN_ON(to > inode->i_size);
+
+       if (from >= to || bsize == PAGE_CACHE_SIZE)
+               return;
+       /* Page straddling @from will not have any hole block created? */
+       rounded_from = round_up(from, bsize);
+       if (to <= rounded_from || !(rounded_from & (PAGE_CACHE_SIZE - 1)))
+               return;
+
+       index = from >> PAGE_CACHE_SHIFT;
+       page = find_lock_page(inode->i_mapping, index);
+       /* Page not cached? Nothing to do */
+       if (!page)
+               return;
+       /*
+        * See clear_page_dirty_for_io() for details why set_page_dirty()
+        * is needed.
+        */
+       if (page_mkclean(page))
+               set_page_dirty(page);
+       unlock_page(page);
+       page_cache_release(page);
+}
+EXPORT_SYMBOL(pagecache_isize_extended);
+
 /**
  * truncate_pagecache_range - unmap and remove pagecache that is hole-punched
  * @inode: inode
index d4042e75f7c7e7c7d498c4fcc33c90f1d1de2bff..c5afd573d7da79afc814225043319cc66120addf 100644 (file)
@@ -165,6 +165,7 @@ static void vmpressure_work_fn(struct work_struct *work)
        unsigned long scanned;
        unsigned long reclaimed;
 
+       spin_lock(&vmpr->sr_lock);
        /*
         * Several contexts might be calling vmpressure(), so it is
         * possible that the work was rescheduled again before the old
@@ -173,11 +174,12 @@ static void vmpressure_work_fn(struct work_struct *work)
         * here. No need for any locks here since we don't care if
         * vmpr->reclaimed is in sync.
         */
-       if (!vmpr->scanned)
+       scanned = vmpr->scanned;
+       if (!scanned) {
+               spin_unlock(&vmpr->sr_lock);
                return;
+       }
 
-       spin_lock(&vmpr->sr_lock);
-       scanned = vmpr->scanned;
        reclaimed = vmpr->reclaimed;
        vmpr->scanned = 0;
        vmpr->reclaimed = 0;
index 6272420a721b0f01e15ffc572251a8f0794d5d8f..99815b5454bf4d68fdc36153951e434f7219b4d0 100644 (file)
@@ -6,7 +6,7 @@ menuconfig NET
        bool "Networking support"
        select NLATTR
        select GENERIC_NET_UTILS
-       select ANON_INODES
+       select BPF
        ---help---
          Unless you really know what you are doing, you should say Y here.
          The reason is that some programs need kernel networking support even
index af73bc3acb406a6256565a18d0ddf2611a96e07f..410dd5e76c41bff9111f6c32fbf8aff536974ddd 100644 (file)
@@ -101,11 +101,11 @@ static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s);
 #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
 #define __get_rpn_parity(line)    (((line) >> 3) & 0x7)
 
+static DECLARE_WAIT_QUEUE_HEAD(rfcomm_wq);
+
 static void rfcomm_schedule(void)
 {
-       if (!rfcomm_thread)
-               return;
-       wake_up_process(rfcomm_thread);
+       wake_up_all(&rfcomm_wq);
 }
 
 /* ---- RFCOMM FCS computation ---- */
@@ -2086,24 +2086,22 @@ static void rfcomm_kill_listener(void)
 
 static int rfcomm_run(void *unused)
 {
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
        BT_DBG("");
 
        set_user_nice(current, -10);
 
        rfcomm_add_listener(BDADDR_ANY);
 
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               if (kthread_should_stop())
-                       break;
+       add_wait_queue(&rfcomm_wq, &wait);
+       while (!kthread_should_stop()) {
 
                /* Process stuff */
                rfcomm_process_sessions();
 
-               schedule();
+               wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
        }
-       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&rfcomm_wq, &wait);
 
        rfcomm_kill_listener();
 
index 992ec49a96aa7e289bd3c74bca9a606762c63614..44cb786b925a2e857633b47b8ce3deaa22c6a5d8 100644 (file)
@@ -112,6 +112,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
 
        kfree_skb(skb);
 }
+EXPORT_SYMBOL_GPL(br_deliver);
 
 /* called with rcu_read_lock */
 void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
index 648d79ccf46244a5769c1703361cf35db4cfeb09..c465876c7861814ba545cf83783c7ba11bbd91eb 100644 (file)
@@ -813,10 +813,9 @@ static void __br_multicast_send_query(struct net_bridge *br,
                return;
 
        if (port) {
-               __skb_push(skb, sizeof(struct ethhdr));
                skb->dev = port->dev;
                NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
-                       dev_queue_xmit);
+                       br_dev_queue_push_xmit);
        } else {
                br_multicast_select_own_querier(br, ip, skb);
                netif_rx(skb);
index 1bada53bb195ca4c35950af943e049a8ddf8347a..1a4f32c09ad51707c063f6eebe14abe747ed0d26 100644 (file)
@@ -192,7 +192,6 @@ static inline void nf_bridge_save_header(struct sk_buff *skb)
 
 static int br_parse_ip_options(struct sk_buff *skb)
 {
-       struct ip_options *opt;
        const struct iphdr *iph;
        struct net_device *dev = skb->dev;
        u32 len;
@@ -201,7 +200,6 @@ static int br_parse_ip_options(struct sk_buff *skb)
                goto inhdr_error;
 
        iph = ip_hdr(skb);
-       opt = &(IPCB(skb)->opt);
 
        /* Basic sanity checks */
        if (iph->ihl < 5 || iph->version != 4)
@@ -227,23 +225,11 @@ static int br_parse_ip_options(struct sk_buff *skb)
        }
 
        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
-       if (iph->ihl == 5)
-               return 0;
-
-       opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
-       if (ip_options_compile(dev_net(dev), opt, skb))
-               goto inhdr_error;
-
-       /* Check correct handling of SRR option */
-       if (unlikely(opt->srr)) {
-               struct in_device *in_dev = __in_dev_get_rcu(dev);
-               if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev))
-                       goto drop;
-
-               if (ip_options_rcv_srr(skb))
-                       goto drop;
-       }
-
+       /* We should really parse IP options here but until
+        * somebody who actually uses IP options complains to
+        * us we'll just silently ignore the options because
+        * we're lazy!
+        */
        return 0;
 
 inhdr_error:
index 2ff9706647f2cb9f7930d22d0a3092fb3fe0d225..e5ec470b851f1f55fe37ec4ecaf557d75483af26 100644 (file)
@@ -280,6 +280,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
        [IFLA_BRPORT_MODE]      = { .type = NLA_U8 },
        [IFLA_BRPORT_GUARD]     = { .type = NLA_U8 },
        [IFLA_BRPORT_PROTECT]   = { .type = NLA_U8 },
+       [IFLA_BRPORT_FAST_LEAVE]= { .type = NLA_U8 },
        [IFLA_BRPORT_LEARNING]  = { .type = NLA_U8 },
        [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
 };
index da17a5eab8b40e5df3eeafcef74934534eb26dd1..074c557ab505eb75bd0970a3045a78f0ca5c85dd 100644 (file)
@@ -75,9 +75,11 @@ static const struct nf_chain_type filter_bridge = {
        .type           = NFT_CHAIN_T_DEFAULT,
        .family         = NFPROTO_BRIDGE,
        .owner          = THIS_MODULE,
-       .hook_mask      = (1 << NF_BR_LOCAL_IN) |
+       .hook_mask      = (1 << NF_BR_PRE_ROUTING) |
+                         (1 << NF_BR_LOCAL_IN) |
                          (1 << NF_BR_FORWARD) |
-                         (1 << NF_BR_LOCAL_OUT),
+                         (1 << NF_BR_LOCAL_OUT) |
+                         (1 << NF_BR_POST_ROUTING),
 };
 
 static int __init nf_tables_bridge_init(void)
index a76479535df2a5005968c18422d999aa897b3556..48da2c54a69e36aa1ae2f1d9e84cdb82e49a84f3 100644 (file)
 #include <net/netfilter/nft_reject.h>
 #include <net/netfilter/ipv4/nf_reject.h>
 #include <net/netfilter/ipv6/nf_reject.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/ip6_checksum.h>
+#include <linux/netfilter_bridge.h>
+#include "../br_private.h"
+
+static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb,
+                                       struct sk_buff *nskb)
+{
+       struct ethhdr *eth;
+
+       eth = (struct ethhdr *)skb_push(nskb, ETH_HLEN);
+       skb_reset_mac_header(nskb);
+       ether_addr_copy(eth->h_source, eth_hdr(oldskb)->h_dest);
+       ether_addr_copy(eth->h_dest, eth_hdr(oldskb)->h_source);
+       eth->h_proto = eth_hdr(oldskb)->h_proto;
+       skb_pull(nskb, ETH_HLEN);
+}
+
+static int nft_reject_iphdr_validate(struct sk_buff *oldskb)
+{
+       struct iphdr *iph;
+       u32 len;
+
+       if (!pskb_may_pull(oldskb, sizeof(struct iphdr)))
+               return 0;
+
+       iph = ip_hdr(oldskb);
+       if (iph->ihl < 5 || iph->version != 4)
+               return 0;
+
+       len = ntohs(iph->tot_len);
+       if (oldskb->len < len)
+               return 0;
+       else if (len < (iph->ihl*4))
+               return 0;
+
+       if (!pskb_may_pull(oldskb, iph->ihl*4))
+               return 0;
+
+       return 1;
+}
+
+static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook)
+{
+       struct sk_buff *nskb;
+       struct iphdr *niph;
+       const struct tcphdr *oth;
+       struct tcphdr _oth;
+
+       if (!nft_reject_iphdr_validate(oldskb))
+               return;
+
+       oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook);
+       if (!oth)
+               return;
+
+       nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
+                        LL_MAX_HEADER, GFP_ATOMIC);
+       if (!nskb)
+               return;
+
+       skb_reserve(nskb, LL_MAX_HEADER);
+       niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
+                                  sysctl_ip_default_ttl);
+       nf_reject_ip_tcphdr_put(nskb, oldskb, oth);
+       niph->ttl       = sysctl_ip_default_ttl;
+       niph->tot_len   = htons(nskb->len);
+       ip_send_check(niph);
+
+       nft_reject_br_push_etherhdr(oldskb, nskb);
+
+       br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
+
+static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook,
+                                         u8 code)
+{
+       struct sk_buff *nskb;
+       struct iphdr *niph;
+       struct icmphdr *icmph;
+       unsigned int len;
+       void *payload;
+       __wsum csum;
+
+       if (!nft_reject_iphdr_validate(oldskb))
+               return;
+
+       /* IP header checks: fragment. */
+       if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
+               return;
+
+       /* RFC says return as much as we can without exceeding 576 bytes. */
+       len = min_t(unsigned int, 536, oldskb->len);
+
+       if (!pskb_may_pull(oldskb, len))
+               return;
+
+       if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), 0))
+               return;
+
+       nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) +
+                        LL_MAX_HEADER + len, GFP_ATOMIC);
+       if (!nskb)
+               return;
+
+       skb_reserve(nskb, LL_MAX_HEADER);
+       niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_ICMP,
+                                  sysctl_ip_default_ttl);
+
+       skb_reset_transport_header(nskb);
+       icmph = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr));
+       memset(icmph, 0, sizeof(*icmph));
+       icmph->type     = ICMP_DEST_UNREACH;
+       icmph->code     = code;
+
+       payload = skb_put(nskb, len);
+       memcpy(payload, skb_network_header(oldskb), len);
+
+       csum = csum_partial((void *)icmph, len + sizeof(struct icmphdr), 0);
+       icmph->checksum = csum_fold(csum);
+
+       niph->tot_len   = htons(nskb->len);
+       ip_send_check(niph);
+
+       nft_reject_br_push_etherhdr(oldskb, nskb);
+
+       br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
+
+static int nft_reject_ip6hdr_validate(struct sk_buff *oldskb)
+{
+       struct ipv6hdr *hdr;
+       u32 pkt_len;
+
+       if (!pskb_may_pull(oldskb, sizeof(struct ipv6hdr)))
+               return 0;
+
+       hdr = ipv6_hdr(oldskb);
+       if (hdr->version != 6)
+               return 0;
+
+       pkt_len = ntohs(hdr->payload_len);
+       if (pkt_len + sizeof(struct ipv6hdr) > oldskb->len)
+               return 0;
+
+       return 1;
+}
+
+static void nft_reject_br_send_v6_tcp_reset(struct net *net,
+                                           struct sk_buff *oldskb, int hook)
+{
+       struct sk_buff *nskb;
+       const struct tcphdr *oth;
+       struct tcphdr _oth;
+       unsigned int otcplen;
+       struct ipv6hdr *nip6h;
+
+       if (!nft_reject_ip6hdr_validate(oldskb))
+               return;
+
+       oth = nf_reject_ip6_tcphdr_get(oldskb, &_oth, &otcplen, hook);
+       if (!oth)
+               return;
+
+       nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct tcphdr) +
+                        LL_MAX_HEADER, GFP_ATOMIC);
+       if (!nskb)
+               return;
+
+       skb_reserve(nskb, LL_MAX_HEADER);
+       nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP,
+                                    net->ipv6.devconf_all->hop_limit);
+       nf_reject_ip6_tcphdr_put(nskb, oldskb, oth, otcplen);
+       nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr));
+
+       nft_reject_br_push_etherhdr(oldskb, nskb);
+
+       br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
+
+static void nft_reject_br_send_v6_unreach(struct net *net,
+                                         struct sk_buff *oldskb, int hook,
+                                         u8 code)
+{
+       struct sk_buff *nskb;
+       struct ipv6hdr *nip6h;
+       struct icmp6hdr *icmp6h;
+       unsigned int len;
+       void *payload;
+
+       if (!nft_reject_ip6hdr_validate(oldskb))
+               return;
+
+       /* Include "As much of invoking packet as possible without the ICMPv6
+        * packet exceeding the minimum IPv6 MTU" in the ICMP payload.
+        */
+       len = min_t(unsigned int, 1220, oldskb->len);
+
+       if (!pskb_may_pull(oldskb, len))
+               return;
+
+       nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) +
+                        LL_MAX_HEADER + len, GFP_ATOMIC);
+       if (!nskb)
+               return;
+
+       skb_reserve(nskb, LL_MAX_HEADER);
+       nip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_ICMPV6,
+                                    net->ipv6.devconf_all->hop_limit);
+
+       skb_reset_transport_header(nskb);
+       icmp6h = (struct icmp6hdr *)skb_put(nskb, sizeof(struct icmp6hdr));
+       memset(icmp6h, 0, sizeof(*icmp6h));
+       icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
+       icmp6h->icmp6_code = code;
+
+       payload = skb_put(nskb, len);
+       memcpy(payload, skb_network_header(oldskb), len);
+       nip6h->payload_len = htons(nskb->len - sizeof(struct ipv6hdr));
+
+       icmp6h->icmp6_cksum =
+               csum_ipv6_magic(&nip6h->saddr, &nip6h->daddr,
+                               nskb->len - sizeof(struct ipv6hdr),
+                               IPPROTO_ICMPV6,
+                               csum_partial(icmp6h,
+                                            nskb->len - sizeof(struct ipv6hdr),
+                                            0));
+
+       nft_reject_br_push_etherhdr(oldskb, nskb);
+
+       br_deliver(br_port_get_rcu(oldskb->dev), nskb);
+}
 
 static void nft_reject_bridge_eval(const struct nft_expr *expr,
                                 struct nft_data data[NFT_REG_MAX + 1],
@@ -23,35 +256,46 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
 {
        struct nft_reject *priv = nft_expr_priv(expr);
        struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
+       const unsigned char *dest = eth_hdr(pkt->skb)->h_dest;
+
+       if (is_broadcast_ether_addr(dest) ||
+           is_multicast_ether_addr(dest))
+               goto out;
 
        switch (eth_hdr(pkt->skb)->h_proto) {
        case htons(ETH_P_IP):
                switch (priv->type) {
                case NFT_REJECT_ICMP_UNREACH:
-                       nf_send_unreach(pkt->skb, priv->icmp_code);
+                       nft_reject_br_send_v4_unreach(pkt->skb,
+                                                     pkt->ops->hooknum,
+                                                     priv->icmp_code);
                        break;
                case NFT_REJECT_TCP_RST:
-                       nf_send_reset(pkt->skb, pkt->ops->hooknum);
+                       nft_reject_br_send_v4_tcp_reset(pkt->skb,
+                                                       pkt->ops->hooknum);
                        break;
                case NFT_REJECT_ICMPX_UNREACH:
-                       nf_send_unreach(pkt->skb,
-                                       nft_reject_icmp_code(priv->icmp_code));
+                       nft_reject_br_send_v4_unreach(pkt->skb,
+                                                     pkt->ops->hooknum,
+                                                     nft_reject_icmp_code(priv->icmp_code));
                        break;
                }
                break;
        case htons(ETH_P_IPV6):
                switch (priv->type) {
                case NFT_REJECT_ICMP_UNREACH:
-                       nf_send_unreach6(net, pkt->skb, priv->icmp_code,
-                                        pkt->ops->hooknum);
+                       nft_reject_br_send_v6_unreach(net, pkt->skb,
+                                                     pkt->ops->hooknum,
+                                                     priv->icmp_code);
                        break;
                case NFT_REJECT_TCP_RST:
-                       nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
+                       nft_reject_br_send_v6_tcp_reset(net, pkt->skb,
+                                                       pkt->ops->hooknum);
                        break;
                case NFT_REJECT_ICMPX_UNREACH:
-                       nf_send_unreach6(net, pkt->skb,
-                                        nft_reject_icmpv6_code(priv->icmp_code),
-                                        pkt->ops->hooknum);
+                       nft_reject_br_send_v6_unreach(net, pkt->skb,
+                                                     pkt->ops->hooknum,
+                                                     nft_reject_icmpv6_code(priv->icmp_code));
                        break;
                }
                break;
@@ -59,15 +303,38 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
                /* No explicit way to reject this protocol, drop it. */
                break;
        }
+out:
        data[NFT_REG_VERDICT].verdict = NF_DROP;
 }
 
+static int nft_reject_bridge_validate_hooks(const struct nft_chain *chain)
+{
+       struct nft_base_chain *basechain;
+
+       if (chain->flags & NFT_BASE_CHAIN) {
+               basechain = nft_base_chain(chain);
+
+               switch (basechain->ops[0].hooknum) {
+               case NF_BR_PRE_ROUTING:
+               case NF_BR_LOCAL_IN:
+                       break;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       }
+       return 0;
+}
+
 static int nft_reject_bridge_init(const struct nft_ctx *ctx,
                                  const struct nft_expr *expr,
                                  const struct nlattr * const tb[])
 {
        struct nft_reject *priv = nft_expr_priv(expr);
-       int icmp_code;
+       int icmp_code, err;
+
+       err = nft_reject_bridge_validate_hooks(ctx->chain);
+       if (err < 0)
+               return err;
 
        if (tb[NFTA_REJECT_TYPE] == NULL)
                return -EINVAL;
@@ -116,6 +383,13 @@ nla_put_failure:
        return -1;
 }
 
+static int nft_reject_bridge_validate(const struct nft_ctx *ctx,
+                                     const struct nft_expr *expr,
+                                     const struct nft_data **data)
+{
+       return nft_reject_bridge_validate_hooks(ctx->chain);
+}
+
 static struct nft_expr_type nft_reject_bridge_type;
 static const struct nft_expr_ops nft_reject_bridge_ops = {
        .type           = &nft_reject_bridge_type,
@@ -123,6 +397,7 @@ static const struct nft_expr_ops nft_reject_bridge_ops = {
        .eval           = nft_reject_bridge_eval,
        .init           = nft_reject_bridge_init,
        .dump           = nft_reject_bridge_dump,
+       .validate       = nft_reject_bridge_validate,
 };
 
 static struct nft_expr_type nft_reject_bridge_type __read_mostly = {
index de6662b14e1f5d7110ac1316c1362e4db6bffc5f..7e38b729696a97567e3c0d284631a3229ef413dd 100644 (file)
@@ -149,6 +149,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
        struct ceph_crypto_key old_key;
        void *ticket_buf = NULL;
        void *tp, *tpend;
+       void **ptp;
        struct ceph_timespec new_validity;
        struct ceph_crypto_key new_session_key;
        struct ceph_buffer *new_ticket_blob;
@@ -208,25 +209,19 @@ static int process_one_ticket(struct ceph_auth_client *ac,
                        goto out;
                }
                tp = ticket_buf;
-               dlen = ceph_decode_32(&tp);
+               ptp = &tp;
+               tpend = *ptp + dlen;
        } else {
                /* unencrypted */
-               ceph_decode_32_safe(p, end, dlen, bad);
-               ticket_buf = kmalloc(dlen, GFP_NOFS);
-               if (!ticket_buf) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               tp = ticket_buf;
-               ceph_decode_need(p, end, dlen, bad);
-               ceph_decode_copy(p, ticket_buf, dlen);
+               ptp = p;
+               tpend = end;
        }
-       tpend = tp + dlen;
+       ceph_decode_32_safe(ptp, tpend, dlen, bad);
        dout(" ticket blob is %d bytes\n", dlen);
-       ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
-       blob_struct_v = ceph_decode_8(&tp);
-       new_secret_id = ceph_decode_64(&tp);
-       ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
+       ceph_decode_need(ptp, tpend, 1 + sizeof(u64), bad);
+       blob_struct_v = ceph_decode_8(ptp);
+       new_secret_id = ceph_decode_64(ptp);
+       ret = ceph_decode_buffer(&new_ticket_blob, ptp, tpend);
        if (ret)
                goto out;
 
index 62fc5e7a9acf7506eba2de7ae314ba6067870ceb..790fe89d90c0ac49301bfcc81ba1b6633b9559cd 100644 (file)
@@ -90,11 +90,82 @@ static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void)
 
 static const u8 *aes_iv = (u8 *)CEPH_AES_IV;
 
+/*
+ * Should be used for buffers allocated with ceph_kvmalloc().
+ * Currently these are encrypt out-buffer (ceph_buffer) and decrypt
+ * in-buffer (msg front).
+ *
+ * Dispose of @sgt with teardown_sgtable().
+ *
+ * @prealloc_sg is to avoid memory allocation inside sg_alloc_table()
+ * in cases where a single sg is sufficient.  No attempt to reduce the
+ * number of sgs by squeezing physically contiguous pages together is
+ * made though, for simplicity.
+ */
+static int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg,
+                        const void *buf, unsigned int buf_len)
+{
+       struct scatterlist *sg;
+       const bool is_vmalloc = is_vmalloc_addr(buf);
+       unsigned int off = offset_in_page(buf);
+       unsigned int chunk_cnt = 1;
+       unsigned int chunk_len = PAGE_ALIGN(off + buf_len);
+       int i;
+       int ret;
+
+       if (buf_len == 0) {
+               memset(sgt, 0, sizeof(*sgt));
+               return -EINVAL;
+       }
+
+       if (is_vmalloc) {
+               chunk_cnt = chunk_len >> PAGE_SHIFT;
+               chunk_len = PAGE_SIZE;
+       }
+
+       if (chunk_cnt > 1) {
+               ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS);
+               if (ret)
+                       return ret;
+       } else {
+               WARN_ON(chunk_cnt != 1);
+               sg_init_table(prealloc_sg, 1);
+               sgt->sgl = prealloc_sg;
+               sgt->nents = sgt->orig_nents = 1;
+       }
+
+       for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
+               struct page *page;
+               unsigned int len = min(chunk_len - off, buf_len);
+
+               if (is_vmalloc)
+                       page = vmalloc_to_page(buf);
+               else
+                       page = virt_to_page(buf);
+
+               sg_set_page(sg, page, len, off);
+
+               off = 0;
+               buf += len;
+               buf_len -= len;
+       }
+       WARN_ON(buf_len != 0);
+
+       return 0;
+}
+
+static void teardown_sgtable(struct sg_table *sgt)
+{
+       if (sgt->orig_nents > 1)
+               sg_free_table(sgt);
+}
+
 static int ceph_aes_encrypt(const void *key, int key_len,
                            void *dst, size_t *dst_len,
                            const void *src, size_t src_len)
 {
-       struct scatterlist sg_in[2], sg_out[1];
+       struct scatterlist sg_in[2], prealloc_sg;
+       struct sg_table sg_out;
        struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
        struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
        int ret;
@@ -110,16 +181,18 @@ static int ceph_aes_encrypt(const void *key, int key_len,
 
        *dst_len = src_len + zero_padding;
 
-       crypto_blkcipher_setkey((void *)tfm, key, key_len);
        sg_init_table(sg_in, 2);
        sg_set_buf(&sg_in[0], src, src_len);
        sg_set_buf(&sg_in[1], pad, zero_padding);
-       sg_init_table(sg_out, 1);
-       sg_set_buf(sg_out, dst, *dst_len);
+       ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len);
+       if (ret)
+               goto out_tfm;
+
+       crypto_blkcipher_setkey((void *)tfm, key, key_len);
        iv = crypto_blkcipher_crt(tfm)->iv;
        ivsize = crypto_blkcipher_ivsize(tfm);
-
        memcpy(iv, aes_iv, ivsize);
+
        /*
        print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
                       key, key_len, 1);
@@ -128,16 +201,22 @@ static int ceph_aes_encrypt(const void *key, int key_len,
        print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
                        pad, zero_padding, 1);
        */
-       ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
+       ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in,
                                     src_len + zero_padding);
-       crypto_free_blkcipher(tfm);
-       if (ret < 0)
+       if (ret < 0) {
                pr_err("ceph_aes_crypt failed %d\n", ret);
+               goto out_sg;
+       }
        /*
        print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
                       dst, *dst_len, 1);
        */
-       return 0;
+
+out_sg:
+       teardown_sgtable(&sg_out);
+out_tfm:
+       crypto_free_blkcipher(tfm);
+       return ret;
 }
 
 static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
@@ -145,7 +224,8 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
                             const void *src1, size_t src1_len,
                             const void *src2, size_t src2_len)
 {
-       struct scatterlist sg_in[3], sg_out[1];
+       struct scatterlist sg_in[3], prealloc_sg;
+       struct sg_table sg_out;
        struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
        struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
        int ret;
@@ -161,17 +241,19 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
 
        *dst_len = src1_len + src2_len + zero_padding;
 
-       crypto_blkcipher_setkey((void *)tfm, key, key_len);
        sg_init_table(sg_in, 3);
        sg_set_buf(&sg_in[0], src1, src1_len);
        sg_set_buf(&sg_in[1], src2, src2_len);
        sg_set_buf(&sg_in[2], pad, zero_padding);
-       sg_init_table(sg_out, 1);
-       sg_set_buf(sg_out, dst, *dst_len);
+       ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len);
+       if (ret)
+               goto out_tfm;
+
+       crypto_blkcipher_setkey((void *)tfm, key, key_len);
        iv = crypto_blkcipher_crt(tfm)->iv;
        ivsize = crypto_blkcipher_ivsize(tfm);
-
        memcpy(iv, aes_iv, ivsize);
+
        /*
        print_hex_dump(KERN_ERR, "enc  key: ", DUMP_PREFIX_NONE, 16, 1,
                       key, key_len, 1);
@@ -182,23 +264,30 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
        print_hex_dump(KERN_ERR, "enc  pad: ", DUMP_PREFIX_NONE, 16, 1,
                        pad, zero_padding, 1);
        */
-       ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
+       ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in,
                                     src1_len + src2_len + zero_padding);
-       crypto_free_blkcipher(tfm);
-       if (ret < 0)
+       if (ret < 0) {
                pr_err("ceph_aes_crypt2 failed %d\n", ret);
+               goto out_sg;
+       }
        /*
        print_hex_dump(KERN_ERR, "enc  out: ", DUMP_PREFIX_NONE, 16, 1,
                       dst, *dst_len, 1);
        */
-       return 0;
+
+out_sg:
+       teardown_sgtable(&sg_out);
+out_tfm:
+       crypto_free_blkcipher(tfm);
+       return ret;
 }
 
 static int ceph_aes_decrypt(const void *key, int key_len,
                            void *dst, size_t *dst_len,
                            const void *src, size_t src_len)
 {
-       struct scatterlist sg_in[1], sg_out[2];
+       struct sg_table sg_in;
+       struct scatterlist sg_out[2], prealloc_sg;
        struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
        struct blkcipher_desc desc = { .tfm = tfm };
        char pad[16];
@@ -210,16 +299,16 @@ static int ceph_aes_decrypt(const void *key, int key_len,
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
-       crypto_blkcipher_setkey((void *)tfm, key, key_len);
-       sg_init_table(sg_in, 1);
        sg_init_table(sg_out, 2);
-       sg_set_buf(sg_in, src, src_len);
        sg_set_buf(&sg_out[0], dst, *dst_len);
        sg_set_buf(&sg_out[1], pad, sizeof(pad));
+       ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len);
+       if (ret)
+               goto out_tfm;
 
+       crypto_blkcipher_setkey((void *)tfm, key, key_len);
        iv = crypto_blkcipher_crt(tfm)->iv;
        ivsize = crypto_blkcipher_ivsize(tfm);
-
        memcpy(iv, aes_iv, ivsize);
 
        /*
@@ -228,12 +317,10 @@ static int ceph_aes_decrypt(const void *key, int key_len,
        print_hex_dump(KERN_ERR, "dec  in: ", DUMP_PREFIX_NONE, 16, 1,
                       src, src_len, 1);
        */
-
-       ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
-       crypto_free_blkcipher(tfm);
+       ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len);
        if (ret < 0) {
                pr_err("ceph_aes_decrypt failed %d\n", ret);
-               return ret;
+               goto out_sg;
        }
 
        if (src_len <= *dst_len)
@@ -251,7 +338,12 @@ static int ceph_aes_decrypt(const void *key, int key_len,
        print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1,
                       dst, *dst_len, 1);
        */
-       return 0;
+
+out_sg:
+       teardown_sgtable(&sg_in);
+out_tfm:
+       crypto_free_blkcipher(tfm);
+       return ret;
 }
 
 static int ceph_aes_decrypt2(const void *key, int key_len,
@@ -259,7 +351,8 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
                             void *dst2, size_t *dst2_len,
                             const void *src, size_t src_len)
 {
-       struct scatterlist sg_in[1], sg_out[3];
+       struct sg_table sg_in;
+       struct scatterlist sg_out[3], prealloc_sg;
        struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
        struct blkcipher_desc desc = { .tfm = tfm };
        char pad[16];
@@ -271,17 +364,17 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
-       sg_init_table(sg_in, 1);
-       sg_set_buf(sg_in, src, src_len);
        sg_init_table(sg_out, 3);
        sg_set_buf(&sg_out[0], dst1, *dst1_len);
        sg_set_buf(&sg_out[1], dst2, *dst2_len);
        sg_set_buf(&sg_out[2], pad, sizeof(pad));
+       ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len);
+       if (ret)
+               goto out_tfm;
 
        crypto_blkcipher_setkey((void *)tfm, key, key_len);
        iv = crypto_blkcipher_crt(tfm)->iv;
        ivsize = crypto_blkcipher_ivsize(tfm);
-
        memcpy(iv, aes_iv, ivsize);
 
        /*
@@ -290,12 +383,10 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
        print_hex_dump(KERN_ERR, "dec   in: ", DUMP_PREFIX_NONE, 16, 1,
                       src, src_len, 1);
        */
-
-       ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
-       crypto_free_blkcipher(tfm);
+       ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len);
        if (ret < 0) {
                pr_err("ceph_aes_decrypt failed %d\n", ret);
-               return ret;
+               goto out_sg;
        }
 
        if (src_len <= *dst1_len)
@@ -325,7 +416,11 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
                       dst2, *dst2_len, 1);
        */
 
-       return 0;
+out_sg:
+       teardown_sgtable(&sg_in);
+out_tfm:
+       crypto_free_blkcipher(tfm);
+       return ret;
 }
 
 
index 559c9f619c2027e33f733469b2a8a59eda582f89..8d1653caffdb4104d893c2bcbac939ed465a8bc9 100644 (file)
@@ -484,7 +484,7 @@ static int ceph_tcp_connect(struct ceph_connection *con)
                               IPPROTO_TCP, &sock);
        if (ret)
                return ret;
-       sock->sk->sk_allocation = GFP_NOFS;
+       sock->sk->sk_allocation = GFP_NOFS | __GFP_MEMALLOC;
 
 #ifdef CONFIG_LOCKDEP
        lockdep_set_class(&sock->sk->sk_lock, &socket_class);
@@ -509,6 +509,9 @@ static int ceph_tcp_connect(struct ceph_connection *con)
 
                return ret;
        }
+
+       sk_set_memalloc(sock->sk);
+
        con->sock = sock;
        return 0;
 }
@@ -2769,8 +2772,11 @@ static void con_work(struct work_struct *work)
 {
        struct ceph_connection *con = container_of(work, struct ceph_connection,
                                                   work.work);
+       unsigned long pflags = current->flags;
        bool fault;
 
+       current->flags |= PF_MEMALLOC;
+
        mutex_lock(&con->mutex);
        while (true) {
                int ret;
@@ -2824,6 +2830,8 @@ static void con_work(struct work_struct *work)
                con_fault_finish(con);
 
        con->ops->put(con);
+
+       tsk_restore_flags(current, pflags, PF_MEMALLOC);
 }
 
 /*
index f3fc54eac09d32e691a64b5d65ba90793cba96b8..6f164289bde8860e333c747934da5459e807d7eb 100644 (file)
@@ -1007,8 +1007,8 @@ static void put_osd(struct ceph_osd *osd)
 static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
 {
        dout("__remove_osd %p\n", osd);
-       BUG_ON(!list_empty(&osd->o_requests));
-       BUG_ON(!list_empty(&osd->o_linger_requests));
+       WARN_ON(!list_empty(&osd->o_requests));
+       WARN_ON(!list_empty(&osd->o_linger_requests));
 
        rb_erase(&osd->o_node, &osdc->osds);
        list_del_init(&osd->o_osd_lru);
@@ -1254,6 +1254,8 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc,
                if (list_empty(&req->r_osd_item))
                        req->r_osd = NULL;
        }
+
+       list_del_init(&req->r_req_lru_item); /* can be on notarget */
        ceph_osdc_put_request(req);
 }
 
@@ -1395,6 +1397,7 @@ static int __map_request(struct ceph_osd_client *osdc,
        if (req->r_osd) {
                __cancel_request(req);
                list_del_init(&req->r_osd_item);
+               list_del_init(&req->r_linger_osd_item);
                req->r_osd = NULL;
        }
 
index b793e3521a3631319bf4d0e7c17c0c9a933331da..3acff097456023e17b1e69188a0553dd5afce8a8 100644 (file)
@@ -4157,6 +4157,10 @@ EXPORT_SYMBOL(napi_gro_receive);
 
 static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
 {
+       if (unlikely(skb->pfmemalloc)) {
+               consume_skb(skb);
+               return;
+       }
        __skb_pull(skb, skb_headlen(skb));
        /* restore the reserve we had after netdev_alloc_skb_ip_align() */
        skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb));
@@ -7196,11 +7200,10 @@ static void __net_exit rtnl_lock_unregistering(struct list_head *net_list)
         */
        struct net *net;
        bool unregistering;
-       DEFINE_WAIT(wait);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
+       add_wait_queue(&netdev_unregistering_wq, &wait);
        for (;;) {
-               prepare_to_wait(&netdev_unregistering_wq, &wait,
-                               TASK_UNINTERRUPTIBLE);
                unregistering = false;
                rtnl_lock();
                list_for_each_entry(net, net_list, exit_list) {
@@ -7212,9 +7215,10 @@ static void __net_exit rtnl_lock_unregistering(struct list_head *net_list)
                if (!unregistering)
                        break;
                __rtnl_unlock();
-               schedule();
+
+               wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
        }
-       finish_wait(&netdev_unregistering_wq, &wait);
+       remove_wait_queue(&netdev_unregistering_wq, &wait);
 }
 
 static void __net_exit default_device_exit_batch(struct list_head *net_list)
index 1600aa24d36bcaa653dff0b0c34f4d700eb4fbb9..06dfb293e5aafa10ab2754bfb80d29ad29f2db95 100644 (file)
@@ -1036,7 +1036,8 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr)
 {
        const struct ethtool_ops *ops = dev->ethtool_ops;
 
-       if (!ops->get_eeprom || !ops->get_eeprom_len)
+       if (!ops->get_eeprom || !ops->get_eeprom_len ||
+           !ops->get_eeprom_len(dev))
                return -EOPNOTSUPP;
 
        return ethtool_get_any_eeprom(dev, useraddr, ops->get_eeprom,
@@ -1052,7 +1053,8 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr)
        u8 *data;
        int ret = 0;
 
-       if (!ops->set_eeprom || !ops->get_eeprom_len)
+       if (!ops->set_eeprom || !ops->get_eeprom_len ||
+           !ops->get_eeprom_len(dev))
                return -EOPNOTSUPP;
 
        if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
index a6882686ca3a10fc3be7ced6299dc7385ffd239d..88e8de3b59b0f4e1b251928a6088019b6513ce68 100644 (file)
@@ -365,11 +365,10 @@ static void rtnl_lock_unregistering_all(void)
 {
        struct net *net;
        bool unregistering;
-       DEFINE_WAIT(wait);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
+       add_wait_queue(&netdev_unregistering_wq, &wait);
        for (;;) {
-               prepare_to_wait(&netdev_unregistering_wq, &wait,
-                               TASK_UNINTERRUPTIBLE);
                unregistering = false;
                rtnl_lock();
                for_each_net(net) {
@@ -381,9 +380,10 @@ static void rtnl_lock_unregistering_all(void)
                if (!unregistering)
                        break;
                __rtnl_unlock();
-               schedule();
+
+               wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
        }
-       finish_wait(&netdev_unregistering_wq, &wait);
+       remove_wait_queue(&netdev_unregistering_wq, &wait);
 }
 
 /**
@@ -1498,6 +1498,7 @@ static int do_setlink(const struct sk_buff *skb,
                        goto errout;
                }
                if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+                       put_net(net);
                        err = -EPERM;
                        goto errout;
                }
@@ -2685,13 +2686,20 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
        int idx = 0;
        u32 portid = NETLINK_CB(cb->skb).portid;
        u32 seq = cb->nlh->nlmsg_seq;
-       struct nlattr *extfilt;
        u32 filter_mask = 0;
 
-       extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg),
-                                 IFLA_EXT_MASK);
-       if (extfilt)
-               filter_mask = nla_get_u32(extfilt);
+       if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) {
+               struct nlattr *extfilt;
+
+               extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg),
+                                         IFLA_EXT_MASK);
+               if (extfilt) {
+                       if (nla_len(extfilt) < sizeof(filter_mask))
+                               return -EINVAL;
+
+                       filter_mask = nla_get_u32(extfilt);
+               }
+       }
 
        rcu_read_lock();
        for_each_netdev_rcu(net, dev) {
@@ -2798,6 +2806,9 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
        if (br_spec) {
                nla_for_each_nested(attr, br_spec, rem) {
                        if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
+                               if (nla_len(attr) < sizeof(flags))
+                                       return -EINVAL;
+
                                have_flags = true;
                                flags = nla_get_u16(attr);
                                break;
@@ -2868,6 +2879,9 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh)
        if (br_spec) {
                nla_for_each_nested(attr, br_spec, rem) {
                        if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
+                               if (nla_len(attr) < sizeof(flags))
+                                       return -EINVAL;
+
                                have_flags = true;
                                flags = nla_get_u16(attr);
                                break;
index 61059a05ec95f1fdc420e7bbb250d1a8b22c87b0..32e31c2996315770149b71b1e17837311d672a1e 100644 (file)
@@ -552,20 +552,13 @@ static void kfree_skbmem(struct sk_buff *skb)
        case SKB_FCLONE_CLONE:
                fclones = container_of(skb, struct sk_buff_fclones, skb2);
 
-               /* Warning : We must perform the atomic_dec_and_test() before
-                * setting skb->fclone back to SKB_FCLONE_FREE, otherwise
-                * skb_clone() could set clone_ref to 2 before our decrement.
-                * Anyway, if we are going to free the structure, no need to
-                * rewrite skb->fclone.
+               /* The clone portion is available for
+                * fast-cloning again.
                 */
-               if (atomic_dec_and_test(&fclones->fclone_ref)) {
+               skb->fclone = SKB_FCLONE_FREE;
+
+               if (atomic_dec_and_test(&fclones->fclone_ref))
                        kmem_cache_free(skbuff_fclone_cache, fclones);
-               } else {
-                       /* The clone portion is available for
-                        * fast-cloning again.
-                        */
-                       skb->fclone = SKB_FCLONE_FREE;
-               }
                break;
        }
 }
@@ -887,11 +880,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
        if (skb->fclone == SKB_FCLONE_ORIG &&
            n->fclone == SKB_FCLONE_FREE) {
                n->fclone = SKB_FCLONE_CLONE;
-               /* As our fastclone was free, clone_ref must be 1 at this point.
-                * We could use atomic_inc() here, but it is faster
-                * to set the final value.
-                */
-               atomic_set(&fclones->fclone_ref, 2);
+               atomic_inc(&fclones->fclone_ref);
        } else {
                if (skb_pfmemalloc(skb))
                        gfp_mask |= __GFP_MEMALLOC;
@@ -4070,15 +4059,22 @@ EXPORT_SYMBOL_GPL(skb_scrub_packet);
 unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
 {
        const struct skb_shared_info *shinfo = skb_shinfo(skb);
+       unsigned int thlen = 0;
 
-       if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
-               return tcp_hdrlen(skb) + shinfo->gso_size;
+       if (skb->encapsulation) {
+               thlen = skb_inner_transport_header(skb) -
+                       skb_transport_header(skb);
 
+               if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
+                       thlen += inner_tcp_hdrlen(skb);
+       } else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) {
+               thlen = tcp_hdrlen(skb);
+       }
        /* UFO sets gso_size to the size of the fragmentation
         * payload, i.e. the size of the L4 (UDP) header is already
         * accounted for.
         */
-       return shinfo->gso_size;
+       return thlen + shinfo->gso_size;
 }
 EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
 
index 8c3203c585b0c116e7d8ea8f66feeda7c4a73452..630b30b4fb5368332428289e449b3247be0cd97b 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/export.h>
 #include <net/ip.h>
 #include <net/tso.h>
+#include <asm/unaligned.h>
 
 /* Calculate expected number of TX descriptors */
 int tso_count_descs(struct sk_buff *skb)
@@ -23,7 +24,7 @@ void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso,
        iph->id = htons(tso->ip_id);
        iph->tot_len = htons(size + hdr_len - mac_hdr_len);
        tcph = (struct tcphdr *)(hdr + skb_transport_offset(skb));
-       tcph->seq = htonl(tso->tcp_seq);
+       put_unaligned_be32(tso->tcp_seq, &tcph->seq);
        tso->ip_id++;
 
        if (!is_last) {
index ca11d283bbebe3ae02345ecd72cb022ae7c43667..93ea80196f0ec383cca46d28bf8c4c96d0310b25 100644 (file)
@@ -1080,13 +1080,13 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
        if (!app)
                return -EMSGSIZE;
 
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        list_for_each_entry(itr, &dcb_app_list, list) {
                if (itr->ifindex == netdev->ifindex) {
                        err = nla_put(skb, DCB_ATTR_IEEE_APP, sizeof(itr->app),
                                         &itr->app);
                        if (err) {
-                               spin_unlock(&dcb_lock);
+                               spin_unlock_bh(&dcb_lock);
                                return -EMSGSIZE;
                        }
                }
@@ -1097,7 +1097,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
        else
                dcbx = -EOPNOTSUPP;
 
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
        nla_nest_end(skb, app);
 
        /* get peer info if available */
@@ -1234,7 +1234,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
        }
 
        /* local app */
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        app = nla_nest_start(skb, DCB_ATTR_CEE_APP_TABLE);
        if (!app)
                goto dcb_unlock;
@@ -1271,7 +1271,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
        else
                dcbx = -EOPNOTSUPP;
 
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
 
        /* features flags */
        if (ops->getfeatcfg) {
@@ -1326,7 +1326,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
        return 0;
 
 dcb_unlock:
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
 nla_put_failure:
        return err;
 }
@@ -1762,10 +1762,10 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
        struct dcb_app_type *itr;
        u8 prio = 0;
 
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
                prio = itr->app.priority;
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
 
        return prio;
 }
@@ -1789,7 +1789,7 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
        if (dev->dcbnl_ops->getdcbx)
                event.dcbx = dev->dcbnl_ops->getdcbx(dev);
 
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        /* Search for existing match and replace */
        if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) {
                if (new->priority)
@@ -1804,7 +1804,7 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
        if (new->priority)
                err = dcb_app_add(new, dev->ifindex);
 out:
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
        if (!err)
                call_dcbevent_notifiers(DCB_APP_EVENT, &event);
        return err;
@@ -1823,10 +1823,10 @@ u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
        struct dcb_app_type *itr;
        u8 prio = 0;
 
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
                prio |= 1 << itr->app.priority;
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
 
        return prio;
 }
@@ -1850,7 +1850,7 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
        if (dev->dcbnl_ops->getdcbx)
                event.dcbx = dev->dcbnl_ops->getdcbx(dev);
 
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        /* Search for existing match and abort if found */
        if (dcb_app_lookup(new, dev->ifindex, new->priority)) {
                err = -EEXIST;
@@ -1859,7 +1859,7 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new)
 
        err = dcb_app_add(new, dev->ifindex);
 out:
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
        if (!err)
                call_dcbevent_notifiers(DCB_APP_EVENT, &event);
        return err;
@@ -1882,7 +1882,7 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
        if (dev->dcbnl_ops->getdcbx)
                event.dcbx = dev->dcbnl_ops->getdcbx(dev);
 
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        /* Search for existing match and remove it. */
        if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) {
                list_del(&itr->list);
@@ -1890,7 +1890,7 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
                err = 0;
        }
 
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
        if (!err)
                call_dcbevent_notifiers(DCB_APP_EVENT, &event);
        return err;
@@ -1902,12 +1902,12 @@ static void dcb_flushapp(void)
        struct dcb_app_type *app;
        struct dcb_app_type *tmp;
 
-       spin_lock(&dcb_lock);
+       spin_lock_bh(&dcb_lock);
        list_for_each_entry_safe(app, tmp, &dcb_app_list, list) {
                list_del(&app->list);
                kfree(app);
        }
-       spin_unlock(&dcb_lock);
+       spin_unlock_bh(&dcb_lock);
 }
 
 static int __init dcbnl_init(void)
index 22f34cf4cb27d1aad06dcb41a1f6d84d4dffd688..6317b41c99b0a58bb82ede4a1205d8c3e7f94283 100644 (file)
@@ -174,8 +174,11 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
                        dst->rcv = brcm_netdev_ops.rcv;
                        break;
 #endif
-               default:
+               case DSA_TAG_PROTO_NONE:
                        break;
+               default:
+                       ret = -ENOPROTOOPT;
+                       goto out;
                }
 
                dst->tag_protocol = drv->tag_protocol;
index 6d1817449c3675bb4ddd6d47a16ea017a5213e0d..ab03e00ffe8f0e2c4095e4f8c33d79c3e6d069da 100644 (file)
@@ -489,11 +489,14 @@ static void dsa_slave_phy_setup(struct dsa_slave_priv *p,
        /* We could not connect to a designated PHY, so use the switch internal
         * MDIO bus instead
         */
-       if (!p->phy)
+       if (!p->phy) {
                p->phy = ds->slave_mii_bus->phy_map[p->port];
-       else
+               phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
+                                  p->phy_interface);
+       } else {
                pr_info("attached PHY at address %d [%s]\n",
                        p->phy->addr, p->phy->drv->name);
+       }
 }
 
 int dsa_slave_suspend(struct net_device *slave_dev)
index 92db7a69f2b9d106d7d235388719d3a476eb91d5..e67da4e6c3240bb20a7d8a03a3b579f7484f629e 100644 (file)
@@ -1246,7 +1246,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 
        encap = SKB_GSO_CB(skb)->encap_level > 0;
        if (encap)
-               features = skb->dev->hw_enc_features & netif_skb_features(skb);
+               features &= skb->dev->hw_enc_features;
        SKB_GSO_CB(skb)->encap_level += ihl;
 
        skb_reset_transport_header(skb);
@@ -1386,6 +1386,17 @@ out:
        return pp;
 }
 
+int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
+{
+       if (sk->sk_family == AF_INET)
+               return ip_recv_error(sk, msg, len, addr_len);
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6)
+               return pingv6_ops.ipv6_recv_error(sk, msg, len, addr_len);
+#endif
+       return -EINVAL;
+}
+
 static int inet_gro_complete(struct sk_buff *skb, int nhoff)
 {
        __be16 newlen = htons(skb->len - nhoff);
index f2e15738534d316ed0c50b8be2e1976fa03052c5..8f7bd56955b0dc35bb89e4fd0d3fe19fe9b53a47 100644 (file)
@@ -62,6 +62,10 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res)
        else
                res->tclassid = 0;
 #endif
+
+       if (err == -ESRCH)
+               err = -ENETUNREACH;
+
        return err;
 }
 EXPORT_SYMBOL_GPL(__fib_lookup);
index 32e78924e246bb7f89ad8a7b7a722e04fd879d0e..606c520ffd5af44dd79126ce119945e1f8a070ce 100644 (file)
@@ -133,6 +133,8 @@ static int fou_gro_complete(struct sk_buff *skb, int nhoff)
        int err = -ENOSYS;
        const struct net_offload **offloads;
 
+       udp_tunnel_gro_complete(skb, nhoff);
+
        rcu_read_lock();
        offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads;
        ops = rcu_dereference(offloads[proto]);
index 065cd94c640c0c2a20cbf99c31cba588db54897e..dedb21e9991438259ff66a4e4817349dfd9d3224 100644 (file)
@@ -144,6 +144,8 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
        gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len);
        geneve_build_header(gnvh, tun_flags, vni, opt_len, opt);
 
+       skb_set_inner_protocol(skb, htons(ETH_P_TEB));
+
        return udp_tunnel_xmit_skb(gs->sock, rt, skb, src, dst,
                                   tos, ttl, df, src_port, dst_port, xnet);
 }
@@ -364,6 +366,7 @@ late_initcall(geneve_init_module);
 static void __exit geneve_cleanup_module(void)
 {
        destroy_workqueue(geneve_wq);
+       unregister_pernet_subsys(&geneve_net_ops);
 }
 module_exit(geneve_cleanup_module);
 
index ccda09628de7e74f0f4f123bc3834afd12fd69a8..bb5947b0ce2dfbd94a0b85a13983c060b2984075 100644 (file)
@@ -47,7 +47,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 
        greh = (struct gre_base_hdr *)skb_transport_header(skb);
 
-       ghl = skb_inner_network_header(skb) - skb_transport_header(skb);
+       ghl = skb_inner_mac_header(skb) - skb_transport_header(skb);
        if (unlikely(ghl < sizeof(*greh)))
                goto out;
 
@@ -68,7 +68,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
        skb->mac_len = skb_inner_network_offset(skb);
 
        /* segment inner packet. */
-       enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
+       enc_features = skb->dev->hw_enc_features & features;
        segs = skb_mac_gso_segment(skb, enc_features);
        if (IS_ERR_OR_NULL(segs)) {
                skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
index fb70e3ecc3e4d58da5db9756db9b6da027369288..bb15d0e03d4f851d789734213814ed5359b59be1 100644 (file)
@@ -318,9 +318,7 @@ igmp_scount(struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted)
        return scount;
 }
 
-#define igmp_skb_size(skb) (*(unsigned int *)((skb)->cb))
-
-static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
+static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
 {
        struct sk_buff *skb;
        struct rtable *rt;
@@ -330,6 +328,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        struct flowi4 fl4;
        int hlen = LL_RESERVED_SPACE(dev);
        int tlen = dev->needed_tailroom;
+       unsigned int size = mtu;
 
        while (1) {
                skb = alloc_skb(size + hlen + tlen,
@@ -341,7 +340,6 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
                        return NULL;
        }
        skb->priority = TC_PRIO_CONTROL;
-       igmp_skb_size(skb) = size;
 
        rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0,
                                   0, 0,
@@ -354,6 +352,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        skb_dst_set(skb, &rt->dst);
        skb->dev = dev;
 
+       skb->reserved_tailroom = skb_end_offset(skb) -
+                                min(mtu, skb_end_offset(skb));
        skb_reserve(skb, hlen);
 
        skb_reset_network_header(skb);
@@ -423,8 +423,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ip_mc_list *pmc,
        return skb;
 }
 
-#define AVAILABLE(skb) ((skb) ? ((skb)->dev ? igmp_skb_size(skb) - (skb)->len : \
-       skb_tailroom(skb)) : 0)
+#define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0)
 
 static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
        int type, int gdeleted, int sdeleted)
index 9eb89f3f0ee4cb88bf065956c45453999d799aa8..19419b60cb37d1c59c8238b49eab77d87ff0b4a1 100644 (file)
@@ -146,7 +146,6 @@ evict_again:
                        atomic_inc(&fq->refcnt);
                        spin_unlock(&hb->chain_lock);
                        del_timer_sync(&fq->timer);
-                       WARN_ON(atomic_read(&fq->refcnt) != 1);
                        inet_frag_put(fq, f);
                        goto evict_again;
                }
@@ -285,7 +284,8 @@ static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f)
        struct inet_frag_bucket *hb;
 
        hb = get_frag_bucket_locked(fq, f);
-       hlist_del(&fq->list);
+       if (!(fq->flags & INET_FRAG_EVICTED))
+               hlist_del(&fq->list);
        spin_unlock(&hb->chain_lock);
 }
 
index 88e5ef2c7f511fe75616ac2d70fdda22c9ac8b5d..bc6471d4abcdaa464d9effc244c5f1bdcb989681 100644 (file)
@@ -231,7 +231,7 @@ static int ip_finish_output_gso(struct sk_buff *skb)
         */
        features = netif_skb_features(skb);
        segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
-       if (IS_ERR(segs)) {
+       if (IS_ERR_OR_NULL(segs)) {
                kfree_skb(skb);
                return -ENOMEM;
        }
index c373a9ad45556815d1d95f4faf71b8f8a3f61996..9daf2177dc005c339c536c618fedc11259c178bc 100644 (file)
@@ -195,7 +195,7 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc,
        for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
                if (!CMSG_OK(msg, cmsg))
                        return -EINVAL;
-#if defined(CONFIG_IPV6)
+#if IS_ENABLED(CONFIG_IPV6)
                if (allow_ipv6 &&
                    cmsg->cmsg_level == SOL_IPV6 &&
                    cmsg->cmsg_type == IPV6_PKTINFO) {
index 3e861011e4a31e57b21c3fa507c178d3693a7970..1a7e979e80ba356f685ecfe020b98855f19db0a3 100644 (file)
@@ -528,6 +528,7 @@ static struct rtnl_link_ops vti_link_ops __read_mostly = {
        .validate       = vti_tunnel_validate,
        .newlink        = vti_newlink,
        .changelink     = vti_changelink,
+       .dellink        = ip_tunnel_dellink,
        .get_size       = vti_get_size,
        .fill_info      = vti_fill_info,
 };
index b023b4eb1a966415c1ae43582428566036379d7a..1baaa83dfe5ce63b8ed7cb8fb6e9e3798671e4de 100644 (file)
@@ -6,48 +6,45 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <net/ip.h>
 #include <net/tcp.h>
 #include <net/route.h>
 #include <net/dst.h>
 #include <linux/netfilter_ipv4.h>
+#include <net/netfilter/ipv4/nf_reject.h>
 
-/* Send RST reply */
-void nf_send_reset(struct sk_buff *oldskb, int hook)
+const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
+                                            struct tcphdr *_oth, int hook)
 {
-       struct sk_buff *nskb;
-       const struct iphdr *oiph;
-       struct iphdr *niph;
        const struct tcphdr *oth;
-       struct tcphdr _otcph, *tcph;
 
        /* IP header checks: fragment. */
        if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
-               return;
+               return NULL;
 
        oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
-                                sizeof(_otcph), &_otcph);
+                                sizeof(struct tcphdr), _oth);
        if (oth == NULL)
-               return;
+               return NULL;
 
        /* No RST for RST. */
        if (oth->rst)
-               return;
-
-       if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
-               return;
+               return NULL;
 
        /* Check checksum */
        if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
-               return;
-       oiph = ip_hdr(oldskb);
+               return NULL;
 
-       nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
-                        LL_MAX_HEADER, GFP_ATOMIC);
-       if (!nskb)
-               return;
+       return oth;
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_get);
 
-       skb_reserve(nskb, LL_MAX_HEADER);
+struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb,
+                                 const struct sk_buff *oldskb,
+                                 __be16 protocol, int ttl)
+{
+       struct iphdr *niph, *oiph = ip_hdr(oldskb);
 
        skb_reset_network_header(nskb);
        niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
@@ -56,10 +53,23 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
        niph->tos       = 0;
        niph->id        = 0;
        niph->frag_off  = htons(IP_DF);
-       niph->protocol  = IPPROTO_TCP;
+       niph->protocol  = protocol;
        niph->check     = 0;
        niph->saddr     = oiph->daddr;
        niph->daddr     = oiph->saddr;
+       niph->ttl       = ttl;
+
+       nskb->protocol = htons(ETH_P_IP);
+
+       return niph;
+}
+EXPORT_SYMBOL_GPL(nf_reject_iphdr_put);
+
+void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
+                         const struct tcphdr *oth)
+{
+       struct iphdr *niph = ip_hdr(nskb);
+       struct tcphdr *tcph;
 
        skb_reset_transport_header(nskb);
        tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
@@ -68,9 +78,9 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
        tcph->dest      = oth->source;
        tcph->doff      = sizeof(struct tcphdr) / 4;
 
-       if (oth->ack)
+       if (oth->ack) {
                tcph->seq = oth->ack_seq;
-       else {
+       else {
                tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
                                      oldskb->len - ip_hdrlen(oldskb) -
                                      (oth->doff << 2));
@@ -83,16 +93,43 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
        nskb->ip_summed = CHECKSUM_PARTIAL;
        nskb->csum_start = (unsigned char *)tcph - nskb->head;
        nskb->csum_offset = offsetof(struct tcphdr, check);
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
+
+/* Send RST reply */
+void nf_send_reset(struct sk_buff *oldskb, int hook)
+{
+       struct sk_buff *nskb;
+       const struct iphdr *oiph;
+       struct iphdr *niph;
+       const struct tcphdr *oth;
+       struct tcphdr _oth;
+
+       oth = nf_reject_ip_tcphdr_get(oldskb, &_oth, hook);
+       if (!oth)
+               return;
+
+       if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+               return;
+
+       oiph = ip_hdr(oldskb);
+
+       nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
+                        LL_MAX_HEADER, GFP_ATOMIC);
+       if (!nskb)
+               return;
 
        /* ip_route_me_harder expects skb->dst to be set */
        skb_dst_set_noref(nskb, skb_dst(oldskb));
 
-       nskb->protocol = htons(ETH_P_IP);
+       skb_reserve(nskb, LL_MAX_HEADER);
+       niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
+                                  ip4_dst_hoplimit(skb_dst(nskb)));
+       nf_reject_ip_tcphdr_put(nskb, oldskb, oth);
+
        if (ip_route_me_harder(nskb, RTN_UNSPEC))
                goto free_nskb;
 
-       niph->ttl       = ip4_dst_hoplimit(skb_dst(nskb));
-
        /* "Never happens" */
        if (nskb->len > dst_mtu(skb_dst(nskb)))
                goto free_nskb;
@@ -125,3 +162,5 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
        kfree_skb(nskb);
 }
 EXPORT_SYMBOL_GPL(nf_send_reset);
+
+MODULE_LICENSE("GPL");
index 1c636d6b5b5007b597e95b7852d7f76d750a4040..665de06561cd51e0933aa8436438b499d3c5066c 100644 (file)
@@ -24,6 +24,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,
        struct nf_nat_range range;
        unsigned int verdict;
 
+       memset(&range, 0, sizeof(range));
        range.flags = priv->flags;
 
        verdict = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum,
@@ -39,6 +40,7 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = {
        .eval           = nft_masq_ipv4_eval,
        .init           = nft_masq_init,
        .dump           = nft_masq_dump,
+       .validate       = nft_masq_validate,
 };
 
 static struct nft_expr_type nft_masq_ipv4_type __read_mostly = {
index 57f7c98041394998fe390735aa5b8cd2602b3f90..5d740cccf69ec29d9778ddb0568c726266904ce9 100644 (file)
@@ -217,6 +217,8 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)
                                             &ipv6_hdr(skb)->daddr))
                                continue;
 #endif
+               } else {
+                       continue;
                }
 
                if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
@@ -853,16 +855,8 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        if (flags & MSG_OOB)
                goto out;
 
-       if (flags & MSG_ERRQUEUE) {
-               if (family == AF_INET) {
-                       return ip_recv_error(sk, msg, len, addr_len);
-#if IS_ENABLED(CONFIG_IPV6)
-               } else if (family == AF_INET6) {
-                       return pingv6_ops.ipv6_recv_error(sk, msg, len,
-                                                         addr_len);
-#endif
-               }
-       }
+       if (flags & MSG_ERRQUEUE)
+               return inet_recv_error(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
index 2d4ae469b471a4fff941e0dd13d014dfd222f6a8..6a2155b02602b100c7ce3bbfda28a38090add7a4 100644 (file)
@@ -1798,6 +1798,7 @@ local_input:
 no_route:
        RT_CACHE_STAT_INC(in_no_route);
        res.type = RTN_UNREACHABLE;
+       res.fi = NULL;
        goto local_input;
 
        /*
index 1bec4e76d88c5852d8ba3392b22aa58d6453ab4d..38c2bcb8dd5da4f2c8dede10942a1388fd3d9954 100644 (file)
@@ -1598,7 +1598,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        u32 urg_hole = 0;
 
        if (unlikely(flags & MSG_ERRQUEUE))
-               return ip_recv_error(sk, msg, len, addr_len);
+               return inet_recv_error(sk, msg, len, addr_len);
 
        if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) &&
            (sk->sk_state == TCP_ESTABLISHED))
@@ -2868,61 +2868,42 @@ EXPORT_SYMBOL(compat_tcp_getsockopt);
 #endif
 
 #ifdef CONFIG_TCP_MD5SIG
-static struct tcp_md5sig_pool __percpu *tcp_md5sig_pool __read_mostly;
+static DEFINE_PER_CPU(struct tcp_md5sig_pool, tcp_md5sig_pool);
 static DEFINE_MUTEX(tcp_md5sig_mutex);
-
-static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool __percpu *pool)
-{
-       int cpu;
-
-       for_each_possible_cpu(cpu) {
-               struct tcp_md5sig_pool *p = per_cpu_ptr(pool, cpu);
-
-               if (p->md5_desc.tfm)
-                       crypto_free_hash(p->md5_desc.tfm);
-       }
-       free_percpu(pool);
-}
+static bool tcp_md5sig_pool_populated = false;
 
 static void __tcp_alloc_md5sig_pool(void)
 {
        int cpu;
-       struct tcp_md5sig_pool __percpu *pool;
-
-       pool = alloc_percpu(struct tcp_md5sig_pool);
-       if (!pool)
-               return;
 
        for_each_possible_cpu(cpu) {
-               struct crypto_hash *hash;
-
-               hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
-               if (IS_ERR_OR_NULL(hash))
-                       goto out_free;
+               if (!per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm) {
+                       struct crypto_hash *hash;
 
-               per_cpu_ptr(pool, cpu)->md5_desc.tfm = hash;
+                       hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
+                       if (IS_ERR_OR_NULL(hash))
+                               return;
+                       per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm = hash;
+               }
        }
-       /* before setting tcp_md5sig_pool, we must commit all writes
-        * to memory. See ACCESS_ONCE() in tcp_get_md5sig_pool()
+       /* before setting tcp_md5sig_pool_populated, we must commit all writes
+        * to memory. See smp_rmb() in tcp_get_md5sig_pool()
         */
        smp_wmb();
-       tcp_md5sig_pool = pool;
-       return;
-out_free:
-       __tcp_free_md5sig_pool(pool);
+       tcp_md5sig_pool_populated = true;
 }
 
 bool tcp_alloc_md5sig_pool(void)
 {
-       if (unlikely(!tcp_md5sig_pool)) {
+       if (unlikely(!tcp_md5sig_pool_populated)) {
                mutex_lock(&tcp_md5sig_mutex);
 
-               if (!tcp_md5sig_pool)
+               if (!tcp_md5sig_pool_populated)
                        __tcp_alloc_md5sig_pool();
 
                mutex_unlock(&tcp_md5sig_mutex);
        }
-       return tcp_md5sig_pool != NULL;
+       return tcp_md5sig_pool_populated;
 }
 EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
 
@@ -2936,13 +2917,13 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
  */
 struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
 {
-       struct tcp_md5sig_pool __percpu *p;
-
        local_bh_disable();
-       p = ACCESS_ONCE(tcp_md5sig_pool);
-       if (p)
-               return raw_cpu_ptr(p);
 
+       if (tcp_md5sig_pool_populated) {
+               /* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */
+               smp_rmb();
+               return this_cpu_ptr(&tcp_md5sig_pool);
+       }
        local_bh_enable();
        return NULL;
 }
index a12b455928e52211efdc6b471ef54de6218f5df0..d107ee246a1d32703ccc260309d52c3493927862 100644 (file)
@@ -2315,6 +2315,35 @@ static inline bool tcp_packet_delayed(const struct tcp_sock *tp)
 
 /* Undo procedures. */
 
+/* We can clear retrans_stamp when there are no retransmissions in the
+ * window. It would seem that it is trivially available for us in
+ * tp->retrans_out, however, that kind of assumptions doesn't consider
+ * what will happen if errors occur when sending retransmission for the
+ * second time. ...It could the that such segment has only
+ * TCPCB_EVER_RETRANS set at the present time. It seems that checking
+ * the head skb is enough except for some reneging corner cases that
+ * are not worth the effort.
+ *
+ * Main reason for all this complexity is the fact that connection dying
+ * time now depends on the validity of the retrans_stamp, in particular,
+ * that successive retransmissions of a segment must not advance
+ * retrans_stamp under any conditions.
+ */
+static bool tcp_any_retrans_done(const struct sock *sk)
+{
+       const struct tcp_sock *tp = tcp_sk(sk);
+       struct sk_buff *skb;
+
+       if (tp->retrans_out)
+               return true;
+
+       skb = tcp_write_queue_head(sk);
+       if (unlikely(skb && TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS))
+               return true;
+
+       return false;
+}
+
 #if FASTRETRANS_DEBUG > 1
 static void DBGUNDO(struct sock *sk, const char *msg)
 {
@@ -2410,6 +2439,8 @@ static bool tcp_try_undo_recovery(struct sock *sk)
                 * is ACKed. For Reno it is MUST to prevent false
                 * fast retransmits (RFC2582). SACK TCP is safe. */
                tcp_moderate_cwnd(tp);
+               if (!tcp_any_retrans_done(sk))
+                       tp->retrans_stamp = 0;
                return true;
        }
        tcp_set_ca_state(sk, TCP_CA_Open);
@@ -2430,35 +2461,6 @@ static bool tcp_try_undo_dsack(struct sock *sk)
        return false;
 }
 
-/* We can clear retrans_stamp when there are no retransmissions in the
- * window. It would seem that it is trivially available for us in
- * tp->retrans_out, however, that kind of assumptions doesn't consider
- * what will happen if errors occur when sending retransmission for the
- * second time. ...It could the that such segment has only
- * TCPCB_EVER_RETRANS set at the present time. It seems that checking
- * the head skb is enough except for some reneging corner cases that
- * are not worth the effort.
- *
- * Main reason for all this complexity is the fact that connection dying
- * time now depends on the validity of the retrans_stamp, in particular,
- * that successive retransmissions of a segment must not advance
- * retrans_stamp under any conditions.
- */
-static bool tcp_any_retrans_done(const struct sock *sk)
-{
-       const struct tcp_sock *tp = tcp_sk(sk);
-       struct sk_buff *skb;
-
-       if (tp->retrans_out)
-               return true;
-
-       skb = tcp_write_queue_head(sk);
-       if (unlikely(skb && TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS))
-               return true;
-
-       return false;
-}
-
 /* Undo during loss recovery after partial ACK or using F-RTO. */
 static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo)
 {
@@ -5229,7 +5231,7 @@ slow_path:
        if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb))
                goto csum_error;
 
-       if (!th->ack && !th->rst)
+       if (!th->ack && !th->rst && !th->syn)
                goto discard;
 
        /*
@@ -5648,7 +5650,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                        goto discard;
        }
 
-       if (!th->ack && !th->rst)
+       if (!th->ack && !th->rst && !th->syn)
                goto discard;
 
        if (!tcp_validate_incoming(sk, skb, th, 0))
index 94d1a7757ff7462edf6c32406df7187b4839bf4f..147be202429064d03b34405dba575c8d002b267c 100644 (file)
@@ -206,8 +206,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        inet->inet_dport = usin->sin_port;
        inet->inet_daddr = daddr;
 
-       inet_set_txhash(sk);
-
        inet_csk(sk)->icsk_ext_hdr_len = 0;
        if (inet_opt)
                inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
@@ -224,6 +222,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (err)
                goto failure;
 
+       inet_set_txhash(sk);
+
        rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
                               inet->inet_sport, inet->inet_dport, sk);
        if (IS_ERR(rt)) {
@@ -598,7 +598,10 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
        if (th->rst)
                return;
 
-       if (skb_rtable(skb)->rt_type != RTN_LOCAL)
+       /* If sk not NULL, it means we did a successful lookup and incoming
+        * route had to be correct. prequeue might have dropped our dst.
+        */
+       if (!sk && skb_rtable(skb)->rt_type != RTN_LOCAL)
                return;
 
        /* Swap the send and the receive. */
index 3af21296d96788b899daaa25562301e38036e802..a3d453b94747c22dd0fad07dfe606fdd11c414b1 100644 (file)
@@ -2126,7 +2126,7 @@ bool tcp_schedule_loss_probe(struct sock *sk)
 static bool skb_still_in_host_queue(const struct sock *sk,
                                    const struct sk_buff *skb)
 {
-       if (unlikely(skb_fclone_busy(skb))) {
+       if (unlikely(skb_fclone_busy(sk, skb))) {
                NET_INC_STATS_BH(sock_net(sk),
                                 LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES);
                return true;
index 507310ef4b5681bd8e59ba779e0560ecc3e5d04e..6480cea7aa53a6df85a970279b82e3b9ed5a33e6 100644 (file)
@@ -58,7 +58,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
                skb->encap_hdr_csum = 1;
 
        /* segment inner packet. */
-       enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
+       enc_features = skb->dev->hw_enc_features & features;
        segs = gso_inner_segment(skb, enc_features);
        if (IS_ERR_OR_NULL(segs)) {
                skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
index 725c763270a067e3945ec3056c4f5893cf9f7060..0169ccf5aa4fec8f691ea3bed77b4c7e5587d2a5 100644 (file)
@@ -4531,6 +4531,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
        }
 
        write_unlock_bh(&idev->lock);
+       inet6_ifinfo_notify(RTM_NEWLINK, idev);
        addrconf_verify_rtnl();
        return 0;
 }
index 12c3c8ef3849467296ced452089008872e64083f..0e32d2e1bdbfecabd3ae7e8ddb33a99f51cd7b51 100644 (file)
@@ -502,11 +502,11 @@ static int ip6gre_rcv(struct sk_buff *skb)
 
                skb->protocol = gre_proto;
                /* WCCP version 1 and 2 protocol decoding.
-                * - Change protocol to IP
+                * - Change protocol to IPv6
                 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
                 */
                if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
-                       skb->protocol = htons(ETH_P_IP);
+                       skb->protocol = htons(ETH_P_IPV6);
                        if ((*(h + offset) & 0xF0) != 0x40)
                                offset += 4;
                }
@@ -961,8 +961,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
        else
                dev->flags &= ~IFF_POINTOPOINT;
 
-       dev->iflink = p->link;
-
        /* Precalculate GRE options length */
        if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
                if (t->parms.o_flags&GRE_CSUM)
@@ -1272,6 +1270,7 @@ static int ip6gre_tunnel_init(struct net_device *dev)
                u64_stats_init(&ip6gre_tunnel_stats->syncp);
        }
 
+       dev->iflink = tunnel->parms.link;
 
        return 0;
 }
@@ -1481,6 +1480,8 @@ static int ip6gre_tap_init(struct net_device *dev)
        if (!dev->tstats)
                return -ENOMEM;
 
+       dev->iflink = tunnel->parms.link;
+
        return 0;
 }
 
index 91014d32488ded4a7eeb0e00d27ee925bc48f8da..01e12d0d8fcc9284403629fd17d7de010463d480 100644 (file)
@@ -69,7 +69,8 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        int nhoff;
 
        if (unlikely(skb_shinfo(skb)->gso_type &
-                    ~(SKB_GSO_UDP |
+                    ~(SKB_GSO_TCPV4 |
+                      SKB_GSO_UDP |
                       SKB_GSO_DODGY |
                       SKB_GSO_TCP_ECN |
                       SKB_GSO_GRE |
@@ -90,7 +91,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 
        encap = SKB_GSO_CB(skb)->encap_level > 0;
        if (encap)
-               features = skb->dev->hw_enc_features & netif_skb_features(skb);
+               features &= skb->dev->hw_enc_features;
        SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h);
 
        ipv6h = ipv6_hdr(skb);
index 9409887fb664dd78d13937b89ea1b5044afdbc94..9cb94cfa0ae71d05a5bd924e58eb225e21dbb62d 100644 (file)
@@ -272,9 +272,6 @@ static int ip6_tnl_create2(struct net_device *dev)
        int err;
 
        t = netdev_priv(dev);
-       err = ip6_tnl_dev_init(dev);
-       if (err < 0)
-               goto out;
 
        err = register_netdevice(dev);
        if (err < 0)
@@ -1462,6 +1459,7 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
 
 
 static const struct net_device_ops ip6_tnl_netdev_ops = {
+       .ndo_init       = ip6_tnl_dev_init,
        .ndo_uninit     = ip6_tnl_dev_uninit,
        .ndo_start_xmit = ip6_tnl_xmit,
        .ndo_do_ioctl   = ip6_tnl_ioctl,
@@ -1546,16 +1544,10 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
        struct ip6_tnl *t = netdev_priv(dev);
        struct net *net = dev_net(dev);
        struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
-       int err = ip6_tnl_dev_init_gen(dev);
-
-       if (err)
-               return err;
 
        t->parms.proto = IPPROTO_IPV6;
        dev_hold(dev);
 
-       ip6_tnl_link_config(t);
-
        rcu_assign_pointer(ip6n->tnls_wc[0], t);
        return 0;
 }
index b04ed72c454247886d7d99ae5c9e36e949b48cd1..8db6c98fe21858f4b3f630af277a0137e438aa8d 100644 (file)
@@ -79,15 +79,13 @@ int udp_tunnel6_xmit_skb(struct socket *sock, struct dst_entry *dst,
        uh->source = src_port;
 
        uh->len = htons(skb->len);
-       uh->check = 0;
 
        memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
        IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED
                            | IPSKB_REROUTED);
        skb_dst_set(skb, dst);
 
-       udp6_set_csum(udp_get_no_check6_tx(sk), skb, &inet6_sk(sk)->saddr,
-                     &sk->sk_v6_daddr, skb->len);
+       udp6_set_csum(udp_get_no_check6_tx(sk), skb, saddr, daddr, skb->len);
 
        __skb_push(skb, sizeof(*ip6h));
        skb_reset_network_header(skb);
index d440bb585524d72202f809ebd1f0cb4ee8b7cc79..bcda14de7f84822a17b382a6256e49b665ed7a83 100644 (file)
@@ -172,10 +172,6 @@ static int vti6_tnl_create2(struct net_device *dev)
        struct vti6_net *ip6n = net_generic(net, vti6_net_id);
        int err;
 
-       err = vti6_dev_init(dev);
-       if (err < 0)
-               goto out;
-
        err = register_netdevice(dev);
        if (err < 0)
                goto out;
@@ -783,6 +779,7 @@ static int vti6_change_mtu(struct net_device *dev, int new_mtu)
 }
 
 static const struct net_device_ops vti6_netdev_ops = {
+       .ndo_init       = vti6_dev_init,
        .ndo_uninit     = vti6_dev_uninit,
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
@@ -852,16 +849,10 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev)
        struct ip6_tnl *t = netdev_priv(dev);
        struct net *net = dev_net(dev);
        struct vti6_net *ip6n = net_generic(net, vti6_net_id);
-       int err = vti6_dev_init_gen(dev);
-
-       if (err)
-               return err;
 
        t->parms.proto = IPPROTO_IPV6;
        dev_hold(dev);
 
-       vti6_link_config(t);
-
        rcu_assign_pointer(ip6n->tnls_wc[0], t);
        return 0;
 }
@@ -914,6 +905,15 @@ static int vti6_newlink(struct net *src_net, struct net_device *dev,
        return vti6_tnl_create2(dev);
 }
 
+static void vti6_dellink(struct net_device *dev, struct list_head *head)
+{
+       struct net *net = dev_net(dev);
+       struct vti6_net *ip6n = net_generic(net, vti6_net_id);
+
+       if (dev != ip6n->fb_tnl_dev)
+               unregister_netdevice_queue(dev, head);
+}
+
 static int vti6_changelink(struct net_device *dev, struct nlattr *tb[],
                           struct nlattr *data[])
 {
@@ -989,6 +989,7 @@ static struct rtnl_link_ops vti6_link_ops __read_mostly = {
        .setup          = vti6_dev_setup,
        .validate       = vti6_validate,
        .newlink        = vti6_newlink,
+       .dellink        = vti6_dellink,
        .changelink     = vti6_changelink,
        .get_size       = vti6_get_size,
        .fill_info      = vti6_fill_info,
@@ -1029,6 +1030,7 @@ static int __net_init vti6_init_net(struct net *net)
        if (!ip6n->fb_tnl_dev)
                goto err_alloc_dev;
        dev_net_set(ip6n->fb_tnl_dev, net);
+       ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops;
 
        err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
        if (err < 0)
index 0171f08325c3ff3991485297de4c532fe6992bf8..1a01d79b86980b1bc00d3692a061f614e7107773 100644 (file)
@@ -1439,6 +1439,10 @@ reg_pernet_fail:
 
 void ip6_mr_cleanup(void)
 {
+       rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
+#ifdef CONFIG_IPV6_PIMSM_V2
+       inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
+#endif
        unregister_netdevice_notifier(&ip6_mr_notifier);
        unregister_pernet_subsys(&ip6mr_net_ops);
        kmem_cache_destroy(mrt_cachep);
index 9648de2b67458201ad9435b6972b05191c88c075..ed2c4e400b46bf762ff5379c3d62d69d940e5dd4 100644 (file)
@@ -1550,7 +1550,7 @@ static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb,
        hdr->daddr = *daddr;
 }
 
-static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
+static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
 {
        struct net_device *dev = idev->dev;
        struct net *net = dev_net(dev);
@@ -1561,13 +1561,13 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
        const struct in6_addr *saddr;
        int hlen = LL_RESERVED_SPACE(dev);
        int tlen = dev->needed_tailroom;
+       unsigned int size = mtu + hlen + tlen;
        int err;
        u8 ra[8] = { IPPROTO_ICMPV6, 0,
                     IPV6_TLV_ROUTERALERT, 2, 0, 0,
                     IPV6_TLV_PADN, 0 };
 
        /* we assume size > sizeof(ra) here */
-       size += hlen + tlen;
        /* limit our allocations to order-0 page */
        size = min_t(int, size, SKB_MAX_ORDER(0, 0));
        skb = sock_alloc_send_skb(sk, size, 1, &err);
@@ -1576,6 +1576,8 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
                return NULL;
 
        skb->priority = TC_PRIO_CONTROL;
+       skb->reserved_tailroom = skb_end_offset(skb) -
+                                min(mtu, skb_end_offset(skb));
        skb_reserve(skb, hlen);
 
        if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
@@ -1690,8 +1692,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
        return skb;
 }
 
-#define AVAILABLE(skb) ((skb) ? ((skb)->dev ? (skb)->dev->mtu - (skb)->len : \
-       skb_tailroom(skb)) : 0)
+#define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0)
 
 static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
        int type, int gdeleted, int sdeleted, int crsend)
index 5f5f0438d74d9b76596b1e5633189402c5925d80..015eb8a80766f477ed797d496762f4fb2e6f7661 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include <linux/module.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
 #include <net/ip6_fib.h>
 #include <net/ip6_checksum.h>
 #include <linux/netfilter_ipv6.h>
+#include <net/netfilter/ipv6/nf_reject.h>
 
-void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
+const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
+                                             struct tcphdr *otcph,
+                                             unsigned int *otcplen, int hook)
 {
-       struct sk_buff *nskb;
-       struct tcphdr otcph, *tcph;
-       unsigned int otcplen, hh_len;
-       int tcphoff, needs_ack;
        const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
-       struct ipv6hdr *ip6h;
-#define DEFAULT_TOS_VALUE      0x0U
-       const __u8 tclass = DEFAULT_TOS_VALUE;
-       struct dst_entry *dst = NULL;
        u8 proto;
        __be16 frag_off;
-       struct flowi6 fl6;
-
-       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
-           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
-               pr_debug("addr is not unicast.\n");
-               return;
-       }
+       int tcphoff;
 
        proto = oip6h->nexthdr;
-       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
+       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
+                                  &proto, &frag_off);
 
        if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
                pr_debug("Cannot get TCP header.\n");
-               return;
+               return NULL;
        }
 
-       otcplen = oldskb->len - tcphoff;
+       *otcplen = oldskb->len - tcphoff;
 
        /* IP header checks: fragment, too short. */
-       if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
-               pr_debug("proto(%d) != IPPROTO_TCP, "
-                        "or too short. otcplen = %d\n",
-                        proto, otcplen);
-               return;
+       if (proto != IPPROTO_TCP || *otcplen < sizeof(struct tcphdr)) {
+               pr_debug("proto(%d) != IPPROTO_TCP or too short (len = %d)\n",
+                        proto, *otcplen);
+               return NULL;
        }
 
-       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
-               BUG();
+       otcph = skb_header_pointer(oldskb, tcphoff, sizeof(struct tcphdr),
+                                  otcph);
+       if (otcph == NULL)
+               return NULL;
 
        /* No RST for RST. */
-       if (otcph.rst) {
+       if (otcph->rst) {
                pr_debug("RST is set\n");
-               return;
+               return NULL;
        }
 
        /* Check checksum. */
        if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
                pr_debug("TCP checksum is invalid\n");
-               return;
+               return NULL;
        }
 
-       memset(&fl6, 0, sizeof(fl6));
-       fl6.flowi6_proto = IPPROTO_TCP;
-       fl6.saddr = oip6h->daddr;
-       fl6.daddr = oip6h->saddr;
-       fl6.fl6_sport = otcph.dest;
-       fl6.fl6_dport = otcph.source;
-       security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
-       dst = ip6_route_output(net, NULL, &fl6);
-       if (dst == NULL || dst->error) {
-               dst_release(dst);
-               return;
-       }
-       dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
-       if (IS_ERR(dst))
-               return;
-
-       hh_len = (dst->dev->hard_header_len + 15)&~15;
-       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
-                        + sizeof(struct tcphdr) + dst->trailer_len,
-                        GFP_ATOMIC);
-
-       if (!nskb) {
-               net_dbg_ratelimited("cannot alloc skb\n");
-               dst_release(dst);
-               return;
-       }
-
-       skb_dst_set(nskb, dst);
+       return otcph;
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_get);
 
-       skb_reserve(nskb, hh_len + dst->header_len);
+struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb,
+                                    const struct sk_buff *oldskb,
+                                    __be16 protocol, int hoplimit)
+{
+       struct ipv6hdr *ip6h;
+       const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
+#define DEFAULT_TOS_VALUE      0x0U
+       const __u8 tclass = DEFAULT_TOS_VALUE;
 
        skb_put(nskb, sizeof(struct ipv6hdr));
        skb_reset_network_header(nskb);
        ip6h = ipv6_hdr(nskb);
        ip6_flow_hdr(ip6h, tclass, 0);
-       ip6h->hop_limit = ip6_dst_hoplimit(dst);
-       ip6h->nexthdr = IPPROTO_TCP;
+       ip6h->hop_limit = hoplimit;
+       ip6h->nexthdr = protocol;
        ip6h->saddr = oip6h->daddr;
        ip6h->daddr = oip6h->saddr;
 
+       nskb->protocol = htons(ETH_P_IPV6);
+
+       return ip6h;
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip6hdr_put);
+
+void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
+                             const struct sk_buff *oldskb,
+                             const struct tcphdr *oth, unsigned int otcplen)
+{
+       struct tcphdr *tcph;
+       int needs_ack;
+
        skb_reset_transport_header(nskb);
        tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
        /* Truncate to length (no data) */
        tcph->doff = sizeof(struct tcphdr)/4;
-       tcph->source = otcph.dest;
-       tcph->dest = otcph.source;
+       tcph->source = oth->dest;
+       tcph->dest = oth->source;
 
-       if (otcph.ack) {
+       if (oth->ack) {
                needs_ack = 0;
-               tcph->seq = otcph.ack_seq;
+               tcph->seq = oth->ack_seq;
                tcph->ack_seq = 0;
        } else {
                needs_ack = 1;
-               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
-                                     + otcplen - (otcph.doff<<2));
+               tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
+                                     otcplen - (oth->doff<<2));
                tcph->seq = 0;
        }
 
@@ -137,6 +125,63 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
                                      sizeof(struct tcphdr), IPPROTO_TCP,
                                      csum_partial(tcph,
                                                   sizeof(struct tcphdr), 0));
+}
+EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);
+
+void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
+{
+       struct sk_buff *nskb;
+       struct tcphdr _otcph;
+       const struct tcphdr *otcph;
+       unsigned int otcplen, hh_len;
+       const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
+       struct ipv6hdr *ip6h;
+       struct dst_entry *dst = NULL;
+       struct flowi6 fl6;
+
+       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
+           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
+               pr_debug("addr is not unicast.\n");
+               return;
+       }
+
+       otcph = nf_reject_ip6_tcphdr_get(oldskb, &_otcph, &otcplen, hook);
+       if (!otcph)
+               return;
+
+       memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_proto = IPPROTO_TCP;
+       fl6.saddr = oip6h->daddr;
+       fl6.daddr = oip6h->saddr;
+       fl6.fl6_sport = otcph->dest;
+       fl6.fl6_dport = otcph->source;
+       security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
+       dst = ip6_route_output(net, NULL, &fl6);
+       if (dst == NULL || dst->error) {
+               dst_release(dst);
+               return;
+       }
+       dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+       if (IS_ERR(dst))
+               return;
+
+       hh_len = (dst->dev->hard_header_len + 15)&~15;
+       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
+                        + sizeof(struct tcphdr) + dst->trailer_len,
+                        GFP_ATOMIC);
+
+       if (!nskb) {
+               net_dbg_ratelimited("cannot alloc skb\n");
+               dst_release(dst);
+               return;
+       }
+
+       skb_dst_set(nskb, dst);
+
+       skb_reserve(nskb, hh_len + dst->header_len);
+       ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP,
+                                   ip6_dst_hoplimit(dst));
+       nf_reject_ip6_tcphdr_put(nskb, oldskb, otcph, otcplen);
 
        nf_ct_attach(nskb, oldskb);
 
@@ -161,3 +206,5 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
                ip6_local_out(nskb);
 }
 EXPORT_SYMBOL_GPL(nf_send_reset6);
+
+MODULE_LICENSE("GPL");
index 556262f407616ee3a20bb10888e02ca1570d73c0..529c119cbb14c9eff00c7a5fb63148ef0bc9f740 100644 (file)
@@ -25,6 +25,7 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr,
        struct nf_nat_range range;
        unsigned int verdict;
 
+       memset(&range, 0, sizeof(range));
        range.flags = priv->flags;
 
        verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out);
@@ -39,6 +40,7 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = {
        .eval           = nft_masq_ipv6_eval,
        .init           = nft_masq_init,
        .dump           = nft_masq_dump,
+       .validate       = nft_masq_validate,
 };
 
 static struct nft_expr_type nft_masq_ipv6_type __read_mostly = {
index fc24c390af0541050782c76434ccbbf9e00c24f0..97f41a3e68d98b89d6b8f643780f8a883bd46f55 100644 (file)
@@ -3,11 +3,45 @@
  * not configured or static.  These functions are needed by GSO/GRO implementation.
  */
 #include <linux/export.h>
+#include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/ip6_fib.h>
 #include <net/addrconf.h>
 #include <net/secure_seq.h>
 
+/* This function exists only for tap drivers that must support broken
+ * clients requesting UFO without specifying an IPv6 fragment ID.
+ *
+ * This is similar to ipv6_select_ident() but we use an independent hash
+ * seed to limit information leakage.
+ *
+ * The network header must be set before calling this.
+ */
+void ipv6_proxy_select_ident(struct sk_buff *skb)
+{
+       static u32 ip6_proxy_idents_hashrnd __read_mostly;
+       struct in6_addr buf[2];
+       struct in6_addr *addrs;
+       u32 hash, id;
+
+       addrs = skb_header_pointer(skb,
+                                  skb_network_offset(skb) +
+                                  offsetof(struct ipv6hdr, saddr),
+                                  sizeof(buf), buf);
+       if (!addrs)
+               return;
+
+       net_get_random_once(&ip6_proxy_idents_hashrnd,
+                           sizeof(ip6_proxy_idents_hashrnd));
+
+       hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd);
+       hash = __ipv6_addr_jhash(&addrs[0], hash);
+
+       id = ip_idents_reserve(hash, 1);
+       skb_shinfo(skb)->ip6_frag_id = htonl(id);
+}
+EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
+
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 {
        u16 offset = sizeof(struct ipv6hdr);
index 58e5b4710127a996e31b9d2faa97feafc611e39f..a24557a1c1d8b6da7ee51e862ae4b847d9e744d6 100644 (file)
@@ -195,10 +195,8 @@ static int ipip6_tunnel_create(struct net_device *dev)
        struct sit_net *sitn = net_generic(net, sit_net_id);
        int err;
 
-       err = ipip6_tunnel_init(dev);
-       if (err < 0)
-               goto out;
-       ipip6_tunnel_clone_6rd(dev, sitn);
+       memcpy(dev->dev_addr, &t->parms.iph.saddr, 4);
+       memcpy(dev->broadcast, &t->parms.iph.daddr, 4);
 
        if ((__force u16)t->parms.i_flags & SIT_ISATAP)
                dev->priv_flags |= IFF_ISATAP;
@@ -207,7 +205,8 @@ static int ipip6_tunnel_create(struct net_device *dev)
        if (err < 0)
                goto out;
 
-       strcpy(t->parms.name, dev->name);
+       ipip6_tunnel_clone_6rd(dev, sitn);
+
        dev->rtnl_link_ops = &sit_link_ops;
 
        dev_hold(dev);
@@ -1330,6 +1329,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 }
 
 static const struct net_device_ops ipip6_netdev_ops = {
+       .ndo_init       = ipip6_tunnel_init,
        .ndo_uninit     = ipip6_tunnel_uninit,
        .ndo_start_xmit = sit_tunnel_xmit,
        .ndo_do_ioctl   = ipip6_tunnel_ioctl,
@@ -1378,9 +1378,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
 
        tunnel->dev = dev;
        tunnel->net = dev_net(dev);
-
-       memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
-       memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
+       strcpy(tunnel->parms.name, dev->name);
 
        ipip6_tunnel_bind_dev(dev);
        dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
@@ -1405,7 +1403,6 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
 
        tunnel->dev = dev;
        tunnel->net = dev_net(dev);
-       strcpy(tunnel->parms.name, dev->name);
 
        iph->version            = 4;
        iph->protocol           = IPPROTO_IPV6;
index 831495529b829c8ff4bc4ec3a8f0e7cf33b011b5..dc495ae2ead05aca0190bcab8c2d95b58beb2ac9 100644 (file)
@@ -200,8 +200,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        sk->sk_v6_daddr = usin->sin6_addr;
        np->flow_label = fl6.flowlabel;
 
-       ip6_set_txhash(sk);
-
        /*
         *      TCP over IPv4
         */
@@ -297,6 +295,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        if (err)
                goto late_failure;
 
+       ip6_set_txhash(sk);
+
        if (!tp->write_seq && likely(!tp->repair))
                tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
                                                             sk->sk_v6_daddr.s6_addr32,
@@ -903,7 +903,10 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
        if (th->rst)
                return;
 
-       if (!ipv6_unicast_destination(skb))
+       /* If sk not NULL, it means we did a successful lookup and incoming
+        * route had to be correct. prequeue might have dropped our dst.
+        */
+       if (!sk && !ipv6_unicast_destination(skb))
                return;
 
 #ifdef CONFIG_TCP_MD5SIG
index ac49f84fe2c34026b7af5392df06fc232ea3b9e1..5f983644373a230890b25189865af73f5e2b3b44 100644 (file)
@@ -170,8 +170,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
                case IPPROTO_DCCP:
                        if (!onlyproto && (nh + offset + 4 < skb->data ||
                             pskb_may_pull(skb, nh + offset + 4 - skb->data))) {
-                               __be16 *ports = (__be16 *)exthdr;
+                               __be16 *ports;
 
+                               nh = skb_network_header(skb);
+                               ports = (__be16 *)(nh + offset);
                                fl6->fl6_sport = ports[!!reverse];
                                fl6->fl6_dport = ports[!reverse];
                        }
@@ -180,8 +182,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 
                case IPPROTO_ICMPV6:
                        if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
-                               u8 *icmp = (u8 *)exthdr;
+                               u8 *icmp;
 
+                               nh = skb_network_header(skb);
+                               icmp = (u8 *)(nh + offset);
                                fl6->fl6_icmp_type = icmp[0];
                                fl6->fl6_icmp_code = icmp[1];
                        }
@@ -192,8 +196,9 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
                case IPPROTO_MH:
                        if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
                                struct ip6_mh *mh;
-                               mh = (struct ip6_mh *)exthdr;
 
+                               nh = skb_network_header(skb);
+                               mh = (struct ip6_mh *)(nh + offset);
                                fl6->fl6_mh_type = mh->ip6mh_type;
                        }
                        fl6->flowi6_proto = nexthdr;
index 91729b807c7d041ae379e89df335acefe5218635..1b095ca37aa46bd86a534a5d7eff4824d65b2ef2 100644 (file)
@@ -1764,6 +1764,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
        struct ipxhdr *ipx = NULL;
        struct sk_buff *skb;
        int copied, rc;
+       bool locked = true;
 
        lock_sock(sk);
        /* put the autobinding in */
@@ -1790,6 +1791,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
        if (sock_flag(sk, SOCK_ZAPPED))
                goto out;
 
+       release_sock(sk);
+       locked = false;
        skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
                                flags & MSG_DONTWAIT, &rc);
        if (!skb) {
@@ -1826,7 +1829,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 out_free:
        skb_free_datagram(sk, skb);
 out:
-       release_sock(sk);
+       if (locked)
+               release_sock(sk);
        return rc;
 }
 
index 92fafd485deb610cad0e6a03ac41ede8aed29553..3f3a6cbdceb7e20054a9c427de10682cf67478b9 100644 (file)
@@ -1064,8 +1064,6 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
 
        if (sk->sk_state != TCP_ESTABLISHED) {
                sock->state = SS_UNCONNECTED;
-               if (sk->sk_prot->disconnect(sk, flags))
-                       sock->state = SS_DISCONNECTING;
                err = sock_error(sk);
                if (!err)
                        err = -ECONNRESET;
index ec24378caaafaf333152e856aa0e2e920ddbb13f..09d9caaec59112f40b060951ae16796388e2e741 100644 (file)
@@ -53,6 +53,9 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
                __aligned(__alignof__(struct aead_request));
        struct aead_request *aead_req = (void *) aead_req_data;
 
+       if (data_len == 0)
+               return -EINVAL;
+
        memset(aead_req, 0, sizeof(aead_req_data));
 
        sg_init_one(&pt, data, data_len);
index fb6a1502b6dfa64980305c3bba380408ef3dde14..343da1e35025199bbef7d6680e0770fbdc3eadd2 100644 (file)
@@ -3458,7 +3458,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
        rcu_read_lock();
        chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
        if (chanctx_conf) {
-               *chandef = chanctx_conf->def;
+               *chandef = sdata->vif.bss_conf.chandef;
                ret = 0;
        } else if (local->open_count > 0 &&
                   local->open_count == local->monitors &&
index 56b53571c8077ae5a3660449cb0afeb81375028c..509bc157ce5551700db59e380d180c486b44f097 100644 (file)
@@ -805,7 +805,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 
        memset(&params, 0, sizeof(params));
        memset(&csa_ie, 0, sizeof(csa_ie));
-       err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon,
+       err = ieee80211_parse_ch_switch_ie(sdata, elems,
                                           ifibss->chandef.chan->band,
                                           sta_flags, ifibss->bssid, &csa_ie);
        /* can't switch to destination channel, fail */
index c2aaec4dfcf0ea38da3e45cfdc7b8ad0ecef5fc8..8c68da30595df7793545200c9ce102ae2d5e612d 100644 (file)
@@ -1642,7 +1642,6 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
  * ieee80211_parse_ch_switch_ie - parses channel switch IEs
  * @sdata: the sdata of the interface which has received the frame
  * @elems: parsed 802.11 elements received with the frame
- * @beacon: indicates if the frame was a beacon or probe response
  * @current_band: indicates the current band
  * @sta_flags: contains information about own capabilities and restrictions
  *     to decide which channel switch announcements can be accepted. Only the
@@ -1656,7 +1655,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
  * Return: 0 on success, <0 on error and >0 if there is nothing to parse.
  */
 int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
-                                struct ieee802_11_elems *elems, bool beacon,
+                                struct ieee802_11_elems *elems,
                                 enum ieee80211_band current_band,
                                 u32 sta_flags, u8 *bssid,
                                 struct ieee80211_csa_ie *csa_ie);
index af237223a8cd9bd3aa6121576650238d42e3bbb0..653f5eb07a27f4432429a8fbbc4b32e7200cf4c3 100644 (file)
@@ -766,10 +766,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        int i, flushed;
        struct ps_data *ps;
        struct cfg80211_chan_def chandef;
+       bool cancel_scan;
 
        clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
-       if (rcu_access_pointer(local->scan_sdata) == sdata)
+       cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
+       if (cancel_scan)
                ieee80211_scan_cancel(local);
 
        /*
@@ -898,6 +900,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                list_del(&sdata->u.vlan.list);
                mutex_unlock(&local->mtx);
                RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
+               /* see comment in the default case below */
+               ieee80211_free_keys(sdata, true);
                /* no need to tell driver */
                break;
        case NL80211_IFTYPE_MONITOR:
@@ -923,17 +927,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                /*
                 * When we get here, the interface is marked down.
                 * Free the remaining keys, if there are any
-                * (shouldn't be, except maybe in WDS mode?)
+                * (which can happen in AP mode if userspace sets
+                * keys before the interface is operating, and maybe
+                * also in WDS mode)
                 *
                 * Force the key freeing to always synchronize_net()
                 * to wait for the RX path in case it is using this
-                * interface enqueuing frames at this very time on
+                * interface enqueuing frames at this very time on
                 * another CPU.
                 */
                ieee80211_free_keys(sdata, true);
-
-               /* fall through */
-       case NL80211_IFTYPE_AP:
                skb_queue_purge(&sdata->skb_queue);
        }
 
@@ -991,6 +994,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
        ieee80211_recalc_ps(local, -1);
 
+       if (cancel_scan)
+               flush_delayed_work(&local->scan_work);
+
        if (local->open_count == 0) {
                ieee80211_stop_device(local);
 
index e9f99c1e3fad5905682a61f978d9897833426fd0..0c8b2a77d312d5e3ad18f975ce808c44755c820b 100644 (file)
@@ -874,7 +874,7 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
 
        memset(&params, 0, sizeof(params));
        memset(&csa_ie, 0, sizeof(csa_ie));
-       err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band,
+       err = ieee80211_parse_ch_switch_ie(sdata, elems, band,
                                           sta_flags, sdata->vif.addr,
                                           &csa_ie);
        if (err < 0)
index 2de88704278b85b8d9ce47f2ef77905108d456e7..93af0f1c9d991a52d82cbc58bcd842415b22a04a 100644 (file)
@@ -1072,7 +1072,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 
        current_band = cbss->channel->band;
        memset(&csa_ie, 0, sizeof(csa_ie));
-       res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
+       res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
                                           ifmgd->flags,
                                           ifmgd->associated->bssid, &csa_ie);
        if (res < 0)
@@ -1168,7 +1168,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
        else
                mod_timer(&ifmgd->chswitch_timer,
-                         TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
+                         TU_TO_EXP_TIME((csa_ie.count - 1) *
+                                        cbss->beacon_interval));
 }
 
 static bool
index 8fdadfd94ba8576ae8bc0ee2e99e8c656c2f6a5b..6081329784dd4475ae95317dde31910efd760525 100644 (file)
@@ -448,7 +448,7 @@ static void rate_fixup_ratelist(struct ieee80211_vif *vif,
         */
        if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) {
                u32 basic_rates = vif->bss_conf.basic_rates;
-               s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0;
+               s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0;
 
                rate = &sband->bitrates[rates[0].idx];
 
index edde723f9f009e33388f5a6f89129f445fae37a2..2acab1bcaa4b377012a31c6354ceeb61fadbb171 100644 (file)
@@ -62,14 +62,14 @@ minstrel_stats_open(struct inode *inode, struct file *file)
        unsigned int i, tp, prob, eprob;
        char *p;
 
-       ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL);
+       ms = kmalloc(2048, GFP_KERNEL);
        if (!ms)
                return -ENOMEM;
 
        file->private_data = ms;
        p = ms->buf;
-       p += sprintf(p, "rate      throughput  ewma prob  this prob  "
-                       "this succ/attempt   success    attempts\n");
+       p += sprintf(p, "rate          tpt eprob *prob"
+                       "  *ok(*cum)        ok(      cum)\n");
        for (i = 0; i < mi->n_rates; i++) {
                struct minstrel_rate *mr = &mi->r[i];
                struct minstrel_rate_stats *mrs = &mi->r[i].stats;
@@ -86,8 +86,8 @@ minstrel_stats_open(struct inode *inode, struct file *file)
                prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
                eprob = MINSTREL_TRUNC(mrs->probability * 1000);
 
-               p += sprintf(p, "  %6u.%1u   %6u.%1u   %6u.%1u        "
-                               "   %3u(%3u)  %8llu    %8llu\n",
+               p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u"
+                               " %4u(%4u) %9llu(%9llu)\n",
                                tp / 10, tp % 10,
                                eprob / 10, eprob % 10,
                                prob / 10, prob % 10,
@@ -102,6 +102,8 @@ minstrel_stats_open(struct inode *inode, struct file *file)
                        mi->sample_packets);
        ms->len = p - ms->buf;
 
+       WARN_ON(ms->len + sizeof(*ms) > 2048);
+
        return 0;
 }
 
index df90ce2db00c042a31bf3cd79dab3cfefcacbc35..408fd8ab4eef7eaf5f39d643644969a3943c1b3f 100644 (file)
@@ -252,19 +252,16 @@ minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u8 index,
        cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp;
        cur_prob = mi->groups[cur_group].rates[cur_idx].probability;
 
-       tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
-       tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
-       tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
-       tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
-
-       while (j > 0 && (cur_thr > tmp_thr ||
-             (cur_thr == tmp_thr && cur_prob > tmp_prob))) {
-               j--;
+       do {
                tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
                tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
                tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
                tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
-       }
+               if (cur_thr < tmp_thr ||
+                   (cur_thr == tmp_thr && cur_prob <= tmp_prob))
+                       break;
+               j--;
+       } while (j > 0);
 
        if (j < MAX_THR_RATES - 1) {
                memmove(&tp_list[j + 1], &tp_list[j], (sizeof(*tp_list) *
index a72ad46f2a04b6e557044d52da1f033c7be2c531..d537bec9375463eb115b0f26260f8f3d03759596 100644 (file)
@@ -63,8 +63,8 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
                prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
                eprob = MINSTREL_TRUNC(mr->probability * 1000);
 
-               p += sprintf(p, "      %6u.%1u   %6u.%1u    %6u.%1u    "
-                               "%3u            %3u(%3u)  %8llu    %8llu\n",
+               p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u "
+                               "%3u %4u(%4u) %9llu(%9llu)\n",
                                tp / 10, tp % 10,
                                eprob / 10, eprob % 10,
                                prob / 10, prob % 10,
@@ -96,14 +96,15 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
                return ret;
        }
 
-       ms = kmalloc(sizeof(*ms) + 8192, GFP_KERNEL);
+       ms = kmalloc(8192, GFP_KERNEL);
        if (!ms)
                return -ENOMEM;
 
        file->private_data = ms;
        p = ms->buf;
-       p += sprintf(p, "type           rate     throughput  ewma prob   "
-                    "this prob  retry   this succ/attempt   success    attempts\n");
+       p += sprintf(p, "type           rate     tpt eprob *prob "
+                       "ret  *ok(*cum)        ok(      cum)\n");
+
 
        p = minstrel_ht_stats_dump(mi, max_mcs, p);
        for (i = 0; i < max_mcs; i++)
@@ -118,6 +119,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file)
                MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
        ms->len = p - ms->buf;
 
+       WARN_ON(ms->len + sizeof(*ms) > 8192);
+
        return nonseekable_open(inode, file);
 }
 
index b04ca4049c95f276aa4627501d5ced01e8a3b878..a37f9af634cb6d3c7bb73ada859473e0e085402d 100644 (file)
@@ -1678,11 +1678,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        sc = le16_to_cpu(hdr->seq_ctrl);
        frag = sc & IEEE80211_SCTL_FRAG;
 
-       if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
-                  is_multicast_ether_addr(hdr->addr1))) {
-               /* not fragmented */
+       if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
+               goto out;
+
+       if (is_multicast_ether_addr(hdr->addr1)) {
+               rx->local->dot11MulticastReceivedFrameCount++;
                goto out;
        }
+
        I802_DEBUG_INC(rx->local->rx_handlers_fragments);
 
        if (skb_linearize(rx->skb))
@@ -1775,10 +1778,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
  out:
        if (rx->sta)
                rx->sta->rx_packets++;
-       if (is_multicast_ether_addr(hdr->addr1))
-               rx->local->dot11MulticastReceivedFrameCount++;
-       else
-               ieee80211_led_rx(rx->local);
+       ieee80211_led_rx(rx->local);
        return RX_CONTINUE;
 }
 
index 6ab00907008461fb14d551b2633a8dbcd4fef623..efeba56c913bae0d7284bfc74862599a2ad2298b 100644 (file)
@@ -22,7 +22,7 @@
 #include "wme.h"
 
 int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
-                                struct ieee802_11_elems *elems, bool beacon,
+                                struct ieee802_11_elems *elems,
                                 enum ieee80211_band current_band,
                                 u32 sta_flags, u8 *bssid,
                                 struct ieee80211_csa_ie *csa_ie)
@@ -91,19 +91,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
                return -EINVAL;
        }
 
-       if (!beacon && sec_chan_offs) {
+       if (sec_chan_offs) {
                secondary_channel_offset = sec_chan_offs->sec_chan_offs;
-       } else if (beacon && ht_oper) {
-               secondary_channel_offset =
-                       ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
        } else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) {
-               /* If it's not a beacon, HT is enabled and the IE not present,
-                * it's 20 MHz, 802.11-2012 8.5.2.6:
-                *      This element [the Secondary Channel Offset Element] is
-                *      present when switching to a 40 MHz channel. It may be
-                *      present when switching to a 20 MHz channel (in which
-                *      case the secondary channel offset is set to SCN).
-                */
+               /* If the secondary channel offset IE is not present,
+                * we can't know what's the post-CSA offset, so the
+                * best we can do is use 20MHz.
+               */
                secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
        }
 
index 42f68cb8957e5a29d1a4e7965b65aff086bfe55e..bcda2ac7d84402f83d03f24390f22f2f32ea701e 100644 (file)
@@ -336,6 +336,7 @@ struct ieee80211_tx_latency_stat {
  * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
  *     AP only.
  * @cipher_scheme: optional cipher scheme for this station
+ * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed
  */
 struct sta_info {
        /* General information, mostly static */
index 0a3c171be5374d2b813a18a368a40053e619cbef..6dec088c2d0f77dff06bf6bbd8557d2f325bafa1 100644 (file)
@@ -1,4 +1,4 @@
 #
 # Makefile for MPLS.
 #
-obj-y += mpls_gso.o
+obj-$(CONFIG_NET_MPLS_GSO) += mpls_gso.o
index e28ed2ef5b0650faf5f3f0db950c319f4caa7c31..e3545f21a099b01b931cd863205a847acd336238 100644 (file)
@@ -48,7 +48,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
        __skb_push(skb, skb->mac_len);
 
        /* Segment inner packet. */
-       mpls_features = skb->dev->mpls_features & netif_skb_features(skb);
+       mpls_features = skb->dev->mpls_features & features;
        segs = skb_mac_gso_segment(skb, mpls_features);
 
 
@@ -59,8 +59,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
         * above pulled.  It will be re-pushed after returning
         * skb_mac_gso_segment(), an indirect caller of this function.
         */
-       __skb_push(skb, skb->data - skb_mac_header(skb));
-
+       __skb_pull(skb, skb->data - skb_mac_header(skb));
 out:
        return segs;
 }
index 912e5a05b79dbdc2de8aaa3729e08af01888dc4e..d259da3ce67a6b18f6e4a345a5729876e373efc0 100644 (file)
@@ -659,7 +659,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index)
        struct ip_set *set;
        struct ip_set_net *inst = ip_set_pernet(net);
 
-       if (index > inst->ip_set_max)
+       if (index >= inst->ip_set_max)
                return IPSET_INVALID_ID;
 
        nfnl_lock(NFNL_SUBSYS_IPSET);
@@ -1863,6 +1863,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
        if (*op < IP_SET_OP_VERSION) {
                /* Check the version at the beginning of operations */
                struct ip_set_req_version *req_version = data;
+
+               if (*len < sizeof(struct ip_set_req_version)) {
+                       ret = -EINVAL;
+                       goto done;
+               }
+
                if (req_version->version != IPSET_PROTOCOL) {
                        ret = -EPROTO;
                        goto done;
index 91f17c1eb8a20c0226e01c68e255acf118a6a4d0..bd90bf8107dacb4e7e0683110bb2146faf168b26 100644 (file)
@@ -316,7 +316,7 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
        if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
                                                  local))) {
                IP_VS_DBG_RL("We are crossing local and non-local addresses"
-                            " daddr=%pI4\n", &dest->addr.ip);
+                            " daddr=%pI4\n", &daddr);
                goto err_put;
        }
 
@@ -458,7 +458,7 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
        if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
                                                  local))) {
                IP_VS_DBG_RL("We are crossing local and non-local addresses"
-                            " daddr=%pI6\n", &dest->addr.in6);
+                            " daddr=%pI6\n", daddr);
                goto err_put;
        }
 
@@ -846,6 +846,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
                new_skb = skb_realloc_headroom(skb, max_headroom);
                if (!new_skb)
                        goto error;
+               if (skb->sk)
+                       skb_set_owner_w(new_skb, skb->sk);
                consume_skb(skb);
                skb = new_skb;
        }
index 44d1ea32570a07338dc39f34624bd823b6f76916..d87b6423ffb21e0f8f9b6ef25ef51c1cb5f54ad6 100644 (file)
@@ -213,7 +213,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
        {
 /* REPLY */
 /*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2   */
-/*syn*/           { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2 },
+/*syn*/           { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sSS, sIV, sS2 },
 /*
  *     sNO -> sIV      Never reached.
  *     sSS -> sS2      Simultaneous open
@@ -223,7 +223,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
  *     sFW -> sIV
  *     sCW -> sIV
  *     sLA -> sIV
- *     sTW -> sIV      Reopened connection, but server may not do it.
+ *     sTW -> sSS      Reopened connection, but server may have switched role
  *     sCL -> sIV
  */
 /*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2   */
index 556a0dfa4abc07f7ed7bde511e07db1a85c99ecd..66e8425dbfe77b11e41eb7c97c68f3778ee0c9e7 100644 (file)
@@ -1328,10 +1328,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
                        basechain->stats = stats;
                } else {
                        stats = netdev_alloc_pcpu_stats(struct nft_stats);
-                       if (IS_ERR(stats)) {
+                       if (stats == NULL) {
                                module_put(type->owner);
                                kfree(basechain);
-                               return PTR_ERR(stats);
+                               return -ENOMEM;
                        }
                        rcu_assign_pointer(basechain->stats, stats);
                }
@@ -3484,13 +3484,8 @@ static void nft_chain_commit_update(struct nft_trans *trans)
        }
 }
 
-/* Schedule objects for release via rcu to make sure no packets are accesing
- * removed rules.
- */
-static void nf_tables_commit_release_rcu(struct rcu_head *rt)
+static void nf_tables_commit_release(struct nft_trans *trans)
 {
-       struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
-
        switch (trans->msg_type) {
        case NFT_MSG_DELTABLE:
                nf_tables_table_destroy(&trans->ctx);
@@ -3612,10 +3607,11 @@ static int nf_tables_commit(struct sk_buff *skb)
                }
        }
 
+       synchronize_rcu();
+
        list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
                list_del(&trans->list);
-               trans->ctx.nla = NULL;
-               call_rcu(&trans->rcu_head, nf_tables_commit_release_rcu);
+               nf_tables_commit_release(trans);
        }
 
        nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
@@ -3623,13 +3619,8 @@ static int nf_tables_commit(struct sk_buff *skb)
        return 0;
 }
 
-/* Schedule objects for release via rcu to make sure no packets are accesing
- * aborted rules.
- */
-static void nf_tables_abort_release_rcu(struct rcu_head *rt)
+static void nf_tables_abort_release(struct nft_trans *trans)
 {
-       struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
-
        switch (trans->msg_type) {
        case NFT_MSG_NEWTABLE:
                nf_tables_table_destroy(&trans->ctx);
@@ -3725,11 +3716,12 @@ static int nf_tables_abort(struct sk_buff *skb)
                }
        }
 
+       synchronize_rcu();
+
        list_for_each_entry_safe_reverse(trans, next,
                                         &net->nft.commit_list, list) {
                list_del(&trans->list);
-               trans->ctx.nla = NULL;
-               call_rcu(&trans->rcu_head, nf_tables_abort_release_rcu);
+               nf_tables_abort_release(trans);
        }
 
        return 0;
@@ -3744,6 +3736,20 @@ static const struct nfnetlink_subsystem nf_tables_subsys = {
        .abort          = nf_tables_abort,
 };
 
+int nft_chain_validate_dependency(const struct nft_chain *chain,
+                                 enum nft_chain_type type)
+{
+       const struct nft_base_chain *basechain;
+
+       if (chain->flags & NFT_BASE_CHAIN) {
+               basechain = nft_base_chain(chain);
+               if (basechain->type->type != type)
+                       return -EOPNOTSUPP;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nft_chain_validate_dependency);
+
 /*
  * Loop detection - walk through the ruleset beginning at the destination chain
  * of a new jump until either the source chain is reached (loop) or all
index 6c5a915cfa758bb4d8187dac9dc606201e99b458..13c2e17bbe279e6660a0a04fc804a6e1dd0a7707 100644 (file)
@@ -47,6 +47,8 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = {
        [NFNLGRP_CONNTRACK_EXP_NEW]     = NFNL_SUBSYS_CTNETLINK_EXP,
        [NFNLGRP_CONNTRACK_EXP_UPDATE]  = NFNL_SUBSYS_CTNETLINK_EXP,
        [NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
+       [NFNLGRP_NFTABLES]              = NFNL_SUBSYS_NFTABLES,
+       [NFNLGRP_ACCT_QUOTA]            = NFNL_SUBSYS_ACCT,
 };
 
 void nfnl_lock(__u8 subsys_id)
@@ -464,7 +466,12 @@ static void nfnetlink_rcv(struct sk_buff *skb)
 static int nfnetlink_bind(int group)
 {
        const struct nfnetlink_subsystem *ss;
-       int type = nfnl_group2type[group];
+       int type;
+
+       if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
+               return -EINVAL;
+
+       type = nfnl_group2type[group];
 
        rcu_read_lock();
        ss = nfnetlink_get_subsys(type);
@@ -514,6 +521,9 @@ static int __init nfnetlink_init(void)
 {
        int i;
 
+       for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
+               BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
+
        for (i=0; i<NFNL_SUBSYS_COUNT; i++)
                mutex_init(&table[i].mutex);
 
index b1e3a05794169283ed50d1c0fb4f44d9e7753eeb..5f1be5ba35595abb3e96a4d7c9e16fe2c8f4bd8c 100644 (file)
@@ -43,7 +43,8 @@
 #define NFULNL_NLBUFSIZ_DEFAULT        NLMSG_GOODSIZE
 #define NFULNL_TIMEOUT_DEFAULT         100     /* every second */
 #define NFULNL_QTHRESH_DEFAULT         100     /* 100 packets */
-#define NFULNL_COPY_RANGE_MAX  0xFFFF  /* max packet size is limited by 16-bit struct nfattr nfa_len field */
+/* max packet size is limited by 16-bit struct nfattr nfa_len field */
+#define NFULNL_COPY_RANGE_MAX  (0xFFFF - NLA_HDRLEN)
 
 #define PRINTR(x, args...)     do { if (net_ratelimit()) \
                                     printk(x, ## args); } while (0);
@@ -252,6 +253,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
 
        case NFULNL_COPY_PACKET:
                inst->copy_mode = mode;
+               if (range == 0)
+                       range = NFULNL_COPY_RANGE_MAX;
                inst->copy_range = min_t(unsigned int,
                                         range, NFULNL_COPY_RANGE_MAX);
                break;
@@ -343,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
        return skb;
 }
 
-static int
+static void
 __nfulnl_send(struct nfulnl_instance *inst)
 {
-       int status = -1;
-
        if (inst->qlen > 1) {
                struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
                                                 NLMSG_DONE,
                                                 sizeof(struct nfgenmsg),
                                                 0);
-               if (!nlh)
+               if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
+                             inst->skb->len, skb_tailroom(inst->skb))) {
+                       kfree_skb(inst->skb);
                        goto out;
+               }
        }
-       status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
-                                  MSG_DONTWAIT);
-
+       nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
+                         MSG_DONTWAIT);
+out:
        inst->qlen = 0;
        inst->skb = NULL;
-out:
-       return status;
 }
 
 static void
@@ -649,7 +651,8 @@ nfulnl_log_packet(struct net *net,
                + nla_total_size(sizeof(u_int32_t))     /* gid */
                + nla_total_size(plen)                  /* prefix */
                + nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
-               + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
+               + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp))
+               + nla_total_size(sizeof(struct nfgenmsg));      /* NLMSG_DONE */
 
        if (in && skb_mac_header_was_set(skb)) {
                size +=   nla_total_size(skb->dev->hard_header_len)
@@ -678,8 +681,7 @@ nfulnl_log_packet(struct net *net,
                break;
 
        case NFULNL_COPY_PACKET:
-               if (inst->copy_range == 0
-                   || inst->copy_range > skb->len)
+               if (inst->copy_range > skb->len)
                        data_len = skb->len;
                else
                        data_len = inst->copy_range;
@@ -692,8 +694,7 @@ nfulnl_log_packet(struct net *net,
                goto unlock_and_release;
        }
 
-       if (inst->skb &&
-           size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) {
+       if (inst->skb && size > skb_tailroom(inst->skb)) {
                /* either the queue len is too high or we don't have
                 * enough room in the skb left. flush to userspace. */
                __nfulnl_flush(inst);
index a82077d9f59b2f49cf755bcc9c8754846cb64b3e..7c60ccd61a3e1685875adc9f2d2391e4957399c8 100644 (file)
@@ -665,7 +665,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
         * returned by nf_queue.  For instance, callers rely on -ECANCELED to
         * mean 'ignore this hook'.
         */
-       if (IS_ERR(segs))
+       if (IS_ERR_OR_NULL(segs))
                goto out_err;
        queued = 0;
        err = 0;
index 7e2683c8a44a9d778ab39c212f7204c28770091c..265e190f22187d83de1a9ed07913ef153cf1f03f 100644 (file)
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
-#include <asm/uaccess.h> /* for set_fs */
 #include <net/netfilter/nf_tables.h>
 
+static int nft_compat_chain_validate_dependency(const char *tablename,
+                                               const struct nft_chain *chain)
+{
+       const struct nft_base_chain *basechain;
+
+       if (!tablename || !(chain->flags & NFT_BASE_CHAIN))
+               return 0;
+
+       basechain = nft_base_chain(chain);
+       if (strcmp(tablename, "nat") == 0 &&
+           basechain->type->type != NFT_CHAIN_T_NAT)
+               return -EINVAL;
+
+       return 0;
+}
+
 union nft_entry {
        struct ipt_entry e4;
        struct ip6t_entry e6;
@@ -74,7 +89,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
                           struct xt_target *target, void *info,
                           union nft_entry *entry, u8 proto, bool inv)
 {
-       par->net        = &init_net;
+       par->net        = ctx->net;
        par->table      = ctx->table->name;
        switch (ctx->afi->family) {
        case AF_INET:
@@ -95,6 +110,8 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
                const struct nf_hook_ops *ops = &basechain->ops[0];
 
                par->hook_mask = 1 << ops->hooknum;
+       } else {
+               par->hook_mask = 0;
        }
        par->family     = ctx->afi->family;
 }
@@ -151,6 +168,10 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
        union nft_entry e = {};
        int ret;
 
+       ret = nft_compat_chain_validate_dependency(target->table, ctx->chain);
+       if (ret < 0)
+               goto err;
+
        target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
 
        if (ctx->nla[NFTA_RULE_COMPAT]) {
@@ -216,6 +237,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
 {
        struct xt_target *target = expr->ops->data;
        unsigned int hook_mask = 0;
+       int ret;
 
        if (ctx->chain->flags & NFT_BASE_CHAIN) {
                const struct nft_base_chain *basechain =
@@ -223,11 +245,13 @@ static int nft_target_validate(const struct nft_ctx *ctx,
                const struct nf_hook_ops *ops = &basechain->ops[0];
 
                hook_mask = 1 << ops->hooknum;
-               if (hook_mask & target->hooks)
-                       return 0;
+               if (!(hook_mask & target->hooks))
+                       return -EINVAL;
 
-               /* This target is being called from an invalid chain */
-               return -EINVAL;
+               ret = nft_compat_chain_validate_dependency(target->table,
+                                                          ctx->chain);
+               if (ret < 0)
+                       return ret;
        }
        return 0;
 }
@@ -272,7 +296,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
                          struct xt_match *match, void *info,
                          union nft_entry *entry, u8 proto, bool inv)
 {
-       par->net        = &init_net;
+       par->net        = ctx->net;
        par->table      = ctx->table->name;
        switch (ctx->afi->family) {
        case AF_INET:
@@ -293,6 +317,8 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
                const struct nf_hook_ops *ops = &basechain->ops[0];
 
                par->hook_mask = 1 << ops->hooknum;
+       } else {
+               par->hook_mask = 0;
        }
        par->family     = ctx->afi->family;
 }
@@ -320,6 +346,10 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
        union nft_entry e = {};
        int ret;
 
+       ret = nft_compat_chain_validate_dependency(match->table, ctx->chain);
+       if (ret < 0)
+               goto err;
+
        match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
 
        if (ctx->nla[NFTA_RULE_COMPAT]) {
@@ -379,6 +409,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
 {
        struct xt_match *match = expr->ops->data;
        unsigned int hook_mask = 0;
+       int ret;
 
        if (ctx->chain->flags & NFT_BASE_CHAIN) {
                const struct nft_base_chain *basechain =
@@ -386,11 +417,13 @@ static int nft_match_validate(const struct nft_ctx *ctx,
                const struct nf_hook_ops *ops = &basechain->ops[0];
 
                hook_mask = 1 << ops->hooknum;
-               if (hook_mask & match->hooks)
-                       return 0;
+               if (!(hook_mask & match->hooks))
+                       return -EINVAL;
 
-               /* This match is being called from an invalid chain */
-               return -EINVAL;
+               ret = nft_compat_chain_validate_dependency(match->table,
+                                                          ctx->chain);
+               if (ret < 0)
+                       return ret;
        }
        return 0;
 }
@@ -611,7 +644,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
        family = ctx->afi->family;
 
        /* Re-use the existing target if it's already loaded. */
-       list_for_each_entry(nft_target, &nft_match_list, head) {
+       list_for_each_entry(nft_target, &nft_target_list, head) {
                struct xt_target *target = nft_target->ops.data;
 
                if (strcmp(target->name, tg_name) == 0 &&
index 6637bab0056705d6cf9671f681b65b1c5166523a..d1ffd5eb3a9b5b86495b53adb5b8bc27c17921df 100644 (file)
@@ -26,6 +26,11 @@ int nft_masq_init(const struct nft_ctx *ctx,
                  const struct nlattr * const tb[])
 {
        struct nft_masq *priv = nft_expr_priv(expr);
+       int err;
+
+       err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
+       if (err < 0)
+               return err;
 
        if (tb[NFTA_MASQ_FLAGS] == NULL)
                return 0;
@@ -55,5 +60,12 @@ nla_put_failure:
 }
 EXPORT_SYMBOL_GPL(nft_masq_dump);
 
+int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
+                     const struct nft_data **data)
+{
+       return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
+}
+EXPORT_SYMBOL_GPL(nft_masq_validate);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
index 799550b476fbdeeadc2745aaff97fe5f2b197761..afe2b0b45ec41f82df6f2430958a4392aa5eb608 100644 (file)
@@ -95,7 +95,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
        u32 family;
        int err;
 
-       if (tb[NFTA_NAT_TYPE] == NULL)
+       err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
+       if (err < 0)
+               return err;
+
+       if (tb[NFTA_NAT_TYPE] == NULL ||
+           (tb[NFTA_NAT_REG_ADDR_MIN] == NULL &&
+            tb[NFTA_NAT_REG_PROTO_MIN] == NULL))
                return -EINVAL;
 
        switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
@@ -120,38 +126,44 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
        priv->family = family;
 
        if (tb[NFTA_NAT_REG_ADDR_MIN]) {
-               priv->sreg_addr_min = ntohl(nla_get_be32(
-                                               tb[NFTA_NAT_REG_ADDR_MIN]));
+               priv->sreg_addr_min =
+                       ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN]));
+
                err = nft_validate_input_register(priv->sreg_addr_min);
                if (err < 0)
                        return err;
-       }
 
-       if (tb[NFTA_NAT_REG_ADDR_MAX]) {
-               priv->sreg_addr_max = ntohl(nla_get_be32(
-                                               tb[NFTA_NAT_REG_ADDR_MAX]));
-               err = nft_validate_input_register(priv->sreg_addr_max);
-               if (err < 0)
-                       return err;
-       } else
-               priv->sreg_addr_max = priv->sreg_addr_min;
+               if (tb[NFTA_NAT_REG_ADDR_MAX]) {
+                       priv->sreg_addr_max =
+                               ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX]));
+
+                       err = nft_validate_input_register(priv->sreg_addr_max);
+                       if (err < 0)
+                               return err;
+               } else {
+                       priv->sreg_addr_max = priv->sreg_addr_min;
+               }
+       }
 
        if (tb[NFTA_NAT_REG_PROTO_MIN]) {
-               priv->sreg_proto_min = ntohl(nla_get_be32(
-                                               tb[NFTA_NAT_REG_PROTO_MIN]));
+               priv->sreg_proto_min =
+                       ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN]));
+
                err = nft_validate_input_register(priv->sreg_proto_min);
                if (err < 0)
                        return err;
-       }
 
-       if (tb[NFTA_NAT_REG_PROTO_MAX]) {
-               priv->sreg_proto_max = ntohl(nla_get_be32(
-                                               tb[NFTA_NAT_REG_PROTO_MAX]));
-               err = nft_validate_input_register(priv->sreg_proto_max);
-               if (err < 0)
-                       return err;
-       } else
-               priv->sreg_proto_max = priv->sreg_proto_min;
+               if (tb[NFTA_NAT_REG_PROTO_MAX]) {
+                       priv->sreg_proto_max =
+                               ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX]));
+
+                       err = nft_validate_input_register(priv->sreg_proto_max);
+                       if (err < 0)
+                               return err;
+               } else {
+                       priv->sreg_proto_max = priv->sreg_proto_min;
+               }
+       }
 
        if (tb[NFTA_NAT_FLAGS]) {
                priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS]));
@@ -179,17 +191,19 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
 
        if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family)))
                goto nla_put_failure;
-       if (nla_put_be32(skb,
-                        NFTA_NAT_REG_ADDR_MIN, htonl(priv->sreg_addr_min)))
-               goto nla_put_failure;
-       if (nla_put_be32(skb,
-                        NFTA_NAT_REG_ADDR_MAX, htonl(priv->sreg_addr_max)))
-               goto nla_put_failure;
+
+       if (priv->sreg_addr_min) {
+               if (nla_put_be32(skb, NFTA_NAT_REG_ADDR_MIN,
+                                htonl(priv->sreg_addr_min)) ||
+                   nla_put_be32(skb, NFTA_NAT_REG_ADDR_MAX,
+                                htonl(priv->sreg_addr_max)))
+                       goto nla_put_failure;
+       }
+
        if (priv->sreg_proto_min) {
                if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN,
-                                htonl(priv->sreg_proto_min)))
-                       goto nla_put_failure;
-               if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
+                                htonl(priv->sreg_proto_min)) ||
+                   nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
                                 htonl(priv->sreg_proto_max)))
                        goto nla_put_failure;
        }
@@ -205,6 +219,13 @@ nla_put_failure:
        return -1;
 }
 
+static int nft_nat_validate(const struct nft_ctx *ctx,
+                           const struct nft_expr *expr,
+                           const struct nft_data **data)
+{
+       return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
+}
+
 static struct nft_expr_type nft_nat_type;
 static const struct nft_expr_ops nft_nat_ops = {
        .type           = &nft_nat_type,
@@ -212,6 +233,7 @@ static const struct nft_expr_ops nft_nat_ops = {
        .eval           = nft_nat_eval,
        .init           = nft_nat_init,
        .dump           = nft_nat_dump,
+       .validate       = nft_nat_validate,
 };
 
 static struct nft_expr_type nft_nat_type __read_mostly = {
index 7a186e74b1b3533b936e0868ff49187321215386..0007b818039708bf447d74252712d93f9a8889e0 100644 (file)
@@ -96,6 +96,14 @@ static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
 static int netlink_dump(struct sock *sk);
 static void netlink_skb_destructor(struct sk_buff *skb);
 
+/* nl_table locking explained:
+ * Lookup and traversal are protected with nl_sk_hash_lock or nl_table_lock
+ * combined with an RCU read-side lock. Insertion and removal are protected
+ * with nl_sk_hash_lock while using RCU list modification primitives and may
+ * run in parallel to nl_table_lock protected lookups. Destruction of the
+ * Netlink socket may only occur *after* nl_table_lock has been acquired
+ * either during or after the socket has been removed from the list.
+ */
 DEFINE_RWLOCK(nl_table_lock);
 EXPORT_SYMBOL_GPL(nl_table_lock);
 static atomic_t nl_table_users = ATOMIC_INIT(0);
@@ -109,10 +117,10 @@ EXPORT_SYMBOL_GPL(nl_sk_hash_lock);
 static int lockdep_nl_sk_hash_is_held(void)
 {
 #ifdef CONFIG_LOCKDEP
-       return (debug_locks) ? lockdep_is_held(&nl_sk_hash_lock) : 1;
-#else
-       return 1;
+       if (debug_locks)
+               return lockdep_is_held(&nl_sk_hash_lock) || lockdep_is_held(&nl_table_lock);
 #endif
+       return 1;
 }
 
 static ATOMIC_NOTIFIER_HEAD(netlink_chain);
@@ -1028,11 +1036,13 @@ static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid)
        struct netlink_table *table = &nl_table[protocol];
        struct sock *sk;
 
+       read_lock(&nl_table_lock);
        rcu_read_lock();
        sk = __netlink_lookup(table, portid, net);
        if (sk)
                sock_hold(sk);
        rcu_read_unlock();
+       read_unlock(&nl_table_lock);
 
        return sk;
 }
@@ -1257,9 +1267,6 @@ static int netlink_release(struct socket *sock)
        }
        netlink_table_ungrab();
 
-       /* Wait for readers to complete */
-       synchronize_net();
-
        kfree(nlk->groups);
        nlk->groups = NULL;
 
@@ -1281,6 +1288,7 @@ static int netlink_autobind(struct socket *sock)
 
 retry:
        cond_resched();
+       netlink_table_grab();
        rcu_read_lock();
        if (__netlink_lookup(table, portid, net)) {
                /* Bind collision, search negative portid values. */
@@ -1288,9 +1296,11 @@ retry:
                if (rover > -4097)
                        rover = -4097;
                rcu_read_unlock();
+               netlink_table_ungrab();
                goto retry;
        }
        rcu_read_unlock();
+       netlink_table_ungrab();
 
        err = netlink_insert(sk, net, portid);
        if (err == -EADDRINUSE)
@@ -1430,7 +1440,7 @@ static void netlink_unbind(int group, long unsigned int groups,
                return;
 
        for (undo = 0; undo < group; undo++)
-               if (test_bit(group, &groups))
+               if (test_bit(undo, &groups))
                        nlk->netlink_unbind(undo);
 }
 
@@ -1482,7 +1492,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                        netlink_insert(sk, net, nladdr->nl_pid) :
                        netlink_autobind(sock);
                if (err) {
-                       netlink_unbind(nlk->ngroups - 1, groups, nlk);
+                       netlink_unbind(nlk->ngroups, groups, nlk);
                        return err;
                }
        }
@@ -2499,6 +2509,7 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
                nl_table[unit].module = module;
                if (cfg) {
                        nl_table[unit].bind = cfg->bind;
+                       nl_table[unit].unbind = cfg->unbind;
                        nl_table[unit].flags = cfg->flags;
                        if (cfg->compare)
                                nl_table[unit].compare = cfg->compare;
@@ -2921,14 +2932,16 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos)
 }
 
 static void *netlink_seq_start(struct seq_file *seq, loff_t *pos)
-       __acquires(RCU)
+       __acquires(nl_table_lock) __acquires(RCU)
 {
+       read_lock(&nl_table_lock);
        rcu_read_lock();
        return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN;
 }
 
 static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
+       struct rhashtable *ht;
        struct netlink_sock *nlk;
        struct nl_seq_iter *iter;
        struct net *net;
@@ -2943,19 +2956,19 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        iter = seq->private;
        nlk = v;
 
-       rht_for_each_entry_rcu(nlk, nlk->node.next, node)
+       i = iter->link;
+       ht = &nl_table[i].hash;
+       rht_for_each_entry(nlk, nlk->node.next, ht, node)
                if (net_eq(sock_net((struct sock *)nlk), net))
                        return nlk;
 
-       i = iter->link;
        j = iter->hash_idx + 1;
 
        do {
-               struct rhashtable *ht = &nl_table[i].hash;
                const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
 
                for (; j < tbl->size; j++) {
-                       rht_for_each_entry_rcu(nlk, tbl->buckets[j], node) {
+                       rht_for_each_entry(nlk, tbl->buckets[j], ht, node) {
                                if (net_eq(sock_net((struct sock *)nlk), net)) {
                                        iter->link = i;
                                        iter->hash_idx = j;
@@ -2971,9 +2984,10 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void netlink_seq_stop(struct seq_file *seq, void *v)
-       __releases(RCU)
+       __releases(RCU) __releases(nl_table_lock)
 {
        rcu_read_unlock();
+       read_unlock(&nl_table_lock);
 }
 
 
index 006886dbee36b075fc7054ec1ddc87781a75d739..8c4229b11c34c617a81e58dcdb1a4a6034fd064c 100644 (file)
@@ -246,11 +246,11 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
 {
        int transport_len = skb->len - skb_transport_offset(skb);
 
-       if (l4_proto == IPPROTO_TCP) {
+       if (l4_proto == NEXTHDR_TCP) {
                if (likely(transport_len >= sizeof(struct tcphdr)))
                        inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb,
                                                  addr, new_addr, 1);
-       } else if (l4_proto == IPPROTO_UDP) {
+       } else if (l4_proto == NEXTHDR_UDP) {
                if (likely(transport_len >= sizeof(struct udphdr))) {
                        struct udphdr *uh = udp_hdr(skb);
 
@@ -261,6 +261,10 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
                                        uh->check = CSUM_MANGLED_0;
                        }
                }
+       } else if (l4_proto == NEXTHDR_ICMP) {
+               if (likely(transport_len >= sizeof(struct icmp6hdr)))
+                       inet_proto_csum_replace16(&icmp6_hdr(skb)->icmp6_cksum,
+                                                 skb, addr, new_addr, 1);
        }
 }
 
@@ -722,8 +726,6 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 
                case OVS_ACTION_ATTR_SAMPLE:
                        err = sample(dp, skb, key, a);
-                       if (unlikely(err)) /* skb already freed. */
-                               return err;
                        break;
                }
 
index 2e31d9e7f4dc4ca1c002b3c488b838236dcdf2de..f9e556b5608650e490ad1608f5a28280f55d3d08 100644 (file)
@@ -324,6 +324,8 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
        segs = __skb_gso_segment(skb, NETIF_F_SG, false);
        if (IS_ERR(segs))
                return PTR_ERR(segs);
+       if (segs == NULL)
+               return -EINVAL;
 
        /* Queue all of the segments. */
        skb = segs;
@@ -1263,7 +1265,7 @@ static size_t ovs_dp_cmd_msg_size(void)
        return msgsize;
 }
 
-/* Called with ovs_mutex or RCU read lock. */
+/* Called with ovs_mutex. */
 static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
                                u32 portid, u32 seq, u32 flags, u8 cmd)
 {
@@ -1553,7 +1555,7 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
        if (!reply)
                return -ENOMEM;
 
-       rcu_read_lock();
+       ovs_lock();
        dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
        if (IS_ERR(dp)) {
                err = PTR_ERR(dp);
@@ -1562,12 +1564,12 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
        err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
                                   info->snd_seq, 0, OVS_DP_CMD_NEW);
        BUG_ON(err < 0);
-       rcu_read_unlock();
+       ovs_unlock();
 
        return genlmsg_reply(reply, info);
 
 err_unlock_free:
-       rcu_read_unlock();
+       ovs_unlock();
        kfree_skb(reply);
        return err;
 }
@@ -1579,8 +1581,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
        int skip = cb->args[0];
        int i = 0;
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(dp, &ovs_net->dps, list_node) {
+       ovs_lock();
+       list_for_each_entry(dp, &ovs_net->dps, list_node) {
                if (i >= skip &&
                    ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid,
                                         cb->nlh->nlmsg_seq, NLM_F_MULTI,
@@ -1588,7 +1590,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        break;
                i++;
        }
-       rcu_read_unlock();
+       ovs_unlock();
 
        cb->args[0] = i;
 
index 939bcb32100fe861b4ad94255d191ee281f83ed3..089b195c064ae56445b458e52e0dcaefa90b615c 100644 (file)
@@ -145,7 +145,7 @@ static bool match_validate(const struct sw_flow_match *match,
        if (match->key->eth.type == htons(ETH_P_ARP)
                        || match->key->eth.type == htons(ETH_P_RARP)) {
                key_expected |= 1 << OVS_KEY_ATTR_ARP;
-               if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
+               if (match->mask && (match->mask->key.tp.src == htons(0xff)))
                        mask_allowed |= 1 << OVS_KEY_ATTR_ARP;
        }
 
@@ -689,6 +689,13 @@ static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
                                ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
                        return -EINVAL;
                }
+
+               if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) {
+                       OVS_NLERR("IPv6 flow label %x is out of range (max=%x).\n",
+                                 ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
+                       return -EINVAL;
+               }
+
                SW_FLOW_KEY_PUT(match, ipv6.label,
                                ipv6_key->ipv6_label, is_mask);
                SW_FLOW_KEY_PUT(match, ip.proto,
index 87d20f48ff06195766e8ecd20a3fcfae5ccae690..07c04a841ba09c5ee5b0bc7718d4e6c87ac561e1 100644 (file)
@@ -378,7 +378,7 @@ static void unregister_prot_hook(struct sock *sk, bool sync)
                __unregister_prot_hook(sk, sync);
 }
 
-static inline __pure struct page *pgv_to_page(void *addr)
+static inline struct page * __pure pgv_to_page(void *addr)
 {
        if (is_vmalloc_addr(addr))
                return vmalloc_to_page(addr);
index 2cf61b3e633c25bb507860e970935998b05bf10d..76f402e05bd6f7a5ea50653629855039e6940d71 100644 (file)
@@ -947,7 +947,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
        if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {
                if (qdisc_is_percpu_stats(sch)) {
                        sch->cpu_bstats =
-                               alloc_percpu(struct gnet_stats_basic_cpu);
+                               netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
                        if (!sch->cpu_bstats)
                                goto err_out4;
 
index 33d7a98a7a9799b3cb5b3ce62c9013c49483184c..b783a446d884d85af054c9a139f91a63a162bc9f 100644 (file)
@@ -445,7 +445,6 @@ static int pie_init(struct Qdisc *sch, struct nlattr *opt)
        sch->limit = q->params.limit;
 
        setup_timer(&q->adapt_timer, pie_timer, (unsigned long)sch);
-       mod_timer(&q->adapt_timer, jiffies + HZ / 2);
 
        if (opt) {
                int err = pie_change(sch, opt);
@@ -454,6 +453,7 @@ static int pie_init(struct Qdisc *sch, struct nlattr *opt)
                        return err;
        }
 
+       mod_timer(&q->adapt_timer, jiffies + HZ / 2);
        return 0;
 }
 
index 0e8529113dc5a009c89bab8be3c87ce0ddbcce49..fb7976aee61c84f38aecdc5c5f0d8be20e577fa9 100644 (file)
@@ -862,8 +862,6 @@ int sctp_auth_set_key(struct sctp_endpoint *ep,
                list_add(&cur_key->key_list, sh_keys);
 
        cur_key->key = key;
-       sctp_auth_key_hold(key);
-
        return 0;
 nomem:
        if (!replace)
index ab734be8cb209864910f2fd667f2a6a27266f3af..9f32741abb1c7b142265297dc2fac78b74b3d195 100644 (file)
@@ -2609,6 +2609,9 @@ do_addr_param:
                addr_param = param.v + sizeof(sctp_addip_param_t);
 
                af = sctp_get_af_specific(param_type2af(param.p->type));
+               if (af == NULL)
+                       break;
+
                af->from_addr_param(&addr, addr_param,
                                    htons(asoc->peer.port), 0);
 
index afb292cd797decf08561492925d87d34d09e485b..53ed8d3f88970a877b2799e6ecb2dc9de6893304 100644 (file)
@@ -1353,6 +1353,7 @@ gss_stringify_acceptor(struct rpc_cred *cred)
        char *string = NULL;
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
        struct gss_cl_ctx *ctx;
+       unsigned int len;
        struct xdr_netobj *acceptor;
 
        rcu_read_lock();
@@ -1360,15 +1361,39 @@ gss_stringify_acceptor(struct rpc_cred *cred)
        if (!ctx)
                goto out;
 
-       acceptor = &ctx->gc_acceptor;
+       len = ctx->gc_acceptor.len;
+       rcu_read_unlock();
 
        /* no point if there's no string */
-       if (!acceptor->len)
-               goto out;
-
-       string = kmalloc(acceptor->len + 1, GFP_KERNEL);
+       if (!len)
+               return NULL;
+realloc:
+       string = kmalloc(len + 1, GFP_KERNEL);
        if (!string)
+               return NULL;
+
+       rcu_read_lock();
+       ctx = rcu_dereference(gss_cred->gc_ctx);
+
+       /* did the ctx disappear or was it replaced by one with no acceptor? */
+       if (!ctx || !ctx->gc_acceptor.len) {
+               kfree(string);
+               string = NULL;
                goto out;
+       }
+
+       acceptor = &ctx->gc_acceptor;
+
+       /*
+        * Did we find a new acceptor that's longer than the original? Allocate
+        * a longer buffer and try again.
+        */
+       if (len < acceptor->len) {
+               len = acceptor->len;
+               rcu_read_unlock();
+               kfree(string);
+               goto realloc;
+       }
 
        memcpy(string, acceptor->data, acceptor->len);
        string[acceptor->len] = '\0';
index 3f959c681885ba41ccdf6300bb27a35745ec11be..f9c052d508f008c4fb74567ea8cbad13f305d497 100644 (file)
@@ -1019,17 +1019,12 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
        xid = *p++;
        calldir = *p;
 
-       if (bc_xprt)
-               req = xprt_lookup_rqst(bc_xprt, xid);
-
-       if (!req) {
-               printk(KERN_NOTICE
-                       "%s: Got unrecognized reply: "
-                       "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
-                       __func__, ntohl(calldir),
-                       bc_xprt, ntohl(xid));
+       if (!bc_xprt)
                return -EAGAIN;
-       }
+       spin_lock_bh(&bc_xprt->transport_lock);
+       req = xprt_lookup_rqst(bc_xprt, xid);
+       if (!req)
+               goto unlock_notfound;
 
        memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf));
        /*
@@ -1040,11 +1035,21 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
        dst = &req->rq_private_buf.head[0];
        src = &rqstp->rq_arg.head[0];
        if (dst->iov_len < src->iov_len)
-               return -EAGAIN; /* whatever; just giving up. */
+               goto unlock_eagain; /* whatever; just giving up. */
        memcpy(dst->iov_base, src->iov_base, src->iov_len);
        xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
        rqstp->rq_arg.len = 0;
+       spin_unlock_bh(&bc_xprt->transport_lock);
        return 0;
+unlock_notfound:
+       printk(KERN_NOTICE
+               "%s: Got unrecognized reply: "
+               "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
+               __func__, ntohl(calldir),
+               bc_xprt, ntohl(xid));
+unlock_eagain:
+       spin_unlock_bh(&bc_xprt->transport_lock);
+       return -EAGAIN;
 }
 
 static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
index 90cee4a6fce49450a0f83cca53fcf663ebea8148..5781634e957d7be47c2e572783f3af2a3db9bf91 100644 (file)
@@ -219,11 +219,11 @@ void tipc_node_abort_sock_conns(struct list_head *conns)
 void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
 {
        struct tipc_link **active = &n_ptr->active_links[0];
-       u32 addr = n_ptr->addr;
 
        n_ptr->working_links++;
-       tipc_nametbl_publish(TIPC_LINK_STATE, addr, addr, TIPC_NODE_SCOPE,
-                            l_ptr->bearer_id, addr);
+       n_ptr->action_flags |= TIPC_NOTIFY_LINK_UP;
+       n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id;
+
        pr_info("Established link <%s> on network plane %c\n",
                l_ptr->name, l_ptr->net_plane);
 
@@ -284,10 +284,10 @@ static void node_select_active_links(struct tipc_node *n_ptr)
 void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
 {
        struct tipc_link **active;
-       u32 addr = n_ptr->addr;
 
        n_ptr->working_links--;
-       tipc_nametbl_withdraw(TIPC_LINK_STATE, addr, l_ptr->bearer_id, addr);
+       n_ptr->action_flags |= TIPC_NOTIFY_LINK_DOWN;
+       n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id;
 
        if (!tipc_link_is_active(l_ptr)) {
                pr_info("Lost standby link <%s> on network plane %c\n",
@@ -552,28 +552,30 @@ void tipc_node_unlock(struct tipc_node *node)
        LIST_HEAD(conn_sks);
        struct sk_buff_head waiting_sks;
        u32 addr = 0;
-       unsigned int flags = node->action_flags;
+       int flags = node->action_flags;
+       u32 link_id = 0;
 
-       if (likely(!node->action_flags)) {
+       if (likely(!flags)) {
                spin_unlock_bh(&node->lock);
                return;
        }
 
+       addr = node->addr;
+       link_id = node->link_id;
        __skb_queue_head_init(&waiting_sks);
-       if (node->action_flags & TIPC_WAKEUP_USERS) {
+
+       if (flags & TIPC_WAKEUP_USERS)
                skb_queue_splice_init(&node->waiting_sks, &waiting_sks);
-               node->action_flags &= ~TIPC_WAKEUP_USERS;
-       }
-       if (node->action_flags & TIPC_NOTIFY_NODE_DOWN) {
+
+       if (flags & TIPC_NOTIFY_NODE_DOWN) {
                list_replace_init(&node->nsub, &nsub_list);
                list_replace_init(&node->conn_sks, &conn_sks);
-               node->action_flags &= ~TIPC_NOTIFY_NODE_DOWN;
        }
-       if (node->action_flags & TIPC_NOTIFY_NODE_UP) {
-               node->action_flags &= ~TIPC_NOTIFY_NODE_UP;
-               addr = node->addr;
-       }
-       node->action_flags &= ~TIPC_WAKEUP_BCAST_USERS;
+       node->action_flags &= ~(TIPC_WAKEUP_USERS | TIPC_NOTIFY_NODE_DOWN |
+                               TIPC_NOTIFY_NODE_UP | TIPC_NOTIFY_LINK_UP |
+                               TIPC_NOTIFY_LINK_DOWN |
+                               TIPC_WAKEUP_BCAST_USERS);
+
        spin_unlock_bh(&node->lock);
 
        while (!skb_queue_empty(&waiting_sks))
@@ -588,6 +590,14 @@ void tipc_node_unlock(struct tipc_node *node)
        if (flags & TIPC_WAKEUP_BCAST_USERS)
                tipc_bclink_wakeup_users();
 
-       if (addr)
+       if (flags & TIPC_NOTIFY_NODE_UP)
                tipc_named_node_up(addr);
+
+       if (flags & TIPC_NOTIFY_LINK_UP)
+               tipc_nametbl_publish(TIPC_LINK_STATE, addr, addr,
+                                    TIPC_NODE_SCOPE, link_id, addr);
+
+       if (flags & TIPC_NOTIFY_LINK_DOWN)
+               tipc_nametbl_withdraw(TIPC_LINK_STATE, addr,
+                                     link_id, addr);
 }
index 67513c3c852c41f2d2a89ffc4d1eb22b7e77de91..04e91458bb29a17916964e65fbca8a99a35a7f0d 100644 (file)
@@ -53,6 +53,7 @@
  * TIPC_WAIT_OWN_LINKS_DOWN: wait until peer node is declared down
  * TIPC_NOTIFY_NODE_DOWN: notify node is down
  * TIPC_NOTIFY_NODE_UP: notify node is up
+ * TIPC_DISTRIBUTE_NAME: publish or withdraw link state name type
  */
 enum {
        TIPC_WAIT_PEER_LINKS_DOWN       = (1 << 1),
@@ -60,7 +61,9 @@ enum {
        TIPC_NOTIFY_NODE_DOWN           = (1 << 3),
        TIPC_NOTIFY_NODE_UP             = (1 << 4),
        TIPC_WAKEUP_USERS               = (1 << 5),
-       TIPC_WAKEUP_BCAST_USERS         = (1 << 6)
+       TIPC_WAKEUP_BCAST_USERS         = (1 << 6),
+       TIPC_NOTIFY_LINK_UP             = (1 << 7),
+       TIPC_NOTIFY_LINK_DOWN           = (1 << 8)
 };
 
 /**
@@ -100,6 +103,7 @@ struct tipc_node_bclink {
  * @working_links: number of working links to node (both active and standby)
  * @link_cnt: number of links to node
  * @signature: node instance identifier
+ * @link_id: local and remote bearer ids of changing link, if any
  * @nsub: list of "node down" subscriptions monitoring node
  * @rcu: rcu struct for tipc_node
  */
@@ -116,6 +120,7 @@ struct tipc_node {
        int link_cnt;
        int working_links;
        u32 signature;
+       u32 link_id;
        struct list_head nsub;
        struct sk_buff_head waiting_sks;
        struct list_head conn_sks;
index 75275c5cf9291a0afe0818b6ef99ccfc14db8822..51bddc236a15582b1a1dd0deb0b1a733c1d40070 100644 (file)
@@ -1776,7 +1776,7 @@ int tipc_sk_rcv(struct sk_buff *buf)
        sk = &tsk->sk;
 
        /* Queue message */
-       bh_lock_sock(sk);
+       spin_lock_bh(&sk->sk_lock.slock);
 
        if (!sock_owned_by_user(sk)) {
                rc = filter_rcv(sk, buf);
@@ -1787,7 +1787,7 @@ int tipc_sk_rcv(struct sk_buff *buf)
                if (sk_add_backlog(sk, buf, limit))
                        rc = -TIPC_ERR_OVERLOAD;
        }
-       bh_unlock_sock(sk);
+       spin_unlock_bh(&sk->sk_lock.slock);
        tipc_sk_put(tsk);
        if (likely(!rc))
                return 0;
@@ -2673,7 +2673,7 @@ static int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg)
        case SIOCGETLINKNAME:
                if (copy_from_user(&lnr, argp, sizeof(lnr)))
                        return -EFAULT;
-               if (!tipc_node_get_linkname(lnr.bearer_id, lnr.peer,
+               if (!tipc_node_get_linkname(lnr.bearer_id & 0xffff, lnr.peer,
                                            lnr.linkname, TIPC_MAX_LINK_NAME)) {
                        if (copy_to_user(argp, &lnr, sizeof(lnr)))
                                return -EFAULT;
index cb9f5a44ffadf7175d109cadefb091bbfdbb41e4..5839c85075f15407e86d84526cfb29087c70aa81 100644 (file)
@@ -5927,6 +5927,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
        int err;
        bool need_new_beacon = false;
        int len, i;
+       u32 cs_count;
 
        if (!rdev->ops->channel_switch ||
            !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
@@ -5963,7 +5964,14 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
        if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
                return -EINVAL;
 
-       params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+       /* Even though the attribute is u32, the specification says
+        * u8, so let's make sure we don't overflow.
+        */
+       cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+       if (cs_count > 255)
+               return -EINVAL;
+
+       params.count = cs_count;
 
        if (!need_new_beacon)
                goto skip_beacons;
index 499d6c18a8ce4366a5fe61184eb7416bfb060401..7c532856b39829f0cddf50baecc6d8c73c3422e7 100644 (file)
@@ -157,6 +157,8 @@ static int xfrm_output_gso(struct sk_buff *skb)
        kfree_skb(skb);
        if (IS_ERR(segs))
                return PTR_ERR(segs);
+       if (segs == NULL)
+               return -EINVAL;
 
        do {
                struct sk_buff *nskb = segs->next;
index 4c4e457e788861a1255dc654cc4d4eec80c22fda..88bf289abdc925a05730d6695944bdef1ec67eaf 100644 (file)
@@ -1962,7 +1962,7 @@ static int xdst_queue_output(struct sock *sk, struct sk_buff *skb)
        struct xfrm_policy *pol = xdst->pols[0];
        struct xfrm_policy_queue *pq = &pol->polq;
 
-       if (unlikely(skb_fclone_busy(skb))) {
+       if (unlikely(skb_fclone_busy(sk, skb))) {
                kfree_skb(skb);
                return 0;
        }
index f44ef11f65a787a26fe99791b24b2b2606321a0e..eb4bec0ad8afd2da3c8a52c61f1937425b082665 100644 (file)
@@ -208,6 +208,17 @@ static struct bpf_test tests[] = {
                .errstr = "R0 !read_ok",
                .result = REJECT,
        },
+       {
+               "program doesn't init R0 before exit in all branches",
+               .insns = {
+                       BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 2),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R0 !read_ok",
+               .result = REJECT,
+       },
        {
                "stack out of bounds",
                .insns = {
index 65e7b08bb2cc04db54412c07e72ef16c9fe2344e..5374b1bdf02f8793ad0a84c677a73e6cfa08b773 100644 (file)
@@ -179,6 +179,12 @@ build := -f $(srctree)/scripts/Makefile.build obj
 # $(Q)$(MAKE) $(modbuiltin)=dir
 modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj
 
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj=
+# Usage:
+# $(Q)$(MAKE) $(dtbinst)=dir
+dtbinst := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.dtbinst obj
+
 # Prefix -I with $(srctree) if it is not an absolute path.
 # skip if -I has no parameter
 addtree = $(if $(patsubst -I%,%,$(1)), \
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst
new file mode 100644 (file)
index 0000000..909ed7a
--- /dev/null
@@ -0,0 +1,51 @@
+# ==========================================================================
+# Installing dtb files
+#
+# Installs all dtb files listed in $(dtb-y) either in the
+# INSTALL_DTBS_PATH directory or the default location:
+#
+#   $INSTALL_PATH/dtbs/$KERNELRELEASE
+#
+# Traverse through subdirectories listed in $(dts-dirs).
+# ==========================================================================
+
+src := $(obj)
+
+PHONY := __dtbs_install
+__dtbs_install:
+
+export dtbinst-root ?= $(obj)
+
+include include/config/auto.conf
+include scripts/Kbuild.include
+include $(srctree)/$(obj)/Makefile
+
+PHONY += __dtbs_install_prep
+__dtbs_install_prep:
+ifeq ("$(dtbinst-root)", "$(obj)")
+       $(Q)if [ -d $(INSTALL_DTBS_PATH).old ]; then rm -rf $(INSTALL_DTBS_PATH).old; fi
+       $(Q)if [ -d $(INSTALL_DTBS_PATH) ]; then mv $(INSTALL_DTBS_PATH) $(INSTALL_DTBS_PATH).old; fi
+       $(Q)mkdir -p $(INSTALL_DTBS_PATH)
+endif
+
+dtbinst-files  := $(dtb-y)
+dtbinst-dirs   := $(dts-dirs)
+
+# Helper targets for Installing DTBs into the boot directory
+quiet_cmd_dtb_install =        INSTALL $<
+      cmd_dtb_install =        mkdir -p $(2); cp $< $(2)
+
+install-dir = $(patsubst $(dtbinst-root)%,$(INSTALL_DTBS_PATH)%,$(obj))
+
+$(dtbinst-files) $(dtbinst-dirs): | __dtbs_install_prep
+
+$(dtbinst-files): %.dtb: $(obj)/%.dtb
+       $(call cmd,dtb_install,$(install-dir))
+
+$(dtbinst-dirs):
+       $(Q)$(MAKE) $(dtbinst)=$(obj)/$@
+
+PHONY += $(dtbinst-files) $(dtbinst-dirs)
+__dtbs_install: $(dtbinst-files) $(dtbinst-dirs)
+
+.PHONY: $(PHONY)
index 54be19a0fa512ed41338faae85746177f1b53376..51175520063445c26ba24b51c2d3403a06793e05 100644 (file)
@@ -283,18 +283,6 @@ $(obj)/%.dtb: $(src)/%.dts FORCE
 
 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
 
-# Helper targets for Installing DTBs into the boot directory
-quiet_cmd_dtb_install =        INSTALL $<
-      cmd_dtb_install =        cp $< $(2)
-
-_dtbinst_pre_:
-       $(Q)if [ -d $(INSTALL_DTBS_PATH).old ]; then rm -rf $(INSTALL_DTBS_PATH).old; fi
-       $(Q)if [ -d $(INSTALL_DTBS_PATH) ]; then mv $(INSTALL_DTBS_PATH) $(INSTALL_DTBS_PATH).old; fi
-       $(Q)mkdir -p $(INSTALL_DTBS_PATH)
-
-%.dtb_dtbinst_: $(obj)/%.dtb _dtbinst_pre_
-       $(call cmd,dtb_install,$(INSTALL_DTBS_PATH))
-
 # Bzip2
 # ---------------------------------------------------------------------------
 
index 9685af330de5db40f4d7d097ea736b377dd68b36..c5ee1a7c5e8a0a361a8fb21de3ee236faba3804a 100644 (file)
@@ -319,9 +319,12 @@ int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
 {
        const struct evm_ima_xattr_data *xattr_data = xattr_value;
 
-       if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0)
-           && (xattr_data->type == EVM_XATTR_HMAC))
-               return -EPERM;
+       if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
+               if (!xattr_value_len)
+                       return -EINVAL;
+               if (xattr_data->type != EVM_IMA_XATTR_DIGSIG)
+                       return -EPERM;
+       }
        return evm_protect_xattr(dentry, xattr_name, xattr_value,
                                 xattr_value_len);
 }
index 922685483bd3625355af6202bb435728ac62c11f..7c8f41e618b6bf41bf5909b89335b465d16512c8 100644 (file)
@@ -378,6 +378,8 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
        result = ima_protect_xattr(dentry, xattr_name, xattr_value,
                                   xattr_value_len);
        if (result == 1) {
+               if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
+                       return -EINVAL;
                ima_reset_appraise_flags(dentry->d_inode,
                         (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
                result = 0;
index c0379d13dbe16f8d4c9705e1c80fd8b2c7b0e4df..9d1c2ebfe12a71d872727fe6f36716ec0a03c5d5 100644 (file)
@@ -61,6 +61,7 @@ enum evm_ima_xattr_type {
        EVM_XATTR_HMAC,
        EVM_IMA_XATTR_DIGSIG,
        IMA_XATTR_DIGEST_NG,
+       IMA_XATTR_LAST
 };
 
 struct evm_ima_xattr_data {
index b8960c4959a5e53635180054d27d788105ebf134..200e37867336a3c2903437e97f591fbc302e15b7 100644 (file)
@@ -117,6 +117,7 @@ struct keyring_search_context {
 #define KEYRING_SEARCH_NO_UPDATE_TIME  0x0004  /* Don't update times */
 #define KEYRING_SEARCH_NO_CHECK_PERM   0x0008  /* Don't check permissions */
 #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0010  /* Give an error on excessive depth */
+#define KEYRING_SEARCH_SKIP_EXPIRED    0x0020  /* Ignore expired keys (intention to replace) */
 
        int (*iterator)(const void *object, void *iterator_data);
 
index eff88a5f5d40da17611d381bcf4e219a90bcc972..4743d71e4aa6dd12f2456a5f00496c1222775c6a 100644 (file)
@@ -26,6 +26,8 @@
 #include <asm/uaccess.h>
 #include "internal.h"
 
+#define KEY_MAX_DESC_SIZE 4096
+
 static int key_get_type_from_user(char *type,
                                  const char __user *_type,
                                  unsigned len)
@@ -78,7 +80,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
 
        description = NULL;
        if (_description) {
-               description = strndup_user(_description, PAGE_SIZE);
+               description = strndup_user(_description, KEY_MAX_DESC_SIZE);
                if (IS_ERR(description)) {
                        ret = PTR_ERR(description);
                        goto error;
@@ -177,7 +179,7 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
                goto error;
 
        /* pull the description into kernel space */
-       description = strndup_user(_description, PAGE_SIZE);
+       description = strndup_user(_description, KEY_MAX_DESC_SIZE);
        if (IS_ERR(description)) {
                ret = PTR_ERR(description);
                goto error;
@@ -287,7 +289,7 @@ long keyctl_join_session_keyring(const char __user *_name)
        /* fetch the name from userspace */
        name = NULL;
        if (_name) {
-               name = strndup_user(_name, PAGE_SIZE);
+               name = strndup_user(_name, KEY_MAX_DESC_SIZE);
                if (IS_ERR(name)) {
                        ret = PTR_ERR(name);
                        goto error;
@@ -562,8 +564,9 @@ long keyctl_describe_key(key_serial_t keyid,
 {
        struct key *key, *instkey;
        key_ref_t key_ref;
-       char *tmpbuf;
+       char *infobuf;
        long ret;
+       int desclen, infolen;
 
        key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW);
        if (IS_ERR(key_ref)) {
@@ -586,38 +589,31 @@ long keyctl_describe_key(key_serial_t keyid,
        }
 
 okay:
-       /* calculate how much description we're going to return */
-       ret = -ENOMEM;
-       tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!tmpbuf)
-               goto error2;
-
        key = key_ref_to_ptr(key_ref);
+       desclen = strlen(key->description);
 
-       ret = snprintf(tmpbuf, PAGE_SIZE - 1,
-                      "%s;%d;%d;%08x;%s",
-                      key->type->name,
-                      from_kuid_munged(current_user_ns(), key->uid),
-                      from_kgid_munged(current_user_ns(), key->gid),
-                      key->perm,
-                      key->description ?: "");
-
-       /* include a NUL char at the end of the data */
-       if (ret > PAGE_SIZE - 1)
-               ret = PAGE_SIZE - 1;
-       tmpbuf[ret] = 0;
-       ret++;
+       /* calculate how much information we're going to return */
+       ret = -ENOMEM;
+       infobuf = kasprintf(GFP_KERNEL,
+                           "%s;%d;%d;%08x;",
+                           key->type->name,
+                           from_kuid_munged(current_user_ns(), key->uid),
+                           from_kgid_munged(current_user_ns(), key->gid),
+                           key->perm);
+       if (!infobuf)
+               goto error2;
+       infolen = strlen(infobuf);
+       ret = infolen + desclen + 1;
 
        /* consider returning the data */
-       if (buffer && buflen > 0) {
-               if (buflen > ret)
-                       buflen = ret;
-
-               if (copy_to_user(buffer, tmpbuf, buflen) != 0)
+       if (buffer && buflen >= ret) {
+               if (copy_to_user(buffer, infobuf, infolen) != 0 ||
+                   copy_to_user(buffer + infolen, key->description,
+                                desclen + 1) != 0)
                        ret = -EFAULT;
        }
 
-       kfree(tmpbuf);
+       kfree(infobuf);
 error2:
        key_ref_put(key_ref);
 error:
@@ -649,7 +645,7 @@ long keyctl_keyring_search(key_serial_t ringid,
        if (ret < 0)
                goto error;
 
-       description = strndup_user(_description, PAGE_SIZE);
+       description = strndup_user(_description, KEY_MAX_DESC_SIZE);
        if (IS_ERR(description)) {
                ret = PTR_ERR(description);
                goto error;
index 8177010174f7b3d47773a43e48bf2b171b264c5f..e72548b5897ec237dd7463374871538c81a84fd7 100644 (file)
@@ -546,7 +546,8 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
                }
 
                if (key->expiry && ctx->now.tv_sec >= key->expiry) {
-                       ctx->result = ERR_PTR(-EKEYEXPIRED);
+                       if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED))
+                               ctx->result = ERR_PTR(-EKEYEXPIRED);
                        kleave(" = %d [expire]", ctx->skipped_ret);
                        goto skipped;
                }
@@ -628,6 +629,10 @@ static bool search_nested_keyrings(struct key *keyring,
               ctx->index_key.type->name,
               ctx->index_key.description);
 
+#define STATE_CHECKS (KEYRING_SEARCH_NO_STATE_CHECK | KEYRING_SEARCH_DO_STATE_CHECK)
+       BUG_ON((ctx->flags & STATE_CHECKS) == 0 ||
+              (ctx->flags & STATE_CHECKS) == STATE_CHECKS);
+
        if (ctx->index_key.description)
                ctx->index_key.desc_len = strlen(ctx->index_key.description);
 
@@ -637,7 +642,6 @@ static bool search_nested_keyrings(struct key *keyring,
        if (ctx->match_data.lookup_type == KEYRING_SEARCH_LOOKUP_ITERATE ||
            keyring_compare_object(keyring, &ctx->index_key)) {
                ctx->skipped_ret = 2;
-               ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK;
                switch (ctx->iterator(keyring_key_to_ptr(keyring), ctx)) {
                case 1:
                        goto found;
@@ -649,8 +653,6 @@ static bool search_nested_keyrings(struct key *keyring,
        }
 
        ctx->skipped_ret = 0;
-       if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
-               ctx->flags &= ~KEYRING_SEARCH_DO_STATE_CHECK;
 
        /* Start processing a new keyring */
 descend_to_keyring:
index bb4337c7ae1b3978fd5e36d692d8cacf27b89816..0c7aea4dea54d8d299edc09b38c9a8f7b5c82be8 100644 (file)
@@ -516,6 +516,8 @@ struct key *request_key_and_link(struct key_type *type,
                .match_data.cmp         = key_default_cmp,
                .match_data.raw_data    = description,
                .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
+               .flags                  = (KEYRING_SEARCH_DO_STATE_CHECK |
+                                          KEYRING_SEARCH_SKIP_EXPIRED),
        };
        struct key *key;
        key_ref_t key_ref;
index 6639e2cb885322c6a43924496b2a68be25b9a5e6..5d672f7580dd5330516dd62f7d705cac46c319fb 100644 (file)
@@ -249,6 +249,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
                .match_data.cmp         = key_default_cmp,
                .match_data.raw_data    = description,
                .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
+               .flags                  = KEYRING_SEARCH_DO_STATE_CHECK,
        };
        struct key *authkey;
        key_ref_t authkey_ref;
index e66314138b3822036968abb52b672dcfc02c73ee..c603b20356ade4ca57c42a0cc7260f945d2c4ff5 100644 (file)
@@ -4725,9 +4725,10 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
        err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
        if (err) {
                if (err == -EINVAL) {
-                       WARN_ONCE(1, "selinux_nlmsg_perm: unrecognized netlink message:"
-                                 " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
-                                 sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
+                       printk(KERN_WARNING
+                              "SELinux: unrecognized netlink message:"
+                              " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
+                              sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
                        if (!selinux_enforcing || security_get_allow_unknown())
                                err = 0;
                }
index 42ded997b223b7ece3d8535000d4defeea2ba8f5..c6ff94ab1ad65a883e5b969437d05afb837e1a02 100644 (file)
@@ -216,6 +216,8 @@ static char *snd_pcm_format_names[] = {
        FORMAT(DSD_U8),
        FORMAT(DSD_U16_LE),
        FORMAT(DSD_U32_LE),
+       FORMAT(DSD_U16_BE),
+       FORMAT(DSD_U32_BE),
 };
 
 const char *snd_pcm_format_name(snd_pcm_format_t format)
index 102e8fd1d4505416ece1d42333cd8270b76cb395..2d957ba635578758172c9d66addc181a3ce438a9 100644 (file)
@@ -210,6 +210,8 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
        if (err < 0)
                return err;
 
+       if (clear_user(src, sizeof(*src)))
+               return -EFAULT;
        if (put_user(status.state, &src->state) ||
            compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
            compat_put_timespec(&status.tstamp, &src->tstamp) ||
index ae7a0feb3b76001f54555187c19343bce352f0c8..ebe8444de6c6ea8f44a5cacfb39b963939d9880d 100644 (file)
@@ -152,6 +152,14 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
                .width = 32, .phys = 32, .le = 1, .signd = 0,
                .silence = { 0x69, 0x69, 0x69, 0x69 },
        },
+       [SNDRV_PCM_FORMAT_DSD_U16_BE] = {
+               .width = 16, .phys = 16, .le = 0, .signd = 0,
+               .silence = { 0x69, 0x69 },
+       },
+       [SNDRV_PCM_FORMAT_DSD_U32_BE] = {
+               .width = 32, .phys = 32, .le = 0, .signd = 0,
+               .silence = { 0x69, 0x69, 0x69, 0x69 },
+       },
        /* FIXME: the following three formats are not defined properly yet */
        [SNDRV_PCM_FORMAT_MPEG] = {
                .le = -1, .signd = -1,
index bfe1cf6b492f08489a2f7a5dd7bc9e54ae61a4cc..166d59cdc86b3e178d7656f510a43983bfd34e19 100644 (file)
@@ -781,16 +781,15 @@ static int snd_pcm_action_group(struct action_ops *ops,
 {
        struct snd_pcm_substream *s = NULL;
        struct snd_pcm_substream *s1;
-       int res = 0;
+       int res = 0, depth = 1;
 
        snd_pcm_group_for_each_entry(s, substream) {
                if (do_lock && s != substream) {
                        if (s->pcm->nonatomic)
-                               mutex_lock_nested(&s->self_group.mutex,
-                                                 SINGLE_DEPTH_NESTING);
+                               mutex_lock_nested(&s->self_group.mutex, depth);
                        else
-                               spin_lock_nested(&s->self_group.lock,
-                                                SINGLE_DEPTH_NESTING);
+                               spin_lock_nested(&s->self_group.lock, depth);
+                       depth++;
                }
                res = ops->pre_action(s, state);
                if (res < 0)
@@ -906,8 +905,7 @@ static int snd_pcm_action_lock_mutex(struct action_ops *ops,
        down_read(&snd_pcm_link_rwsem);
        if (snd_pcm_stream_linked(substream)) {
                mutex_lock(&substream->group->mutex);
-               mutex_lock_nested(&substream->self_group.mutex,
-                                 SINGLE_DEPTH_NESTING);
+               mutex_lock(&substream->self_group.mutex);
                res = snd_pcm_action_group(ops, substream, state, 1);
                mutex_unlock(&substream->self_group.mutex);
                mutex_unlock(&substream->group->mutex);
@@ -3311,7 +3309,7 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
 
 #ifndef ARCH_HAS_DMA_MMAP_COHERENT
 /* This should be defined / handled globally! */
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
 #define ARCH_HAS_DMA_MMAP_COHERENT
 #endif
 #endif
index 45a0eed6d5b17413eaa002e8eb4eafeef2d67088..3b052ed0fbf58d284d55b562ac46ec1ee65cc763 100644 (file)
 #define SAFFIRE_CLOCK_SOURCE_INTERNAL          0
 #define SAFFIRE_CLOCK_SOURCE_SPDIF             1
 
-/* '1' is absent, why... */
+/* clock sources as returned from register of Saffire Pro 10 and 26 */
 #define SAFFIREPRO_CLOCK_SOURCE_INTERNAL       0
+#define SAFFIREPRO_CLOCK_SOURCE_SKIP           1 /* never used on hardware */
 #define SAFFIREPRO_CLOCK_SOURCE_SPDIF          2
-#define SAFFIREPRO_CLOCK_SOURCE_ADAT1          3
-#define SAFFIREPRO_CLOCK_SOURCE_ADAT2          4
+#define SAFFIREPRO_CLOCK_SOURCE_ADAT1          3 /* not used on s.pro. 10 */
+#define SAFFIREPRO_CLOCK_SOURCE_ADAT2          4 /* not used on s.pro. 10 */
 #define SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK      5
+#define SAFFIREPRO_CLOCK_SOURCE_COUNT          6
 
 /* S/PDIF, ADAT1, ADAT2 is enabled or not. three quadlets */
 #define SAFFIREPRO_ENABLE_DIG_IFACES           0x01a4
@@ -101,13 +103,34 @@ saffire_write_quad(struct snd_bebob *bebob, u64 offset, u32 value)
                                  &data, sizeof(__be32), 0);
 }
 
+static char *const saffirepro_10_clk_src_labels[] = {
+       SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
+};
 static char *const saffirepro_26_clk_src_labels[] = {
        SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "ADAT1", "ADAT2", "Word Clock"
 };
-
-static char *const saffirepro_10_clk_src_labels[] = {
-       SND_BEBOB_CLOCK_INTERNAL, "S/PDIF", "Word Clock"
+/* Value maps between registers and labels for SaffirePro 10/26. */
+static const signed char saffirepro_clk_maps[][SAFFIREPRO_CLOCK_SOURCE_COUNT] = {
+       /* SaffirePro 10 */
+       [0] = {
+               [SAFFIREPRO_CLOCK_SOURCE_INTERNAL]  =  0,
+               [SAFFIREPRO_CLOCK_SOURCE_SKIP]      = -1, /* not supported */
+               [SAFFIREPRO_CLOCK_SOURCE_SPDIF]     =  1,
+               [SAFFIREPRO_CLOCK_SOURCE_ADAT1]     = -1, /* not supported */
+               [SAFFIREPRO_CLOCK_SOURCE_ADAT2]     = -1, /* not supported */
+               [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] =  2,
+       },
+       /* SaffirePro 26 */
+       [1] = {
+               [SAFFIREPRO_CLOCK_SOURCE_INTERNAL]  =  0,
+               [SAFFIREPRO_CLOCK_SOURCE_SKIP]      = -1, /* not supported */
+               [SAFFIREPRO_CLOCK_SOURCE_SPDIF]     =  1,
+               [SAFFIREPRO_CLOCK_SOURCE_ADAT1]     =  2,
+               [SAFFIREPRO_CLOCK_SOURCE_ADAT2]     =  3,
+               [SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK] =  4,
+       }
 };
+
 static int
 saffirepro_both_clk_freq_get(struct snd_bebob *bebob, unsigned int *rate)
 {
@@ -138,24 +161,35 @@ saffirepro_both_clk_freq_set(struct snd_bebob *bebob, unsigned int rate)
 
        return saffire_write_quad(bebob, SAFFIREPRO_RATE_NOREBOOT, id);
 }
+
+/*
+ * query hardware for current clock source, return our internally
+ * used clock index in *id, depending on hardware.
+ */
 static int
 saffirepro_both_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
 {
        int err;
-       u32 value;
+       u32 value;       /* clock source read from hw register */
+       const signed char *map;
 
        err = saffire_read_quad(bebob, SAFFIREPRO_OFFSET_CLOCK_SOURCE, &value);
        if (err < 0)
                goto end;
 
-       if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels) {
-               if (value == SAFFIREPRO_CLOCK_SOURCE_WORDCLOCK)
-                       *id = 2;
-               else if (value == SAFFIREPRO_CLOCK_SOURCE_SPDIF)
-                       *id = 1;
-       } else if (value > 1) {
-               *id = value - 1;
+       /* depending on hardware, use a different mapping */
+       if (bebob->spec->clock->labels == saffirepro_10_clk_src_labels)
+               map = saffirepro_clk_maps[0];
+       else
+               map = saffirepro_clk_maps[1];
+
+       /* In a case that this driver cannot handle the value of register. */
+       if (value >= SAFFIREPRO_CLOCK_SOURCE_COUNT || map[value] < 0) {
+               err = -EIO;
+               goto end;
        }
+
+       *id = (unsigned int)map[value];
 end:
        return err;
 }
index ef4d0c9f65781a2e2684a143264a8b3aad12d8be..1aab0a32870c84d20a0c5b87f46d625299b34fd4 100644 (file)
@@ -129,12 +129,24 @@ snd_bebob_stream_check_internal_clock(struct snd_bebob *bebob, bool *internal)
        /* 1.The device has its own operation to switch source of clock */
        if (clk_spec) {
                err = clk_spec->get(bebob, &id);
-               if (err < 0)
+               if (err < 0) {
                        dev_err(&bebob->unit->device,
                                "fail to get clock source: %d\n", err);
-               else if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
-                                strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
+                       goto end;
+               }
+
+               if (id >= clk_spec->num) {
+                       dev_err(&bebob->unit->device,
+                               "clock source %d out of range 0..%d\n",
+                               id, clk_spec->num - 1);
+                       err = -EIO;
+                       goto end;
+               }
+
+               if (strncmp(clk_spec->labels[id], SND_BEBOB_CLOCK_INTERNAL,
+                           strlen(SND_BEBOB_CLOCK_INTERNAL)) == 0)
                        *internal = true;
+
                goto end;
        }
 
index 0e4c0bfc463bbbb3222d92a54f269c3ecff283ee..9940611f2e1b59cd8a15ea9d55c01a6f15c8d417 100644 (file)
@@ -24,7 +24,12 @@ phase88_rack_clk_src_get(struct snd_bebob *bebob, unsigned int *id)
        if (err < 0)
                goto end;
 
-       *id = (enable_ext & 0x01) | ((enable_word & 0x01) << 1);
+       if (enable_ext == 0)
+               *id = 0;
+       else if (enable_word == 0)
+               *id = 1;
+       else
+               *id = 2;
 end:
        return err;
 }
index 7bfdf9c514165c384a36beb89d72f4a9678648b3..1610c38337afe6887e02074f98446a6c18aadc6e 100644 (file)
@@ -681,7 +681,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
        
        /* WARQ is at offset 12 */
        tmp = (reg & AD_DS_WSMC_WARQ) ?
-                       (((reg & AD_DS_WSMC_WARQ >> 12) & 0x01) ? 12 : 18) : 4;
+               ((((reg & AD_DS_WSMC_WARQ) >> 12) & 0x01) ? 12 : 18) : 4;
        tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
        
        snd_iprintf(buffer, "Wave FIFO: %d %s words\n\n", tmp,
@@ -693,7 +693,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
        
        /* SYRQ is at offset 4 */
        tmp = (reg & AD_DS_WSMC_SYRQ) ?
-                       (((reg & AD_DS_WSMC_SYRQ >> 4) & 0x01) ? 12 : 18) : 4;
+               ((((reg & AD_DS_WSMC_SYRQ) >> 4) & 0x01) ? 12 : 18) : 4;
        tmp /= (reg & AD_DS_WSMC_WAST) ? 2 : 1;
        
        snd_iprintf(buffer, "Synthesis FIFO: %d %s words\n\n", tmp,
@@ -709,7 +709,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
        
        /* ACRQ is at offset 4 */
        tmp = (reg & AD_DS_RAMC_ACRQ) ?
-                       (((reg & AD_DS_RAMC_ACRQ >> 4) & 0x01) ? 12 : 18) : 4;
+               ((((reg & AD_DS_RAMC_ACRQ) >> 4) & 0x01) ? 12 : 18) : 4;
        tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
        
        snd_iprintf(buffer, "ADC FIFO: %d %s words\n\n", tmp,
@@ -720,7 +720,7 @@ snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffe
                        
        /* RERQ is at offset 12 */
        tmp = (reg & AD_DS_RAMC_RERQ) ?
-                       (((reg & AD_DS_RAMC_RERQ >> 12) & 0x01) ? 12 : 18) : 4;
+               ((((reg & AD_DS_RAMC_RERQ) >> 12) & 0x01) ? 12 : 18) : 4;
        tmp /= (reg & AD_DS_RAMC_ADST) ? 2 : 1;
        
        snd_iprintf(buffer, "Resampler FIFO: %d %s words\n\n", tmp,
index cfcca4c30d4da5f2be82ae40a32b709d9279f97b..48b6c5a3884f3b1ed729d542fd286ba2840a938b 100644 (file)
@@ -219,6 +219,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
                         "{Intel, LPT_LP},"
                         "{Intel, WPT_LP},"
                         "{Intel, SPT},"
+                        "{Intel, SPT_LP},"
                         "{Intel, HPT},"
                         "{Intel, PBG},"
                         "{Intel, SCH},"
@@ -297,7 +298,8 @@ enum {
 
 /* quirks for ATI/AMD HDMI */
 #define AZX_DCAPS_PRESET_ATI_HDMI \
-       (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB)
+       (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_SYNC_WRITE | AZX_DCAPS_POSFIX_LPIB|\
+        AZX_DCAPS_NO_MSI64)
 
 /* quirks for Nvidia */
 #define AZX_DCAPS_PRESET_NVIDIA \
@@ -374,6 +376,8 @@ static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool
 #ifdef CONFIG_SND_DMA_SGBUF
        if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) {
                struct snd_sg_buf *sgbuf = dmab->private_data;
+               if (chip->driver_type == AZX_DRIVER_CMEDIA)
+                       return; /* deal with only CORB/RIRB buffers */
                if (on)
                        set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
                else
@@ -1483,6 +1487,7 @@ static int azx_first_init(struct azx *chip)
        struct snd_card *card = chip->card;
        int err;
        unsigned short gcap;
+       unsigned int dma_bits = 64;
 
 #if BITS_PER_LONG != 64
        /* Fix up base address on ULI M5461 */
@@ -1506,9 +1511,14 @@ static int azx_first_init(struct azx *chip)
                return -ENXIO;
        }
 
-       if (chip->msi)
+       if (chip->msi) {
+               if (chip->driver_caps & AZX_DCAPS_NO_MSI64) {
+                       dev_dbg(card->dev, "Disabling 64bit MSI\n");
+                       pci->no_64bit_msi = true;
+               }
                if (pci_enable_msi(pci) < 0)
                        chip->msi = 0;
+       }
 
        if (azx_acquire_irq(chip, 0) < 0)
                return -EBUSY;
@@ -1519,9 +1529,14 @@ static int azx_first_init(struct azx *chip)
        gcap = azx_readw(chip, GCAP);
        dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap);
 
+       /* AMD devices support 40 or 48bit DMA, take the safe one */
+       if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
+               dma_bits = 40;
+
        /* disable SB600 64bit support for safety */
        if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
                struct pci_dev *p_smbus;
+               dma_bits = 40;
                p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
                                         PCI_DEVICE_ID_ATI_SBX00_SMBUS,
                                         NULL);
@@ -1551,9 +1566,11 @@ static int azx_first_init(struct azx *chip)
        }
 
        /* allow 64bit DMA address if supported by H/W */
-       if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
-               pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
-       else {
+       if (!(gcap & AZX_GCAP_64OK))
+               dma_bits = 32;
+       if (!pci_set_dma_mask(pci, DMA_BIT_MASK(dma_bits))) {
+               pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(dma_bits));
+       } else {
                pci_set_dma_mask(pci, DMA_BIT_MASK(32));
                pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32));
        }
@@ -1769,7 +1786,7 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
 #ifdef CONFIG_X86
        struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
        struct azx *chip = apcm->chip;
-       if (!azx_snoop(chip))
+       if (!azx_snoop(chip) && chip->driver_type != AZX_DRIVER_CMEDIA)
                area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
 #endif
 }
@@ -2002,6 +2019,9 @@ static const struct pci_device_id azx_ids[] = {
        /* Sunrise Point */
        { PCI_DEVICE(0x8086, 0xa170),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+       /* Sunrise Point-LP */
+       { PCI_DEVICE(0x8086, 0x9d70),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Haswell */
        { PCI_DEVICE(0x8086, 0x0a0c),
          .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
index 7eb44e78e141fcd0bcb98d2e9ce3358f9c4c80ae..62658f2f8c9f2db94fca481a86da8432858105a0 100644 (file)
@@ -419,7 +419,7 @@ struct snd_hda_pin_quirk {
          .subvendor = _subvendor,\
          .name = _name,\
          .value = _value,\
-         .pins = (const struct hda_pintbl[]) { _pins } \
+         .pins = (const struct hda_pintbl[]) { _pins, {0, 0}} \
        }
 #else
 
@@ -427,7 +427,7 @@ struct snd_hda_pin_quirk {
        { .codec = _codec,\
          .subvendor = _subvendor,\
          .value = _value,\
-         .pins = (const struct hda_pintbl[]) { _pins } \
+         .pins = (const struct hda_pintbl[]) { _pins, {0, 0}} \
        }
 
 #endif
index 949cd437eeb264798aec5d9b2f5c5e61a87fc294..5016014e57f2f1dc65f68d5b71db8d12f065493f 100644 (file)
@@ -171,6 +171,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
 #define AZX_DCAPS_I915_POWERWELL (1 << 27)     /* HSW i915 powerwell support */
 #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)  /* CORBRP clears itself after reset */
+#define AZX_DCAPS_NO_MSI64      (1 << 29)      /* Stick to 32-bit MSIs */
 
 /* HD Audio class code */
 #define PCI_CLASS_MULTIMEDIA_HD_AUDIO  0x0403
index 71e4bad06345c856fcfb80e9e75578d444db117e..e9ebc7bd752cae1afdf95c0b2d2e0e8a15d2393b 100644 (file)
@@ -43,6 +43,7 @@ struct conexant_spec {
        unsigned int num_eapds;
        hda_nid_t eapds[4];
        bool dynamic_eapd;
+       hda_nid_t mute_led_eapd;
 
        unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
 
@@ -163,6 +164,17 @@ static void cx_auto_vmaster_hook(void *private_data, int enabled)
        cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
 }
 
+/* turn on/off EAPD according to Master switch (inversely!) for mute LED */
+static void cx_auto_vmaster_hook_mute_led(void *private_data, int enabled)
+{
+       struct hda_codec *codec = private_data;
+       struct conexant_spec *spec = codec->spec;
+
+       snd_hda_codec_write(codec, spec->mute_led_eapd, 0,
+                           AC_VERB_SET_EAPD_BTLENABLE,
+                           enabled ? 0x00 : 0x02);
+}
+
 static int cx_auto_build_controls(struct hda_codec *codec)
 {
        int err;
@@ -223,6 +235,7 @@ enum {
        CXT_FIXUP_TOSHIBA_P105,
        CXT_FIXUP_HP_530,
        CXT_FIXUP_CAP_MIX_AMP_5047,
+       CXT_FIXUP_MUTE_LED_EAPD,
 };
 
 /* for hda_fixup_thinkpad_acpi() */
@@ -557,6 +570,18 @@ static void cxt_fixup_olpc_xo(struct hda_codec *codec,
        }
 }
 
+static void cxt_fixup_mute_led_eapd(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       struct conexant_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->mute_led_eapd = 0x1b;
+               spec->dynamic_eapd = 1;
+               spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook_mute_led;
+       }
+}
+
 /*
  * Fix max input level on mixer widget to 0dB
  * (originally it has 0x2b steps with 0dB offset 0x14)
@@ -705,6 +730,10 @@ static const struct hda_fixup cxt_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cxt_fixup_cap_mix_amp_5047,
        },
+       [CXT_FIXUP_MUTE_LED_EAPD] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cxt_fixup_mute_led_eapd,
+       },
 };
 
 static const struct snd_pci_quirk cxt5045_fixups[] = {
@@ -762,6 +791,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
+       SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
@@ -780,6 +810,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
        { .id = CXT_PINCFG_LEMOTE_A1004, .name = "lemote-a1004" },
        { .id = CXT_PINCFG_LEMOTE_A1205, .name = "lemote-a1205" },
        { .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" },
+       { .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" },
        {}
 };
 
index 39862e98551c41466505ee7b1764496e04799880..9dc9cf8c90e97bd5d0faa08bedae29139e43d3bc 100644 (file)
@@ -1583,19 +1583,22 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
                }
        }
 
-       if (pin_eld->eld_valid && !eld->eld_valid) {
-               update_eld = true;
+       if (pin_eld->eld_valid != eld->eld_valid)
                eld_changed = true;
-       }
+
+       if (pin_eld->eld_valid && !eld->eld_valid)
+               update_eld = true;
+
        if (update_eld) {
                bool old_eld_valid = pin_eld->eld_valid;
                pin_eld->eld_valid = eld->eld_valid;
-               eld_changed = pin_eld->eld_size != eld->eld_size ||
+               if (pin_eld->eld_size != eld->eld_size ||
                              memcmp(pin_eld->eld_buffer, eld->eld_buffer,
-                                    eld->eld_size) != 0;
-               if (eld_changed)
+                                    eld->eld_size) != 0) {
                        memcpy(pin_eld->eld_buffer, eld->eld_buffer,
                               eld->eld_size);
+                       eld_changed = true;
+               }
                pin_eld->eld_size = eld->eld_size;
                pin_eld->info = eld->info;
 
index bc86c36b4bfa39b383f113b5dbd377b0c8ffd22d..b118a5be18df7ea2a9bfeab4997c677e1ae176b5 100644 (file)
@@ -288,21 +288,91 @@ static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
        snd_hda_jack_unsol_event(codec, res >> 2);
 }
 
-/* additional initialization for ALC888 variants */
-static void alc888_coef_init(struct hda_codec *codec)
+/* Change EAPD to verb control */
+static void alc_fill_eapd_coef(struct hda_codec *codec)
 {
-       if (alc_get_coef0(codec) == 0x20)
-               /* alc888S-VC */
-               alc_write_coef_idx(codec, 7, 0x830);
-        else
-                /* alc888-VB */
-               alc_write_coef_idx(codec, 7, 0x3030);
+       int coef;
+
+       coef = alc_get_coef0(codec);
+
+       switch (codec->vendor_id) {
+       case 0x10ec0262:
+               alc_update_coef_idx(codec, 0x7, 0, 1<<5);
+               break;
+       case 0x10ec0267:
+       case 0x10ec0268:
+               alc_update_coef_idx(codec, 0x7, 0, 1<<13);
+               break;
+       case 0x10ec0269:
+               if ((coef & 0x00f0) == 0x0010)
+                       alc_update_coef_idx(codec, 0xd, 0, 1<<14);
+               if ((coef & 0x00f0) == 0x0020)
+                       alc_update_coef_idx(codec, 0x4, 1<<15, 0);
+               if ((coef & 0x00f0) == 0x0030)
+                       alc_update_coef_idx(codec, 0x10, 1<<9, 0);
+               break;
+       case 0x10ec0280:
+       case 0x10ec0284:
+       case 0x10ec0290:
+       case 0x10ec0292:
+               alc_update_coef_idx(codec, 0x4, 1<<15, 0);
+               break;
+       case 0x10ec0233:
+       case 0x10ec0255:
+       case 0x10ec0282:
+       case 0x10ec0283:
+       case 0x10ec0286:
+       case 0x10ec0288:
+               alc_update_coef_idx(codec, 0x10, 1<<9, 0);
+               break;
+       case 0x10ec0285:
+       case 0x10ec0293:
+               alc_update_coef_idx(codec, 0xa, 1<<13, 0);
+               break;
+       case 0x10ec0662:
+               if ((coef & 0x00f0) == 0x0030)
+                       alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
+               break;
+       case 0x10ec0272:
+       case 0x10ec0273:
+       case 0x10ec0663:
+       case 0x10ec0665:
+       case 0x10ec0670:
+       case 0x10ec0671:
+       case 0x10ec0672:
+               alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
+               break;
+       case 0x10ec0668:
+               alc_update_coef_idx(codec, 0x7, 3<<13, 0);
+               break;
+       case 0x10ec0867:
+               alc_update_coef_idx(codec, 0x4, 1<<10, 0);
+               break;
+       case 0x10ec0888:
+               if ((coef & 0x00f0) == 0x0020 || (coef & 0x00f0) == 0x0030)
+                       alc_update_coef_idx(codec, 0x7, 1<<5, 0);
+               break;
+       case 0x10ec0892:
+               alc_update_coef_idx(codec, 0x7, 1<<5, 0);
+               break;
+       case 0x10ec0899:
+       case 0x10ec0900:
+               alc_update_coef_idx(codec, 0x7, 1<<1, 0);
+               break;
+       }
 }
 
-/* additional initialization for ALC889 variants */
-static void alc889_coef_init(struct hda_codec *codec)
+/* additional initialization for ALC888 variants */
+static void alc888_coef_init(struct hda_codec *codec)
 {
-       alc_update_coef_idx(codec, 7, 0, 0x2010);
+       switch (alc_get_coef0(codec) & 0x00f0) {
+       /* alc888-VA */
+       case 0x00:
+       /* alc888-VB */
+       case 0x10:
+               alc_update_coef_idx(codec, 7, 0, 0x2030); /* Turn EAPD to High */
+               break;
+       }
 }
 
 /* turn on/off EAPD control (only if available) */
@@ -343,6 +413,7 @@ static void alc_eapd_shutup(struct hda_codec *codec)
 /* generic EAPD initialization */
 static void alc_auto_init_amp(struct hda_codec *codec, int type)
 {
+       alc_fill_eapd_coef(codec);
        alc_auto_setup_eapd(codec, true);
        switch (type) {
        case ALC_INIT_GPIO1:
@@ -359,25 +430,15 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
                case 0x10ec0260:
                        alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010);
                        break;
-               case 0x10ec0262:
                case 0x10ec0880:
                case 0x10ec0882:
                case 0x10ec0883:
                case 0x10ec0885:
-               case 0x10ec0887:
-               /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
-               case 0x10ec0900:
-                       alc889_coef_init(codec);
+                       alc_update_coef_idx(codec, 7, 0, 0x2030);
                        break;
                case 0x10ec0888:
                        alc888_coef_init(codec);
                        break;
-#if 0 /* XXX: This may cause the silent output on speaker on some machines */
-               case 0x10ec0267:
-               case 0x10ec0268:
-                       alc_update_coef_idx(codec, 7, 0, 0x3000);
-                       break;
-#endif /* XXX */
                }
                break;
        }
@@ -1710,7 +1771,7 @@ static void alc889_fixup_coef(struct hda_codec *codec,
 {
        if (action != HDA_FIXUP_ACT_INIT)
                return;
-       alc889_coef_init(codec);
+       alc_update_coef_idx(codec, 7, 0, 0x2030);
 }
 
 /* toggle speaker-output according to the hp-jack state */
@@ -2675,7 +2736,7 @@ static void alc269_shutup(struct hda_codec *codec)
 
 static struct coef_fw alc282_coefs[] = {
        WRITE_COEF(0x03, 0x0002), /* Power Down Control */
-       WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */
+       UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
        WRITE_COEF(0x07, 0x0200), /* DMIC control */
        UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
        UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
@@ -2786,7 +2847,7 @@ static void alc282_shutup(struct hda_codec *codec)
 
 static struct coef_fw alc283_coefs[] = {
        WRITE_COEF(0x03, 0x0002), /* Power Down Control */
-       WRITE_COEF(0x05, 0x0700), /* FIFO and filter clock */
+       UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
        WRITE_COEF(0x07, 0x0200), /* DMIC control */
        UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
        UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
@@ -2817,6 +2878,7 @@ static struct coef_fw alc283_coefs[] = {
        UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */
        UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */
        WRITE_COEF(0x37, 0xfc06), /* Class D amp control */
+       UPDATE_COEF(0x1b, 0x8000, 0), /* HP JD control */
        {}
 };
 
@@ -2884,6 +2946,9 @@ static void alc283_shutup(struct hda_codec *codec)
 
        alc_write_coef_idx(codec, 0x43, 0x9004);
 
+       /*depop hp during suspend*/
+       alc_write_coef_idx(codec, 0x06, 0x2100);
+
        snd_hda_codec_write(codec, hp_pin, 0,
                            AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 
@@ -3346,6 +3411,27 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
        }
 }
 
+static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
+                                  const struct hda_fixup *fix, int action)
+{
+       /* Like hp_gpio_mic1_led, but also needs GPIO4 low to enable headphone amp */
+       struct alc_spec *spec = codec->spec;
+       static const struct hda_verb gpio_init[] = {
+               { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
+               { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
+               {}
+       };
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
+               spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
+               spec->gpio_led = 0;
+               spec->cap_mute_led_nid = 0x18;
+               snd_hda_add_verbs(codec, gpio_init);
+               codec->power_filter = led_power_filter;
+       }
+}
+
 static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
 {
@@ -4213,6 +4299,7 @@ enum {
        ALC283_FIXUP_BXBT2807_MIC,
        ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
        ALC282_FIXUP_ASPIRE_V5_PINS,
+       ALC280_FIXUP_HP_GPIO4,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -4433,6 +4520,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC269_FIXUP_HEADSET_MODE] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_headset_mode,
+               .chained = true,
+               .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED
        },
        [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
                .type = HDA_FIXUP_FUNC,
@@ -4622,6 +4711,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC255_FIXUP_HEADSET_MODE] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_headset_mode_alc255,
+               .chained = true,
+               .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED
        },
        [ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
                .type = HDA_FIXUP_FUNC,
@@ -4657,8 +4748,6 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_dell_wmi,
-               .chained_before = true,
-               .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
        },
        [ALC282_FIXUP_ASPIRE_V5_PINS] = {
                .type = HDA_FIXUP_PINS,
@@ -4676,7 +4765,10 @@ static const struct hda_fixup alc269_fixups[] = {
                        { },
                },
        },
-
+       [ALC280_FIXUP_HP_GPIO4] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc280_fixup_hp_gpio4,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -4693,13 +4785,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
        SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
        SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
-       SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
        SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
        SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -4724,21 +4816,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        /* ALC290 */
        SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4747,7 +4833,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
-       SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
        SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4800,7 +4885,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
-       SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
        SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -4980,6 +5065,19 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x17, 0x40000000},
                {0x1d, 0x40700001},
                {0x21, 0x02211040}),
+       SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
+               {0x12, 0x90a60130},
+               {0x13, 0x40000000},
+               {0x14, 0x90170110},
+               {0x15, 0x0421101f},
+               {0x16, 0x411111f0},
+               {0x17, 0x411111f0},
+               {0x18, 0x411111f0},
+               {0x19, 0x411111f0},
+               {0x1a, 0x04a11020},
+               {0x1b, 0x411111f0},
+               {0x1d, 0x40748605},
+               {0x1e, 0x411111f0}),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED,
                {0x12, 0x90a60140},
                {0x13, 0x40000000},
@@ -5190,9 +5288,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
                }
        }
 
-       /* Class D */
-       alc_update_coef_idx(codec, 0xd, 0, 1<<14);
-
        /* HP */
        alc_update_coef_idx(codec, 0x4, 0, 1<<11);
 }
@@ -5610,9 +5705,9 @@ static void alc662_led_gpio1_mute_hook(void *private_data, int enabled)
        unsigned int oldval = spec->gpio_led;
 
        if (enabled)
-               spec->gpio_led &= ~0x01;
-       else
                spec->gpio_led |= 0x01;
+       else
+               spec->gpio_led &= ~0x01;
        if (spec->gpio_led != oldval)
                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
                                    spec->gpio_led);
@@ -5647,6 +5742,35 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec,
        }
 }
 
+static struct coef_fw alc668_coefs[] = {
+       WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03,    0x0),
+       WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06,    0x0), WRITE_COEF(0x07, 0x0f80),
+       WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b,    0x0),
+       WRITE_COEF(0x0c, 0x7cf7), WRITE_COEF(0x0d, 0x1080), WRITE_COEF(0x0e, 0x7f7f),
+       WRITE_COEF(0x0f, 0xcccc), WRITE_COEF(0x10, 0xddcc), WRITE_COEF(0x11, 0x0001),
+       WRITE_COEF(0x13,    0x0), WRITE_COEF(0x14, 0x2aa0), WRITE_COEF(0x17, 0xa940),
+       WRITE_COEF(0x19,    0x0), WRITE_COEF(0x1a,    0x0), WRITE_COEF(0x1b,    0x0),
+       WRITE_COEF(0x1c,    0x0), WRITE_COEF(0x1d,    0x0), WRITE_COEF(0x1e, 0x7418),
+       WRITE_COEF(0x1f, 0x0804), WRITE_COEF(0x20, 0x4200), WRITE_COEF(0x21, 0x0468),
+       WRITE_COEF(0x22, 0x8ccc), WRITE_COEF(0x23, 0x0250), WRITE_COEF(0x24, 0x7418),
+       WRITE_COEF(0x27,    0x0), WRITE_COEF(0x28, 0x8ccc), WRITE_COEF(0x2a, 0xff00),
+       WRITE_COEF(0x2b, 0x8000), WRITE_COEF(0xa7, 0xff00), WRITE_COEF(0xa8, 0x8000),
+       WRITE_COEF(0xaa, 0x2e17), WRITE_COEF(0xab, 0xa0c0), WRITE_COEF(0xac,    0x0),
+       WRITE_COEF(0xad,    0x0), WRITE_COEF(0xae, 0x2ac6), WRITE_COEF(0xaf, 0xa480),
+       WRITE_COEF(0xb0,    0x0), WRITE_COEF(0xb1,    0x0), WRITE_COEF(0xb2,    0x0),
+       WRITE_COEF(0xb3,    0x0), WRITE_COEF(0xb4,    0x0), WRITE_COEF(0xb5, 0x1040),
+       WRITE_COEF(0xb6, 0xd697), WRITE_COEF(0xb7, 0x902b), WRITE_COEF(0xb8, 0xd697),
+       WRITE_COEF(0xb9, 0x902b), WRITE_COEF(0xba, 0xb8ba), WRITE_COEF(0xbb, 0xaaab),
+       WRITE_COEF(0xbc, 0xaaaf), WRITE_COEF(0xbd, 0x6aaa), WRITE_COEF(0xbe, 0x1c02),
+       WRITE_COEF(0xc0, 0x00ff), WRITE_COEF(0xc1, 0x0fa6),
+       {}
+};
+
+static void alc668_restore_default_value(struct hda_codec *codec)
+{
+       alc_process_coef_fw(codec, alc668_coefs);
+}
+
 enum {
        ALC662_FIXUP_ASPIRE,
        ALC662_FIXUP_LED_GPIO1,
@@ -5919,6 +6043,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
        SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
        SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
@@ -6072,29 +6197,6 @@ static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
        {}
 };
 
-static void alc662_fill_coef(struct hda_codec *codec)
-{
-       int coef;
-
-       coef = alc_get_coef0(codec);
-
-       switch (codec->vendor_id) {
-       case 0x10ec0662:
-               if ((coef & 0x00f0) == 0x0030)
-                       alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
-               break;
-       case 0x10ec0272:
-       case 0x10ec0273:
-       case 0x10ec0663:
-       case 0x10ec0665:
-       case 0x10ec0670:
-       case 0x10ec0671:
-       case 0x10ec0672:
-               alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
-               break;
-       }
-}
-
 /*
  */
 static int patch_alc662(struct hda_codec *codec)
@@ -6113,8 +6215,11 @@ static int patch_alc662(struct hda_codec *codec)
 
        alc_fix_pll_init(codec, 0x20, 0x04, 15);
 
-       spec->init_hook = alc662_fill_coef;
-       alc662_fill_coef(codec);
+       switch (codec->vendor_id) {
+       case 0x10ec0668:
+               spec->init_hook = alc668_restore_default_value;
+               break;
+       }
 
        snd_hda_pick_fixup(codec, alc662_fixup_models,
                       alc662_fixup_tbl, alc662_fixups);
index 0e9623368ab0ad19fcba9fc5970949dce213e35d..7d5d6444a83737ffa3c01acbe1925de619e0390a 100644 (file)
@@ -49,7 +49,6 @@ source "sound/soc/mxs/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/rockchip/Kconfig"
 source "sound/soc/samsung/Kconfig"
-source "sound/soc/s6000/Kconfig"
 source "sound/soc/sh/Kconfig"
 source "sound/soc/sirf/Kconfig"
 source "sound/soc/spear/Kconfig"
index 534714a1ca449dcfbefc176bba1e65cdce73a782..d88edfced8c498c4bed67dfc5b14941c4ba904bf 100644 (file)
@@ -26,7 +26,6 @@ obj-$(CONFIG_SND_SOC) += kirkwood/
 obj-$(CONFIG_SND_SOC)  += pxa/
 obj-$(CONFIG_SND_SOC)  += rockchip/
 obj-$(CONFIG_SND_SOC)  += samsung/
-obj-$(CONFIG_SND_SOC)  += s6000/
 obj-$(CONFIG_SND_SOC)  += sh/
 obj-$(CONFIG_SND_SOC)  += sirf/
 obj-$(CONFIG_SND_SOC)  += spear/
index 5518ebd6947c5f28329fb474b4b313920f5e94ec..91f60282fd2fbff8a64315ec8400b3e156a374b9 100644 (file)
@@ -405,6 +405,7 @@ static const struct snd_soc_dapm_widget adau1761_dapm_widgets[] = {
                2, 0, NULL, 0),
 
        SND_SOC_DAPM_SUPPLY("Slew Clock", ADAU1761_CLK_ENABLE0, 6, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("ALC Clock", ADAU1761_CLK_ENABLE0, 5, 0, NULL, 0),
 
        SND_SOC_DAPM_SUPPLY_S("Digital Clock 0", 1, ADAU1761_CLK_ENABLE1,
                0, 0, NULL, 0),
@@ -436,6 +437,9 @@ static const struct snd_soc_dapm_route adau1761_dapm_routes[] = {
        { "Right Playback Mixer", NULL, "Slew Clock" },
        { "Left Playback Mixer", NULL, "Slew Clock" },
 
+       { "Left Input Mixer", NULL, "ALC Clock" },
+       { "Right Input Mixer", NULL, "ALC Clock" },
+
        { "Digital Clock 0", NULL, "SYSCLK" },
        { "Digital Clock 1", NULL, "SYSCLK" },
 };
index cee51ae177c1e219325231eb517b91784ac258fe..c40428f25ba5c9b9b3d2e5e657a71020702dc12b 100644 (file)
@@ -46,6 +46,7 @@ static struct i2c_driver cs42l51_i2c_driver = {
        .driver = {
                .name = "cs42l51",
                .owner = THIS_MODULE,
+               .of_match_table = cs42l51_of_match,
        },
        .probe = cs42l51_i2c_probe,
        .remove = cs42l51_i2c_remove,
index 09488d97de60d040bbdb37edfa3a94a999930633..669c38fc303468d51dd6bbd3dfa16e935c030e8c 100644 (file)
@@ -558,11 +558,13 @@ error:
 }
 EXPORT_SYMBOL_GPL(cs42l51_probe);
 
-static const struct of_device_id cs42l51_of_match[] = {
+const struct of_device_id cs42l51_of_match[] = {
        { .compatible = "cirrus,cs42l51", },
        { }
 };
 MODULE_DEVICE_TABLE(of, cs42l51_of_match);
+EXPORT_SYMBOL_GPL(cs42l51_of_match);
+
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
 MODULE_LICENSE("GPL");
index 8c55bf384bc65189545807d9ce9278d6c66670f2..0ca805492ac4b77d110dc24b378845fb5b3768a6 100644 (file)
@@ -22,6 +22,7 @@ struct device;
 
 extern const struct regmap_config cs42l51_regmap;
 int cs42l51_probe(struct device *dev, struct regmap *regmap);
+extern const struct of_device_id cs42l51_of_match[];
 
 #define CS42L51_CHIP_ID                        0x1B
 #define CS42L51_CHIP_REV_A             0x00
index aae410d122ee1f8f7cb99fbd416fd02c0f17fdfd..2d05b5d3a6ce7fdc3531f5c322853dbb1a0ca63e 100644 (file)
@@ -19,7 +19,7 @@
 #include "es8328.h"
 
 static const struct i2c_device_id es8328_id[] = {
-       { "everest,es8328", 0 },
+       { "es8328", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, es8328_id);
index d519294f57c79c289784f9a71bb43d7bf51dc7e9..1229554f1464d1e1c37a1d82d227a5a6347e377d 100644 (file)
@@ -1941,13 +1941,13 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
         *               0x02 (when master clk is 20MHz to 40MHz)..
         *               0x03 (when master clk is 40MHz to 60MHz)..
         */
-       if ((freq >= 10000000) && (freq < 20000000)) {
+       if ((freq >= 10000000) && (freq <= 20000000)) {
                snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,
                        M98090_PSCLK_DIV1);
-       } else if ((freq >= 20000000) && (freq < 40000000)) {
+       } else if ((freq > 20000000) && (freq <= 40000000)) {
                snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,
                        M98090_PSCLK_DIV2);
-       } else if ((freq >= 40000000) && (freq < 60000000)) {
+       } else if ((freq > 40000000) && (freq <= 60000000)) {
                snd_soc_write(codec, M98090_REG_SYSTEM_CLOCK,
                        M98090_PSCLK_DIV4);
        } else {
index 3fb83bf09768347f1bcd469d2be9be4b56ea62e2..d16331e0b64d4532647b5f4eb4d4abe58a4d66ec 100644 (file)
@@ -139,6 +139,7 @@ static const struct reg_default rt5645_reg[] = {
        { 0x76, 0x000a },
        { 0x77, 0x0c00 },
        { 0x78, 0x0000 },
+       { 0x79, 0x0123 },
        { 0x80, 0x0000 },
        { 0x81, 0x0000 },
        { 0x82, 0x0000 },
@@ -334,6 +335,7 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg)
        case RT5645_DMIC_CTRL2:
        case RT5645_TDM_CTRL_1:
        case RT5645_TDM_CTRL_2:
+       case RT5645_TDM_CTRL_3:
        case RT5645_GLB_CLK:
        case RT5645_PLL_CTRL1:
        case RT5645_PLL_CTRL2:
index ba9d9b4d485783c80efa30e13e3218f1fec7742e..9bd8b4f633032c713a432ca3af1bc38aa3c81f16 100644 (file)
@@ -100,18 +100,18 @@ static const struct reg_default rt5670_reg[] = {
        { 0x4c, 0x5380 },
        { 0x4f, 0x0073 },
        { 0x52, 0x00d3 },
-       { 0x53, 0xf0f0 },
+       { 0x53, 0xf000 },
        { 0x61, 0x0000 },
        { 0x62, 0x0001 },
        { 0x63, 0x00c3 },
        { 0x64, 0x0000 },
-       { 0x65, 0x0000 },
+       { 0x65, 0x0001 },
        { 0x66, 0x0000 },
        { 0x6f, 0x8000 },
        { 0x70, 0x8000 },
        { 0x71, 0x8000 },
        { 0x72, 0x8000 },
-       { 0x73, 0x1110 },
+       { 0x73, 0x7770 },
        { 0x74, 0x0e00 },
        { 0x75, 0x1505 },
        { 0x76, 0x0015 },
@@ -125,21 +125,21 @@ static const struct reg_default rt5670_reg[] = {
        { 0x83, 0x0000 },
        { 0x84, 0x0000 },
        { 0x85, 0x0000 },
-       { 0x86, 0x0008 },
+       { 0x86, 0x0004 },
        { 0x87, 0x0000 },
        { 0x88, 0x0000 },
        { 0x89, 0x0000 },
        { 0x8a, 0x0000 },
        { 0x8b, 0x0000 },
-       { 0x8c, 0x0007 },
+       { 0x8c, 0x0003 },
        { 0x8d, 0x0000 },
        { 0x8e, 0x0004 },
        { 0x8f, 0x1100 },
        { 0x90, 0x0646 },
        { 0x91, 0x0c06 },
        { 0x93, 0x0000 },
-       { 0x94, 0x0000 },
-       { 0x95, 0x0000 },
+       { 0x94, 0x1270 },
+       { 0x95, 0x1000 },
        { 0x97, 0x0000 },
        { 0x98, 0x0000 },
        { 0x99, 0x0000 },
@@ -150,11 +150,11 @@ static const struct reg_default rt5670_reg[] = {
        { 0x9e, 0x0400 },
        { 0xae, 0x7000 },
        { 0xaf, 0x0000 },
-       { 0xb0, 0x6000 },
+       { 0xb0, 0x7000 },
        { 0xb1, 0x0000 },
        { 0xb2, 0x0000 },
        { 0xb3, 0x001f },
-       { 0xb4, 0x2206 },
+       { 0xb4, 0x220c },
        { 0xb5, 0x1f00 },
        { 0xb6, 0x0000 },
        { 0xb7, 0x0000 },
@@ -171,25 +171,25 @@ static const struct reg_default rt5670_reg[] = {
        { 0xcf, 0x1813 },
        { 0xd0, 0x0690 },
        { 0xd1, 0x1c17 },
-       { 0xd3, 0xb320 },
+       { 0xd3, 0xa220 },
        { 0xd4, 0x0000 },
        { 0xd6, 0x0400 },
        { 0xd9, 0x0809 },
        { 0xda, 0x0000 },
        { 0xdb, 0x0001 },
        { 0xdc, 0x0049 },
-       { 0xdd, 0x0009 },
+       { 0xdd, 0x0024 },
        { 0xe6, 0x8000 },
        { 0xe7, 0x0000 },
-       { 0xec, 0xb300 },
+       { 0xec, 0xa200 },
        { 0xed, 0x0000 },
-       { 0xee, 0xb300 },
+       { 0xee, 0xa200 },
        { 0xef, 0x0000 },
        { 0xf8, 0x0000 },
        { 0xf9, 0x0000 },
        { 0xfa, 0x8010 },
        { 0xfb, 0x0033 },
-       { 0xfc, 0x0080 },
+       { 0xfc, 0x0100 },
 };
 
 static bool rt5670_volatile_register(struct device *dev, unsigned int reg)
@@ -1877,6 +1877,10 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = {
        { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" },
        { "DAC1 MIXR", NULL, "DAC Stereo1 Filter" },
 
+       { "DAC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll },
+       { "DAC Mono Left Filter", NULL, "PLL1", is_sys_clk_from_pll },
+       { "DAC Mono Right Filter", NULL, "PLL1", is_sys_clk_from_pll },
+
        { "DAC MIX", NULL, "DAC1 MIXL" },
        { "DAC MIX", NULL, "DAC1 MIXR" },
 
@@ -1926,14 +1930,10 @@ static const struct snd_soc_dapm_route rt5670_dapm_routes[] = {
 
        { "DAC L1", NULL, "DAC L1 Power" },
        { "DAC L1", NULL, "Stereo DAC MIXL" },
-       { "DAC L1", NULL, "PLL1", is_sys_clk_from_pll },
        { "DAC R1", NULL, "DAC R1 Power" },
        { "DAC R1", NULL, "Stereo DAC MIXR" },
-       { "DAC R1", NULL, "PLL1", is_sys_clk_from_pll },
        { "DAC L2", NULL, "Mono DAC MIXL" },
-       { "DAC L2", NULL, "PLL1", is_sys_clk_from_pll },
        { "DAC R2", NULL, "Mono DAC MIXR" },
-       { "DAC R2", NULL, "PLL1", is_sys_clk_from_pll },
 
        { "OUT MIXL", "BST1 Switch", "BST1" },
        { "OUT MIXL", "INL Switch", "INL VOL" },
index 6bb77d76561b8964303275955d1e1beb579ba859..dab9b15304af829a510742ec4a4827bdca90a453 100644 (file)
@@ -1299,8 +1299,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
 
        /* enable small pop, introduce 400ms delay in turning off */
        snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
-                               SGTL5000_SMALL_POP,
-                               SGTL5000_SMALL_POP);
+                               SGTL5000_SMALL_POP, 1);
 
        /* disable short cut detector */
        snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0);
index 2f8c88931f690579f86d497d03ef7327a156a94c..bd7a344bf8c517edf69af2fda9e06e08488e47e0 100644 (file)
 #define SGTL5000_BIAS_CTRL_MASK                        0x000e
 #define SGTL5000_BIAS_CTRL_SHIFT               1
 #define SGTL5000_BIAS_CTRL_WIDTH               3
-#define SGTL5000_SMALL_POP                     0x0001
+#define SGTL5000_SMALL_POP                     0
 
 /*
  * SGTL5000_CHIP_MIC_CTRL
index f412a9911a75d2fe531930f6a0108fb977c41e77..67124783558a5374b547f26d30d1ccc2bdc16ae4 100644 (file)
@@ -1355,6 +1355,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                          file, blocks, pos - firmware->size);
 
 out_fw:
+       regmap_async_complete(regmap);
        release_firmware(firmware);
        wm_adsp_buf_free(&buf_list);
 out:
index 3b145313f93eecc0602cc72115d71769f07fdf26..9deabdd2b1a29adf3d27335557cd1cc23fee11f4 100644 (file)
@@ -684,12 +684,38 @@ static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg)
        }
 }
 
+static struct reg_default fsl_asrc_reg[] = {
+       { REG_ASRCTR, 0x0000 }, { REG_ASRIER, 0x0000 },
+       { REG_ASRCNCR, 0x0000 }, { REG_ASRCFG, 0x0000 },
+       { REG_ASRCSR, 0x0000 }, { REG_ASRCDR1, 0x0000 },
+       { REG_ASRCDR2, 0x0000 }, { REG_ASRSTR, 0x0000 },
+       { REG_ASRRA, 0x0000 }, { REG_ASRRB, 0x0000 },
+       { REG_ASRRC, 0x0000 }, { REG_ASRPM1, 0x0000 },
+       { REG_ASRPM2, 0x0000 }, { REG_ASRPM3, 0x0000 },
+       { REG_ASRPM4, 0x0000 }, { REG_ASRPM5, 0x0000 },
+       { REG_ASRTFR1, 0x0000 }, { REG_ASRCCR, 0x0000 },
+       { REG_ASRDIA, 0x0000 }, { REG_ASRDOA, 0x0000 },
+       { REG_ASRDIB, 0x0000 }, { REG_ASRDOB, 0x0000 },
+       { REG_ASRDIC, 0x0000 }, { REG_ASRDOC, 0x0000 },
+       { REG_ASRIDRHA, 0x0000 }, { REG_ASRIDRLA, 0x0000 },
+       { REG_ASRIDRHB, 0x0000 }, { REG_ASRIDRLB, 0x0000 },
+       { REG_ASRIDRHC, 0x0000 }, { REG_ASRIDRLC, 0x0000 },
+       { REG_ASR76K, 0x0A47 }, { REG_ASR56K, 0x0DF3 },
+       { REG_ASRMCRA, 0x0000 }, { REG_ASRFSTA, 0x0000 },
+       { REG_ASRMCRB, 0x0000 }, { REG_ASRFSTB, 0x0000 },
+       { REG_ASRMCRC, 0x0000 }, { REG_ASRFSTC, 0x0000 },
+       { REG_ASRMCR1A, 0x0000 }, { REG_ASRMCR1B, 0x0000 },
+       { REG_ASRMCR1C, 0x0000 },
+};
+
 static const struct regmap_config fsl_asrc_regmap_config = {
        .reg_bits = 32,
        .reg_stride = 4,
        .val_bits = 32,
 
        .max_register = REG_ASRMCR1C,
+       .reg_defaults = fsl_asrc_reg,
+       .num_reg_defaults = ARRAY_SIZE(fsl_asrc_reg),
        .readable_reg = fsl_asrc_readable_reg,
        .volatile_reg = fsl_asrc_volatile_reg,
        .writeable_reg = fsl_asrc_writeable_reg,
@@ -792,7 +818,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        asrc_priv->pdev = pdev;
-       strcpy(asrc_priv->name, np->name);
+       strncpy(asrc_priv->name, np->name, sizeof(asrc_priv->name) - 1);
 
        /* Get the addresses and IRQ */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 8bcdfda09d7ad9c5fd724cc685e63f3ac7829f77..a645e296199e14086c6def7a98d34be5de54bcf2 100644 (file)
@@ -734,7 +734,7 @@ static int fsl_esai_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        esai_priv->pdev = pdev;
-       strcpy(esai_priv->name, np->name);
+       strncpy(esai_priv->name, np->name, sizeof(esai_priv->name) - 1);
 
        /* Get the addresses and IRQ */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index 33fc5c3abf558e52850e46c523702559e203b1bc..4df867cbb92a1992154b12bf1f69293accd51367 100644 (file)
@@ -691,9 +691,7 @@ static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
 }
 
 #define HSW_FORMATS \
-       (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \
-       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE |\
-       SNDRV_PCM_FMTBIT_S8)
+       (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
 
 static struct snd_soc_dai_driver hsw_dais[] = {
        {
index f373e37f83050a246c2d35fbed008db7cdd0b5a5..c74ba37f862c121b1114edd84bded49ec7d72907 100644 (file)
@@ -154,8 +154,10 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
                        while (val) {
                                regmap_read(i2s->regmap, I2S_CLR, &val);
                                retry--;
-                               if (!retry)
+                               if (!retry) {
                                        dev_warn(i2s->dev, "fail to clear\n");
+                                       break;
+                               }
                        }
                }
        }
diff --git a/sound/soc/s6000/Kconfig b/sound/soc/s6000/Kconfig
deleted file mode 100644 (file)
index f244a25..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-config SND_S6000_SOC
-       tristate "SoC Audio for the Stretch s6000 family"
-       depends on XTENSA_VARIANT_S6000 || COMPILE_TEST
-       depends on HAS_IOMEM
-       select SND_S6000_SOC_PCM if XTENSA_VARIANT_S6000
-       help
-         Say Y or M if you want to add support for codecs attached to
-         s6000 family chips. You will also need to select the platform
-         to support below.
-
-config SND_S6000_SOC_PCM
-       tristate
-
-config SND_S6000_SOC_I2S
-       tristate
-
-config SND_S6000_SOC_S6IPCAM
-       bool "SoC Audio support for Stretch 6105 IP Camera"
-       depends on SND_S6000_SOC=y
-       depends on I2C=y
-       depends on XTENSA_PLATFORM_S6105 || COMPILE_TEST
-       select SND_S6000_SOC_I2S
-       select SND_SOC_TLV320AIC3X
-       help
-         Say Y if you want to add support for SoC audio on the
-         Stretch s6105 IP Camera Reference Design.
diff --git a/sound/soc/s6000/Makefile b/sound/soc/s6000/Makefile
deleted file mode 100644 (file)
index 0f0ae2a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# s6000 Platform Support
-snd-soc-s6000-objs := s6000-pcm.o
-snd-soc-s6000-i2s-objs := s6000-i2s.o
-
-obj-$(CONFIG_SND_S6000_SOC_PCM) += snd-soc-s6000.o
-obj-$(CONFIG_SND_S6000_SOC_I2S) += snd-soc-s6000-i2s.o
-
-# s6105 Machine Support
-snd-soc-s6ipcam-objs := s6105-ipcam.o
-
-obj-$(CONFIG_SND_S6000_SOC_S6IPCAM) += snd-soc-s6ipcam.o
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
deleted file mode 100644 (file)
index 1c8d011..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * ALSA SoC I2S Audio Layer for the Stretch S6000 family
- *
- * Author:      Daniel Gloeckner, <dg@emlix.com>
- * Copyright:   (C) 2009 emlix GmbH <info@emlix.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/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include "s6000-i2s.h"
-#include "s6000-pcm.h"
-
-struct s6000_i2s_dev {
-       dma_addr_t sifbase;
-       u8 __iomem *scbbase;
-       unsigned int wide;
-       unsigned int channel_in;
-       unsigned int channel_out;
-       unsigned int lines_in;
-       unsigned int lines_out;
-       struct s6000_pcm_dma_params dma_params;
-};
-
-#define S6_I2S_INTERRUPT_STATUS        0x00
-#define   S6_I2S_INT_OVERRUN   1
-#define   S6_I2S_INT_UNDERRUN  2
-#define   S6_I2S_INT_ALIGNMENT 4
-#define S6_I2S_INTERRUPT_ENABLE        0x04
-#define S6_I2S_INTERRUPT_RAW   0x08
-#define S6_I2S_INTERRUPT_CLEAR 0x0C
-#define S6_I2S_INTERRUPT_SET   0x10
-#define S6_I2S_MODE            0x20
-#define   S6_I2S_DUAL          0
-#define   S6_I2S_WIDE          1
-#define S6_I2S_TX_DEFAULT      0x24
-#define S6_I2S_DATA_CFG(c)     (0x40 + 0x10 * (c))
-#define   S6_I2S_IN            0
-#define   S6_I2S_OUT           1
-#define   S6_I2S_UNUSED                2
-#define S6_I2S_INTERFACE_CFG(c)        (0x44 + 0x10 * (c))
-#define   S6_I2S_DIV_MASK      0x001fff
-#define   S6_I2S_16BIT         0x000000
-#define   S6_I2S_20BIT         0x002000
-#define   S6_I2S_24BIT         0x004000
-#define   S6_I2S_32BIT         0x006000
-#define   S6_I2S_BITS_MASK     0x006000
-#define   S6_I2S_MEM_16BIT     0x000000
-#define   S6_I2S_MEM_32BIT     0x008000
-#define   S6_I2S_MEM_MASK      0x008000
-#define   S6_I2S_CHANNELS_SHIFT        16
-#define   S6_I2S_CHANNELS_MASK 0x030000
-#define   S6_I2S_SCK_IN                0x000000
-#define   S6_I2S_SCK_OUT       0x040000
-#define   S6_I2S_SCK_DIR       0x040000
-#define   S6_I2S_WS_IN         0x000000
-#define   S6_I2S_WS_OUT                0x080000
-#define   S6_I2S_WS_DIR                0x080000
-#define   S6_I2S_LEFT_FIRST    0x000000
-#define   S6_I2S_RIGHT_FIRST   0x100000
-#define   S6_I2S_FIRST         0x100000
-#define   S6_I2S_CUR_SCK       0x200000
-#define   S6_I2S_CUR_WS                0x400000
-#define S6_I2S_ENABLE(c)       (0x48 + 0x10 * (c))
-#define   S6_I2S_DISABLE_IF    0x02
-#define   S6_I2S_ENABLE_IF     0x03
-#define   S6_I2S_IS_BUSY       0x04
-#define   S6_I2S_DMA_ACTIVE    0x08
-#define   S6_I2S_IS_ENABLED    0x10
-
-#define S6_I2S_NUM_LINES       4
-
-#define S6_I2S_SIF_PORT0       0x0000000
-#define S6_I2S_SIF_PORT1       0x0000080 /* docs say 0x0000010 */
-
-static inline void s6_i2s_write_reg(struct s6000_i2s_dev *dev, int reg, u32 val)
-{
-       writel(val, dev->scbbase + reg);
-}
-
-static inline u32 s6_i2s_read_reg(struct s6000_i2s_dev *dev, int reg)
-{
-       return readl(dev->scbbase + reg);
-}
-
-static inline void s6_i2s_mod_reg(struct s6000_i2s_dev *dev, int reg,
-                                 u32 mask, u32 val)
-{
-       val ^= s6_i2s_read_reg(dev, reg) & ~mask;
-       s6_i2s_write_reg(dev, reg, val);
-}
-
-static void s6000_i2s_start_channel(struct s6000_i2s_dev *dev, int channel)
-{
-       int i, j, cur, prev;
-
-       /*
-        * Wait for WCLK to toggle 5 times before enabling the channel
-        * s6000 Family Datasheet 3.6.4:
-        *   "At least two cycles of WS must occur between commands
-        *    to disable or enable the interface"
-        */
-       j = 0;
-       prev = ~S6_I2S_CUR_WS;
-       for (i = 1000000; --i && j < 6; ) {
-               cur = s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(channel))
-                      & S6_I2S_CUR_WS;
-               if (prev != cur) {
-                       prev = cur;
-                       j++;
-               }
-       }
-       if (j < 6)
-               printk(KERN_WARNING "s6000-i2s: timeout waiting for WCLK\n");
-
-       s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_ENABLE_IF);
-}
-
-static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel)
-{
-       s6_i2s_write_reg(dev, S6_I2S_ENABLE(channel), S6_I2S_DISABLE_IF);
-}
-
-static void s6000_i2s_start(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-       int channel;
-
-       channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-                       dev->channel_out : dev->channel_in;
-
-       s6000_i2s_start_channel(dev, channel);
-}
-
-static void s6000_i2s_stop(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-       int channel;
-
-       channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-                       dev->channel_out : dev->channel_in;
-
-       s6000_i2s_stop_channel(dev, channel);
-}
-
-static int s6000_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
-                            int after)
-{
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ^ !after)
-                       s6000_i2s_start(substream);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               if (!after)
-                       s6000_i2s_stop(substream);
-       }
-       return 0;
-}
-
-static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)
-{
-       unsigned int pending;
-       pending = s6_i2s_read_reg(dev, S6_I2S_INTERRUPT_RAW);
-       pending &= S6_I2S_INT_ALIGNMENT |
-                  S6_I2S_INT_UNDERRUN |
-                  S6_I2S_INT_OVERRUN;
-       s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR, pending);
-
-       return pending;
-}
-
-static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai)
-{
-       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
-       unsigned int errors;
-       unsigned int ret;
-
-       errors = s6000_i2s_int_sources(dev);
-       if (likely(!errors))
-               return 0;
-
-       ret = 0;
-       if (errors & S6_I2S_INT_ALIGNMENT)
-               printk(KERN_ERR "s6000-i2s: WCLK misaligned\n");
-       if (errors & S6_I2S_INT_UNDERRUN)
-               ret |= 1 << SNDRV_PCM_STREAM_PLAYBACK;
-       if (errors & S6_I2S_INT_OVERRUN)
-               ret |= 1 << SNDRV_PCM_STREAM_CAPTURE;
-       return ret;
-}
-
-static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)
-{
-       int channel;
-       int n = 50;
-       for (channel = 0; channel < 2; channel++) {
-               while (--n >= 0) {
-                       int v = s6_i2s_read_reg(dev, S6_I2S_ENABLE(channel));
-                       if ((v & S6_I2S_IS_ENABLED)
-                           || !(v & (S6_I2S_DMA_ACTIVE | S6_I2S_IS_BUSY)))
-                               break;
-                       udelay(20);
-               }
-       }
-       if (n < 0)
-               printk(KERN_WARNING "s6000-i2s: timeout disabling interfaces");
-}
-
-static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
-                                  unsigned int fmt)
-{
-       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
-       u32 w;
-
-       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBM_CFM:
-               w = S6_I2S_SCK_IN | S6_I2S_WS_IN;
-               break;
-       case SND_SOC_DAIFMT_CBS_CFM:
-               w = S6_I2S_SCK_OUT | S6_I2S_WS_IN;
-               break;
-       case SND_SOC_DAIFMT_CBM_CFS:
-               w = S6_I2S_SCK_IN | S6_I2S_WS_OUT;
-               break;
-       case SND_SOC_DAIFMT_CBS_CFS:
-               w = S6_I2S_SCK_OUT | S6_I2S_WS_OUT;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-       case SND_SOC_DAIFMT_NB_NF:
-               w |= S6_I2S_LEFT_FIRST;
-               break;
-       case SND_SOC_DAIFMT_NB_IF:
-               w |= S6_I2S_RIGHT_FIRST;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(0),
-                      S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
-       s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(1),
-                      S6_I2S_FIRST | S6_I2S_WS_DIR | S6_I2S_SCK_DIR, w);
-
-       return 0;
-}
-
-static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
-{
-       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
-
-       if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2)
-               return -EINVAL;
-
-       s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(div_id),
-                      S6_I2S_DIV_MASK, div / 2 - 1);
-       return 0;
-}
-
-static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
-                              struct snd_pcm_hw_params *params,
-                              struct snd_soc_dai *dai)
-{
-       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
-       int interf;
-       u32 w = 0;
-
-       if (dev->wide)
-               interf = 0;
-       else {
-               w |= (((params_channels(params) - 2) / 2)
-                     << S6_I2S_CHANNELS_SHIFT) & S6_I2S_CHANNELS_MASK;
-               interf = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                               ? dev->channel_out : dev->channel_in;
-       }
-
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               w |= S6_I2S_16BIT | S6_I2S_MEM_16BIT;
-               break;
-       case SNDRV_PCM_FORMAT_S32_LE:
-               w |= S6_I2S_32BIT | S6_I2S_MEM_32BIT;
-               break;
-       default:
-               printk(KERN_WARNING "s6000-i2s: unsupported PCM format %x\n",
-                      params_format(params));
-               return -EINVAL;
-       }
-
-       if (s6_i2s_read_reg(dev, S6_I2S_INTERFACE_CFG(interf))
-            & S6_I2S_IS_ENABLED) {
-               printk(KERN_ERR "s6000-i2s: interface already enabled\n");
-               return -EBUSY;
-       }
-
-       s6_i2s_mod_reg(dev, S6_I2S_INTERFACE_CFG(interf),
-                      S6_I2S_CHANNELS_MASK|S6_I2S_MEM_MASK|S6_I2S_BITS_MASK,
-                      w);
-
-       return 0;
-}
-
-static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)
-{
-       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
-       struct s6000_snd_platform_data *pdata = dai->dev->platform_data;
-
-       if (!pdata)
-               return -EINVAL;
-
-       dai->capture_dma_data = &dev->dma_params;
-       dai->playback_dma_data = &dev->dma_params;
-
-       dev->wide = pdata->wide;
-       dev->channel_in = pdata->channel_in;
-       dev->channel_out = pdata->channel_out;
-       dev->lines_in = pdata->lines_in;
-       dev->lines_out = pdata->lines_out;
-
-       s6_i2s_write_reg(dev, S6_I2S_MODE,
-                        dev->wide ? S6_I2S_WIDE : S6_I2S_DUAL);
-
-       if (dev->wide) {
-               int i;
-
-               if (dev->lines_in + dev->lines_out > S6_I2S_NUM_LINES)
-                       return -EINVAL;
-
-               dev->channel_in = 0;
-               dev->channel_out = 1;
-               dai->driver->capture.channels_min = 2 * dev->lines_in;
-               dai->driver->capture.channels_max = dai->driver->capture.channels_min;
-               dai->driver->playback.channels_min = 2 * dev->lines_out;
-               dai->driver->playback.channels_max = dai->driver->playback.channels_min;
-
-               for (i = 0; i < dev->lines_out; i++)
-                       s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT);
-
-               for (; i < S6_I2S_NUM_LINES - dev->lines_in; i++)
-                       s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i),
-                                        S6_I2S_UNUSED);
-
-               for (; i < S6_I2S_NUM_LINES; i++)
-                       s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_IN);
-       } else {
-               unsigned int cfg[2] = {S6_I2S_UNUSED, S6_I2S_UNUSED};
-
-               if (dev->lines_in > 1 || dev->lines_out > 1)
-                       return -EINVAL;
-
-               dai->driver->capture.channels_min = 2 * dev->lines_in;
-               dai->driver->capture.channels_max = 8 * dev->lines_in;
-               dai->driver->playback.channels_min = 2 * dev->lines_out;
-               dai->driver->playback.channels_max = 8 * dev->lines_out;
-
-               if (dev->lines_in)
-                       cfg[dev->channel_in] = S6_I2S_IN;
-               if (dev->lines_out)
-                       cfg[dev->channel_out] = S6_I2S_OUT;
-
-               s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(0), cfg[0]);
-               s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(1), cfg[1]);
-       }
-
-       if (dev->lines_out) {
-               if (dev->lines_in) {
-                       if (!dev->dma_params.dma_out)
-                               return -ENODEV;
-               } else {
-                       dev->dma_params.dma_out = dev->dma_params.dma_in;
-                       dev->dma_params.dma_in = 0;
-               }
-       }
-       dev->dma_params.sif_in = dev->sifbase + (dev->channel_in ?
-                                       S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
-       dev->dma_params.sif_out = dev->sifbase + (dev->channel_out ?
-                                       S6_I2S_SIF_PORT1 : S6_I2S_SIF_PORT0);
-       dev->dma_params.same_rate = pdata->same_rate | pdata->wide;
-       return 0;
-}
-
-#define S6000_I2S_RATES SNDRV_PCM_RATE_CONTINUOUS
-#define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
-
-static const struct snd_soc_dai_ops s6000_i2s_dai_ops = {
-       .set_fmt = s6000_i2s_set_dai_fmt,
-       .set_clkdiv = s6000_i2s_set_clkdiv,
-       .hw_params = s6000_i2s_hw_params,
-};
-
-static struct snd_soc_dai_driver s6000_i2s_dai = {
-       .probe = s6000_i2s_dai_probe,
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 8,
-               .formats = S6000_I2S_FORMATS,
-               .rates = S6000_I2S_RATES,
-               .rate_min = 0,
-               .rate_max = 1562500,
-       },
-       .capture = {
-               .channels_min = 2,
-               .channels_max = 8,
-               .formats = S6000_I2S_FORMATS,
-               .rates = S6000_I2S_RATES,
-               .rate_min = 0,
-               .rate_max = 1562500,
-       },
-       .ops = &s6000_i2s_dai_ops,
-};
-
-static const struct snd_soc_component_driver s6000_i2s_component = {
-       .name           = "s6000-i2s",
-};
-
-static int s6000_i2s_probe(struct platform_device *pdev)
-{
-       struct s6000_i2s_dev *dev;
-       struct resource *scbmem, *sifmem, *region, *dma1, *dma2;
-       u8 __iomem *mmio;
-       int ret;
-
-       scbmem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!scbmem) {
-               dev_err(&pdev->dev, "no mem resource?\n");
-               ret = -ENODEV;
-               goto err_release_none;
-       }
-
-       region = request_mem_region(scbmem->start, resource_size(scbmem),
-                                                               pdev->name);
-       if (!region) {
-               dev_err(&pdev->dev, "I2S SCB region already claimed\n");
-               ret = -EBUSY;
-               goto err_release_none;
-       }
-
-       mmio = ioremap(scbmem->start, resource_size(scbmem));
-       if (!mmio) {
-               dev_err(&pdev->dev, "can't ioremap SCB region\n");
-               ret = -ENOMEM;
-               goto err_release_scb;
-       }
-
-       sifmem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!sifmem) {
-               dev_err(&pdev->dev, "no second mem resource?\n");
-               ret = -ENODEV;
-               goto err_release_map;
-       }
-
-       region = request_mem_region(sifmem->start, resource_size(sifmem),
-                                                               pdev->name);
-       if (!region) {
-               dev_err(&pdev->dev, "I2S SIF region already claimed\n");
-               ret = -EBUSY;
-               goto err_release_map;
-       }
-
-       dma1 = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (!dma1) {
-               dev_err(&pdev->dev, "no dma resource?\n");
-               ret = -ENODEV;
-               goto err_release_sif;
-       }
-
-       region = request_mem_region(dma1->start, resource_size(dma1),
-                                                               pdev->name);
-       if (!region) {
-               dev_err(&pdev->dev, "I2S DMA region already claimed\n");
-               ret = -EBUSY;
-               goto err_release_sif;
-       }
-
-       dma2 = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (dma2) {
-               region = request_mem_region(dma2->start, resource_size(dma2),
-                                                               pdev->name);
-               if (!region) {
-                       dev_err(&pdev->dev,
-                               "I2S DMA region already claimed\n");
-                       ret = -EBUSY;
-                       goto err_release_dma1;
-               }
-       }
-
-       dev = kzalloc(sizeof(struct s6000_i2s_dev), GFP_KERNEL);
-       if (!dev) {
-               ret = -ENOMEM;
-               goto err_release_dma2;
-       }
-       dev_set_drvdata(&pdev->dev, dev);
-
-       dev->sifbase = sifmem->start;
-       dev->scbbase = mmio;
-
-       s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
-       s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_CLEAR,
-                        S6_I2S_INT_ALIGNMENT |
-                        S6_I2S_INT_UNDERRUN |
-                        S6_I2S_INT_OVERRUN);
-
-       s6000_i2s_stop_channel(dev, 0);
-       s6000_i2s_stop_channel(dev, 1);
-       s6000_i2s_wait_disabled(dev);
-
-       dev->dma_params.check_xrun = s6000_i2s_check_xrun;
-       dev->dma_params.trigger = s6000_i2s_trigger;
-       dev->dma_params.dma_in = dma1->start;
-       dev->dma_params.dma_out = dma2 ? dma2->start : 0;
-       dev->dma_params.irq = platform_get_irq(pdev, 0);
-       if (dev->dma_params.irq < 0) {
-               dev_err(&pdev->dev, "no irq resource?\n");
-               ret = -ENODEV;
-               goto err_release_dev;
-       }
-
-       s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE,
-                        S6_I2S_INT_ALIGNMENT |
-                        S6_I2S_INT_UNDERRUN |
-                        S6_I2S_INT_OVERRUN);
-
-       ret = snd_soc_register_component(&pdev->dev, &s6000_i2s_component,
-                                        &s6000_i2s_dai, 1);
-       if (ret)
-               goto err_release_dev;
-
-       return 0;
-
-err_release_dev:
-       kfree(dev);
-err_release_dma2:
-       if (dma2)
-               release_mem_region(dma2->start, resource_size(dma2));
-err_release_dma1:
-       release_mem_region(dma1->start, resource_size(dma1));
-err_release_sif:
-       release_mem_region(sifmem->start, resource_size(sifmem));
-err_release_map:
-       iounmap(mmio);
-err_release_scb:
-       release_mem_region(scbmem->start, resource_size(scbmem));
-err_release_none:
-       return ret;
-}
-
-static int s6000_i2s_remove(struct platform_device *pdev)
-{
-       struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
-       struct resource *region;
-       void __iomem *mmio = dev->scbbase;
-
-       snd_soc_unregister_component(&pdev->dev);
-
-       s6000_i2s_stop_channel(dev, 0);
-       s6000_i2s_stop_channel(dev, 1);
-
-       s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
-       kfree(dev);
-
-       region = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       release_mem_region(region->start, resource_size(region));
-
-       region = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (region)
-               release_mem_region(region->start, resource_size(region));
-
-       region = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(region->start, resource_size(region));
-
-       iounmap(mmio);
-       region = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       release_mem_region(region->start, resource_size(region));
-
-       return 0;
-}
-
-static struct platform_driver s6000_i2s_driver = {
-       .probe  = s6000_i2s_probe,
-       .remove = s6000_i2s_remove,
-       .driver = {
-               .name   = "s6000-i2s",
-               .owner  = THIS_MODULE,
-       },
-};
-
-module_platform_driver(s6000_i2s_driver);
-
-MODULE_AUTHOR("Daniel Gloeckner");
-MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h
deleted file mode 100644 (file)
index 86aa192..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * ALSA SoC I2S Audio Layer for the Stretch s6000 family
- *
- * Author:      Daniel Gloeckner, <dg@emlix.com>
- * Copyright:   (C) 2009 emlix GmbH <info@emlix.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 _S6000_I2S_H
-#define _S6000_I2S_H
-
-struct s6000_snd_platform_data {
-       int lines_in;
-       int lines_out;
-       int channel_in;
-       int channel_out;
-       int wide;
-       int same_rate;
-};
-#endif
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
deleted file mode 100644 (file)
index fb8461e..0000000
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * ALSA PCM interface for the Stetch s6000 family
- *
- * Author:      Daniel Gloeckner, <dg@emlix.com>
- * Copyright:   (C) 2009 emlix GmbH <info@emlix.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/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/dma.h>
-#include <variant/dmac.h>
-
-#include "s6000-pcm.h"
-
-#define S6_PCM_PREALLOCATE_SIZE (96 * 1024)
-#define S6_PCM_PREALLOCATE_MAX  (2048 * 1024)
-
-static struct snd_pcm_hardware s6000_pcm_hardware = {
-       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-                SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_JOINT_DUPLEX),
-       .buffer_bytes_max = 0x7ffffff0,
-       .period_bytes_min = 16,
-       .period_bytes_max = 0xfffff0,
-       .periods_min = 2,
-       .periods_max = 1024, /* no limit */
-       .fifo_size = 0,
-};
-
-struct s6000_runtime_data {
-       spinlock_t lock;
-       int period;             /* current DMA period */
-};
-
-static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct s6000_runtime_data *prtd = runtime->private_data;
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par;
-       int channel;
-       unsigned int period_size;
-       unsigned int dma_offset;
-       dma_addr_t dma_pos;
-       dma_addr_t src, dst;
-
-       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-
-       period_size = snd_pcm_lib_period_bytes(substream);
-       dma_offset = prtd->period * period_size;
-       dma_pos = runtime->dma_addr + dma_offset;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               src = dma_pos;
-               dst = par->sif_out;
-               channel = par->dma_out;
-       } else {
-               src = par->sif_in;
-               dst = dma_pos;
-               channel = par->dma_in;
-       }
-
-       if (!s6dmac_channel_enabled(DMA_MASK_DMAC(channel),
-                                   DMA_INDEX_CHNL(channel)))
-               return;
-
-       if (s6dmac_fifo_full(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel))) {
-               printk(KERN_ERR "s6000-pcm: fifo full\n");
-               return;
-       }
-
-       if (WARN_ON(period_size & 15))
-               return;
-       s6dmac_put_fifo(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel),
-                       src, dst, period_size);
-
-       prtd->period++;
-       if (unlikely(prtd->period >= runtime->periods))
-               prtd->period = 0;
-}
-
-static irqreturn_t s6000_pcm_irq(int irq, void *data)
-{
-       struct snd_pcm *pcm = data;
-       struct snd_soc_pcm_runtime *runtime = pcm->private_data;
-       struct s6000_runtime_data *prtd;
-       unsigned int has_xrun;
-       int i, ret = IRQ_NONE;
-
-       for (i = 0; i < 2; ++i) {
-               struct snd_pcm_substream *substream = pcm->streams[i].substream;
-               struct s6000_pcm_dma_params *params =
-                                       snd_soc_dai_get_dma_data(runtime->cpu_dai, substream);
-               u32 channel;
-               unsigned int pending;
-
-               if (substream == SNDRV_PCM_STREAM_PLAYBACK)
-                       channel = params->dma_out;
-               else
-                       channel = params->dma_in;
-
-               has_xrun = params->check_xrun(runtime->cpu_dai);
-
-               if (!channel)
-                       continue;
-
-               if (unlikely(has_xrun & (1 << i)) &&
-                   substream->runtime &&
-                   snd_pcm_running(substream)) {
-                       dev_dbg(pcm->dev, "xrun\n");
-                       snd_pcm_stream_lock(substream);
-                       snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-                       snd_pcm_stream_unlock(substream);
-                       ret = IRQ_HANDLED;
-               }
-
-               pending = s6dmac_int_sources(DMA_MASK_DMAC(channel),
-                                            DMA_INDEX_CHNL(channel));
-
-               if (pending & 1) {
-                       ret = IRQ_HANDLED;
-                       if (likely(substream->runtime &&
-                                  snd_pcm_running(substream))) {
-                               snd_pcm_period_elapsed(substream);
-                               dev_dbg(pcm->dev, "period elapsed %x %x\n",
-                                      s6dmac_cur_src(DMA_MASK_DMAC(channel),
-                                                  DMA_INDEX_CHNL(channel)),
-                                      s6dmac_cur_dst(DMA_MASK_DMAC(channel),
-                                                  DMA_INDEX_CHNL(channel)));
-                               prtd = substream->runtime->private_data;
-                               spin_lock(&prtd->lock);
-                               s6000_pcm_enqueue_dma(substream);
-                               spin_unlock(&prtd->lock);
-                       }
-               }
-
-               if (unlikely(pending & ~7)) {
-                       if (pending & (1 << 3))
-                               printk(KERN_WARNING
-                                      "s6000-pcm: DMA %x Underflow\n",
-                                      channel);
-                       if (pending & (1 << 4))
-                               printk(KERN_WARNING
-                                      "s6000-pcm: DMA %x Overflow\n",
-                                      channel);
-                       if (pending & 0x1e0)
-                               printk(KERN_WARNING
-                                      "s6000-pcm: DMA %x Master Error "
-                                      "(mask %x)\n",
-                                      channel, pending >> 5);
-
-               }
-       }
-
-       return ret;
-}
-
-static int s6000_pcm_start(struct snd_pcm_substream *substream)
-{
-       struct s6000_runtime_data *prtd = substream->runtime->private_data;
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par;
-       unsigned long flags;
-       int srcinc;
-       u32 dma;
-
-       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-
-       spin_lock_irqsave(&prtd->lock, flags);
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               srcinc = 1;
-               dma = par->dma_out;
-       } else {
-               srcinc = 0;
-               dma = par->dma_in;
-       }
-       s6dmac_enable_chan(DMA_MASK_DMAC(dma), DMA_INDEX_CHNL(dma),
-                          1 /* priority 1 (0 is max) */,
-                          0 /* peripheral requests w/o xfer length mode */,
-                          srcinc /* source address increment */,
-                          srcinc^1 /* destination address increment */,
-                          0 /* chunksize 0 (skip impossible on this dma) */,
-                          0 /* source skip after chunk (impossible) */,
-                          0 /* destination skip after chunk (impossible) */,
-                          4 /* 16 byte burst size */,
-                          -1 /* don't conserve bandwidth */,
-                          0 /* low watermark irq descriptor threshold */,
-                          0 /* disable hardware timestamps */,
-                          1 /* enable channel */);
-
-       s6000_pcm_enqueue_dma(substream);
-       s6000_pcm_enqueue_dma(substream);
-
-       spin_unlock_irqrestore(&prtd->lock, flags);
-
-       return 0;
-}
-
-static int s6000_pcm_stop(struct snd_pcm_substream *substream)
-{
-       struct s6000_runtime_data *prtd = substream->runtime->private_data;
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par;
-       unsigned long flags;
-       u32 channel;
-
-       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               channel = par->dma_out;
-       else
-               channel = par->dma_in;
-
-       s6dmac_set_terminal_count(DMA_MASK_DMAC(channel),
-                                 DMA_INDEX_CHNL(channel), 0);
-
-       spin_lock_irqsave(&prtd->lock, flags);
-
-       s6dmac_disable_chan(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel));
-
-       spin_unlock_irqrestore(&prtd->lock, flags);
-
-       return 0;
-}
-
-static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par;
-       int ret;
-
-       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-
-       ret = par->trigger(substream, cmd, 0);
-       if (ret < 0)
-               return ret;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               ret = s6000_pcm_start(substream);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               ret = s6000_pcm_stop(substream);
-               break;
-       default:
-               ret = -EINVAL;
-       }
-       if (ret < 0)
-               return ret;
-
-       return par->trigger(substream, cmd, 1);
-}
-
-static int s6000_pcm_prepare(struct snd_pcm_substream *substream)
-{
-       struct s6000_runtime_data *prtd = substream->runtime->private_data;
-
-       prtd->period = 0;
-
-       return 0;
-}
-
-static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct s6000_runtime_data *prtd = runtime->private_data;
-       unsigned long flags;
-       unsigned int offset;
-       dma_addr_t count;
-
-       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-
-       spin_lock_irqsave(&prtd->lock, flags);
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               count = s6dmac_cur_src(DMA_MASK_DMAC(par->dma_out),
-                                      DMA_INDEX_CHNL(par->dma_out));
-       else
-               count = s6dmac_cur_dst(DMA_MASK_DMAC(par->dma_in),
-                                      DMA_INDEX_CHNL(par->dma_in));
-
-       count -= runtime->dma_addr;
-
-       spin_unlock_irqrestore(&prtd->lock, flags);
-
-       offset = bytes_to_frames(runtime, count);
-       if (unlikely(offset >= runtime->buffer_size))
-               offset = 0;
-
-       return offset;
-}
-
-static int s6000_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par;
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct s6000_runtime_data *prtd;
-       int ret;
-
-       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-       snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
-
-       ret = snd_pcm_hw_constraint_step(runtime, 0,
-                                        SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
-       if (ret < 0)
-               return ret;
-       ret = snd_pcm_hw_constraint_step(runtime, 0,
-                                        SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
-       if (ret < 0)
-               return ret;
-       ret = snd_pcm_hw_constraint_integer(runtime,
-                                           SNDRV_PCM_HW_PARAM_PERIODS);
-       if (ret < 0)
-               return ret;
-
-       if (par->same_rate) {
-               int rate;
-               spin_lock(&par->lock); /* needed? */
-               rate = par->rate;
-               spin_unlock(&par->lock);
-               if (rate != -1) {
-                       ret = snd_pcm_hw_constraint_minmax(runtime,
-                                                       SNDRV_PCM_HW_PARAM_RATE,
-                                                       rate, rate);
-                       if (ret < 0)
-                               return ret;
-               }
-       }
-
-       prtd = kzalloc(sizeof(struct s6000_runtime_data), GFP_KERNEL);
-       if (prtd == NULL)
-               return -ENOMEM;
-
-       spin_lock_init(&prtd->lock);
-
-       runtime->private_data = prtd;
-
-       return 0;
-}
-
-static int s6000_pcm_close(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct s6000_runtime_data *prtd = runtime->private_data;
-
-       kfree(prtd);
-
-       return 0;
-}
-
-static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par;
-       int ret;
-       ret = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (ret < 0) {
-               printk(KERN_WARNING "s6000-pcm: allocation of memory failed\n");
-               return ret;
-       }
-
-       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-
-       if (par->same_rate) {
-               spin_lock(&par->lock);
-               if (par->rate == -1 ||
-                   !(par->in_use & ~(1 << substream->stream))) {
-                       par->rate = params_rate(hw_params);
-                       par->in_use |= 1 << substream->stream;
-               } else if (params_rate(hw_params) != par->rate) {
-                       snd_pcm_lib_free_pages(substream);
-                       par->in_use &= ~(1 << substream->stream);
-                       ret = -EBUSY;
-               }
-               spin_unlock(&par->lock);
-       }
-       return ret;
-}
-
-static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par =
-               snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
-
-       spin_lock(&par->lock);
-       par->in_use &= ~(1 << substream->stream);
-       if (!par->in_use)
-               par->rate = -1;
-       spin_unlock(&par->lock);
-
-       return snd_pcm_lib_free_pages(substream);
-}
-
-static struct snd_pcm_ops s6000_pcm_ops = {
-       .open =         s6000_pcm_open,
-       .close =        s6000_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    s6000_pcm_hw_params,
-       .hw_free =      s6000_pcm_hw_free,
-       .trigger =      s6000_pcm_trigger,
-       .prepare =      s6000_pcm_prepare,
-       .pointer =      s6000_pcm_pointer,
-};
-
-static void s6000_pcm_free(struct snd_pcm *pcm)
-{
-       struct snd_soc_pcm_runtime *runtime = pcm->private_data;
-       struct s6000_pcm_dma_params *params =
-               snd_soc_dai_get_dma_data(runtime->cpu_dai,
-                       pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
-
-       free_irq(params->irq, pcm);
-       snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
-{
-       struct snd_card *card = runtime->card->snd_card;
-       struct snd_pcm *pcm = runtime->pcm;
-       struct s6000_pcm_dma_params *params;
-       int res;
-
-       params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
-                       pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
-
-       res = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
-       if (res)
-               return res;
-
-       if (params->dma_in) {
-               s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
-                                   DMA_INDEX_CHNL(params->dma_in));
-               s6dmac_int_sources(DMA_MASK_DMAC(params->dma_in),
-                                  DMA_INDEX_CHNL(params->dma_in));
-       }
-
-       if (params->dma_out) {
-               s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_out),
-                                   DMA_INDEX_CHNL(params->dma_out));
-               s6dmac_int_sources(DMA_MASK_DMAC(params->dma_out),
-                                  DMA_INDEX_CHNL(params->dma_out));
-       }
-
-       res = request_irq(params->irq, s6000_pcm_irq, IRQF_SHARED,
-                         "s6000-audio", pcm);
-       if (res) {
-               printk(KERN_ERR "s6000-pcm couldn't get IRQ\n");
-               return res;
-       }
-
-       res = snd_pcm_lib_preallocate_pages_for_all(pcm,
-                                                   SNDRV_DMA_TYPE_DEV,
-                                                   card->dev,
-                                                   S6_PCM_PREALLOCATE_SIZE,
-                                                   S6_PCM_PREALLOCATE_MAX);
-       if (res)
-               printk(KERN_WARNING "s6000-pcm: preallocation failed\n");
-
-       spin_lock_init(&params->lock);
-       params->in_use = 0;
-       params->rate = -1;
-       return 0;
-}
-
-static struct snd_soc_platform_driver s6000_soc_platform = {
-       .ops =          &s6000_pcm_ops,
-       .pcm_new =      s6000_pcm_new,
-       .pcm_free =     s6000_pcm_free,
-};
-
-static int s6000_soc_platform_probe(struct platform_device *pdev)
-{
-       return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
-}
-
-static int s6000_soc_platform_remove(struct platform_device *pdev)
-{
-       snd_soc_unregister_platform(&pdev->dev);
-       return 0;
-}
-
-static struct platform_driver s6000_pcm_driver = {
-       .driver = {
-                       .name = "s6000-pcm-audio",
-                       .owner = THIS_MODULE,
-       },
-
-       .probe = s6000_soc_platform_probe,
-       .remove = s6000_soc_platform_remove,
-};
-
-module_platform_driver(s6000_pcm_driver);
-
-MODULE_AUTHOR("Daniel Gloeckner");
-MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h
deleted file mode 100644 (file)
index 09d9b88..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * ALSA PCM interface for the Stretch s6000 family
- *
- * Author:      Daniel Gloeckner, <dg@emlix.com>
- * Copyright:   (C) 2009 emlix GmbH <info@emlix.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 _S6000_PCM_H
-#define _S6000_PCM_H
-
-struct snd_soc_dai;
-struct snd_pcm_substream;
-
-struct s6000_pcm_dma_params {
-       unsigned int (*check_xrun)(struct snd_soc_dai *cpu_dai);
-       int (*trigger)(struct snd_pcm_substream *substream, int cmd, int after);
-       dma_addr_t sif_in;
-       dma_addr_t sif_out;
-       u32 dma_in;
-       u32 dma_out;
-       int irq;
-       int same_rate;
-
-       spinlock_t lock;
-       int in_use;
-       int rate;
-};
-
-#endif
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
deleted file mode 100644 (file)
index 3510c01..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * ASoC driver for Stretch s6105 IP camera platform
- *
- * Author:      Daniel Gloeckner, <dg@emlix.com>
- * Copyright:   (C) 2009 emlix GmbH <info@emlix.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/module.h>
-#include <linux/moduleparam.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-
-#include "s6000-pcm.h"
-#include "s6000-i2s.h"
-
-#define S6105_CAM_CODEC_CLOCK 12288000
-
-static int s6105_hw_params(struct snd_pcm_substream *substream,
-                          struct snd_pcm_hw_params *params)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int ret = 0;
-
-       /* set codec DAI configuration */
-       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-                                            SND_SOC_DAIFMT_CBM_CFM);
-       if (ret < 0)
-               return ret;
-
-       /* set cpu DAI configuration */
-       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
-                                          SND_SOC_DAIFMT_NB_NF);
-       if (ret < 0)
-               return ret;
-
-       /* set the codec system clock */
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0, S6105_CAM_CODEC_CLOCK,
-                                           SND_SOC_CLOCK_OUT);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static struct snd_soc_ops s6105_ops = {
-       .hw_params = s6105_hw_params,
-};
-
-/* s6105 machine dapm widgets */
-static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
-       SND_SOC_DAPM_LINE("Audio Out Differential", NULL),
-       SND_SOC_DAPM_LINE("Audio Out Stereo", NULL),
-       SND_SOC_DAPM_LINE("Audio In", NULL),
-};
-
-/* s6105 machine audio_mapnections to the codec pins */
-static const struct snd_soc_dapm_route audio_map[] = {
-       /* Audio Out connected to HPLOUT, HPLCOM, HPROUT */
-       {"Audio Out Differential", NULL, "HPLOUT"},
-       {"Audio Out Differential", NULL, "HPLCOM"},
-       {"Audio Out Stereo", NULL, "HPLOUT"},
-       {"Audio Out Stereo", NULL, "HPROUT"},
-
-       /* Audio In connected to LINE1L, LINE1R */
-       {"LINE1L", NULL, "Audio In"},
-       {"LINE1R", NULL, "Audio In"},
-};
-
-static int output_type_info(struct snd_kcontrol *kcontrol,
-                           struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-       uinfo->count = 1;
-       uinfo->value.enumerated.items = 2;
-       if (uinfo->value.enumerated.item) {
-               uinfo->value.enumerated.item = 1;
-               strcpy(uinfo->value.enumerated.name, "HPLOUT/HPROUT");
-       } else {
-               strcpy(uinfo->value.enumerated.name, "HPLOUT/HPLCOM");
-       }
-       return 0;
-}
-
-static int output_type_get(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_value *ucontrol)
-{
-       ucontrol->value.enumerated.item[0] = kcontrol->private_value;
-       return 0;
-}
-
-static int output_type_put(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_card *card = kcontrol->private_data;
-       struct snd_soc_dapm_context *dapm = &card->dapm;
-       unsigned int val = (ucontrol->value.enumerated.item[0] != 0);
-       char *differential = "Audio Out Differential";
-       char *stereo = "Audio Out Stereo";
-
-       if (kcontrol->private_value == val)
-               return 0;
-       kcontrol->private_value = val;
-       snd_soc_dapm_disable_pin(dapm, val ? differential : stereo);
-       snd_soc_dapm_sync(dapm);
-       snd_soc_dapm_enable_pin(dapm, val ? stereo : differential);
-       snd_soc_dapm_sync(dapm);
-
-       return 1;
-}
-
-static const struct snd_kcontrol_new audio_out_mux = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Master Output Mux",
-       .index = 0,
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-       .info = output_type_info,
-       .get = output_type_get,
-       .put = output_type_put,
-       .private_value = 1 /* default to stereo */
-};
-
-/* Logic for a aic3x as connected on the s6105 ip camera ref design */
-static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)
-{
-       struct snd_soc_card *card = rtd->card;
-
-       /* must correspond to audio_out_mux.private_value initializer */
-       snd_soc_dapm_disable_pin(&card->dapm, "Audio Out Differential");
-
-       snd_ctl_add(card->snd_card, snd_ctl_new1(&audio_out_mux, card));
-
-       return 0;
-}
-
-/* s6105 digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link s6105_dai = {
-       .name = "TLV320AIC31",
-       .stream_name = "AIC31",
-       .cpu_dai_name = "s6000-i2s",
-       .codec_dai_name = "tlv320aic3x-hifi",
-       .platform_name = "s6000-pcm-audio",
-       .codec_name = "tlv320aic3x-codec.0-001a",
-       .init = s6105_aic3x_init,
-       .ops = &s6105_ops,
-};
-
-/* s6105 audio machine driver */
-static struct snd_soc_card snd_soc_card_s6105 = {
-       .name = "Stretch IP Camera",
-       .owner = THIS_MODULE,
-       .dai_link = &s6105_dai,
-       .num_links = 1,
-
-       .dapm_widgets = aic3x_dapm_widgets,
-       .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets),
-       .dapm_routes = audio_map,
-       .num_dapm_routes = ARRAY_SIZE(audio_map),
-       .fully_routed = true,
-};
-
-static struct s6000_snd_platform_data s6105_snd_data __initdata = {
-       .wide           = 0,
-       .channel_in     = 0,
-       .channel_out    = 1,
-       .lines_in       = 1,
-       .lines_out      = 1,
-       .same_rate      = 1,
-};
-
-static struct platform_device *s6105_snd_device;
-
-/* temporary i2c device creation until this can be moved into the machine
- * support file.
-*/
-static struct i2c_board_info i2c_device[] = {
-       { I2C_BOARD_INFO("tlv320aic33", 0x18), }
-};
-
-static int __init s6105_init(void)
-{
-       int ret;
-
-       i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device));
-
-       s6105_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!s6105_snd_device)
-               return -ENOMEM;
-
-       platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105);
-       platform_device_add_data(s6105_snd_device, &s6105_snd_data,
-                                sizeof(s6105_snd_data));
-
-       ret = platform_device_add(s6105_snd_device);
-       if (ret)
-               platform_device_put(s6105_snd_device);
-
-       return ret;
-}
-
-static void __exit s6105_exit(void)
-{
-       platform_device_unregister(s6105_snd_device);
-}
-
-module_init(s6105_init);
-module_exit(s6105_exit);
-
-MODULE_AUTHOR("Daniel Gloeckner");
-MODULE_DESCRIPTION("Stretch s6105 IP camera ASoC driver");
-MODULE_LICENSE("GPL");
index 0acf5d0eed53a30979f66d466252b51f660f3d2e..72118a77dd5b70aa2a08fb51c32b5204063829f5 100644 (file)
@@ -110,6 +110,7 @@ static const struct of_device_id snow_of_match[] = {
        { .compatible = "google,snow-audio-max98095", },
        {},
 };
+MODULE_DEVICE_TABLE(of, snow_of_match);
 
 static struct platform_driver snow_driver = {
        .driver = {
index 66fddec9543d0ecc1bb414871d035bc244abc521..88e5df474ccf0ed089e23d9fe00f1268189886c9 100644 (file)
@@ -1711,8 +1711,7 @@ static const struct snd_soc_dai_ops fsi_dai_ops = {
 static struct snd_pcm_hardware fsi_pcm_hardware = {
        .info =         SNDRV_PCM_INFO_INTERLEAVED      |
                        SNDRV_PCM_INFO_MMAP             |
-                       SNDRV_PCM_INFO_MMAP_VALID       |
-                       SNDRV_PCM_INFO_PAUSE,
+                       SNDRV_PCM_INFO_MMAP_VALID,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
        .period_bytes_max       = 8192,
index 1922ec57d10a1fd29c174295adb6de5446e8d7a2..70042197f9e26eaf6f95f5f429435388b12976b4 100644 (file)
@@ -886,8 +886,7 @@ static int rsnd_dai_probe(struct platform_device *pdev,
 static struct snd_pcm_hardware rsnd_pcm_hardware = {
        .info =         SNDRV_PCM_INFO_INTERLEAVED      |
                        SNDRV_PCM_INFO_MMAP             |
-                       SNDRV_PCM_INFO_MMAP_VALID       |
-                       SNDRV_PCM_INFO_PAUSE,
+                       SNDRV_PCM_INFO_MMAP_VALID,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
        .period_bytes_max       = 8192,
index 4c8f8a23a0e9de132827fc041438fc1e07a4892c..b60ff56ebc0f56c2199a3473521fa657d9436713 100644 (file)
@@ -884,7 +884,7 @@ static struct snd_soc_dai *snd_soc_find_dai(
        list_for_each_entry(component, &component_list, list) {
                if (dlc->of_node && component->dev->of_node != dlc->of_node)
                        continue;
-               if (dlc->name && strcmp(dev_name(component->dev), dlc->name))
+               if (dlc->name && strcmp(component->name, dlc->name))
                        continue;
                list_for_each_entry(dai, &component->dai_list, list) {
                        if (dlc->dai_name && strcmp(dai->name, dlc->dai_name))
index 002311afdeaa8bd6ceb40d120b0c6afaa13c6119..57277dd79e112c2b59bf2ee3925bae6228bc30ac 100644 (file)
@@ -1522,13 +1522,36 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
                dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture);
 }
 
+static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd);
+
+/* Set FE's runtime_update state; the state is protected via PCM stream lock
+ * for avoiding the race with trigger callback.
+ * If the state is unset and a trigger is pending while the previous operation,
+ * process the pending trigger action here.
+ */
+static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
+                                    int stream, enum snd_soc_dpcm_update state)
+{
+       struct snd_pcm_substream *substream =
+               snd_soc_dpcm_get_substream(fe, stream);
+
+       snd_pcm_stream_lock_irq(substream);
+       if (state == SND_SOC_DPCM_UPDATE_NO && fe->dpcm[stream].trigger_pending) {
+               dpcm_fe_dai_do_trigger(substream,
+                                      fe->dpcm[stream].trigger_pending - 1);
+               fe->dpcm[stream].trigger_pending = 0;
+       }
+       fe->dpcm[stream].runtime_update = state;
+       snd_pcm_stream_unlock_irq(substream);
+}
+
 static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
 {
        struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
        struct snd_pcm_runtime *runtime = fe_substream->runtime;
        int stream = fe_substream->stream, ret = 0;
 
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
 
        ret = dpcm_be_dai_startup(fe, fe_substream->stream);
        if (ret < 0) {
@@ -1550,13 +1573,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
        dpcm_set_fe_runtime(fe_substream);
        snd_pcm_limit_hw_rates(runtime);
 
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
        return 0;
 
 unwind:
        dpcm_be_dai_startup_unwind(fe, fe_substream->stream);
 be_err:
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
        return ret;
 }
 
@@ -1603,7 +1626,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *fe = substream->private_data;
        int stream = substream->stream;
 
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
 
        /* shutdown the BEs */
        dpcm_be_dai_shutdown(fe, substream->stream);
@@ -1617,7 +1640,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
        dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
 
        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
        return 0;
 }
 
@@ -1665,7 +1688,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
        int err, stream = substream->stream;
 
        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
 
        dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name);
 
@@ -1680,7 +1703,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
        err = dpcm_be_dai_hw_free(fe, stream);
 
        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
 
        mutex_unlock(&fe->card->mutex);
        return 0;
@@ -1773,7 +1796,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
        int ret, stream = substream->stream;
 
        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
 
        memcpy(&fe->dpcm[substream->stream].hw_params, params,
                        sizeof(struct snd_pcm_hw_params));
@@ -1796,7 +1819,7 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
 
 out:
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
        mutex_unlock(&fe->card->mutex);
        return ret;
 }
@@ -1910,7 +1933,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
 }
 EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger);
 
-static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
+static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *fe = substream->private_data;
        int stream = substream->stream, ret;
@@ -1984,6 +2007,23 @@ out:
        return ret;
 }
 
+static int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_soc_pcm_runtime *fe = substream->private_data;
+       int stream = substream->stream;
+
+       /* if FE's runtime_update is already set, we're in race;
+        * process this trigger later at exit
+        */
+       if (fe->dpcm[stream].runtime_update != SND_SOC_DPCM_UPDATE_NO) {
+               fe->dpcm[stream].trigger_pending = cmd + 1;
+               return 0; /* delayed, assuming it's successful */
+       }
+
+       /* we're alone, let's trigger */
+       return dpcm_fe_dai_do_trigger(substream, cmd);
+}
+
 int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
 {
        struct snd_soc_dpcm *dpcm;
@@ -2027,7 +2067,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
 
        dev_dbg(fe->dev, "ASoC: prepare FE %s\n", fe->dai_link->name);
 
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE);
 
        /* there is no point preparing this FE if there are no BEs */
        if (list_empty(&fe->dpcm[stream].be_clients)) {
@@ -2054,7 +2094,7 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
 
 out:
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
        mutex_unlock(&fe->card->mutex);
 
        return ret;
@@ -2201,11 +2241,11 @@ static int dpcm_run_new_update(struct snd_soc_pcm_runtime *fe, int stream)
 {
        int ret;
 
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
        ret = dpcm_run_update_startup(fe, stream);
        if (ret < 0)
                dev_err(fe->dev, "ASoC: failed to startup some BEs\n");
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
 
        return ret;
 }
@@ -2214,11 +2254,11 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
 {
        int ret;
 
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE);
        ret = dpcm_run_update_shutdown(fe, stream);
        if (ret < 0)
                dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n");
-       fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
+       dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
 
        return ret;
 }
index 7ecd0e8a5c51ba435e590090a52259fe0be35561..f61ebb17cc64e3dd33aadd41185e00ea460ebbe9 100644 (file)
@@ -591,18 +591,19 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
 {
        struct snd_card *card;
        struct list_head *p;
+       bool was_shutdown;
 
        if (chip == (void *)-1L)
                return;
 
        card = chip->card;
        down_write(&chip->shutdown_rwsem);
+       was_shutdown = chip->shutdown;
        chip->shutdown = 1;
        up_write(&chip->shutdown_rwsem);
 
        mutex_lock(&register_mutex);
-       chip->num_interfaces--;
-       if (chip->num_interfaces <= 0) {
+       if (!was_shutdown) {
                struct snd_usb_endpoint *ep;
 
                snd_card_disconnect(card);
@@ -622,6 +623,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                list_for_each(p, &chip->mixer_list) {
                        snd_usb_mixer_disconnect(p);
                }
+       }
+
+       chip->num_interfaces--;
+       if (chip->num_interfaces <= 0) {
                usb_chip[chip->index] = NULL;
                mutex_unlock(&register_mutex);
                snd_card_free_when_closed(card);
index 2e4a9dbc51faeca29529da8d231d779a10b92aed..6e354d3268585bfa38e2e35e4b1c6382ceb10067 100644 (file)
@@ -2033,10 +2033,11 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
        cval->res = 1;
        cval->initialized = 1;
 
-       if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
-               cval->control = UAC2_CX_CLOCK_SELECTOR;
-       else
+       if (state->mixer->protocol == UAC_VERSION_1)
                cval->control = 0;
+       else /* UAC_VERSION_2 */
+               cval->control = (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) ?
+                       UAC2_CX_CLOCK_SELECTOR : UAC2_SU_SELECTOR;
 
        namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
        if (!namelist) {
index f119a41ed9a94986cc1ec1ccd99b1aac3c400260..8c9bf4b7aaf0e003db413347efe1ca2ae09053fe 100644 (file)
@@ -593,10 +593,10 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
        if (mixer->chip->shutdown)
                ret = -ENODEV;
        else
-               ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
+               ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                                  0, wIndex,
-                                 &tmp, sizeof(tmp), 1000);
+                                 &tmp, sizeof(tmp));
        up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
@@ -885,6 +885,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        return changed;
 }
 
+static void kctl_private_value_free(struct snd_kcontrol *kctl)
+{
+       kfree((void *)kctl->private_value);
+}
+
 static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
        int validx, int bUnitID)
 {
@@ -919,6 +924,7 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
                return -ENOMEM;
        }
 
+       kctl->private_free = kctl_private_value_free;
        err = snd_ctl_add(mixer->chip->card, kctl);
        if (err < 0)
                return err;
index 223c47b33ba30e767c7af227c974a57471d02b90..c657752a420c024aba8c61fa8ced9b8971434fcf 100644 (file)
@@ -384,6 +384,36 @@ YAMAHA_DEVICE(0x105d, NULL),
                }
        }
 },
+{
+       USB_DEVICE(0x0499, 0x1509),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "Yamaha", */
+               /* .product_name = "Steinberg UR22", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 3,
+                               .type = QUIRK_MIDI_YAMAHA
+                       },
+                       {
+                               .ifnum = 4,
+                               .type = QUIRK_IGNORE_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 {
        USB_DEVICE(0x0499, 0x150a),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
index d2aa45a8d89546b378fa05fc94750a35f6fe5c18..60dfe0d28771bbc244ae8b4e41b737d8281c6f04 100644 (file)
@@ -1146,6 +1146,20 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
        if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) &&
            (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
                mdelay(20);
+
+       /* Marantz/Denon devices with USB DAC functionality need a delay
+        * after each class compliant request
+        */
+       if ((le16_to_cpu(dev->descriptor.idVendor) == 0x154e) &&
+           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) {
+
+               switch (le16_to_cpu(dev->descriptor.idProduct)) {
+               case 0x3005: /* Marantz HD-DAC1 */
+               case 0x3006: /* Marantz SA-14S1 */
+                       mdelay(20);
+                       break;
+               }
+       }
 }
 
 /*
@@ -1179,12 +1193,12 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        /* iFi Audio micro/nano iDSD */
        case USB_ID(0x20b1, 0x3008):
                if (fp->altsetting == 2)
-                       return SNDRV_PCM_FMTBIT_DSD_U32_LE;
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
        /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
        case USB_ID(0x20b1, 0x2009):
                if (fp->altsetting == 3)
-                       return SNDRV_PCM_FMTBIT_DSD_U32_LE;
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
        default:
                break;
index eda326fc86203c87537325e905569e3439bdc304..3727de48c8d50267c4c9cd1df33af69a1ff12643 100644 (file)
@@ -85,8 +85,9 @@ typedef unsigned int u32;
 #define MOVE_MEDIUM                    0xa5
 #define EXCHANGE_MEDIUM                        0xa6
 #define READ_12                                0xa8
+#define SERVICE_ACTION_OUT_12          0xa9
 #define WRITE_12                       0xaa
-#define READ_MEDIA_SERIAL_NUMBER       0xab
+#define SERVICE_ACTION_IN_12           0xab
 #define WRITE_VERIFY_12                        0xae
 #define VERIFY_12                      0xaf
 #define SEARCH_HIGH_12                 0xb0
@@ -107,7 +108,9 @@ typedef unsigned int u32;
 #define VERIFY_16                      0x8f
 #define SYNCHRONIZE_CACHE_16           0x91
 #define WRITE_SAME_16                  0x93
-#define SERVICE_ACTION_IN              0x9e
+#define SERVICE_ACTION_BIDIRECTIONAL   0x9d
+#define SERVICE_ACTION_IN_16           0x9e
+#define SERVICE_ACTION_OUT_16          0x9f
 /* values for service action in */
 #define        SAI_READ_CAPACITY_16            0x10
 #define SAI_GET_LBA_STATUS             0x12
@@ -393,7 +396,7 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
                return scsi_trace_rw16(p, cdb, len);
        case UNMAP:
                return scsi_trace_unmap(p, cdb, len);
-       case SERVICE_ACTION_IN:
+       case SERVICE_ACTION_IN_16:
                return scsi_trace_service_action_in(p, cdb, len);
        case VARIABLE_LENGTH_CMD:
                return scsi_trace_varlen(p, cdb, len);
index 717221e98450a37ffb0eb726e0ffd2773af300ff..40399c3d97d6bcc50396a0961fe90f8309cde9dd 100644 (file)
@@ -2,6 +2,8 @@ PERF-CFLAGS
 PERF-GUI-VARS
 PERF-VERSION-FILE
 perf
+perf-read-vdso32
+perf-read-vdsox32
 perf-help
 perf-record
 perf-report
index 398f8d53bd6d39629071f59dab9ccba4747fc30b..af9a54ece0245fe9c340a0172438e18883b536d3 100644 (file)
@@ -214,6 +214,12 @@ if combined with -a or -C options.
 After starting the program, wait msecs before measuring. This is useful to
 filter out the startup phase of the program, which is often very different.
 
+-I::
+--intr-regs::
+Capture machine state (registers) at interrupt, i.e., on counter overflows for
+each sample. List of captured registers depends on the architecture. This option
+is off by default.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
index 0927bf4e6c2a6c78b30cc185bf0c4637b2c5082e..dd7cccdde49883d30a6114151935ac4e2850cfc0 100644 (file)
@@ -159,7 +159,7 @@ OPTIONS
 --dump-raw-trace::
         Dump raw trace in ASCII.
 
--g [type,min[,limit],order[,key]]::
+-g [type,min[,limit],order[,key][,branch]]::
 --call-graph::
         Display call chains using type, min percent threshold, optional print
        limit and order.
@@ -177,6 +177,11 @@ OPTIONS
        - function: compare on functions
        - address: compare on individual code addresses
 
+       branch can be:
+       - branch: include last branch information in callgraph
+       when available. Usually more convenient to use --branch-history
+       for this.
+
        Default: fractal,0.5,callee,function.
 
 --children::
@@ -266,6 +271,11 @@ OPTIONS
        branch stacks and it will automatically switch to the branch view mode,
        unless --no-branch-stack is used.
 
+--branch-history::
+       Add the addresses of sampled taken branches to the callstack.
+       This allows to examine the path the program took to each sample.
+       The data collection must have used -b (or -j) and -g.
+
 --objdump=<path>::
         Path to objdump binary.
 
index 262916f4a37758447ec0ece4aa17a956c332dd84..478efa9b23640abbad22db3974c7474017ab2a9f 100644 (file)
@@ -60,6 +60,15 @@ include config/utilities.mak
 #
 # Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support
 # for dwarf backtrace post unwind.
+#
+# Define NO_PERF_READ_VDSO32 if you do not want to build perf-read-vdso32
+# for reading the 32-bit compatibility VDSO in 64-bit mode
+#
+# Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32
+# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode
+#
+# Define NO_ZLIB if you do not want to support compressed kernel modules
+
 
 ifeq ($(srctree),)
 srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -171,11 +180,16 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
 
 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
 
-#
-# Single 'perf' binary right now:
-#
 PROGRAMS += $(OUTPUT)perf
 
+ifndef NO_PERF_READ_VDSO32
+PROGRAMS += $(OUTPUT)perf-read-vdso32
+endif
+
+ifndef NO_PERF_READ_VDSOX32
+PROGRAMS += $(OUTPUT)perf-read-vdsox32
+endif
+
 # what 'all' will build and 'install' will install, in perfexecdir
 ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
 
@@ -247,12 +261,14 @@ LIB_H += util/annotate.h
 LIB_H += util/cache.h
 LIB_H += util/callchain.h
 LIB_H += util/build-id.h
+LIB_H += util/db-export.h
 LIB_H += util/debug.h
 LIB_H += util/pmu.h
 LIB_H += util/event.h
 LIB_H += util/evsel.h
 LIB_H += util/evlist.h
 LIB_H += util/exec_cmd.h
+LIB_H += util/find-vdso-map.c
 LIB_H += util/levenshtein.h
 LIB_H += util/machine.h
 LIB_H += util/map.h
@@ -304,6 +320,7 @@ LIB_H += ui/util.h
 LIB_H += ui/ui.h
 LIB_H += util/data.h
 LIB_H += util/kvm-stat.h
+LIB_H += util/thread-stack.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -311,6 +328,7 @@ LIB_OBJS += $(OUTPUT)util/annotate.o
 LIB_OBJS += $(OUTPUT)util/build-id.o
 LIB_OBJS += $(OUTPUT)util/config.o
 LIB_OBJS += $(OUTPUT)util/ctype.o
+LIB_OBJS += $(OUTPUT)util/db-export.o
 LIB_OBJS += $(OUTPUT)util/pmu.o
 LIB_OBJS += $(OUTPUT)util/environment.o
 LIB_OBJS += $(OUTPUT)util/event.o
@@ -380,6 +398,7 @@ LIB_OBJS += $(OUTPUT)util/srcline.o
 LIB_OBJS += $(OUTPUT)util/data.o
 LIB_OBJS += $(OUTPUT)util/tsc.o
 LIB_OBJS += $(OUTPUT)util/cloexec.o
+LIB_OBJS += $(OUTPUT)util/thread-stack.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
@@ -478,8 +497,6 @@ ifneq ($(OUTPUT),)
 endif
 
 ifdef NO_LIBELF
-EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
-
 # Remove ELF/DWARF dependent codes
 LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
 LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
@@ -568,6 +585,10 @@ ifndef NO_LIBNUMA
   BUILTIN_OBJS += $(OUTPUT)bench/numa.o
 endif
 
+ifndef NO_ZLIB
+  LIB_OBJS += $(OUTPUT)util/zlib.o
+endif
+
 ifdef ASCIIDOC8
   export ASCIIDOC8
 endif
@@ -732,6 +753,16 @@ $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Uti
 $(OUTPUT)perf-%: %.o $(PERFLIBS)
        $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
 
+ifndef NO_PERF_READ_VDSO32
+$(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-vdso-map.c
+       $(QUIET_CC)$(CC) -m32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
+endif
+
+ifndef NO_PERF_READ_VDSOX32
+$(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
+       $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
+endif
+
 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 $(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
 
@@ -876,6 +907,14 @@ install-bin: all install-gtk
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
                $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
                $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'
+ifndef NO_PERF_READ_VDSO32
+       $(call QUIET_INSTALL, perf-read-vdso32) \
+               $(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)';
+endif
+ifndef NO_PERF_READ_VDSOX32
+       $(call QUIET_INSTALL, perf-read-vdsox32) \
+               $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)';
+endif
        $(call QUIET_INSTALL, libexec) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
        $(call QUIET_INSTALL, perf-archive) \
@@ -928,7 +967,7 @@ config-clean:
 
 clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
        $(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
-       $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
+       $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
        $(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
        $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
        $(python-clean)
index d73ef8bb08c76a63c8846d4bdf49114c0558908a..3bb50eac5542fc62c4482c92f4478806e731a9f7 100644 (file)
@@ -145,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
  *             yet used)
  *     -1 in case of errors
  */
-static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
+static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
 {
        int             rc = -1;
        Dwfl            *dwfl;
@@ -156,15 +156,27 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
        Dwarf_Addr      end = pc;
        bool            signalp;
 
-       dwfl = dwfl_begin(&offline_callbacks);
-       if (!dwfl) {
-               pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
-               return -1;
-       }
+       dwfl = dso->dwfl;
 
-       if (dwfl_report_offline(dwfl, "",  exec_file, -1) == NULL) {
-               pr_debug("dwfl_report_offline() failed %s\n", dwarf_errmsg(-1));
-               goto out;
+       if (!dwfl) {
+               dwfl = dwfl_begin(&offline_callbacks);
+               if (!dwfl) {
+                       pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
+                       return -1;
+               }
+
+               if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) {
+                       pr_debug("dwfl_report_offline() failed %s\n",
+                                               dwarf_errmsg(-1));
+                       /*
+                        * We normally cache the DWARF debug info and never
+                        * call dwfl_end(). But to prevent fd leak, free in
+                        * case of error.
+                        */
+                       dwfl_end(dwfl);
+                       goto out;
+               }
+               dso->dwfl = dwfl;
        }
 
        mod = dwfl_addrmodule(dwfl, pc);
@@ -194,7 +206,6 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
        rc = check_return_reg(ra_regno, frame);
 
 out:
-       dwfl_end(dwfl);
        return rc;
 }
 
@@ -221,8 +232,7 @@ out:
  *     index:  of callchain entry that needs to be ignored (if any)
  *     -1      if no entry needs to be ignored or in case of errors
  */
-int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
-                               struct ip_callchain *chain)
+int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
 {
        struct addr_location al;
        struct dso *dso = NULL;
@@ -235,7 +245,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
 
        ip = chain->ips[2];
 
-       thread__find_addr_location(thread, machine, PERF_RECORD_MISC_USER,
+       thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
                        MAP__FUNCTION, ip, &al);
 
        if (al.map)
@@ -246,7 +256,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
                return skip_slot;
        }
 
-       rc = check_return_addr(dso->long_name, ip);
+       rc = check_return_addr(dso, ip);
 
        pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n",
                                dso->long_name, chain->nr, ip, rc);
index 8c5c11ca8c539d5292d9ceb3524754e4e06ead49..1ce425d101a99691121b62a2a0c879c4f362fdf5 100644 (file)
@@ -357,6 +357,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
 static struct perf_tool tool = {
        .sample = diff__process_sample_event,
        .mmap   = perf_event__process_mmap,
+       .mmap2  = perf_event__process_mmap2,
        .comm   = perf_event__process_comm,
        .exit   = perf_event__process_exit,
        .fork   = perf_event__process_fork,
@@ -1142,6 +1143,11 @@ static int data_init(int argc, const char **argv)
 
 int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+       int ret = hists__init();
+
+       if (ret < 0)
+               return ret;
+
        perf_config(perf_default_config, NULL);
 
        argc = parse_options(argc, argv, options, diff_usage, 0);
index de99ca1bb94268d01c1baebb5757490c367ec912..84df2deed988ab4e0427b5d34aa7e435ce96a893 100644 (file)
@@ -217,8 +217,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
                goto repipe;
        }
 
-       thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
-                             sample->ip, &al);
+       thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
 
        if (al.map != NULL) {
                if (!al.map->dso->hit) {
@@ -410,6 +409,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                        .tracing_data   = perf_event__repipe_op2_synth,
                        .finished_round = perf_event__repipe_op2_synth,
                        .build_id       = perf_event__repipe_op2_synth,
+                       .id_index       = perf_event__repipe_op2_synth,
                },
                .input_name  = "-",
                .samples = LIST_HEAD_INIT(inject.samples),
index b65eb0507b38a97bb86b948eec3d6c045b5c27e1..3c0f3d4fb021b4b0b6730c23e764d931d23faab2 100644 (file)
@@ -1132,6 +1132,10 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
                "-m", "1024",
                "-c", "1",
        };
+       const char * const kvm_stat_record_usage[] = {
+               "perf kvm stat record [<options>]",
+               NULL
+       };
        const char * const *events_tp;
        events_tp_size = 0;
 
@@ -1159,6 +1163,27 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
        for (j = 1; j < (unsigned int)argc; j++, i++)
                rec_argv[i] = argv[j];
 
+       set_option_flag(record_options, 'e', "event", PARSE_OPT_HIDDEN);
+       set_option_flag(record_options, 0, "filter", PARSE_OPT_HIDDEN);
+       set_option_flag(record_options, 'R', "raw-samples", PARSE_OPT_HIDDEN);
+
+       set_option_flag(record_options, 'F', "freq", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 0, "group", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'g', NULL, PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 0, "call-graph", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'd', "data", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'T', "timestamp", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'P', "period", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'n', "no-samples", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'N', "no-buildid-cache", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'B', "no-buildid", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'G', "cgroup", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'b', "branch-any", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'j', "branch-filter", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 'W', "weight", PARSE_OPT_DISABLED);
+       set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
+
+       record_usage = kvm_stat_record_usage;
        return cmd_record(i, rec_argv, NULL);
 }
 
index 04412b4770a2230ec83296cb179eb397ebb42e94..921bb69425035f08f8cb85bd8933ba26cc9687cf 100644 (file)
@@ -55,6 +55,7 @@ static struct {
        bool show_funcs;
        bool mod_events;
        bool uprobes;
+       bool quiet;
        int nevents;
        struct perf_probe_event events[MAX_PROBES];
        struct strlist *dellist;
@@ -312,9 +313,11 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 #endif
                NULL
 };
-       const struct option options[] = {
+       struct option options[] = {
        OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show parsed arguments, etc)"),
+       OPT_BOOLEAN('q', "quiet", &params.quiet,
+                   "be quiet (do not show any mesages)"),
        OPT_BOOLEAN('l', "list", &params.list_events,
                    "list up current probe events"),
        OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
@@ -375,13 +378,21 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_CALLBACK('x', "exec", NULL, "executable|path",
                        "target executable name or path", opt_set_target),
        OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
-                   "Disable symbol demangling"),
+                   "Enable symbol demangling"),
        OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
                    "Enable kernel symbol demangling"),
        OPT_END()
        };
        int ret;
 
+       set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
+       set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
+       set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
+#ifdef HAVE_DWARF_SUPPORT
+       set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
+       set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
+#endif
+
        argc = parse_options(argc, argv, options, probe_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
        if (argc > 0) {
@@ -396,6 +407,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
                }
        }
 
+       if (params.quiet) {
+               if (verbose != 0) {
+                       pr_err("  Error: -v and -q are exclusive.\n");
+                       return -EINVAL;
+               }
+               verbose = -1;
+       }
+
        if (params.max_probe_points == 0)
                params.max_probe_points = MAX_PROBES;
 
@@ -409,22 +428,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
        symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
 
        if (params.list_events) {
-               if (params.mod_events) {
-                       pr_err("  Error: Don't use --list with --add/--del.\n");
-                       usage_with_options(probe_usage, options);
-               }
-               if (params.show_lines) {
-                       pr_err("  Error: Don't use --list with --line.\n");
-                       usage_with_options(probe_usage, options);
-               }
-               if (params.show_vars) {
-                       pr_err(" Error: Don't use --list with --vars.\n");
-                       usage_with_options(probe_usage, options);
-               }
-               if (params.show_funcs) {
-                       pr_err("  Error: Don't use --list with --funcs.\n");
-                       usage_with_options(probe_usage, options);
-               }
                if (params.uprobes) {
                        pr_warning("  Error: Don't use --list with --exec.\n");
                        usage_with_options(probe_usage, options);
@@ -435,19 +438,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
                return ret;
        }
        if (params.show_funcs) {
-               if (params.nevents != 0 || params.dellist) {
-                       pr_err("  Error: Don't use --funcs with"
-                              " --add/--del.\n");
-                       usage_with_options(probe_usage, options);
-               }
-               if (params.show_lines) {
-                       pr_err("  Error: Don't use --funcs with --line.\n");
-                       usage_with_options(probe_usage, options);
-               }
-               if (params.show_vars) {
-                       pr_err("  Error: Don't use --funcs with --vars.\n");
-                       usage_with_options(probe_usage, options);
-               }
                if (!params.filter)
                        params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
                                                       NULL);
@@ -462,16 +452,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 
 #ifdef HAVE_DWARF_SUPPORT
        if (params.show_lines) {
-               if (params.mod_events) {
-                       pr_err("  Error: Don't use --line with"
-                              " --add/--del.\n");
-                       usage_with_options(probe_usage, options);
-               }
-               if (params.show_vars) {
-                       pr_err(" Error: Don't use --line with --vars.\n");
-                       usage_with_options(probe_usage, options);
-               }
-
                ret = show_line_range(&params.line_range, params.target,
                                      params.uprobes);
                if (ret < 0)
@@ -479,11 +459,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
                return ret;
        }
        if (params.show_vars) {
-               if (params.mod_events) {
-                       pr_err("  Error: Don't use --vars with"
-                              " --add/--del.\n");
-                       usage_with_options(probe_usage, options);
-               }
                if (!params.filter)
                        params.filter = strfilter__new(DEFAULT_VAR_FILTER,
                                                       NULL);
index 2583a9b043178453890c8006b41f138afb9db8f0..8648c6d3003ddb3d64c54142ece0f56b1e30e813 100644 (file)
@@ -200,6 +200,17 @@ static int process_buildids(struct record *rec)
        if (size == 0)
                return 0;
 
+       /*
+        * During this process, it'll load kernel map and replace the
+        * dso->long_name to a real pathname it found.  In this case
+        * we prefer the vmlinux path like
+        *   /lib/modules/3.16.4/build/vmlinux
+        *
+        * rather than build-id path (in debug directory).
+        *   $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
+        */
+       symbol_conf.ignore_vmlinux_buildid = true;
+
        return __perf_session__process_events(session, start,
                                              size - start,
                                              size, &build_id__mark_dso_hit_ops);
@@ -680,11 +691,12 @@ static int perf_record_config(const char *var, const char *value, void *cb)
        return perf_default_config(var, value, cb);
 }
 
-static const char * const record_usage[] = {
+static const char * const __record_usage[] = {
        "perf record [<options>] [<command>]",
        "perf record [<options>] -- <command> [<options>]",
        NULL
 };
+const char * const *record_usage = __record_usage;
 
 /*
  * XXX Ideally would be local to cmd_record() and passed to a record__new
@@ -725,7 +737,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp";
  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
  * using pipes, etc.
  */
-const struct option record_options[] = {
+struct option __record_options[] = {
        OPT_CALLBACK('e', "event", &record.evlist, "event",
                     "event selector. use 'perf list' to list available events",
                     parse_events_option),
@@ -799,9 +811,13 @@ const struct option record_options[] = {
                    "sample transaction flags (special events only)"),
        OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
                    "use per-thread mmaps"),
+       OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
+                   "Sample machine registers on interrupt"),
        OPT_END()
 };
 
+struct option *record_options = __record_options;
+
 int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        int err = -ENOMEM;
index 140a6cd883514b0b14f65a8d7c5fe3e082a8cc64..39367609c707bc0332d4fdbd4a05cf49f4cb78d5 100644 (file)
@@ -226,8 +226,9 @@ static int report__setup_sample_type(struct report *rep)
                        return -EINVAL;
                }
                if (symbol_conf.use_callchain) {
-                       ui__error("Selected -g but no callchain data. Did "
-                                   "you call 'perf record' without -g?\n");
+                       ui__error("Selected -g or --branch-history but no "
+                                 "callchain data. Did\n"
+                                 "you call 'perf record' without -g?\n");
                        return -1;
                }
        } else if (!rep->dont_use_callchains &&
@@ -575,6 +576,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        struct stat st;
        bool has_br_stack = false;
        int branch_mode = -1;
+       bool branch_call_mode = false;
        char callchain_default_opt[] = "fractal,0.5,callee";
        const char * const report_usage[] = {
                "perf report [<options>]",
@@ -637,8 +639,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                   "regex filter to identify parent, see: '--sort parent'"),
        OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
                    "Only display entries with parent-match"),
-       OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
-                    "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
+       OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]",
+                    "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. "
                     "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
        OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
                    "Accumulate callchains of children and show total overhead as well"),
@@ -684,7 +686,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
                    "Show event group information together"),
        OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
-                   "use branch records for histogram filling", parse_branch_mode),
+                   "use branch records for per branch histogram filling",
+                   parse_branch_mode),
+       OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
+                   "add last branch records to call history"),
        OPT_STRING(0, "objdump", &objdump_path, "path",
                   "objdump binary to use for disassembly and annotations"),
        OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
@@ -745,10 +750,24 @@ repeat:
        has_br_stack = perf_header__has_feat(&session->header,
                                             HEADER_BRANCH_STACK);
 
-       if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) {
+       /*
+        * Branch mode is a tristate:
+        * -1 means default, so decide based on the file having branch data.
+        * 0/1 means the user chose a mode.
+        */
+       if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
+           branch_call_mode == -1) {
                sort__mode = SORT_MODE__BRANCH;
                symbol_conf.cumulate_callchain = false;
        }
+       if (branch_call_mode) {
+               callchain_param.key = CCKEY_ADDRESS;
+               callchain_param.branch_callstack = 1;
+               symbol_conf.use_callchain = true;
+               callchain_register_param(&callchain_param);
+               if (sort_order == NULL)
+                       sort_order = "srcline,symbol,dso";
+       }
 
        if (report.mem_mode) {
                if (sort__mode == SORT_MODE__BRANCH) {
index 9708a12905715e78759c88c397dcf27d5c5a863b..ce304dfd962a13db6d2f471a1a6baa304a7bd130 100644 (file)
@@ -23,7 +23,6 @@ static char const             *generate_script_lang;
 static bool                    debug_mode;
 static u64                     last_timestamp;
 static u64                     nr_unordered;
-extern const struct option     record_options[];
 static bool                    no_callchain;
 static bool                    latency_format;
 static bool                    system_wide;
@@ -379,7 +378,6 @@ static void print_sample_start(struct perf_sample *sample,
 
 static void print_sample_addr(union perf_event *event,
                          struct perf_sample *sample,
-                         struct machine *machine,
                          struct thread *thread,
                          struct perf_event_attr *attr)
 {
@@ -390,7 +388,7 @@ static void print_sample_addr(union perf_event *event,
        if (!sample_addr_correlates_sym(attr))
                return;
 
-       perf_event__preprocess_sample_addr(event, sample, machine, thread, &al);
+       perf_event__preprocess_sample_addr(event, sample, thread, &al);
 
        if (PRINT_FIELD(SYM)) {
                printf(" ");
@@ -438,7 +436,7 @@ static void print_sample_bts(union perf_event *event,
            ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
             !output[attr->type].user_set)) {
                printf(" => ");
-               print_sample_addr(event, sample, al->machine, thread, attr);
+               print_sample_addr(event, sample, thread, attr);
        }
 
        if (print_srcline_last)
@@ -475,7 +473,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
                event_format__print(evsel->tp_format, sample->cpu,
                                    sample->raw_data, sample->raw_size);
        if (PRINT_FIELD(ADDR))
-               print_sample_addr(event, sample, al->machine, thread, attr);
+               print_sample_addr(event, sample, thread, attr);
 
        if (PRINT_FIELD(IP)) {
                if (!symbol_conf.use_callchain)
index 055ce9232c9ee0a887e9767e9ba018fe5f501660..89108637638140d44365274b1cd017d9cbdd09a3 100644 (file)
@@ -388,20 +388,102 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
                update_stats(&runtime_itlb_cache_stats[0], count[0]);
 }
 
+static void zero_per_pkg(struct perf_evsel *counter)
+{
+       if (counter->per_pkg_mask)
+               memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
+}
+
+static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
+{
+       unsigned long *mask = counter->per_pkg_mask;
+       struct cpu_map *cpus = perf_evsel__cpus(counter);
+       int s;
+
+       *skip = false;
+
+       if (!counter->per_pkg)
+               return 0;
+
+       if (cpu_map__empty(cpus))
+               return 0;
+
+       if (!mask) {
+               mask = zalloc(MAX_NR_CPUS);
+               if (!mask)
+                       return -ENOMEM;
+
+               counter->per_pkg_mask = mask;
+       }
+
+       s = cpu_map__get_socket(cpus, cpu);
+       if (s < 0)
+               return -1;
+
+       *skip = test_and_set_bit(s, mask) == 1;
+       return 0;
+}
+
+static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
+                  struct perf_counts_values *count)
+{
+       struct perf_counts_values *aggr = &evsel->counts->aggr;
+       static struct perf_counts_values zero;
+       bool skip = false;
+
+       if (check_per_pkg(evsel, cpu, &skip)) {
+               pr_err("failed to read per-pkg counter\n");
+               return -1;
+       }
+
+       if (skip)
+               count = &zero;
+
+       switch (aggr_mode) {
+       case AGGR_CORE:
+       case AGGR_SOCKET:
+       case AGGR_NONE:
+               if (!evsel->snapshot)
+                       perf_evsel__compute_deltas(evsel, cpu, count);
+               perf_counts_values__scale(count, scale, NULL);
+               evsel->counts->cpu[cpu] = *count;
+               update_shadow_stats(evsel, count->values);
+               break;
+       case AGGR_GLOBAL:
+               aggr->val += count->val;
+               if (scale) {
+                       aggr->ena += count->ena;
+                       aggr->run += count->run;
+               }
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int read_counter(struct perf_evsel *counter);
+
 /*
  * Read out the results of a single counter:
  * aggregate counts across CPUs in system-wide mode
  */
 static int read_counter_aggr(struct perf_evsel *counter)
 {
+       struct perf_counts_values *aggr = &counter->counts->aggr;
        struct perf_stat *ps = counter->priv;
        u64 *count = counter->counts->aggr.values;
        int i;
 
-       if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
-                              thread_map__nr(evsel_list->threads), scale) < 0)
+       aggr->val = aggr->ena = aggr->run = 0;
+
+       if (read_counter(counter))
                return -1;
 
+       if (!counter->snapshot)
+               perf_evsel__compute_deltas(counter, -1, aggr);
+       perf_counts_values__scale(aggr, scale, &counter->counts->scaled);
+
        for (i = 0; i < 3; i++)
                update_stats(&ps->res_stats[i], count[i]);
 
@@ -424,16 +506,21 @@ static int read_counter_aggr(struct perf_evsel *counter)
  */
 static int read_counter(struct perf_evsel *counter)
 {
-       u64 *count;
-       int cpu;
+       int nthreads = thread_map__nr(evsel_list->threads);
+       int ncpus = perf_evsel__nr_cpus(counter);
+       int cpu, thread;
 
-       for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-               if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
-                       return -1;
+       if (counter->system_wide)
+               nthreads = 1;
 
-               count = counter->counts->cpu[cpu].values;
+       if (counter->per_pkg)
+               zero_per_pkg(counter);
 
-               update_shadow_stats(counter, count);
+       for (thread = 0; thread < nthreads; thread++) {
+               for (cpu = 0; cpu < ncpus; cpu++) {
+                       if (perf_evsel__read_cb(counter, cpu, thread, read_cb))
+                               return -1;
+               }
        }
 
        return 0;
index 35b425b6293f759b5119d8fb6a07d2ab2303d6f7..f3bb1a4bf060c4a6ad2347f7f40b321916669533 100644 (file)
@@ -528,7 +528,7 @@ static const char *cat_backtrace(union perf_event *event,
                }
 
                tal.filtered = 0;
-               thread__find_addr_location(al.thread, machine, cpumode,
+               thread__find_addr_location(al.thread, cpumode,
                                           MAP__FUNCTION, ip, &tal);
 
                if (tal.sym)
@@ -1963,7 +1963,7 @@ int cmd_timechart(int argc, const char **argv,
                NULL
        };
 
-       const struct option record_options[] = {
+       const struct option timechart_record_options[] = {
        OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
        OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
                    "output processes data only"),
@@ -1972,7 +1972,7 @@ int cmd_timechart(int argc, const char **argv,
        OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
        OPT_END()
        };
-       const char * const record_usage[] = {
+       const char * const timechart_record_usage[] = {
                "perf timechart record [<options>]",
                NULL
        };
@@ -1985,7 +1985,8 @@ int cmd_timechart(int argc, const char **argv,
        }
 
        if (argc && !strncmp(argv[0], "rec", 3)) {
-               argc = parse_options(argc, argv, record_options, record_usage,
+               argc = parse_options(argc, argv, timechart_record_options,
+                                    timechart_record_usage,
                                     PARSE_OPT_STOP_AT_NON_OPTION);
 
                if (tchart.power_only && tchart.tasks_only) {
index fb126459b134ace86ab70b167b67d836a5bd2000..83a4835c8118c5d4fa45aa9f4010e6e4cf33e45d 100644 (file)
@@ -1846,7 +1846,7 @@ static int trace__pgfault(struct trace *trace,
        if (trace->summary_only)
                return 0;
 
-       thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION,
+       thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
                              sample->ip, &al);
 
        trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
@@ -1859,11 +1859,11 @@ static int trace__pgfault(struct trace *trace,
 
        fprintf(trace->output, "] => ");
 
-       thread__find_addr_location(thread, trace->host, cpumode, MAP__VARIABLE,
+       thread__find_addr_location(thread, cpumode, MAP__VARIABLE,
                                   sample->addr, &al);
 
        if (!al.map) {
-               thread__find_addr_location(thread, trace->host, cpumode,
+               thread__find_addr_location(thread, cpumode,
                                           MAP__FUNCTION, sample->addr, &al);
 
                if (al.map)
index 58f609198c6dcce0c7af6082d62c7254c29e5179..5d4b039fe1edc6ebf6f6dafec597e125383d0c4f 100644 (file)
@@ -150,7 +150,7 @@ CFLAGS += -std=gnu99
 # adding assembler files missing the .GNU-stack linker note.
 LDFLAGS += -Wl,-z,noexecstack
 
-EXTLIBS = -lelf -lpthread -lrt -lm -ldl
+EXTLIBS = -lpthread -lrt -lm -ldl
 
 ifneq ($(OUTPUT),)
   OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
@@ -200,7 +200,8 @@ CORE_FEATURE_TESTS =                        \
        libunwind                       \
        stackprotector-all              \
        timerfd                         \
-       libdw-dwarf-unwind
+       libdw-dwarf-unwind              \
+       zlib
 
 LIB_FEATURE_TESTS =                    \
        dwarf                           \
@@ -214,7 +215,8 @@ LIB_FEATURE_TESTS =                 \
        libpython                       \
        libslang                        \
        libunwind                       \
-       libdw-dwarf-unwind
+       libdw-dwarf-unwind              \
+       zlib
 
 VF_FEATURE_TESTS =                     \
        backtrace                       \
@@ -230,7 +232,9 @@ VF_FEATURE_TESTS =                  \
        bionic                          \
        liberty                         \
        liberty-z                       \
-       cplus-demangle
+       cplus-demangle                  \
+       compile-32                      \
+       compile-x32
 
 # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
 # If in the future we need per-feature checks/flags for features not
@@ -350,6 +354,7 @@ endif # NO_LIBELF
 
 ifndef NO_LIBELF
   CFLAGS += -DHAVE_LIBELF_SUPPORT
+  EXTLIBS += -lelf
 
   ifeq ($(feature-libelf-mmap), 1)
     CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
@@ -369,7 +374,7 @@ ifndef NO_LIBELF
     else
       CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
       LDFLAGS += $(LIBDW_LDFLAGS)
-      EXTLIBS += -lelf -ldw
+      EXTLIBS += -ldw
     endif # PERF_HAVE_DWARF_REGS
   endif # NO_DWARF
 endif # NO_LIBELF
@@ -602,6 +607,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),)
   CFLAGS += -DHAVE_LIBBFD_SUPPORT
 endif
 
+ifndef NO_ZLIB
+  ifeq ($(feature-zlib), 1)
+    CFLAGS += -DHAVE_ZLIB_SUPPORT
+    EXTLIBS += -lz
+  else
+    NO_ZLIB := 1
+  endif
+endif
+
 ifndef NO_BACKTRACE
   ifeq ($(feature-backtrace), 1)
     CFLAGS += -DHAVE_BACKTRACE_SUPPORT
@@ -622,6 +636,31 @@ ifdef HAVE_KVM_STAT_SUPPORT
     CFLAGS += -DHAVE_KVM_STAT_SUPPORT
 endif
 
+ifeq (${IS_64_BIT}, 1)
+  ifndef NO_PERF_READ_VDSO32
+    $(call feature_check,compile-32)
+    ifeq ($(feature-compile-32), 1)
+      CFLAGS += -DHAVE_PERF_READ_VDSO32
+    else
+      NO_PERF_READ_VDSO32 := 1
+    endif
+  endif
+  ifneq (${IS_X86_64}, 1)
+    NO_PERF_READ_VDSOX32 := 1
+  endif
+  ifndef NO_PERF_READ_VDSOX32
+    $(call feature_check,compile-x32)
+    ifeq ($(feature-compile-x32), 1)
+      CFLAGS += -DHAVE_PERF_READ_VDSOX32
+    else
+      NO_PERF_READ_VDSOX32 := 1
+    endif
+  endif
+else
+  NO_PERF_READ_VDSO32 := 1
+  NO_PERF_READ_VDSOX32 := 1
+endif
+
 # Among the variables below, these:
 #   perfexecdir
 #   template_dir
index 4b06719ee984618c6154fa0bfbadd78977a4861e..851cd0172a7694a0e21fd18d07c79031d5f9b253 100644 (file)
@@ -21,3 +21,11 @@ ifeq ($(ARCH),x86_64)
     RAW_ARCH := x86_64
   endif
 endif
+
+ifeq (${IS_X86_64}, 1)
+  IS_64_BIT := 1
+else ifeq ($(ARCH),x86)
+  IS_64_BIT := 0
+else
+  IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
+endif
index 72ab2984718e341e0a18f2e4ad0953cc3359a4c6..53f19b5dbc37b3f991eb3afe9a8b09be814f4297 100644 (file)
@@ -27,7 +27,10 @@ FILES=                                       \
        test-libunwind-debug-frame.bin  \
        test-stackprotector-all.bin     \
        test-timerfd.bin                \
-       test-libdw-dwarf-unwind.bin
+       test-libdw-dwarf-unwind.bin     \
+       test-compile-32.bin             \
+       test-compile-x32.bin            \
+       test-zlib.bin
 
 CC := $(CROSS_COMPILE)gcc -MD
 PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -39,7 +42,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
 ###############################
 
 test-all.bin:
-       $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
+       $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz
 
 test-hello.bin:
        $(BUILD)
@@ -131,6 +134,15 @@ test-libdw-dwarf-unwind.bin:
 test-sync-compare-and-swap.bin:
        $(BUILD) -Werror
 
+test-compile-32.bin:
+       $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
+
+test-compile-x32.bin:
+       $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c
+
+test-zlib.bin:
+       $(BUILD) -lz
+
 -include *.d
 
 ###############################
index a7d022e161c0ce8a027e800baa127a5ccb5831e0..652e0098eba6ef7a050ebed5530c6ac757712024 100644 (file)
 # include "test-sync-compare-and-swap.c"
 #undef main
 
+#define main main_test_zlib
+# include "test-zlib.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
        main_test_libpython();
@@ -116,6 +120,7 @@ int main(int argc, char *argv[])
        main_test_stackprotector_all();
        main_test_libdw_dwarf_unwind();
        main_test_sync_compare_and_swap(argc, argv);
+       main_test_zlib();
 
        return 0;
 }
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/perf/config/feature-checks/test-compile.c
new file mode 100644 (file)
index 0000000..31dbf45
--- /dev/null
@@ -0,0 +1,4 @@
+int main(void)
+{
+       return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
new file mode 100644 (file)
index 0000000..e111fff
--- /dev/null
@@ -0,0 +1,9 @@
+#include <zlib.h>
+
+int main(void)
+{
+       z_stream zs;
+
+       inflateInit(&zs);
+       return 0;
+}
diff --git a/tools/perf/perf-read-vdso.c b/tools/perf/perf-read-vdso.c
new file mode 100644 (file)
index 0000000..764e254
--- /dev/null
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <string.h>
+
+#define VDSO__MAP_NAME "[vdso]"
+
+/*
+ * Include definition of find_vdso_map() also used in util/vdso.c for
+ * building perf.
+ */
+#include "util/find-vdso-map.c"
+
+int main(void)
+{
+       void *start, *end;
+       size_t size, written;
+
+       if (find_vdso_map(&start, &end))
+               return 1;
+
+       size = end - start;
+
+       while (size) {
+               written = fwrite(start, 1, size, stdout);
+               if (!written)
+                       return 1;
+               start += written;
+               size -= written;
+       }
+
+       if (fflush(stdout))
+               return 1;
+
+       return 0;
+}
index 937e4324ad94ed601bb43a2d12489c2f90eb841b..a3b13d7dc1d43f3caf301b4d9f941c60d88ed37c 100644 (file)
@@ -13,7 +13,7 @@
 #define wmb()          asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
 #define rmb()          asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
 #define cpu_relax()    asm volatile("rep; nop" ::: "memory");
-#define CPUINFO_PROC   "model name"
+#define CPUINFO_PROC   {"model name"}
 #ifndef __NR_perf_event_open
 # define __NR_perf_event_open 336
 #endif
@@ -30,7 +30,7 @@
 #define wmb()          asm volatile("sfence" ::: "memory")
 #define rmb()          asm volatile("lfence" ::: "memory")
 #define cpu_relax()    asm volatile("rep; nop" ::: "memory");
-#define CPUINFO_PROC   "model name"
+#define CPUINFO_PROC   {"model name"}
 #ifndef __NR_perf_event_open
 # define __NR_perf_event_open 298
 #endif
 #define mb()           asm volatile ("sync" ::: "memory")
 #define wmb()          asm volatile ("sync" ::: "memory")
 #define rmb()          asm volatile ("sync" ::: "memory")
-#define CPUINFO_PROC   "cpu"
+#define CPUINFO_PROC   {"cpu"}
 #endif
 
 #ifdef __s390__
 #define mb()           asm volatile("bcr 15,0" ::: "memory")
 #define wmb()          asm volatile("bcr 15,0" ::: "memory")
 #define rmb()          asm volatile("bcr 15,0" ::: "memory")
-#define CPUINFO_PROC   "vendor_id"
+#define CPUINFO_PROC   {"vendor_id"}
 #endif
 
 #ifdef __sh__
 # define wmb()         asm volatile("" ::: "memory")
 # define rmb()         asm volatile("" ::: "memory")
 #endif
-#define CPUINFO_PROC   "cpu type"
+#define CPUINFO_PROC   {"cpu type"}
 #endif
 
 #ifdef __hppa__
 #define mb()           asm volatile("" ::: "memory")
 #define wmb()          asm volatile("" ::: "memory")
 #define rmb()          asm volatile("" ::: "memory")
-#define CPUINFO_PROC   "cpu"
+#define CPUINFO_PROC   {"cpu"}
 #endif
 
 #ifdef __sparc__
 #endif
 #define wmb()          asm volatile("":::"memory")
 #define rmb()          asm volatile("":::"memory")
-#define CPUINFO_PROC   "cpu"
+#define CPUINFO_PROC   {"cpu"}
 #endif
 
 #ifdef __alpha__
 #define mb()           asm volatile("mb" ::: "memory")
 #define wmb()          asm volatile("wmb" ::: "memory")
 #define rmb()          asm volatile("mb" ::: "memory")
-#define CPUINFO_PROC   "cpu model"
+#define CPUINFO_PROC   {"cpu model"}
 #endif
 
 #ifdef __ia64__
 #define wmb()          asm volatile ("mf" ::: "memory")
 #define rmb()          asm volatile ("mf" ::: "memory")
 #define cpu_relax()    asm volatile ("hint @pause" ::: "memory")
-#define CPUINFO_PROC   "model name"
+#define CPUINFO_PROC   {"model name"}
 #endif
 
 #ifdef __arm__
 #define mb()           ((void(*)(void))0xffff0fa0)()
 #define wmb()          ((void(*)(void))0xffff0fa0)()
 #define rmb()          ((void(*)(void))0xffff0fa0)()
-#define CPUINFO_PROC   "Processor"
+#define CPUINFO_PROC   {"model name", "Processor"}
 #endif
 
 #ifdef __aarch64__
                                : "memory")
 #define wmb()  mb()
 #define rmb()  mb()
-#define CPUINFO_PROC   "cpu model"
+#define CPUINFO_PROC   {"cpu model"}
 #endif
 
 #ifdef __arc__
 #define mb()           asm volatile("" ::: "memory")
 #define wmb()          asm volatile("" ::: "memory")
 #define rmb()          asm volatile("" ::: "memory")
-#define CPUINFO_PROC   "Processor"
+#define CPUINFO_PROC   {"Processor"}
 #endif
 
 #ifdef __metag__
 #define mb()           asm volatile("" ::: "memory")
 #define wmb()          asm volatile("" ::: "memory")
 #define rmb()          asm volatile("" ::: "memory")
-#define CPUINFO_PROC   "CPU"
+#define CPUINFO_PROC   {"CPU"}
 #endif
 
 #ifdef __xtensa__
 #define mb()           asm volatile("memw" ::: "memory")
 #define wmb()          asm volatile("memw" ::: "memory")
 #define rmb()          asm volatile("" ::: "memory")
-#define CPUINFO_PROC   "core ID"
+#define CPUINFO_PROC   {"core ID"}
 #endif
 
 #ifdef __tile__
 #define wmb()          asm volatile ("mf" ::: "memory")
 #define rmb()          asm volatile ("mf" ::: "memory")
 #define cpu_relax()    asm volatile ("mfspr zero, PASS" ::: "memory")
-#define CPUINFO_PROC    "model name"
+#define CPUINFO_PROC    {"model name"}
 #endif
 
 #define barrier() asm volatile ("" ::: "memory")
index 220d44e44c1b1d4fdfafcbe546690d2534108d7f..1dabb855349978de385f45690499d83f86e10580 100644 (file)
@@ -52,6 +52,7 @@ struct record_opts {
        bool         sample_weight;
        bool         sample_time;
        bool         period;
+       bool         sample_intr_regs;
        unsigned int freq;
        unsigned int mmap_pages;
        unsigned int user_freq;
@@ -62,4 +63,7 @@ struct record_opts {
        unsigned     initial_delay;
 };
 
+struct option;
+extern const char * const *record_usage;
+extern struct option *record_options;
 #endif
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-record b/tools/perf/scripts/python/bin/export-to-postgresql-record
new file mode 100644 (file)
index 0000000..221d66e
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+#
+# export perf data to a postgresql database. Can cover
+# perf ip samples (excluding the tracepoints). No special
+# record requirements, just record what you want to export.
+#
+perf record $@
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-report b/tools/perf/scripts/python/bin/export-to-postgresql-report
new file mode 100644 (file)
index 0000000..cd335b6
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/bash
+# description: export perf data to a postgresql database
+# args: [database name] [columns] [calls]
+n_args=0
+for i in "$@"
+do
+    if expr match "$i" "-" > /dev/null ; then
+       break
+    fi
+    n_args=$(( $n_args + 1 ))
+done
+if [ "$n_args" -gt 3 ] ; then
+    echo "usage: export-to-postgresql-report [database name] [columns] [calls]"
+    exit
+fi
+if [ "$n_args" -gt 2 ] ; then
+    dbname=$1
+    columns=$2
+    calls=$3
+    shift 3
+elif [ "$n_args" -gt 1 ] ; then
+    dbname=$1
+    columns=$2
+    shift 2
+elif [ "$n_args" -gt 0 ] ; then
+    dbname=$1
+    shift
+fi
+perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/export-to-postgresql.py $dbname $columns $calls
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
new file mode 100644 (file)
index 0000000..4cdafd8
--- /dev/null
@@ -0,0 +1,444 @@
+# export-to-postgresql.py: export perf data to a postgresql database
+# Copyright (c) 2014, Intel Corporation.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+
+import os
+import sys
+import struct
+import datetime
+
+from PySide.QtSql import *
+
+# Need to access PostgreSQL C library directly to use COPY FROM STDIN
+from ctypes import *
+libpq = CDLL("libpq.so.5")
+PQconnectdb = libpq.PQconnectdb
+PQconnectdb.restype = c_void_p
+PQfinish = libpq.PQfinish
+PQstatus = libpq.PQstatus
+PQexec = libpq.PQexec
+PQexec.restype = c_void_p
+PQresultStatus = libpq.PQresultStatus
+PQputCopyData = libpq.PQputCopyData
+PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ]
+PQputCopyEnd = libpq.PQputCopyEnd
+PQputCopyEnd.argtypes = [ c_void_p, c_void_p ]
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+       '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+# These perf imports are not used at present
+#from perf_trace_context import *
+#from Core import *
+
+perf_db_export_mode = True
+perf_db_export_calls = False
+
+def usage():
+       print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>]"
+       print >> sys.stderr, "where:    columns         'all' or 'branches'"
+       print >> sys.stderr, "          calls           'calls' => create calls table"
+       raise Exception("Too few arguments")
+
+if (len(sys.argv) < 2):
+       usage()
+
+dbname = sys.argv[1]
+
+if (len(sys.argv) >= 3):
+       columns = sys.argv[2]
+else:
+       columns = "all"
+
+if columns not in ("all", "branches"):
+       usage()
+
+branches = (columns == "branches")
+
+if (len(sys.argv) >= 4):
+       if (sys.argv[3] == "calls"):
+               perf_db_export_calls = True
+       else:
+               usage()
+
+output_dir_name = os.getcwd() + "/" + dbname + "-perf-data"
+os.mkdir(output_dir_name)
+
+def do_query(q, s):
+       if (q.exec_(s)):
+               return
+       raise Exception("Query failed: " + q.lastError().text())
+
+print datetime.datetime.today(), "Creating database..."
+
+db = QSqlDatabase.addDatabase('QPSQL')
+query = QSqlQuery(db)
+db.setDatabaseName('postgres')
+db.open()
+try:
+       do_query(query, 'CREATE DATABASE ' + dbname)
+except:
+       os.rmdir(output_dir_name)
+       raise
+query.finish()
+query.clear()
+db.close()
+
+db.setDatabaseName(dbname)
+db.open()
+
+query = QSqlQuery(db)
+do_query(query, 'SET client_min_messages TO WARNING')
+
+do_query(query, 'CREATE TABLE selected_events ('
+               'id             bigint          NOT NULL,'
+               'name           varchar(80))')
+do_query(query, 'CREATE TABLE machines ('
+               'id             bigint          NOT NULL,'
+               'pid            integer,'
+               'root_dir       varchar(4096))')
+do_query(query, 'CREATE TABLE threads ('
+               'id             bigint          NOT NULL,'
+               'machine_id     bigint,'
+               'process_id     bigint,'
+               'pid            integer,'
+               'tid            integer)')
+do_query(query, 'CREATE TABLE comms ('
+               'id             bigint          NOT NULL,'
+               'comm           varchar(16))')
+do_query(query, 'CREATE TABLE comm_threads ('
+               'id             bigint          NOT NULL,'
+               'comm_id        bigint,'
+               'thread_id      bigint)')
+do_query(query, 'CREATE TABLE dsos ('
+               'id             bigint          NOT NULL,'
+               'machine_id     bigint,'
+               'short_name     varchar(256),'
+               'long_name      varchar(4096),'
+               'build_id       varchar(64))')
+do_query(query, 'CREATE TABLE symbols ('
+               'id             bigint          NOT NULL,'
+               'dso_id         bigint,'
+               'sym_start      bigint,'
+               'sym_end        bigint,'
+               'binding        integer,'
+               'name           varchar(2048))')
+do_query(query, 'CREATE TABLE branch_types ('
+               'id             integer         NOT NULL,'
+               'name           varchar(80))')
+
+if branches:
+       do_query(query, 'CREATE TABLE samples ('
+               'id             bigint          NOT NULL,'
+               'evsel_id       bigint,'
+               'machine_id     bigint,'
+               'thread_id      bigint,'
+               'comm_id        bigint,'
+               'dso_id         bigint,'
+               'symbol_id      bigint,'
+               'sym_offset     bigint,'
+               'ip             bigint,'
+               'time           bigint,'
+               'cpu            integer,'
+               'to_dso_id      bigint,'
+               'to_symbol_id   bigint,'
+               'to_sym_offset  bigint,'
+               'to_ip          bigint,'
+               'branch_type    integer,'
+               'in_tx          boolean)')
+else:
+       do_query(query, 'CREATE TABLE samples ('
+               'id             bigint          NOT NULL,'
+               'evsel_id       bigint,'
+               'machine_id     bigint,'
+               'thread_id      bigint,'
+               'comm_id        bigint,'
+               'dso_id         bigint,'
+               'symbol_id      bigint,'
+               'sym_offset     bigint,'
+               'ip             bigint,'
+               'time           bigint,'
+               'cpu            integer,'
+               'to_dso_id      bigint,'
+               'to_symbol_id   bigint,'
+               'to_sym_offset  bigint,'
+               'to_ip          bigint,'
+               'period         bigint,'
+               'weight         bigint,'
+               'transaction    bigint,'
+               'data_src       bigint,'
+               'branch_type    integer,'
+               'in_tx          boolean)')
+
+if perf_db_export_calls:
+       do_query(query, 'CREATE TABLE call_paths ('
+               'id             bigint          NOT NULL,'
+               'parent_id      bigint,'
+               'symbol_id      bigint,'
+               'ip             bigint)')
+       do_query(query, 'CREATE TABLE calls ('
+               'id             bigint          NOT NULL,'
+               'thread_id      bigint,'
+               'comm_id        bigint,'
+               'call_path_id   bigint,'
+               'call_time      bigint,'
+               'return_time    bigint,'
+               'branch_count   bigint,'
+               'call_id        bigint,'
+               'return_id      bigint,'
+               'parent_call_path_id    bigint,'
+               'flags          integer)')
+
+do_query(query, 'CREATE VIEW samples_view AS '
+       'SELECT '
+               'id,'
+               'time,'
+               'cpu,'
+               '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
+               '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
+               '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
+               '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
+               'to_hex(ip) AS ip_hex,'
+               '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
+               'sym_offset,'
+               '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
+               'to_hex(to_ip) AS to_ip_hex,'
+               '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
+               'to_sym_offset,'
+               '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
+               '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
+               'in_tx'
+       ' FROM samples')
+
+
+file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0)
+file_trailer = "\377\377"
+
+def open_output_file(file_name):
+       path_name = output_dir_name + "/" + file_name
+       file = open(path_name, "w+")
+       file.write(file_header)
+       return file
+
+def close_output_file(file):
+       file.write(file_trailer)
+       file.close()
+
+def copy_output_file_direct(file, table_name):
+       close_output_file(file)
+       sql = "COPY " + table_name + " FROM '" + file.name + "' (FORMAT 'binary')"
+       do_query(query, sql)
+
+# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly
+def copy_output_file(file, table_name):
+       conn = PQconnectdb("dbname = " + dbname)
+       if (PQstatus(conn)):
+               raise Exception("COPY FROM STDIN PQconnectdb failed")
+       file.write(file_trailer)
+       file.seek(0)
+       sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')"
+       res = PQexec(conn, sql)
+       if (PQresultStatus(res) != 4):
+               raise Exception("COPY FROM STDIN PQexec failed")
+       data = file.read(65536)
+       while (len(data)):
+               ret = PQputCopyData(conn, data, len(data))
+               if (ret != 1):
+                       raise Exception("COPY FROM STDIN PQputCopyData failed, error " + str(ret))
+               data = file.read(65536)
+       ret = PQputCopyEnd(conn, None)
+       if (ret != 1):
+               raise Exception("COPY FROM STDIN PQputCopyEnd failed, error " + str(ret))
+       PQfinish(conn)
+
+def remove_output_file(file):
+       name = file.name
+       file.close()
+       os.unlink(name)
+
+evsel_file             = open_output_file("evsel_table.bin")
+machine_file           = open_output_file("machine_table.bin")
+thread_file            = open_output_file("thread_table.bin")
+comm_file              = open_output_file("comm_table.bin")
+comm_thread_file       = open_output_file("comm_thread_table.bin")
+dso_file               = open_output_file("dso_table.bin")
+symbol_file            = open_output_file("symbol_table.bin")
+branch_type_file       = open_output_file("branch_type_table.bin")
+sample_file            = open_output_file("sample_table.bin")
+if perf_db_export_calls:
+       call_path_file          = open_output_file("call_path_table.bin")
+       call_file               = open_output_file("call_table.bin")
+
+def trace_begin():
+       print datetime.datetime.today(), "Writing to intermediate files..."
+       # id == 0 means unknown.  It is easier to create records for them than replace the zeroes with NULLs
+       evsel_table(0, "unknown")
+       machine_table(0, 0, "unknown")
+       thread_table(0, 0, 0, -1, -1)
+       comm_table(0, "unknown")
+       dso_table(0, 0, "unknown", "unknown", "")
+       symbol_table(0, 0, 0, 0, 0, "unknown")
+       sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+       if perf_db_export_calls:
+               call_path_table(0, 0, 0, 0)
+
+unhandled_count = 0
+
+def trace_end():
+       print datetime.datetime.today(), "Copying to database..."
+       copy_output_file(evsel_file,            "selected_events")
+       copy_output_file(machine_file,          "machines")
+       copy_output_file(thread_file,           "threads")
+       copy_output_file(comm_file,             "comms")
+       copy_output_file(comm_thread_file,      "comm_threads")
+       copy_output_file(dso_file,              "dsos")
+       copy_output_file(symbol_file,           "symbols")
+       copy_output_file(branch_type_file,      "branch_types")
+       copy_output_file(sample_file,           "samples")
+       if perf_db_export_calls:
+               copy_output_file(call_path_file,        "call_paths")
+               copy_output_file(call_file,             "calls")
+
+       print datetime.datetime.today(), "Removing intermediate files..."
+       remove_output_file(evsel_file)
+       remove_output_file(machine_file)
+       remove_output_file(thread_file)
+       remove_output_file(comm_file)
+       remove_output_file(comm_thread_file)
+       remove_output_file(dso_file)
+       remove_output_file(symbol_file)
+       remove_output_file(branch_type_file)
+       remove_output_file(sample_file)
+       if perf_db_export_calls:
+               remove_output_file(call_path_file)
+               remove_output_file(call_file)
+       os.rmdir(output_dir_name)
+       print datetime.datetime.today(), "Adding primary keys"
+       do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE machines        ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE threads         ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE comms           ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE comm_threads    ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE dsos            ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE symbols         ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE branch_types    ADD PRIMARY KEY (id)')
+       do_query(query, 'ALTER TABLE samples         ADD PRIMARY KEY (id)')
+       if perf_db_export_calls:
+               do_query(query, 'ALTER TABLE call_paths      ADD PRIMARY KEY (id)')
+               do_query(query, 'ALTER TABLE calls           ADD PRIMARY KEY (id)')
+
+       print datetime.datetime.today(), "Adding foreign keys"
+       do_query(query, 'ALTER TABLE threads '
+                                       'ADD CONSTRAINT machinefk  FOREIGN KEY (machine_id)   REFERENCES machines   (id),'
+                                       'ADD CONSTRAINT processfk  FOREIGN KEY (process_id)   REFERENCES threads    (id)')
+       do_query(query, 'ALTER TABLE comm_threads '
+                                       'ADD CONSTRAINT commfk     FOREIGN KEY (comm_id)      REFERENCES comms      (id),'
+                                       'ADD CONSTRAINT threadfk   FOREIGN KEY (thread_id)    REFERENCES threads    (id)')
+       do_query(query, 'ALTER TABLE dsos '
+                                       'ADD CONSTRAINT machinefk  FOREIGN KEY (machine_id)   REFERENCES machines   (id)')
+       do_query(query, 'ALTER TABLE symbols '
+                                       'ADD CONSTRAINT dsofk      FOREIGN KEY (dso_id)       REFERENCES dsos       (id)')
+       do_query(query, 'ALTER TABLE samples '
+                                       'ADD CONSTRAINT evselfk    FOREIGN KEY (evsel_id)     REFERENCES selected_events (id),'
+                                       'ADD CONSTRAINT machinefk  FOREIGN KEY (machine_id)   REFERENCES machines   (id),'
+                                       'ADD CONSTRAINT threadfk   FOREIGN KEY (thread_id)    REFERENCES threads    (id),'
+                                       'ADD CONSTRAINT commfk     FOREIGN KEY (comm_id)      REFERENCES comms      (id),'
+                                       'ADD CONSTRAINT dsofk      FOREIGN KEY (dso_id)       REFERENCES dsos       (id),'
+                                       'ADD CONSTRAINT symbolfk   FOREIGN KEY (symbol_id)    REFERENCES symbols    (id),'
+                                       'ADD CONSTRAINT todsofk    FOREIGN KEY (to_dso_id)    REFERENCES dsos       (id),'
+                                       'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols    (id)')
+       if perf_db_export_calls:
+               do_query(query, 'ALTER TABLE call_paths '
+                                       'ADD CONSTRAINT parentfk    FOREIGN KEY (parent_id)    REFERENCES call_paths (id),'
+                                       'ADD CONSTRAINT symbolfk    FOREIGN KEY (symbol_id)    REFERENCES symbols    (id)')
+               do_query(query, 'ALTER TABLE calls '
+                                       'ADD CONSTRAINT threadfk    FOREIGN KEY (thread_id)    REFERENCES threads    (id),'
+                                       'ADD CONSTRAINT commfk      FOREIGN KEY (comm_id)      REFERENCES comms      (id),'
+                                       'ADD CONSTRAINT call_pathfk FOREIGN KEY (call_path_id) REFERENCES call_paths (id),'
+                                       'ADD CONSTRAINT callfk      FOREIGN KEY (call_id)      REFERENCES samples    (id),'
+                                       'ADD CONSTRAINT returnfk    FOREIGN KEY (return_id)    REFERENCES samples    (id),'
+                                       'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)')
+               do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
+
+       if (unhandled_count):
+               print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
+       print datetime.datetime.today(), "Done"
+
+def trace_unhandled(event_name, context, event_fields_dict):
+       global unhandled_count
+       unhandled_count += 1
+
+def sched__sched_switch(*x):
+       pass
+
+def evsel_table(evsel_id, evsel_name, *x):
+       n = len(evsel_name)
+       fmt = "!hiqi" + str(n) + "s"
+       value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name)
+       evsel_file.write(value)
+
+def machine_table(machine_id, pid, root_dir, *x):
+       n = len(root_dir)
+       fmt = "!hiqiii" + str(n) + "s"
+       value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir)
+       machine_file.write(value)
+
+def thread_table(thread_id, machine_id, process_id, pid, tid, *x):
+       value = struct.pack("!hiqiqiqiiii", 5, 8, thread_id, 8, machine_id, 8, process_id, 4, pid, 4, tid)
+       thread_file.write(value)
+
+def comm_table(comm_id, comm_str, *x):
+       n = len(comm_str)
+       fmt = "!hiqi" + str(n) + "s"
+       value = struct.pack(fmt, 2, 8, comm_id, n, comm_str)
+       comm_file.write(value)
+
+def comm_thread_table(comm_thread_id, comm_id, thread_id, *x):
+       fmt = "!hiqiqiq"
+       value = struct.pack(fmt, 3, 8, comm_thread_id, 8, comm_id, 8, thread_id)
+       comm_thread_file.write(value)
+
+def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
+       n1 = len(short_name)
+       n2 = len(long_name)
+       n3 = len(build_id)
+       fmt = "!hiqiqi" + str(n1) + "si"  + str(n2) + "si" + str(n3) + "s"
+       value = struct.pack(fmt, 5, 8, dso_id, 8, machine_id, n1, short_name, n2, long_name, n3, build_id)
+       dso_file.write(value)
+
+def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x):
+       n = len(symbol_name)
+       fmt = "!hiqiqiqiqiii" + str(n) + "s"
+       value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name)
+       symbol_file.write(value)
+
+def branch_type_table(branch_type, name, *x):
+       n = len(name)
+       fmt = "!hiii" + str(n) + "s"
+       value = struct.pack(fmt, 2, 4, branch_type, n, name)
+       branch_type_file.write(value)
+
+def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, *x):
+       if branches:
+               value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiB", 17, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx)
+       else:
+               value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiB", 21, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx)
+       sample_file.write(value)
+
+def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
+       fmt = "!hiqiqiqiq"
+       value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip)
+       call_path_file.write(value)
+
+def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x):
+       fmt = "!hiqiqiqiqiqiqiqiqiqiqii"
+       value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags)
+       call_file.write(value)
index 162c978f1491a9e49dd6f37e1dd34ccb40d2a540..4b7d9ab0f0492867fa0154ce6da3d6418034cad1 100644 (file)
@@ -85,7 +85,7 @@ static struct test {
                .func = test__hists_link,
        },
        {
-               .desc = "Try 'use perf' in python, checking link problems",
+               .desc = "Try 'import perf' in python, checking link problems",
                .func = test__python_use,
        },
        {
index 67f2d63235587be7a6c3b7725727d28c1d4022f0..f671ec37a7c40c1346ebe92e77a6d201bc89305e 100644 (file)
@@ -133,8 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
 }
 
 static int read_object_code(u64 addr, size_t len, u8 cpumode,
-                           struct thread *thread, struct machine *machine,
-                           struct state *state)
+                           struct thread *thread, struct state *state)
 {
        struct addr_location al;
        unsigned char buf1[BUFSZ];
@@ -145,8 +144,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
 
        pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
 
-       thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr,
-                             &al);
+       thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
        if (!al.map || !al.map->dso) {
                pr_debug("thread__find_addr_map failed\n");
                return -1;
@@ -170,8 +168,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
                len = al.map->end - addr;
 
        /* Read the object code using perf */
-       ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1,
-                                       len);
+       ret_len = dso__data_read_offset(al.map->dso, thread->mg->machine,
+                                       al.addr, buf1, len);
        if (ret_len != len) {
                pr_debug("dso__data_read_offset failed\n");
                return -1;
@@ -264,8 +262,7 @@ static int process_sample_event(struct machine *machine,
 
        cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
-       return read_object_code(sample.ip, READLEN, cpumode, thread, machine,
-                               state);
+       return read_object_code(sample.ip, READLEN, cpumode, thread, state);
 }
 
 static int process_event(struct machine *machine, struct perf_evlist *evlist,
index fc25e57f4a5d2bdf5455c9db75298b4700b34c04..ab28cca2cb97ad436dd7c419ee4ee7fa37ecb0b9 100644 (file)
@@ -59,7 +59,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
 }
 
 __attribute__ ((noinline))
-static int unwind_thread(struct thread *thread, struct machine *machine)
+static int unwind_thread(struct thread *thread)
 {
        struct perf_sample sample;
        unsigned long cnt = 0;
@@ -72,7 +72,7 @@ static int unwind_thread(struct thread *thread, struct machine *machine)
                goto out;
        }
 
-       err = unwind__get_entries(unwind_entry, &cnt, machine, thread,
+       err = unwind__get_entries(unwind_entry, &cnt, thread,
                                  &sample, MAX_STACK);
        if (err)
                pr_debug("unwind failed\n");
@@ -89,21 +89,21 @@ static int unwind_thread(struct thread *thread, struct machine *machine)
 }
 
 __attribute__ ((noinline))
-static int krava_3(struct thread *thread, struct machine *machine)
+static int krava_3(struct thread *thread)
 {
-       return unwind_thread(thread, machine);
+       return unwind_thread(thread);
 }
 
 __attribute__ ((noinline))
-static int krava_2(struct thread *thread, struct machine *machine)
+static int krava_2(struct thread *thread)
 {
-       return krava_3(thread, machine);
+       return krava_3(thread);
 }
 
 __attribute__ ((noinline))
-static int krava_1(struct thread *thread, struct machine *machine)
+static int krava_1(struct thread *thread)
 {
-       return krava_2(thread, machine);
+       return krava_2(thread);
 }
 
 int test__dwarf_unwind(void)
@@ -137,7 +137,7 @@ int test__dwarf_unwind(void)
                goto out;
        }
 
-       err = krava_1(thread, machine);
+       err = krava_1(thread);
 
  out:
        machine__delete_threads(machine);
index 5a31787cc6b915031a93d83a8a44001b1b8a8269..74f257a812653177f9d334d7a25df8359d8ef3d4 100644 (file)
@@ -43,7 +43,7 @@ static struct sample fake_samples[] = {
 };
 
 static int add_hist_entries(struct perf_evlist *evlist,
-                           struct machine *machine __maybe_unused)
+                           struct machine *machine)
 {
        struct perf_evsel *evsel;
        struct addr_location al;
index 4a456fef66ca06ab05cb76ccd9d79b18746ee9f0..2113f1c8611fb569b0fb6bc7f676477e7de0a666 100644 (file)
@@ -187,7 +187,7 @@ static int mmap_events(synth_cb synth)
 
                pr_debug("looking for map %p\n", td->map);
 
-               thread__find_addr_map(thread, machine,
+               thread__find_addr_map(thread,
                                      PERF_RECORD_MISC_USER, MAP__FUNCTION,
                                      (unsigned long) (td->map + 1), &al);
 
index ca292f9a4ae241e07ce53af24514417cb9ffaa41..4908c648a59783fa0dee6f78055a1ec454f50fed 100644 (file)
@@ -126,16 +126,28 @@ static bool samples_same(const struct perf_sample *s1,
        if (type & PERF_SAMPLE_TRANSACTION)
                COMP(transaction);
 
+       if (type & PERF_SAMPLE_REGS_INTR) {
+               size_t sz = hweight_long(s1->intr_regs.mask) * sizeof(u64);
+
+               COMP(intr_regs.mask);
+               COMP(intr_regs.abi);
+               if (s1->intr_regs.abi &&
+                   (!s1->intr_regs.regs || !s2->intr_regs.regs ||
+                    memcmp(s1->intr_regs.regs, s2->intr_regs.regs, sz))) {
+                       pr_debug("Samples differ at 'intr_regs'\n");
+                       return false;
+               }
+       }
+
        return true;
 }
 
-static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
+static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
 {
        struct perf_evsel evsel = {
                .needs_swap = false,
                .attr = {
                        .sample_type = sample_type,
-                       .sample_regs_user = sample_regs_user,
                        .read_format = read_format,
                },
        };
@@ -154,7 +166,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
                /* 1 branch_entry */
                .data = {1, 211, 212, 213},
        };
-       u64 user_regs[64];
+       u64 regs[64];
        const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL};
        const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
        struct perf_sample sample = {
@@ -176,8 +188,8 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
                .branch_stack   = &branch_stack.branch_stack,
                .user_regs      = {
                        .abi    = PERF_SAMPLE_REGS_ABI_64,
-                       .mask   = sample_regs_user,
-                       .regs   = user_regs,
+                       .mask   = sample_regs,
+                       .regs   = regs,
                },
                .user_stack     = {
                        .size   = sizeof(data),
@@ -187,14 +199,25 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
                        .time_enabled = 0x030a59d664fca7deULL,
                        .time_running = 0x011b6ae553eb98edULL,
                },
+               .intr_regs      = {
+                       .abi    = PERF_SAMPLE_REGS_ABI_64,
+                       .mask   = sample_regs,
+                       .regs   = regs,
+               },
        };
        struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
        struct perf_sample sample_out;
        size_t i, sz, bufsz;
        int err, ret = -1;
 
-       for (i = 0; i < sizeof(user_regs); i++)
-               *(i + (u8 *)user_regs) = i & 0xfe;
+       if (sample_type & PERF_SAMPLE_REGS_USER)
+               evsel.attr.sample_regs_user = sample_regs;
+
+       if (sample_type & PERF_SAMPLE_REGS_INTR)
+               evsel.attr.sample_regs_intr = sample_regs;
+
+       for (i = 0; i < sizeof(regs); i++)
+               *(i + (u8 *)regs) = i & 0xfe;
 
        if (read_format & PERF_FORMAT_GROUP) {
                sample.read.group.nr     = 4;
@@ -271,7 +294,7 @@ int test__sample_parsing(void)
 {
        const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
        u64 sample_type;
-       u64 sample_regs_user;
+       u64 sample_regs;
        size_t i;
        int err;
 
@@ -280,7 +303,7 @@ int test__sample_parsing(void)
         * were added.  Please actually update the test rather than just change
         * the condition below.
         */
-       if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) {
+       if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) {
                pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
                return -1;
        }
@@ -297,22 +320,24 @@ int test__sample_parsing(void)
                        }
                        continue;
                }
+               sample_regs = 0;
 
                if (sample_type == PERF_SAMPLE_REGS_USER)
-                       sample_regs_user = 0x3fff;
-               else
-                       sample_regs_user = 0;
+                       sample_regs = 0x3fff;
+
+               if (sample_type == PERF_SAMPLE_REGS_INTR)
+                       sample_regs = 0xff0fff;
 
-               err = do_test(sample_type, sample_regs_user, 0);
+               err = do_test(sample_type, sample_regs, 0);
                if (err)
                        return err;
        }
 
        /* Test all sample format bits together */
        sample_type = PERF_SAMPLE_MAX - 1;
-       sample_regs_user = 0x3fff;
+       sample_regs = 0x3fff; /* shared yb intr and user regs */
        for (i = 0; i < ARRAY_SIZE(rf); i++) {
-               err = do_test(sample_type, sample_regs_user, rf[i]);
+               err = do_test(sample_type, sample_regs, rf[i]);
                if (err)
                        return err;
        }
index f0697a3aede04cb19f91d459cab62a6c08c5326f..1e0a2fd80115aba0654008d87a26fb3bf53f6177 100644 (file)
@@ -27,6 +27,7 @@ static struct annotate_browser_opt {
        bool hide_src_code,
             use_offset,
             jump_arrows,
+            show_linenr,
             show_nr_jumps;
 } annotate_browser__opts = {
        .use_offset     = true,
@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
        if (!*dl->line)
                slsmg_write_nstring(" ", width - pcnt_width);
        else if (dl->offset == -1) {
-               printed = scnprintf(bf, sizeof(bf), "%*s  ",
+               if (dl->line_nr && annotate_browser__opts.show_linenr)
+                       printed = scnprintf(bf, sizeof(bf), "%-*d ",
+                                       ab->addr_width + 1, dl->line_nr);
+               else
+                       printed = scnprintf(bf, sizeof(bf), "%*s  ",
                                    ab->addr_width, " ");
                slsmg_write_nstring(bf, printed);
                slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1);
@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
                "o             Toggle disassembler output/simplified view\n"
                "s             Toggle source code view\n"
                "/             Search string\n"
+               "k             Toggle line numbers\n"
                "r             Run available scripts\n"
                "?             Search string backwards\n");
                        continue;
@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser,
                                script_browse(NULL);
                                continue;
                        }
+               case 'k':
+                       annotate_browser__opts.show_linenr =
+                               !annotate_browser__opts.show_linenr;
+                       break;
                case 'H':
                        nd = browser->curr_hot;
                        break;
@@ -984,6 +994,7 @@ static struct annotate_config {
 } annotate__configs[] = {
        ANNOTATE_CFG(hide_src_code),
        ANNOTATE_CFG(jump_arrows),
+       ANNOTATE_CFG(show_linenr),
        ANNOTATE_CFG(show_nr_jumps),
        ANNOTATE_CFG(use_offset),
 };
index cfb976b3de3a0a1593b96f33c2c4136acdccf6aa..502daff76ceba70be29243aecc13bab3040c0a20 100644 (file)
@@ -227,10 +227,14 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *no
        }
 }
 
-static void callchain_node__init_have_children(struct callchain_node *node)
+static void callchain_node__init_have_children(struct callchain_node *node,
+                                              bool has_sibling)
 {
        struct callchain_list *chain;
 
+       chain = list_entry(node->val.next, struct callchain_list, list);
+       chain->ms.has_children = has_sibling;
+
        if (!list_empty(&node->val)) {
                chain = list_entry(node->val.prev, struct callchain_list, list);
                chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
@@ -241,11 +245,12 @@ static void callchain_node__init_have_children(struct callchain_node *node)
 
 static void callchain__init_have_children(struct rb_root *root)
 {
-       struct rb_node *nd;
+       struct rb_node *nd = rb_first(root);
+       bool has_sibling = nd && rb_next(nd);
 
        for (nd = rb_first(root); nd; nd = rb_next(nd)) {
                struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
-               callchain_node__init_have_children(node);
+               callchain_node__init_have_children(node, has_sibling);
        }
 }
 
@@ -463,23 +468,6 @@ out:
        return key;
 }
 
-static char *callchain_list__sym_name(struct callchain_list *cl,
-                                     char *bf, size_t bfsize, bool show_dso)
-{
-       int printed;
-
-       if (cl->ms.sym)
-               printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
-       else
-               printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
-
-       if (show_dso)
-               scnprintf(bf + printed, bfsize - printed, " %s",
-                         cl->ms.map ? cl->ms.map->dso->short_name : "unknown");
-
-       return bf;
-}
-
 struct callchain_print_arg {
        /* for hists browser */
        off_t   row_offset;
@@ -559,8 +547,11 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
        struct rb_node *node;
        int first_row = row, offset = level * LEVEL_OFFSET_STEP;
        u64 new_total;
+       bool need_percent;
 
        node = rb_first(root);
+       need_percent = !!rb_next(node);
+
        while (node) {
                struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
                struct rb_node *next = rb_next(node);
@@ -577,7 +568,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
 
                        if (first)
                                first = false;
-                       else if (level > 1)
+                       else if (need_percent)
                                extra_offset = LEVEL_OFFSET_STEP;
 
                        folded_sign = callchain_list__folded(chain);
@@ -590,7 +581,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
                        str = callchain_list__sym_name(chain, bf, sizeof(bf),
                                                       browser->show_dso);
 
-                       if (was_first && level > 1) {
+                       if (was_first && need_percent) {
                                double percent = cumul * 100.0 / total;
 
                                if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
@@ -807,6 +798,13 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        .is_current_entry = current_entry,
                };
 
+               if (callchain_param.mode == CHAIN_GRAPH_REL) {
+                       if (symbol_conf.cumulate_callchain)
+                               total = entry->stat_acc->period;
+                       else
+                               total = entry->stat.period;
+               }
+
                printed += hist_browser__show_callchain(browser,
                                        &entry->sorted_chain, 1, row, total,
                                        hist_browser__show_callchain_entry, &arg,
index fc654fb77ace52769294ad70b6846fc4fa5f0ee9..4b3585eed1e84be6feb0243f4f9f0cbd7e1ef592 100644 (file)
@@ -89,15 +89,6 @@ void perf_gtk__init_hpp(void)
                                perf_gtk__hpp_color_overhead_acc;
 }
 
-static void callchain_list__sym_name(struct callchain_list *cl,
-                                    char *bf, size_t bfsize)
-{
-       if (cl->ms.sym)
-               scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
-       else
-               scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
-}
-
 static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
                                    GtkTreeIter *parent, int col, u64 total)
 {
@@ -128,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
                        scnprintf(buf, sizeof(buf), "%5.2f%%", percent);
                        gtk_tree_store_set(store, &iter, 0, buf, -1);
 
-                       callchain_list__sym_name(chain, buf, sizeof(buf));
+                       callchain_list__sym_name(chain, buf, sizeof(buf), false);
                        gtk_tree_store_set(store, &iter, col, buf, -1);
 
                        if (need_new_parent) {
index 15b451acbde61081eaf22aba07a5da3752a9e205..dfcbc90146ef0227bcdd19faca44c5890c823e26 100644 (file)
@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
 {
        int i;
        size_t ret = 0;
+       char bf[1024];
 
        ret += callchain__fprintf_left_margin(fp, left_margin);
        for (i = 0; i < depth; i++) {
@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
                } else
                        ret += fprintf(fp, "%s", "          ");
        }
-       if (chain->ms.sym)
-               ret += fprintf(fp, "%s\n", chain->ms.sym->name);
-       else
-               ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
-
+       fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp);
+       fputc('\n', fp);
        return ret;
 }
 
@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
        struct rb_node *node;
        int i = 0;
        int ret = 0;
+       char bf[1024];
 
        /*
         * If have one single callchain root, don't bother printing
@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
                        } else
                                ret += callchain__fprintf_left_margin(fp, left_margin);
 
-                       if (chain->ms.sym)
-                               ret += fprintf(fp, " %s\n", chain->ms.sym->name);
-                       else
-                               ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
+                       ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf),
+                                                       false));
 
                        if (++entries_printed == callchain_param.print_limit)
                                break;
@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
 {
        struct callchain_list *chain;
        size_t ret = 0;
+       char bf[1024];
 
        if (!node)
                return 0;
@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
        list_for_each_entry(chain, &node->val, list) {
                if (chain->ip >= PERF_CONTEXT_MAX)
                        continue;
-               if (chain->ms.sym)
-                       ret += fprintf(fp, "                %s\n", chain->ms.sym->name);
-               else
-                       ret += fprintf(fp, "                %p\n",
-                                       (void *)(long)chain->ip);
+               ret += fprintf(fp, "                %s\n", callchain_list__sym_name(chain,
+                                       bf, sizeof(bf), false));
        }
 
        return ret;
index 7dabde14ea54ace4c0ca3e6e54c619640035f845..79999ceaf2be08e5f4880e853d467bf59874340c 100644 (file)
 #include "debug.h"
 #include "annotate.h"
 #include "evsel.h"
+#include <regex.h>
 #include <pthread.h>
 #include <linux/bitops.h>
 
 const char     *disassembler_style;
 const char     *objdump_path;
+static regex_t  file_lineno;
 
 static struct ins *ins__find(const char *name);
 static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -570,13 +572,15 @@ out_free_name:
        return -1;
 }
 
-static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize)
+static struct disasm_line *disasm_line__new(s64 offset, char *line,
+                                       size_t privsize, int line_nr)
 {
        struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
 
        if (dl != NULL) {
                dl->offset = offset;
                dl->line = strdup(line);
+               dl->line_nr = line_nr;
                if (dl->line == NULL)
                        goto out_delete;
 
@@ -788,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
  * The ops.raw part will be parsed further according to type of the instruction.
  */
 static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
-                                     FILE *file, size_t privsize)
+                                     FILE *file, size_t privsize,
+                                     int *line_nr)
 {
        struct annotation *notes = symbol__annotation(sym);
        struct disasm_line *dl;
        char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
        size_t line_len;
        s64 line_ip, offset = -1;
+       regmatch_t match[2];
 
        if (getline(&line, &line_len, file) < 0)
                return -1;
@@ -812,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
        line_ip = -1;
        parsed_line = line;
 
+       /* /filename:linenr ? Save line number and ignore. */
+       if (regexec(&file_lineno, line, 2, match, 0) == 0) {
+               *line_nr = atoi(line + match[1].rm_so);
+               return 0;
+       }
+
        /*
         * Strip leading spaces:
         */
@@ -842,8 +854,9 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
                        parsed_line = tmp2 + 1;
        }
 
-       dl = disasm_line__new(offset, parsed_line, privsize);
+       dl = disasm_line__new(offset, parsed_line, privsize, *line_nr);
        free(line);
+       (*line_nr)++;
 
        if (dl == NULL)
                return -1;
@@ -869,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
        return 0;
 }
 
+static __attribute__((constructor)) void symbol__init_regexpr(void)
+{
+       regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
+}
+
 static void delete_last_nop(struct symbol *sym)
 {
        struct annotation *notes = symbol__annotation(sym);
@@ -904,6 +922,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
        char symfs_filename[PATH_MAX];
        struct kcore_extract kce;
        bool delete_extract = false;
+       int lineno = 0;
 
        if (filename)
                symbol__join_symfs(symfs_filename, filename);
@@ -915,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
                        return -ENOMEM;
                }
                goto fallback;
+       } else if (dso__is_kcore(dso)) {
+               goto fallback;
        } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
                   strstr(command, "[kernel.kallsyms]") ||
                   access(symfs_filename, R_OK)) {
@@ -982,7 +1003,7 @@ fallback:
        snprintf(command, sizeof(command),
                 "%s %s%s --start-address=0x%016" PRIx64
                 " --stop-address=0x%016" PRIx64
-                " -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
+                " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
                 objdump_path ? objdump_path : "objdump",
                 disassembler_style ? "-M " : "",
                 disassembler_style ? disassembler_style : "",
@@ -999,7 +1020,8 @@ fallback:
                goto out_free_filename;
 
        while (!feof(file))
-               if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
+               if (symbol__parse_objdump_line(sym, map, file, privsize,
+                           &lineno) < 0)
                        break;
 
        /*
@@ -1170,7 +1192,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
                        goto next;
 
                offset = start + i;
-               src_line->path = get_srcline(map->dso, offset);
+               src_line->path = get_srcline(map->dso, offset, NULL, false);
                insert_source_line(&tmp_root, src_line);
 
        next:
index 112d6e2681508ac66d160b50769be34fc7611e92..0784a9420528603efa9450a8c72c78ebf271298a 100644 (file)
@@ -58,6 +58,7 @@ struct disasm_line {
        char                *line;
        char                *name;
        struct ins          *ins;
+       int                 line_nr;
        struct ins_operands ops;
 };
 
index a904a4cfe7d3902e0a8075cc34285c7bc9cf1318..e8d79e5bfaf75c921f156752a6d14829b76ac872 100644 (file)
 #include "debug.h"
 #include "session.h"
 #include "tool.h"
+#include "header.h"
+#include "vdso.h"
+
+
+static bool no_buildid_cache;
 
 int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
                           union perf_event *event,
@@ -33,8 +38,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
                return -1;
        }
 
-       thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
-                             sample->ip, &al);
+       thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
 
        if (al.map != NULL)
                al.map->dso->hit = 1;
@@ -106,3 +110,343 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
                         build_id_hex, build_id_hex + 2);
        return bf;
 }
+
+#define dsos__for_each_with_build_id(pos, head)        \
+       list_for_each_entry(pos, head, node)    \
+               if (!pos->has_build_id)         \
+                       continue;               \
+               else
+
+static int write_buildid(const char *name, size_t name_len, u8 *build_id,
+                        pid_t pid, u16 misc, int fd)
+{
+       int err;
+       struct build_id_event b;
+       size_t len;
+
+       len = name_len + 1;
+       len = PERF_ALIGN(len, NAME_ALIGN);
+
+       memset(&b, 0, sizeof(b));
+       memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
+       b.pid = pid;
+       b.header.misc = misc;
+       b.header.size = sizeof(b) + len;
+
+       err = writen(fd, &b, sizeof(b));
+       if (err < 0)
+               return err;
+
+       return write_padded(fd, name, name_len + 1, len);
+}
+
+static int __dsos__write_buildid_table(struct list_head *head,
+                                      struct machine *machine,
+                                      pid_t pid, u16 misc, int fd)
+{
+       char nm[PATH_MAX];
+       struct dso *pos;
+
+       dsos__for_each_with_build_id(pos, head) {
+               int err;
+               const char *name;
+               size_t name_len;
+
+               if (!pos->hit)
+                       continue;
+
+               if (dso__is_vdso(pos)) {
+                       name = pos->short_name;
+                       name_len = pos->short_name_len + 1;
+               } else if (dso__is_kcore(pos)) {
+                       machine__mmap_name(machine, nm, sizeof(nm));
+                       name = nm;
+                       name_len = strlen(nm) + 1;
+               } else {
+                       name = pos->long_name;
+                       name_len = pos->long_name_len + 1;
+               }
+
+               err = write_buildid(name, name_len, pos->build_id,
+                                   pid, misc, fd);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int machine__write_buildid_table(struct machine *machine, int fd)
+{
+       int err;
+       u16 kmisc = PERF_RECORD_MISC_KERNEL,
+           umisc = PERF_RECORD_MISC_USER;
+
+       if (!machine__is_host(machine)) {
+               kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
+               umisc = PERF_RECORD_MISC_GUEST_USER;
+       }
+
+       err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
+                                         machine->pid, kmisc, fd);
+       if (err == 0)
+               err = __dsos__write_buildid_table(&machine->user_dsos.head,
+                                                 machine, machine->pid, umisc,
+                                                 fd);
+       return err;
+}
+
+int perf_session__write_buildid_table(struct perf_session *session, int fd)
+{
+       struct rb_node *nd;
+       int err = machine__write_buildid_table(&session->machines.host, fd);
+
+       if (err)
+               return err;
+
+       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
+               struct machine *pos = rb_entry(nd, struct machine, rb_node);
+               err = machine__write_buildid_table(pos, fd);
+               if (err)
+                       break;
+       }
+       return err;
+}
+
+static int __dsos__hit_all(struct list_head *head)
+{
+       struct dso *pos;
+
+       list_for_each_entry(pos, head, node)
+               pos->hit = true;
+
+       return 0;
+}
+
+static int machine__hit_all_dsos(struct machine *machine)
+{
+       int err;
+
+       err = __dsos__hit_all(&machine->kernel_dsos.head);
+       if (err)
+               return err;
+
+       return __dsos__hit_all(&machine->user_dsos.head);
+}
+
+int dsos__hit_all(struct perf_session *session)
+{
+       struct rb_node *nd;
+       int err;
+
+       err = machine__hit_all_dsos(&session->machines.host);
+       if (err)
+               return err;
+
+       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
+               struct machine *pos = rb_entry(nd, struct machine, rb_node);
+
+               err = machine__hit_all_dsos(pos);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+void disable_buildid_cache(void)
+{
+       no_buildid_cache = true;
+}
+
+int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
+                         const char *name, bool is_kallsyms, bool is_vdso)
+{
+       const size_t size = PATH_MAX;
+       char *realname, *filename = zalloc(size),
+            *linkname = zalloc(size), *targetname;
+       int len, err = -1;
+       bool slash = is_kallsyms || is_vdso;
+
+       if (is_kallsyms) {
+               if (symbol_conf.kptr_restrict) {
+                       pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
+                       err = 0;
+                       goto out_free;
+               }
+               realname = (char *) name;
+       } else
+               realname = realpath(name, NULL);
+
+       if (realname == NULL || filename == NULL || linkname == NULL)
+               goto out_free;
+
+       len = scnprintf(filename, size, "%s%s%s",
+                      debugdir, slash ? "/" : "",
+                      is_vdso ? DSO__NAME_VDSO : realname);
+       if (mkdir_p(filename, 0755))
+               goto out_free;
+
+       snprintf(filename + len, size - len, "/%s", sbuild_id);
+
+       if (access(filename, F_OK)) {
+               if (is_kallsyms) {
+                        if (copyfile("/proc/kallsyms", filename))
+                               goto out_free;
+               } else if (link(realname, filename) && copyfile(name, filename))
+                       goto out_free;
+       }
+
+       len = scnprintf(linkname, size, "%s/.build-id/%.2s",
+                      debugdir, sbuild_id);
+
+       if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
+               goto out_free;
+
+       snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
+       targetname = filename + strlen(debugdir) - 5;
+       memcpy(targetname, "../..", 5);
+
+       if (symlink(targetname, linkname) == 0)
+               err = 0;
+out_free:
+       if (!is_kallsyms)
+               free(realname);
+       free(filename);
+       free(linkname);
+       return err;
+}
+
+static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
+                                const char *name, const char *debugdir,
+                                bool is_kallsyms, bool is_vdso)
+{
+       char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+
+       build_id__sprintf(build_id, build_id_size, sbuild_id);
+
+       return build_id_cache__add_s(sbuild_id, debugdir, name,
+                                    is_kallsyms, is_vdso);
+}
+
+int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
+{
+       const size_t size = PATH_MAX;
+       char *filename = zalloc(size),
+            *linkname = zalloc(size);
+       int err = -1;
+
+       if (filename == NULL || linkname == NULL)
+               goto out_free;
+
+       snprintf(linkname, size, "%s/.build-id/%.2s/%s",
+                debugdir, sbuild_id, sbuild_id + 2);
+
+       if (access(linkname, F_OK))
+               goto out_free;
+
+       if (readlink(linkname, filename, size - 1) < 0)
+               goto out_free;
+
+       if (unlink(linkname))
+               goto out_free;
+
+       /*
+        * Since the link is relative, we must make it absolute:
+        */
+       snprintf(linkname, size, "%s/.build-id/%.2s/%s",
+                debugdir, sbuild_id, filename);
+
+       if (unlink(linkname))
+               goto out_free;
+
+       err = 0;
+out_free:
+       free(filename);
+       free(linkname);
+       return err;
+}
+
+static int dso__cache_build_id(struct dso *dso, struct machine *machine,
+                              const char *debugdir)
+{
+       bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
+       bool is_vdso = dso__is_vdso(dso);
+       const char *name = dso->long_name;
+       char nm[PATH_MAX];
+
+       if (dso__is_kcore(dso)) {
+               is_kallsyms = true;
+               machine__mmap_name(machine, nm, sizeof(nm));
+               name = nm;
+       }
+       return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
+                                    debugdir, is_kallsyms, is_vdso);
+}
+
+static int __dsos__cache_build_ids(struct list_head *head,
+                                  struct machine *machine, const char *debugdir)
+{
+       struct dso *pos;
+       int err = 0;
+
+       dsos__for_each_with_build_id(pos, head)
+               if (dso__cache_build_id(pos, machine, debugdir))
+                       err = -1;
+
+       return err;
+}
+
+static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
+{
+       int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
+                                         debugdir);
+       ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
+                                      debugdir);
+       return ret;
+}
+
+int perf_session__cache_build_ids(struct perf_session *session)
+{
+       struct rb_node *nd;
+       int ret;
+       char debugdir[PATH_MAX];
+
+       if (no_buildid_cache)
+               return 0;
+
+       snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
+
+       if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
+               return -1;
+
+       ret = machine__cache_build_ids(&session->machines.host, debugdir);
+
+       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
+               struct machine *pos = rb_entry(nd, struct machine, rb_node);
+               ret |= machine__cache_build_ids(pos, debugdir);
+       }
+       return ret ? -1 : 0;
+}
+
+static bool machine__read_build_ids(struct machine *machine, bool with_hits)
+{
+       bool ret;
+
+       ret  = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
+       ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
+       return ret;
+}
+
+bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
+{
+       struct rb_node *nd;
+       bool ret = machine__read_build_ids(&session->machines.host, with_hits);
+
+       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
+               struct machine *pos = rb_entry(nd, struct machine, rb_node);
+               ret |= machine__read_build_ids(pos, with_hits);
+       }
+
+       return ret;
+}
index ae392561470b83a6e268f177397cb195ce0f2e74..8236319514d582090eecc0d9e918ee1e48eb3943 100644 (file)
@@ -15,4 +15,16 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
 int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
                           struct perf_sample *sample, struct perf_evsel *evsel,
                           struct machine *machine);
+
+int dsos__hit_all(struct perf_session *session);
+
+bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
+int perf_session__write_buildid_table(struct perf_session *session, int fd);
+int perf_session__cache_build_ids(struct perf_session *session);
+
+int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
+                         const char *name, bool is_kallsyms, bool is_vdso);
+int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
+void disable_buildid_cache(void);
+
 #endif
index c84d3f8dcb7594602c4664c4926eaf050d26247e..cf524a35cc841a9784a77b3da4794409130283c9 100644 (file)
@@ -149,6 +149,10 @@ static int parse_callchain_sort_key(const char *value)
                callchain_param.key = CCKEY_ADDRESS;
                return 0;
        }
+       if (!strncmp(value, "branch", strlen(value))) {
+               callchain_param.branch_callstack = 1;
+               return 0;
+       }
        return -1;
 }
 
@@ -754,8 +758,8 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
 
        if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
            sort__has_parent) {
-               return machine__resolve_callchain(al->machine, evsel, al->thread,
-                                                 sample, parent, al, max_stack);
+               return thread__resolve_callchain(al->thread, evsel, sample,
+                                                parent, al, max_stack);
        }
        return 0;
 }
@@ -808,3 +812,32 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
 out:
        return 1;
 }
+
+char *callchain_list__sym_name(struct callchain_list *cl,
+                              char *bf, size_t bfsize, bool show_dso)
+{
+       int printed;
+
+       if (cl->ms.sym) {
+               if (callchain_param.key == CCKEY_ADDRESS &&
+                   cl->ms.map && !cl->srcline)
+                       cl->srcline = get_srcline(cl->ms.map->dso,
+                                                 map__rip_2objdump(cl->ms.map,
+                                                                   cl->ip),
+                                                 cl->ms.sym, false);
+               if (cl->srcline)
+                       printed = scnprintf(bf, bfsize, "%s %s",
+                                       cl->ms.sym->name, cl->srcline);
+               else
+                       printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
+       } else
+               printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
+
+       if (show_dso)
+               scnprintf(bf + printed, bfsize - printed, " %s",
+                         cl->ms.map ?
+                         cl->ms.map->dso->short_name :
+                         "unknown");
+
+       return bf;
+}
index 94cfefddf4db033eb2af2f7a4adad6e6c6147227..dbc08cf5f970a2f25e9451ca5e259a38f5cdbfe1 100644 (file)
@@ -63,6 +63,7 @@ struct callchain_param {
        sort_chain_func_t       sort;
        enum chain_order        order;
        enum chain_key          key;
+       bool                    branch_callstack;
 };
 
 extern struct callchain_param callchain_param;
@@ -70,6 +71,7 @@ extern struct callchain_param callchain_param;
 struct callchain_list {
        u64                     ip;
        struct map_symbol       ms;
+       char                   *srcline;
        struct list_head        list;
 };
 
@@ -184,15 +186,16 @@ static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
 }
 
 #ifdef HAVE_SKIP_CALLCHAIN_IDX
-extern int arch_skip_callchain_idx(struct machine *machine,
-                       struct thread *thread, struct ip_callchain *chain);
+extern int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
 #else
-static inline int arch_skip_callchain_idx(struct machine *machine __maybe_unused,
-                       struct thread *thread __maybe_unused,
+static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
                        struct ip_callchain *chain __maybe_unused)
 {
        return -1;
 }
 #endif
 
+char *callchain_list__sym_name(struct callchain_list *cl,
+                              char *bf, size_t bfsize, bool show_dso);
+
 #endif /* __PERF_CALLCHAIN_H */
index 51c10ab257f8b2b079d120075cc7effb45bd73e3..71c9c39340d4bf52a8b117c0927896501970b357 100644 (file)
@@ -12,6 +12,10 @@ struct comm {
        u64 start;
        struct list_head list;
        bool exec;
+       union { /* Tool specific area */
+               void    *priv;
+               u64     db_id;
+       };
 };
 
 void comm__free(struct comm *comm);
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
new file mode 100644 (file)
index 0000000..c81dae3
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * db-export.c: Support for exporting data suitable for import to a database
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <errno.h>
+
+#include "evsel.h"
+#include "machine.h"
+#include "thread.h"
+#include "comm.h"
+#include "symbol.h"
+#include "event.h"
+#include "util.h"
+#include "thread-stack.h"
+#include "db-export.h"
+
+struct deferred_export {
+       struct list_head node;
+       struct comm *comm;
+};
+
+static int db_export__deferred(struct db_export *dbe)
+{
+       struct deferred_export *de;
+       int err;
+
+       while (!list_empty(&dbe->deferred)) {
+               de = list_entry(dbe->deferred.next, struct deferred_export,
+                               node);
+               err = dbe->export_comm(dbe, de->comm);
+               list_del(&de->node);
+               free(de);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static void db_export__free_deferred(struct db_export *dbe)
+{
+       struct deferred_export *de;
+
+       while (!list_empty(&dbe->deferred)) {
+               de = list_entry(dbe->deferred.next, struct deferred_export,
+                               node);
+               list_del(&de->node);
+               free(de);
+       }
+}
+
+static int db_export__defer_comm(struct db_export *dbe, struct comm *comm)
+{
+       struct deferred_export *de;
+
+       de = zalloc(sizeof(struct deferred_export));
+       if (!de)
+               return -ENOMEM;
+
+       de->comm = comm;
+       list_add_tail(&de->node, &dbe->deferred);
+
+       return 0;
+}
+
+int db_export__init(struct db_export *dbe)
+{
+       memset(dbe, 0, sizeof(struct db_export));
+       INIT_LIST_HEAD(&dbe->deferred);
+       return 0;
+}
+
+int db_export__flush(struct db_export *dbe)
+{
+       return db_export__deferred(dbe);
+}
+
+void db_export__exit(struct db_export *dbe)
+{
+       db_export__free_deferred(dbe);
+       call_return_processor__free(dbe->crp);
+       dbe->crp = NULL;
+}
+
+int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
+{
+       if (evsel->db_id)
+               return 0;
+
+       evsel->db_id = ++dbe->evsel_last_db_id;
+
+       if (dbe->export_evsel)
+               return dbe->export_evsel(dbe, evsel);
+
+       return 0;
+}
+
+int db_export__machine(struct db_export *dbe, struct machine *machine)
+{
+       if (machine->db_id)
+               return 0;
+
+       machine->db_id = ++dbe->machine_last_db_id;
+
+       if (dbe->export_machine)
+               return dbe->export_machine(dbe, machine);
+
+       return 0;
+}
+
+int db_export__thread(struct db_export *dbe, struct thread *thread,
+                     struct machine *machine, struct comm *comm)
+{
+       u64 main_thread_db_id = 0;
+       int err;
+
+       if (thread->db_id)
+               return 0;
+
+       thread->db_id = ++dbe->thread_last_db_id;
+
+       if (thread->pid_ != -1) {
+               struct thread *main_thread;
+
+               if (thread->pid_ == thread->tid) {
+                       main_thread = thread;
+               } else {
+                       main_thread = machine__findnew_thread(machine,
+                                                             thread->pid_,
+                                                             thread->pid_);
+                       if (!main_thread)
+                               return -ENOMEM;
+                       err = db_export__thread(dbe, main_thread, machine,
+                                               comm);
+                       if (err)
+                               return err;
+                       if (comm) {
+                               err = db_export__comm_thread(dbe, comm, thread);
+                               if (err)
+                                       return err;
+                       }
+               }
+               main_thread_db_id = main_thread->db_id;
+       }
+
+       if (dbe->export_thread)
+               return dbe->export_thread(dbe, thread, main_thread_db_id,
+                                         machine);
+
+       return 0;
+}
+
+int db_export__comm(struct db_export *dbe, struct comm *comm,
+                   struct thread *main_thread)
+{
+       int err;
+
+       if (comm->db_id)
+               return 0;
+
+       comm->db_id = ++dbe->comm_last_db_id;
+
+       if (dbe->export_comm) {
+               if (main_thread->comm_set)
+                       err = dbe->export_comm(dbe, comm);
+               else
+                       err = db_export__defer_comm(dbe, comm);
+               if (err)
+                       return err;
+       }
+
+       return db_export__comm_thread(dbe, comm, main_thread);
+}
+
+int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
+                          struct thread *thread)
+{
+       u64 db_id;
+
+       db_id = ++dbe->comm_thread_last_db_id;
+
+       if (dbe->export_comm_thread)
+               return dbe->export_comm_thread(dbe, db_id, comm, thread);
+
+       return 0;
+}
+
+int db_export__dso(struct db_export *dbe, struct dso *dso,
+                  struct machine *machine)
+{
+       if (dso->db_id)
+               return 0;
+
+       dso->db_id = ++dbe->dso_last_db_id;
+
+       if (dbe->export_dso)
+               return dbe->export_dso(dbe, dso, machine);
+
+       return 0;
+}
+
+int db_export__symbol(struct db_export *dbe, struct symbol *sym,
+                     struct dso *dso)
+{
+       u64 *sym_db_id = symbol__priv(sym);
+
+       if (*sym_db_id)
+               return 0;
+
+       *sym_db_id = ++dbe->symbol_last_db_id;
+
+       if (dbe->export_symbol)
+               return dbe->export_symbol(dbe, sym, dso);
+
+       return 0;
+}
+
+static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
+{
+       if (thread->pid_ == thread->tid)
+               return thread;
+
+       if (thread->pid_ == -1)
+               return NULL;
+
+       return machine__find_thread(machine, thread->pid_, thread->pid_);
+}
+
+static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
+                         u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
+{
+       int err;
+
+       if (al->map) {
+               struct dso *dso = al->map->dso;
+
+               err = db_export__dso(dbe, dso, al->machine);
+               if (err)
+                       return err;
+               *dso_db_id = dso->db_id;
+
+               if (!al->sym) {
+                       al->sym = symbol__new(al->addr, 0, 0, "unknown");
+                       if (al->sym)
+                               symbols__insert(&dso->symbols[al->map->type],
+                                               al->sym);
+               }
+
+               if (al->sym) {
+                       u64 *db_id = symbol__priv(al->sym);
+
+                       err = db_export__symbol(dbe, al->sym, dso);
+                       if (err)
+                               return err;
+                       *sym_db_id = *db_id;
+                       *offset = al->addr - al->sym->start;
+               }
+       }
+
+       return 0;
+}
+
+int db_export__branch_type(struct db_export *dbe, u32 branch_type,
+                          const char *name)
+{
+       if (dbe->export_branch_type)
+               return dbe->export_branch_type(dbe, branch_type, name);
+
+       return 0;
+}
+
+int db_export__sample(struct db_export *dbe, union perf_event *event,
+                     struct perf_sample *sample, struct perf_evsel *evsel,
+                     struct thread *thread, struct addr_location *al)
+{
+       struct export_sample es = {
+               .event = event,
+               .sample = sample,
+               .evsel = evsel,
+               .thread = thread,
+               .al = al,
+       };
+       struct thread *main_thread;
+       struct comm *comm = NULL;
+       int err;
+
+       err = db_export__evsel(dbe, evsel);
+       if (err)
+               return err;
+
+       err = db_export__machine(dbe, al->machine);
+       if (err)
+               return err;
+
+       main_thread = get_main_thread(al->machine, thread);
+       if (main_thread)
+               comm = machine__thread_exec_comm(al->machine, main_thread);
+
+       err = db_export__thread(dbe, thread, al->machine, comm);
+       if (err)
+               return err;
+
+       if (comm) {
+               err = db_export__comm(dbe, comm, main_thread);
+               if (err)
+                       return err;
+               es.comm_db_id = comm->db_id;
+       }
+
+       es.db_id = ++dbe->sample_last_db_id;
+
+       err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
+       if (err)
+               return err;
+
+       if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
+           sample_addr_correlates_sym(&evsel->attr)) {
+               struct addr_location addr_al;
+
+               perf_event__preprocess_sample_addr(event, sample, thread, &addr_al);
+               err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
+                                    &es.addr_sym_db_id, &es.addr_offset);
+               if (err)
+                       return err;
+               if (dbe->crp) {
+                       err = thread_stack__process(thread, comm, sample, al,
+                                                   &addr_al, es.db_id,
+                                                   dbe->crp);
+                       if (err)
+                               return err;
+               }
+       }
+
+       if (dbe->export_sample)
+               return dbe->export_sample(dbe, &es);
+
+       return 0;
+}
+
+static struct {
+       u32 branch_type;
+       const char *name;
+} branch_types[] = {
+       {0, "no branch"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"},
+       {PERF_IP_FLAG_BRANCH, "unconditional jump"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT,
+        "software interrupt"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT,
+        "return from interrupt"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET,
+        "system call"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET,
+        "return from system call"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
+        PERF_IP_FLAG_INTERRUPT, "hardware interrupt"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
+       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
+       {0, NULL}
+};
+
+int db_export__branch_types(struct db_export *dbe)
+{
+       int i, err = 0;
+
+       for (i = 0; branch_types[i].name ; i++) {
+               err = db_export__branch_type(dbe, branch_types[i].branch_type,
+                                            branch_types[i].name);
+               if (err)
+                       break;
+       }
+       return err;
+}
+
+int db_export__call_path(struct db_export *dbe, struct call_path *cp)
+{
+       int err;
+
+       if (cp->db_id)
+               return 0;
+
+       if (cp->parent) {
+               err = db_export__call_path(dbe, cp->parent);
+               if (err)
+                       return err;
+       }
+
+       cp->db_id = ++dbe->call_path_last_db_id;
+
+       if (dbe->export_call_path)
+               return dbe->export_call_path(dbe, cp);
+
+       return 0;
+}
+
+int db_export__call_return(struct db_export *dbe, struct call_return *cr)
+{
+       int err;
+
+       if (cr->db_id)
+               return 0;
+
+       err = db_export__call_path(dbe, cr->cp);
+       if (err)
+               return err;
+
+       cr->db_id = ++dbe->call_return_last_db_id;
+
+       if (dbe->export_call_return)
+               return dbe->export_call_return(dbe, cr);
+
+       return 0;
+}
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
new file mode 100644 (file)
index 0000000..adbd22d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * db-export.h: Support for exporting data suitable for import to a database
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __PERF_DB_EXPORT_H
+#define __PERF_DB_EXPORT_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+struct perf_evsel;
+struct machine;
+struct thread;
+struct comm;
+struct dso;
+struct perf_sample;
+struct addr_location;
+struct call_return_processor;
+struct call_path;
+struct call_return;
+
+struct export_sample {
+       union perf_event        *event;
+       struct perf_sample      *sample;
+       struct perf_evsel       *evsel;
+       struct thread           *thread;
+       struct addr_location    *al;
+       u64                     db_id;
+       u64                     comm_db_id;
+       u64                     dso_db_id;
+       u64                     sym_db_id;
+       u64                     offset; /* ip offset from symbol start */
+       u64                     addr_dso_db_id;
+       u64                     addr_sym_db_id;
+       u64                     addr_offset; /* addr offset from symbol start */
+};
+
+struct db_export {
+       int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel);
+       int (*export_machine)(struct db_export *dbe, struct machine *machine);
+       int (*export_thread)(struct db_export *dbe, struct thread *thread,
+                            u64 main_thread_db_id, struct machine *machine);
+       int (*export_comm)(struct db_export *dbe, struct comm *comm);
+       int (*export_comm_thread)(struct db_export *dbe, u64 db_id,
+                                 struct comm *comm, struct thread *thread);
+       int (*export_dso)(struct db_export *dbe, struct dso *dso,
+                         struct machine *machine);
+       int (*export_symbol)(struct db_export *dbe, struct symbol *sym,
+                            struct dso *dso);
+       int (*export_branch_type)(struct db_export *dbe, u32 branch_type,
+                                 const char *name);
+       int (*export_sample)(struct db_export *dbe, struct export_sample *es);
+       int (*export_call_path)(struct db_export *dbe, struct call_path *cp);
+       int (*export_call_return)(struct db_export *dbe,
+                                 struct call_return *cr);
+       struct call_return_processor *crp;
+       u64 evsel_last_db_id;
+       u64 machine_last_db_id;
+       u64 thread_last_db_id;
+       u64 comm_last_db_id;
+       u64 comm_thread_last_db_id;
+       u64 dso_last_db_id;
+       u64 symbol_last_db_id;
+       u64 sample_last_db_id;
+       u64 call_path_last_db_id;
+       u64 call_return_last_db_id;
+       struct list_head deferred;
+};
+
+int db_export__init(struct db_export *dbe);
+int db_export__flush(struct db_export *dbe);
+void db_export__exit(struct db_export *dbe);
+int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel);
+int db_export__machine(struct db_export *dbe, struct machine *machine);
+int db_export__thread(struct db_export *dbe, struct thread *thread,
+                     struct machine *machine, struct comm *comm);
+int db_export__comm(struct db_export *dbe, struct comm *comm,
+                   struct thread *main_thread);
+int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
+                          struct thread *thread);
+int db_export__dso(struct db_export *dbe, struct dso *dso,
+                  struct machine *machine);
+int db_export__symbol(struct db_export *dbe, struct symbol *sym,
+                     struct dso *dso);
+int db_export__branch_type(struct db_export *dbe, u32 branch_type,
+                          const char *name);
+int db_export__sample(struct db_export *dbe, union perf_event *event,
+                     struct perf_sample *sample, struct perf_evsel *evsel,
+                     struct thread *thread, struct addr_location *al);
+
+int db_export__branch_types(struct db_export *dbe);
+
+int db_export__call_path(struct db_export *dbe, struct call_path *cp);
+int db_export__call_return(struct db_export *dbe, struct call_return *cr);
+
+#endif
index ba357f3226c69533c5d79497e3d2fb2207656514..ad60b2f202582c27c3d107540c1d7cca041fb1cf 100644 (file)
 int verbose;
 bool dump_trace = false, quiet = false;
 int debug_ordered_events;
+static int redirect_to_stderr;
 
 static int _eprintf(int level, int var, const char *fmt, va_list args)
 {
        int ret = 0;
 
        if (var >= level) {
-               if (use_browser >= 1)
+               if (use_browser >= 1 && !redirect_to_stderr)
                        ui_helpline__vshow(fmt, args);
                else
                        ret = vfprintf(stderr, fmt, args);
@@ -145,6 +146,7 @@ static struct debug_variable {
 } debug_variables[] = {
        { .name = "verbose",            .ptr = &verbose },
        { .name = "ordered-events",     .ptr = &debug_ordered_events},
+       { .name = "stderr",             .ptr = &redirect_to_stderr},
        { .name = NULL, }
 };
 
index 0247acfdfaca807a1378631f19d6d38ddef67cf3..45be944d450adfcfaf9c0dff3a0c68296769027a 100644 (file)
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso)
                [DSO_BINARY_TYPE__BUILDID_DEBUGINFO]            = 'b',
                [DSO_BINARY_TYPE__SYSTEM_PATH_DSO]              = 'd',
                [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE]          = 'K',
+               [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP]     = 'm',
                [DSO_BINARY_TYPE__GUEST_KALLSYMS]               = 'g',
                [DSO_BINARY_TYPE__GUEST_KMODULE]                = 'G',
+               [DSO_BINARY_TYPE__GUEST_KMODULE_COMP]           = 'M',
                [DSO_BINARY_TYPE__GUEST_VMLINUX]                = 'V',
        };
 
@@ -112,11 +114,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
                break;
 
        case DSO_BINARY_TYPE__GUEST_KMODULE:
+       case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
                path__join3(filename, size, symbol_conf.symfs,
                            root_dir, dso->long_name);
                break;
 
        case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
+       case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
                __symbol__join_symfs(filename, size, dso->long_name);
                break;
 
@@ -137,6 +141,73 @@ int dso__read_binary_type_filename(const struct dso *dso,
        return ret;
 }
 
+static const struct {
+       const char *fmt;
+       int (*decompress)(const char *input, int output);
+} compressions[] = {
+#ifdef HAVE_ZLIB_SUPPORT
+       { "gz", gzip_decompress_to_file },
+#endif
+       { NULL, NULL },
+};
+
+bool is_supported_compression(const char *ext)
+{
+       unsigned i;
+
+       for (i = 0; compressions[i].fmt; i++) {
+               if (!strcmp(ext, compressions[i].fmt))
+                       return true;
+       }
+       return false;
+}
+
+bool is_kmodule_extension(const char *ext)
+{
+       if (strncmp(ext, "ko", 2))
+               return false;
+
+       if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3)))
+               return true;
+
+       return false;
+}
+
+bool is_kernel_module(const char *pathname, bool *compressed)
+{
+       const char *ext = strrchr(pathname, '.');
+
+       if (ext == NULL)
+               return false;
+
+       if (is_supported_compression(ext + 1)) {
+               if (compressed)
+                       *compressed = true;
+               ext -= 3;
+       } else if (compressed)
+               *compressed = false;
+
+       return is_kmodule_extension(ext + 1);
+}
+
+bool decompress_to_file(const char *ext, const char *filename, int output_fd)
+{
+       unsigned i;
+
+       for (i = 0; compressions[i].fmt; i++) {
+               if (!strcmp(ext, compressions[i].fmt))
+                       return !compressions[i].decompress(filename,
+                                                          output_fd);
+       }
+       return false;
+}
+
+bool dso__needs_decompress(struct dso *dso)
+{
+       return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
+               dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
+}
+
 /*
  * Global list of open DSOs and the counter.
  */
index acb651acc7fdf1e6ee74dde78cf85ee98da6a1bf..3782c82c6e44b579895dc0b48f034f856706c8d4 100644 (file)
@@ -22,7 +22,9 @@ enum dso_binary_type {
        DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
        DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
        DSO_BINARY_TYPE__GUEST_KMODULE,
+       DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
        DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+       DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
        DSO_BINARY_TYPE__KCORE,
        DSO_BINARY_TYPE__GUEST_KCORE,
        DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
@@ -127,6 +129,7 @@ struct dso {
        const char       *long_name;
        u16              long_name_len;
        u16              short_name_len;
+       void            *dwfl;                  /* DWARF debug info */
 
        /* dso data file */
        struct {
@@ -138,6 +141,11 @@ struct dso {
                struct list_head open_entry;
        } data;
 
+       union { /* Tool specific area */
+               void     *priv;
+               u64      db_id;
+       };
+
        char             name[0];
 };
 
@@ -179,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
 char dso__symtab_origin(const struct dso *dso);
 int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
                                   char *root_dir, char *filename, size_t size);
+bool is_supported_compression(const char *ext);
+bool is_kmodule_extension(const char *ext);
+bool is_kernel_module(const char *pathname, bool *compressed);
+bool decompress_to_file(const char *ext, const char *filename, int output_fd);
+bool dso__needs_decompress(struct dso *dso);
 
 /*
  * The dso__data_* external interface provides following functions:
index 4af6b279e34a94881da3e838ff41f407aeb0cbfc..6c6d044e959aacf7c4c6515f2e8115d5aea391de 100644 (file)
@@ -28,6 +28,7 @@ static const char *perf_event__names[] = {
        [PERF_RECORD_HEADER_TRACING_DATA]       = "TRACING_DATA",
        [PERF_RECORD_HEADER_BUILD_ID]           = "BUILD_ID",
        [PERF_RECORD_FINISHED_ROUND]            = "FINISHED_ROUND",
+       [PERF_RECORD_ID_INDEX]                  = "ID_INDEX",
 };
 
 const char *perf_event__name(unsigned int id)
@@ -730,12 +731,12 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
        return machine__process_event(machine, event, sample);
 }
 
-void thread__find_addr_map(struct thread *thread,
-                          struct machine *machine, u8 cpumode,
+void thread__find_addr_map(struct thread *thread, u8 cpumode,
                           enum map_type type, u64 addr,
                           struct addr_location *al)
 {
        struct map_groups *mg = thread->mg;
+       struct machine *machine = mg->machine;
        bool load_map = false;
 
        al->machine = machine;
@@ -806,14 +807,14 @@ try_again:
        }
 }
 
-void thread__find_addr_location(struct thread *thread, struct machine *machine,
+void thread__find_addr_location(struct thread *thread,
                                u8 cpumode, enum map_type type, u64 addr,
                                struct addr_location *al)
 {
-       thread__find_addr_map(thread, machine, cpumode, type, addr, al);
+       thread__find_addr_map(thread, cpumode, type, addr, al);
        if (al->map != NULL)
                al->sym = map__find_symbol(al->map, al->addr,
-                                          machine->symbol_filter);
+                                          thread->mg->machine->symbol_filter);
        else
                al->sym = NULL;
 }
@@ -842,8 +843,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
            machine->vmlinux_maps[MAP__FUNCTION] == NULL)
                machine__create_kernel_maps(machine);
 
-       thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
-                             sample->ip, al);
+       thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
        dump_printf(" ...... dso: %s\n",
                    al->map ? al->map->dso->long_name :
                        al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -902,16 +902,14 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr)
 
 void perf_event__preprocess_sample_addr(union perf_event *event,
                                        struct perf_sample *sample,
-                                       struct machine *machine,
                                        struct thread *thread,
                                        struct addr_location *al)
 {
        u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
-       thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
-                             sample->addr, al);
+       thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al);
        if (!al->map)
-               thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
+               thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
                                      sample->addr, al);
 
        al->cpu = sample->cpu;
index 5699e7e2a7909e04ddfa40c59c8459109d8b1d46..c4ffe2bd0738df24f7b39854e6c0c25db806aa37 100644 (file)
@@ -143,6 +143,32 @@ struct branch_stack {
        struct branch_entry     entries[0];
 };
 
+enum {
+       PERF_IP_FLAG_BRANCH             = 1ULL << 0,
+       PERF_IP_FLAG_CALL               = 1ULL << 1,
+       PERF_IP_FLAG_RETURN             = 1ULL << 2,
+       PERF_IP_FLAG_CONDITIONAL        = 1ULL << 3,
+       PERF_IP_FLAG_SYSCALLRET         = 1ULL << 4,
+       PERF_IP_FLAG_ASYNC              = 1ULL << 5,
+       PERF_IP_FLAG_INTERRUPT          = 1ULL << 6,
+       PERF_IP_FLAG_TX_ABORT           = 1ULL << 7,
+       PERF_IP_FLAG_TRACE_BEGIN        = 1ULL << 8,
+       PERF_IP_FLAG_TRACE_END          = 1ULL << 9,
+       PERF_IP_FLAG_IN_TX              = 1ULL << 10,
+};
+
+#define PERF_BRANCH_MASK               (\
+       PERF_IP_FLAG_BRANCH             |\
+       PERF_IP_FLAG_CALL               |\
+       PERF_IP_FLAG_RETURN             |\
+       PERF_IP_FLAG_CONDITIONAL        |\
+       PERF_IP_FLAG_SYSCALLRET         |\
+       PERF_IP_FLAG_ASYNC              |\
+       PERF_IP_FLAG_INTERRUPT          |\
+       PERF_IP_FLAG_TX_ABORT           |\
+       PERF_IP_FLAG_TRACE_BEGIN        |\
+       PERF_IP_FLAG_TRACE_END)
+
 struct perf_sample {
        u64 ip;
        u32 pid, tid;
@@ -162,6 +188,7 @@ struct perf_sample {
        struct ip_callchain *callchain;
        struct branch_stack *branch_stack;
        struct regs_dump  user_regs;
+       struct regs_dump  intr_regs;
        struct stack_dump user_stack;
        struct sample_read read;
 };
@@ -187,6 +214,7 @@ enum perf_user_event_type { /* above any possible kernel type */
        PERF_RECORD_HEADER_TRACING_DATA         = 66,
        PERF_RECORD_HEADER_BUILD_ID             = 67,
        PERF_RECORD_FINISHED_ROUND              = 68,
+       PERF_RECORD_ID_INDEX                    = 69,
        PERF_RECORD_HEADER_MAX
 };
 
@@ -214,6 +242,7 @@ struct events_stats {
        u32 nr_invalid_chains;
        u32 nr_unknown_id;
        u32 nr_unprocessable_samples;
+       u32 nr_unordered_events;
 };
 
 struct attr_event {
@@ -239,6 +268,19 @@ struct tracing_data_event {
        u32 size;
 };
 
+struct id_index_entry {
+       u64 id;
+       u64 idx;
+       u64 cpu;
+       u64 tid;
+};
+
+struct id_index_event {
+       struct perf_event_header header;
+       u64 nr;
+       struct id_index_entry entries[0];
+};
+
 union perf_event {
        struct perf_event_header        header;
        struct mmap_event               mmap;
@@ -253,6 +295,7 @@ union perf_event {
        struct event_type_event         event_type;
        struct tracing_data_event       tracing_data;
        struct build_id_event           build_id;
+       struct id_index_event           id_index;
 };
 
 void perf_event__print_totals(void);
@@ -322,7 +365,6 @@ bool is_bts_event(struct perf_event_attr *attr);
 bool sample_addr_correlates_sym(struct perf_event_attr *attr);
 void perf_event__preprocess_sample_addr(union perf_event *event,
                                        struct perf_sample *sample,
-                                       struct machine *machine,
                                        struct thread *thread,
                                        struct addr_location *al);
 
index 3c9e77d6b4c2bf97b863d3ff75e2cc8f88a68e04..cfbe2b99b9aa5826b60fc574a211a115fc6f6a2d 100644 (file)
@@ -413,7 +413,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
        int nfds = 0;
        struct perf_evsel *evsel;
 
-       list_for_each_entry(evsel, &evlist->entries, node) {
+       evlist__for_each(evlist, evsel) {
                if (evsel->system_wide)
                        nfds += nr_cpus;
                else
@@ -527,6 +527,22 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
        return 0;
 }
 
+static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
+                                    struct perf_evsel *evsel, int idx, int cpu,
+                                    int thread)
+{
+       struct perf_sample_id *sid = SID(evsel, cpu, thread);
+       sid->idx = idx;
+       if (evlist->cpus && cpu >= 0)
+               sid->cpu = evlist->cpus->map[cpu];
+       else
+               sid->cpu = -1;
+       if (!evsel->system_wide && evlist->threads && thread >= 0)
+               sid->tid = evlist->threads->map[thread];
+       else
+               sid->tid = -1;
+}
+
 struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
 {
        struct hlist_head *head;
@@ -800,14 +816,26 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
                        perf_evlist__mmap_get(evlist, idx);
                }
 
-               if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
+               /*
+                * The system_wide flag causes a selected event to be opened
+                * always without a pid.  Consequently it will never get a
+                * POLLHUP, but it is used for tracking in combination with
+                * other events, so it should not need to be polled anyway.
+                * Therefore don't add it for polling.
+                */
+               if (!evsel->system_wide &&
+                   __perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
                        perf_evlist__mmap_put(evlist, idx);
                        return -1;
                }
 
-               if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
-                   perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
-                       return -1;
+               if (evsel->attr.read_format & PERF_FORMAT_ID) {
+                       if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
+                                                  fd) < 0)
+                               return -1;
+                       perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
+                                                thread);
+               }
        }
 
        return 0;
index 2f9e68025ede6615d60ca0c3aacc8e6b11c7011e..1e90c8557ede152b52ff5cf3f0baa443dbdbad3e 100644 (file)
@@ -658,9 +658,22 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
                attr->mmap_data = track;
        }
 
+       /*
+        * We don't allow user space callchains for  function trace
+        * event, due to issues with page faults while tracing page
+        * fault handler and its overall trickiness nature.
+        */
+       if (perf_evsel__is_function_event(evsel))
+               evsel->attr.exclude_callchain_user = 1;
+
        if (callchain_param.enabled && !evsel->no_aux_samples)
                perf_evsel__config_callgraph(evsel);
 
+       if (opts->sample_intr_regs) {
+               attr->sample_regs_intr = PERF_REGS_MASK;
+               perf_evsel__set_sample_bit(evsel, REGS_INTR);
+       }
+
        if (target__has_cpu(&opts->target))
                perf_evsel__set_sample_bit(evsel, CPU);
 
@@ -853,8 +866,6 @@ void perf_evsel__exit(struct perf_evsel *evsel)
        perf_evsel__free_id(evsel);
        close_cgroup(evsel->cgrp);
        zfree(&evsel->group_name);
-       if (evsel->tp_format)
-               pevent_free_format(evsel->tp_format);
        zfree(&evsel->name);
        perf_evsel__object.fini(evsel);
 }
@@ -865,9 +876,8 @@ void perf_evsel__delete(struct perf_evsel *evsel)
        free(evsel);
 }
 
-static inline void compute_deltas(struct perf_evsel *evsel,
-                                 int cpu,
-                                 struct perf_counts_values *count)
+void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
+                               struct perf_counts_values *count)
 {
        struct perf_counts_values tmp;
 
@@ -887,81 +897,60 @@ static inline void compute_deltas(struct perf_evsel *evsel,
        count->run = count->run - tmp.run;
 }
 
-int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
-                             int cpu, int thread, bool scale)
+void perf_counts_values__scale(struct perf_counts_values *count,
+                              bool scale, s8 *pscaled)
 {
-       struct perf_counts_values count;
-       size_t nv = scale ? 3 : 1;
-
-       if (FD(evsel, cpu, thread) < 0)
-               return -EINVAL;
-
-       if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
-               return -ENOMEM;
-
-       if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
-               return -errno;
-
-       compute_deltas(evsel, cpu, &count);
+       s8 scaled = 0;
 
        if (scale) {
-               if (count.run == 0)
-                       count.val = 0;
-               else if (count.run < count.ena)
-                       count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
+               if (count->run == 0) {
+                       scaled = -1;
+                       count->val = 0;
+               } else if (count->run < count->ena) {
+                       scaled = 1;
+                       count->val = (u64)((double) count->val * count->ena / count->run + 0.5);
+               }
        } else
-               count.ena = count.run = 0;
+               count->ena = count->run = 0;
 
-       evsel->counts->cpu[cpu] = count;
-       return 0;
+       if (pscaled)
+               *pscaled = scaled;
 }
 
-int __perf_evsel__read(struct perf_evsel *evsel,
-                      int ncpus, int nthreads, bool scale)
+int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
+                       perf_evsel__read_cb_t cb)
 {
-       size_t nv = scale ? 3 : 1;
-       int cpu, thread;
-       struct perf_counts_values *aggr = &evsel->counts->aggr, count;
+       struct perf_counts_values count;
 
-       if (evsel->system_wide)
-               nthreads = 1;
+       memset(&count, 0, sizeof(count));
 
-       aggr->val = aggr->ena = aggr->run = 0;
+       if (FD(evsel, cpu, thread) < 0)
+               return -EINVAL;
 
-       for (cpu = 0; cpu < ncpus; cpu++) {
-               for (thread = 0; thread < nthreads; thread++) {
-                       if (FD(evsel, cpu, thread) < 0)
-                               continue;
+       if (readn(FD(evsel, cpu, thread), &count, sizeof(count)) < 0)
+               return -errno;
 
-                       if (readn(FD(evsel, cpu, thread),
-                                 &count, nv * sizeof(u64)) < 0)
-                               return -errno;
+       return cb(evsel, cpu, thread, &count);
+}
 
-                       aggr->val += count.val;
-                       if (scale) {
-                               aggr->ena += count.ena;
-                               aggr->run += count.run;
-                       }
-               }
-       }
+int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
+                             int cpu, int thread, bool scale)
+{
+       struct perf_counts_values count;
+       size_t nv = scale ? 3 : 1;
 
-       compute_deltas(evsel, -1, aggr);
+       if (FD(evsel, cpu, thread) < 0)
+               return -EINVAL;
 
-       evsel->counts->scaled = 0;
-       if (scale) {
-               if (aggr->run == 0) {
-                       evsel->counts->scaled = -1;
-                       aggr->val = 0;
-                       return 0;
-               }
+       if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
+               return -ENOMEM;
 
-               if (aggr->run < aggr->ena) {
-                       evsel->counts->scaled = 1;
-                       aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
-               }
-       } else
-               aggr->ena = aggr->run = 0;
+       if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
+               return -errno;
 
+       perf_evsel__compute_deltas(evsel, cpu, &count);
+       perf_counts_values__scale(&count, scale, NULL);
+       evsel->counts->cpu[cpu] = count;
        return 0;
 }
 
@@ -1039,6 +1028,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
        ret += PRINT_ATTR_X64(branch_sample_type);
        ret += PRINT_ATTR_X64(sample_regs_user);
        ret += PRINT_ATTR_U32(sample_stack_user);
+       ret += PRINT_ATTR_X64(sample_regs_intr);
 
        ret += fprintf(fp, "%.60s\n", graph_dotted_line);
 
@@ -1538,6 +1528,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
                array++;
        }
 
+       data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE;
+       if (type & PERF_SAMPLE_REGS_INTR) {
+               OVERFLOW_CHECK_u64(array);
+               data->intr_regs.abi = *array;
+               array++;
+
+               if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
+                       u64 mask = evsel->attr.sample_regs_intr;
+
+                       sz = hweight_long(mask) * sizeof(u64);
+                       OVERFLOW_CHECK(array, sz, max_size);
+                       data->intr_regs.mask = mask;
+                       data->intr_regs.regs = (u64 *)array;
+                       array = (void *)array + sz;
+               }
+       }
+
        return 0;
 }
 
@@ -1633,6 +1640,16 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
        if (type & PERF_SAMPLE_TRANSACTION)
                result += sizeof(u64);
 
+       if (type & PERF_SAMPLE_REGS_INTR) {
+               if (sample->intr_regs.abi) {
+                       result += sizeof(u64);
+                       sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
+                       result += sz;
+               } else {
+                       result += sizeof(u64);
+               }
+       }
+
        return result;
 }
 
@@ -1811,6 +1828,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
                array++;
        }
 
+       if (type & PERF_SAMPLE_REGS_INTR) {
+               if (sample->intr_regs.abi) {
+                       *array++ = sample->intr_regs.abi;
+                       sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
+                       memcpy(array, sample->intr_regs.regs, sz);
+                       array = (void *)array + sz;
+               } else {
+                       *array++ = 0;
+               }
+       }
+
        return 0;
 }
 
@@ -1940,7 +1968,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
                bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
                bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
                bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
-               bit_name(IDENTIFIER),
+               bit_name(IDENTIFIER), bit_name(REGS_INTR),
                { .name = NULL, }
        };
 #undef bit_name
index 163c5604e5d15d97ff682716da589caf8dec148e..38622747d13034c3d6f383f56e411a833b18a07b 100644 (file)
@@ -36,6 +36,9 @@ struct perf_sample_id {
        struct hlist_node       node;
        u64                     id;
        struct perf_evsel       *evsel;
+       int                     idx;
+       int                     cpu;
+       pid_t                   tid;
 
        /* Holds total ID period value for PERF_SAMPLE_READ processing. */
        u64                     period;
@@ -54,6 +57,7 @@ struct cgroup_sel;
  * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or
  *          PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all
  *          is used there is an id sample appended to non-sample events
+ * @priv:   And what is in its containing unnamed union are tool specific
  */
 struct perf_evsel {
        struct list_head        node;
@@ -69,10 +73,12 @@ struct perf_evsel {
        char                    *name;
        double                  scale;
        const char              *unit;
+       bool                    snapshot;
        struct event_format     *tp_format;
        union {
                void            *priv;
                off_t           id_offset;
+               u64             db_id;
        };
        struct cgroup_sel       *cgrp;
        void                    *handler;
@@ -86,6 +92,8 @@ struct perf_evsel {
        bool                    immediate;
        bool                    system_wide;
        bool                    tracking;
+       bool                    per_pkg;
+       unsigned long           *per_pkg_mask;
        /* parse modifier helper */
        int                     exclude_GH;
        int                     nr_members;
@@ -105,6 +113,12 @@ struct thread_map;
 struct perf_evlist;
 struct record_opts;
 
+void perf_counts_values__scale(struct perf_counts_values *count,
+                              bool scale, s8 *pscaled);
+
+void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
+                               struct perf_counts_values *count);
+
 int perf_evsel__object_config(size_t object_size,
                              int (*init)(struct perf_evsel *evsel),
                              void (*fini)(struct perf_evsel *evsel));
@@ -222,6 +236,13 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
         (a)->attr.type == (b)->attr.type &&    \
         (a)->attr.config == (b)->attr.config)
 
+typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel,
+                                   int cpu, int thread,
+                                   struct perf_counts_values *count);
+
+int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
+                       perf_evsel__read_cb_t cb);
+
 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
                              int cpu, int thread, bool scale);
 
@@ -251,35 +272,6 @@ static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
        return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
 }
 
-int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads,
-                      bool scale);
-
-/**
- * perf_evsel__read - Read the aggregate results on all CPUs
- *
- * @evsel - event selector to read value
- * @ncpus - Number of cpus affected, from zero
- * @nthreads - Number of threads affected, from zero
- */
-static inline int perf_evsel__read(struct perf_evsel *evsel,
-                                   int ncpus, int nthreads)
-{
-       return __perf_evsel__read(evsel, ncpus, nthreads, false);
-}
-
-/**
- * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled
- *
- * @evsel - event selector to read value
- * @ncpus - Number of cpus affected, from zero
- * @nthreads - Number of threads affected, from zero
- */
-static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
-                                         int ncpus, int nthreads)
-{
-       return __perf_evsel__read(evsel, ncpus, nthreads, true);
-}
-
 int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
                             struct perf_sample *sample);
 
diff --git a/tools/perf/util/find-vdso-map.c b/tools/perf/util/find-vdso-map.c
new file mode 100644 (file)
index 0000000..95ef1cf
--- /dev/null
@@ -0,0 +1,30 @@
+static int find_vdso_map(void **start, void **end)
+{
+       FILE *maps;
+       char line[128];
+       int found = 0;
+
+       maps = fopen("/proc/self/maps", "r");
+       if (!maps) {
+               fprintf(stderr, "vdso: cannot open maps\n");
+               return -1;
+       }
+
+       while (!found && fgets(line, sizeof(line), maps)) {
+               int m = -1;
+
+               /* We care only about private r-x mappings. */
+               if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
+                               start, end, &m))
+                       continue;
+               if (m < 0)
+                       continue;
+
+               if (!strncmp(&line[m], VDSO__MAP_NAME,
+                            sizeof(VDSO__MAP_NAME) - 1))
+                       found = 1;
+       }
+
+       fclose(maps);
+       return !found;
+}
index ce0de00399da381accf00472f66c6064cdcee20a..b20e40c74468d13f951c8e3415e7bd8db225ee53 100644 (file)
@@ -24,8 +24,6 @@
 #include "build-id.h"
 #include "data.h"
 
-static bool no_buildid_cache = false;
-
 static u32 header_argc;
 static const char **header_argv;
 
@@ -79,10 +77,7 @@ static int do_write(int fd, const void *buf, size_t size)
        return 0;
 }
 
-#define NAME_ALIGN 64
-
-static int write_padded(int fd, const void *bf, size_t count,
-                       size_t count_aligned)
+int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
 {
        static const char zero_buf[NAME_ALIGN];
        int err = do_write(fd, bf, count);
@@ -171,340 +166,6 @@ perf_header__set_cmdline(int argc, const char **argv)
        return 0;
 }
 
-#define dsos__for_each_with_build_id(pos, head)        \
-       list_for_each_entry(pos, head, node)    \
-               if (!pos->has_build_id)         \
-                       continue;               \
-               else
-
-static int write_buildid(const char *name, size_t name_len, u8 *build_id,
-                        pid_t pid, u16 misc, int fd)
-{
-       int err;
-       struct build_id_event b;
-       size_t len;
-
-       len = name_len + 1;
-       len = PERF_ALIGN(len, NAME_ALIGN);
-
-       memset(&b, 0, sizeof(b));
-       memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
-       b.pid = pid;
-       b.header.misc = misc;
-       b.header.size = sizeof(b) + len;
-
-       err = do_write(fd, &b, sizeof(b));
-       if (err < 0)
-               return err;
-
-       return write_padded(fd, name, name_len + 1, len);
-}
-
-static int __dsos__hit_all(struct list_head *head)
-{
-       struct dso *pos;
-
-       list_for_each_entry(pos, head, node)
-               pos->hit = true;
-
-       return 0;
-}
-
-static int machine__hit_all_dsos(struct machine *machine)
-{
-       int err;
-
-       err = __dsos__hit_all(&machine->kernel_dsos.head);
-       if (err)
-               return err;
-
-       return __dsos__hit_all(&machine->user_dsos.head);
-}
-
-int dsos__hit_all(struct perf_session *session)
-{
-       struct rb_node *nd;
-       int err;
-
-       err = machine__hit_all_dsos(&session->machines.host);
-       if (err)
-               return err;
-
-       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
-               struct machine *pos = rb_entry(nd, struct machine, rb_node);
-
-               err = machine__hit_all_dsos(pos);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int __dsos__write_buildid_table(struct list_head *head,
-                                      struct machine *machine,
-                                      pid_t pid, u16 misc, int fd)
-{
-       char nm[PATH_MAX];
-       struct dso *pos;
-
-       dsos__for_each_with_build_id(pos, head) {
-               int err;
-               const char *name;
-               size_t name_len;
-
-               if (!pos->hit)
-                       continue;
-
-               if (dso__is_vdso(pos)) {
-                       name = pos->short_name;
-                       name_len = pos->short_name_len + 1;
-               } else if (dso__is_kcore(pos)) {
-                       machine__mmap_name(machine, nm, sizeof(nm));
-                       name = nm;
-                       name_len = strlen(nm) + 1;
-               } else {
-                       name = pos->long_name;
-                       name_len = pos->long_name_len + 1;
-               }
-
-               err = write_buildid(name, name_len, pos->build_id,
-                                   pid, misc, fd);
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int machine__write_buildid_table(struct machine *machine, int fd)
-{
-       int err;
-       u16 kmisc = PERF_RECORD_MISC_KERNEL,
-           umisc = PERF_RECORD_MISC_USER;
-
-       if (!machine__is_host(machine)) {
-               kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
-               umisc = PERF_RECORD_MISC_GUEST_USER;
-       }
-
-       err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
-                                         machine->pid, kmisc, fd);
-       if (err == 0)
-               err = __dsos__write_buildid_table(&machine->user_dsos.head,
-                                                 machine, machine->pid, umisc,
-                                                 fd);
-       return err;
-}
-
-static int dsos__write_buildid_table(struct perf_header *header, int fd)
-{
-       struct perf_session *session = container_of(header,
-                       struct perf_session, header);
-       struct rb_node *nd;
-       int err = machine__write_buildid_table(&session->machines.host, fd);
-
-       if (err)
-               return err;
-
-       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
-               struct machine *pos = rb_entry(nd, struct machine, rb_node);
-               err = machine__write_buildid_table(pos, fd);
-               if (err)
-                       break;
-       }
-       return err;
-}
-
-int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
-                         const char *name, bool is_kallsyms, bool is_vdso)
-{
-       const size_t size = PATH_MAX;
-       char *realname, *filename = zalloc(size),
-            *linkname = zalloc(size), *targetname;
-       int len, err = -1;
-       bool slash = is_kallsyms || is_vdso;
-
-       if (is_kallsyms) {
-               if (symbol_conf.kptr_restrict) {
-                       pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
-                       err = 0;
-                       goto out_free;
-               }
-               realname = (char *) name;
-       } else
-               realname = realpath(name, NULL);
-
-       if (realname == NULL || filename == NULL || linkname == NULL)
-               goto out_free;
-
-       len = scnprintf(filename, size, "%s%s%s",
-                      debugdir, slash ? "/" : "",
-                      is_vdso ? DSO__NAME_VDSO : realname);
-       if (mkdir_p(filename, 0755))
-               goto out_free;
-
-       snprintf(filename + len, size - len, "/%s", sbuild_id);
-
-       if (access(filename, F_OK)) {
-               if (is_kallsyms) {
-                        if (copyfile("/proc/kallsyms", filename))
-                               goto out_free;
-               } else if (link(realname, filename) && copyfile(name, filename))
-                       goto out_free;
-       }
-
-       len = scnprintf(linkname, size, "%s/.build-id/%.2s",
-                      debugdir, sbuild_id);
-
-       if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
-               goto out_free;
-
-       snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
-       targetname = filename + strlen(debugdir) - 5;
-       memcpy(targetname, "../..", 5);
-
-       if (symlink(targetname, linkname) == 0)
-               err = 0;
-out_free:
-       if (!is_kallsyms)
-               free(realname);
-       free(filename);
-       free(linkname);
-       return err;
-}
-
-static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
-                                const char *name, const char *debugdir,
-                                bool is_kallsyms, bool is_vdso)
-{
-       char sbuild_id[BUILD_ID_SIZE * 2 + 1];
-
-       build_id__sprintf(build_id, build_id_size, sbuild_id);
-
-       return build_id_cache__add_s(sbuild_id, debugdir, name,
-                                    is_kallsyms, is_vdso);
-}
-
-int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
-{
-       const size_t size = PATH_MAX;
-       char *filename = zalloc(size),
-            *linkname = zalloc(size);
-       int err = -1;
-
-       if (filename == NULL || linkname == NULL)
-               goto out_free;
-
-       snprintf(linkname, size, "%s/.build-id/%.2s/%s",
-                debugdir, sbuild_id, sbuild_id + 2);
-
-       if (access(linkname, F_OK))
-               goto out_free;
-
-       if (readlink(linkname, filename, size - 1) < 0)
-               goto out_free;
-
-       if (unlink(linkname))
-               goto out_free;
-
-       /*
-        * Since the link is relative, we must make it absolute:
-        */
-       snprintf(linkname, size, "%s/.build-id/%.2s/%s",
-                debugdir, sbuild_id, filename);
-
-       if (unlink(linkname))
-               goto out_free;
-
-       err = 0;
-out_free:
-       free(filename);
-       free(linkname);
-       return err;
-}
-
-static int dso__cache_build_id(struct dso *dso, struct machine *machine,
-                              const char *debugdir)
-{
-       bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
-       bool is_vdso = dso__is_vdso(dso);
-       const char *name = dso->long_name;
-       char nm[PATH_MAX];
-
-       if (dso__is_kcore(dso)) {
-               is_kallsyms = true;
-               machine__mmap_name(machine, nm, sizeof(nm));
-               name = nm;
-       }
-       return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
-                                    debugdir, is_kallsyms, is_vdso);
-}
-
-static int __dsos__cache_build_ids(struct list_head *head,
-                                  struct machine *machine, const char *debugdir)
-{
-       struct dso *pos;
-       int err = 0;
-
-       dsos__for_each_with_build_id(pos, head)
-               if (dso__cache_build_id(pos, machine, debugdir))
-                       err = -1;
-
-       return err;
-}
-
-static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
-{
-       int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
-                                         debugdir);
-       ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
-                                      debugdir);
-       return ret;
-}
-
-static int perf_session__cache_build_ids(struct perf_session *session)
-{
-       struct rb_node *nd;
-       int ret;
-       char debugdir[PATH_MAX];
-
-       snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
-
-       if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
-               return -1;
-
-       ret = machine__cache_build_ids(&session->machines.host, debugdir);
-
-       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
-               struct machine *pos = rb_entry(nd, struct machine, rb_node);
-               ret |= machine__cache_build_ids(pos, debugdir);
-       }
-       return ret ? -1 : 0;
-}
-
-static bool machine__read_build_ids(struct machine *machine, bool with_hits)
-{
-       bool ret;
-
-       ret  = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
-       ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
-       return ret;
-}
-
-static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
-{
-       struct rb_node *nd;
-       bool ret = machine__read_build_ids(&session->machines.host, with_hits);
-
-       for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
-               struct machine *pos = rb_entry(nd, struct machine, rb_node);
-               ret |= machine__read_build_ids(pos, with_hits);
-       }
-
-       return ret;
-}
-
 static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
                            struct perf_evlist *evlist)
 {
@@ -523,13 +184,12 @@ static int write_build_id(int fd, struct perf_header *h,
        if (!perf_session__read_build_ids(session, true))
                return -1;
 
-       err = dsos__write_buildid_table(h, fd);
+       err = perf_session__write_buildid_table(session, fd);
        if (err < 0) {
                pr_debug("failed to write buildid table\n");
                return err;
        }
-       if (!no_buildid_cache)
-               perf_session__cache_build_ids(session);
+       perf_session__cache_build_ids(session);
 
        return 0;
 }
@@ -579,16 +239,12 @@ static int write_version(int fd, struct perf_header *h __maybe_unused,
        return do_write_string(fd, perf_version_string);
 }
 
-static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
-                      struct perf_evlist *evlist __maybe_unused)
+static int __write_cpudesc(int fd, const char *cpuinfo_proc)
 {
-#ifndef CPUINFO_PROC
-#define CPUINFO_PROC NULL
-#endif
        FILE *file;
        char *buf = NULL;
        char *s, *p;
-       const char *search = CPUINFO_PROC;
+       const char *search = cpuinfo_proc;
        size_t len = 0;
        int ret = -1;
 
@@ -605,8 +261,10 @@ static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
                        break;
        }
 
-       if (ret)
+       if (ret) {
+               ret = -1;
                goto done;
+       }
 
        s = buf;
 
@@ -638,6 +296,25 @@ done:
        return ret;
 }
 
+static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
+                      struct perf_evlist *evlist __maybe_unused)
+{
+#ifndef CPUINFO_PROC
+#define CPUINFO_PROC {"model name", }
+#endif
+       const char *cpuinfo_procs[] = CPUINFO_PROC;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
+               int ret;
+               ret = __write_cpudesc(fd, cpuinfo_procs[i]);
+               if (ret >= 0)
+                       return ret;
+       }
+       return -1;
+}
+
+
 static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
                        struct perf_evlist *evlist __maybe_unused)
 {
@@ -950,7 +627,8 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
                n = sscanf(buf, "%*s %"PRIu64, &mem);
                if (n == 1)
                        ret = do_write(fd, &mem, sizeof(mem));
-       }
+       } else
+               ret = -1;
        free(buf);
        fclose(fp);
        return ret;
@@ -1588,7 +1266,7 @@ static int __event_process_build_id(struct build_id_event *bev,
 
                dso__set_build_id(dso, &bev->build_id);
 
-               if (filename[0] == '[')
+               if (!is_kernel_module(filename, NULL))
                        dso->kernel = dso_type;
 
                build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2462,6 +2140,7 @@ static const int attr_file_abi_sizes[] = {
        [1] = PERF_ATTR_SIZE_VER1,
        [2] = PERF_ATTR_SIZE_VER2,
        [3] = PERF_ATTR_SIZE_VER3,
+       [4] = PERF_ATTR_SIZE_VER4,
        0,
 };
 
@@ -3109,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
                                 session);
        return 0;
 }
-
-void disable_buildid_cache(void)
-{
-       no_buildid_cache = true;
-}
index 8f5cbaea64a5288faba84440722595854c04c044..3bb90ac172a1ba0c8429494f4ebf501909a55274 100644 (file)
@@ -122,10 +122,6 @@ int perf_header__process_sections(struct perf_header *header, int fd,
 
 int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
 
-int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
-                         const char *name, bool is_kallsyms, bool is_vdso);
-int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
-
 int perf_event__synthesize_attr(struct perf_tool *tool,
                                struct perf_event_attr *attr, u32 ids, u64 *id,
                                perf_event__handler_t process);
@@ -151,7 +147,9 @@ int perf_event__process_build_id(struct perf_tool *tool,
                                 struct perf_session *session);
 bool is_perf_magic(u64 magic);
 
-int dsos__hit_all(struct perf_session *session);
+#define NAME_ALIGN 64
+
+int write_padded(int fd, const void *bf, size_t count, size_t count_aligned);
 
 /*
  * arch specific callback
index 01ffd12dc79140033d7d691d0c5b8f2e2bd38dd1..40bd21488032b0d68998ddfe04fbadac9dc1edf9 100644 (file)
@@ -46,4 +46,21 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
                __bitmap_or(dst, src1, src2, nbits);
 }
 
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+static inline int test_and_set_bit(int nr, unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       unsigned long old;
+
+       old = *p;
+       *p = old | mask;
+
+       return (old & mask) != 0;
+}
+
 #endif /* _PERF_BITOPS_H */
index dadfa7e54287b9aaa46da7227d4b0f275717ddb2..c3294163de1759b754e618105460829427d71a4a 100644 (file)
@@ -15,6 +15,8 @@
 #define BITS_TO_U64(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
 #define BITS_TO_U32(nr)         DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
 #define BITS_TO_BYTES(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE)
+#define BIT_WORD(nr)            ((nr) / BITS_PER_LONG)
+#define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_LONG))
 
 #define for_each_set_bit(bit, addr, size) \
        for ((bit) = find_first_bit((addr), (size));            \
index 34fc7c8672e4ab2a6547c1543ae1b07b21cc1e46..15dd0a9691ceea7efe0d091b43aa0c46b191061d 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdbool.h>
 #include <symbol/kallsyms.h>
 #include "unwind.h"
+#include "linux/hash.h"
 
 static void dsos__init(struct dsos *dsos)
 {
@@ -21,7 +22,7 @@ static void dsos__init(struct dsos *dsos)
 
 int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
 {
-       map_groups__init(&machine->kmaps);
+       map_groups__init(&machine->kmaps, machine);
        RB_CLEAR_NODE(&machine->rb_node);
        dsos__init(&machine->user_dsos);
        dsos__init(&machine->kernel_dsos);
@@ -32,7 +33,6 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
 
        machine->vdso_info = NULL;
 
-       machine->kmaps.machine = machine;
        machine->pid = pid;
 
        machine->symbol_filter = NULL;
@@ -319,7 +319,7 @@ static void machine__update_thread_pid(struct machine *machine,
                goto out_err;
 
        if (!leader->mg)
-               leader->mg = map_groups__new();
+               leader->mg = map_groups__new(machine);
 
        if (!leader->mg)
                goto out_err;
@@ -465,6 +465,7 @@ struct map *machine__new_module(struct machine *machine, u64 start,
 {
        struct map *map;
        struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
+       bool compressed;
 
        if (dso == NULL)
                return NULL;
@@ -477,6 +478,11 @@ struct map *machine__new_module(struct machine *machine, u64 start,
                dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
        else
                dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
+
+       /* _KMODULE_COMP should be next to _KMODULE */
+       if (is_kernel_module(filename, &compressed) && compressed)
+               dso->symtab_type++;
+
        map_groups__insert(&machine->kmaps, map);
        return map;
 }
@@ -862,8 +868,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
                        struct map *map;
                        char *long_name;
 
-                       if (dot == NULL || strcmp(dot, ".ko"))
+                       if (dot == NULL)
                                continue;
+
+                       /* On some system, modules are compressed like .ko.gz */
+                       if (is_supported_compression(dot + 1) &&
+                           is_kmodule_extension(dot - 2))
+                               dot -= 3;
+
                        snprintf(dso_name, sizeof(dso_name), "[%.*s]",
                                 (int)(dot - dent->d_name), dent->d_name);
 
@@ -1045,6 +1057,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
                        dot = strrchr(name, '.');
                        if (dot == NULL)
                                goto out_problem;
+                       /* On some system, modules are compressed like .ko.gz */
+                       if (is_supported_compression(dot + 1))
+                               dot -= 3;
+                       if (!is_kmodule_extension(dot + 1))
+                               goto out_problem;
                        snprintf(short_module_name, sizeof(short_module_name),
                                        "[%.*s]", (int)(dot - name), name);
                        strxfrchar(short_module_name, '-', '_');
@@ -1069,8 +1086,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
                 * Should be there already, from the build-id table in
                 * the header.
                 */
-               struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
-                                                    kmmap_prefix);
+               struct dso *kernel = NULL;
+               struct dso *dso;
+
+               list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
+                       if (is_kernel_module(dso->long_name, NULL))
+                               continue;
+
+                       kernel = dso;
+                       break;
+               }
+
+               if (kernel == NULL)
+                       kernel = __dsos__findnew(&machine->kernel_dsos,
+                                                kmmap_prefix);
                if (kernel == NULL)
                        goto out_problem;
 
@@ -1078,6 +1107,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
                if (__machine__create_kernel_maps(machine, kernel) < 0)
                        goto out_problem;
 
+               if (strstr(kernel->long_name, "vmlinux"))
+                       dso__set_short_name(kernel, "[kernel.vmlinux]", false);
+
                machine__set_kernel_mmap_len(machine, event);
 
                /*
@@ -1290,7 +1322,7 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
        return 0;
 }
 
-static void ip__resolve_ams(struct machine *machine, struct thread *thread,
+static void ip__resolve_ams(struct thread *thread,
                            struct addr_map_symbol *ams,
                            u64 ip)
 {
@@ -1304,7 +1336,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
         * Thus, we have to try consecutively until we find a match
         * or else, the symbol is unknown
         */
-       thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al);
+       thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al);
 
        ams->addr = ip;
        ams->al_addr = al.addr;
@@ -1312,23 +1344,21 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
        ams->map = al.map;
 }
 
-static void ip__resolve_data(struct machine *machine, struct thread *thread,
+static void ip__resolve_data(struct thread *thread,
                             u8 m, struct addr_map_symbol *ams, u64 addr)
 {
        struct addr_location al;
 
        memset(&al, 0, sizeof(al));
 
-       thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr,
-                                  &al);
+       thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al);
        if (al.map == NULL) {
                /*
                 * some shared data regions have execute bit set which puts
                 * their mapping in the MAP__FUNCTION type array.
                 * Check there as a fallback option before dropping the sample.
                 */
-               thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr,
-                                          &al);
+               thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al);
        }
 
        ams->addr = addr;
@@ -1345,14 +1375,45 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
        if (!mi)
                return NULL;
 
-       ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip);
-       ip__resolve_data(al->machine, al->thread, al->cpumode,
-                        &mi->daddr, sample->addr);
+       ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
+       ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr);
        mi->data_src.val = sample->data_src;
 
        return mi;
 }
 
+static int add_callchain_ip(struct thread *thread,
+                           struct symbol **parent,
+                           struct addr_location *root_al,
+                           int cpumode,
+                           u64 ip)
+{
+       struct addr_location al;
+
+       al.filtered = 0;
+       al.sym = NULL;
+       if (cpumode == -1)
+               thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
+                                                  ip, &al);
+       else
+               thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
+                                  ip, &al);
+       if (al.sym != NULL) {
+               if (sort__has_parent && !*parent &&
+                   symbol__match_regex(al.sym, &parent_regex))
+                       *parent = al.sym;
+               else if (have_ignore_callees && root_al &&
+                 symbol__match_regex(al.sym, &ignore_callees_regex)) {
+                       /* Treat this symbol as the root,
+                          forgetting its callees. */
+                       *root_al = al;
+                       callchain_cursor_reset(&callchain_cursor);
+               }
+       }
+
+       return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym);
+}
+
 struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
                                           struct addr_location *al)
 {
@@ -1364,16 +1425,57 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
                return NULL;
 
        for (i = 0; i < bs->nr; i++) {
-               ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to);
-               ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from);
+               ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to);
+               ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from);
                bi[i].flags = bs->entries[i].flags;
        }
        return bi;
 }
 
-static int machine__resolve_callchain_sample(struct machine *machine,
-                                            struct thread *thread,
+#define CHASHSZ 127
+#define CHASHBITS 7
+#define NO_ENTRY 0xff
+
+#define PERF_MAX_BRANCH_DEPTH 127
+
+/* Remove loops. */
+static int remove_loops(struct branch_entry *l, int nr)
+{
+       int i, j, off;
+       unsigned char chash[CHASHSZ];
+
+       memset(chash, NO_ENTRY, sizeof(chash));
+
+       BUG_ON(PERF_MAX_BRANCH_DEPTH > 255);
+
+       for (i = 0; i < nr; i++) {
+               int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ;
+
+               /* no collision handling for now */
+               if (chash[h] == NO_ENTRY) {
+                       chash[h] = i;
+               } else if (l[chash[h]].from == l[i].from) {
+                       bool is_loop = true;
+                       /* check if it is a real loop */
+                       off = 0;
+                       for (j = chash[h]; j < i && i + off < nr; j++, off++)
+                               if (l[j].from != l[i + off].from) {
+                                       is_loop = false;
+                                       break;
+                               }
+                       if (is_loop) {
+                               memmove(l + i, l + i + off,
+                                       (nr - (i + off)) * sizeof(*l));
+                               nr -= off;
+                       }
+               }
+       }
+       return nr;
+}
+
+static int thread__resolve_callchain_sample(struct thread *thread,
                                             struct ip_callchain *chain,
+                                            struct branch_stack *branch,
                                             struct symbol **parent,
                                             struct addr_location *root_al,
                                             int max_stack)
@@ -1383,24 +1485,83 @@ static int machine__resolve_callchain_sample(struct machine *machine,
        int i;
        int j;
        int err;
-       int skip_idx __maybe_unused;
+       int skip_idx = -1;
+       int first_call = 0;
+
+       /*
+        * Based on DWARF debug information, some architectures skip
+        * a callchain entry saved by the kernel.
+        */
+       if (chain->nr < PERF_MAX_STACK_DEPTH)
+               skip_idx = arch_skip_callchain_idx(thread, chain);
 
        callchain_cursor_reset(&callchain_cursor);
 
+       /*
+        * Add branches to call stack for easier browsing. This gives
+        * more context for a sample than just the callers.
+        *
+        * This uses individual histograms of paths compared to the
+        * aggregated histograms the normal LBR mode uses.
+        *
+        * Limitations for now:
+        * - No extra filters
+        * - No annotations (should annotate somehow)
+        */
+
+       if (branch && callchain_param.branch_callstack) {
+               int nr = min(max_stack, (int)branch->nr);
+               struct branch_entry be[nr];
+
+               if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
+                       pr_warning("corrupted branch chain. skipping...\n");
+                       goto check_calls;
+               }
+
+               for (i = 0; i < nr; i++) {
+                       if (callchain_param.order == ORDER_CALLEE) {
+                               be[i] = branch->entries[i];
+                               /*
+                                * Check for overlap into the callchain.
+                                * The return address is one off compared to
+                                * the branch entry. To adjust for this
+                                * assume the calling instruction is not longer
+                                * than 8 bytes.
+                                */
+                               if (i == skip_idx ||
+                                   chain->ips[first_call] >= PERF_CONTEXT_MAX)
+                                       first_call++;
+                               else if (be[i].from < chain->ips[first_call] &&
+                                   be[i].from >= chain->ips[first_call] - 8)
+                                       first_call++;
+                       } else
+                               be[i] = branch->entries[branch->nr - i - 1];
+               }
+
+               nr = remove_loops(be, nr);
+
+               for (i = 0; i < nr; i++) {
+                       err = add_callchain_ip(thread, parent, root_al,
+                                              -1, be[i].to);
+                       if (!err)
+                               err = add_callchain_ip(thread, parent, root_al,
+                                                      -1, be[i].from);
+                       if (err == -EINVAL)
+                               break;
+                       if (err)
+                               return err;
+               }
+               chain_nr -= nr;
+       }
+
+check_calls:
        if (chain->nr > PERF_MAX_STACK_DEPTH) {
                pr_warning("corrupted callchain. skipping...\n");
                return 0;
        }
 
-       /*
-        * Based on DWARF debug information, some architectures skip
-        * a callchain entry saved by the kernel.
-        */
-       skip_idx = arch_skip_callchain_idx(machine, thread, chain);
-
-       for (i = 0; i < chain_nr; i++) {
+       for (i = first_call; i < chain_nr; i++) {
                u64 ip;
-               struct addr_location al;
 
                if (callchain_param.order == ORDER_CALLEE)
                        j = i;
@@ -1437,24 +1598,10 @@ static int machine__resolve_callchain_sample(struct machine *machine,
                        continue;
                }
 
-               al.filtered = 0;
-               thread__find_addr_location(thread, machine, cpumode,
-                                          MAP__FUNCTION, ip, &al);
-               if (al.sym != NULL) {
-                       if (sort__has_parent && !*parent &&
-                           symbol__match_regex(al.sym, &parent_regex))
-                               *parent = al.sym;
-                       else if (have_ignore_callees && root_al &&
-                         symbol__match_regex(al.sym, &ignore_callees_regex)) {
-                               /* Treat this symbol as the root,
-                                  forgetting its callees. */
-                               *root_al = al;
-                               callchain_cursor_reset(&callchain_cursor);
-                       }
-               }
-
-               err = callchain_cursor_append(&callchain_cursor,
-                                             ip, al.map, al.sym);
+               err = add_callchain_ip(thread, parent, root_al,
+                                      cpumode, ip);
+               if (err == -EINVAL)
+                       break;
                if (err)
                        return err;
        }
@@ -1469,19 +1616,16 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
                                       entry->map, entry->sym);
 }
 
-int machine__resolve_callchain(struct machine *machine,
-                              struct perf_evsel *evsel,
-                              struct thread *thread,
-                              struct perf_sample *sample,
-                              struct symbol **parent,
-                              struct addr_location *root_al,
-                              int max_stack)
+int thread__resolve_callchain(struct thread *thread,
+                             struct perf_evsel *evsel,
+                             struct perf_sample *sample,
+                             struct symbol **parent,
+                             struct addr_location *root_al,
+                             int max_stack)
 {
-       int ret;
-
-       ret = machine__resolve_callchain_sample(machine, thread,
-                                               sample->callchain, parent,
-                                               root_al, max_stack);
+       int ret = thread__resolve_callchain_sample(thread, sample->callchain,
+                                                  sample->branch_stack,
+                                                  parent, root_al, max_stack);
        if (ret)
                return ret;
 
@@ -1495,7 +1639,7 @@ int machine__resolve_callchain(struct machine *machine,
            (!sample->user_stack.size))
                return 0;
 
-       return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
+       return unwind__get_entries(unwind_entry, &callchain_cursor,
                                   thread, sample, max_stack);
 
 }
index 2b651a7f5d0d113c59461f4badbd35c9ad870a45..e8b7779a0a3f85c05e6d01f086a0b56ea8ec1ff2 100644 (file)
@@ -40,6 +40,10 @@ struct machine {
        u64               kernel_start;
        symbol_filter_t   symbol_filter;
        pid_t             *current_tid;
+       union { /* Tool specific area */
+               void      *priv;
+               u64       db_id;
+       };
 };
 
 static inline
@@ -122,13 +126,12 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
                                           struct addr_location *al);
 struct mem_info *sample__resolve_mem(struct perf_sample *sample,
                                     struct addr_location *al);
-int machine__resolve_callchain(struct machine *machine,
-                              struct perf_evsel *evsel,
-                              struct thread *thread,
-                              struct perf_sample *sample,
-                              struct symbol **parent,
-                              struct addr_location *root_al,
-                              int max_stack);
+int thread__resolve_callchain(struct thread *thread,
+                             struct perf_evsel *evsel,
+                             struct perf_sample *sample,
+                             struct symbol **parent,
+                             struct addr_location *root_al,
+                             int max_stack);
 
 /*
  * Default guest kernel is defined by parameter --guestkallsyms
index 2137c4596ec79aa49b3fc0d9e58f2a6aaea1b920..62ca9f2607d557804a0bc260e74a5e5c5dbc32e1 100644 (file)
@@ -360,7 +360,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
 
        if (map && map->dso) {
                srcline = get_srcline(map->dso,
-                                     map__rip_2objdump(map, addr));
+                                     map__rip_2objdump(map, addr), NULL, true);
                if (srcline != SRCLINE_UNKNOWN)
                        ret = fprintf(fp, "%s%s", prefix, srcline);
                free_srcline(srcline);
@@ -413,14 +413,14 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
        return ip + map->reloc;
 }
 
-void map_groups__init(struct map_groups *mg)
+void map_groups__init(struct map_groups *mg, struct machine *machine)
 {
        int i;
        for (i = 0; i < MAP__NR_TYPES; ++i) {
                mg->maps[i] = RB_ROOT;
                INIT_LIST_HEAD(&mg->removed_maps[i]);
        }
-       mg->machine = NULL;
+       mg->machine = machine;
        mg->refcnt = 1;
 }
 
@@ -471,12 +471,12 @@ bool map_groups__empty(struct map_groups *mg)
        return true;
 }
 
-struct map_groups *map_groups__new(void)
+struct map_groups *map_groups__new(struct machine *machine)
 {
        struct map_groups *mg = malloc(sizeof(*mg));
 
        if (mg != NULL)
-               map_groups__init(mg);
+               map_groups__init(mg, machine);
 
        return mg;
 }
index 2f83954af05013f88b7ce1fea2561ba81fbb08e6..6951a9d42339ee089c67dd068622f41c64f4670b 100644 (file)
@@ -64,7 +64,7 @@ struct map_groups {
        int              refcnt;
 };
 
-struct map_groups *map_groups__new(void);
+struct map_groups *map_groups__new(struct machine *machine);
 void map_groups__delete(struct map_groups *mg);
 bool map_groups__empty(struct map_groups *mg);
 
@@ -150,7 +150,7 @@ void maps__remove(struct rb_root *maps, struct map *map);
 struct map *maps__find(struct rb_root *maps, u64 addr);
 struct map *maps__first(struct rb_root *maps);
 struct map *maps__next(struct map *map);
-void map_groups__init(struct map_groups *mg);
+void map_groups__init(struct map_groups *mg, struct machine *machine);
 void map_groups__exit(struct map_groups *mg);
 int map_groups__clone(struct map_groups *mg,
                      struct map_groups *parent, enum map_type type);
index c659a3ca1283e7fedc44e2afe4935cbd65cb7e13..77b43fe43d55732c6d9ffeef50dbb66e309fca63 100644 (file)
@@ -681,6 +681,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
        if (evsel) {
                evsel->unit = info.unit;
                evsel->scale = info.scale;
+               evsel->per_pkg = info.per_pkg;
+               evsel->snapshot = info.snapshot;
        }
 
        return evsel ? 0 : -ENOMEM;
index bf48092983c65fe8cec8bb3ff4662e1b1803b18e..f62dee7bd924b30696da6205fece4980a7b13e24 100644 (file)
@@ -42,7 +42,26 @@ static int get_value(struct parse_opt_ctx_t *p,
                return opterror(opt, "takes no value", flags);
        if (unset && (opt->flags & PARSE_OPT_NONEG))
                return opterror(opt, "isn't available", flags);
-
+       if (opt->flags & PARSE_OPT_DISABLED)
+               return opterror(opt, "is not usable", flags);
+
+       if (opt->flags & PARSE_OPT_EXCLUSIVE) {
+               if (p->excl_opt) {
+                       char msg[128];
+
+                       if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
+                           p->excl_opt->long_name == NULL) {
+                               scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
+                                         p->excl_opt->short_name);
+                       } else {
+                               scnprintf(msg, sizeof(msg), "cannot be used with %s",
+                                         p->excl_opt->long_name);
+                       }
+                       opterror(opt, msg, flags);
+                       return -3;
+               }
+               p->excl_opt = opt;
+       }
        if (!(flags & OPT_SHORT) && p->opt) {
                switch (opt->type) {
                case OPTION_CALLBACK:
@@ -343,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                       const char * const usagestr[])
 {
        int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
+       int excl_short_opt = 1;
+       const char *arg;
 
        /* we must reset ->opt, unknown short option leave it dangling */
        ctx->opt = NULL;
 
        for (; ctx->argc; ctx->argc--, ctx->argv++) {
-               const char *arg = ctx->argv[0];
-
+               arg = ctx->argv[0];
                if (*arg != '-' || !arg[1]) {
                        if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
                                break;
@@ -358,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                }
 
                if (arg[1] != '-') {
-                       ctx->opt = arg + 1;
+                       ctx->opt = ++arg;
                        if (internal_help && *ctx->opt == 'h')
                                return usage_with_options_internal(usagestr, options, 0);
                        switch (parse_short_opt(ctx, options)) {
                        case -1:
-                               return parse_options_usage(usagestr, options, arg + 1, 1);
+                               return parse_options_usage(usagestr, options, arg, 1);
                        case -2:
                                goto unknown;
+                       case -3:
+                               goto exclusive;
                        default:
                                break;
                        }
                        if (ctx->opt)
-                               check_typos(arg + 1, options);
+                               check_typos(arg, options);
                        while (ctx->opt) {
                                if (internal_help && *ctx->opt == 'h')
                                        return usage_with_options_internal(usagestr, options, 0);
@@ -387,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                                        ctx->argv[0] = strdup(ctx->opt - 1);
                                        *(char *)ctx->argv[0] = '-';
                                        goto unknown;
+                               case -3:
+                                       goto exclusive;
                                default:
                                        break;
                                }
@@ -402,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
                        break;
                }
 
-               if (internal_help && !strcmp(arg + 2, "help-all"))
+               arg += 2;
+               if (internal_help && !strcmp(arg, "help-all"))
                        return usage_with_options_internal(usagestr, options, 1);
-               if (internal_help && !strcmp(arg + 2, "help"))
+               if (internal_help && !strcmp(arg, "help"))
                        return usage_with_options_internal(usagestr, options, 0);
-               if (!strcmp(arg + 2, "list-opts"))
+               if (!strcmp(arg, "list-opts"))
                        return PARSE_OPT_LIST_OPTS;
-               if (!strcmp(arg + 2, "list-cmds"))
+               if (!strcmp(arg, "list-cmds"))
                        return PARSE_OPT_LIST_SUBCMDS;
-               switch (parse_long_opt(ctx, arg + 2, options)) {
+               switch (parse_long_opt(ctx, arg, options)) {
                case -1:
-                       return parse_options_usage(usagestr, options, arg + 2, 0);
+                       return parse_options_usage(usagestr, options, arg, 0);
                case -2:
                        goto unknown;
+               case -3:
+                       excl_short_opt = 0;
+                       goto exclusive;
                default:
                        break;
                }
@@ -426,6 +454,17 @@ unknown:
                ctx->opt = NULL;
        }
        return PARSE_OPT_DONE;
+
+exclusive:
+       parse_options_usage(usagestr, options, arg, excl_short_opt);
+       if ((excl_short_opt && ctx->excl_opt->short_name) ||
+           ctx->excl_opt->long_name == NULL) {
+               char opt = ctx->excl_opt->short_name;
+               parse_options_usage(NULL, options, &opt, 1);
+       } else {
+               parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
+       }
+       return PARSE_OPT_HELP;
 }
 
 int parse_options_end(struct parse_opt_ctx_t *ctx)
@@ -509,6 +548,8 @@ static void print_option_help(const struct option *opts, int full)
        }
        if (!full && (opts->flags & PARSE_OPT_HIDDEN))
                return;
+       if (opts->flags & PARSE_OPT_DISABLED)
+               return;
 
        pos = fprintf(stderr, "    ");
        if (opts->short_name)
@@ -679,3 +720,16 @@ int parse_opt_verbosity_cb(const struct option *opt,
        }
        return 0;
 }
+
+void set_option_flag(struct option *opts, int shortopt, const char *longopt,
+                    int flag)
+{
+       for (; opts->type != OPTION_END; opts++) {
+               if ((shortopt && opts->short_name == shortopt) ||
+                   (opts->long_name && longopt &&
+                    !strcmp(opts->long_name, longopt))) {
+                       opts->flags |= flag;
+                       break;
+               }
+       }
+}
index b59ba858e73d6768d58e6e476fb4678b5a9da837..97b153fb4999099315003da8c981bd5bbfa23838 100644 (file)
@@ -38,6 +38,8 @@ enum parse_opt_option_flags {
        PARSE_OPT_NONEG   = 4,
        PARSE_OPT_HIDDEN  = 8,
        PARSE_OPT_LASTARG_DEFAULT = 16,
+       PARSE_OPT_DISABLED = 32,
+       PARSE_OPT_EXCLUSIVE = 64,
 };
 
 struct option;
@@ -173,6 +175,7 @@ struct parse_opt_ctx_t {
        const char **out;
        int argc, cpidx;
        const char *opt;
+       const struct option *excl_opt;
        int flags;
 };
 
@@ -211,4 +214,5 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
 
 extern const char *parse_options_fix_filename(const char *prefix, const char *file);
 
+void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
 #endif /* __PERF_PARSE_OPTIONS_H */
index e243ad962a4d8876aecaafccf18858df2e52118f..5c9c4947cfb43f08522baa88aef0d16b5bdc4ee8 100644 (file)
@@ -163,6 +163,41 @@ error:
        return -1;
 }
 
+static int
+perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
+{
+       char path[PATH_MAX];
+       int fd;
+
+       snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       close(fd);
+
+       alias->per_pkg = true;
+       return 0;
+}
+
+static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
+                                   char *dir, char *name)
+{
+       char path[PATH_MAX];
+       int fd;
+
+       snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       alias->snapshot = true;
+       close(fd);
+       return 0;
+}
+
 static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
 {
        struct perf_pmu_alias *alias;
@@ -181,6 +216,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
        INIT_LIST_HEAD(&alias->terms);
        alias->scale = 1.0;
        alias->unit[0] = '\0';
+       alias->per_pkg = false;
 
        ret = parse_events_terms(&alias->terms, buf);
        if (ret) {
@@ -194,6 +230,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
         */
        perf_pmu__parse_unit(alias, dir, name);
        perf_pmu__parse_scale(alias, dir, name);
+       perf_pmu__parse_per_pkg(alias, dir, name);
+       perf_pmu__parse_snapshot(alias, dir, name);
 
        list_add_tail(&alias->list, list);
 
@@ -209,6 +247,10 @@ static inline bool pmu_alias_info_file(char *name)
                return true;
        if (len > 6 && !strcmp(name + len - 6, ".scale"))
                return true;
+       if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
+               return true;
+       if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
+               return true;
 
        return false;
 }
@@ -617,23 +659,27 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
 }
 
 
-static int check_unit_scale(struct perf_pmu_alias *alias,
-                           const char **unit, double *scale)
+static int check_info_data(struct perf_pmu_alias *alias,
+                          struct perf_pmu_info *info)
 {
        /*
         * Only one term in event definition can
-        * define unit and scale, fail if there's
-        * more than one.
+        * define unit, scale and snapshot, fail
+        * if there's more than one.
         */
-       if ((*unit && alias->unit) ||
-           (*scale && alias->scale))
+       if ((info->unit && alias->unit) ||
+           (info->scale && alias->scale) ||
+           (info->snapshot && alias->snapshot))
                return -EINVAL;
 
        if (alias->unit)
-               *unit = alias->unit;
+               info->unit = alias->unit;
 
        if (alias->scale)
-               *scale = alias->scale;
+               info->scale = alias->scale;
+
+       if (alias->snapshot)
+               info->snapshot = alias->snapshot;
 
        return 0;
 }
@@ -649,12 +695,15 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
        struct perf_pmu_alias *alias;
        int ret;
 
+       info->per_pkg = false;
+
        /*
         * Mark unit and scale as not set
         * (different from default values, see below)
         */
-       info->unit   = NULL;
-       info->scale  = 0.0;
+       info->unit     = NULL;
+       info->scale    = 0.0;
+       info->snapshot = false;
 
        list_for_each_entry_safe(term, h, head_terms, list) {
                alias = pmu_find_alias(pmu, term);
@@ -664,10 +713,13 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
                if (ret)
                        return ret;
 
-               ret = check_unit_scale(alias, &info->unit, &info->scale);
+               ret = check_info_data(alias, info);
                if (ret)
                        return ret;
 
+               if (alias->per_pkg)
+                       info->per_pkg = true;
+
                list_del(&term->list);
                free(term);
        }
@@ -747,15 +799,18 @@ void print_pmu_events(const char *event_glob, bool name_only)
 
        pmu = NULL;
        len = 0;
-       while ((pmu = perf_pmu__scan(pmu)) != NULL)
+       while ((pmu = perf_pmu__scan(pmu)) != NULL) {
                list_for_each_entry(alias, &pmu->aliases, list)
                        len++;
-       aliases = malloc(sizeof(char *) * len);
+               if (pmu->selectable)
+                       len++;
+       }
+       aliases = zalloc(sizeof(char *) * len);
        if (!aliases)
-               return;
+               goto out_enomem;
        pmu = NULL;
        j = 0;
-       while ((pmu = perf_pmu__scan(pmu)) != NULL)
+       while ((pmu = perf_pmu__scan(pmu)) != NULL) {
                list_for_each_entry(alias, &pmu->aliases, list) {
                        char *name = format_alias(buf, sizeof(buf), pmu, alias);
                        bool is_cpu = !strcmp(pmu->name, "cpu");
@@ -765,13 +820,23 @@ void print_pmu_events(const char *event_glob, bool name_only)
                              (!is_cpu && strglobmatch(alias->name,
                                                       event_glob))))
                                continue;
-                       aliases[j] = name;
+
                        if (is_cpu && !name_only)
-                               aliases[j] = format_alias_or(buf, sizeof(buf),
-                                                             pmu, alias);
-                       aliases[j] = strdup(aliases[j]);
+                               name = format_alias_or(buf, sizeof(buf), pmu, alias);
+
+                       aliases[j] = strdup(name);
+                       if (aliases[j] == NULL)
+                               goto out_enomem;
                        j++;
                }
+               if (pmu->selectable) {
+                       char *s;
+                       if (asprintf(&s, "%s//", pmu->name) < 0)
+                               goto out_enomem;
+                       aliases[j] = s;
+                       j++;
+               }
+       }
        len = j;
        qsort(aliases, len, sizeof(char *), cmp_string);
        for (j = 0; j < len; j++) {
@@ -780,12 +845,20 @@ void print_pmu_events(const char *event_glob, bool name_only)
                        continue;
                }
                printf("  %-50s [Kernel PMU event]\n", aliases[j]);
-               zfree(&aliases[j]);
                printed++;
        }
        if (printed)
                printf("\n");
-       free(aliases);
+out_free:
+       for (j = 0; j < len; j++)
+               zfree(&aliases[j]);
+       zfree(&aliases);
+       return;
+
+out_enomem:
+       printf("FATAL: not enough memory to print PMU events\n");
+       if (aliases)
+               goto out_free;
 }
 
 bool pmu_have_event(const char *pname, const char *name)
index fe9dfbee8eed96c710c45883927a45c7d7ebf652..6b1249fbdb5f3a736c7c55a4005bf2c679addfa7 100644 (file)
@@ -18,6 +18,7 @@ struct perf_event_attr;
 struct perf_pmu {
        char *name;
        __u32 type;
+       bool selectable;
        struct perf_event_attr *default_config;
        struct cpu_map *cpus;
        struct list_head format;  /* HEAD struct perf_pmu_format -> list */
@@ -28,6 +29,8 @@ struct perf_pmu {
 struct perf_pmu_info {
        const char *unit;
        double scale;
+       bool per_pkg;
+       bool snapshot;
 };
 
 #define UNIT_MAX_LEN   31 /* max length for event unit name */
@@ -38,6 +41,8 @@ struct perf_pmu_alias {
        struct list_head list;  /* ELEM */
        char unit[UNIT_MAX_LEN+1];
        double scale;
+       bool per_pkg;
+       bool snapshot;
 };
 
 struct perf_pmu *perf_pmu__find(const char *name);
index c150ca4343eb216c81244abb73bec70703f142ea..28eb1417cb2a3fc5d3acebc2280cf37ac79ad778 100644 (file)
@@ -1910,21 +1910,21 @@ static int show_perf_probe_event(struct perf_probe_event *pev,
        if (ret < 0)
                return ret;
 
-       printf("  %-20s (on %s", buf, place);
+       pr_info("  %-20s (on %s", buf, place);
        if (module)
-               printf(" in %s", module);
+               pr_info(" in %s", module);
 
        if (pev->nargs > 0) {
-               printf(" with");
+               pr_info(" with");
                for (i = 0; i < pev->nargs; i++) {
                        ret = synthesize_perf_probe_arg(&pev->args[i],
                                                        buf, 128);
                        if (ret < 0)
                                break;
-                       printf(" %s", buf);
+                       pr_info(" %s", buf);
                }
        }
-       printf(")\n");
+       pr_info(")\n");
        free(place);
        return ret;
 }
@@ -2124,7 +2124,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
        }
 
        ret = 0;
-       printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
+       pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
        for (i = 0; i < ntevs; i++) {
                tev = &tevs[i];
                if (pev->event)
@@ -2179,8 +2179,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 
        if (ret >= 0) {
                /* Show how to use the event. */
-               printf("\nYou can now use it in all perf tools, such as:\n\n");
-               printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
+               pr_info("\nYou can now use it in all perf tools, such as:\n\n");
+               pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
                         tev->event);
        }
 
@@ -2444,7 +2444,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
                goto error;
        }
 
-       printf("Removed event: %s\n", ent->s);
+       pr_info("Removed event: %s\n", ent->s);
        return 0;
 error:
        pr_warning("Failed to delete event: %s\n",
index 0a01bac4ce023e136ef15357e80360a90f35d40e..22ebc46226e7ffe05793fadea8527584c616cb01 100644 (file)
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
+#include <linux/bitmap.h>
 
 #include "../util.h"
 #include <EXTERN.h>
@@ -57,7 +58,7 @@ INTERP my_perl;
 #define FTRACE_MAX_EVENT                               \
        ((1 << (sizeof(unsigned short) * 8)) - 1)
 
-struct event_format *events[FTRACE_MAX_EVENT];
+static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
 
 extern struct scripting_context *scripting_context;
 
@@ -238,35 +239,15 @@ static void define_event_symbols(struct event_format *event,
                define_event_symbols(event, ev_name, args->next);
 }
 
-static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
-{
-       static char ev_name[256];
-       struct event_format *event;
-       int type = evsel->attr.config;
-
-       if (events[type])
-               return events[type];
-
-       events[type] = event = evsel->tp_format;
-       if (!event)
-               return NULL;
-
-       sprintf(ev_name, "%s::%s", event->system, event->name);
-
-       define_event_symbols(event, ev_name, event->print_fmt.args);
-
-       return event;
-}
-
 static void perl_process_tracepoint(struct perf_sample *sample,
                                    struct perf_evsel *evsel,
                                    struct thread *thread)
 {
+       struct event_format *event = evsel->tp_format;
        struct format_field *field;
        static char handler[256];
        unsigned long long val;
        unsigned long s, ns;
-       struct event_format *event;
        int pid;
        int cpu = sample->cpu;
        void *data = sample->raw_data;
@@ -278,7 +259,6 @@ static void perl_process_tracepoint(struct perf_sample *sample,
        if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
                return;
 
-       event = find_cache_event(evsel);
        if (!event)
                die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
 
@@ -286,6 +266,9 @@ static void perl_process_tracepoint(struct perf_sample *sample,
 
        sprintf(handler, "%s::%s", event->system, event->name);
 
+       if (!test_and_set_bit(event->id, events_defined))
+               define_event_symbols(event, handler, event->print_fmt.args);
+
        s = nsecs / NSECS_PER_SEC;
        ns = nsecs - s * NSECS_PER_SEC;
 
index 496f21cadd97098751c22e054ec89311a29417f9..d808a328f4dca03cd255edef292271ff9a4cf3f9 100644 (file)
@@ -24,7 +24,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 #include <errno.h>
+#include <linux/bitmap.h>
 
 #include "../../perf.h"
 #include "../debug.h"
 #include "../util.h"
 #include "../event.h"
 #include "../thread.h"
+#include "../comm.h"
+#include "../machine.h"
+#include "../db-export.h"
+#include "../thread-stack.h"
 #include "../trace-event.h"
 #include "../machine.h"
 
@@ -41,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void);
 #define FTRACE_MAX_EVENT                               \
        ((1 << (sizeof(unsigned short) * 8)) - 1)
 
-struct event_format *events[FTRACE_MAX_EVENT];
+static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
 
 #define MAX_FIELDS     64
 #define N_COMMON_FIELDS        7
@@ -53,6 +59,24 @@ static int zero_flag_atom;
 
 static PyObject *main_module, *main_dict;
 
+struct tables {
+       struct db_export        dbe;
+       PyObject                *evsel_handler;
+       PyObject                *machine_handler;
+       PyObject                *thread_handler;
+       PyObject                *comm_handler;
+       PyObject                *comm_thread_handler;
+       PyObject                *dso_handler;
+       PyObject                *symbol_handler;
+       PyObject                *branch_type_handler;
+       PyObject                *sample_handler;
+       PyObject                *call_path_handler;
+       PyObject                *call_return_handler;
+       bool                    db_export_mode;
+};
+
+static struct tables tables_global;
+
 static void handler_call_die(const char *handler_name) NORETURN;
 static void handler_call_die(const char *handler_name)
 {
@@ -232,31 +256,6 @@ static void define_event_symbols(struct event_format *event,
                define_event_symbols(event, ev_name, args->next);
 }
 
-static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
-{
-       static char ev_name[256];
-       struct event_format *event;
-       int type = evsel->attr.config;
-
-       /*
-        * XXX: Do we really need to cache this since now we have evsel->tp_format
-        * cached already? Need to re-read this "cache" routine that as well calls
-        * define_event_symbols() :-\
-        */
-       if (events[type])
-               return events[type];
-
-       events[type] = event = evsel->tp_format;
-       if (!event)
-               return NULL;
-
-       sprintf(ev_name, "%s__%s", event->system, event->name);
-
-       define_event_symbols(event, ev_name, event->print_fmt.args);
-
-       return event;
-}
-
 static PyObject *get_field_numeric_entry(struct event_format *event,
                struct format_field *field, void *data)
 {
@@ -312,9 +311,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
        if (!symbol_conf.use_callchain || !sample->callchain)
                goto exit;
 
-       if (machine__resolve_callchain(al->machine, evsel, al->thread,
-                                          sample, NULL, NULL,
-                                          PERF_MAX_STACK_DEPTH) != 0) {
+       if (thread__resolve_callchain(al->thread, evsel,
+                                     sample, NULL, NULL,
+                                     PERF_MAX_STACK_DEPTH) != 0) {
                pr_err("Failed to resolve callchain. Skipping\n");
                goto exit;
        }
@@ -380,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample,
                                      struct thread *thread,
                                      struct addr_location *al)
 {
+       struct event_format *event = evsel->tp_format;
        PyObject *handler, *context, *t, *obj, *callchain;
        PyObject *dict = NULL;
        static char handler_name[256];
        struct format_field *field;
        unsigned long s, ns;
-       struct event_format *event;
        unsigned n = 0;
        int pid;
        int cpu = sample->cpu;
@@ -397,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample,
        if (!t)
                Py_FatalError("couldn't create Python tuple");
 
-       event = find_cache_event(evsel);
        if (!event)
                die("ug! no event found for type %d", (int)evsel->attr.config);
 
@@ -405,6 +403,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
 
        sprintf(handler_name, "%s__%s", event->system, event->name);
 
+       if (!test_and_set_bit(event->id, events_defined))
+               define_event_symbols(event, handler_name, event->print_fmt.args);
+
        handler = get_handler(handler_name);
        if (!handler) {
                dict = PyDict_New();
@@ -475,6 +476,289 @@ static void python_process_tracepoint(struct perf_sample *sample,
        Py_DECREF(t);
 }
 
+static PyObject *tuple_new(unsigned int sz)
+{
+       PyObject *t;
+
+       t = PyTuple_New(sz);
+       if (!t)
+               Py_FatalError("couldn't create Python tuple");
+       return t;
+}
+
+static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
+{
+#if BITS_PER_LONG == 64
+       return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
+#endif
+#if BITS_PER_LONG == 32
+       return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
+#endif
+}
+
+static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
+{
+       return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
+}
+
+static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
+{
+       return PyTuple_SetItem(t, pos, PyString_FromString(s));
+}
+
+static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+
+       t = tuple_new(2);
+
+       tuple_set_u64(t, 0, evsel->db_id);
+       tuple_set_string(t, 1, perf_evsel__name(evsel));
+
+       call_object(tables->evsel_handler, t, "evsel_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_machine(struct db_export *dbe,
+                                struct machine *machine)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+
+       t = tuple_new(3);
+
+       tuple_set_u64(t, 0, machine->db_id);
+       tuple_set_s32(t, 1, machine->pid);
+       tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : "");
+
+       call_object(tables->machine_handler, t, "machine_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_thread(struct db_export *dbe, struct thread *thread,
+                               u64 main_thread_db_id, struct machine *machine)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+
+       t = tuple_new(5);
+
+       tuple_set_u64(t, 0, thread->db_id);
+       tuple_set_u64(t, 1, machine->db_id);
+       tuple_set_u64(t, 2, main_thread_db_id);
+       tuple_set_s32(t, 3, thread->pid_);
+       tuple_set_s32(t, 4, thread->tid);
+
+       call_object(tables->thread_handler, t, "thread_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_comm(struct db_export *dbe, struct comm *comm)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+
+       t = tuple_new(2);
+
+       tuple_set_u64(t, 0, comm->db_id);
+       tuple_set_string(t, 1, comm__str(comm));
+
+       call_object(tables->comm_handler, t, "comm_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_comm_thread(struct db_export *dbe, u64 db_id,
+                                    struct comm *comm, struct thread *thread)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+
+       t = tuple_new(3);
+
+       tuple_set_u64(t, 0, db_id);
+       tuple_set_u64(t, 1, comm->db_id);
+       tuple_set_u64(t, 2, thread->db_id);
+
+       call_object(tables->comm_thread_handler, t, "comm_thread_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_dso(struct db_export *dbe, struct dso *dso,
+                            struct machine *machine)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+       PyObject *t;
+
+       build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
+
+       t = tuple_new(5);
+
+       tuple_set_u64(t, 0, dso->db_id);
+       tuple_set_u64(t, 1, machine->db_id);
+       tuple_set_string(t, 2, dso->short_name);
+       tuple_set_string(t, 3, dso->long_name);
+       tuple_set_string(t, 4, sbuild_id);
+
+       call_object(tables->dso_handler, t, "dso_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_symbol(struct db_export *dbe, struct symbol *sym,
+                               struct dso *dso)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       u64 *sym_db_id = symbol__priv(sym);
+       PyObject *t;
+
+       t = tuple_new(6);
+
+       tuple_set_u64(t, 0, *sym_db_id);
+       tuple_set_u64(t, 1, dso->db_id);
+       tuple_set_u64(t, 2, sym->start);
+       tuple_set_u64(t, 3, sym->end);
+       tuple_set_s32(t, 4, sym->binding);
+       tuple_set_string(t, 5, sym->name);
+
+       call_object(tables->symbol_handler, t, "symbol_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_branch_type(struct db_export *dbe, u32 branch_type,
+                                    const char *name)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+
+       t = tuple_new(2);
+
+       tuple_set_s32(t, 0, branch_type);
+       tuple_set_string(t, 1, name);
+
+       call_object(tables->branch_type_handler, t, "branch_type_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_sample(struct db_export *dbe,
+                               struct export_sample *es)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+
+       t = tuple_new(21);
+
+       tuple_set_u64(t, 0, es->db_id);
+       tuple_set_u64(t, 1, es->evsel->db_id);
+       tuple_set_u64(t, 2, es->al->machine->db_id);
+       tuple_set_u64(t, 3, es->thread->db_id);
+       tuple_set_u64(t, 4, es->comm_db_id);
+       tuple_set_u64(t, 5, es->dso_db_id);
+       tuple_set_u64(t, 6, es->sym_db_id);
+       tuple_set_u64(t, 7, es->offset);
+       tuple_set_u64(t, 8, es->sample->ip);
+       tuple_set_u64(t, 9, es->sample->time);
+       tuple_set_s32(t, 10, es->sample->cpu);
+       tuple_set_u64(t, 11, es->addr_dso_db_id);
+       tuple_set_u64(t, 12, es->addr_sym_db_id);
+       tuple_set_u64(t, 13, es->addr_offset);
+       tuple_set_u64(t, 14, es->sample->addr);
+       tuple_set_u64(t, 15, es->sample->period);
+       tuple_set_u64(t, 16, es->sample->weight);
+       tuple_set_u64(t, 17, es->sample->transaction);
+       tuple_set_u64(t, 18, es->sample->data_src);
+       tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
+       tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
+
+       call_object(tables->sample_handler, t, "sample_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_call_path(struct db_export *dbe, struct call_path *cp)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       PyObject *t;
+       u64 parent_db_id, sym_db_id;
+
+       parent_db_id = cp->parent ? cp->parent->db_id : 0;
+       sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0;
+
+       t = tuple_new(4);
+
+       tuple_set_u64(t, 0, cp->db_id);
+       tuple_set_u64(t, 1, parent_db_id);
+       tuple_set_u64(t, 2, sym_db_id);
+       tuple_set_u64(t, 3, cp->ip);
+
+       call_object(tables->call_path_handler, t, "call_path_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_export_call_return(struct db_export *dbe,
+                                    struct call_return *cr)
+{
+       struct tables *tables = container_of(dbe, struct tables, dbe);
+       u64 comm_db_id = cr->comm ? cr->comm->db_id : 0;
+       PyObject *t;
+
+       t = tuple_new(11);
+
+       tuple_set_u64(t, 0, cr->db_id);
+       tuple_set_u64(t, 1, cr->thread->db_id);
+       tuple_set_u64(t, 2, comm_db_id);
+       tuple_set_u64(t, 3, cr->cp->db_id);
+       tuple_set_u64(t, 4, cr->call_time);
+       tuple_set_u64(t, 5, cr->return_time);
+       tuple_set_u64(t, 6, cr->branch_count);
+       tuple_set_u64(t, 7, cr->call_ref);
+       tuple_set_u64(t, 8, cr->return_ref);
+       tuple_set_u64(t, 9, cr->cp->parent->db_id);
+       tuple_set_s32(t, 10, cr->flags);
+
+       call_object(tables->call_return_handler, t, "call_return_table");
+
+       Py_DECREF(t);
+
+       return 0;
+}
+
+static int python_process_call_return(struct call_return *cr, void *data)
+{
+       struct db_export *dbe = data;
+
+       return db_export__call_return(dbe, cr);
+}
+
 static void python_process_general_event(struct perf_sample *sample,
                                         struct perf_evsel *evsel,
                                         struct thread *thread,
@@ -551,19 +835,25 @@ exit:
        Py_DECREF(t);
 }
 
-static void python_process_event(union perf_event *event __maybe_unused,
+static void python_process_event(union perf_event *event,
                                 struct perf_sample *sample,
                                 struct perf_evsel *evsel,
                                 struct thread *thread,
                                 struct addr_location *al)
 {
+       struct tables *tables = &tables_global;
+
        switch (evsel->attr.type) {
        case PERF_TYPE_TRACEPOINT:
                python_process_tracepoint(sample, evsel, thread, al);
                break;
        /* Reserve for future process_hw/sw/raw APIs */
        default:
-               python_process_general_event(sample, evsel, thread, al);
+               if (tables->db_export_mode)
+                       db_export__sample(&tables->dbe, event, sample, evsel,
+                                         thread, al);
+               else
+                       python_process_general_event(sample, evsel, thread, al);
        }
 }
 
@@ -589,11 +879,79 @@ error:
        return -1;
 }
 
+#define SET_TABLE_HANDLER_(name, handler_name, table_name) do {                \
+       tables->handler_name = get_handler(#table_name);                \
+       if (tables->handler_name)                                       \
+               tables->dbe.export_ ## name = python_export_ ## name;   \
+} while (0)
+
+#define SET_TABLE_HANDLER(name) \
+       SET_TABLE_HANDLER_(name, name ## _handler, name ## _table)
+
+static void set_table_handlers(struct tables *tables)
+{
+       const char *perf_db_export_mode = "perf_db_export_mode";
+       const char *perf_db_export_calls = "perf_db_export_calls";
+       PyObject *db_export_mode, *db_export_calls;
+       bool export_calls = false;
+       int ret;
+
+       memset(tables, 0, sizeof(struct tables));
+       if (db_export__init(&tables->dbe))
+               Py_FatalError("failed to initialize export");
+
+       db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode);
+       if (!db_export_mode)
+               return;
+
+       ret = PyObject_IsTrue(db_export_mode);
+       if (ret == -1)
+               handler_call_die(perf_db_export_mode);
+       if (!ret)
+               return;
+
+       tables->dbe.crp = NULL;
+       db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
+       if (db_export_calls) {
+               ret = PyObject_IsTrue(db_export_calls);
+               if (ret == -1)
+                       handler_call_die(perf_db_export_calls);
+               export_calls = !!ret;
+       }
+
+       if (export_calls) {
+               tables->dbe.crp =
+                       call_return_processor__new(python_process_call_return,
+                                                  &tables->dbe);
+               if (!tables->dbe.crp)
+                       Py_FatalError("failed to create calls processor");
+       }
+
+       tables->db_export_mode = true;
+       /*
+        * Reserve per symbol space for symbol->db_id via symbol__priv()
+        */
+       symbol_conf.priv_size = sizeof(u64);
+
+       SET_TABLE_HANDLER(evsel);
+       SET_TABLE_HANDLER(machine);
+       SET_TABLE_HANDLER(thread);
+       SET_TABLE_HANDLER(comm);
+       SET_TABLE_HANDLER(comm_thread);
+       SET_TABLE_HANDLER(dso);
+       SET_TABLE_HANDLER(symbol);
+       SET_TABLE_HANDLER(branch_type);
+       SET_TABLE_HANDLER(sample);
+       SET_TABLE_HANDLER(call_path);
+       SET_TABLE_HANDLER(call_return);
+}
+
 /*
  * Start trace script
  */
 static int python_start_script(const char *script, int argc, const char **argv)
 {
+       struct tables *tables = &tables_global;
        const char **command_line;
        char buf[PATH_MAX];
        int i, err = 0;
@@ -632,6 +990,14 @@ static int python_start_script(const char *script, int argc, const char **argv)
 
        free(command_line);
 
+       set_table_handlers(tables);
+
+       if (tables->db_export_mode) {
+               err = db_export__branch_types(&tables->dbe);
+               if (err)
+                       goto error;
+       }
+
        return err;
 error:
        Py_Finalize();
@@ -642,7 +1008,9 @@ error:
 
 static int python_flush_script(void)
 {
-       return 0;
+       struct tables *tables = &tables_global;
+
+       return db_export__flush(&tables->dbe);
 }
 
 /*
@@ -650,8 +1018,12 @@ static int python_flush_script(void)
  */
 static int python_stop_script(void)
 {
+       struct tables *tables = &tables_global;
+
        try_call_object("trace_end", NULL);
 
+       db_export__exit(&tables->dbe);
+
        Py_XDECREF(main_dict);
        Py_XDECREF(main_module);
        Py_Finalize();
index 6702ac28754b903d5d682ad433d70af9909970d8..5f0e05a76c05ab00a267b27701ca37728aee8c54 100644 (file)
@@ -228,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool,
                                  union perf_event *event,
                                  struct perf_session *session);
 
+static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
+                                union perf_event *event __maybe_unused,
+                                struct perf_session *perf_session
+                                __maybe_unused)
+{
+       dump_printf(": unhandled!\n");
+       return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
        if (tool->sample == NULL)
@@ -262,6 +271,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
                else
                        tool->finished_round = process_finished_round_stub;
        }
+       if (tool->id_index == NULL)
+               tool->id_index = process_id_index_stub;
 }
  
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -460,6 +471,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
        [PERF_RECORD_HEADER_EVENT_TYPE]   = perf_event__event_type_swap,
        [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
        [PERF_RECORD_HEADER_BUILD_ID]     = NULL,
+       [PERF_RECORD_ID_INDEX]            = perf_event__all64_swap,
        [PERF_RECORD_HEADER_MAX]          = NULL,
 };
 
@@ -521,15 +533,11 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
                return -ETIME;
 
        if (timestamp < oe->last_flush) {
-               WARN_ONCE(1, "Timestamp below last timeslice flush\n");
-
-               pr_oe_time(timestamp,      "out of order event");
+               pr_oe_time(timestamp,      "out of order event\n");
                pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
                           oe->last_flush_type);
 
-               /* We could get out of order messages after forced flush. */
-               if (oe->last_flush_type != OE_FLUSH__HALF)
-                       return -EINVAL;
+               s->stats.nr_unordered_events++;
        }
 
        new = ordered_events__new(oe, timestamp, event);
@@ -580,15 +588,46 @@ static void regs_dump__printf(u64 mask, u64 *regs)
        }
 }
 
+static const char *regs_abi[] = {
+       [PERF_SAMPLE_REGS_ABI_NONE] = "none",
+       [PERF_SAMPLE_REGS_ABI_32] = "32-bit",
+       [PERF_SAMPLE_REGS_ABI_64] = "64-bit",
+};
+
+static inline const char *regs_dump_abi(struct regs_dump *d)
+{
+       if (d->abi > PERF_SAMPLE_REGS_ABI_64)
+               return "unknown";
+
+       return regs_abi[d->abi];
+}
+
+static void regs__printf(const char *type, struct regs_dump *regs)
+{
+       u64 mask = regs->mask;
+
+       printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n",
+              type,
+              mask,
+              regs_dump_abi(regs));
+
+       regs_dump__printf(mask, regs->regs);
+}
+
 static void regs_user__printf(struct perf_sample *sample)
 {
        struct regs_dump *user_regs = &sample->user_regs;
 
-       if (user_regs->regs) {
-               u64 mask = user_regs->mask;
-               printf("... user regs: mask 0x%" PRIx64 "\n", mask);
-               regs_dump__printf(mask, user_regs->regs);
-       }
+       if (user_regs->regs)
+               regs__printf("user", user_regs);
+}
+
+static void regs_intr__printf(struct perf_sample *sample)
+{
+       struct regs_dump *intr_regs = &sample->intr_regs;
+
+       if (intr_regs->regs)
+               regs__printf("intr", intr_regs);
 }
 
 static void stack_user__printf(struct stack_dump *dump)
@@ -687,6 +726,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
        if (sample_type & PERF_SAMPLE_REGS_USER)
                regs_user__printf(sample);
 
+       if (sample_type & PERF_SAMPLE_REGS_INTR)
+               regs_intr__printf(sample);
+
        if (sample_type & PERF_SAMPLE_STACK_USER)
                stack_user__printf(&sample->user_stack);
 
@@ -888,11 +930,26 @@ static s64 perf_session__process_user_event(struct perf_session *session,
                return tool->build_id(tool, event, session);
        case PERF_RECORD_FINISHED_ROUND:
                return tool->finished_round(tool, event, session);
+       case PERF_RECORD_ID_INDEX:
+               return tool->id_index(tool, event, session);
        default:
                return -EINVAL;
        }
 }
 
+int perf_session__deliver_synth_event(struct perf_session *session,
+                                     union perf_event *event,
+                                     struct perf_sample *sample,
+                                     struct perf_tool *tool)
+{
+       events_stats__inc(&session->stats, event->header.type);
+
+       if (event->header.type >= PERF_RECORD_USER_TYPE_START)
+               return perf_session__process_user_event(session, event, tool, 0);
+
+       return perf_session__deliver_event(session, event, sample, tool, 0);
+}
+
 static void event_swap(union perf_event *event, bool sample_id_all)
 {
        perf_event__swap_op swap;
@@ -1057,6 +1114,9 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
                            "Do you have a KVM guest running and not using 'perf kvm'?\n",
                            session->stats.nr_unprocessable_samples);
        }
+
+       if (session->stats.nr_unordered_events != 0)
+               ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events);
 }
 
 volatile int session_done;
@@ -1417,9 +1477,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
        if (symbol_conf.use_callchain && sample->callchain) {
                struct addr_location node_al;
 
-               if (machine__resolve_callchain(al->machine, evsel, al->thread,
-                                              sample, NULL, NULL,
-                                              PERF_MAX_STACK_DEPTH) != 0) {
+               if (thread__resolve_callchain(al->thread, evsel,
+                                             sample, NULL, NULL,
+                                             PERF_MAX_STACK_DEPTH) != 0) {
                        if (verbose)
                                error("Failed to resolve callchain. Skipping\n");
                        return;
@@ -1594,3 +1654,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
 out:
        return err;
 }
+
+int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
+                                union perf_event *event,
+                                struct perf_session *session)
+{
+       struct perf_evlist *evlist = session->evlist;
+       struct id_index_event *ie = &event->id_index;
+       size_t i, nr, max_nr;
+
+       max_nr = (ie->header.size - sizeof(struct id_index_event)) /
+                sizeof(struct id_index_entry);
+       nr = ie->nr;
+       if (nr > max_nr)
+               return -EINVAL;
+
+       if (dump_trace)
+               fprintf(stdout, " nr: %zu\n", nr);
+
+       for (i = 0; i < nr; i++) {
+               struct id_index_entry *e = &ie->entries[i];
+               struct perf_sample_id *sid;
+
+               if (dump_trace) {
+                       fprintf(stdout, " ... id: %"PRIu64, e->id);
+                       fprintf(stdout, "  idx: %"PRIu64, e->idx);
+                       fprintf(stdout, "  cpu: %"PRId64, e->cpu);
+                       fprintf(stdout, "  tid: %"PRId64"\n", e->tid);
+               }
+
+               sid = perf_evlist__id2sid(evlist, e->id);
+               if (!sid)
+                       return -ENOENT;
+               sid->idx = e->idx;
+               sid->cpu = e->cpu;
+               sid->tid = e->tid;
+       }
+       return 0;
+}
+
+int perf_event__synthesize_id_index(struct perf_tool *tool,
+                                   perf_event__handler_t process,
+                                   struct perf_evlist *evlist,
+                                   struct machine *machine)
+{
+       union perf_event *ev;
+       struct perf_evsel *evsel;
+       size_t nr = 0, i = 0, sz, max_nr, n;
+       int err;
+
+       pr_debug2("Synthesizing id index\n");
+
+       max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
+                sizeof(struct id_index_entry);
+
+       evlist__for_each(evlist, evsel)
+               nr += evsel->ids;
+
+       n = nr > max_nr ? max_nr : nr;
+       sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
+       ev = zalloc(sz);
+       if (!ev)
+               return -ENOMEM;
+
+       ev->id_index.header.type = PERF_RECORD_ID_INDEX;
+       ev->id_index.header.size = sz;
+       ev->id_index.nr = n;
+
+       evlist__for_each(evlist, evsel) {
+               u32 j;
+
+               for (j = 0; j < evsel->ids; j++) {
+                       struct id_index_entry *e;
+                       struct perf_sample_id *sid;
+
+                       if (i >= n) {
+                               err = process(tool, ev, NULL, machine);
+                               if (err)
+                                       goto out_err;
+                               nr -= n;
+                               i = 0;
+                       }
+
+                       e = &ev->id_index.entries[i++];
+
+                       e->id = evsel->id[j];
+
+                       sid = perf_evlist__id2sid(evlist, e->id);
+                       if (!sid) {
+                               free(ev);
+                               return -ENOENT;
+                       }
+
+                       e->idx = sid->idx;
+                       e->cpu = sid->cpu;
+                       e->tid = sid->tid;
+               }
+       }
+
+       sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
+       ev->id_index.header.size = sz;
+       ev->id_index.nr = nr;
+
+       err = process(tool, ev, NULL, machine);
+out_err:
+       free(ev);
+
+       return err;
+}
index a4be851f1a90e0c7a4450aece2bdb80c878b9dbd..dc26ebf60fe421050b58eafa9c8fb29d49fa3f0a 100644 (file)
@@ -126,4 +126,19 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
 extern volatile int session_done;
 
 #define session_done() ACCESS_ONCE(session_done)
+
+int perf_session__deliver_synth_event(struct perf_session *session,
+                                     union perf_event *event,
+                                     struct perf_sample *sample,
+                                     struct perf_tool *tool);
+
+int perf_event__process_id_index(struct perf_tool *tool,
+                                union perf_event *event,
+                                struct perf_session *session);
+
+int perf_event__synthesize_id_index(struct perf_tool *tool,
+                                   perf_event__handler_t process,
+                                   struct perf_evlist *evlist,
+                                   struct machine *machine);
+
 #endif /* __PERF_SESSION_H */
index 4906cd81cb56a852843b38e85a1d2f5b82417654..9139dda9f9a37afd7ae16921928e224604950cf5 100644 (file)
@@ -291,7 +291,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
                else {
                        struct map *map = left->ms.map;
                        left->srcline = get_srcline(map->dso,
-                                           map__rip_2objdump(map, left->ip));
+                                          map__rip_2objdump(map, left->ip),
+                                                   left->ms.sym, true);
                }
        }
        if (!right->srcline) {
@@ -300,7 +301,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
                else {
                        struct map *map = right->ms.map;
                        right->srcline = get_srcline(map->dso,
-                                           map__rip_2objdump(map, right->ip));
+                                            map__rip_2objdump(map, right->ip),
+                                                    right->ms.sym, true);
                }
        }
        return strcmp(right->srcline, left->srcline);
@@ -309,7 +311,7 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
                                        size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline);
+       return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
 }
 
 struct sort_entry sort_srcline = {
@@ -373,6 +375,9 @@ struct sort_entry sort_cpu = {
 static int64_t
 sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
 {
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
+
        return _sort__dso_cmp(left->branch_info->from.map,
                              right->branch_info->from.map);
 }
@@ -380,13 +385,19 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
-       return _hist_entry__dso_snprintf(he->branch_info->from.map,
-                                        bf, size, width);
+       if (he->branch_info)
+               return _hist_entry__dso_snprintf(he->branch_info->from.map,
+                                                bf, size, width);
+       else
+               return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
 }
 
 static int64_t
 sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
 {
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
+
        return _sort__dso_cmp(left->branch_info->to.map,
                              right->branch_info->to.map);
 }
@@ -394,8 +405,11 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
                                       size_t size, unsigned int width)
 {
-       return _hist_entry__dso_snprintf(he->branch_info->to.map,
-                                        bf, size, width);
+       if (he->branch_info)
+               return _hist_entry__dso_snprintf(he->branch_info->to.map,
+                                                bf, size, width);
+       else
+               return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
 }
 
 static int64_t
@@ -404,6 +418,12 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
        struct addr_map_symbol *from_l = &left->branch_info->from;
        struct addr_map_symbol *from_r = &right->branch_info->from;
 
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
+
+       from_l = &left->branch_info->from;
+       from_r = &right->branch_info->from;
+
        if (!from_l->sym && !from_r->sym)
                return _sort__addr_cmp(from_l->addr, from_r->addr);
 
@@ -413,8 +433,13 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
 static int64_t
 sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-       struct addr_map_symbol *to_l = &left->branch_info->to;
-       struct addr_map_symbol *to_r = &right->branch_info->to;
+       struct addr_map_symbol *to_l, *to_r;
+
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
+
+       to_l = &left->branch_info->to;
+       to_r = &right->branch_info->to;
 
        if (!to_l->sym && !to_r->sym)
                return _sort__addr_cmp(to_l->addr, to_r->addr);
@@ -425,19 +450,27 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
                                         size_t size, unsigned int width)
 {
-       struct addr_map_symbol *from = &he->branch_info->from;
-       return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
-                                        he->level, bf, size, width);
+       if (he->branch_info) {
+               struct addr_map_symbol *from = &he->branch_info->from;
 
+               return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
+                                                he->level, bf, size, width);
+       }
+
+       return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
 }
 
 static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
                                       size_t size, unsigned int width)
 {
-       struct addr_map_symbol *to = &he->branch_info->to;
-       return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
-                                        he->level, bf, size, width);
+       if (he->branch_info) {
+               struct addr_map_symbol *to = &he->branch_info->to;
 
+               return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
+                                                he->level, bf, size, width);
+       }
+
+       return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
 }
 
 struct sort_entry sort_dso_from = {
@@ -471,11 +504,13 @@ struct sort_entry sort_sym_to = {
 static int64_t
 sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-       const unsigned char mp = left->branch_info->flags.mispred !=
-                                       right->branch_info->flags.mispred;
-       const unsigned char p = left->branch_info->flags.predicted !=
-                                       right->branch_info->flags.predicted;
+       unsigned char mp, p;
+
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
 
+       mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred;
+       p  = left->branch_info->flags.predicted != right->branch_info->flags.predicted;
        return mp || p;
 }
 
@@ -483,10 +518,12 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width){
        static const char *out = "N/A";
 
-       if (he->branch_info->flags.predicted)
-               out = "N";
-       else if (he->branch_info->flags.mispred)
-               out = "Y";
+       if (he->branch_info) {
+               if (he->branch_info->flags.predicted)
+                       out = "N";
+               else if (he->branch_info->flags.mispred)
+                       out = "Y";
+       }
 
        return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
 }
@@ -989,6 +1026,9 @@ struct sort_entry sort_mem_dcacheline = {
 static int64_t
 sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
 {
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
+
        return left->branch_info->flags.abort !=
                right->branch_info->flags.abort;
 }
@@ -996,10 +1036,15 @@ sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
-       static const char *out = ".";
+       static const char *out = "N/A";
+
+       if (he->branch_info) {
+               if (he->branch_info->flags.abort)
+                       out = "A";
+               else
+                       out = ".";
+       }
 
-       if (he->branch_info->flags.abort)
-               out = "A";
        return repsep_snprintf(bf, size, "%-*s", width, out);
 }
 
@@ -1013,6 +1058,9 @@ struct sort_entry sort_abort = {
 static int64_t
 sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
 {
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
+
        return left->branch_info->flags.in_tx !=
                right->branch_info->flags.in_tx;
 }
@@ -1020,10 +1068,14 @@ sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
-       static const char *out = ".";
+       static const char *out = "N/A";
 
-       if (he->branch_info->flags.in_tx)
-               out = "T";
+       if (he->branch_info) {
+               if (he->branch_info->flags.in_tx)
+                       out = "T";
+               else
+                       out = ".";
+       }
 
        return repsep_snprintf(bf, size, "%-*s", width, out);
 }
index f3e4bc5fe5d214444594193197509fe161bf7104..e73b6a5c9e0fa8772862fdd3535701b67325c5dc 100644 (file)
@@ -8,6 +8,8 @@
 #include "util/util.h"
 #include "util/debug.h"
 
+#include "symbol.h"
+
 #ifdef HAVE_LIBBFD_SUPPORT
 
 /*
@@ -250,7 +252,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
  */
 #define A2L_FAIL_LIMIT 123
 
-char *get_srcline(struct dso *dso, unsigned long addr)
+char *get_srcline(struct dso *dso, unsigned long addr, struct symbol *sym,
+                 bool show_sym)
 {
        char *file = NULL;
        unsigned line = 0;
@@ -258,7 +261,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
        const char *dso_name;
 
        if (!dso->has_srcline)
-               return SRCLINE_UNKNOWN;
+               goto out;
 
        if (dso->symsrc_filename)
                dso_name = dso->symsrc_filename;
@@ -274,7 +277,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
        if (!addr2line(dso_name, addr, &file, &line, dso))
                goto out;
 
-       if (asprintf(&srcline, "%s:%u", file, line) < 0) {
+       if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) {
                free(file);
                goto out;
        }
@@ -289,7 +292,13 @@ out:
                dso->has_srcline = 0;
                dso__free_a2l(dso);
        }
-       return SRCLINE_UNKNOWN;
+       if (sym) {
+               if (asprintf(&srcline, "%s+%ld", show_sym ? sym->name : "",
+                                       addr - sym->start) < 0)
+                       return SRCLINE_UNKNOWN;
+       } else if (asprintf(&srcline, "%s[%lx]", dso->short_name, addr) < 0)
+               return SRCLINE_UNKNOWN;
+       return srcline;
 }
 
 void free_srcline(char *srcline)
index 1e23a5bfb044a4cf39f2a0dfbbb5bf26bbad4b4b..06fcd1bf98b6034e39ef9af8dd0b4111d9208535 100644 (file)
 #include <symbol/kallsyms.h>
 #include "debug.h"
 
+#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
+extern char *cplus_demangle(const char *, int);
+
+static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
+{
+       return cplus_demangle(c, i);
+}
+#else
+#ifdef NO_DEMANGLE
+static inline char *bfd_demangle(void __maybe_unused *v,
+                                const char __maybe_unused *c,
+                                int __maybe_unused i)
+{
+       return NULL;
+}
+#else
+#define PACKAGE 'perf'
+#include <bfd.h>
+#endif
+#endif
+
 #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
 static int elf_getphdrnum(Elf *elf, size_t *dst)
 {
@@ -546,6 +567,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
        return 0;
 }
 
+static int decompress_kmodule(struct dso *dso, const char *name,
+                             enum dso_binary_type type)
+{
+       int fd;
+       const char *ext = strrchr(name, '.');
+       char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
+
+       if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
+            type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) ||
+           type != dso->symtab_type)
+               return -1;
+
+       if (!ext || !is_supported_compression(ext + 1))
+               return -1;
+
+       fd = mkstemp(tmpbuf);
+       if (fd < 0)
+               return -1;
+
+       if (!decompress_to_file(ext + 1, name, fd)) {
+               close(fd);
+               fd = -1;
+       }
+
+       unlink(tmpbuf);
+
+       return fd;
+}
+
 bool symsrc__possibly_runtime(struct symsrc *ss)
 {
        return ss->dynsym || ss->opdsec;
@@ -571,7 +621,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
        Elf *elf;
        int fd;
 
-       fd = open(name, O_RDONLY);
+       if (dso__needs_decompress(dso))
+               fd = decompress_kmodule(dso, name, type);
+       else
+               fd = open(name, O_RDONLY);
+
        if (fd < 0)
                return -1;
 
index c9541fea95148163b380979a5d5a8a8405bfd692..fa585c63f56adcf7dfb0afede3ee55cd5e37298e 100644 (file)
@@ -341,7 +341,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
 
        if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
                dso__set_build_id(dso, build_id);
-               return 1;
        }
        return 0;
 }
index 078331140d8c6a5feec6f9aeda597b49f974cbda..c24c5b83156cd92ec5ba5c457153e43706b81424 100644 (file)
@@ -51,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = {
        DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
        DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
        DSO_BINARY_TYPE__GUEST_KMODULE,
+       DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
        DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+       DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
        DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
        DSO_BINARY_TYPE__NOT_FOUND,
 };
@@ -1300,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
                return dso->kernel == DSO_TYPE_GUEST_KERNEL;
 
        case DSO_BINARY_TYPE__GUEST_KMODULE:
+       case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
        case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
+       case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
                /*
                 * kernel modules know their symtab type - it's set when
                 * creating a module dso in machine__new_module().
@@ -1368,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
                return -1;
 
        kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
-               dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
+               dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
+               dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE ||
+               dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
 
        /*
         * Iterate over candidate debug images.
@@ -1505,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
                           symbol_filter_t filter)
 {
        int i, err = 0;
-       char *filename;
+       char *filename = NULL;
 
-       pr_debug("Looking at the vmlinux_path (%d entries long)\n",
-                vmlinux_path__nr_entries + 1);
-
-       filename = dso__build_id_filename(dso, NULL, 0);
+       if (!symbol_conf.ignore_vmlinux_buildid)
+               filename = dso__build_id_filename(dso, NULL, 0);
        if (filename != NULL) {
                err = dso__load_vmlinux(dso, map, filename, true, filter);
                if (err > 0)
@@ -1518,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
                free(filename);
        }
 
+       pr_debug("Looking at the vmlinux_path (%d entries long)\n",
+                vmlinux_path__nr_entries + 1);
+
        for (i = 0; i < vmlinux_path__nr_entries; ++i) {
                err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
                if (err > 0)
index eb2c19bf8d90d4901703381c3f216ba9576f109f..9d602e9c6f590f73eb9413f53bbbceeada64b20d 100644 (file)
 
 #include "dso.h"
 
-#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
-extern char *cplus_demangle(const char *, int);
-
-static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
-{
-       return cplus_demangle(c, i);
-}
-#else
-#ifdef NO_DEMANGLE
-static inline char *bfd_demangle(void __maybe_unused *v,
-                                const char __maybe_unused *c,
-                                int __maybe_unused i)
-{
-       return NULL;
-}
-#else
-#define PACKAGE 'perf'
-#include <bfd.h>
-#endif
-#endif
-
 /*
  * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
  * for newer versions we can use mmap to reduce memory usage:
@@ -105,6 +84,7 @@ struct symbol_conf {
        unsigned short  nr_events;
        bool            try_vmlinux_path,
                        ignore_vmlinux,
+                       ignore_vmlinux_buildid,
                        show_kernel_path,
                        use_modules,
                        sort_by_name,
@@ -122,7 +102,8 @@ struct symbol_conf {
                        demangle,
                        demangle_kernel,
                        filter_relative,
-                       show_hist_headers;
+                       show_hist_headers,
+                       branch_callstack;
        const char      *vmlinux_name,
                        *kallsyms_name,
                        *source_prefix,
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
new file mode 100644 (file)
index 0000000..9ed59a4
--- /dev/null
@@ -0,0 +1,747 @@
+/*
+ * thread-stack.c: Synthesize a thread's stack using call / return events
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include "thread.h"
+#include "event.h"
+#include "machine.h"
+#include "util.h"
+#include "debug.h"
+#include "symbol.h"
+#include "comm.h"
+#include "thread-stack.h"
+
+#define CALL_PATH_BLOCK_SHIFT 8
+#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
+#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
+
+struct call_path_block {
+       struct call_path cp[CALL_PATH_BLOCK_SIZE];
+       struct list_head node;
+};
+
+/**
+ * struct call_path_root - root of all call paths.
+ * @call_path: root call path
+ * @blocks: list of blocks to store call paths
+ * @next: next free space
+ * @sz: number of spaces
+ */
+struct call_path_root {
+       struct call_path call_path;
+       struct list_head blocks;
+       size_t next;
+       size_t sz;
+};
+
+/**
+ * struct call_return_processor - provides a call-back to consume call-return
+ *                                information.
+ * @cpr: call path root
+ * @process: call-back that accepts call/return information
+ * @data: anonymous data for call-back
+ */
+struct call_return_processor {
+       struct call_path_root *cpr;
+       int (*process)(struct call_return *cr, void *data);
+       void *data;
+};
+
+#define STACK_GROWTH 2048
+
+/**
+ * struct thread_stack_entry - thread stack entry.
+ * @ret_addr: return address
+ * @timestamp: timestamp (if known)
+ * @ref: external reference (e.g. db_id of sample)
+ * @branch_count: the branch count when the entry was created
+ * @cp: call path
+ * @no_call: a 'call' was not seen
+ */
+struct thread_stack_entry {
+       u64 ret_addr;
+       u64 timestamp;
+       u64 ref;
+       u64 branch_count;
+       struct call_path *cp;
+       bool no_call;
+};
+
+/**
+ * struct thread_stack - thread stack constructed from 'call' and 'return'
+ *                       branch samples.
+ * @stack: array that holds the stack
+ * @cnt: number of entries in the stack
+ * @sz: current maximum stack size
+ * @trace_nr: current trace number
+ * @branch_count: running branch count
+ * @kernel_start: kernel start address
+ * @last_time: last timestamp
+ * @crp: call/return processor
+ * @comm: current comm
+ */
+struct thread_stack {
+       struct thread_stack_entry *stack;
+       size_t cnt;
+       size_t sz;
+       u64 trace_nr;
+       u64 branch_count;
+       u64 kernel_start;
+       u64 last_time;
+       struct call_return_processor *crp;
+       struct comm *comm;
+};
+
+static int thread_stack__grow(struct thread_stack *ts)
+{
+       struct thread_stack_entry *new_stack;
+       size_t sz, new_sz;
+
+       new_sz = ts->sz + STACK_GROWTH;
+       sz = new_sz * sizeof(struct thread_stack_entry);
+
+       new_stack = realloc(ts->stack, sz);
+       if (!new_stack)
+               return -ENOMEM;
+
+       ts->stack = new_stack;
+       ts->sz = new_sz;
+
+       return 0;
+}
+
+static struct thread_stack *thread_stack__new(struct thread *thread,
+                                             struct call_return_processor *crp)
+{
+       struct thread_stack *ts;
+
+       ts = zalloc(sizeof(struct thread_stack));
+       if (!ts)
+               return NULL;
+
+       if (thread_stack__grow(ts)) {
+               free(ts);
+               return NULL;
+       }
+
+       if (thread->mg && thread->mg->machine)
+               ts->kernel_start = machine__kernel_start(thread->mg->machine);
+       else
+               ts->kernel_start = 1ULL << 63;
+       ts->crp = crp;
+
+       return ts;
+}
+
+static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
+{
+       int err = 0;
+
+       if (ts->cnt == ts->sz) {
+               err = thread_stack__grow(ts);
+               if (err) {
+                       pr_warning("Out of memory: discarding thread stack\n");
+                       ts->cnt = 0;
+               }
+       }
+
+       ts->stack[ts->cnt++].ret_addr = ret_addr;
+
+       return err;
+}
+
+static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr)
+{
+       size_t i;
+
+       /*
+        * In some cases there may be functions which are not seen to return.
+        * For example when setjmp / longjmp has been used.  Or the perf context
+        * switch in the kernel which doesn't stop and start tracing in exactly
+        * the same code path.  When that happens the return address will be
+        * further down the stack.  If the return address is not found at all,
+        * we assume the opposite (i.e. this is a return for a call that wasn't
+        * seen for some reason) and leave the stack alone.
+        */
+       for (i = ts->cnt; i; ) {
+               if (ts->stack[--i].ret_addr == ret_addr) {
+                       ts->cnt = i;
+                       return;
+               }
+       }
+}
+
+static bool thread_stack__in_kernel(struct thread_stack *ts)
+{
+       if (!ts->cnt)
+               return false;
+
+       return ts->stack[ts->cnt - 1].cp->in_kernel;
+}
+
+static int thread_stack__call_return(struct thread *thread,
+                                    struct thread_stack *ts, size_t idx,
+                                    u64 timestamp, u64 ref, bool no_return)
+{
+       struct call_return_processor *crp = ts->crp;
+       struct thread_stack_entry *tse;
+       struct call_return cr = {
+               .thread = thread,
+               .comm = ts->comm,
+               .db_id = 0,
+       };
+
+       tse = &ts->stack[idx];
+       cr.cp = tse->cp;
+       cr.call_time = tse->timestamp;
+       cr.return_time = timestamp;
+       cr.branch_count = ts->branch_count - tse->branch_count;
+       cr.call_ref = tse->ref;
+       cr.return_ref = ref;
+       if (tse->no_call)
+               cr.flags |= CALL_RETURN_NO_CALL;
+       if (no_return)
+               cr.flags |= CALL_RETURN_NO_RETURN;
+
+       return crp->process(&cr, crp->data);
+}
+
+static int thread_stack__flush(struct thread *thread, struct thread_stack *ts)
+{
+       struct call_return_processor *crp = ts->crp;
+       int err;
+
+       if (!crp) {
+               ts->cnt = 0;
+               return 0;
+       }
+
+       while (ts->cnt) {
+               err = thread_stack__call_return(thread, ts, --ts->cnt,
+                                               ts->last_time, 0, true);
+               if (err) {
+                       pr_err("Error flushing thread stack!\n");
+                       ts->cnt = 0;
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
+                       u64 to_ip, u16 insn_len, u64 trace_nr)
+{
+       if (!thread)
+               return -EINVAL;
+
+       if (!thread->ts) {
+               thread->ts = thread_stack__new(thread, NULL);
+               if (!thread->ts) {
+                       pr_warning("Out of memory: no thread stack\n");
+                       return -ENOMEM;
+               }
+               thread->ts->trace_nr = trace_nr;
+       }
+
+       /*
+        * When the trace is discontinuous, the trace_nr changes.  In that case
+        * the stack might be completely invalid.  Better to report nothing than
+        * to report something misleading, so flush the stack.
+        */
+       if (trace_nr != thread->ts->trace_nr) {
+               if (thread->ts->trace_nr)
+                       thread_stack__flush(thread, thread->ts);
+               thread->ts->trace_nr = trace_nr;
+       }
+
+       /* Stop here if thread_stack__process() is in use */
+       if (thread->ts->crp)
+               return 0;
+
+       if (flags & PERF_IP_FLAG_CALL) {
+               u64 ret_addr;
+
+               if (!to_ip)
+                       return 0;
+               ret_addr = from_ip + insn_len;
+               if (ret_addr == to_ip)
+                       return 0; /* Zero-length calls are excluded */
+               return thread_stack__push(thread->ts, ret_addr);
+       } else if (flags & PERF_IP_FLAG_RETURN) {
+               if (!from_ip)
+                       return 0;
+               thread_stack__pop(thread->ts, to_ip);
+       }
+
+       return 0;
+}
+
+void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
+{
+       if (!thread || !thread->ts)
+               return;
+
+       if (trace_nr != thread->ts->trace_nr) {
+               if (thread->ts->trace_nr)
+                       thread_stack__flush(thread, thread->ts);
+               thread->ts->trace_nr = trace_nr;
+       }
+}
+
+void thread_stack__free(struct thread *thread)
+{
+       if (thread->ts) {
+               thread_stack__flush(thread, thread->ts);
+               zfree(&thread->ts->stack);
+               zfree(&thread->ts);
+       }
+}
+
+void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
+                         size_t sz, u64 ip)
+{
+       size_t i;
+
+       if (!thread || !thread->ts)
+               chain->nr = 1;
+       else
+               chain->nr = min(sz, thread->ts->cnt + 1);
+
+       chain->ips[0] = ip;
+
+       for (i = 1; i < chain->nr; i++)
+               chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
+}
+
+static void call_path__init(struct call_path *cp, struct call_path *parent,
+                           struct symbol *sym, u64 ip, bool in_kernel)
+{
+       cp->parent = parent;
+       cp->sym = sym;
+       cp->ip = sym ? 0 : ip;
+       cp->db_id = 0;
+       cp->in_kernel = in_kernel;
+       RB_CLEAR_NODE(&cp->rb_node);
+       cp->children = RB_ROOT;
+}
+
+static struct call_path_root *call_path_root__new(void)
+{
+       struct call_path_root *cpr;
+
+       cpr = zalloc(sizeof(struct call_path_root));
+       if (!cpr)
+               return NULL;
+       call_path__init(&cpr->call_path, NULL, NULL, 0, false);
+       INIT_LIST_HEAD(&cpr->blocks);
+       return cpr;
+}
+
+static void call_path_root__free(struct call_path_root *cpr)
+{
+       struct call_path_block *pos, *n;
+
+       list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
+               list_del(&pos->node);
+               free(pos);
+       }
+       free(cpr);
+}
+
+static struct call_path *call_path__new(struct call_path_root *cpr,
+                                       struct call_path *parent,
+                                       struct symbol *sym, u64 ip,
+                                       bool in_kernel)
+{
+       struct call_path_block *cpb;
+       struct call_path *cp;
+       size_t n;
+
+       if (cpr->next < cpr->sz) {
+               cpb = list_last_entry(&cpr->blocks, struct call_path_block,
+                                     node);
+       } else {
+               cpb = zalloc(sizeof(struct call_path_block));
+               if (!cpb)
+                       return NULL;
+               list_add_tail(&cpb->node, &cpr->blocks);
+               cpr->sz += CALL_PATH_BLOCK_SIZE;
+       }
+
+       n = cpr->next++ & CALL_PATH_BLOCK_MASK;
+       cp = &cpb->cp[n];
+
+       call_path__init(cp, parent, sym, ip, in_kernel);
+
+       return cp;
+}
+
+static struct call_path *call_path__findnew(struct call_path_root *cpr,
+                                           struct call_path *parent,
+                                           struct symbol *sym, u64 ip, u64 ks)
+{
+       struct rb_node **p;
+       struct rb_node *node_parent = NULL;
+       struct call_path *cp;
+       bool in_kernel = ip >= ks;
+
+       if (sym)
+               ip = 0;
+
+       if (!parent)
+               return call_path__new(cpr, parent, sym, ip, in_kernel);
+
+       p = &parent->children.rb_node;
+       while (*p != NULL) {
+               node_parent = *p;
+               cp = rb_entry(node_parent, struct call_path, rb_node);
+
+               if (cp->sym == sym && cp->ip == ip)
+                       return cp;
+
+               if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+
+       cp = call_path__new(cpr, parent, sym, ip, in_kernel);
+       if (!cp)
+               return NULL;
+
+       rb_link_node(&cp->rb_node, node_parent, p);
+       rb_insert_color(&cp->rb_node, &parent->children);
+
+       return cp;
+}
+
+struct call_return_processor *
+call_return_processor__new(int (*process)(struct call_return *cr, void *data),
+                          void *data)
+{
+       struct call_return_processor *crp;
+
+       crp = zalloc(sizeof(struct call_return_processor));
+       if (!crp)
+               return NULL;
+       crp->cpr = call_path_root__new();
+       if (!crp->cpr)
+               goto out_free;
+       crp->process = process;
+       crp->data = data;
+       return crp;
+
+out_free:
+       free(crp);
+       return NULL;
+}
+
+void call_return_processor__free(struct call_return_processor *crp)
+{
+       if (crp) {
+               call_path_root__free(crp->cpr);
+               free(crp);
+       }
+}
+
+static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
+                                u64 timestamp, u64 ref, struct call_path *cp,
+                                bool no_call)
+{
+       struct thread_stack_entry *tse;
+       int err;
+
+       if (ts->cnt == ts->sz) {
+               err = thread_stack__grow(ts);
+               if (err)
+                       return err;
+       }
+
+       tse = &ts->stack[ts->cnt++];
+       tse->ret_addr = ret_addr;
+       tse->timestamp = timestamp;
+       tse->ref = ref;
+       tse->branch_count = ts->branch_count;
+       tse->cp = cp;
+       tse->no_call = no_call;
+
+       return 0;
+}
+
+static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts,
+                               u64 ret_addr, u64 timestamp, u64 ref,
+                               struct symbol *sym)
+{
+       int err;
+
+       if (!ts->cnt)
+               return 1;
+
+       if (ts->cnt == 1) {
+               struct thread_stack_entry *tse = &ts->stack[0];
+
+               if (tse->cp->sym == sym)
+                       return thread_stack__call_return(thread, ts, --ts->cnt,
+                                                        timestamp, ref, false);
+       }
+
+       if (ts->stack[ts->cnt - 1].ret_addr == ret_addr) {
+               return thread_stack__call_return(thread, ts, --ts->cnt,
+                                                timestamp, ref, false);
+       } else {
+               size_t i = ts->cnt - 1;
+
+               while (i--) {
+                       if (ts->stack[i].ret_addr != ret_addr)
+                               continue;
+                       i += 1;
+                       while (ts->cnt > i) {
+                               err = thread_stack__call_return(thread, ts,
+                                                               --ts->cnt,
+                                                               timestamp, ref,
+                                                               true);
+                               if (err)
+                                       return err;
+                       }
+                       return thread_stack__call_return(thread, ts, --ts->cnt,
+                                                        timestamp, ref, false);
+               }
+       }
+
+       return 1;
+}
+
+static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
+                               struct perf_sample *sample,
+                               struct addr_location *from_al,
+                               struct addr_location *to_al, u64 ref)
+{
+       struct call_path_root *cpr = ts->crp->cpr;
+       struct call_path *cp;
+       struct symbol *sym;
+       u64 ip;
+
+       if (sample->ip) {
+               ip = sample->ip;
+               sym = from_al->sym;
+       } else if (sample->addr) {
+               ip = sample->addr;
+               sym = to_al->sym;
+       } else {
+               return 0;
+       }
+
+       cp = call_path__findnew(cpr, &cpr->call_path, sym, ip,
+                               ts->kernel_start);
+       if (!cp)
+               return -ENOMEM;
+
+       return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp,
+                                    true);
+}
+
+static int thread_stack__no_call_return(struct thread *thread,
+                                       struct thread_stack *ts,
+                                       struct perf_sample *sample,
+                                       struct addr_location *from_al,
+                                       struct addr_location *to_al, u64 ref)
+{
+       struct call_path_root *cpr = ts->crp->cpr;
+       struct call_path *cp, *parent;
+       u64 ks = ts->kernel_start;
+       int err;
+
+       if (sample->ip >= ks && sample->addr < ks) {
+               /* Return to userspace, so pop all kernel addresses */
+               while (thread_stack__in_kernel(ts)) {
+                       err = thread_stack__call_return(thread, ts, --ts->cnt,
+                                                       sample->time, ref,
+                                                       true);
+                       if (err)
+                               return err;
+               }
+
+               /* If the stack is empty, push the userspace address */
+               if (!ts->cnt) {
+                       cp = call_path__findnew(cpr, &cpr->call_path,
+                                               to_al->sym, sample->addr,
+                                               ts->kernel_start);
+                       if (!cp)
+                               return -ENOMEM;
+                       return thread_stack__push_cp(ts, 0, sample->time, ref,
+                                                    cp, true);
+               }
+       } else if (thread_stack__in_kernel(ts) && sample->ip < ks) {
+               /* Return to userspace, so pop all kernel addresses */
+               while (thread_stack__in_kernel(ts)) {
+                       err = thread_stack__call_return(thread, ts, --ts->cnt,
+                                                       sample->time, ref,
+                                                       true);
+                       if (err)
+                               return err;
+               }
+       }
+
+       if (ts->cnt)
+               parent = ts->stack[ts->cnt - 1].cp;
+       else
+               parent = &cpr->call_path;
+
+       /* This 'return' had no 'call', so push and pop top of stack */
+       cp = call_path__findnew(cpr, parent, from_al->sym, sample->ip,
+                               ts->kernel_start);
+       if (!cp)
+               return -ENOMEM;
+
+       err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp,
+                                   true);
+       if (err)
+               return err;
+
+       return thread_stack__pop_cp(thread, ts, sample->addr, sample->time, ref,
+                                   to_al->sym);
+}
+
+static int thread_stack__trace_begin(struct thread *thread,
+                                    struct thread_stack *ts, u64 timestamp,
+                                    u64 ref)
+{
+       struct thread_stack_entry *tse;
+       int err;
+
+       if (!ts->cnt)
+               return 0;
+
+       /* Pop trace end */
+       tse = &ts->stack[ts->cnt - 1];
+       if (tse->cp->sym == NULL && tse->cp->ip == 0) {
+               err = thread_stack__call_return(thread, ts, --ts->cnt,
+                                               timestamp, ref, false);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int thread_stack__trace_end(struct thread_stack *ts,
+                                  struct perf_sample *sample, u64 ref)
+{
+       struct call_path_root *cpr = ts->crp->cpr;
+       struct call_path *cp;
+       u64 ret_addr;
+
+       /* No point having 'trace end' on the bottom of the stack */
+       if (!ts->cnt || (ts->cnt == 1 && ts->stack[0].ref == ref))
+               return 0;
+
+       cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, NULL, 0,
+                               ts->kernel_start);
+       if (!cp)
+               return -ENOMEM;
+
+       ret_addr = sample->ip + sample->insn_len;
+
+       return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp,
+                                    false);
+}
+
+int thread_stack__process(struct thread *thread, struct comm *comm,
+                         struct perf_sample *sample,
+                         struct addr_location *from_al,
+                         struct addr_location *to_al, u64 ref,
+                         struct call_return_processor *crp)
+{
+       struct thread_stack *ts = thread->ts;
+       int err = 0;
+
+       if (ts) {
+               if (!ts->crp) {
+                       /* Supersede thread_stack__event() */
+                       thread_stack__free(thread);
+                       thread->ts = thread_stack__new(thread, crp);
+                       if (!thread->ts)
+                               return -ENOMEM;
+                       ts = thread->ts;
+                       ts->comm = comm;
+               }
+       } else {
+               thread->ts = thread_stack__new(thread, crp);
+               if (!thread->ts)
+                       return -ENOMEM;
+               ts = thread->ts;
+               ts->comm = comm;
+       }
+
+       /* Flush stack on exec */
+       if (ts->comm != comm && thread->pid_ == thread->tid) {
+               err = thread_stack__flush(thread, ts);
+               if (err)
+                       return err;
+               ts->comm = comm;
+       }
+
+       /* If the stack is empty, put the current symbol on the stack */
+       if (!ts->cnt) {
+               err = thread_stack__bottom(thread, ts, sample, from_al, to_al,
+                                          ref);
+               if (err)
+                       return err;
+       }
+
+       ts->branch_count += 1;
+       ts->last_time = sample->time;
+
+       if (sample->flags & PERF_IP_FLAG_CALL) {
+               struct call_path_root *cpr = ts->crp->cpr;
+               struct call_path *cp;
+               u64 ret_addr;
+
+               if (!sample->ip || !sample->addr)
+                       return 0;
+
+               ret_addr = sample->ip + sample->insn_len;
+               if (ret_addr == sample->addr)
+                       return 0; /* Zero-length calls are excluded */
+
+               cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp,
+                                       to_al->sym, sample->addr,
+                                       ts->kernel_start);
+               if (!cp)
+                       return -ENOMEM;
+               err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
+                                           cp, false);
+       } else if (sample->flags & PERF_IP_FLAG_RETURN) {
+               if (!sample->ip || !sample->addr)
+                       return 0;
+
+               err = thread_stack__pop_cp(thread, ts, sample->addr,
+                                          sample->time, ref, from_al->sym);
+               if (err) {
+                       if (err < 0)
+                               return err;
+                       err = thread_stack__no_call_return(thread, ts, sample,
+                                                          from_al, to_al, ref);
+               }
+       } else if (sample->flags & PERF_IP_FLAG_TRACE_BEGIN) {
+               err = thread_stack__trace_begin(thread, ts, sample->time, ref);
+       } else if (sample->flags & PERF_IP_FLAG_TRACE_END) {
+               err = thread_stack__trace_end(ts, sample, ref);
+       }
+
+       return err;
+}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
new file mode 100644 (file)
index 0000000..b843bbe
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * thread-stack.h: Synthesize a thread's stack using call / return events
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __PERF_THREAD_STACK_H
+#define __PERF_THREAD_STACK_H
+
+#include <sys/types.h>
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+
+struct thread;
+struct comm;
+struct ip_callchain;
+struct symbol;
+struct dso;
+struct call_return_processor;
+struct comm;
+struct perf_sample;
+struct addr_location;
+
+/*
+ * Call/Return flags.
+ *
+ * CALL_RETURN_NO_CALL: 'return' but no matching 'call'
+ * CALL_RETURN_NO_RETURN: 'call' but no matching 'return'
+ */
+enum {
+       CALL_RETURN_NO_CALL     = 1 << 0,
+       CALL_RETURN_NO_RETURN   = 1 << 1,
+};
+
+/**
+ * struct call_return - paired call/return information.
+ * @thread: thread in which call/return occurred
+ * @comm: comm in which call/return occurred
+ * @cp: call path
+ * @call_time: timestamp of call (if known)
+ * @return_time: timestamp of return (if known)
+ * @branch_count: number of branches seen between call and return
+ * @call_ref: external reference to 'call' sample (e.g. db_id)
+ * @return_ref:  external reference to 'return' sample (e.g. db_id)
+ * @db_id: id used for db-export
+ * @flags: Call/Return flags
+ */
+struct call_return {
+       struct thread *thread;
+       struct comm *comm;
+       struct call_path *cp;
+       u64 call_time;
+       u64 return_time;
+       u64 branch_count;
+       u64 call_ref;
+       u64 return_ref;
+       u64 db_id;
+       u32 flags;
+};
+
+/**
+ * struct call_path - node in list of calls leading to a function call.
+ * @parent: call path to the parent function call
+ * @sym: symbol of function called
+ * @ip: only if sym is null, the ip of the function
+ * @db_id: id used for db-export
+ * @in_kernel: whether function is a in the kernel
+ * @rb_node: node in parent's tree of called functions
+ * @children: tree of call paths of functions called
+ *
+ * In combination with the call_return structure, the call_path structure
+ * defines a context-sensitve call-graph.
+ */
+struct call_path {
+       struct call_path *parent;
+       struct symbol *sym;
+       u64 ip;
+       u64 db_id;
+       bool in_kernel;
+       struct rb_node rb_node;
+       struct rb_root children;
+};
+
+int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
+                       u64 to_ip, u16 insn_len, u64 trace_nr);
+void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
+void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
+                         size_t sz, u64 ip);
+void thread_stack__free(struct thread *thread);
+
+struct call_return_processor *
+call_return_processor__new(int (*process)(struct call_return *cr, void *data),
+                          void *data);
+void call_return_processor__free(struct call_return_processor *crp);
+int thread_stack__process(struct thread *thread, struct comm *comm,
+                         struct perf_sample *sample,
+                         struct addr_location *from_al,
+                         struct addr_location *to_al, u64 ref,
+                         struct call_return_processor *crp);
+
+#endif
index 2b7b2d91c016b211f48a9823f9837033615b1136..9ebc8b1f9be51f82801e305804e4017eaa274db7 100644 (file)
@@ -4,6 +4,7 @@
 #include <string.h>
 #include "session.h"
 #include "thread.h"
+#include "thread-stack.h"
 #include "util.h"
 #include "debug.h"
 #include "comm.h"
@@ -15,7 +16,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
        pid_t pid = thread->pid_;
 
        if (pid == thread->tid || pid == -1) {
-               thread->mg = map_groups__new();
+               thread->mg = map_groups__new(machine);
        } else {
                leader = machine__findnew_thread(machine, pid, pid);
                if (leader)
@@ -66,6 +67,8 @@ void thread__delete(struct thread *thread)
 {
        struct comm *comm, *tmp;
 
+       thread_stack__free(thread);
+
        if (thread->mg) {
                map_groups__put(thread->mg);
                thread->mg = NULL;
@@ -100,15 +103,14 @@ struct comm *thread__exec_comm(const struct thread *thread)
        return last;
 }
 
-/* CHECKME: time should always be 0 if event aren't ordered */
 int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
                       bool exec)
 {
        struct comm *new, *curr = thread__comm(thread);
        int err;
 
-       /* Override latest entry if it had no specific time coverage */
-       if (!curr->start && !curr->exec) {
+       /* Override the default :tid entry */
+       if (!thread->comm_set) {
                err = comm__override(curr, str, timestamp, exec);
                if (err)
                        return err;
@@ -117,6 +119,9 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
                if (!new)
                        return -ENOMEM;
                list_add(&new->list, &thread->comm_list);
+
+               if (exec)
+                       unwind__flush_access(thread);
        }
 
        thread->comm_set = true;
@@ -195,7 +200,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
 }
 
 void thread__find_cpumode_addr_location(struct thread *thread,
-                                       struct machine *machine,
                                        enum map_type type, u64 addr,
                                        struct addr_location *al)
 {
@@ -208,8 +212,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
        };
 
        for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
-               thread__find_addr_location(thread, machine, cpumodes[i], type,
-                                          addr, al);
+               thread__find_addr_location(thread, cpumodes[i], type, addr, al);
                if (al->map)
                        break;
        }
index 8c75fa774706352d22e2c4aa3390fb3350c89195..160fd066a7d1efe7a45a9bcfb8012bf0bccfc777 100644 (file)
@@ -8,6 +8,8 @@
 #include "symbol.h"
 #include <strlist.h>
 
+struct thread_stack;
+
 struct thread {
        union {
                struct rb_node   rb_node;
@@ -23,8 +25,10 @@ struct thread {
        bool                    dead; /* if set thread has exited */
        struct list_head        comm_list;
        int                     comm_len;
+       u64                     db_id;
 
        void                    *priv;
+       struct thread_stack     *ts;
 };
 
 struct machine;
@@ -54,16 +58,15 @@ void thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
 size_t thread__fprintf(struct thread *thread, FILE *fp);
 
-void thread__find_addr_map(struct thread *thread, struct machine *machine,
+void thread__find_addr_map(struct thread *thread,
                           u8 cpumode, enum map_type type, u64 addr,
                           struct addr_location *al);
 
-void thread__find_addr_location(struct thread *thread, struct machine *machine,
+void thread__find_addr_location(struct thread *thread,
                                u8 cpumode, enum map_type type, u64 addr,
                                struct addr_location *al);
 
 void thread__find_cpumode_addr_location(struct thread *thread,
-                                       struct machine *machine,
                                        enum map_type type, u64 addr,
                                        struct addr_location *al);
 
index f11636966a0f19ee3e77b8e16f0f55e6db505827..bb2708bbfaca9565b48657608ff4d9a0e831e3d6 100644 (file)
@@ -39,7 +39,8 @@ struct perf_tool {
        event_attr_op   attr;
        event_op2       tracing_data;
        event_op2       finished_round,
-                       build_id;
+                       build_id,
+                       id_index;
        bool            ordered_events;
        bool            ordering_requires_timestamps;
 };
index 7419768c38b1f750fc756d370ab08a5d2b791429..2dcfe9a7c8d085b62d66acd574930ea2e5f327a7 100644 (file)
@@ -26,7 +26,7 @@ static int __report_module(struct addr_location *al, u64 ip,
        Dwfl_Module *mod;
        struct dso *dso = NULL;
 
-       thread__find_addr_location(ui->thread, ui->machine,
+       thread__find_addr_location(ui->thread,
                                   PERF_RECORD_MISC_USER,
                                   MAP__FUNCTION, ip, al);
 
@@ -89,7 +89,7 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
        struct addr_location al;
        ssize_t size;
 
-       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
+       thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
                              MAP__FUNCTION, addr, &al);
        if (!al.map) {
                pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -164,14 +164,14 @@ frame_callback(Dwfl_Frame *state, void *arg)
 }
 
 int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
-                       struct machine *machine, struct thread *thread,
+                       struct thread *thread,
                        struct perf_sample *data,
                        int max_stack)
 {
        struct unwind_info ui = {
                .sample         = data,
                .thread         = thread,
-               .machine        = machine,
+               .machine        = thread->mg->machine,
                .cb             = cb,
                .arg            = arg,
                .max_stack      = max_stack,
index e060386165c5fad82372123e99252f577eb7eac4..371219a6daf1cd8209687115bca9a67f7ffc3209 100644 (file)
@@ -284,7 +284,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
 {
        struct addr_location al;
 
-       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
+       thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
                              MAP__FUNCTION, ip, &al);
        return al.map;
 }
@@ -374,7 +374,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
        struct addr_location al;
        ssize_t size;
 
-       thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
+       thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
                              MAP__FUNCTION, addr, &al);
        if (!al.map) {
                pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -476,14 +476,13 @@ static void put_unwind_info(unw_addr_space_t __maybe_unused as,
        pr_debug("unwind: put_unwind_info called\n");
 }
 
-static int entry(u64 ip, struct thread *thread, struct machine *machine,
+static int entry(u64 ip, struct thread *thread,
                 unwind_entry_cb_t cb, void *arg)
 {
        struct unwind_entry e;
        struct addr_location al;
 
-       thread__find_addr_location(thread, machine,
-                                  PERF_RECORD_MISC_USER,
+       thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
                                   MAP__FUNCTION, ip, &al);
 
        e.ip = ip;
@@ -539,11 +538,23 @@ int unwind__prepare_access(struct thread *thread)
                return -ENOMEM;
        }
 
+       unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
        thread__set_priv(thread, addr_space);
 
        return 0;
 }
 
+void unwind__flush_access(struct thread *thread)
+{
+       unw_addr_space_t addr_space;
+
+       if (callchain_param.record_mode != CALLCHAIN_DWARF)
+               return;
+
+       addr_space = thread__priv(thread);
+       unw_flush_cache(addr_space, 0, 0);
+}
+
 void unwind__finish_access(struct thread *thread)
 {
        unw_addr_space_t addr_space;
@@ -574,21 +585,21 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
                unw_word_t ip;
 
                unw_get_reg(&c, UNW_REG_IP, &ip);
-               ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0;
+               ret = ip ? entry(ip, ui->thread, cb, arg) : 0;
        }
 
        return ret;
 }
 
 int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
-                       struct machine *machine, struct thread *thread,
+                       struct thread *thread,
                        struct perf_sample *data, int max_stack)
 {
        u64 ip;
        struct unwind_info ui = {
                .sample       = data,
                .thread       = thread,
-               .machine      = machine,
+               .machine      = thread->mg->machine,
        };
        int ret;
 
@@ -599,7 +610,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
        if (ret)
                return ret;
 
-       ret = entry(ip, thread, machine, cb, arg);
+       ret = entry(ip, thread, cb, arg);
        if (ret)
                return -ENOMEM;
 
index c17c4855bdbc3e4bcf8423246c92b8f7bc750494..12790cf94618eddb9cdcec8607792f57e75a73c8 100644 (file)
@@ -16,13 +16,13 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
 
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
 int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
-                       struct machine *machine,
                        struct thread *thread,
                        struct perf_sample *data, int max_stack);
 /* libunwind specific */
 #ifdef HAVE_LIBUNWIND_SUPPORT
 int libunwind__arch_reg_id(int regnum);
 int unwind__prepare_access(struct thread *thread);
+void unwind__flush_access(struct thread *thread);
 void unwind__finish_access(struct thread *thread);
 #else
 static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
@@ -30,13 +30,13 @@ static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
        return 0;
 }
 
+static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
 static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
 #endif
 #else
 static inline int
 unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
                    void *arg __maybe_unused,
-                   struct machine *machine __maybe_unused,
                    struct thread *thread __maybe_unused,
                    struct perf_sample *data __maybe_unused,
                    int max_stack __maybe_unused)
@@ -49,6 +49,7 @@ static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
        return 0;
 }
 
+static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
 static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
 #endif /* HAVE_DWARF_UNWIND_SUPPORT */
 #endif /* __UNWIND_H */
index 80bfdaa0e2a45e5c7316625ad85e0b61ff9c191c..419bee030f835c295fee546a4211afaa19f84ace 100644 (file)
@@ -154,7 +154,6 @@ extern void set_die_routine(void (*routine)(const char *err, va_list params) NOR
 
 extern int prefixcmp(const char *str, const char *prefix);
 extern void set_buildid_dir(void);
-extern void disable_buildid_cache(void);
 
 static inline const char *skip_prefix(const char *str, const char *prefix)
 {
@@ -338,8 +337,10 @@ static inline int path__join3(char *bf, size_t size,
 }
 
 struct dso;
+struct symbol;
 
-char *get_srcline(struct dso *dso, unsigned long addr);
+char *get_srcline(struct dso *dso, unsigned long addr, struct symbol *sym,
+                 bool show_sym);
 void free_srcline(char *srcline);
 
 int filename__read_int(const char *filename, int *value);
@@ -351,4 +352,9 @@ void mem_bswap_32(void *src, int byte_size);
 
 const char *get_filename_for_perf_kvm(void);
 bool find_process(const char *name);
+
+#ifdef HAVE_ZLIB_SUPPORT
+int gzip_decompress_to_file(const char *input, int output_fd);
+#endif
+
 #endif /* GIT_COMPAT_UTIL_H */
index adca69384fcc044eeea0a1a51580e8a29dea7058..5c7dd796979d0d625df236c82c30b5e22f5ac7d9 100644 (file)
 #include "util.h"
 #include "symbol.h"
 #include "machine.h"
+#include "thread.h"
 #include "linux/string.h"
 #include "debug.h"
 
+/*
+ * Include definition of find_vdso_map() also used in perf-read-vdso.c for
+ * building perf-read-vdso32 and perf-read-vdsox32.
+ */
+#include "find-vdso-map.c"
+
 #define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
 
 struct vdso_file {
@@ -22,10 +29,15 @@ struct vdso_file {
        bool error;
        char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
        const char *dso_name;
+       const char *read_prog;
 };
 
 struct vdso_info {
        struct vdso_file vdso;
+#if BITS_PER_LONG == 64
+       struct vdso_file vdso32;
+       struct vdso_file vdsox32;
+#endif
 };
 
 static struct vdso_info *vdso_info__new(void)
@@ -35,42 +47,23 @@ static struct vdso_info *vdso_info__new(void)
                        .temp_file_name = VDSO__TEMP_FILE_NAME,
                        .dso_name = DSO__NAME_VDSO,
                },
+#if BITS_PER_LONG == 64
+               .vdso32  = {
+                       .temp_file_name = VDSO__TEMP_FILE_NAME,
+                       .dso_name = DSO__NAME_VDSO32,
+                       .read_prog = "perf-read-vdso32",
+               },
+               .vdsox32  = {
+                       .temp_file_name = VDSO__TEMP_FILE_NAME,
+                       .dso_name = DSO__NAME_VDSOX32,
+                       .read_prog = "perf-read-vdsox32",
+               },
+#endif
        };
 
        return memdup(&vdso_info_init, sizeof(vdso_info_init));
 }
 
-static int find_vdso_map(void **start, void **end)
-{
-       FILE *maps;
-       char line[128];
-       int found = 0;
-
-       maps = fopen("/proc/self/maps", "r");
-       if (!maps) {
-               pr_err("vdso: cannot open maps\n");
-               return -1;
-       }
-
-       while (!found && fgets(line, sizeof(line), maps)) {
-               int m = -1;
-
-               /* We care only about private r-x mappings. */
-               if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
-                               start, end, &m))
-                       continue;
-               if (m < 0)
-                       continue;
-
-               if (!strncmp(&line[m], VDSO__MAP_NAME,
-                            sizeof(VDSO__MAP_NAME) - 1))
-                       found = 1;
-       }
-
-       fclose(maps);
-       return !found;
-}
-
 static char *get_file(struct vdso_file *vdso_file)
 {
        char *vdso = NULL;
@@ -117,6 +110,12 @@ void vdso__exit(struct machine *machine)
 
        if (vdso_info->vdso.found)
                unlink(vdso_info->vdso.temp_file_name);
+#if BITS_PER_LONG == 64
+       if (vdso_info->vdso32.found)
+               unlink(vdso_info->vdso32.temp_file_name);
+       if (vdso_info->vdsox32.found)
+               unlink(vdso_info->vdsox32.temp_file_name);
+#endif
 
        zfree(&machine->vdso_info);
 }
@@ -135,6 +134,153 @@ static struct dso *vdso__new(struct machine *machine, const char *short_name,
        return dso;
 }
 
+#if BITS_PER_LONG == 64
+
+static enum dso_type machine__thread_dso_type(struct machine *machine,
+                                             struct thread *thread)
+{
+       enum dso_type dso_type = DSO__TYPE_UNKNOWN;
+       struct map *map;
+       struct dso *dso;
+
+       map = map_groups__first(thread->mg, MAP__FUNCTION);
+       for (; map ; map = map_groups__next(map)) {
+               dso = map->dso;
+               if (!dso || dso->long_name[0] != '/')
+                       continue;
+               dso_type = dso__type(dso, machine);
+               if (dso_type != DSO__TYPE_UNKNOWN)
+                       break;
+       }
+
+       return dso_type;
+}
+
+static int vdso__do_copy_compat(FILE *f, int fd)
+{
+       char buf[4096];
+       size_t count;
+
+       while (1) {
+               count = fread(buf, 1, sizeof(buf), f);
+               if (ferror(f))
+                       return -errno;
+               if (feof(f))
+                       break;
+               if (count && writen(fd, buf, count) != (ssize_t)count)
+                       return -errno;
+       }
+
+       return 0;
+}
+
+static int vdso__copy_compat(const char *prog, int fd)
+{
+       FILE *f;
+       int err;
+
+       f = popen(prog, "r");
+       if (!f)
+               return -errno;
+
+       err = vdso__do_copy_compat(f, fd);
+
+       if (pclose(f) == -1)
+               return -errno;
+
+       return err;
+}
+
+static int vdso__create_compat_file(const char *prog, char *temp_name)
+{
+       int fd, err;
+
+       fd = mkstemp(temp_name);
+       if (fd < 0)
+               return -errno;
+
+       err = vdso__copy_compat(prog, fd);
+
+       if (close(fd) == -1)
+               return -errno;
+
+       return err;
+}
+
+static const char *vdso__get_compat_file(struct vdso_file *vdso_file)
+{
+       int err;
+
+       if (vdso_file->found)
+               return vdso_file->temp_file_name;
+
+       if (vdso_file->error)
+               return NULL;
+
+       err = vdso__create_compat_file(vdso_file->read_prog,
+                                      vdso_file->temp_file_name);
+       if (err) {
+               pr_err("%s failed, error %d\n", vdso_file->read_prog, err);
+               vdso_file->error = true;
+               return NULL;
+       }
+
+       vdso_file->found = true;
+
+       return vdso_file->temp_file_name;
+}
+
+static struct dso *vdso__findnew_compat(struct machine *machine,
+                                       struct vdso_file *vdso_file)
+{
+       const char *file_name;
+       struct dso *dso;
+
+       dso = dsos__find(&machine->user_dsos, vdso_file->dso_name, true);
+       if (dso)
+               return dso;
+
+       file_name = vdso__get_compat_file(vdso_file);
+       if (!file_name)
+               return NULL;
+
+       return vdso__new(machine, vdso_file->dso_name, file_name);
+}
+
+static int vdso__dso_findnew_compat(struct machine *machine,
+                                   struct thread *thread,
+                                   struct vdso_info *vdso_info,
+                                   struct dso **dso)
+{
+       enum dso_type dso_type;
+
+       dso_type = machine__thread_dso_type(machine, thread);
+
+#ifndef HAVE_PERF_READ_VDSO32
+       if (dso_type == DSO__TYPE_32BIT)
+               return 0;
+#endif
+#ifndef HAVE_PERF_READ_VDSOX32
+       if (dso_type == DSO__TYPE_X32BIT)
+               return 0;
+#endif
+
+       switch (dso_type) {
+       case DSO__TYPE_32BIT:
+               *dso = vdso__findnew_compat(machine, &vdso_info->vdso32);
+               return 1;
+       case DSO__TYPE_X32BIT:
+               *dso = vdso__findnew_compat(machine, &vdso_info->vdsox32);
+               return 1;
+       case DSO__TYPE_UNKNOWN:
+       case DSO__TYPE_64BIT:
+       default:
+               return 0;
+       }
+}
+
+#endif
+
 struct dso *vdso__dso_findnew(struct machine *machine,
                              struct thread *thread __maybe_unused)
 {
@@ -148,6 +294,11 @@ struct dso *vdso__dso_findnew(struct machine *machine,
        if (!vdso_info)
                return NULL;
 
+#if BITS_PER_LONG == 64
+       if (vdso__dso_findnew_compat(machine, thread, vdso_info, &dso))
+               return dso;
+#endif
+
        dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
        if (!dso) {
                char *file;
@@ -164,5 +315,7 @@ struct dso *vdso__dso_findnew(struct machine *machine,
 
 bool dso__is_vdso(struct dso *dso)
 {
-       return !strcmp(dso->short_name, DSO__NAME_VDSO);
+       return !strcmp(dso->short_name, DSO__NAME_VDSO) ||
+              !strcmp(dso->short_name, DSO__NAME_VDSO32) ||
+              !strcmp(dso->short_name, DSO__NAME_VDSOX32);
 }
index af9d6929a215571712afb7598b1b90f6216c9ccc..d97da1616f0c5b658d8c1846b0285835b3a3478c 100644 (file)
@@ -7,7 +7,9 @@
 
 #define VDSO__MAP_NAME "[vdso]"
 
-#define DSO__NAME_VDSO "[vdso]"
+#define DSO__NAME_VDSO    "[vdso]"
+#define DSO__NAME_VDSO32  "[vdso32]"
+#define DSO__NAME_VDSOX32 "[vdsox32]"
 
 static inline bool is_vdso_map(const char *filename)
 {
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644 (file)
index 0000000..495a449
--- /dev/null
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <zlib.h>
+
+#include "util/util.h"
+#include "util/debug.h"
+
+
+#define CHUNK_SIZE  16384
+
+int gzip_decompress_to_file(const char *input, int output_fd)
+{
+       int ret = Z_STREAM_ERROR;
+       int input_fd;
+       void *ptr;
+       int len;
+       struct stat stbuf;
+       unsigned char buf[CHUNK_SIZE];
+       z_stream zs = {
+               .zalloc         = Z_NULL,
+               .zfree          = Z_NULL,
+               .opaque         = Z_NULL,
+               .avail_in       = 0,
+               .next_in        = Z_NULL,
+       };
+
+       input_fd = open(input, O_RDONLY);
+       if (input_fd < 0)
+               return -1;
+
+       if (fstat(input_fd, &stbuf) < 0)
+               goto out_close;
+
+       ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
+       if (ptr == MAP_FAILED)
+               goto out_close;
+
+       if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)
+               goto out_unmap;
+
+       zs.next_in = ptr;
+       zs.avail_in = stbuf.st_size;
+
+       do {
+               zs.next_out = buf;
+               zs.avail_out = CHUNK_SIZE;
+
+               ret = inflate(&zs, Z_NO_FLUSH);
+               switch (ret) {
+               case Z_NEED_DICT:
+                       ret = Z_DATA_ERROR;
+                       /* fall through */
+               case Z_DATA_ERROR:
+               case Z_MEM_ERROR:
+                       goto out;
+               default:
+                       break;
+               }
+
+               len = CHUNK_SIZE - zs.avail_out;
+               if (writen(output_fd, buf, len) != len) {
+                       ret = Z_DATA_ERROR;
+                       goto out;
+               }
+
+       } while (ret != Z_STREAM_END);
+
+out:
+       inflateEnd(&zs);
+out_unmap:
+       munmap(ptr, stbuf.st_size);
+out_close:
+       close(input_fd);
+
+       return ret == Z_STREAM_END ? 0 : -1;
+}
index 60b58cd18410e2406352d985215e525e94026f6a..7ccb073f8316d48b6136c60634465a0d9c67dc78 100644 (file)
@@ -122,6 +122,14 @@ static void os_enter_line_edit_mode(void)
 {
        struct termios local_term_attributes;
 
+       term_attributes_were_set = 0;
+
+       /* STDIN must be a terminal */
+
+       if (!isatty(STDIN_FILENO)) {
+               return;
+       }
+
        /* Get and keep the original attributes */
 
        if (tcgetattr(STDIN_FILENO, &original_term_attributes)) {
index 53cee781e24e646f98a041ff1906b1fb13158a3a..24d32968802d5fa4ba7af2583629b720b3a5bc38 100644 (file)
@@ -146,7 +146,7 @@ u32 ap_get_table_length(struct acpi_table_header *table)
 
        if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
                rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
-               return (rsdp->length);
+               return (acpi_tb_get_rsdp_length(rsdp));
        }
 
        /* Normal ACPI table */
index a8f81c782856270ff559dcf7d48d52aec182df31..515247601df4c783f576722cdd0261d41dfe9886 100755 (executable)
@@ -82,7 +82,7 @@ parse_opts() { # opts
 }
 
 # Parameters
-DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' '`
+DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
 TRACING_DIR=$DEBUGFS_DIR/tracing
 TOP_DIR=`absdir $0`
 TEST_DIR=$TOP_DIR/test.d
index 57b9c2b7c4ffbfb5950af351f9157e97a075caac..6f6733331d9597918353464a71af1e9d9e04a251 100644 (file)
@@ -128,7 +128,7 @@ static int sock_fanout_read_ring(int fd, void *ring)
        struct tpacket2_hdr *header = ring;
        int count = 0;
 
-       while (header->tp_status & TP_STATUS_USER && count < RING_NUM_FRAMES) {
+       while (count < RING_NUM_FRAMES && header->tp_status & TP_STATUS_USER) {
                count++;
                header = ring + (count * getpagesize());
        }
index f6b2b4771b78796e8633f87b054aac64a7ddd424..8ca9f21f2efcba8ab113585192d9cf285ebca77a 100755 (executable)
@@ -45,7 +45,7 @@ trap 'rm -rf $T' 0
 touch $T
 
 . $KVM/bin/functions.sh
-. $KVPATH/ver_functions.sh
+. $CONFIGFRAG/ver_functions.sh
 
 config_template=${1}
 config_dir=`echo $config_template | sed -e 's,/[^/]*$,,'`
@@ -168,8 +168,8 @@ then
        touch $resdir/buildonly
        exit 0
 fi
-echo $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
-( $QEMU $qemu_args -m 512 -kernel $builddir/$BOOT_IMAGE -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) &
+echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
+( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) &
 qemu_pid=$!
 commandcompleted=0
 echo Monitoring qemu job at pid $qemu_pid
index e527dc952eb010553a9dca7b76d2b324b541a44b..368d64ac779e52e1cb787564bc1ddcc880e91ec5 100755 (executable)
@@ -47,7 +47,6 @@ resdir=""
 configs=""
 cpus=0
 ds=`date +%Y.%m.%d-%H:%M:%S`
-kversion=""
 
 . functions.sh
 
@@ -64,7 +63,6 @@ usage () {
        echo "       --duration minutes"
        echo "       --interactive"
        echo "       --kmake-arg kernel-make-arguments"
-       echo "       --kversion vN.NN"
        echo "       --mac nn:nn:nn:nn:nn:nn"
        echo "       --no-initrd"
        echo "       --qemu-args qemu-system-..."
@@ -128,11 +126,6 @@ do
                TORTURE_KMAKE_ARG="$2"
                shift
                ;;
-       --kversion)
-               checkarg --kversion "(kernel version)" $# "$2" '^v[0-9.]*$' '^error'
-               kversion=$2
-               shift
-               ;;
        --mac)
                checkarg --mac "(MAC address)" $# "$2" '^\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}$' error
                TORTURE_QEMU_MAC=$2
@@ -170,11 +163,10 @@ do
 done
 
 CONFIGFRAG=${KVM}/configs/${TORTURE_SUITE}; export CONFIGFRAG
-KVPATH=${CONFIGFRAG}/$kversion; export KVPATH
 
 if test -z "$configs"
 then
-       configs="`cat $CONFIGFRAG/$kversion/CFLIST`"
+       configs="`cat $CONFIGFRAG/CFLIST`"
 fi
 
 if test -z "$resdir"
@@ -186,10 +178,10 @@ fi
 touch $T/cfgcpu
 for CF in $configs
 do
-       if test -f "$CONFIGFRAG/$kversion/$CF"
+       if test -f "$CONFIGFRAG/$CF"
        then
-               cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$kversion/$CF`
-               cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$kversion/$CF" "$cpu_count"`
+               cpu_count=`configNR_CPUS.sh $CONFIGFRAG/$CF`
+               cpu_count=`configfrag_boot_cpus "$TORTURE_BOOTARGS" "$CONFIGFRAG/$CF" "$cpu_count"`
                echo $CF $cpu_count >> $T/cfgcpu
        else
                echo "The --configs file $CF does not exist, terminating."
@@ -252,7 +244,6 @@ END {
 cat << ___EOF___ > $T/script
 CONFIGFRAG="$CONFIGFRAG"; export CONFIGFRAG
 KVM="$KVM"; export KVM
-KVPATH="$KVPATH"; export KVPATH
 PATH="$PATH"; export PATH
 TORTURE_BOOT_IMAGE="$TORTURE_BOOT_IMAGE"; export TORTURE_BOOT_IMAGE
 TORTURE_BUILDONLY="$TORTURE_BUILDONLY"; export TORTURE_BUILDONLY
@@ -285,7 +276,7 @@ then
 fi
 ___EOF___
 awk < $T/cfgcpu.pack \
-       -v CONFIGDIR="$CONFIGFRAG/$kversion/" \
+       -v CONFIGDIR="$CONFIGFRAG/" \
        -v KVM="$KVM" \
        -v ncpus=$cpus \
        -v rd=$resdir/$ds/ \
index f4feaee4077662e588772d62801fc93c79043b5e..36e41df3d27aa6ad7abdf56dba609fd51bb1a9b1 100644 (file)
@@ -7,6 +7,8 @@ CONFIG_HZ_PERIODIC=y
 CONFIG_NO_HZ_IDLE=n
 CONFIG_NO_HZ_FULL=n
 CONFIG_RCU_TRACE=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
 CONFIG_DEBUG_LOCK_ALLOC=y
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
 CONFIG_PREEMPT_COUNT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot b/tools/testing/selftests/rcutorture/configs/rcu/TINY02.boot
new file mode 100644 (file)
index 0000000..0f08027
--- /dev/null
@@ -0,0 +1,2 @@
+rcupdate.rcu_self_test=1
+rcupdate.rcu_self_test_bh=1
index 38e3895759dd6ee2b05589fd75aaea92980337ae..f8a10a7500c64f057987e3d5e3ab765d322973fb 100644 (file)
@@ -2,7 +2,7 @@ CONFIG_SMP=y
 CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+#CHECK#CONFIG_PREEMPT_RCU=y
 CONFIG_HZ_PERIODIC=n
 CONFIG_NO_HZ_IDLE=y
 CONFIG_NO_HZ_FULL=n
@@ -14,6 +14,5 @@ CONFIG_RCU_NOCB_CPU=y
 CONFIG_RCU_NOCB_CPU_ZERO=y
 CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index ea119ba2f7d42b5977d225c0b9480a7454548bea..629122fb8b4a12323e800f09453a3a06718927d8 100644 (file)
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8
 CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+#CHECK#CONFIG_PREEMPT_RCU=y
 CONFIG_HZ_PERIODIC=n
 CONFIG_NO_HZ_IDLE=y
 CONFIG_NO_HZ_FULL=n
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=n
 CONFIG_DEBUG_LOCK_ALLOC=y
 CONFIG_PROVE_LOCKING=n
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=y
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index 19cf9485f48a4b0191fda1f19fadcc17b52e2094..a25de47888a4fc11371adc7bc99a93fe2dfcf8d6 100644 (file)
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8
 CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+#CHECK#CONFIG_PREEMPT_RCU=y
 CONFIG_HZ_PERIODIC=n
 CONFIG_NO_HZ_IDLE=y
 CONFIG_NO_HZ_FULL=n
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=n
 CONFIG_DEBUG_LOCK_ALLOC=y
 CONFIG_PROVE_LOCKING=n
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=y
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index f4567fb3e3325ce967f5731cfbde164151f3d368..53f24e0a0ab618c8470e1727ecec0a8d78ce5db3 100644 (file)
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=8
 CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+#CHECK#CONFIG_PREEMPT_RCU=y
 CONFIG_HZ_PERIODIC=y
 CONFIG_NO_HZ_IDLE=n
 CONFIG_NO_HZ_FULL=n
@@ -15,7 +15,6 @@ CONFIG_RCU_FANOUT_EXACT=n
 CONFIG_RCU_NOCB_CPU=n
 CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
+CONFIG_RCU_KTHREAD_PRIO=2
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index 0a262fbb0c124bb2caf6a042eac87c80171cb22f..0f84db35b36d6221b05a1a25d001f459b0870a08 100644 (file)
@@ -19,5 +19,4 @@ CONFIG_RCU_FANOUT_EXACT=n
 CONFIG_RCU_NOCB_CPU=n
 CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_RCU_CPU_STALL_VERBOSE=y
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index 3a06b97e9a732641ebee070a6b08bf4102c7601f..212e3bfd2b2ac0b8d21bc261e247600733e3c5cc 100644 (file)
@@ -19,5 +19,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_PROVE_RCU=y
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index 3b42b8b033cd4a81940364e877747854eb67a2dc..15b3e1a86f74211f305519ee0a08dd932d5f8bb8 100644 (file)
@@ -1 +1,2 @@
 rcutorture.torture_type=sched
+rcupdate.rcu_self_test_sched=1
index 8f084cca91bfeb48be70aa427858035f66ef4a8c..7eee63b442181267b6ae4ca0c723af59bcb2ac37 100644 (file)
@@ -20,5 +20,4 @@ CONFIG_DEBUG_LOCK_ALLOC=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_PROVE_RCU=y
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE06.boot
new file mode 100644 (file)
index 0000000..da9a03a
--- /dev/null
@@ -0,0 +1,3 @@
+rcupdate.rcu_self_test=1
+rcupdate.rcu_self_test_bh=1
+rcupdate.rcu_self_test_sched=1
index 8f1017666aa7698853f43456e07cd66db52e366c..92a97fa97dec1c4b06dabea9dcbea5e614bad965 100644 (file)
@@ -19,5 +19,4 @@ CONFIG_RCU_FANOUT_EXACT=n
 CONFIG_RCU_NOCB_CPU=n
 CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index 69a2e255bf984527d60faa2d8e425c642ee8fa81..5812027d6f9ff043fecdcb2558a0c4befe83b50c 100644 (file)
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=16
 CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+#CHECK#CONFIG_PREEMPT_RCU=y
 CONFIG_HZ_PERIODIC=n
 CONFIG_NO_HZ_IDLE=y
 CONFIG_NO_HZ_FULL=n
@@ -18,7 +18,8 @@ CONFIG_RCU_FANOUT_LEAF=2
 CONFIG_RCU_NOCB_CPU=y
 CONFIG_RCU_NOCB_CPU_ALL=y
 CONFIG_DEBUG_LOCK_ALLOC=n
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index a0f32fb8f17e3f2d793a21bc10c8a7b991029bce..3eaeccacb08389117d7d2ace6e4381049a2e5e57 100644 (file)
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=16
 CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+#CHECK#CONFIG_PREEMPT_RCU=y
 CONFIG_HZ_PERIODIC=n
 CONFIG_NO_HZ_IDLE=y
 CONFIG_NO_HZ_FULL=n
@@ -19,6 +19,5 @@ CONFIG_RCU_NOCB_CPU=y
 CONFIG_RCU_NOCB_CPU_ALL=y
 CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
index 3b42b8b033cd4a81940364e877747854eb67a2dc..2561daf605ad5f9a09920e98b18ab451d3ddada3 100644 (file)
@@ -1 +1,3 @@
 rcutorture.torture_type=sched
+rcupdate.rcu_self_test=1
+rcupdate.rcu_self_test_sched=1
index b7a62a540ad1397a9c9e3e8d23213e1cb3af5a55..6076b36f6c0b452c27ffb0c80e40fdacc4014eca 100644 (file)
@@ -3,7 +3,7 @@ CONFIG_NR_CPUS=1
 CONFIG_PREEMPT_NONE=n
 CONFIG_PREEMPT_VOLUNTARY=n
 CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
+#CHECK#CONFIG_PREEMPT_RCU=y
 CONFIG_HZ_PERIODIC=n
 CONFIG_NO_HZ_IDLE=y
 CONFIG_NO_HZ_FULL=n
@@ -14,6 +14,5 @@ CONFIG_HIBERNATION=n
 CONFIG_RCU_NOCB_CPU=n
 CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_RCU_CPU_STALL_INFO=n
-CONFIG_RCU_CPU_STALL_VERBOSE=n
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/CFLIST
deleted file mode 100644 (file)
index 1822394..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d3ef873..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index f72402d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index a55c008..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v0.0/ver_functions.sh
deleted file mode 100644 (file)
index 5ace37a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-#
-# Kernel-version-dependent shell functions for the rest of the scripts.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2013
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-# per_version_boot_params bootparam-string config-file seconds
-#
-# Adds per-version torture-module parameters to kernels supporting them.
-# Which old kernels do not.
-per_version_boot_params () {
-       echo    rcutorture.stat_interval=15 \
-               rcutorture.shutdown_secs=$3 \
-               rcutorture.rcutorture_runnable=1 \
-               rcutorture.test_no_idle_hz=1 \
-               rcutorture.verbose=1
-}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/CFLIST
deleted file mode 100644 (file)
index da4cbc6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-sysidleY.2013.06.19a
-sysidleN.2013.06.19a
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-P6---t-nh-SD-smp-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d81e11d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N6---t-nh-SD-smp-hp
deleted file mode 100644 (file)
index 0ccc36d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_NR_CPUS=1
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N7-4-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 3f640cf..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=y
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/N8-2-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 285da2d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=14
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 9647c44..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index a55c008..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P6---t-nh-SD-smp-hp
deleted file mode 100644 (file)
index f4c9175..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=n
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 77a8c5b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=n
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-all
deleted file mode 100644 (file)
index 0eecebc..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=y
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-HP-none
deleted file mode 100644 (file)
index 0eecebc..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=y
-CONFIG_RCU_NOCB_CPU_ZERO=n
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/P7-4-T-NH-SD-SMP-hp
deleted file mode 100644 (file)
index 588bc70..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=16
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_RCU_NOCB_CPU=y
-CONFIG_RCU_NOCB_CPU_NONE=n
-CONFIG_RCU_NOCB_CPU_ZERO=y
-CONFIG_RCU_NOCB_CPU_ALL=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLUB=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.12/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/CFLIST
deleted file mode 100644 (file)
index 1822394..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d81e11d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 9647c44..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index a55c008..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.3/ver_functions.sh
deleted file mode 100644 (file)
index bae5569..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-#
-# Kernel-version-dependent shell functions for the rest of the scripts.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2013
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-# rcutorture_param_onoff bootparam-string config-file
-#
-# Adds onoff rcutorture module parameters to kernels having it.
-rcutorture_param_onoff () {
-       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
-       then
-               echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
-               echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
-       fi
-}
-
-# per_version_boot_params bootparam-string config-file seconds
-#
-# Adds per-version torture-module parameters to kernels supporting them.
-per_version_boot_params () {
-       echo $1 `rcutorture_param_onoff "$1" "$2"` \
-               rcutorture.stat_interval=15 \
-               rcutorture.shutdown_secs=$3 \
-               rcutorture.rcutorture_runnable=1 \
-               rcutorture.test_no_idle_hz=1 \
-               rcutorture.verbose=1
-}
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/CFLIST
deleted file mode 100644 (file)
index 1822394..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-P1-S-T-NH-SD-SMP-HP
-P2-2-t-nh-sd-SMP-hp
-P3-3-T-nh-SD-SMP-hp
-P4-A-t-NH-sd-SMP-HP
-P5-U-T-NH-sd-SMP-hp
-N1-S-T-NH-SD-SMP-HP
-N2-2-t-nh-sd-SMP-hp
-N3-3-T-nh-SD-SMP-hp
-N4-A-t-NH-sd-SMP-HP
-N5-U-T-NH-sd-SMP-hp
-PT1-nh
-PT2-NH
-NT1-nh
-NT3-NH
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index d81e11d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 02e4185..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b3100f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index c56b445..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/N5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index 90d924f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-#CHECK#CONFIG_TREE_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT1-nh
deleted file mode 100644 (file)
index 023f312..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/NT3-NH
deleted file mode 100644 (file)
index 6fd0235..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#CHECK#CONFIG_TINY_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=y
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=n
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P1-S-T-NH-SD-SMP-HP
deleted file mode 100644 (file)
index 9647c44..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_RCU_FAST_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=8
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P2-2-t-nh-sd-SMP-hp
deleted file mode 100644 (file)
index 0f3b667..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=4
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P3-3-T-nh-SD-SMP-hp
deleted file mode 100644 (file)
index b035e14..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_NO_HZ=n
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=2
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P4-A-t-NH-sd-SMP-HP
deleted file mode 100644 (file)
index 3ccf6a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_RCU_TRACE=n
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=n
-CONFIG_HOTPLUG_CPU=y
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/P5-U-T-NH-sd-SMP-hp
deleted file mode 100644 (file)
index a55c008..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_CPU_STALL_INFO=y
-CONFIG_NO_HZ=y
-CONFIG_SMP=y
-CONFIG_RCU_FANOUT=6
-CONFIG_NR_CPUS=8
-CONFIG_RCU_FANOUT_EXACT=y
-CONFIG_HOTPLUG_CPU=n
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-#CHECK#CONFIG_TREE_PREEMPT_RCU=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_RT_MUTEXES=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT1-nh
deleted file mode 100644 (file)
index e3361c3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_BOOST=y
-CONFIG_RCU_BOOST_PRIO=2
-CONFIG_RCU_TRACE=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=n
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/PT2-NH
deleted file mode 100644 (file)
index 64abfc3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-CONFIG_TINY_PREEMPT_RCU=y
-CONFIG_RCU_TORTURE_TEST=m
-CONFIG_MODULE_UNLOAD=y
-CONFIG_SUSPEND=n
-CONFIG_HIBERNATION=n
-#
-CONFIG_SMP=n
-#
-CONFIG_HOTPLUG_CPU=n
-#
-CONFIG_NO_HZ=y
-#
-CONFIG_PREEMPT_NONE=n
-CONFIG_PREEMPT_VOLUNTARY=n
-CONFIG_PREEMPT=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_PROVE_RCU=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_PRINTK_TIME=y
-
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcu/v3.5/ver_functions.sh
deleted file mode 100644 (file)
index 8977d8d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/bash
-#
-# Kernel-version-dependent shell functions for the rest of the scripts.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU 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, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (C) IBM Corporation, 2013
-#
-# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-
-# rcutorture_param_n_barrier_cbs bootparam-string
-#
-# Adds n_barrier_cbs rcutorture module parameter to kernels having it.
-rcutorture_param_n_barrier_cbs () {
-       if echo $1 | grep -q "rcutorture\.n_barrier_cbs"
-       then
-               :
-       else
-               echo rcutorture.n_barrier_cbs=4
-       fi
-}
-
-# rcutorture_param_onoff bootparam-string config-file
-#
-# Adds onoff rcutorture module parameters to kernels having it.
-rcutorture_param_onoff () {
-       if ! bootparam_hotplug_cpu "$1" && configfrag_hotplug_cpu "$2"
-       then
-               echo CPU-hotplug kernel, adding rcutorture onoff. 1>&2
-               echo rcutorture.onoff_interval=3 rcutorture.onoff_holdoff=30
-       fi
-}
-
-# per_version_boot_params bootparam-string config-file seconds
-#
-# Adds per-version torture-module parameters to kernels supporting them.
-per_version_boot_params () {
-       echo $1 `rcutorture_param_onoff "$1" "$2"` \
-               `rcutorture_param_n_barrier_cbs "$1"` \
-               rcutorture.stat_interval=15 \
-               rcutorture.shutdown_secs=$3 \
-               rcutorture.rcutorture_runnable=1 \
-               rcutorture.test_no_idle_hz=1 \
-               rcutorture.verbose=1
-}
index 28db67b54e55d404bff62a720c0a814b34ef6647..9ef33a743b733339ec104c10f0caadfb47035794 100644 (file)
@@ -34,7 +34,7 @@ CONFIG_PREEMPT
 CONFIG_PREEMPT_RCU
 CONFIG_SMP
 CONFIG_TINY_RCU
-CONFIG_TREE_PREEMPT_RCU
+CONFIG_PREEMPT_RCU
 CONFIG_TREE_RCU
 
        All forced by CONFIG_TINY_RCU.
index 3e588db86a17c23cb952419753ed0cde5daa6d04..ec03c883db005192c3d5c644ff2595f3e3c6f673 100644 (file)
@@ -1,5 +1,5 @@
 This document gives a brief rationale for the TREE_RCU-related test
-cases, a group that includes TREE_PREEMPT_RCU.
+cases, a group that includes PREEMPT_RCU.
 
 
 Kconfig Parameters:
@@ -14,10 +14,9 @@ CONFIG_NO_HZ_FULL_SYSIDLE -- Do one.
 CONFIG_PREEMPT -- Do half.  (First three and #8.)
 CONFIG_PROVE_LOCKING -- Do all but two, covering CONFIG_PROVE_RCU and not.
 CONFIG_PROVE_RCU -- Do all but one under CONFIG_PROVE_LOCKING.
-CONFIG_RCU_BOOST -- one of TREE_PREEMPT_RCU.
-CONFIG_RCU_BOOST_PRIO -- set to 2 for _BOOST testing.
-CONFIG_RCU_CPU_STALL_INFO -- do one with and without _VERBOSE.
-CONFIG_RCU_CPU_STALL_VERBOSE -- do one with and without _INFO.
+CONFIG_RCU_BOOST -- one of PREEMPT_RCU.
+CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing.
+CONFIG_RCU_CPU_STALL_INFO -- Do one.
 CONFIG_RCU_FANOUT -- Cover hierarchy as currently, but overlap with others.
 CONFIG_RCU_FANOUT_EXACT -- Do one.
 CONFIG_RCU_FANOUT_LEAF -- Do one non-default.
@@ -27,7 +26,7 @@ CONFIG_RCU_NOCB_CPU_ALL -- Do one.
 CONFIG_RCU_NOCB_CPU_NONE -- Do one.
 CONFIG_RCU_NOCB_CPU_ZERO -- Do one.
 CONFIG_RCU_TRACE -- Do half.
-CONFIG_SMP -- Need one !SMP for TREE_PREEMPT_RCU.
+CONFIG_SMP -- Need one !SMP for PREEMPT_RCU.
 RCU-bh: Do one with PREEMPT and one with !PREEMPT.
 RCU-sched: Do one with PREEMPT but not BOOST.
 
@@ -77,7 +76,7 @@ CONFIG_RCU_CPU_STALL_TIMEOUT
 
 CONFIG_RCU_STALL_COMMON
 
-       Implied by TREE_RCU and TREE_PREEMPT_RCU.
+       Implied by TREE_RCU and PREEMPT_RCU.
 
 CONFIG_RCU_TORTURE_TEST
 CONFIG_RCU_TORTURE_TEST_RUNNABLE
@@ -88,7 +87,7 @@ CONFIG_RCU_USER_QS
 
        Redundant with CONFIG_NO_HZ_FULL.
 
-CONFIG_TREE_PREEMPT_RCU
+CONFIG_PREEMPT_RCU
 CONFIG_TREE_RCU
 
        These are controlled by CONFIG_PREEMPT.
index 3aaca49de3257eed0bd905ac26112cacd49588dd..aacdb59f30dedcd780ee29e2903d928194a42a5c 100644 (file)
@@ -1933,7 +1933,7 @@ out:
 
 int kvm_vgic_create(struct kvm *kvm)
 {
-       int i, vcpu_lock_idx = -1, ret = 0;
+       int i, vcpu_lock_idx = -1, ret;
        struct kvm_vcpu *vcpu;
 
        mutex_lock(&kvm->lock);
@@ -1948,6 +1948,7 @@ int kvm_vgic_create(struct kvm *kvm)
         * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
         * that no other VCPUs are run while we create the vgic.
         */
+       ret = -EBUSY;
        kvm_for_each_vcpu(i, vcpu, kvm) {
                if (!mutex_trylock(&vcpu->mutex))
                        goto out_unlock;
@@ -1955,11 +1956,10 @@ int kvm_vgic_create(struct kvm *kvm)
        }
 
        kvm_for_each_vcpu(i, vcpu, kvm) {
-               if (vcpu->arch.has_run_once) {
-                       ret = -EBUSY;
+               if (vcpu->arch.has_run_once)
                        goto out_unlock;
-               }
        }
+       ret = 0;
 
        spin_lock_init(&kvm->arch.vgic.lock);
        kvm->arch.vgic.in_kernel = true;
index e51d9f9b995f1864faa6921a41cc0809ce69fb8a..c1e6ae989a432165f9d6871626929ed2ecb578e8 100644 (file)
@@ -43,13 +43,13 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
                                gfn_t base_gfn, unsigned long npages);
 
 static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn,
-                          unsigned long size)
+                          unsigned long npages)
 {
        gfn_t end_gfn;
        pfn_t pfn;
 
        pfn     = gfn_to_pfn_memslot(slot, gfn);
-       end_gfn = gfn + (size >> PAGE_SHIFT);
+       end_gfn = gfn + npages;
        gfn    += 1;
 
        if (is_error_noslot_pfn(pfn))
@@ -119,7 +119,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
                 * Pin all pages we are about to map in memory. This is
                 * important because we unmap and unpin in 4kb steps later.
                 */
-               pfn = kvm_pin_pages(slot, gfn, page_size);
+               pfn = kvm_pin_pages(slot, gfn, page_size >> PAGE_SHIFT);
                if (is_error_noslot_pfn(pfn)) {
                        gfn += 1;
                        continue;
@@ -131,7 +131,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
                if (r) {
                        printk(KERN_ERR "kvm_iommu_map_address:"
                               "iommu failed to map pfn=%llx\n", pfn);
-                       kvm_unpin_pages(kvm, pfn, page_size);
+                       kvm_unpin_pages(kvm, pfn, page_size >> PAGE_SHIFT);
                        goto unmap_pages;
                }
 
index 384eaa7b02fa993f77981d6c91e6dd7f039c1f34..3cee7b167052b58e07c147abb65985865e39e0f9 100644 (file)
@@ -107,10 +107,10 @@ EXPORT_SYMBOL_GPL(kvm_rebooting);
 
 static bool largepages_enabled = true;
 
-bool kvm_is_mmio_pfn(pfn_t pfn)
+bool kvm_is_reserved_pfn(pfn_t pfn)
 {
        if (pfn_valid(pfn))
-               return !is_zero_pfn(pfn) && PageReserved(pfn_to_page(pfn));
+               return PageReserved(pfn_to_page(pfn));
 
        return true;
 }
@@ -1321,7 +1321,7 @@ static pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async,
        else if ((vma->vm_flags & VM_PFNMAP)) {
                pfn = ((addr - vma->vm_start) >> PAGE_SHIFT) +
                        vma->vm_pgoff;
-               BUG_ON(!kvm_is_mmio_pfn(pfn));
+               BUG_ON(!kvm_is_reserved_pfn(pfn));
        } else {
                if (async && vma_is_valid(vma, write_fault))
                        *async = true;
@@ -1427,7 +1427,7 @@ static struct page *kvm_pfn_to_page(pfn_t pfn)
        if (is_error_noslot_pfn(pfn))
                return KVM_ERR_PTR_BAD_PAGE;
 
-       if (kvm_is_mmio_pfn(pfn)) {
+       if (kvm_is_reserved_pfn(pfn)) {
                WARN_ON(1);
                return KVM_ERR_PTR_BAD_PAGE;
        }
@@ -1456,7 +1456,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
 void kvm_release_pfn_clean(pfn_t pfn)
 {
-       if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
+       if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn))
                put_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);
@@ -1477,7 +1477,7 @@ static void kvm_release_pfn_dirty(pfn_t pfn)
 
 void kvm_set_pfn_dirty(pfn_t pfn)
 {
-       if (!kvm_is_mmio_pfn(pfn)) {
+       if (!kvm_is_reserved_pfn(pfn)) {
                struct page *page = pfn_to_page(pfn);
                if (!PageReserved(page))
                        SetPageDirty(page);
@@ -1487,14 +1487,14 @@ EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
 
 void kvm_set_pfn_accessed(pfn_t pfn)
 {
-       if (!kvm_is_mmio_pfn(pfn))
+       if (!kvm_is_reserved_pfn(pfn))
                mark_page_accessed(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_set_pfn_accessed);
 
 void kvm_get_pfn(pfn_t pfn)
 {
-       if (!kvm_is_mmio_pfn(pfn))
+       if (!kvm_is_reserved_pfn(pfn))
                get_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_get_pfn);
@@ -2354,6 +2354,12 @@ int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type)
        return 0;
 }
 
+void kvm_unregister_device_ops(u32 type)
+{
+       if (kvm_device_ops_table[type] != NULL)
+               kvm_device_ops_table[type] = NULL;
+}
+
 static int kvm_ioctl_create_device(struct kvm *kvm,
                                   struct kvm_create_device *cd)
 {
@@ -3328,5 +3334,6 @@ void kvm_exit(void)
        kvm_arch_exit();
        kvm_irqfd_exit();
        free_cpumask_var(cpus_hardware_enabled);
+       kvm_vfio_ops_exit();
 }
 EXPORT_SYMBOL_GPL(kvm_exit);
index 281e7cf2b8e56c07ab2e53a21707f3a4cf0c4c60..620e37f741b868a231a414a71511cd8872704a3c 100644 (file)
@@ -283,3 +283,8 @@ int kvm_vfio_ops_init(void)
 {
        return kvm_register_device_ops(&kvm_vfio_ops, KVM_DEV_TYPE_VFIO);
 }
+
+void kvm_vfio_ops_exit(void)
+{
+       kvm_unregister_device_ops(KVM_DEV_TYPE_VFIO);
+}
index 92eac75d6b6281daabf3715e4d82196cf079aa6f..ab88c7dc05143f764a29ee30a9b03167794eb06e 100644 (file)
@@ -3,11 +3,15 @@
 
 #ifdef CONFIG_KVM_VFIO
 int kvm_vfio_ops_init(void);
+void kvm_vfio_ops_exit(void);
 #else
 static inline int kvm_vfio_ops_init(void)
 {
        return 0;
 }
+static inline void kvm_vfio_ops_exit(void)
+{
+}
 #endif
 
 #endif